2 * Copyright (c) 2000-2002 by Solar Designer. See LICENSE.
13 #define SEPARATORS "_,.;:-!&"
15 static int read_loop(int fd
, char *buffer
, int count
)
21 block
= read(fd
, &buffer
[offset
], count
);
24 if (errno
== EINTR
) continue;
27 if (!block
) return offset
;
36 char *_passwdqc_random(passwdqc_params_t
*params
)
38 static char output
[0x100];
40 int use_separators
, count
, i
;
44 unsigned char bytes
[2];
46 if (!(bits
= params
->random_bits
))
49 count
= 1 + ((bits
- 12) + 14) / 15;
50 use_separators
= ((bits
+ 11) / 12 != count
);
52 length
= count
* 7 - 1;
53 if (length
>= sizeof(output
) || (int)length
> params
->max
)
56 if ((fd
= open("/dev/urandom", O_RDONLY
)) < 0) return NULL
;
60 if (read_loop(fd
, bytes
, sizeof(bytes
)) != sizeof(bytes
)) {
65 i
= (((int)bytes
[1] & 0x0f) << 8) | (int)bytes
[0];
66 start
= _passwdqc_wordset_4k
[i
];
67 end
= memchr(start
, '\0', 6);
68 if (!end
) end
= start
+ 6;
69 if (length
+ (end
- start
) >= sizeof(output
) - 1) {
73 memcpy(&output
[length
], start
, end
- start
);
74 length
+= end
- start
;
77 if (use_separators
&& bits
> 3) {
78 i
= ((int)bytes
[1] & 0x70) >> 4;
79 output
[length
++] = SEPARATORS
[i
];
83 output
[length
++] = ' ';
86 memset(bytes
, 0, sizeof(bytes
));
87 output
[length
] = '\0';