/* HMAC-KDF-Extract. * RFC 5869 - HMAC-based Extract-and-Expand Key Derivation Function (HKDF). * * type The hash algorithm type. * salt The optional salt value. * saltSz The size of the salt. * inKey The input keying material. * inKeySz The size of the input keying material. * out The pseudorandom key with the length that of the hash. * returns 0 on success, otherwise failure. */ int wc_HKDF_Extract(int type, const byte* salt, word32 saltSz, const byte* inKey, word32 inKeySz, byte* out) { byte tmp[WC_MAX_DIGEST_SIZE]; /* localSalt helper */ Hmac myHmac; int ret; const byte* localSalt; /* either points to user input or tmp */ int hashSz; ret = wc_HmacSizeByType(type); if (ret < 0) return ret; hashSz = ret; localSalt = salt; if (localSalt == NULL) { XMEMSET(tmp, 0, hashSz); localSalt = tmp; saltSz = hashSz; } ret = wc_HmacInit(&myHmac, NULL, INVALID_DEVID); if (ret == 0) { ret = wc_HmacSetKey(&myHmac, type, localSalt, saltSz); if (ret == 0) ret = wc_HmacUpdate(&myHmac, inKey, inKeySz); if (ret == 0) ret = wc_HmacFinal(&myHmac, out); wc_HmacFree(&myHmac); } return ret; }
/* HMAC-KDF-Expand. * RFC 5869 - HMAC-based Extract-and-Expand Key Derivation Function (HKDF). * * type The hash algorithm type. * inKey The input key. * inKeySz The size of the input key. * info The application specific information. * infoSz The size of the application specific information. * out The output keying material. * returns 0 on success, otherwise failure. */ int wc_HKDF_Expand(int type, const byte* inKey, word32 inKeySz, const byte* info, word32 infoSz, byte* out, word32 outSz) { byte tmp[WC_MAX_DIGEST_SIZE]; Hmac myHmac; int ret = 0; word32 outIdx = 0; word32 hashSz = wc_HmacSizeByType(type); byte n = 0x1; ret = wc_HmacInit(&myHmac, NULL, INVALID_DEVID); if (ret != 0) return ret; while (outIdx < outSz) { int tmpSz = (n == 1) ? 0 : hashSz; word32 left = outSz - outIdx; ret = wc_HmacSetKey(&myHmac, type, inKey, inKeySz); if (ret != 0) break; ret = wc_HmacUpdate(&myHmac, tmp, tmpSz); if (ret != 0) break; ret = wc_HmacUpdate(&myHmac, info, infoSz); if (ret != 0) break; ret = wc_HmacUpdate(&myHmac, &n, 1); if (ret != 0) break; ret = wc_HmacFinal(&myHmac, tmp); if (ret != 0) break; left = min(left, hashSz); XMEMCPY(out+outIdx, tmp, left); outIdx += hashSz; n++; } wc_HmacFree(&myHmac); return ret; }
int wc_HmacInit_Id(Hmac* hmac, unsigned char* id, int len, void* heap, int devId) { int ret = 0; if (hmac == NULL) ret = BAD_FUNC_ARG; if (ret == 0 && (len < 0 || len > HMAC_MAX_ID_LEN)) ret = BUFFER_E; if (ret == 0) ret = wc_HmacInit(hmac, heap, devId); if (ret == 0) { XMEMCPY(hmac->id, id, len); hmac->idLen = len; } return ret; }
int wc_PBKDF2(byte* output, const byte* passwd, int pLen, const byte* salt, int sLen, int iterations, int kLen, int hashType) { word32 i = 1; int hLen; int j, ret; Hmac hmac; #ifdef WOLFSSL_SMALL_STACK byte* buffer; #else byte buffer[MAX_DIGEST_SIZE]; #endif hLen = GetDigestSize(hashType); if (hLen < 0) return BAD_FUNC_ARG; #ifdef WOLFSSL_SMALL_STACK buffer = (byte*)XMALLOC(MAX_DIGEST_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER); if (buffer == NULL) return MEMORY_E; #endif ret = wc_HmacInit(&hmac, NULL, INVALID_DEVID); if (ret == 0) { ret = wc_HmacSetKey(&hmac, hashType, passwd, pLen); while (ret == 0 && kLen) { int currentLen; ret = wc_HmacUpdate(&hmac, salt, sLen); if (ret != 0) break; /* encode i */ for (j = 0; j < 4; j++) { byte b = (byte)(i >> ((3-j) * 8)); ret = wc_HmacUpdate(&hmac, &b, 1); if (ret != 0) break; } /* check ret from inside for loop */ if (ret != 0) break; ret = wc_HmacFinal(&hmac, buffer); if (ret != 0) break; currentLen = min(kLen, hLen); XMEMCPY(output, buffer, currentLen); for (j = 1; j < iterations; j++) { ret = wc_HmacUpdate(&hmac, buffer, hLen); if (ret != 0) break; ret = wc_HmacFinal(&hmac, buffer); if (ret != 0) break; xorbuf(output, buffer, currentLen); } /* check ret from inside for loop */ if (ret != 0) break; output += currentLen; kLen -= currentLen; i++; } wc_HmacFree(&hmac); }