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); }
int32_t psHmacInit(psHmac_t *ctx, psCipherType_e type, const unsigned char *key, uint16_t keyLen) { ctx->type = (uint8_t)type; switch(type) { #ifdef USE_HMAC_MD5 case HMAC_MD5: return psHmacMd5Init(&ctx->u.md5, key, keyLen); #endif #ifdef USE_HMAC_SHA1 case HMAC_SHA1: return psHmacSha1Init(&ctx->u.sha1, key, keyLen); #endif #ifdef USE_HMAC_SHA256 case HMAC_SHA256: return psHmacSha256Init(&ctx->u.sha256, key, keyLen); #endif #ifdef USE_HMAC_SHA384 case HMAC_SHA384: return psHmacSha384Init(&ctx->u.sha384, key, keyLen); #endif default: return PS_ARG_FAIL; } /* Redundant return */ return PS_ARG_FAIL; }
/* 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; }
/* 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; }
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; }
/* 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); }
static int32 psAesTestCBCHmac(void) { int32 err; psCipherContext_t eCtx; psHmac_t hCtx; #if defined(USE_MATRIX_AES_CBC) && !defined(PS_AES_IMPROVE_PERF_INCREASE_CODESIZE) _psTrace("##########\n#\n# "); _psTrace("AES speeds can be improved by enabling\n# "); _psTrace("PS_AES_IMPROVE_PERF_INCREASE_CODESIZE in cryptoConfig.h\n"); _psTrace("#\n#\n#########\n"); #endif #ifdef USE_HMAC_SHA1 _psTrace("***** AES-128 CBC + SHA1-HMAC *****\n"); if ((err = psAesInitCBC(&eCtx.aes, iv, key, 16, PS_AES_ENCRYPT)) != PS_SUCCESS) { _psTraceInt("FAILED: returned %d\n", err); return err; } psHmacSha1Init(&hCtx.u.sha1, key, SHA1_HASH_SIZE); runWithHmac(&eCtx, &hCtx, 0, TINY_CHUNKS, AES_HMAC_ALG); psHmacSha1Init(&hCtx.u.sha1, key, SHA1_HASH_SIZE); runWithHmac(&eCtx, &hCtx, 0, SMALL_CHUNKS, AES_HMAC_ALG); psHmacSha1Init(&hCtx.u.sha1, key, SHA1_HASH_SIZE); runWithHmac(&eCtx, &hCtx, 0, MEDIUM_CHUNKS, AES_HMAC_ALG); psHmacSha1Init(&hCtx.u.sha1, key, SHA1_HASH_SIZE); runWithHmac(&eCtx, &hCtx, 0, LARGE_CHUNKS, AES_HMAC_ALG); psHmacSha1Init(&hCtx.u.sha1, key, SHA1_HASH_SIZE); runWithHmac(&eCtx, &hCtx, 0, HUGE_CHUNKS, AES_HMAC_ALG); psAesClearCBC(&eCtx.aes); _psTrace("***** AES-256 CBC + SHA1-HMAC *****\n"); if ((err = psAesInitCBC(&eCtx.aes, iv, key, 32, PS_AES_ENCRYPT)) != PS_SUCCESS) { _psTraceInt("FAILED: returned %d\n", err); return err; } psHmacSha1Init(&hCtx.u.sha1, key, SHA1_HASH_SIZE); runWithHmac(&eCtx, &hCtx, 0, TINY_CHUNKS, AES_HMAC_ALG); psHmacSha1Init(&hCtx.u.sha1, key, SHA1_HASH_SIZE); runWithHmac(&eCtx, &hCtx, 0, SMALL_CHUNKS, AES_HMAC_ALG); psHmacSha1Init(&hCtx.u.sha1, key, SHA1_HASH_SIZE); runWithHmac(&eCtx, &hCtx, 0, MEDIUM_CHUNKS, AES_HMAC_ALG); psHmacSha1Init(&hCtx.u.sha1, key, SHA1_HASH_SIZE); runWithHmac(&eCtx, &hCtx, 0, LARGE_CHUNKS, AES_HMAC_ALG); psHmacSha1Init(&hCtx.u.sha1, key, SHA1_HASH_SIZE); runWithHmac(&eCtx, &hCtx, 0, HUGE_CHUNKS, AES_HMAC_ALG); psAesClearCBC(&eCtx.aes); #endif #ifdef USE_HMAC_SHA256 _psTrace("***** AES-128 CBC + SHA256-HMAC *****\n"); if ((err = psAesInitCBC(&eCtx.aes, iv, key, 16, PS_AES_ENCRYPT)) != PS_SUCCESS) { _psTraceInt("FAILED: returned %d\n", err); return err; } psHmacSha256Init(&hCtx.u.sha256, key, 32); runWithHmac(&eCtx, &hCtx, SHA256_HASH_SIZE, TINY_CHUNKS, AES_HMAC256_ALG); psHmacSha256Init(&hCtx.u.sha256, key, 32); runWithHmac(&eCtx, &hCtx, SHA256_HASH_SIZE, SMALL_CHUNKS, AES_HMAC256_ALG); psHmacSha256Init(&hCtx.u.sha256, key, 32); runWithHmac(&eCtx, &hCtx, SHA256_HASH_SIZE, MEDIUM_CHUNKS, AES_HMAC256_ALG); psHmacSha256Init(&hCtx.u.sha256, key, 32); runWithHmac(&eCtx, &hCtx, SHA256_HASH_SIZE, LARGE_CHUNKS, AES_HMAC256_ALG); psHmacSha256Init(&hCtx.u.sha256, key, 32); runWithHmac(&eCtx, &hCtx, SHA256_HASH_SIZE, HUGE_CHUNKS, AES_HMAC256_ALG); psAesClearCBC(&eCtx.aes); _psTrace("***** AES-256 CBC + SHA256-HMAC *****\n"); if ((err = psAesInitCBC(&eCtx.aes, iv, key, 32, PS_AES_ENCRYPT)) != PS_SUCCESS) { _psTraceInt("FAILED: returned %d\n", err); return err; } psHmacSha256Init(&hCtx.u.sha256, key, 32); runWithHmac(&eCtx, &hCtx, SHA256_HASH_SIZE, TINY_CHUNKS, AES_HMAC256_ALG); psHmacSha256Init(&hCtx.u.sha256, key, 32); runWithHmac(&eCtx, &hCtx, SHA256_HASH_SIZE, SMALL_CHUNKS, AES_HMAC256_ALG); psHmacSha256Init(&hCtx.u.sha256, key, 32); runWithHmac(&eCtx, &hCtx, SHA256_HASH_SIZE, MEDIUM_CHUNKS, AES_HMAC256_ALG); psHmacSha256Init(&hCtx.u.sha256, key, 32); runWithHmac(&eCtx, &hCtx, SHA256_HASH_SIZE, LARGE_CHUNKS, AES_HMAC256_ALG); psHmacSha256Init(&hCtx.u.sha256, key, 32); runWithHmac(&eCtx, &hCtx, SHA256_HASH_SIZE, HUGE_CHUNKS, AES_HMAC256_ALG); psHmacSha256Init(&hCtx.u.sha256, key, 32); psAesClearCBC(&eCtx.aes); #endif return 0; }
/* 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; }