/** * PBKDF2_SHA256(passwd, passwdlen, salt, saltlen, c, buf, dkLen): * Compute PBKDF2(passwd, salt, c, dkLen) using HMAC-SHA256 as the PRF, and * write the output to buf. The value dkLen must be at most 32 * (2^32 - 1). */ void PBKDF2_SHA256(const uint8_t *passwd, size_t passwdlen, const uint8_t *salt, size_t saltlen, uint64_t c, uint8_t *buf, size_t dkLen) { crypto_auth_hmacsha256_state PShctx, hctx; size_t i; uint8_t ivec[4]; uint8_t U[32]; uint8_t T[32]; uint64_t j; int k; size_t clen; #if SIZE_MAX > 0x1fffffffe0ULL if (dkLen > 0x1fffffffe0ULL) { abort(); } #endif crypto_auth_hmacsha256_init(&PShctx, passwd, passwdlen); crypto_auth_hmacsha256_update(&PShctx, salt, saltlen); for (i = 0; i * 32 < dkLen; i++) { STORE32_BE(ivec, (uint32_t)(i + 1)); memcpy(&hctx, &PShctx, sizeof(crypto_auth_hmacsha256_state)); crypto_auth_hmacsha256_update(&hctx, ivec, 4); crypto_auth_hmacsha256_final(&hctx, U); memcpy(T, U, 32); /* LCOV_EXCL_START */ for (j = 2; j <= c; j++) { crypto_auth_hmacsha256_init(&hctx, passwd, passwdlen); crypto_auth_hmacsha256_update(&hctx, U, 32); crypto_auth_hmacsha256_final(&hctx, U); for (k = 0; k < 32; k++) { T[k] ^= U[k]; } } /* LCOV_EXCL_STOP */ clen = dkLen - i * 32; if (clen > 32) { clen = 32; } memcpy(&buf[i * 32], T, clen); } sodium_memzero((void *) &PShctx, sizeof PShctx); }
static int hkdf_extract(unsigned char* out, const unsigned char* salt, const size_t saltlen, const unsigned char* in, const size_t inlen) { crypto_auth_hmacsha256_state state; crypto_auth_hmacsha256_init(&state, salt, saltlen); crypto_auth_hmacsha256_update(&state, in, inlen); return crypto_auth_hmacsha256_final(&state, out); }
static void mm_hmacsha256(void) { crypto_auth_hmacsha256_state st; unsigned char *h, *h2; unsigned char *k; unsigned char *m; size_t mlen; size_t l1, l2; int i; for (i = 0; i < MAX_ITER; i++) { mlen = randombytes_uniform(MAXLEN); m = (unsigned char *) sodium_malloc(mlen); k = (unsigned char *) sodium_malloc(crypto_auth_hmacsha256_KEYBYTES); h = (unsigned char *) sodium_malloc(crypto_auth_hmacsha256_BYTES); h2 = (unsigned char *) sodium_malloc(crypto_auth_hmacsha256_BYTES); crypto_auth_hmacsha256_keygen(k); randombytes_buf(m, mlen); crypto_auth_hmacsha256_init(&st, k, crypto_auth_hmacsha256_KEYBYTES); l1 = randombytes_uniform(mlen); l2 = randombytes_uniform(mlen - l1); crypto_auth_hmacsha256_update(&st, m, l1); crypto_auth_hmacsha256_update(&st, m + l1, l2); crypto_auth_hmacsha256_update(&st, m + l1 + l2, mlen - l1 - l2); crypto_auth_hmacsha256_final(&st, h); crypto_auth_hmacsha256(h2, m, mlen, k); assert(memcmp(h, h2, crypto_auth_hmacsha256_BYTES) == 0); sodium_free(h2); sodium_free(h); sodium_free(k); sodium_free(m); } }
static int hkdf_expand(unsigned char* out, enum hkdf_msg_ver_t offset, const unsigned char* prk, const size_t prklen, const unsigned char* info, const size_t infolen, const unsigned outlen) { unsigned iters = (unsigned) ceil( (double)outlen / (double)HASH_OUTSZ ); unsigned char mixin[crypto_auth_hmacsha256_BYTES]; unsigned remaining_bytes = outlen; sodium_memzero(out, outlen); sodium_memzero(mixin, sizeof mixin); unsigned char* tmp_res = out; for (unsigned i = offset; i < iters + offset; i++){ crypto_auth_hmacsha256_state state; crypto_auth_hmacsha256_init(&state, prk, prklen); if (i != offset) crypto_auth_hmacsha256_update(&state, mixin, sizeof mixin); if (info != NULL) crypto_auth_hmacsha256_update(&state, info, infolen); unsigned char ii = (unsigned char)i; crypto_auth_hmacsha256_update(&state, &ii, sizeof ii); unsigned char step_out[crypto_auth_hmacsha256_BYTES]; crypto_auth_hmacsha256_final(&state, step_out); int steplen = min(remaining_bytes, sizeof step_out); memcpy(tmp_res, step_out, steplen); tmp_res += steplen; memcpy(mixin, step_out, sizeof step_out); remaining_bytes -= steplen; } return 0; }