Home | History | Annotate | Line # | Download | only in pbkdf2
      1  1.3  christos /*	$NetBSD: pw-pbkdf2.c,v 1.4 2025/09/05 21:16:17 christos Exp $	*/
      2  1.1  christos 
      3  1.1  christos /* $OpenLDAP$ */
      4  1.1  christos /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
      5  1.1  christos  *
      6  1.4  christos  * Copyright 2009-2024 The OpenLDAP Foundation.
      7  1.1  christos  * All rights reserved.
      8  1.1  christos  *
      9  1.1  christos  * Redistribution and use in source and binary forms, with or without
     10  1.1  christos  * modification, are permitted only as authorized by the OpenLDAP
     11  1.1  christos  * Public License.
     12  1.1  christos  *
     13  1.1  christos  * A copy of this license is available in the file LICENSE in the
     14  1.1  christos  * top-level directory of the distribution or, alternatively, at
     15  1.1  christos  * <http://www.OpenLDAP.org/license.html>.
     16  1.1  christos  */
     17  1.1  christos /* ACKNOWLEDGEMENT:
     18  1.1  christos  * This work was initially developed by HAMANO Tsukasa <hamano (at) osstech.co.jp>
     19  1.1  christos  */
     20  1.1  christos 
     21  1.1  christos #define _GNU_SOURCE
     22  1.1  christos 
     23  1.1  christos #include <sys/cdefs.h>
     24  1.3  christos __RCSID("$NetBSD: pw-pbkdf2.c,v 1.4 2025/09/05 21:16:17 christos Exp $");
     25  1.1  christos 
     26  1.1  christos #include "portable.h"
     27  1.1  christos #include <ac/string.h>
     28  1.1  christos #include "lber_pvt.h"
     29  1.1  christos #include "lutil.h"
     30  1.1  christos #include <stdio.h>
     31  1.1  christos #include <stdlib.h>
     32  1.1  christos 
     33  1.1  christos #ifdef HAVE_OPENSSL
     34  1.1  christos #include <openssl/evp.h>
     35  1.1  christos #elif HAVE_GNUTLS
     36  1.1  christos #include <nettle/pbkdf2.h>
     37  1.1  christos #include <nettle/hmac.h>
     38  1.1  christos typedef void (*pbkdf2_hmac_update)(void *, unsigned, const uint8_t *);
     39  1.1  christos typedef void (*pbkdf2_hmac_digest)(void *, unsigned, uint8_t *);
     40  1.1  christos #else
     41  1.1  christos #error Unsupported crypto backend.
     42  1.1  christos #endif
     43  1.1  christos 
     44  1.1  christos #define PBKDF2_ITERATION 10000
     45  1.1  christos #define PBKDF2_SALT_SIZE 16
     46  1.1  christos #define PBKDF2_SHA1_DK_SIZE 20
     47  1.1  christos #define PBKDF2_SHA256_DK_SIZE 32
     48  1.1  christos #define PBKDF2_SHA512_DK_SIZE 64
     49  1.1  christos #define PBKDF2_MAX_DK_SIZE 64
     50  1.1  christos 
     51  1.1  christos const struct berval pbkdf2_scheme = BER_BVC("{PBKDF2}");
     52  1.1  christos const struct berval pbkdf2_sha1_scheme = BER_BVC("{PBKDF2-SHA1}");
     53  1.1  christos const struct berval pbkdf2_sha256_scheme = BER_BVC("{PBKDF2-SHA256}");
     54  1.1  christos const struct berval pbkdf2_sha512_scheme = BER_BVC("{PBKDF2-SHA512}");
     55  1.1  christos 
     56  1.1  christos /*
     57  1.1  christos  * Converting base64 string to adapted base64 string.
     58  1.1  christos  * Adapted base64 encode is identical to general base64 encode except
     59  1.1  christos  * that it uses '.' instead of '+', and omits trailing padding '=' and
     60  1.3  christos  * whitespace.
     61  1.1  christos  * see http://pythonhosted.org/passlib/lib/passlib.utils.html
     62  1.1  christos  * This is destructive function.
     63  1.1  christos  */
     64  1.1  christos static int b64_to_ab64(char *str)
     65  1.1  christos {
     66  1.1  christos 	char *p = str;
     67  1.2  christos 	do {
     68  1.1  christos 		if(*p == '+'){
     69  1.1  christos 			*p = '.';
     70  1.1  christos 		}
     71  1.1  christos 		if(*p == '='){
     72  1.1  christos 			*p = '\0';
     73  1.1  christos 		}
     74  1.2  christos 	} while(*p++);
     75  1.1  christos 	return 0;
     76  1.1  christos }
     77  1.1  christos 
     78  1.1  christos /*
     79  1.1  christos  * Converting adapted base64 string to base64 string.
     80  1.1  christos  * dstsize will require src length + 2, due to output string have
     81  1.1  christos  * potential to append "=" or "==".
     82  1.1  christos  * return -1 if few output buffer.
     83  1.1  christos  */
     84  1.1  christos static int ab64_to_b64(char *src, char *dst, size_t dstsize){
     85  1.1  christos 	int i;
     86  1.1  christos 	char *p = src;
     87  1.1  christos 	for(i=0; p[i] && p[i] != '$'; i++){
     88  1.1  christos 		if(i >= dstsize){
     89  1.1  christos 			dst[0] = '\0';
     90  1.1  christos 			return -1;
     91  1.1  christos 		}
     92  1.1  christos 		if(p[i] == '.'){
     93  1.1  christos 			dst[i] = '+';
     94  1.1  christos 		}else{
     95  1.1  christos 			dst[i] = p[i];
     96  1.1  christos 		}
     97  1.1  christos 	}
     98  1.1  christos 	for(;i%4;i++){
     99  1.1  christos 		if(i >= dstsize){
    100  1.1  christos 			dst[0] = '\0';
    101  1.1  christos 			return -1;
    102  1.1  christos 		}
    103  1.1  christos 		dst[i] = '=';
    104  1.1  christos 	}
    105  1.1  christos 	dst[i] = '\0';
    106  1.1  christos 	return 0;
    107  1.1  christos }
    108  1.1  christos 
    109  1.1  christos static int pbkdf2_format(
    110  1.1  christos 	const struct berval *sc,
    111  1.1  christos 	int iteration,
    112  1.1  christos 	const struct berval *salt,
    113  1.1  christos 	const struct berval *dk,
    114  1.1  christos 	struct berval *msg)
    115  1.1  christos {
    116  1.1  christos 
    117  1.1  christos 	int rc, msg_len;
    118  1.1  christos 	char salt_b64[LUTIL_BASE64_ENCODE_LEN(PBKDF2_SALT_SIZE) + 1];
    119  1.1  christos 	char dk_b64[LUTIL_BASE64_ENCODE_LEN(PBKDF2_MAX_DK_SIZE) + 1];
    120  1.1  christos 
    121  1.1  christos 	rc = lutil_b64_ntop((unsigned char *)salt->bv_val, salt->bv_len,
    122  1.1  christos 						salt_b64, sizeof(salt_b64));
    123  1.1  christos 	if(rc < 0){
    124  1.1  christos 		return LUTIL_PASSWD_ERR;
    125  1.1  christos 	}
    126  1.1  christos 	b64_to_ab64(salt_b64);
    127  1.1  christos 	rc = lutil_b64_ntop((unsigned char *)dk->bv_val, dk->bv_len,
    128  1.1  christos 						dk_b64, sizeof(dk_b64));
    129  1.1  christos 	if(rc < 0){
    130  1.1  christos 		return LUTIL_PASSWD_ERR;
    131  1.1  christos 	}
    132  1.1  christos 	b64_to_ab64(dk_b64);
    133  1.1  christos 	msg_len = asprintf(&msg->bv_val, "%s%d$%s$%s",
    134  1.1  christos 						   sc->bv_val, iteration,
    135  1.1  christos 						   salt_b64, dk_b64);
    136  1.1  christos 	if(msg_len < 0){
    137  1.1  christos 		msg->bv_len = 0;
    138  1.1  christos 		return LUTIL_PASSWD_ERR;
    139  1.1  christos 	}
    140  1.1  christos 
    141  1.1  christos 	msg->bv_len = msg_len;
    142  1.1  christos 	return LUTIL_PASSWD_OK;
    143  1.1  christos }
    144  1.1  christos 
    145  1.1  christos static int pbkdf2_encrypt(
    146  1.1  christos 	const struct berval *scheme,
    147  1.1  christos 	const struct berval *passwd,
    148  1.1  christos 	struct berval *msg,
    149  1.1  christos 	const char **text)
    150  1.1  christos {
    151  1.1  christos 	unsigned char salt_value[PBKDF2_SALT_SIZE];
    152  1.1  christos 	struct berval salt;
    153  1.1  christos 	unsigned char dk_value[PBKDF2_MAX_DK_SIZE];
    154  1.1  christos 	struct berval dk;
    155  1.1  christos 	int iteration = PBKDF2_ITERATION;
    156  1.1  christos 	int rc;
    157  1.1  christos #ifdef HAVE_OPENSSL
    158  1.1  christos 	const EVP_MD *md;
    159  1.1  christos #elif HAVE_GNUTLS
    160  1.1  christos 	struct hmac_sha1_ctx sha1_ctx;
    161  1.1  christos 	struct hmac_sha256_ctx sha256_ctx;
    162  1.1  christos 	struct hmac_sha512_ctx sha512_ctx;
    163  1.1  christos 	void * current_ctx = NULL;
    164  1.1  christos 	pbkdf2_hmac_update current_hmac_update = NULL;
    165  1.1  christos 	pbkdf2_hmac_digest current_hmac_digest = NULL;
    166  1.1  christos #endif
    167  1.1  christos 
    168  1.1  christos 	salt.bv_val = (char *)salt_value;
    169  1.1  christos 	salt.bv_len = sizeof(salt_value);
    170  1.1  christos 	dk.bv_val = (char *)dk_value;
    171  1.1  christos 
    172  1.1  christos #ifdef HAVE_OPENSSL
    173  1.1  christos 	if(!ber_bvcmp(scheme, &pbkdf2_scheme)){
    174  1.1  christos 		dk.bv_len = PBKDF2_SHA1_DK_SIZE;
    175  1.1  christos 		md = EVP_sha1();
    176  1.1  christos 	}else if(!ber_bvcmp(scheme, &pbkdf2_sha1_scheme)){
    177  1.1  christos 		dk.bv_len = PBKDF2_SHA1_DK_SIZE;
    178  1.1  christos 		md = EVP_sha1();
    179  1.1  christos 	}else if(!ber_bvcmp(scheme, &pbkdf2_sha256_scheme)){
    180  1.1  christos 		dk.bv_len = PBKDF2_SHA256_DK_SIZE;
    181  1.1  christos 		md = EVP_sha256();
    182  1.1  christos 	}else if(!ber_bvcmp(scheme, &pbkdf2_sha512_scheme)){
    183  1.1  christos 		dk.bv_len = PBKDF2_SHA512_DK_SIZE;
    184  1.1  christos 		md = EVP_sha512();
    185  1.1  christos 	}else{
    186  1.1  christos 		return LUTIL_PASSWD_ERR;
    187  1.1  christos 	}
    188  1.1  christos #elif HAVE_GNUTLS
    189  1.1  christos 	if(!ber_bvcmp(scheme, &pbkdf2_scheme)){
    190  1.1  christos 		dk.bv_len = PBKDF2_SHA1_DK_SIZE;
    191  1.1  christos 		current_ctx = &sha1_ctx;
    192  1.1  christos 		current_hmac_update = (pbkdf2_hmac_update) &hmac_sha1_update;
    193  1.1  christos 		current_hmac_digest = (pbkdf2_hmac_digest) &hmac_sha1_digest;
    194  1.1  christos 		hmac_sha1_set_key(current_ctx, passwd->bv_len, (const uint8_t *) passwd->bv_val);
    195  1.1  christos 	}else if(!ber_bvcmp(scheme, &pbkdf2_sha1_scheme)){
    196  1.1  christos 		dk.bv_len = PBKDF2_SHA1_DK_SIZE;
    197  1.1  christos 		current_ctx = &sha1_ctx;
    198  1.1  christos 		current_hmac_update = (pbkdf2_hmac_update) &hmac_sha1_update;
    199  1.1  christos 		current_hmac_digest = (pbkdf2_hmac_digest) &hmac_sha1_digest;
    200  1.1  christos 		hmac_sha1_set_key(current_ctx, passwd->bv_len, (const uint8_t *) passwd->bv_val);
    201  1.1  christos 	}else if(!ber_bvcmp(scheme, &pbkdf2_sha256_scheme)){
    202  1.1  christos 		dk.bv_len = PBKDF2_SHA256_DK_SIZE;
    203  1.1  christos 		current_ctx = &sha256_ctx;
    204  1.1  christos 		current_hmac_update = (pbkdf2_hmac_update) &hmac_sha256_update;
    205  1.1  christos 		current_hmac_digest = (pbkdf2_hmac_digest) &hmac_sha256_digest;
    206  1.1  christos 		hmac_sha256_set_key(current_ctx, passwd->bv_len, (const uint8_t *) passwd->bv_val);
    207  1.1  christos 	}else if(!ber_bvcmp(scheme, &pbkdf2_sha512_scheme)){
    208  1.1  christos 		dk.bv_len = PBKDF2_SHA512_DK_SIZE;
    209  1.1  christos 		current_ctx = &sha512_ctx;
    210  1.1  christos 		current_hmac_update = (pbkdf2_hmac_update) &hmac_sha512_update;
    211  1.1  christos 		current_hmac_digest = (pbkdf2_hmac_digest) &hmac_sha512_digest;
    212  1.1  christos 		hmac_sha512_set_key(current_ctx, passwd->bv_len, (const uint8_t *) passwd->bv_val);
    213  1.1  christos 	}else{
    214  1.1  christos 		return LUTIL_PASSWD_ERR;
    215  1.1  christos 	}
    216  1.1  christos #endif
    217  1.1  christos 
    218  1.1  christos 	if(lutil_entropy((unsigned char *)salt.bv_val, salt.bv_len) < 0){
    219  1.1  christos 		return LUTIL_PASSWD_ERR;
    220  1.1  christos 	}
    221  1.1  christos 
    222  1.1  christos #ifdef HAVE_OPENSSL
    223  1.1  christos 	if(!PKCS5_PBKDF2_HMAC(passwd->bv_val, passwd->bv_len,
    224  1.1  christos 						  (unsigned char *)salt.bv_val, salt.bv_len,
    225  1.1  christos 						  iteration, md, dk.bv_len, dk_value)){
    226  1.1  christos 		return LUTIL_PASSWD_ERR;
    227  1.1  christos 	}
    228  1.1  christos #elif HAVE_GNUTLS
    229  1.1  christos 	PBKDF2(current_ctx, current_hmac_update, current_hmac_digest,
    230  1.1  christos 						  dk.bv_len, iteration,
    231  1.1  christos 						  salt.bv_len, (const uint8_t *) salt.bv_val,
    232  1.1  christos 						  dk.bv_len, dk_value);
    233  1.1  christos #endif
    234  1.1  christos 
    235  1.1  christos #ifdef SLAPD_PBKDF2_DEBUG
    236  1.1  christos 	printf("Encrypt for %s\n", scheme->bv_val);
    237  1.1  christos 	printf("  Password:\t%s\n", passwd->bv_val);
    238  1.1  christos 
    239  1.1  christos 	printf("  Salt:\t\t");
    240  1.1  christos 	int i;
    241  1.1  christos 	for(i=0; i<salt.bv_len; i++){
    242  1.1  christos 		printf("%02x", salt_value[i]);
    243  1.1  christos 	}
    244  1.1  christos 	printf("\n");
    245  1.1  christos 	printf("  Iteration:\t%d\n", iteration);
    246  1.1  christos 
    247  1.1  christos 	printf("  DK:\t\t");
    248  1.1  christos 	for(i=0; i<dk.bv_len; i++){
    249  1.1  christos 		printf("%02x", dk_value[i]);
    250  1.1  christos 	}
    251  1.1  christos 	printf("\n");
    252  1.1  christos #endif
    253  1.1  christos 
    254  1.1  christos 	rc = pbkdf2_format(scheme, iteration, &salt, &dk, msg);
    255  1.1  christos 
    256  1.1  christos #ifdef SLAPD_PBKDF2_DEBUG
    257  1.1  christos 	printf("  Output:\t%s\n", msg->bv_val);
    258  1.1  christos #endif
    259  1.1  christos 
    260  1.1  christos 	return rc;
    261  1.1  christos }
    262  1.1  christos 
    263  1.1  christos static int pbkdf2_check(
    264  1.1  christos 	const struct berval *scheme,
    265  1.1  christos 	const struct berval *passwd,
    266  1.1  christos 	const struct berval *cred,
    267  1.1  christos 	const char **text)
    268  1.1  christos {
    269  1.1  christos 	int rc;
    270  1.1  christos 	int iteration;
    271  1.1  christos 
    272  1.1  christos 	/* salt_value require PBKDF2_SALT_SIZE + 1 in lutil_b64_pton. */
    273  1.1  christos 	unsigned char salt_value[PBKDF2_SALT_SIZE + 1];
    274  1.1  christos 	char salt_b64[LUTIL_BASE64_ENCODE_LEN(PBKDF2_SALT_SIZE) + 1];
    275  1.1  christos 	/* dk_value require PBKDF2_MAX_DK_SIZE + 1 in lutil_b64_pton. */
    276  1.1  christos 	unsigned char dk_value[PBKDF2_MAX_DK_SIZE + 1];
    277  1.1  christos 	char dk_b64[LUTIL_BASE64_ENCODE_LEN(PBKDF2_MAX_DK_SIZE) + 1];
    278  1.1  christos 	unsigned char input_dk_value[PBKDF2_MAX_DK_SIZE];
    279  1.1  christos 	size_t dk_len;
    280  1.1  christos #ifdef HAVE_OPENSSL
    281  1.1  christos 	const EVP_MD *md;
    282  1.1  christos #elif HAVE_GNUTLS
    283  1.1  christos 	struct hmac_sha1_ctx sha1_ctx;
    284  1.1  christos 	struct hmac_sha256_ctx sha256_ctx;
    285  1.1  christos 	struct hmac_sha512_ctx sha512_ctx;
    286  1.1  christos 	void * current_ctx = NULL;
    287  1.1  christos 	pbkdf2_hmac_update current_hmac_update = NULL;
    288  1.1  christos 	pbkdf2_hmac_digest current_hmac_digest = NULL;
    289  1.1  christos #endif
    290  1.1  christos 
    291  1.1  christos #ifdef SLAPD_PBKDF2_DEBUG
    292  1.1  christos 	printf("Checking for %s\n", scheme->bv_val);
    293  1.1  christos 	printf("  Stored Value:\t%s\n", passwd->bv_val);
    294  1.1  christos 	printf("  Input Cred:\t%s\n", cred->bv_val);
    295  1.1  christos #endif
    296  1.1  christos 
    297  1.1  christos #ifdef HAVE_OPENSSL
    298  1.1  christos 	if(!ber_bvcmp(scheme, &pbkdf2_scheme)){
    299  1.1  christos 		dk_len = PBKDF2_SHA1_DK_SIZE;
    300  1.1  christos 		md = EVP_sha1();
    301  1.1  christos 	}else if(!ber_bvcmp(scheme, &pbkdf2_sha1_scheme)){
    302  1.1  christos 		dk_len = PBKDF2_SHA1_DK_SIZE;
    303  1.1  christos 		md = EVP_sha1();
    304  1.1  christos 	}else if(!ber_bvcmp(scheme, &pbkdf2_sha256_scheme)){
    305  1.1  christos 		dk_len = PBKDF2_SHA256_DK_SIZE;
    306  1.1  christos 		md = EVP_sha256();
    307  1.1  christos 	}else if(!ber_bvcmp(scheme, &pbkdf2_sha512_scheme)){
    308  1.1  christos 		dk_len = PBKDF2_SHA512_DK_SIZE;
    309  1.1  christos 		md = EVP_sha512();
    310  1.1  christos 	}else{
    311  1.1  christos 		return LUTIL_PASSWD_ERR;
    312  1.1  christos 	}
    313  1.1  christos #elif HAVE_GNUTLS
    314  1.1  christos 	if(!ber_bvcmp(scheme, &pbkdf2_scheme)){
    315  1.1  christos 		dk_len = PBKDF2_SHA1_DK_SIZE;
    316  1.1  christos 		current_ctx = &sha1_ctx;
    317  1.1  christos 		current_hmac_update = (pbkdf2_hmac_update) &hmac_sha1_update;
    318  1.1  christos 		current_hmac_digest = (pbkdf2_hmac_digest) &hmac_sha1_digest;
    319  1.1  christos 		hmac_sha1_set_key(current_ctx, cred->bv_len, (const uint8_t *) cred->bv_val);
    320  1.1  christos 	}else if(!ber_bvcmp(scheme, &pbkdf2_sha1_scheme)){
    321  1.1  christos 		dk_len = PBKDF2_SHA1_DK_SIZE;
    322  1.1  christos 		current_ctx = &sha1_ctx;
    323  1.1  christos 		current_hmac_update = (pbkdf2_hmac_update) &hmac_sha1_update;
    324  1.1  christos 		current_hmac_digest = (pbkdf2_hmac_digest) &hmac_sha1_digest;
    325  1.1  christos 		hmac_sha1_set_key(current_ctx, cred->bv_len, (const uint8_t *) cred->bv_val);
    326  1.1  christos 	}else if(!ber_bvcmp(scheme, &pbkdf2_sha256_scheme)){
    327  1.1  christos 		dk_len = PBKDF2_SHA256_DK_SIZE;
    328  1.1  christos 		current_ctx = &sha256_ctx;
    329  1.1  christos 		current_hmac_update = (pbkdf2_hmac_update) &hmac_sha256_update;
    330  1.1  christos 		current_hmac_digest = (pbkdf2_hmac_digest) &hmac_sha256_digest;
    331  1.1  christos 		hmac_sha256_set_key(current_ctx, cred->bv_len, (const uint8_t *) cred->bv_val);
    332  1.1  christos 	}else if(!ber_bvcmp(scheme, &pbkdf2_sha512_scheme)){
    333  1.1  christos 		dk_len = PBKDF2_SHA512_DK_SIZE;
    334  1.1  christos 		current_ctx = &sha512_ctx;
    335  1.1  christos 		current_hmac_update = (pbkdf2_hmac_update) &hmac_sha512_update;
    336  1.1  christos 		current_hmac_digest = (pbkdf2_hmac_digest) &hmac_sha512_digest;
    337  1.1  christos 		hmac_sha512_set_key(current_ctx, cred->bv_len, (const uint8_t *) cred->bv_val);
    338  1.1  christos 	}else{
    339  1.1  christos 		return LUTIL_PASSWD_ERR;
    340  1.1  christos 	}
    341  1.1  christos #endif
    342  1.1  christos 
    343  1.1  christos 	iteration = atoi(passwd->bv_val);
    344  1.1  christos 	if(iteration < 1){
    345  1.1  christos 		return LUTIL_PASSWD_ERR;
    346  1.1  christos 	}
    347  1.1  christos 
    348  1.1  christos 	char *ptr;
    349  1.1  christos 	ptr = strchr(passwd->bv_val, '$');
    350  1.1  christos 	if(!ptr){
    351  1.1  christos 		return LUTIL_PASSWD_ERR;
    352  1.1  christos 	}
    353  1.1  christos 	ptr++; /* skip '$' */
    354  1.1  christos 	rc = ab64_to_b64(ptr, salt_b64, sizeof(salt_b64));
    355  1.1  christos 	if(rc < 0){
    356  1.1  christos 		return LUTIL_PASSWD_ERR;
    357  1.1  christos 	}
    358  1.1  christos 
    359  1.1  christos 	ptr = strchr(ptr, '$');
    360  1.1  christos 	if(!ptr){
    361  1.1  christos 		return LUTIL_PASSWD_ERR;
    362  1.1  christos 	}
    363  1.1  christos 	ptr++; /* skip '$' */
    364  1.1  christos 	rc = ab64_to_b64(ptr, dk_b64, sizeof(dk_b64));
    365  1.1  christos 	if(rc < 0){
    366  1.1  christos 		return LUTIL_PASSWD_ERR;
    367  1.1  christos 	}
    368  1.1  christos 
    369  1.1  christos 	/* The targetsize require PBKDF2_SALT_SIZE + 1 in lutil_b64_pton. */
    370  1.1  christos 	rc = lutil_b64_pton(salt_b64, salt_value, PBKDF2_SALT_SIZE + 1);
    371  1.1  christos 	if(rc < 0){
    372  1.1  christos 		return LUTIL_PASSWD_ERR;
    373  1.1  christos 	}
    374  1.1  christos 
    375  1.1  christos 	/* consistency check */
    376  1.1  christos 	if(rc != PBKDF2_SALT_SIZE){
    377  1.1  christos 		return LUTIL_PASSWD_ERR;
    378  1.1  christos 	}
    379  1.1  christos 
    380  1.1  christos 	/* The targetsize require PBKDF2_MAX_DK_SIZE + 1 in lutil_b64_pton. */
    381  1.1  christos 	rc = lutil_b64_pton(dk_b64, dk_value, sizeof(dk_value));
    382  1.1  christos 	if(rc < 0){
    383  1.1  christos 		return LUTIL_PASSWD_ERR;
    384  1.1  christos 	}
    385  1.1  christos 
    386  1.1  christos 	/* consistency check */
    387  1.1  christos 	if(rc != dk_len){
    388  1.1  christos 		return LUTIL_PASSWD_ERR;
    389  1.1  christos 	}
    390  1.1  christos 
    391  1.1  christos #ifdef HAVE_OPENSSL
    392  1.1  christos 	if(!PKCS5_PBKDF2_HMAC(cred->bv_val, cred->bv_len,
    393  1.1  christos 						  salt_value, PBKDF2_SALT_SIZE,
    394  1.1  christos 						  iteration, md, dk_len, input_dk_value)){
    395  1.1  christos 		return LUTIL_PASSWD_ERR;
    396  1.1  christos 	}
    397  1.1  christos #elif HAVE_GNUTLS
    398  1.1  christos 	PBKDF2(current_ctx, current_hmac_update, current_hmac_digest,
    399  1.1  christos 						  dk_len, iteration,
    400  1.1  christos 						  PBKDF2_SALT_SIZE, salt_value,
    401  1.1  christos 						  dk_len, input_dk_value);
    402  1.1  christos #endif
    403  1.1  christos 
    404  1.1  christos 	rc = memcmp(dk_value, input_dk_value, dk_len);
    405  1.1  christos #ifdef SLAPD_PBKDF2_DEBUG
    406  1.1  christos 	printf("  Iteration:\t%d\n", iteration);
    407  1.1  christos 	printf("  Base64 Salt:\t%s\n", salt_b64);
    408  1.1  christos 	printf("  Base64 DK:\t%s\n", dk_b64);
    409  1.1  christos 	int i;
    410  1.1  christos 	printf("  Stored Salt:\t");
    411  1.1  christos 	for(i=0; i<PBKDF2_SALT_SIZE; i++){
    412  1.1  christos 		printf("%02x", salt_value[i]);
    413  1.1  christos 	}
    414  1.1  christos 	printf("\n");
    415  1.1  christos 
    416  1.1  christos 	printf("  Stored DK:\t");
    417  1.1  christos 	for(i=0; i<dk_len; i++){
    418  1.1  christos 		printf("%02x", dk_value[i]);
    419  1.1  christos 	}
    420  1.1  christos 	printf("\n");
    421  1.1  christos 
    422  1.1  christos 	printf("  Input DK:\t");
    423  1.1  christos 	for(i=0; i<dk_len; i++){
    424  1.1  christos 		printf("%02x", input_dk_value[i]);
    425  1.1  christos 	}
    426  1.1  christos 	printf("\n");
    427  1.1  christos 	printf("  Result:\t%d\n", rc);
    428  1.1  christos #endif
    429  1.1  christos 	return rc?LUTIL_PASSWD_ERR:LUTIL_PASSWD_OK;
    430  1.1  christos }
    431  1.1  christos 
    432  1.1  christos int init_module(int argc, char *argv[]) {
    433  1.1  christos 	int rc;
    434  1.1  christos 	rc = lutil_passwd_add((struct berval *)&pbkdf2_scheme,
    435  1.1  christos 						  pbkdf2_check, pbkdf2_encrypt);
    436  1.1  christos 	if(rc) return rc;
    437  1.1  christos 	rc = lutil_passwd_add((struct berval *)&pbkdf2_sha1_scheme,
    438  1.1  christos 						  pbkdf2_check, pbkdf2_encrypt);
    439  1.1  christos 	if(rc) return rc;
    440  1.1  christos 
    441  1.1  christos 	rc = lutil_passwd_add((struct berval *)&pbkdf2_sha256_scheme,
    442  1.1  christos 						  pbkdf2_check, pbkdf2_encrypt);
    443  1.1  christos 	if(rc) return rc;
    444  1.1  christos 
    445  1.1  christos 	rc = lutil_passwd_add((struct berval *)&pbkdf2_sha512_scheme,
    446  1.1  christos 						  pbkdf2_check, pbkdf2_encrypt);
    447  1.1  christos 	return rc;
    448  1.1  christos }
    449  1.1  christos 
    450  1.1  christos /*
    451  1.1  christos  * Local variables:
    452  1.1  christos  * indent-tabs-mode: t
    453  1.1  christos  * tab-width: 4
    454  1.1  christos  * c-basic-offset: 4
    455  1.1  christos  * End:
    456  1.1  christos  */
    457