1 /* MIT (BSD) license - see LICENSE file for details */
2 #include <ccan/crypto/hmac_sha256/hmac_sha256.h>
5 #define IPAD 0x3636363636363636ULL
6 #define OPAD 0x5C5C5C5C5C5C5C5CULL
8 #define BLOCK_U64S (HMAC_SHA256_BLOCKSIZE / sizeof(uint64_t))
10 static inline void xor_block(uint64_t block[BLOCK_U64S], uint64_t pad)
14 for (i = 0; i < BLOCK_U64S; i++)
18 void hmac_sha256_init(struct hmac_sha256_ctx *ctx,
19 const void *k, size_t ksize)
21 struct sha256 hashed_key;
22 /* We use k_opad as k_ipad temporarily. */
23 uint64_t *k_ipad = ctx->k_opad;
25 /* (keys longer than B bytes are first hashed using H) */
26 if (ksize > HMAC_SHA256_BLOCKSIZE) {
27 sha256(&hashed_key, k, ksize);
29 ksize = sizeof(hashed_key);
34 * (1) append zeros to the end of K to create a B byte string
35 * (e.g., if K is of length 20 bytes and B=64, then K will be
36 * appended with 44 zero bytes 0x00)
39 memcpy(k_ipad, k, ksize);
40 memset((char *)k_ipad + ksize, 0, HMAC_SHA256_BLOCKSIZE - ksize);
43 * (2) XOR (bitwise exclusive-OR) the B byte string computed
44 * in step (1) with ipad
46 xor_block(k_ipad, IPAD);
49 * We start (4) here, appending text later:
51 * (3) append the stream of data 'text' to the B byte string resulting
53 * (4) apply H to the stream generated in step (3)
55 sha256_init(&ctx->sha);
56 sha256_update(&ctx->sha, k_ipad, HMAC_SHA256_BLOCKSIZE);
59 * (5) XOR (bitwise exclusive-OR) the B byte string computed in
62 xor_block(ctx->k_opad, IPAD^OPAD);
65 void hmac_sha256_update(struct hmac_sha256_ctx *ctx, const void *p, size_t size)
67 /* This is the appending-text part of this:
69 * (3) append the stream of data 'text' to the B byte string resulting
71 * (4) apply H to the stream generated in step (3)
73 sha256_update(&ctx->sha, p, size);
76 void hmac_sha256_done(struct hmac_sha256_ctx *ctx,
77 struct hmac_sha256 *hmac)
79 /* (4) apply H to the stream generated in step (3) */
80 sha256_done(&ctx->sha, &hmac->sha);
83 * (6) append the H result from step (4) to the B byte string
84 * resulting from step (5)
85 * (7) apply H to the stream generated in step (6) and output
88 sha256_init(&ctx->sha);
89 sha256_update(&ctx->sha, ctx->k_opad, sizeof(ctx->k_opad));
90 sha256_update(&ctx->sha, &hmac->sha, sizeof(hmac->sha));
91 sha256_done(&ctx->sha, &hmac->sha);
95 void hmac_sha256(struct hmac_sha256 *hmac,
96 const void *k, size_t ksize,
97 const void *d, size_t dsize)
99 struct hmac_sha256_ctx ctx;
101 hmac_sha256_init(&ctx, k, ksize);
102 hmac_sha256_update(&ctx, d, dsize);
103 hmac_sha256_done(&ctx, hmac);
106 /* Direct mapping from MD5 example in RFC2104 */
107 void hmac_sha256(struct hmac_sha256 *hmac,
108 const void *key, size_t key_len,
109 const void *text, size_t text_len)
111 struct sha256_ctx context;
112 unsigned char k_ipad[65]; /* inner padding -
115 unsigned char k_opad[65]; /* outer padding -
117 *//* start out by storing key in pads */
118 unsigned char tk[32];
121 /* if key is longer than 64 bytes reset it to key=MD5(key) */
124 struct sha256_ctx tctx;
127 sha256_update(&tctx, key, key_len);
128 sha256_done(&tctx, tk);
133 bzero( k_ipad, sizeof k_ipad);
134 bzero( k_opad, sizeof k_opad);
135 bcopy( key, k_ipad, key_len);
136 bcopy( key, k_opad, key_len);
138 /* XOR key with ipad and opad values */
139 for (i=0; i<64; i++) {
146 sha256_init(&context); /* init context for 1st
148 sha256_update(&context, k_ipad, 64); /* start with inner pad */
149 sha256_update(&context, text, text_len); /* then text of datagram */
150 sha256_done(&context, &hmac->sha); /* finish up 1st pass */
154 sha256_init(&context); /* init context for 2nd
156 sha256_update(&context, k_opad, 64); /* start with outer pad */
157 sha256_update(&context, &hmac->sha, 32); /* then results of 1st
159 sha256_done(&context, &hmac->sha); /* finish up 2nd pass */