static int dcrypt_gnutls_pbkdf2(const unsigned char *password, size_t password_len, const unsigned char *salt, size_t salt_len, const char *algorithm, unsigned int rounds, buffer_t *result, unsigned int result_len, const char **error_r) { unsigned char buf[result_len]; /* only sha1 or sha256 is supported */ if (strncasecmp(algorithm, "sha1", 4) == 0) { pbkdf2_hmac_sha1(password_len, password, rounds, salt_len, salt, result_len, buf); } else if (strncasecmp(algorithm, "sha256", 6) == 0) { pbkdf2_hmac_sha256(password_len, password, rounds, salt_len, salt, result_len, buf); } else if (strncasecmp(algorithm, "sha512", 6) == 0) { struct hmac_sha512_ctx ctx; hmac_sha512_set_key(&ctx, password_len, password); PBKDF2(&ctx, hmac_sha512_update, hmac_sha512_digest, 64, rounds, salt_len, salt, result_len, buf); i_zero(&ctx); } else { *error_r = "Unsupported algorithm"; return -1; } buffer_append(result, buf, result_len); memset(buf, 0, sizeof(buf)); return 0; }
static int pbkdf2_check( const struct berval *scheme, const struct berval *passwd, const struct berval *cred, const char **text) { int rc; int iteration; /* salt_value require PBKDF2_SALT_SIZE + 1 in lutil_b64_pton. */ unsigned char salt_value[PBKDF2_SALT_SIZE + 1]; char salt_b64[LUTIL_BASE64_ENCODE_LEN(PBKDF2_SALT_SIZE) + 1]; /* dk_value require PBKDF2_MAX_DK_SIZE + 1 in lutil_b64_pton. */ unsigned char dk_value[PBKDF2_MAX_DK_SIZE + 1]; char dk_b64[LUTIL_BASE64_ENCODE_LEN(PBKDF2_MAX_DK_SIZE) + 1]; unsigned char input_dk_value[PBKDF2_MAX_DK_SIZE]; size_t dk_len; #ifdef HAVE_OPENSSL const EVP_MD *md; #elif HAVE_GNUTLS struct hmac_sha1_ctx sha1_ctx; struct hmac_sha256_ctx sha256_ctx; struct hmac_sha512_ctx sha512_ctx; void * current_ctx = NULL; pbkdf2_hmac_update current_hmac_update = NULL; pbkdf2_hmac_digest current_hmac_digest = NULL; #endif #ifdef SLAPD_PBKDF2_DEBUG printf("Checking for %s\n", scheme->bv_val); printf(" Stored Value:\t%s\n", passwd->bv_val); printf(" Input Cred:\t%s\n", cred->bv_val); #endif #ifdef HAVE_OPENSSL if(!ber_bvcmp(scheme, &pbkdf2_scheme)){ dk_len = PBKDF2_SHA1_DK_SIZE; md = EVP_sha1(); }else if(!ber_bvcmp(scheme, &pbkdf2_sha1_scheme)){ dk_len = PBKDF2_SHA1_DK_SIZE; md = EVP_sha1(); }else if(!ber_bvcmp(scheme, &pbkdf2_sha256_scheme)){ dk_len = PBKDF2_SHA256_DK_SIZE; md = EVP_sha256(); }else if(!ber_bvcmp(scheme, &pbkdf2_sha512_scheme)){ dk_len = PBKDF2_SHA512_DK_SIZE; md = EVP_sha512(); }else{ return LUTIL_PASSWD_ERR; } #elif HAVE_GNUTLS if(!ber_bvcmp(scheme, &pbkdf2_scheme)){ dk_len = PBKDF2_SHA1_DK_SIZE; current_ctx = &sha1_ctx; current_hmac_update = (pbkdf2_hmac_update) &hmac_sha1_update; current_hmac_digest = (pbkdf2_hmac_digest) &hmac_sha1_digest; hmac_sha1_set_key(current_ctx, cred->bv_len, (const uint8_t *) cred->bv_val); }else if(!ber_bvcmp(scheme, &pbkdf2_sha1_scheme)){ dk_len = PBKDF2_SHA1_DK_SIZE; current_ctx = &sha1_ctx; current_hmac_update = (pbkdf2_hmac_update) &hmac_sha1_update; current_hmac_digest = (pbkdf2_hmac_digest) &hmac_sha1_digest; hmac_sha1_set_key(current_ctx, cred->bv_len, (const uint8_t *) cred->bv_val); }else if(!ber_bvcmp(scheme, &pbkdf2_sha256_scheme)){ dk_len = PBKDF2_SHA256_DK_SIZE; current_ctx = &sha256_ctx; current_hmac_update = (pbkdf2_hmac_update) &hmac_sha256_update; current_hmac_digest = (pbkdf2_hmac_digest) &hmac_sha256_digest; hmac_sha256_set_key(current_ctx, cred->bv_len, (const uint8_t *) cred->bv_val); }else if(!ber_bvcmp(scheme, &pbkdf2_sha512_scheme)){ dk_len = PBKDF2_SHA512_DK_SIZE; current_ctx = &sha512_ctx; current_hmac_update = (pbkdf2_hmac_update) &hmac_sha512_update; current_hmac_digest = (pbkdf2_hmac_digest) &hmac_sha512_digest; hmac_sha512_set_key(current_ctx, cred->bv_len, (const uint8_t *) cred->bv_val); }else{ return LUTIL_PASSWD_ERR; } #endif iteration = atoi(passwd->bv_val); if(iteration < 1){ return LUTIL_PASSWD_ERR; } char *ptr; ptr = strchr(passwd->bv_val, '$'); if(!ptr){ return LUTIL_PASSWD_ERR; } ptr++; /* skip '$' */ rc = ab64_to_b64(ptr, salt_b64, sizeof(salt_b64)); if(rc < 0){ return LUTIL_PASSWD_ERR; } ptr = strchr(ptr, '$'); if(!ptr){ return LUTIL_PASSWD_ERR; } ptr++; /* skip '$' */ rc = ab64_to_b64(ptr, dk_b64, sizeof(dk_b64)); if(rc < 0){ return LUTIL_PASSWD_ERR; } /* The targetsize require PBKDF2_SALT_SIZE + 1 in lutil_b64_pton. */ rc = lutil_b64_pton(salt_b64, salt_value, PBKDF2_SALT_SIZE + 1); if(rc < 0){ return LUTIL_PASSWD_ERR; } /* consistency check */ if(rc != PBKDF2_SALT_SIZE){ return LUTIL_PASSWD_ERR; } /* The targetsize require PBKDF2_MAX_DK_SIZE + 1 in lutil_b64_pton. */ rc = lutil_b64_pton(dk_b64, dk_value, sizeof(dk_value)); if(rc < 0){ return LUTIL_PASSWD_ERR; } /* consistency check */ if(rc != dk_len){ return LUTIL_PASSWD_ERR; } #ifdef HAVE_OPENSSL if(!PKCS5_PBKDF2_HMAC(cred->bv_val, cred->bv_len, salt_value, PBKDF2_SALT_SIZE, iteration, md, dk_len, input_dk_value)){ return LUTIL_PASSWD_ERR; } #elif HAVE_GNUTLS PBKDF2(current_ctx, current_hmac_update, current_hmac_digest, dk_len, iteration, PBKDF2_SALT_SIZE, salt_value, dk_len, input_dk_value); #endif rc = memcmp(dk_value, input_dk_value, dk_len); #ifdef SLAPD_PBKDF2_DEBUG printf(" Iteration:\t%d\n", iteration); printf(" Base64 Salt:\t%s\n", salt_b64); printf(" Base64 DK:\t%s\n", dk_b64); int i; printf(" Stored Salt:\t"); for(i=0; i<PBKDF2_SALT_SIZE; i++){ printf("%02x", salt_value[i]); } printf("\n"); printf(" Stored DK:\t"); for(i=0; i<dk_len; i++){ printf("%02x", dk_value[i]); } printf("\n"); printf(" Input DK:\t"); for(i=0; i<dk_len; i++){ printf("%02x", input_dk_value[i]); } printf("\n"); printf(" Result:\t%d\n", rc); #endif return rc?LUTIL_PASSWD_ERR:LUTIL_PASSWD_OK; }
static int pbkdf2_encrypt( const struct berval *scheme, const struct berval *passwd, struct berval *msg, const char **text) { unsigned char salt_value[PBKDF2_SALT_SIZE]; struct berval salt; unsigned char dk_value[PBKDF2_MAX_DK_SIZE]; struct berval dk; int iteration = PBKDF2_ITERATION; int rc; #ifdef HAVE_OPENSSL const EVP_MD *md; #elif HAVE_GNUTLS struct hmac_sha1_ctx sha1_ctx; struct hmac_sha256_ctx sha256_ctx; struct hmac_sha512_ctx sha512_ctx; void * current_ctx = NULL; pbkdf2_hmac_update current_hmac_update = NULL; pbkdf2_hmac_digest current_hmac_digest = NULL; #endif salt.bv_val = (char *)salt_value; salt.bv_len = sizeof(salt_value); dk.bv_val = (char *)dk_value; #ifdef HAVE_OPENSSL if(!ber_bvcmp(scheme, &pbkdf2_scheme)){ dk.bv_len = PBKDF2_SHA1_DK_SIZE; md = EVP_sha1(); }else if(!ber_bvcmp(scheme, &pbkdf2_sha1_scheme)){ dk.bv_len = PBKDF2_SHA1_DK_SIZE; md = EVP_sha1(); }else if(!ber_bvcmp(scheme, &pbkdf2_sha256_scheme)){ dk.bv_len = PBKDF2_SHA256_DK_SIZE; md = EVP_sha256(); }else if(!ber_bvcmp(scheme, &pbkdf2_sha512_scheme)){ dk.bv_len = PBKDF2_SHA512_DK_SIZE; md = EVP_sha512(); }else{ return LUTIL_PASSWD_ERR; } #elif HAVE_GNUTLS if(!ber_bvcmp(scheme, &pbkdf2_scheme)){ dk.bv_len = PBKDF2_SHA1_DK_SIZE; current_ctx = &sha1_ctx; current_hmac_update = (pbkdf2_hmac_update) &hmac_sha1_update; current_hmac_digest = (pbkdf2_hmac_digest) &hmac_sha1_digest; hmac_sha1_set_key(current_ctx, passwd->bv_len, (const uint8_t *) passwd->bv_val); }else if(!ber_bvcmp(scheme, &pbkdf2_sha1_scheme)){ dk.bv_len = PBKDF2_SHA1_DK_SIZE; current_ctx = &sha1_ctx; current_hmac_update = (pbkdf2_hmac_update) &hmac_sha1_update; current_hmac_digest = (pbkdf2_hmac_digest) &hmac_sha1_digest; hmac_sha1_set_key(current_ctx, passwd->bv_len, (const uint8_t *) passwd->bv_val); }else if(!ber_bvcmp(scheme, &pbkdf2_sha256_scheme)){ dk.bv_len = PBKDF2_SHA256_DK_SIZE; current_ctx = &sha256_ctx; current_hmac_update = (pbkdf2_hmac_update) &hmac_sha256_update; current_hmac_digest = (pbkdf2_hmac_digest) &hmac_sha256_digest; hmac_sha256_set_key(current_ctx, passwd->bv_len, (const uint8_t *) passwd->bv_val); }else if(!ber_bvcmp(scheme, &pbkdf2_sha512_scheme)){ dk.bv_len = PBKDF2_SHA512_DK_SIZE; current_ctx = &sha512_ctx; current_hmac_update = (pbkdf2_hmac_update) &hmac_sha512_update; current_hmac_digest = (pbkdf2_hmac_digest) &hmac_sha512_digest; hmac_sha512_set_key(current_ctx, passwd->bv_len, (const uint8_t *) passwd->bv_val); }else{ return LUTIL_PASSWD_ERR; } #endif if(lutil_entropy((unsigned char *)salt.bv_val, salt.bv_len) < 0){ return LUTIL_PASSWD_ERR; } #ifdef HAVE_OPENSSL if(!PKCS5_PBKDF2_HMAC(passwd->bv_val, passwd->bv_len, (unsigned char *)salt.bv_val, salt.bv_len, iteration, md, dk.bv_len, dk_value)){ return LUTIL_PASSWD_ERR; } #elif HAVE_GNUTLS PBKDF2(current_ctx, current_hmac_update, current_hmac_digest, dk.bv_len, iteration, salt.bv_len, (const uint8_t *) salt.bv_val, dk.bv_len, dk_value); #endif #ifdef SLAPD_PBKDF2_DEBUG printf("Encrypt for %s\n", scheme->bv_val); printf(" Password:\t%s\n", passwd->bv_val); printf(" Salt:\t\t"); int i; for(i=0; i<salt.bv_len; i++){ printf("%02x", salt_value[i]); } printf("\n"); printf(" Iteration:\t%d\n", iteration); printf(" DK:\t\t"); for(i=0; i<dk.bv_len; i++){ printf("%02x", dk_value[i]); } printf("\n"); #endif rc = pbkdf2_format(scheme, iteration, &salt, &dk, msg); #ifdef SLAPD_PBKDF2_DEBUG printf(" Output:\t%s\n", msg->bv_val); #endif return rc; }