slapd-sha2.c revision 1.1.1.2
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 */
38static 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
94char * 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
116char * 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
137char * 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
158static 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
178static 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
201static 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
221static 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
238static 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
255static 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
271const struct berval sha256scheme = BER_BVC("{SHA256}");
272const struct berval sha384scheme = BER_BVC("{SHA384}");
273const struct berval sha512scheme = BER_BVC("{SHA512}");
274
275int 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