1*4e5722bbStedu /* $OpenBSD: hmac.c,v 1.4 2016/09/19 18:09:40 tedu Exp $ */
288d04b37Sdamien
388d04b37Sdamien /*-
488d04b37Sdamien * Copyright (c) 2008 Damien Bergamini <damien.bergamini@free.fr>
588d04b37Sdamien *
688d04b37Sdamien * Permission to use, copy, modify, and distribute this software for any
788d04b37Sdamien * purpose with or without fee is hereby granted, provided that the above
888d04b37Sdamien * copyright notice and this permission notice appear in all copies.
988d04b37Sdamien *
1088d04b37Sdamien * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1188d04b37Sdamien * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1288d04b37Sdamien * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1388d04b37Sdamien * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1488d04b37Sdamien * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1588d04b37Sdamien * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1688d04b37Sdamien * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1788d04b37Sdamien */
1888d04b37Sdamien
1988d04b37Sdamien /*
2088d04b37Sdamien * This code implements the HMAC algorithm described in RFC 2104 using
2188d04b37Sdamien * the MD5, SHA1 and SHA-256 hash functions.
2288d04b37Sdamien */
2388d04b37Sdamien
2488d04b37Sdamien #include <sys/param.h>
2588d04b37Sdamien #include <sys/systm.h>
2688d04b37Sdamien
2788d04b37Sdamien #include <crypto/md5.h>
2888d04b37Sdamien #include <crypto/sha1.h>
2988d04b37Sdamien #include <crypto/sha2.h>
3088d04b37Sdamien #include <crypto/hmac.h>
3188d04b37Sdamien
3288d04b37Sdamien void
HMAC_MD5_Init(HMAC_MD5_CTX * ctx,const u_int8_t * key,u_int key_len)3388d04b37Sdamien HMAC_MD5_Init(HMAC_MD5_CTX *ctx, const u_int8_t *key, u_int key_len)
3488d04b37Sdamien {
3588d04b37Sdamien u_int8_t k_ipad[MD5_BLOCK_LENGTH];
3688d04b37Sdamien int i;
3788d04b37Sdamien
3888d04b37Sdamien if (key_len > MD5_BLOCK_LENGTH) {
3988d04b37Sdamien MD5Init(&ctx->ctx);
4088d04b37Sdamien MD5Update(&ctx->ctx, key, key_len);
4188d04b37Sdamien MD5Final(ctx->key, &ctx->ctx);
4288d04b37Sdamien ctx->key_len = MD5_DIGEST_LENGTH;
4388d04b37Sdamien } else {
4488d04b37Sdamien bcopy(key, ctx->key, key_len);
4588d04b37Sdamien ctx->key_len = key_len;
4688d04b37Sdamien }
4788d04b37Sdamien
4888d04b37Sdamien bzero(k_ipad, MD5_BLOCK_LENGTH);
49*4e5722bbStedu memcpy(k_ipad, ctx->key, ctx->key_len);
5088d04b37Sdamien for (i = 0; i < MD5_BLOCK_LENGTH; i++)
5188d04b37Sdamien k_ipad[i] ^= 0x36;
5288d04b37Sdamien
5388d04b37Sdamien MD5Init(&ctx->ctx);
5488d04b37Sdamien MD5Update(&ctx->ctx, k_ipad, MD5_BLOCK_LENGTH);
5588d04b37Sdamien
56fa2d22afSderaadt explicit_bzero(k_ipad, sizeof k_ipad);
5788d04b37Sdamien }
5888d04b37Sdamien
5988d04b37Sdamien void
HMAC_MD5_Update(HMAC_MD5_CTX * ctx,const u_int8_t * data,u_int len)6088d04b37Sdamien HMAC_MD5_Update(HMAC_MD5_CTX *ctx, const u_int8_t *data, u_int len)
6188d04b37Sdamien {
6288d04b37Sdamien MD5Update(&ctx->ctx, data, len);
6388d04b37Sdamien }
6488d04b37Sdamien
6588d04b37Sdamien void
HMAC_MD5_Final(u_int8_t digest[MD5_DIGEST_LENGTH],HMAC_MD5_CTX * ctx)6688d04b37Sdamien HMAC_MD5_Final(u_int8_t digest[MD5_DIGEST_LENGTH], HMAC_MD5_CTX *ctx)
6788d04b37Sdamien {
6888d04b37Sdamien u_int8_t k_opad[MD5_BLOCK_LENGTH];
6988d04b37Sdamien int i;
7088d04b37Sdamien
7188d04b37Sdamien MD5Final(digest, &ctx->ctx);
7288d04b37Sdamien
7388d04b37Sdamien bzero(k_opad, MD5_BLOCK_LENGTH);
74*4e5722bbStedu memcpy(k_opad, ctx->key, ctx->key_len);
7588d04b37Sdamien for (i = 0; i < MD5_BLOCK_LENGTH; i++)
7688d04b37Sdamien k_opad[i] ^= 0x5c;
7788d04b37Sdamien
7888d04b37Sdamien MD5Init(&ctx->ctx);
7988d04b37Sdamien MD5Update(&ctx->ctx, k_opad, MD5_BLOCK_LENGTH);
8088d04b37Sdamien MD5Update(&ctx->ctx, digest, MD5_DIGEST_LENGTH);
8188d04b37Sdamien MD5Final(digest, &ctx->ctx);
8288d04b37Sdamien
83fa2d22afSderaadt explicit_bzero(k_opad, sizeof k_opad);
8488d04b37Sdamien }
8588d04b37Sdamien
8688d04b37Sdamien void
HMAC_SHA1_Init(HMAC_SHA1_CTX * ctx,const u_int8_t * key,u_int key_len)8788d04b37Sdamien HMAC_SHA1_Init(HMAC_SHA1_CTX *ctx, const u_int8_t *key, u_int key_len)
8888d04b37Sdamien {
8988d04b37Sdamien u_int8_t k_ipad[SHA1_BLOCK_LENGTH];
9088d04b37Sdamien int i;
9188d04b37Sdamien
9288d04b37Sdamien if (key_len > SHA1_BLOCK_LENGTH) {
9388d04b37Sdamien SHA1Init(&ctx->ctx);
9488d04b37Sdamien SHA1Update(&ctx->ctx, key, key_len);
9588d04b37Sdamien SHA1Final(ctx->key, &ctx->ctx);
9688d04b37Sdamien ctx->key_len = SHA1_DIGEST_LENGTH;
9788d04b37Sdamien } else {
9888d04b37Sdamien bcopy(key, ctx->key, key_len);
9988d04b37Sdamien ctx->key_len = key_len;
10088d04b37Sdamien }
10188d04b37Sdamien
10288d04b37Sdamien bzero(k_ipad, SHA1_BLOCK_LENGTH);
103*4e5722bbStedu memcpy(k_ipad, ctx->key, ctx->key_len);
10488d04b37Sdamien for (i = 0; i < SHA1_BLOCK_LENGTH; i++)
10588d04b37Sdamien k_ipad[i] ^= 0x36;
10688d04b37Sdamien
10788d04b37Sdamien SHA1Init(&ctx->ctx);
10888d04b37Sdamien SHA1Update(&ctx->ctx, k_ipad, SHA1_BLOCK_LENGTH);
10988d04b37Sdamien
110fa2d22afSderaadt explicit_bzero(k_ipad, sizeof k_ipad);
11188d04b37Sdamien }
11288d04b37Sdamien
11388d04b37Sdamien void
HMAC_SHA1_Update(HMAC_SHA1_CTX * ctx,const u_int8_t * data,u_int len)11488d04b37Sdamien HMAC_SHA1_Update(HMAC_SHA1_CTX *ctx, const u_int8_t *data, u_int len)
11588d04b37Sdamien {
11688d04b37Sdamien SHA1Update(&ctx->ctx, data, len);
11788d04b37Sdamien }
11888d04b37Sdamien
11988d04b37Sdamien void
HMAC_SHA1_Final(u_int8_t digest[SHA1_DIGEST_LENGTH],HMAC_SHA1_CTX * ctx)12088d04b37Sdamien HMAC_SHA1_Final(u_int8_t digest[SHA1_DIGEST_LENGTH], HMAC_SHA1_CTX *ctx)
12188d04b37Sdamien {
12288d04b37Sdamien u_int8_t k_opad[SHA1_BLOCK_LENGTH];
12388d04b37Sdamien int i;
12488d04b37Sdamien
12588d04b37Sdamien SHA1Final(digest, &ctx->ctx);
12688d04b37Sdamien
12788d04b37Sdamien bzero(k_opad, SHA1_BLOCK_LENGTH);
128*4e5722bbStedu memcpy(k_opad, ctx->key, ctx->key_len);
12988d04b37Sdamien for (i = 0; i < SHA1_BLOCK_LENGTH; i++)
13088d04b37Sdamien k_opad[i] ^= 0x5c;
13188d04b37Sdamien
13288d04b37Sdamien SHA1Init(&ctx->ctx);
13388d04b37Sdamien SHA1Update(&ctx->ctx, k_opad, SHA1_BLOCK_LENGTH);
13488d04b37Sdamien SHA1Update(&ctx->ctx, digest, SHA1_DIGEST_LENGTH);
13588d04b37Sdamien SHA1Final(digest, &ctx->ctx);
13688d04b37Sdamien
137fa2d22afSderaadt explicit_bzero(k_opad, sizeof k_opad);
13888d04b37Sdamien }
13988d04b37Sdamien
14088d04b37Sdamien void
HMAC_SHA256_Init(HMAC_SHA256_CTX * ctx,const u_int8_t * key,u_int key_len)14188d04b37Sdamien HMAC_SHA256_Init(HMAC_SHA256_CTX *ctx, const u_int8_t *key, u_int key_len)
14288d04b37Sdamien {
14388d04b37Sdamien u_int8_t k_ipad[SHA256_BLOCK_LENGTH];
14488d04b37Sdamien int i;
14588d04b37Sdamien
14688d04b37Sdamien if (key_len > SHA256_BLOCK_LENGTH) {
1479e65de06Sdjm SHA256Init(&ctx->ctx);
1489e65de06Sdjm SHA256Update(&ctx->ctx, key, key_len);
1499e65de06Sdjm SHA256Final(ctx->key, &ctx->ctx);
15088d04b37Sdamien ctx->key_len = SHA256_DIGEST_LENGTH;
15188d04b37Sdamien } else {
15288d04b37Sdamien bcopy(key, ctx->key, key_len);
15388d04b37Sdamien ctx->key_len = key_len;
15488d04b37Sdamien }
15588d04b37Sdamien
15688d04b37Sdamien bzero(k_ipad, SHA256_BLOCK_LENGTH);
157*4e5722bbStedu memcpy(k_ipad, ctx->key, ctx->key_len);
15888d04b37Sdamien for (i = 0; i < SHA256_BLOCK_LENGTH; i++)
15988d04b37Sdamien k_ipad[i] ^= 0x36;
16088d04b37Sdamien
1619e65de06Sdjm SHA256Init(&ctx->ctx);
1629e65de06Sdjm SHA256Update(&ctx->ctx, k_ipad, SHA256_BLOCK_LENGTH);
16388d04b37Sdamien
164fa2d22afSderaadt explicit_bzero(k_ipad, sizeof k_ipad);
16588d04b37Sdamien }
16688d04b37Sdamien
16788d04b37Sdamien void
HMAC_SHA256_Update(HMAC_SHA256_CTX * ctx,const u_int8_t * data,u_int len)16888d04b37Sdamien HMAC_SHA256_Update(HMAC_SHA256_CTX *ctx, const u_int8_t *data, u_int len)
16988d04b37Sdamien {
1709e65de06Sdjm SHA256Update(&ctx->ctx, data, len);
17188d04b37Sdamien }
17288d04b37Sdamien
17388d04b37Sdamien void
HMAC_SHA256_Final(u_int8_t digest[SHA256_DIGEST_LENGTH],HMAC_SHA256_CTX * ctx)17488d04b37Sdamien HMAC_SHA256_Final(u_int8_t digest[SHA256_DIGEST_LENGTH], HMAC_SHA256_CTX *ctx)
17588d04b37Sdamien {
17688d04b37Sdamien u_int8_t k_opad[SHA256_BLOCK_LENGTH];
17788d04b37Sdamien int i;
17888d04b37Sdamien
1799e65de06Sdjm SHA256Final(digest, &ctx->ctx);
18088d04b37Sdamien
18188d04b37Sdamien bzero(k_opad, SHA256_BLOCK_LENGTH);
182*4e5722bbStedu memcpy(k_opad, ctx->key, ctx->key_len);
18388d04b37Sdamien for (i = 0; i < SHA256_BLOCK_LENGTH; i++)
18488d04b37Sdamien k_opad[i] ^= 0x5c;
18588d04b37Sdamien
1869e65de06Sdjm SHA256Init(&ctx->ctx);
1879e65de06Sdjm SHA256Update(&ctx->ctx, k_opad, SHA256_BLOCK_LENGTH);
1889e65de06Sdjm SHA256Update(&ctx->ctx, digest, SHA256_DIGEST_LENGTH);
1899e65de06Sdjm SHA256Final(digest, &ctx->ctx);
19088d04b37Sdamien
191fa2d22afSderaadt explicit_bzero(k_opad, sizeof k_opad);
19288d04b37Sdamien }
193