/* SHA1 portion of the prf */ __inline static int32_t pSha1(const unsigned char *key, uint16_t keyLen, const unsigned char *text, uint16_t textLen, unsigned char *out, uint16_t outLen) { psHmacSha1_t ctx; unsigned char a[SHA1_HASH_SIZE]; unsigned char mac[SHA1_HASH_SIZE]; unsigned char hmacKey[SHA1_HASH_SIZE]; int32_t rc = PS_FAIL; uint16_t hmacKeyLen, i, keyIter; for (keyIter = 1; (uint16_t)(SHA1_HASH_SIZE * keyIter) < outLen;) { keyIter++; } if ((rc = psHmacSha1(key, keyLen, text, textLen, a, hmacKey, &hmacKeyLen)) < 0) { goto L_RETURN; } if (hmacKeyLen != keyLen) { /* Support for keys larger than 64 bytes. Must take the hash of the original key in these cases which is indicated by different outgoing values from the passed in key and keyLen values */ psAssert(keyLen > 64); /* Typecast is OK, we don't update key below */ key = (const unsigned char *)hmacKey; keyLen = hmacKeyLen; } for (i = 0; i < keyIter; i++) { if ((rc = psHmacSha1Init(&ctx, key, keyLen)) < 0) { goto L_RETURN; } psHmacSha1Update(&ctx, a, SHA1_HASH_SIZE); psHmacSha1Update(&ctx, text, textLen); psHmacSha1Final(&ctx, mac); if (i == keyIter - 1) { memcpy(out + (SHA1_HASH_SIZE * i), mac, outLen - (SHA1_HASH_SIZE * i)); } else { memcpy(out + (SHA1_HASH_SIZE * i), mac, SHA1_HASH_SIZE); if ((rc = psHmacSha1(key, keyLen, a, SHA1_HASH_SIZE, a, hmacKey, &hmacKeyLen)) < 0) { goto L_RETURN; } } } rc = PS_SUCCESS; L_RETURN: memzero_s(a, SHA1_HASH_SIZE); memzero_s(mac, SHA1_HASH_SIZE); memzero_s(hmacKey, SHA1_HASH_SIZE); if (rc < 0) { memzero_s(out, outLen); /* zero any partial result on error */ } return rc; }
int32 psHmacSha1(unsigned char *key, uint32 keyLen, const unsigned char *buf, uint32 len, unsigned char *hash, unsigned char *hmacKey, uint32 *hmacKeyLen) { psHmacContext_t ctx; psDigestContext_t sha; /* Support for keys larger than 64 bytes. In this case, we take the hash of the key itself and use that instead. Inform the caller by updating the hmacKey and hmacKeyLen outputs */ if (keyLen > 64) { psSha1Init(&sha); psSha1Update(&sha, key, keyLen); *hmacKeyLen = psSha1Final(&sha, hash); memcpy(hmacKey, hash, *hmacKeyLen); } else { hmacKey = key; *hmacKeyLen = keyLen; } psHmacSha1Init(&ctx, hmacKey, *hmacKeyLen); psHmacSha1Update(&ctx, buf, len); return psHmacSha1Final(&ctx, hash); }
void psHmacUpdate(psHmac_t *ctx, const unsigned char *buf, uint32_t len) { switch((psCipherType_e)ctx->type) { #ifdef USE_HMAC_MD5 case HMAC_MD5: psHmacMd5Update(&ctx->u.md5, buf, len); break; #endif #ifdef USE_HMAC_SHA1 case HMAC_SHA1: psHmacSha1Update(&ctx->u.sha1, buf, len); break; #endif #ifdef USE_HMAC_SHA256 case HMAC_SHA256: psHmacSha256Update(&ctx->u.sha256, buf, len); break; #endif #ifdef USE_HMAC_SHA384 case HMAC_SHA384: psHmacSha384Update(&ctx->u.sha384, buf, len); break; #endif default: break; } }
/* SHA1 portion of the prf */ static int32 pSha1(unsigned char *key, uint32 keyLen, unsigned char *text, uint32 textLen, unsigned char *out, uint32 outLen) { psHmacContext_t ctx; unsigned char a[SHA1_HASH_SIZE]; unsigned char mac[SHA1_HASH_SIZE]; unsigned char hmacKey[SHA1_HASH_SIZE]; int32 i, keyIter = 1; uint32 hmacKeyLen; while ((uint32)(SHA1_HASH_SIZE * keyIter) < outLen) { keyIter++; } psHmacSha1(key, keyLen, text, textLen, a, hmacKey, &hmacKeyLen); if (hmacKeyLen != keyLen) { /* Support for keys larger than 64 bytes. Must take the hash of the original key in these cases which is indicated by different outgoing values from the passed in key and keyLen values */ psAssert(keyLen > 64); key = hmacKey; keyLen = hmacKeyLen; } for (i = 0; i < keyIter; i++) { psHmacSha1Init(&ctx, key, keyLen); psHmacSha1Update(&ctx, a, SHA1_HASH_SIZE); psHmacSha1Update(&ctx, text, textLen); psHmacSha1Final(&ctx, mac); if (i == keyIter - 1) { memcpy(out + (SHA1_HASH_SIZE * i), mac, outLen - (SHA1_HASH_SIZE * i)); } else { memcpy(out + (SHA1_HASH_SIZE * i), mac, SHA1_HASH_SIZE); psHmacSha1(key, keyLen, a, SHA1_HASH_SIZE, a, hmacKey, &hmacKeyLen); } } return 0; }
/* TLS sha1 HMAC generate/verify */ int32 tlsHMACSha1(ssl_t *ssl, int32 mode, unsigned char type, unsigned char *data, uint32 len, unsigned char *mac) { psHmacContext_t ctx; unsigned char *key, *seq; unsigned char majVer, minVer, tmp[5]; int32 i; majVer = ssl->majVer; minVer = ssl->minVer; if (mode == HMAC_CREATE) { key = ssl->sec.writeMAC; seq = ssl->sec.seq; } else { /* HMAC_VERIFY */ key = ssl->sec.readMAC; seq = ssl->sec.remSeq; } psHmacSha1Init(&ctx, key, SHA1_HASH_SIZE); psHmacSha1Update(&ctx, seq, 8); for (i = 7; i >= 0; i--) { seq[i]++; if (seq[i] != 0) { break; } } tmp[0] = type; tmp[1] = majVer; tmp[2] = minVer; tmp[3] = (len & 0xFF00) >> 8; tmp[4] = len & 0xFF; psHmacSha1Update(&ctx, tmp, 5); psHmacSha1Update(&ctx, data, len); return psHmacSha1Final(&ctx, mac); }
int32_t psHmacSha1(const unsigned char *key, uint16_t keyLen, const unsigned char *buf, uint32_t len, unsigned char hash[SHA1_HASHLEN], unsigned char *hmacKey, uint16_t *hmacKeyLen) { int32_t rc; union { psHmacSha1_t mac; psSha1_t md; } u; psHmacSha1_t *mac = &u.mac; psSha1_t *md = &u.md; /* Support for keys larger than 64 bytes. In this case, we take the hash of the key itself and use that instead. Inform the caller by updating the hmacKey and hmacKeyLen outputs */ if (keyLen > 64) { if ((rc = psSha1Init(md)) < 0) { return rc; } psSha1Update(md, key, keyLen); psSha1Final(md, hash); *hmacKeyLen = SHA1_HASHLEN; memcpy(hmacKey, hash, *hmacKeyLen); } else { hmacKey = (unsigned char *)key; /* @note typecasting from const */ *hmacKeyLen = keyLen; } if ((rc = psHmacSha1Init(mac, hmacKey, *hmacKeyLen)) < 0) { return rc; } psHmacSha1Update(mac, buf, len); psHmacSha1Final(mac, hash); return PS_SUCCESS; }
static void runWithHmac(psCipherContext_t *ctx, psHmac_t *hmac, int32 hashSize, int32 chunk, int32 alg) { psTime_t start, end; unsigned char *dataChunk; int32 bytesSent, bytesToSend, round; unsigned char mac[MAX_HASH_SIZE]; #ifdef USE_HIGHRES_TIME int32 mod; int64 diffu; #else int32 diffm; #endif dataChunk = psMalloc(NULL, chunk); memset(dataChunk, 0x0, chunk); bytesToSend = (DATABYTES_AMOUNT / chunk) * chunk; bytesSent = 0; switch (alg) { #ifdef USE_AES #ifdef USE_HMAC_SHA1 case AES_HMAC_ALG: psGetTime(&start, NULL); while (bytesSent < bytesToSend) { #ifdef USE_HMAC_TLS static unsigned char hmacKey[64] = { 0, }; unsigned char mac[20]; psHmacSha1Tls(hmacKey, 20, dataChunk, chunk, NULL, 0, NULL, 0, 0, mac); #else psHmacSha1Update(&hmac->u.sha1, dataChunk, chunk); #endif psAesEncryptCBC(&ctx->aes, dataChunk, dataChunk, chunk); bytesSent += chunk; } psHmacSha1Final(&hmac->u.sha1, mac); psGetTime(&end, NULL); break; #endif #ifdef USE_HMAC_SHA256 case AES_HMAC256_ALG: psGetTime(&start, NULL); while (bytesSent < bytesToSend) { #ifdef USE_HMAC_TLS static unsigned char hmacKey[64] = { 0, }; unsigned char mac[32]; psHmacSha2Tls(hmacKey, 32, dataChunk, chunk, NULL, 0, NULL, 0, 0, mac, 32); #else psHmacSha256Update(&hmac->u.sha256, dataChunk, chunk); #endif psAesEncryptCBC(&ctx->aes, dataChunk, dataChunk, chunk); bytesSent += chunk; } psHmacSha256Final(&hmac->u.sha256, mac); psGetTime(&end, NULL); break; #endif #endif default: printf("Skipping HMAC Test\n"); return; } #ifdef USE_HIGHRES_TIME diffu = psDiffUsecs(start, end); round = (bytesToSend / diffu); mod = (bytesToSend % diffu); printf("%d byte chunks in %lld usecs total for rate of %d.%d MB/sec\n", chunk, (unsigned long long)diffu, round, mod); #else diffm = psDiffMsecs(start, end, NULL); round = (bytesToSend / diffm) / 1000; printf("%d byte chunks in %d msecs total for rate of %d MB/sec\n", chunk, diffm, round); #endif }
/* TLS sha1 HMAC generate/verify */ int32_t tlsHMACSha1(ssl_t *ssl, int32 mode, unsigned char type, unsigned char *data, uint32 len, unsigned char *mac) { #ifndef USE_HMAC_TLS psHmacSha1_t ctx; #endif unsigned char *key, *seq; unsigned char majVer, minVer, tmp[5]; int32 i; #ifdef USE_DTLS unsigned char dtls_seq[8]; #endif /* USE_DTLS */ #ifdef USE_HMAC_TLS uint32 alt_len; #endif /* USE_HMAC_TLS */ majVer = ssl->majVer; minVer = ssl->minVer; if (mode == HMAC_CREATE) { key = ssl->sec.writeMAC; seq = ssl->sec.seq; } else { /* HMAC_VERIFY */ key = ssl->sec.readMAC; seq = ssl->sec.remSeq; } /* Sanity */ if (key == NULL) { return PS_FAILURE; } #ifdef USE_DTLS if (ssl->flags & SSL_FLAGS_DTLS) { if (mode == HMAC_CREATE) { seq = dtls_seq; memcpy(dtls_seq, ssl->epoch, 2); memcpy(dtls_seq + 2, ssl->rsn, 6); } else { /* HMAC_VERIFY */ seq = dtls_seq; memcpy(dtls_seq, ssl->rec.epoch, 2); memcpy(dtls_seq + 2, ssl->rec.rsn, 6); } } #endif /* USE_DTLS */ tmp[0] = type; tmp[1] = majVer; tmp[2] = minVer; tmp[3] = (len & 0xFF00) >> 8; tmp[4] = len & 0xFF; #ifdef USE_HMAC_TLS #ifdef USE_HMAC_TLS_LUCKY13_COUNTERMEASURE alt_len = mode == HMAC_CREATE ? len : ssl->rec.len; #else alt_len = len; #endif (void)psHmacSha1Tls(key, SHA1_HASH_SIZE, seq, 8, tmp, 5, data, len, alt_len, mac); #else if (psHmacSha1Init(&ctx, key, SHA1_HASH_SIZE) < 0) { return PS_FAIL; } psHmacSha1Update(&ctx, seq, 8); psHmacSha1Update(&ctx, tmp, 5); psHmacSha1Update(&ctx, data, len); psHmacSha1Final(&ctx, mac); #endif /* Update seq (only for normal TLS) */ for (i = 7; i >= 0; i--) { seq[i]++; if (seq[i] != 0) { break; } } return PS_SUCCESS; }