2 * Copyright (c) 2000-2002,2005,2008,2010,2013,2016,2021 by Solar Designer
7 #define _CRT_NONSTDC_NO_WARNINGS /* we use POSIX function names */
20 #include "wordset_4k.h"
23 * We separate words in the generated "passphrases" with random special
24 * characters out of a set of 16 (so we encode 4 bits per separator
25 * character). To enable the use of our "passphrases" within FTP URLs
26 * (and similar), we pick characters that are defined by RFC 3986 as
27 * being safe within "userinfo" part of URLs without encoding and
28 * without having a special meaning. Out of those, we avoid characters
29 * that are visually ambiguous or difficult over the phone. This
30 * happens to leave us with exactly 8 symbols, and we add 8 digits that
31 * are not visually ambiguous. Unfortunately, the exclamation mark
32 * might be confused for the digit 1 (which we don't use), though.
34 #define SEPARATORS "-_!$&*+=23456789"
37 * Number of bits encoded per separator character.
39 #define SEPARATOR_BITS 4
42 * Number of bits encoded per word. We use 4096 words, which gives 12 bits,
43 * and we toggle the case of the first character, which gives one bit more.
48 * Number of bits encoded per separator and word.
51 (SEPARATOR_BITS + WORD_BITS)
54 * Maximum number of words to use.
59 * Minimum and maximum number of bits to encode. With the settings above,
60 * these are 24 and 136, respectively.
65 (WORDS_MAX * SWORD_BITS)
68 static ssize_t
read_loop(int fd
, void *buffer
, size_t count
)
70 ssize_t offset
, block
;
73 while (count
> 0 && count
<= SSIZE_MAX
) {
74 block
= read(fd
, (char *)buffer
+ offset
, count
);
93 char *passwdqc_random(const passwdqc_params_qc_t
*params
)
95 int bits
= params
->random_bits
; /* further code assumes signed type */
96 if (bits
< BITS_MIN
|| bits
> BITS_MAX
)
100 * Calculate the number of words to use. The first word is always present
101 * (hence the "1 +" and the "- WORD_BITS"). Each one of the following words,
102 * if any, is prefixed by a separator character, so we use SWORD_BITS when
103 * calculating how many additional words to use. We divide "bits - WORD_BITS"
104 * by SWORD_BITS with rounding up (hence the addition of "SWORD_BITS - 1").
106 int word_count
= 1 + (bits
+ (SWORD_BITS
- 1 - WORD_BITS
)) / SWORD_BITS
;
109 * Special case: would we still encode enough bits if we omit the final word,
110 * but keep the would-be-trailing separator?
112 int trailing_separator
= (SWORD_BITS
* (word_count
- 1) >= bits
);
113 word_count
-= trailing_separator
;
116 * To determine whether we need to use different separator characters or maybe
117 * not, calculate the number of words we'd need to use if we don't use
118 * different separators. We calculate it by dividing "bits" by WORD_BITS with
119 * rounding up (hence the addition of "WORD_BITS - 1"). The resulting number
120 * is either the same as or greater than word_count. Use different separators
121 * only if their use, in the word_count calculation above, has helped reduce
124 int use_separators
= ((bits
+ (WORD_BITS
- 1)) / WORD_BITS
!= word_count
);
125 trailing_separator
&= use_separators
;
128 * Toggle case of the first character of each word only if we wouldn't achieve
129 * sufficient entropy otherwise.
131 int toggle_case
= (bits
>
132 ((WORD_BITS
- 1) * word_count
) +
133 (use_separators
? (SEPARATOR_BITS
* (word_count
- !trailing_separator
)) : 0));
138 * Calculate and check the maximum possible length of a "passphrase" we may
139 * generate for a given word_count. We add 1 to WORDSET_4K_LENGTH_MAX to
140 * account for separators (whether different or not). When there's no
141 * trailing separator, we subtract 1. The check against sizeof(output) uses
142 * ">=" to account for NUL termination.
144 unsigned int max_length
= word_count
* (WORDSET_4K_LENGTH_MAX
+ 1) - !trailing_separator
;
145 if (max_length
>= sizeof(output
) || (int)max_length
> params
->max
)
148 unsigned char rnd
[WORDS_MAX
* 3];
152 if (!CryptAcquireContextA(&hprov
, NULL
, NULL
, PROV_RSA_FULL
, CRYPT_VERIFYCONTEXT
| CRYPT_SILENT
))
154 memset(rnd
, 0, sizeof(rnd
)); /* old Windows would use previous content as extra seed */
155 if (!CryptGenRandom(hprov
, sizeof(rnd
), rnd
)) {
156 CryptReleaseContext(hprov
, 0);
159 CryptReleaseContext(hprov
, 0);
162 if ((fd
= open("/dev/urandom", O_RDONLY
)) < 0)
164 if (read_loop(fd
, rnd
, sizeof(rnd
)) != sizeof(rnd
)) {
172 const unsigned char *rndptr
;
174 for (rndptr
= rnd
; rndptr
<= rnd
+ sizeof(rnd
) - 3; rndptr
+= 3) {
178 * Treating *rndptr as little-endian, we use bits 0 to 11 for the word index
179 * and bit 13 for toggling the case of the first character. Bits 12, 14, and
180 * 15 are left unused. Bits 16 to 23 are left for the separator.
182 unsigned int i
= (((unsigned int)rndptr
[1] & 0x0f) << 8) | rndptr
[0];
183 const char *start
= _passwdqc_wordset_4k
[i
];
184 const char *end
= memchr(start
, '\0', WORDSET_4K_LENGTH_MAX
);
186 end
= start
+ WORDSET_4K_LENGTH_MAX
;
187 size_t extra
= end
- start
;
188 /* The ">=" leaves room for either one more separator or NUL */
189 if (length
+ extra
>= sizeof(output
))
191 memcpy(&output
[length
], start
, extra
);
193 /* Toggle case if bit set (we assume ASCII) */
194 output
[length
] ^= rndptr
[1] & 0x20;
198 bits
-= WORD_BITS
- 1;
204 * Append a separator character. We use bits 16 to 19. Bits 20 to 23 are left
207 * Special case: we may happen to leave a trailing separator if it provides
208 * enough bits on its own. With WORD_BITS 13 and SEPARATOR_BITS 4, this
209 * happens e.g. for bits values from 31 to 34, 48 to 51, 65 to 68.
211 if (use_separators
) {
212 i
= rndptr
[2] & 0x0f;
213 output
[length
++] = SEPARATORS
[i
];
214 bits
-= SEPARATOR_BITS
;
216 output
[length
++] = SEPARATORS
[0];
225 if (bits
<= 0 && length
< sizeof(output
)) {
226 output
[length
] = '\0';
227 retval
= strdup(output
);
230 _passwdqc_memzero(rnd
, sizeof(rnd
));
231 _passwdqc_memzero(output
, length
);