1 /* $NetBSD: pw_gensalt.c,v 1.7 2009/01/18 12:15:27 lukem Exp $ */
4 * Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de>
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by Niels Provos.
18 * 4. The name of the author may not be used to endorse or promote products
19 * derived from this software without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 * from OpenBSD: pwd_gensalt.c,v 1.9 1998/07/05 21:08:32 provos Exp
35 #include <sys/cdefs.h>
37 __RCSID("$NetBSD: pw_gensalt.c,v 1.7 2009/01/18 12:15:27 lukem Exp $");
40 #include <sys/syslimits.h>
41 #include <sys/types.h>
57 static const struct pw_salt
{
59 int (*gensalt
)(char *, size_t, const char *);
61 { "old", __gensalt_old
},
62 { "new", __gensalt_new
},
63 { "newsalt", __gensalt_new
},
64 { "md5", __gensalt_md5
},
65 { "sha1", __gensalt_sha1
},
66 { "blowfish", __gensalt_blowfish
},
71 getnum(const char *str
, size_t *num
)
81 rv
= strtoul(str
, &ep
, 0);
83 if (str
== ep
|| *ep
) {
88 if (errno
== ERANGE
&& rv
== ULONG_MAX
)
96 __gensalt_old(char *salt
, size_t saltsiz
, const char *option
)
102 __crypt_to64(&salt
[0], arc4random(), 2);
109 __gensalt_new(char *salt
, size_t saltsiz
, const char* option
)
118 if (getnum(option
, &nrounds
) == -1)
121 /* Check rounds, 24 bit is max */
124 else if (nrounds
> 0xffffff)
126 salt
[0] = _PASSWORD_EFMT1
;
127 __crypt_to64(&salt
[1], (uint32_t)nrounds
, 4);
128 __crypt_to64(&salt
[5], arc4random(), 4);
135 __gensalt_md5(char *salt
, size_t saltsiz
, const char *option
)
137 if (saltsiz
< 13) { /* $1$8salt$\0 */
141 salt
[0] = _PASSWORD_NONDES
;
144 __crypt_to64(&salt
[3], arc4random(), 4);
145 __crypt_to64(&salt
[7], arc4random(), 4);
152 __gensalt_sha1(char *salt
, size_t saltsiz
, const char *option
)
157 if (getnum(option
, &nrounds
) == -1)
159 n
= snprintf(salt
, saltsiz
, "%s%u$", SHA1_MAGIC
,
160 __crypt_sha1_iterations(nrounds
));
162 * The salt can be up to 64 bytes, but 8
163 * is considered enough for now.
165 if ((size_t)n
+ 9 >= saltsiz
)
167 __crypt_to64(&salt
[n
], arc4random(), 4);
168 __crypt_to64(&salt
[n
+ 4], arc4random(), 4);
175 pw_gensalt(char *salt
, size_t saltlen
, const char *type
, const char *option
)
177 const struct pw_salt
*sp
;
179 for (sp
= salts
; sp
->name
; sp
++)
180 if (strcmp(sp
->name
, type
) == 0)
181 return (*sp
->gensalt
)(salt
, saltlen
, option
);