1 /*	$NetBSD: slapd-sha2.c,v 1.1.1.2 2010/12/12 15:19:14 adam Exp $	*/
2 
3 /* OpenLDAP: pkg/ldap/contrib/slapd-modules/passwd/sha2/slapd-sha2.c,v 1.1.2.5 2010/04/15 18:40:14 quanah Exp */
4 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5  *
6  * Copyright 2009-2010 The OpenLDAP Foundation.
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted only as authorized by the OpenLDAP
11  * Public License.
12  *
13  * A copy of this license is available in the file LICENSE in the
14  * top-level directory of the distribution or, alternatively, at
15  * <http://www.OpenLDAP.org/license.html>.
16  */
17 /* ACKNOWLEDGEMENT:
18  * This work was initially developed by Jeff Turner for inclusion
19  * in OpenLDAP Software.
20  *
21  * Hash methods for passwords generation added by Cédric Delfosse.
22  */
23 
24 #include <lber.h>
25 #include <lber_pvt.h>
26 #include <ac/string.h>
27 #include "lutil.h"
28 #include <stdint.h>
29 #include <string.h>
30 #include <assert.h>
31 #include "sha2.h"
32 
33 #ifdef SLAPD_SHA2_DEBUG
34 #include <stdio.h>
35 #endif
36 
37 /* pw_string64 function taken from libraries/liblutil/passwd.c */
38 static int pw_string64(
39 	const struct berval *sc,
40 	const struct berval *hash,
41 	struct berval *b64,
42 	const struct berval *salt )
43 {
44 	int rc;
45 	struct berval string;
46 	size_t b64len;
47 
48 	if( salt ) {
49 		/* need to base64 combined string */
50 		string.bv_len = hash->bv_len + salt->bv_len;
51 		string.bv_val = ber_memalloc( string.bv_len + 1 );
52 
53 		if( string.bv_val == NULL ) {
54 			return LUTIL_PASSWD_ERR;
55 		}
56 
57 		AC_MEMCPY( string.bv_val, hash->bv_val,
58 			hash->bv_len );
59 		AC_MEMCPY( &string.bv_val[hash->bv_len], salt->bv_val,
60 			salt->bv_len );
61 		string.bv_val[string.bv_len] = '\0';
62 
63 	} else {
64 		string = *hash;
65 	}
66 
67 	b64len = LUTIL_BASE64_ENCODE_LEN( string.bv_len ) + 1;
68 	b64->bv_len = b64len + sc->bv_len;
69 	b64->bv_val = ber_memalloc( b64->bv_len + 1 );
70 
71 	if( b64->bv_val == NULL ) {
72 		if( salt ) ber_memfree( string.bv_val );
73 		return LUTIL_PASSWD_ERR;
74 	}
75 
76 	AC_MEMCPY(b64->bv_val, sc->bv_val, sc->bv_len);
77 
78 	rc = lutil_b64_ntop(
79 		(unsigned char *) string.bv_val, string.bv_len,
80 		&b64->bv_val[sc->bv_len], b64len );
81 
82 	if( salt ) ber_memfree( string.bv_val );
83 
84 	if( rc < 0 ) {
85 		return LUTIL_PASSWD_ERR;
86 	}
87 
88 	/* recompute length */
89 	b64->bv_len = sc->bv_len + rc;
90 	assert( strlen(b64->bv_val) == b64->bv_len );
91 	return LUTIL_PASSWD_OK;
92 }
93 
94 char * sha256_hex_hash(const char * passwd) {
95 
96 	SHA256_CTX ct;
97 	unsigned char hash[SHA256_DIGEST_LENGTH];
98 	static char real_hash[LUTIL_BASE64_ENCODE_LEN(SHA256_DIGEST_LENGTH)+1]; // extra char for \0
99 
100 	SHA256_Init(&ct);
101 	SHA256_Update(&ct, (const uint8_t*)passwd, strlen(passwd));
102 	SHA256_Final(hash, &ct);
103 
104         /* base64 encode it */
105 	lutil_b64_ntop(
106 			hash,
107 			SHA256_DIGEST_LENGTH,
108 			real_hash,
109 			LUTIL_BASE64_ENCODE_LEN(SHA256_DIGEST_LENGTH)+1
110 			);
111 
112 	return real_hash;
113 }
114 
115 
116 char * sha384_hex_hash(const char * passwd) {
117 
118 	SHA384_CTX ct;
119 	unsigned char hash[SHA384_DIGEST_LENGTH];
120 	static char real_hash[LUTIL_BASE64_ENCODE_LEN(SHA384_DIGEST_LENGTH)+1]; // extra char for \0
121 
122 	SHA384_Init(&ct);
123 	SHA384_Update(&ct, (const uint8_t*)passwd, strlen(passwd));
124 	SHA384_Final(hash, &ct);
125 
126         /* base64 encode it */
127 	lutil_b64_ntop(
128 			hash,
129 			SHA384_DIGEST_LENGTH,
130 			real_hash,
131 			LUTIL_BASE64_ENCODE_LEN(SHA384_DIGEST_LENGTH)+1
132 			);
133 
134 	return real_hash;
135 }
136 
137 char * sha512_hex_hash(const char * passwd) {
138 
139 	SHA512_CTX ct;
140 	unsigned char hash[SHA512_DIGEST_LENGTH];
141 	static char real_hash[LUTIL_BASE64_ENCODE_LEN(SHA512_DIGEST_LENGTH)+1]; // extra char for \0
142 
143 	SHA512_Init(&ct);
144 	SHA512_Update(&ct, (const uint8_t*)passwd, strlen(passwd));
145 	SHA512_Final(hash, &ct);
146 
147         /* base64 encode it */
148 	lutil_b64_ntop(
149 			hash,
150 			SHA512_DIGEST_LENGTH,
151 			real_hash,
152 			LUTIL_BASE64_ENCODE_LEN(SHA512_DIGEST_LENGTH)+1
153 			);
154 
155 	return real_hash;
156 }
157 
158 static int hash_sha256(
159 	const struct berval *scheme,
160 	const struct berval *passwd,
161 	struct berval *hash,
162 	const char **text )
163 {
164 	SHA256_CTX ct;
165 	unsigned char hash256[SHA256_DIGEST_LENGTH];
166 
167 	SHA256_Init(&ct);
168 	SHA256_Update(&ct, (const uint8_t*)passwd->bv_val, passwd->bv_len);
169 	SHA256_Final(hash256, &ct);
170 
171 	struct berval digest;
172 	digest.bv_val = (char *) hash256;
173 	digest.bv_len = sizeof(hash256);
174 
175 	return pw_string64(scheme, &digest, hash, NULL);
176 }
177 
178 static int hash_sha384(
179 	const struct berval *scheme,
180 	const struct berval *passwd,
181 	struct berval *hash,
182 	const char **text )
183 {
184 	SHA384_CTX ct;
185 	unsigned char hash384[SHA384_DIGEST_LENGTH];
186 
187 #ifdef SLAPD_SHA2_DEBUG
188 	fprintf(stderr, "hashing password\n");
189 #endif
190 	SHA384_Init(&ct);
191 	SHA384_Update(&ct, (const uint8_t*)passwd->bv_val, passwd->bv_len);
192 	SHA384_Final(hash384, &ct);
193 
194 	struct berval digest;
195 	digest.bv_val = (char *) hash384;
196 	digest.bv_len = sizeof(hash384);
197 
198 	return pw_string64(scheme, &digest, hash, NULL);
199 }
200 
201 static int hash_sha512(
202 	const struct berval *scheme,
203 	const struct berval *passwd,
204 	struct berval *hash,
205 	const char **text )
206 {
207 	SHA512_CTX ct;
208 	unsigned char hash512[SHA512_DIGEST_LENGTH];
209 
210 	SHA512_Init(&ct);
211 	SHA512_Update(&ct, (const uint8_t*)passwd->bv_val, passwd->bv_len);
212 	SHA512_Final(hash512, &ct);
213 
214 	struct berval digest;
215 	digest.bv_val = (char *) hash512;
216 	digest.bv_len = sizeof(hash512);
217 
218 	return pw_string64(scheme, &digest, hash, NULL);
219 }
220 
221 static int chk_sha256(
222 	const struct berval *scheme, // Scheme of hashed reference password
223 	const struct berval *passwd, // Hashed reference password to check against
224 	const struct berval *cred, // user-supplied password to check
225 	const char **text )
226 {
227 #ifdef SLAPD_SHA2_DEBUG
228 	fprintf(stderr, "Validating password\n");
229 	fprintf(stderr, "  Password to validate: %s\n", cred->bv_val);
230 	fprintf(stderr, "  Hashes to: %s\n", sha256_hex_hash(cred->bv_val));
231 	fprintf(stderr, "  Stored password scheme: %s\n", scheme->bv_val);
232 	fprintf(stderr, "  Stored password value: %s\n", passwd->bv_val);
233 	fprintf(stderr, "  -> Passwords %s\n", strcmp(sha256_hex_hash(cred->bv_val), passwd->bv_val) == 0 ? "match" : "do not match");
234 #endif
235 	return (strcmp(sha256_hex_hash(cred->bv_val), passwd->bv_val));
236 }
237 
238 static int chk_sha384(
239 	const struct berval *scheme, // Scheme of hashed reference password
240 	const struct berval *passwd, // Hashed reference password to check against
241 	const struct berval *cred, // user-supplied password to check
242 	const char **text )
243 {
244 #ifdef SLAPD_SHA2_DEBUG
245 	fprintf(stderr, "Validating password\n");
246 	fprintf(stderr, "  Password to validate: %s\n", cred->bv_val);
247 	fprintf(stderr, "  Hashes to: %s\n", sha384_hex_hash(cred->bv_val));
248 	fprintf(stderr, "  Stored password scheme: %s\n", scheme->bv_val);
249 	fprintf(stderr, "  Stored password value: %s\n", passwd->bv_val);
250 	fprintf(stderr, "  -> Passwords %s\n", strcmp(sha384_hex_hash(cred->bv_val), passwd->bv_val) == 0 ? "match" : "do not match");
251 #endif
252 	return (strcmp(sha384_hex_hash(cred->bv_val), passwd->bv_val));
253 }
254 
255 static int chk_sha512(
256 	const struct berval *scheme, // Scheme of hashed reference password
257 	const struct berval *passwd, // Hashed reference password to check against
258 	const struct berval *cred, // user-supplied password to check
259 	const char **text )
260 {
261 #ifdef SLAPD_SHA2_DEBUG
262 	fprintf(stderr, "  Password to validate: %s\n", cred->bv_val);
263 	fprintf(stderr, "  Hashes to: %s\n", sha512_hex_hash(cred->bv_val));
264 	fprintf(stderr, "  Stored password scheme: %s\n", scheme->bv_val);
265 	fprintf(stderr, "  Stored password value: %s\n", passwd->bv_val);
266 	fprintf(stderr, "  -> Passwords %s\n", strcmp(sha512_hex_hash(cred->bv_val), passwd->bv_val) == 0 ? "match" : "do not match");
267 #endif
268 	return (strcmp(sha512_hex_hash(cred->bv_val), passwd->bv_val));
269 }
270 
271 const struct berval sha256scheme = BER_BVC("{SHA256}");
272 const struct berval sha384scheme = BER_BVC("{SHA384}");
273 const struct berval sha512scheme = BER_BVC("{SHA512}");
274 
275 int init_module(int argc, char *argv[]) {
276 	int result = 0;
277 	result = lutil_passwd_add( (struct berval *)&sha256scheme, chk_sha256, hash_sha256 );
278 	if (result != 0) return result;
279 	result = lutil_passwd_add( (struct berval *)&sha384scheme, chk_sha384, hash_sha384 );
280 	if (result != 0) return result;
281 	result = lutil_passwd_add( (struct berval *)&sha512scheme, chk_sha512, hash_sha512 );
282 	return result;
283 }
284