static int pbkdf2_format( const struct berval *sc, int iteration, const struct berval *salt, const struct berval *dk, struct berval *msg) { int rc, msg_len; char salt_b64[LUTIL_BASE64_ENCODE_LEN(PBKDF2_SALT_SIZE) + 1]; char dk_b64[LUTIL_BASE64_ENCODE_LEN(PBKDF2_MAX_DK_SIZE) + 1]; rc = lutil_b64_ntop((unsigned char *)salt->bv_val, salt->bv_len, salt_b64, sizeof(salt_b64)); if(rc < 0){ return LUTIL_PASSWD_ERR; } b64_to_ab64(salt_b64); rc = lutil_b64_ntop((unsigned char *)dk->bv_val, dk->bv_len, dk_b64, sizeof(dk_b64)); if(rc < 0){ return LUTIL_PASSWD_ERR; } b64_to_ab64(dk_b64); msg_len = asprintf(&msg->bv_val, "%s%d$%s$%s", sc->bv_val, iteration, salt_b64, dk_b64); if(msg_len < 0){ msg->bv_len = 0; return LUTIL_PASSWD_ERR; } msg->bv_len = msg_len; return LUTIL_PASSWD_OK; }
/* pw_string64 function taken from libraries/liblutil/passwd.c */ static int pw_string64( const struct berval *sc, const struct berval *hash, struct berval *b64, const struct berval *salt ) { int rc; struct berval string; size_t b64len; if( salt ) { /* need to base64 combined string */ string.bv_len = hash->bv_len + salt->bv_len; string.bv_val = ber_memalloc( string.bv_len + 1 ); if( string.bv_val == NULL ) { return LUTIL_PASSWD_ERR; } AC_MEMCPY( string.bv_val, hash->bv_val, hash->bv_len ); AC_MEMCPY( &string.bv_val[hash->bv_len], salt->bv_val, salt->bv_len ); string.bv_val[string.bv_len] = '\0'; } else { string = *hash; } b64len = LUTIL_BASE64_ENCODE_LEN( string.bv_len ) + 1; b64->bv_len = b64len + sc->bv_len; b64->bv_val = ber_memalloc( b64->bv_len + 1 ); if( b64->bv_val == NULL ) { if( salt ) ber_memfree( string.bv_val ); return LUTIL_PASSWD_ERR; } AC_MEMCPY(b64->bv_val, sc->bv_val, sc->bv_len); rc = lutil_b64_ntop( (unsigned char *) string.bv_val, string.bv_len, &b64->bv_val[sc->bv_len], b64len ); if( salt ) ber_memfree( string.bv_val ); if( rc < 0 ) { return LUTIL_PASSWD_ERR; } /* recompute length */ b64->bv_len = sc->bv_len + rc; assert( strlen(b64->bv_val) == b64->bv_len ); return LUTIL_PASSWD_OK; }
char * sha256_hex_hash(const char * passwd) { SHA256_CTX ct; unsigned char hash[SHA256_DIGEST_LENGTH]; static char real_hash[LUTIL_BASE64_ENCODE_LEN(SHA256_DIGEST_LENGTH)+1]; // extra char for \0 SHA256_Init(&ct); SHA256_Update(&ct, (const uint8_t*)passwd, strlen(passwd)); SHA256_Final(hash, &ct); /* base64 encode it */ lutil_b64_ntop( hash, SHA256_DIGEST_LENGTH, real_hash, LUTIL_BASE64_ENCODE_LEN(SHA256_DIGEST_LENGTH)+1 ); return real_hash; }
static void chk_sha_debug( const struct berval *scheme, const struct berval *passwd, const struct berval *cred, const char *cred_hash, size_t cred_len, int cmp_rc) { int rc; struct berval cred_b64; cred_b64.bv_len = LUTIL_BASE64_ENCODE_LEN(cred_len) + 1; cred_b64.bv_val = ber_memalloc(cred_b64.bv_len + 1); if( cred_b64.bv_val == NULL ) { return; } rc = lutil_b64_ntop( (unsigned char *) cred_hash, cred_len, cred_b64.bv_val, cred_b64.bv_len ); if( rc < 0 ) { ber_memfree(cred_b64.bv_val); return; } fprintf(stderr, "Validating password\n"); fprintf(stderr, " Hash scheme:\t\t%s\n", scheme->bv_val); fprintf(stderr, " Password to validate: %s\n", cred->bv_val); fprintf(stderr, " Password hash:\t%s\n", cred_b64.bv_val); fprintf(stderr, " Stored password hash:\t%s\n", passwd->bv_val); fprintf(stderr, " Result:\t\t%s\n", cmp_rc ? "do not match" : "match"); ber_memfree(cred_b64.bv_val); }
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_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_DK_SIZE + 1 in lutil_b64_pton. */ unsigned char dk_value[PBKDF2_DK_SIZE + 1]; char dk_b64[LUTIL_BASE64_ENCODE_LEN(PBKDF2_DK_SIZE) + 1]; unsigned char input_dk_value[PBKDF2_DK_SIZE]; #ifdef SLAPD_PBKDF2_DEBUG printf("DEBUG pbkdf2_check()\n"); printf(" Stored Value:\t%s\n", passwd->bv_val); printf(" Input Cred:\t%s\n", cred->bv_val); #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_DK_SIZE + 1 in lutil_b64_pton. */ rc = lutil_b64_pton(dk_b64, dk_value, PBKDF2_DK_SIZE + 1); if(rc < 0){ return LUTIL_PASSWD_ERR; } /* consistency check */ if(rc != PBKDF2_DK_SIZE){ return LUTIL_PASSWD_ERR; } if(!PKCS5_PBKDF2_HMAC_SHA1(cred->bv_val, cred->bv_len, salt_value, PBKDF2_SALT_SIZE, iteration, PBKDF2_DK_SIZE, input_dk_value)){ return LUTIL_PASSWD_ERR; } rc = memcmp(dk_value, input_dk_value, PBKDF2_DK_SIZE); #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<PBKDF2_DK_SIZE; i++){ printf("%02x", dk_value[i]); } printf("\n"); printf(" Input DK:\t"); for(i=0; i<PBKDF2_DK_SIZE; i++){ printf("%02x", input_dk_value[i]); } printf("\n"); printf(" Result:\t%d\n", rc); #endif return rc?LUTIL_PASSWD_ERR:LUTIL_PASSWD_OK; }