/* * hmac * * Description: * This function will compute an HMAC message digest. * * Parameters: * whichSha: [in] * One of SHA1, SHA224, SHA256, SHA384, SHA512 * key: [in] * The secret shared key. * key_len: [in] * The length of the secret shared key. * message_array: [in] * An array of characters representing the message. * length: [in] * The length of the message in message_array * digest: [out] * Where the digest is returned. * NOTE: The length of the digest is determined by * the value of whichSha. * * Returns: * sha Error Code. * */ int hmac(SHAversion whichSha, const unsigned char *text, int text_len, const unsigned char *key, int key_len, uint8_t digest[USHAMaxHashSize]) { HMACContext ctx; return hmacReset(&ctx, whichSha, key, key_len) || hmacInput(&ctx, text, text_len) || hmacResult(&ctx, digest); }
int hmac(SHAversion whichSha, const unsigned char *message_array, int length, const unsigned char *key, int key_len, uint8_t digest[USHAMaxHashSize]) { HMACContext context; return hmacReset(&context, whichSha, key, key_len) || hmacInput(&context, message_array, length) || hmacResult(&context, digest); }
/* * hkdfReset * * Description: * This function will initialize the hkdfContext in preparation * for key derivation using the modular HKDF interface for * arbitrary length inputs. * * Parameters: * context: [in/out] * The context to reset. * whichSha: [in] * One of SHA1, SHA224, SHA256, SHA384, SHA512 * salt[ ]: [in] * The optional salt value (a non-secret random value); * if not provided (salt == NULL), it is set internally * to a string of HashLen(whichSha) zeros. * salt_len: [in] * The length of the salt value. (Ignored if salt == NULL.) * * Returns: * sha Error Code. * */ int hkdfReset(HKDFContext *context, enum SHAversion whichSha, const unsigned char *salt, int salt_len) { unsigned char nullSalt[USHAMaxHashSize]; if (!context) return shaNull; context->whichSha = whichSha; context->hashSize = USHAHashSize(whichSha); if (salt == 0) { salt = nullSalt; salt_len = context->hashSize; memset(nullSalt, '\0', salt_len); } return hmacReset(&context->hmacContext, whichSha, salt, salt_len); }
static int rtmp_handshake_make_digest(const uint8_t* key, size_t len, const uint8_t* ptr, size_t ptrlen, const uint8_t* digest, uint8_t* dst) { HMACContext hmac; hmacReset(&hmac, SHA256, key, len); if (digest) { assert(digest + SHA256_DIGEST_LENGTH <= ptr + ptrlen); hmacInput(&hmac, ptr, digest - ptr); if (digest + SHA256_DIGEST_LENGTH < ptr + ptrlen) hmacInput(&hmac, digest + SHA256_DIGEST_LENGTH, ptrlen - (digest - ptr) - SHA256_DIGEST_LENGTH); } else { hmacInput(&hmac, ptr, ptrlen); } hmacResult(&hmac, dst); return 0; }
/* * hkdfExpand * * Description: * This function will perform HKDF expansion. * * Parameters: * whichSha: [in] * One of SHA1, SHA224, SHA256, SHA384, SHA512 * prk[ ]: [in] * The pseudo-random key to be expanded; either obtained * directly from a cryptographically strong, uniformly * distributed pseudo-random number generator, or as the * output from hkdfExtract(). * prk_len: [in] * The length of the pseudo-random key in prk; * should at least be equal to USHAHashSize(whichSHA). * info[ ]: [in] * The optional context and application specific information. * If info == NULL or a zero-length string, it is ignored. * info_len: [in] * The length of the optional context and application specific * information. (Ignored if info == NULL.) * okm[ ]: [out] * Where the HKDF is to be stored. * okm_len: [in] * The length of the buffer to hold okm. * okm_len must be <= 255 * USHABlockSize(whichSha) * * Returns: * sha Error Code. * */ int hkdfExpand(SHAversion whichSha, const uint8_t prk[ ], int prk_len, const unsigned char *info, int info_len, uint8_t okm[ ], int okm_len) { int hash_len, N; unsigned char T[USHAMaxHashSize]; int Tlen, where, i; if (info == 0) { info = (const unsigned char *)""; info_len = 0; } else if (info_len < 0) { return shaBadParam; } if (okm_len <= 0) return shaBadParam; if (!okm) return shaBadParam; hash_len = USHAHashSize(whichSha); if (prk_len < hash_len) return shaBadParam; N = okm_len / hash_len; if ((okm_len % hash_len) != 0) N++; if (N > 255) return shaBadParam; Tlen = 0; where = 0; for (i = 1; i <= N; i++) { HMACContext context; unsigned char c = i; int ret = hmacReset(&context, whichSha, prk, prk_len) || hmacInput(&context, T, Tlen) || hmacInput(&context, info, info_len) || hmacInput(&context, &c, 1) || hmacResult(&context, T); if (ret != shaSuccess) return ret; memcpy(okm + where, T, (i != N) ? hash_len : (okm_len - where)); where += hash_len; Tlen = hash_len; } return shaSuccess; }
int hmacsha512Reset (hmacsha512Param* sp) { return hmacReset(sp->kxi, &sha512, &sp->sparam); }
int hmacsha256Reset (hmacsha256Param* sp) { return hmacReset(sp->kxi, &sha256, &sp->sparam); }
int hmac_sha512_test(void) { uint8_t hash[SHA512HashSize]; HMACContext context; const unsigned char* keys[]= { "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b" "\x0b\x0b\x0b", "Jefe", "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" "\xAA\xAA\xAA" }; testVector a, b, c; testVector test_hmac[3]; int times = sizeof(test_hmac) / sizeof(testVector), i; a.input = "Hi There"; a.output = "\x87\xaa\x7c\xde\xa5\xef\x61\x9d\x4f\xf0\xb4\x24\x1a\x1d\x6c" "\xb0\x23\x79\xf4\xe2\xce\x4e\xc2\x78\x7a\xd0\xb3\x05\x45\xe1" "\x7c\xde\xda\xa8\x33\xb7\xd6\xb8\xa7\x02\x03\x8b\x27\x4e\xae" "\xa3\xf4\xe4\xbe\x9d\x91\x4e\xeb\x61\xf1\x70\x2e\x69\x6c\x20" "\x3a\x12\x68\x54"; a.inLen = strlen((char *)a.input); a.outLen = SHA512HashSize; b.input = "what do ya want for nothing?"; b.output = "\x16\x4b\x7a\x7b\xfc\xf8\x19\xe2\xe3\x95\xfb\xe7\x3b\x56\xe0" "\xa3\x87\xbd\x64\x22\x2e\x83\x1f\xd6\x10\x27\x0c\xd7\xea\x25" "\x05\x54\x97\x58\xbf\x75\xc0\x5a\x99\x4a\x6d\x03\x4f\x65\xf8" "\xf0\xe6\xfd\xca\xea\xb1\xa3\x4d\x4a\x6b\x4b\x63\x6e\x07\x0a" "\x38\xbc\xe7\x37"; b.inLen = strlen((char *)b.input); b.outLen = SHA512HashSize; c.input = "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" "\xDD\xDD\xDD\xDD\xDD\xDD"; c.output = "\xfa\x73\xb0\x08\x9d\x56\xa2\x84\xef\xb0\xf0\x75\x6c\x89\x0b" "\xe9\xb1\xb5\xdb\xdd\x8e\xe8\x1a\x36\x55\xf8\x3e\x33\xb2\x27" "\x9d\x39\xbf\x3e\x84\x82\x79\xa7\x22\xc8\x06\xb4\x85\xa4\x7e" "\x67\xc8\x07\xb9\x46\xa3\x37\xbe\xe8\x94\x26\x74\x27\x88\x59" "\xe1\x32\x92\xfb"; c.inLen = strlen((char *)c.input); c.outLen = SHA512HashSize; test_hmac[0] = a; test_hmac[1] = b; test_hmac[2] = c; for (i = 0; i < times; ++i) { hmacReset(&context, SHA512, keys[i], strlen((char *)keys[i])); hmacInput(&context, test_hmac[i].input, test_hmac[i].inLen); hmacResult(&context, hash); for (int j = 0; j < SHA512HashSize; j++) { printf("-0x%x",hash[j]); } printf("\r\n"); printf("\r\n"); if (memcmp(hash, test_hmac[i].output, SHA512HashSize) != 0) return i+1; } return 0; }