1 /* $OpenBSD: hmac.c,v 1.4 2016/09/19 18:09:40 tedu Exp $ */ 2 3 /*- 4 * Copyright (c) 2008 Damien Bergamini <damien.bergamini@free.fr> 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 /* 20 * This code implements the HMAC algorithm described in RFC 2104 using 21 * the MD5, SHA1 and SHA-256 hash functions. 22 */ 23 24 #include <sys/param.h> 25 #include <sys/systm.h> 26 27 #include <crypto/md5.h> 28 #include <crypto/sha1.h> 29 #include <crypto/sha2.h> 30 #include <crypto/hmac.h> 31 32 void 33 HMAC_MD5_Init(HMAC_MD5_CTX *ctx, const u_int8_t *key, u_int key_len) 34 { 35 u_int8_t k_ipad[MD5_BLOCK_LENGTH]; 36 int i; 37 38 if (key_len > MD5_BLOCK_LENGTH) { 39 MD5Init(&ctx->ctx); 40 MD5Update(&ctx->ctx, key, key_len); 41 MD5Final(ctx->key, &ctx->ctx); 42 ctx->key_len = MD5_DIGEST_LENGTH; 43 } else { 44 bcopy(key, ctx->key, key_len); 45 ctx->key_len = key_len; 46 } 47 48 bzero(k_ipad, MD5_BLOCK_LENGTH); 49 memcpy(k_ipad, ctx->key, ctx->key_len); 50 for (i = 0; i < MD5_BLOCK_LENGTH; i++) 51 k_ipad[i] ^= 0x36; 52 53 MD5Init(&ctx->ctx); 54 MD5Update(&ctx->ctx, k_ipad, MD5_BLOCK_LENGTH); 55 56 explicit_bzero(k_ipad, sizeof k_ipad); 57 } 58 59 void 60 HMAC_MD5_Update(HMAC_MD5_CTX *ctx, const u_int8_t *data, u_int len) 61 { 62 MD5Update(&ctx->ctx, data, len); 63 } 64 65 void 66 HMAC_MD5_Final(u_int8_t digest[MD5_DIGEST_LENGTH], HMAC_MD5_CTX *ctx) 67 { 68 u_int8_t k_opad[MD5_BLOCK_LENGTH]; 69 int i; 70 71 MD5Final(digest, &ctx->ctx); 72 73 bzero(k_opad, MD5_BLOCK_LENGTH); 74 memcpy(k_opad, ctx->key, ctx->key_len); 75 for (i = 0; i < MD5_BLOCK_LENGTH; i++) 76 k_opad[i] ^= 0x5c; 77 78 MD5Init(&ctx->ctx); 79 MD5Update(&ctx->ctx, k_opad, MD5_BLOCK_LENGTH); 80 MD5Update(&ctx->ctx, digest, MD5_DIGEST_LENGTH); 81 MD5Final(digest, &ctx->ctx); 82 83 explicit_bzero(k_opad, sizeof k_opad); 84 } 85 86 void 87 HMAC_SHA1_Init(HMAC_SHA1_CTX *ctx, const u_int8_t *key, u_int key_len) 88 { 89 u_int8_t k_ipad[SHA1_BLOCK_LENGTH]; 90 int i; 91 92 if (key_len > SHA1_BLOCK_LENGTH) { 93 SHA1Init(&ctx->ctx); 94 SHA1Update(&ctx->ctx, key, key_len); 95 SHA1Final(ctx->key, &ctx->ctx); 96 ctx->key_len = SHA1_DIGEST_LENGTH; 97 } else { 98 bcopy(key, ctx->key, key_len); 99 ctx->key_len = key_len; 100 } 101 102 bzero(k_ipad, SHA1_BLOCK_LENGTH); 103 memcpy(k_ipad, ctx->key, ctx->key_len); 104 for (i = 0; i < SHA1_BLOCK_LENGTH; i++) 105 k_ipad[i] ^= 0x36; 106 107 SHA1Init(&ctx->ctx); 108 SHA1Update(&ctx->ctx, k_ipad, SHA1_BLOCK_LENGTH); 109 110 explicit_bzero(k_ipad, sizeof k_ipad); 111 } 112 113 void 114 HMAC_SHA1_Update(HMAC_SHA1_CTX *ctx, const u_int8_t *data, u_int len) 115 { 116 SHA1Update(&ctx->ctx, data, len); 117 } 118 119 void 120 HMAC_SHA1_Final(u_int8_t digest[SHA1_DIGEST_LENGTH], HMAC_SHA1_CTX *ctx) 121 { 122 u_int8_t k_opad[SHA1_BLOCK_LENGTH]; 123 int i; 124 125 SHA1Final(digest, &ctx->ctx); 126 127 bzero(k_opad, SHA1_BLOCK_LENGTH); 128 memcpy(k_opad, ctx->key, ctx->key_len); 129 for (i = 0; i < SHA1_BLOCK_LENGTH; i++) 130 k_opad[i] ^= 0x5c; 131 132 SHA1Init(&ctx->ctx); 133 SHA1Update(&ctx->ctx, k_opad, SHA1_BLOCK_LENGTH); 134 SHA1Update(&ctx->ctx, digest, SHA1_DIGEST_LENGTH); 135 SHA1Final(digest, &ctx->ctx); 136 137 explicit_bzero(k_opad, sizeof k_opad); 138 } 139 140 void 141 HMAC_SHA256_Init(HMAC_SHA256_CTX *ctx, const u_int8_t *key, u_int key_len) 142 { 143 u_int8_t k_ipad[SHA256_BLOCK_LENGTH]; 144 int i; 145 146 if (key_len > SHA256_BLOCK_LENGTH) { 147 SHA256Init(&ctx->ctx); 148 SHA256Update(&ctx->ctx, key, key_len); 149 SHA256Final(ctx->key, &ctx->ctx); 150 ctx->key_len = SHA256_DIGEST_LENGTH; 151 } else { 152 bcopy(key, ctx->key, key_len); 153 ctx->key_len = key_len; 154 } 155 156 bzero(k_ipad, SHA256_BLOCK_LENGTH); 157 memcpy(k_ipad, ctx->key, ctx->key_len); 158 for (i = 0; i < SHA256_BLOCK_LENGTH; i++) 159 k_ipad[i] ^= 0x36; 160 161 SHA256Init(&ctx->ctx); 162 SHA256Update(&ctx->ctx, k_ipad, SHA256_BLOCK_LENGTH); 163 164 explicit_bzero(k_ipad, sizeof k_ipad); 165 } 166 167 void 168 HMAC_SHA256_Update(HMAC_SHA256_CTX *ctx, const u_int8_t *data, u_int len) 169 { 170 SHA256Update(&ctx->ctx, data, len); 171 } 172 173 void 174 HMAC_SHA256_Final(u_int8_t digest[SHA256_DIGEST_LENGTH], HMAC_SHA256_CTX *ctx) 175 { 176 u_int8_t k_opad[SHA256_BLOCK_LENGTH]; 177 int i; 178 179 SHA256Final(digest, &ctx->ctx); 180 181 bzero(k_opad, SHA256_BLOCK_LENGTH); 182 memcpy(k_opad, ctx->key, ctx->key_len); 183 for (i = 0; i < SHA256_BLOCK_LENGTH; i++) 184 k_opad[i] ^= 0x5c; 185 186 SHA256Init(&ctx->ctx); 187 SHA256Update(&ctx->ctx, k_opad, SHA256_BLOCK_LENGTH); 188 SHA256Update(&ctx->ctx, digest, SHA256_DIGEST_LENGTH); 189 SHA256Final(digest, &ctx->ctx); 190 191 explicit_bzero(k_opad, sizeof k_opad); 192 } 193