blob: ef6ad824ba153a5df5e8100d83cc9bdeaf5c1006 [file] [log] [blame]
// 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);
}