| // Copyright 2016 Google Inc. |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| #include "cryptoc/hmac.h" |
| #include "cryptoc/util.h" |
| |
| #include <string.h> |
| #include "cryptoc/sha.h" |
| #include "cryptoc/md5.h" |
| #include "cryptoc/sha256.h" |
| |
| static void HMAC_init(LITE_HMAC_CTX* ctx, const void* key, unsigned int len) { |
| unsigned int i; |
| memset(&ctx->opad[0], 0, sizeof(ctx->opad)); |
| |
| if (len > sizeof(ctx->opad)) { |
| HASH_init(&ctx->hash); |
| HASH_update(&ctx->hash, key, len); |
| memcpy(&ctx->opad[0], HASH_final(&ctx->hash), HASH_size(&ctx->hash)); |
| } else { |
| memcpy(&ctx->opad[0], key, len); |
| } |
| |
| for (i = 0; i < sizeof(ctx->opad); ++i) { |
| ctx->opad[i] ^= 0x36; |
| } |
| |
| HASH_init(&ctx->hash); |
| HASH_update(&ctx->hash, ctx->opad, sizeof(ctx->opad)); // hash ipad |
| |
| for (i = 0; i < sizeof(ctx->opad); ++i) { |
| ctx->opad[i] ^= (0x36 ^ 0x5c); |
| } |
| } |
| |
| void HMAC_MD5_init(LITE_HMAC_CTX* ctx, const void* key, unsigned int len) { |
| MD5_init(&ctx->hash); |
| HMAC_init(ctx, key, len); |
| } |
| |
| void HMAC_SHA_init(LITE_HMAC_CTX* ctx, const void* key, unsigned int len) { |
| SHA_init(&ctx->hash); |
| HMAC_init(ctx, key, len); |
| } |
| |
| void HMAC_SHA256_init(LITE_HMAC_CTX* ctx, const void* key, unsigned int len) { |
| SHA256_init(&ctx->hash); |
| HMAC_init(ctx, key, len); |
| } |
| |
| const uint8_t* HMAC_final(LITE_HMAC_CTX* ctx) { |
| uint8_t digest[32]; // upto SHA2 |
| memcpy(digest, HASH_final(&ctx->hash), |
| (HASH_size(&ctx->hash) <= sizeof(digest) ? |
| HASH_size(&ctx->hash) : sizeof(digest))); |
| HASH_init(&ctx->hash); |
| HASH_update(&ctx->hash, ctx->opad, sizeof(ctx->opad)); |
| HASH_update(&ctx->hash, digest, HASH_size(&ctx->hash)); |
| always_memset(&ctx->opad[0], 0, sizeof(ctx->opad)); // wipe key |
| return HASH_final(&ctx->hash); |
| } |