Skip to content

Commit

Permalink
refactor: replace custom PBKDF2 implementation with OpenSSL's PKCS5_P…
Browse files Browse the repository at this point in the history
…BKDF2_HMAC for improved security and maintainability

Signed-off-by: Dengfeng Liu <liudf0716@gmail.com>
  • Loading branch information
liudf0716 committed Nov 13, 2024
1 parent 65ddb68 commit d423b4f
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 97 deletions.
80 changes: 9 additions & 71 deletions fastpbkdf2.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,91 +4,29 @@
#include <openssl/core_names.h>
#include "fastpbkdf2.h"

static void write32_be(uint32_t n, uint8_t out[4]) {
out[0] = (n >> 24) & 0xff;
out[1] = (n >> 16) & 0xff;
out[2] = (n >> 8) & 0xff;
out[3] = n & 0xff;
}

static void xor_block(uint8_t *out, const uint8_t *in) {
size_t i;
for (i = 0; i < EVP_MAX_MD_SIZE; i++) {
out[i] ^= in[i];
}
}

static void pbkdf2_impl(const EVP_MD *md,
const uint8_t *pw, size_t npw,
const uint8_t *salt, size_t nsalt,
uint32_t iterations,
uint8_t *out, size_t nout) {
EVP_MAC *mac = EVP_MAC_fetch(NULL, "HMAC", NULL);
EVP_MAC_CTX *ctx = EVP_MAC_CTX_new(mac);
OSSL_PARAM params[2];
uint32_t counter = 1;
unsigned int digestlen;
size_t remain = nout;

params[0] = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_DIGEST,
(char *)EVP_MD_name(md), 0);
params[1] = OSSL_PARAM_construct_end();

EVP_MAC_init(ctx, pw, npw, params);

while (remain > 0) {
uint8_t countbuf[4];
uint8_t Txi[EVP_MAX_MD_SIZE];
uint8_t Ti[EVP_MAX_MD_SIZE];
size_t copy;
size_t outlen;

write32_be(counter, countbuf);

/* First iteration */
EVP_MAC_init(ctx, NULL, 0, NULL);
EVP_MAC_update(ctx, salt, nsalt);
EVP_MAC_update(ctx, countbuf, 4);
EVP_MAC_final(ctx, Ti, &outlen, EVP_MAX_MD_SIZE);
digestlen = outlen;
memcpy(Txi, Ti, digestlen);

/* Subsequent iterations */
for (uint32_t i = 1; i < iterations; i++) {
EVP_MAC_init(ctx, NULL, 0, NULL);
EVP_MAC_update(ctx, Ti, digestlen);
EVP_MAC_final(ctx, Ti, &outlen, EVP_MAX_MD_SIZE);
xor_block(Txi, Ti);
}

copy = (remain > digestlen) ? digestlen : remain;
memcpy(out, Txi, copy);
out += copy;
remain -= copy;
counter++;
}

EVP_MAC_CTX_free(ctx);
EVP_MAC_free(mac);
}

void fastpbkdf2_hmac_sha1(const uint8_t *pw, size_t npw,
const uint8_t *salt, size_t nsalt,
uint32_t iterations,
uint8_t *out, size_t nout) {
pbkdf2_impl(EVP_sha1(), pw, npw, salt, nsalt, iterations, out, nout);
PKCS5_PBKDF2_HMAC((const char *)pw, npw,
salt, nsalt, iterations,
EVP_sha1(), nout, out);
}

void fastpbkdf2_hmac_sha256(const uint8_t *pw, size_t npw,
const uint8_t *salt, size_t nsalt,
uint32_t iterations,
uint8_t *out, size_t nout) {
pbkdf2_impl(EVP_sha256(), pw, npw, salt, nsalt, iterations, out, nout);
PKCS5_PBKDF2_HMAC((const char *)pw, npw,
salt, nsalt, iterations,
EVP_sha256(), nout, out);
}

void fastpbkdf2_hmac_sha512(const uint8_t *pw, size_t npw,
const uint8_t *salt, size_t nsalt,
uint32_t iterations,
uint8_t *out, size_t nout) {
pbkdf2_impl(EVP_sha512(), pw, npw, salt, nsalt, iterations, out, nout);
PKCS5_PBKDF2_HMAC((const char *)pw, npw,
salt, nsalt, iterations,
EVP_sha512(), nout, out);
}
8 changes: 0 additions & 8 deletions fastpbkdf2.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,6 @@
#include <stdint.h>
#include <openssl/evp.h>

#ifdef __cplusplus
extern "C" {
#endif

/* Function declarations remain unchanged for API compatibility */
void fastpbkdf2_hmac_sha1(const uint8_t *pw, size_t npw,
const uint8_t *salt, size_t nsalt,
Expand All @@ -25,8 +21,4 @@ void fastpbkdf2_hmac_sha512(const uint8_t *pw, size_t npw,
uint32_t iterations,
uint8_t *out, size_t nout);

#ifdef __cplusplus
}
#endif

#endif
38 changes: 20 additions & 18 deletions test_fastpbkdf2.c
Original file line number Diff line number Diff line change
@@ -1,28 +1,30 @@
#include <stdio.h>
#include <openssl/evp.h>
#include <openssl/sha.h>
#include <string.h>
#include <stdint.h>
#include "fastpbkdf2.h"
#include <stdio.h>

void print_hex(const uint8_t *data, size_t len) {
for (size_t i = 0; i < len; i++) {
printf("%02x", data[i]);
}
printf("\n");
void pbkdf2_key(const uint8_t *password, size_t password_len,
const uint8_t *salt, size_t salt_len,
uint32_t iterations, uint8_t *out, size_t out_len) {
PKCS5_PBKDF2_HMAC((const char *)password, password_len,
salt, salt_len, iterations,
EVP_sha1(), out_len, out);
}

void test_fastpbkdf2_hmac_sha1() {
const uint8_t password[] = "password";
const uint8_t salt[] = "salt";
uint32_t iterations = 1000;
uint8_t output[20]; // SHA-1 produces a 20-byte hash
int main() {
const char *password = "password";
const uint8_t salt[] = "saltsalt";
uint8_t key[16]; // size of the derived key

fastpbkdf2_hmac_sha1(password, strlen((const char *)password), salt, strlen((const char *)salt), iterations, output, sizeof(output));
pbkdf2_key((const uint8_t *)password, strlen(password),
salt, sizeof(salt) - 1, 1000, key, sizeof(key));

printf("PBKDF2-HMAC-SHA1: ");
print_hex(output, sizeof(output));
}
printf("Derived key: ");
for (size_t i = 0; i < sizeof(key); i++) {
printf("%02x", key[i]);
}
printf("\n");

int main() {
test_fastpbkdf2_hmac_sha1();
return 0;
}

0 comments on commit d423b4f

Please sign in to comment.