/**************************************************************************** * crypto/hmac.c * $OpenBSD: hmac.c,v 1.4 2016/09/19 18:09:40 tedu Exp $ * * Copyright (c) 2008 Damien Bergamini * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * ****************************************************************************/ /* This code implements the HMAC algorithm described in RFC 2104 using * the MD5, SHA1 and SHA-256 hash functions. */ /**************************************************************************** * Included Files ****************************************************************************/ #include #include #include #include #include #include #include /**************************************************************************** * Public Functions ****************************************************************************/ void hmca_md5_init(FAR HMAC_MD5_CTX *ctx, FAR const uint8_t *key, u_int key_len) { uint8_t k_ipad[MD5_BLOCK_LENGTH]; int i; if (key_len > MD5_BLOCK_LENGTH) { md5init(&ctx->ctx); md5update(&ctx->ctx, key, key_len); md5final(ctx->key, &ctx->ctx); ctx->key_len = MD5_DIGEST_LENGTH; } else { bcopy(key, ctx->key, key_len); ctx->key_len = key_len; } bzero(k_ipad, MD5_BLOCK_LENGTH); memcpy(k_ipad, ctx->key, ctx->key_len); for (i = 0; i < MD5_BLOCK_LENGTH; i++) { k_ipad[i] ^= 0x36; } md5init(&ctx->ctx); md5update(&ctx->ctx, k_ipad, MD5_BLOCK_LENGTH); explicit_bzero(k_ipad, sizeof k_ipad); } void hmac_md5_update(FAR HMAC_MD5_CTX *ctx, FAR const uint8_t *data, u_int len) { md5update(&ctx->ctx, data, len); } void hmac_md5_final(FAR uint8_t *digest, FAR HMAC_MD5_CTX *ctx) { uint8_t k_opad[MD5_BLOCK_LENGTH]; int i; md5final(digest, &ctx->ctx); bzero(k_opad, MD5_BLOCK_LENGTH); memcpy(k_opad, ctx->key, ctx->key_len); for (i = 0; i < MD5_BLOCK_LENGTH; i++) { k_opad[i] ^= 0x5c; } md5init(&ctx->ctx); md5update(&ctx->ctx, k_opad, MD5_BLOCK_LENGTH); md5update(&ctx->ctx, digest, MD5_DIGEST_LENGTH); md5final(digest, &ctx->ctx); explicit_bzero(k_opad, sizeof k_opad); } void hmac_sha1_init(FAR HMAC_SHA1_CTX *ctx, FAR const uint8_t *key, u_int key_len) { uint8_t k_ipad[SHA1_BLOCK_LENGTH]; int i; if (key_len > SHA1_BLOCK_LENGTH) { sha1init(&ctx->ctx); sha1update(&ctx->ctx, key, key_len); sha1final(ctx->key, &ctx->ctx); ctx->key_len = SHA1_DIGEST_LENGTH; } else { bcopy(key, ctx->key, key_len); ctx->key_len = key_len; } bzero(k_ipad, SHA1_BLOCK_LENGTH); memcpy(k_ipad, ctx->key, ctx->key_len); for (i = 0; i < SHA1_BLOCK_LENGTH; i++) { k_ipad[i] ^= 0x36; } sha1init(&ctx->ctx); sha1update(&ctx->ctx, k_ipad, SHA1_BLOCK_LENGTH); explicit_bzero(k_ipad, sizeof k_ipad); } void hmac_sha1_update(FAR HMAC_SHA1_CTX *ctx, FAR const uint8_t *data, u_int len) { sha1update(&ctx->ctx, data, len); } void hmca_sha1_final(FAR uint8_t *digest, FAR HMAC_SHA1_CTX *ctx) { uint8_t k_opad[SHA1_BLOCK_LENGTH]; int i; sha1final(digest, &ctx->ctx); bzero(k_opad, SHA1_BLOCK_LENGTH); memcpy(k_opad, ctx->key, ctx->key_len); for (i = 0; i < SHA1_BLOCK_LENGTH; i++) { k_opad[i] ^= 0x5c; } sha1init(&ctx->ctx); sha1update(&ctx->ctx, k_opad, SHA1_BLOCK_LENGTH); sha1update(&ctx->ctx, digest, SHA1_DIGEST_LENGTH); sha1final(digest, &ctx->ctx); explicit_bzero(k_opad, sizeof k_opad); } void hmac_sha256_init(FAR HMAC_SHA256_CTX *ctx, FAR const uint8_t *key, u_int key_len) { uint8_t k_ipad[SHA256_BLOCK_LENGTH]; int i; if (key_len > SHA256_BLOCK_LENGTH) { sha256init(&ctx->ctx); sha256update(&ctx->ctx, key, key_len); sha256final(ctx->key, &ctx->ctx); ctx->key_len = SHA256_DIGEST_LENGTH; } else { bcopy(key, ctx->key, key_len); ctx->key_len = key_len; } bzero(k_ipad, SHA256_BLOCK_LENGTH); memcpy(k_ipad, ctx->key, ctx->key_len); for (i = 0; i < SHA256_BLOCK_LENGTH; i++) { k_ipad[i] ^= 0x36; } sha256init(&ctx->ctx); sha256update(&ctx->ctx, k_ipad, SHA256_BLOCK_LENGTH); explicit_bzero(k_ipad, sizeof k_ipad); } void hmac_sha256_update(FAR HMAC_SHA256_CTX *ctx, FAR const uint8_t *data, u_int len) { sha256update(&ctx->ctx, data, len); } void hmac_sha256_final(FAR uint8_t *digest, FAR HMAC_SHA256_CTX *ctx) { uint8_t k_opad[SHA256_BLOCK_LENGTH]; int i; sha256final(digest, &ctx->ctx); bzero(k_opad, SHA256_BLOCK_LENGTH); memcpy(k_opad, ctx->key, ctx->key_len); for (i = 0; i < SHA256_BLOCK_LENGTH; i++) { k_opad[i] ^= 0x5c; } sha256init(&ctx->ctx); sha256update(&ctx->ctx, k_opad, SHA256_BLOCK_LENGTH); sha256update(&ctx->ctx, digest, SHA256_DIGEST_LENGTH); sha256final(digest, &ctx->ctx); explicit_bzero(k_opad, sizeof k_opad); }