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