"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 }