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@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