1/*	$NetBSD: slapd-sha2.c,v 1.3 2021/08/14 16:14:53 christos Exp $	*/
2
3/* $OpenLDAP$ */
4/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5 *
6 * Copyright 2009-2021 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 * SSHA256 / SSHA384 / SSHA512 support added, and chk_sha*() replaced
24 * with libraries/liblutil/passwd.c:chk_sha1() implementation to
25 * fix a race by SATOH Fumiyasu @ OSS Technology, Inc.
26 */
27
28#include <sys/cdefs.h>
29__RCSID("$NetBSD: slapd-sha2.c,v 1.3 2021/08/14 16:14:53 christos Exp $");
30
31#include "portable.h"
32
33#include <ac/string.h>
34
35#include "lber_pvt.h"
36#include "lutil.h"
37#include "sha2.h"
38
39#ifdef SLAPD_SHA2_DEBUG
40#include <stdio.h>
41#endif
42
43#define SHA2_SALT_SIZE 8
44
45static int hash_ssha256(
46	const struct berval *scheme,
47	const struct berval *passwd,
48	struct berval *hash,
49	const char **text )
50{
51	SHA256_CTX ct;
52	unsigned char hash256[SHA256_DIGEST_LENGTH];
53	char          saltdata[SHA2_SALT_SIZE];
54	struct berval digest;
55	struct berval salt;
56
57	digest.bv_val = (char *) hash256;
58	digest.bv_len = sizeof(hash256);
59	salt.bv_val = saltdata;
60	salt.bv_len = sizeof(saltdata);
61
62	if (lutil_entropy((unsigned char *)salt.bv_val, salt.bv_len) < 0) {
63		return LUTIL_PASSWD_ERR;
64	}
65
66	SHA256_Init(&ct);
67	SHA256_Update(&ct, (const uint8_t*)passwd->bv_val, passwd->bv_len);
68	SHA256_Update(&ct, (const uint8_t*)salt.bv_val, salt.bv_len);
69	SHA256_Final(hash256, &ct);
70
71	return lutil_passwd_string64(scheme, &digest, hash, &salt);
72}
73
74static int hash_sha256(
75	const struct berval *scheme,
76	const struct berval *passwd,
77	struct berval *hash,
78	const char **text )
79{
80	SHA256_CTX ct;
81	unsigned char hash256[SHA256_DIGEST_LENGTH];
82	struct berval digest;
83	digest.bv_val = (char *) hash256;
84	digest.bv_len = sizeof(hash256);
85
86	SHA256_Init(&ct);
87	SHA256_Update(&ct, (const uint8_t*)passwd->bv_val, passwd->bv_len);
88	SHA256_Final(hash256, &ct);
89
90	return lutil_passwd_string64(scheme, &digest, hash, NULL);
91}
92
93static int hash_ssha384(
94	const struct berval *scheme,
95	const struct berval *passwd,
96	struct berval *hash,
97	const char **text )
98{
99	SHA384_CTX ct;
100	unsigned char hash384[SHA384_DIGEST_LENGTH];
101	char          saltdata[SHA2_SALT_SIZE];
102	struct berval digest;
103	struct berval salt;
104
105	digest.bv_val = (char *) hash384;
106	digest.bv_len = sizeof(hash384);
107	salt.bv_val = saltdata;
108	salt.bv_len = sizeof(saltdata);
109
110	if (lutil_entropy((unsigned char *)salt.bv_val, salt.bv_len) < 0) {
111		return LUTIL_PASSWD_ERR;
112	}
113
114	SHA384_Init(&ct);
115	SHA384_Update(&ct, (const uint8_t*)passwd->bv_val, passwd->bv_len);
116	SHA384_Update(&ct, (const uint8_t*)salt.bv_val, salt.bv_len);
117	SHA384_Final(hash384, &ct);
118
119	return lutil_passwd_string64(scheme, &digest, hash, &salt);
120}
121
122static int hash_sha384(
123	const struct berval *scheme,
124	const struct berval *passwd,
125	struct berval *hash,
126	const char **text )
127{
128	SHA384_CTX ct;
129	unsigned char hash384[SHA384_DIGEST_LENGTH];
130	struct berval digest;
131	digest.bv_val = (char *) hash384;
132	digest.bv_len = sizeof(hash384);
133
134	SHA384_Init(&ct);
135	SHA384_Update(&ct, (const uint8_t*)passwd->bv_val, passwd->bv_len);
136	SHA384_Final(hash384, &ct);
137
138	return lutil_passwd_string64(scheme, &digest, hash, NULL);
139}
140
141static int hash_ssha512(
142	const struct berval *scheme,
143	const struct berval *passwd,
144	struct berval *hash,
145	const char **text )
146{
147	SHA512_CTX ct;
148	unsigned char hash512[SHA512_DIGEST_LENGTH];
149	char          saltdata[SHA2_SALT_SIZE];
150	struct berval digest;
151	struct berval salt;
152
153	digest.bv_val = (char *) hash512;
154	digest.bv_len = sizeof(hash512);
155	salt.bv_val = saltdata;
156	salt.bv_len = sizeof(saltdata);
157
158	if (lutil_entropy((unsigned char *)salt.bv_val, salt.bv_len) < 0) {
159		return LUTIL_PASSWD_ERR;
160	}
161
162	SHA512_Init(&ct);
163	SHA512_Update(&ct, (const uint8_t*)passwd->bv_val, passwd->bv_len);
164	SHA512_Update(&ct, (const uint8_t*)salt.bv_val, salt.bv_len);
165	SHA512_Final(hash512, &ct);
166
167	return lutil_passwd_string64(scheme, &digest, hash, &salt);
168}
169
170static int hash_sha512(
171	const struct berval *scheme,
172	const struct berval *passwd,
173	struct berval *hash,
174	const char **text )
175{
176	SHA512_CTX ct;
177	unsigned char hash512[SHA512_DIGEST_LENGTH];
178	struct berval digest;
179	digest.bv_val = (char *) hash512;
180	digest.bv_len = sizeof(hash512);
181
182	SHA512_Init(&ct);
183	SHA512_Update(&ct, (const uint8_t*)passwd->bv_val, passwd->bv_len);
184	SHA512_Final(hash512, &ct);
185
186	return lutil_passwd_string64(scheme, &digest, hash, NULL);
187}
188
189#ifdef SLAPD_SHA2_DEBUG
190static void chk_sha_debug(
191	const struct berval *scheme,
192	const struct berval *passwd,
193	const struct berval *cred,
194	const char *cred_hash,
195	size_t cred_len,
196	int cmp_rc)
197{
198	int rc;
199	struct berval cred_b64;
200
201	cred_b64.bv_len = LUTIL_BASE64_ENCODE_LEN(cred_len) + 1;
202	cred_b64.bv_val = ber_memalloc(cred_b64.bv_len + 1);
203
204	if( cred_b64.bv_val == NULL ) {
205		return;
206	}
207
208	rc = lutil_b64_ntop(
209		(unsigned char *) cred_hash, cred_len,
210		cred_b64.bv_val, cred_b64.bv_len );
211
212	if( rc < 0 ) {
213		ber_memfree(cred_b64.bv_val);
214		return;
215	}
216
217	fprintf(stderr, "Validating password\n");
218	fprintf(stderr, "  Hash scheme:\t\t%s\n", scheme->bv_val);
219	fprintf(stderr, "  Password to validate: %s\n", cred->bv_val);
220	fprintf(stderr, "  Password hash:\t%s\n", cred_b64.bv_val);
221	fprintf(stderr, "  Stored password hash:\t%s\n", passwd->bv_val);
222	fprintf(stderr, "  Result:\t\t%s\n", cmp_rc ?  "do not match" : "match");
223
224	ber_memfree(cred_b64.bv_val);
225}
226#endif
227
228static int chk_ssha256(
229	const struct berval *scheme, /* Scheme of hashed reference password */
230	const struct berval *passwd, /* Hashed reference password to check against */
231	const struct berval *cred, /* user-supplied password to check */
232	const char **text )
233{
234	SHA256_CTX SHAcontext;
235	unsigned char SHAdigest[SHA256_DIGEST_LENGTH];
236	int rc;
237	unsigned char *orig_pass = NULL;
238	size_t decode_len = LUTIL_BASE64_DECODE_LEN(passwd->bv_len);
239
240	/* safety check */
241	if (decode_len <= sizeof(SHAdigest)) {
242		return LUTIL_PASSWD_ERR;
243	}
244
245	/* base64 un-encode password */
246	orig_pass = (unsigned char *) ber_memalloc(decode_len + 1);
247
248	if( orig_pass == NULL ) return LUTIL_PASSWD_ERR;
249
250	rc = lutil_b64_pton(passwd->bv_val, orig_pass, decode_len);
251
252	if( rc <= (int)(sizeof(SHAdigest)) ) {
253		ber_memfree(orig_pass);
254		return LUTIL_PASSWD_ERR;
255	}
256
257	/* hash credentials with salt */
258	SHA256_Init(&SHAcontext);
259	SHA256_Update(&SHAcontext,
260		(const unsigned char *) cred->bv_val, cred->bv_len);
261	SHA256_Update(&SHAcontext,
262		(const unsigned char *) &orig_pass[sizeof(SHAdigest)],
263		rc - sizeof(SHAdigest));
264	SHA256_Final(SHAdigest, &SHAcontext);
265
266	/* compare */
267	rc = memcmp((char *)orig_pass, (char *)SHAdigest, sizeof(SHAdigest));
268	ber_memfree(orig_pass);
269	return rc ? LUTIL_PASSWD_ERR : LUTIL_PASSWD_OK;
270}
271
272static int chk_sha256(
273	const struct berval *scheme, /* Scheme of hashed reference password */
274	const struct berval *passwd, /* Hashed reference password to check against */
275	const struct berval *cred, /* user-supplied password to check */
276	const char **text )
277{
278	SHA256_CTX SHAcontext;
279	unsigned char SHAdigest[SHA256_DIGEST_LENGTH];
280	int rc;
281	unsigned char *orig_pass = NULL;
282	size_t decode_len = LUTIL_BASE64_DECODE_LEN(passwd->bv_len);
283
284	/* safety check */
285	if (decode_len < sizeof(SHAdigest)) {
286		return LUTIL_PASSWD_ERR;
287	}
288
289	/* base64 un-encode password */
290	orig_pass = (unsigned char *) ber_memalloc(decode_len + 1);
291
292	if( orig_pass == NULL ) return LUTIL_PASSWD_ERR;
293
294	rc = lutil_b64_pton(passwd->bv_val, orig_pass, decode_len);
295
296	if( rc != sizeof(SHAdigest) ) {
297		ber_memfree(orig_pass);
298		return LUTIL_PASSWD_ERR;
299	}
300
301	/* hash credentials with salt */
302	SHA256_Init(&SHAcontext);
303	SHA256_Update(&SHAcontext,
304		(const unsigned char *) cred->bv_val, cred->bv_len);
305	SHA256_Final(SHAdigest, &SHAcontext);
306
307	/* compare */
308	rc = memcmp((char *)orig_pass, (char *)SHAdigest, sizeof(SHAdigest));
309#ifdef SLAPD_SHA2_DEBUG
310	chk_sha_debug(scheme, passwd, cred, (char *)SHAdigest, sizeof(SHAdigest), rc);
311#endif
312	ber_memfree(orig_pass);
313	return rc ? LUTIL_PASSWD_ERR : LUTIL_PASSWD_OK;
314}
315
316static int chk_ssha384(
317	const struct berval *scheme, /* Scheme of hashed reference password */
318	const struct berval *passwd, /* Hashed reference password to check against */
319	const struct berval *cred, /* user-supplied password to check */
320	const char **text )
321{
322	SHA384_CTX SHAcontext;
323	unsigned char SHAdigest[SHA384_DIGEST_LENGTH];
324	int rc;
325	unsigned char *orig_pass = NULL;
326	size_t decode_len = LUTIL_BASE64_DECODE_LEN(passwd->bv_len);
327
328	/* safety check */
329	if (decode_len <= sizeof(SHAdigest)) {
330		return LUTIL_PASSWD_ERR;
331	}
332
333	/* base64 un-encode password */
334	orig_pass = (unsigned char *) ber_memalloc(decode_len + 1);
335
336	if( orig_pass == NULL ) return LUTIL_PASSWD_ERR;
337
338	rc = lutil_b64_pton(passwd->bv_val, orig_pass, decode_len);
339
340	if( rc <= (int)(sizeof(SHAdigest)) ) {
341		ber_memfree(orig_pass);
342		return LUTIL_PASSWD_ERR;
343	}
344
345	/* hash credentials with salt */
346	SHA384_Init(&SHAcontext);
347	SHA384_Update(&SHAcontext,
348		(const unsigned char *) cred->bv_val, cred->bv_len);
349	SHA384_Update(&SHAcontext,
350		(const unsigned char *) &orig_pass[sizeof(SHAdigest)],
351		rc - sizeof(SHAdigest));
352	SHA384_Final(SHAdigest, &SHAcontext);
353
354	/* compare */
355	rc = memcmp((char *)orig_pass, (char *)SHAdigest, sizeof(SHAdigest));
356	ber_memfree(orig_pass);
357	return rc ? LUTIL_PASSWD_ERR : LUTIL_PASSWD_OK;
358}
359
360static int chk_sha384(
361	const struct berval *scheme, /* Scheme of hashed reference password */
362	const struct berval *passwd, /* Hashed reference password to check against */
363	const struct berval *cred, /* user-supplied password to check */
364	const char **text )
365{
366	SHA384_CTX SHAcontext;
367	unsigned char SHAdigest[SHA384_DIGEST_LENGTH];
368	int rc;
369	unsigned char *orig_pass = NULL;
370	size_t decode_len = LUTIL_BASE64_DECODE_LEN(passwd->bv_len);
371
372	/* safety check */
373	if (decode_len < sizeof(SHAdigest)) {
374		return LUTIL_PASSWD_ERR;
375	}
376
377	/* base64 un-encode password */
378	orig_pass = (unsigned char *) ber_memalloc(decode_len + 1);
379
380	if( orig_pass == NULL ) return LUTIL_PASSWD_ERR;
381
382	rc = lutil_b64_pton(passwd->bv_val, orig_pass, decode_len);
383
384	if( rc != sizeof(SHAdigest) ) {
385		ber_memfree(orig_pass);
386		return LUTIL_PASSWD_ERR;
387	}
388
389	/* hash credentials with salt */
390	SHA384_Init(&SHAcontext);
391	SHA384_Update(&SHAcontext,
392		(const unsigned char *) cred->bv_val, cred->bv_len);
393	SHA384_Final(SHAdigest, &SHAcontext);
394
395	/* compare */
396	rc = memcmp((char *)orig_pass, (char *)SHAdigest, sizeof(SHAdigest));
397#ifdef SLAPD_SHA2_DEBUG
398	chk_sha_debug(scheme, passwd, cred, (char *)SHAdigest, sizeof(SHAdigest), rc);
399#endif
400	ber_memfree(orig_pass);
401	return rc ? LUTIL_PASSWD_ERR : LUTIL_PASSWD_OK;
402}
403
404static int chk_ssha512(
405	const struct berval *scheme, /* Scheme of hashed reference password */
406	const struct berval *passwd, /* Hashed reference password to check against */
407	const struct berval *cred, /* user-supplied password to check */
408	const char **text )
409{
410	SHA512_CTX SHAcontext;
411	unsigned char SHAdigest[SHA512_DIGEST_LENGTH];
412	int rc;
413	unsigned char *orig_pass = NULL;
414	size_t decode_len = LUTIL_BASE64_DECODE_LEN(passwd->bv_len);
415
416	/* safety check */
417	if (decode_len <= sizeof(SHAdigest)) {
418		return LUTIL_PASSWD_ERR;
419	}
420
421	/* base64 un-encode password */
422	orig_pass = (unsigned char *) ber_memalloc(decode_len + 1);
423
424	if( orig_pass == NULL ) return LUTIL_PASSWD_ERR;
425
426	rc = lutil_b64_pton(passwd->bv_val, orig_pass, decode_len);
427
428	if( rc <= (int)(sizeof(SHAdigest)) ) {
429		ber_memfree(orig_pass);
430		return LUTIL_PASSWD_ERR;
431	}
432
433	/* hash credentials with salt */
434	SHA512_Init(&SHAcontext);
435	SHA512_Update(&SHAcontext,
436		(const unsigned char *) cred->bv_val, cred->bv_len);
437	SHA512_Update(&SHAcontext,
438		(const unsigned char *) &orig_pass[sizeof(SHAdigest)],
439		rc - sizeof(SHAdigest));
440	SHA512_Final(SHAdigest, &SHAcontext);
441
442	/* compare */
443	rc = memcmp((char *)orig_pass, (char *)SHAdigest, sizeof(SHAdigest));
444	ber_memfree(orig_pass);
445	return rc ? LUTIL_PASSWD_ERR : LUTIL_PASSWD_OK;
446}
447
448static int chk_sha512(
449	const struct berval *scheme, /* Scheme of hashed reference password */
450	const struct berval *passwd, /* Hashed reference password to check against */
451	const struct berval *cred, /* user-supplied password to check */
452	const char **text )
453{
454	SHA512_CTX SHAcontext;
455	unsigned char SHAdigest[SHA512_DIGEST_LENGTH];
456	int rc;
457	unsigned char *orig_pass = NULL;
458	size_t decode_len = LUTIL_BASE64_DECODE_LEN(passwd->bv_len);
459
460	/* safety check */
461	if (decode_len < sizeof(SHAdigest)) {
462		return LUTIL_PASSWD_ERR;
463	}
464
465	/* base64 un-encode password */
466	orig_pass = (unsigned char *) ber_memalloc(decode_len + 1);
467
468	if( orig_pass == NULL ) return LUTIL_PASSWD_ERR;
469
470	rc = lutil_b64_pton(passwd->bv_val, orig_pass, decode_len);
471
472	if( rc != sizeof(SHAdigest) ) {
473		ber_memfree(orig_pass);
474		return LUTIL_PASSWD_ERR;
475	}
476
477	/* hash credentials with salt */
478	SHA512_Init(&SHAcontext);
479	SHA512_Update(&SHAcontext,
480		(const unsigned char *) cred->bv_val, cred->bv_len);
481	SHA512_Final(SHAdigest, &SHAcontext);
482
483	/* compare */
484	rc = memcmp((char *)orig_pass, (char *)SHAdigest, sizeof(SHAdigest));
485#ifdef SLAPD_SHA2_DEBUG
486	chk_sha_debug(scheme, passwd, cred, (char *)SHAdigest, sizeof(SHAdigest), rc);
487#endif
488	ber_memfree(orig_pass);
489	return rc ? LUTIL_PASSWD_ERR : LUTIL_PASSWD_OK;
490}
491
492const struct berval ssha256scheme = BER_BVC("{SSHA256}");
493const struct berval sha256scheme = BER_BVC("{SHA256}");
494const struct berval ssha384scheme = BER_BVC("{SSHA384}");
495const struct berval sha384scheme = BER_BVC("{SHA384}");
496const struct berval ssha512scheme = BER_BVC("{SSHA512}");
497const struct berval sha512scheme = BER_BVC("{SHA512}");
498
499int init_module(int argc, char *argv[]) {
500	int result = 0;
501	result = lutil_passwd_add( (struct berval *)&ssha256scheme, chk_ssha256, hash_ssha256 );
502	if (result != 0) return result;
503	result = lutil_passwd_add( (struct berval *)&sha256scheme, chk_sha256, hash_sha256 );
504	if (result != 0) return result;
505	result = lutil_passwd_add( (struct berval *)&ssha384scheme, chk_ssha384, hash_ssha384 );
506	if (result != 0) return result;
507	result = lutil_passwd_add( (struct berval *)&sha384scheme, chk_sha384, hash_sha384 );
508	if (result != 0) return result;
509	result = lutil_passwd_add( (struct berval *)&ssha512scheme, chk_ssha512, hash_ssha512 );
510	if (result != 0) return result;
511	result = lutil_passwd_add( (struct berval *)&sha512scheme, chk_sha512, hash_sha512 );
512	return result;
513}
514