"Fossies" - the Fresh Open Source Software Archive

Member "passwdqc-2.0.3/passwdqc_filter.c" (23 Jun 2023, 3979 Bytes) of package /linux/privat/passwdqc-2.0.3.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "passwdqc_filter.c" see the Fossies "Dox" file reference documentation.

    1 /*
    2  * Copyright (c) 2020,2021 by Solar Designer
    3  * See LICENSE
    4  */
    5 
    6 #define _FILE_OFFSET_BITS 64
    7 #define _LARGEFILE_SOURCE 1
    8 #define _LARGEFILE64_SOURCE 1
    9 #define _LARGE_FILES 1
   10 
   11 #ifdef _MSC_VER
   12 #define _CRT_NONSTDC_NO_WARNINGS /* we use POSIX function names */
   13 #define _CRT_SECURE_NO_WARNINGS /* we use open() */
   14 #include <stdio.h> /* for SEEK_SET and SEEK_END */
   15 #include <io.h>
   16 #define lseek _lseeki64
   17 #define ssize_t int /* MSVC's read() returns int and we don't need more here */
   18 #define SSIZE_MAX INT_MAX
   19 #define OPEN_FLAGS (O_RDONLY | _O_BINARY | _O_RANDOM)
   20 #else
   21 #include <unistd.h>
   22 #define OPEN_FLAGS O_RDONLY
   23 #endif
   24 
   25 #include <stdint.h>
   26 #include <limits.h>
   27 #include <fcntl.h>
   28 
   29 #include "passwdqc.h"
   30 #define PASSWDQC_FILTER_INTERNALS
   31 #include "passwdqc_filter.h"
   32 
   33 static ssize_t read_loop(int fd, void *buffer, size_t count)
   34 {
   35     ssize_t offset, block;
   36 
   37     offset = 0;
   38     while (count > 0 && count <= SSIZE_MAX) {
   39         block = read(fd, (char *)buffer + offset, count);
   40 
   41         if (block < 0)
   42             return block;
   43         if (!block)
   44             return offset;
   45 
   46         offset += block;
   47         count -= block;
   48     }
   49 
   50     return offset;
   51 }
   52 
   53 int passwdqc_filter_open(passwdqc_filter_t *flt, const char *filename)
   54 {
   55     if ((flt->fd = open(filename, OPEN_FLAGS)) < 0)
   56         return -1;
   57 
   58     if (read_loop(flt->fd, &flt->header, sizeof(flt->header)) != sizeof(flt->header) ||
   59         passwdqc_filter_verify_header(&flt->header) ||
   60         flt->header.hash_id < PASSWDQC_FILTER_HASH_MIN || flt->header.hash_id > PASSWDQC_FILTER_HASH_MAX ||
   61         (size_t)lseek(flt->fd, 0, SEEK_END) != sizeof(flt->header) + (flt->header.capacity << 2)) {
   62         passwdqc_filter_close(flt);
   63         return -1;
   64     }
   65 
   66     return 0;
   67 }
   68 
   69 int passwdqc_filter_close(passwdqc_filter_t *flt)
   70 {
   71     int retval = close(flt->fd);
   72     flt->fd = -1;
   73     return retval;
   74 }
   75 
   76 static int check(const passwdqc_filter_t *flt, passwdqc_filter_i_t i, passwdqc_filter_f_t f)
   77 {
   78     int retval = -1;
   79 
   80     passwdqc_filter_packed_t p;
   81     if (lseek(flt->fd, sizeof(flt->header) + (uint64_t)i * sizeof(p), SEEK_SET) < 0 ||
   82         read_loop(flt->fd, &p, sizeof(p)) != sizeof(p))
   83         goto out;
   84 
   85     passwdqc_filter_unpacked_t u;
   86     unsigned int n = (unsigned int)passwdqc_filter_unpack(&u, &p, NULL);
   87     if (n > flt->header.bucket_size)
   88         goto out;
   89 
   90     unsigned int j;
   91     for (j = 0; j < n; j++) {
   92         if (passwdqc_filter_f_eq(u.slots[j], f, flt->header.bucket_size)) {
   93             retval = 1;
   94             goto out;
   95         }
   96     }
   97 
   98     retval = (n < flt->header.threshold) ? 0 : 2;
   99 
  100 out:
  101     _passwdqc_memzero(&p, sizeof(p));
  102     _passwdqc_memzero(&u, sizeof(u));
  103     return retval;
  104 }
  105 
  106 int passwdqc_filter_lookup(const passwdqc_filter_t *flt, const char *plaintext)
  107 {
  108     int retval = 3;
  109     passwdqc_filter_hash_t h;
  110     passwdqc_filter_f_t ftest;
  111 
  112 clean:
  113     switch (flt->header.hash_id) {
  114     case PASSWDQC_FILTER_HASH_MD4:
  115         passwdqc_filter_md4(&h, plaintext);
  116         ftest = 0x8c6420f439de2000ULL;
  117         break;
  118     case PASSWDQC_FILTER_HASH_NTLM_CP1252:
  119         passwdqc_filter_ntlm_cp1252(&h, plaintext);
  120         ftest = 0x26bd9256ff7e052eULL;
  121         break;
  122     default:
  123         return -1;
  124     }
  125 
  126     uint32_t nbuckets = (uint32_t)(flt->header.capacity >> 2);
  127     passwdqc_filter_i_t i = passwdqc_filter_h2i(&h, nbuckets);
  128     passwdqc_filter_f_t f = passwdqc_filter_h2f(&h);
  129 
  130     _passwdqc_memzero(&h, sizeof(h));
  131 
  132 /*
  133  * The tests of i and f here not only self-test the code, but also prevent the
  134  * compiler from moving "return retval;" to before the computation of h, i, and
  135  * f, which would leave sensitive data from the real hash computation around.
  136  */
  137     if (i >= nbuckets)
  138         return -1;
  139 
  140     if (retval <= 1) {
  141 /* Waste two syscalls on overwriting lseek()'s stack and current file offset */
  142         i = passwdqc_filter_h2i(&h, nbuckets); /* 0 */
  143         if (check(flt, i, f) < 0)
  144             return -1;
  145         if (f != ftest)
  146             return -1;
  147         return retval;
  148     }
  149 
  150 /* At least 1 character to overwrite passwdqc_filter_ntlm_cp1252()'s buffer */
  151     plaintext = " 09AZaz\x7e\x7f\x80\x81\x9e\x9f\xa0\xff";
  152 
  153     retval = check(flt, i, f);
  154     if (retval <= 1)
  155         goto clean;
  156 
  157     retval = check(flt, passwdqc_filter_alti(i, f, nbuckets), f);
  158     if (retval == 2)
  159         retval = 0;
  160     goto clean;
  161 }