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)
38 memcpy(k_ipad, k, ksize);
39 memset((char *)k_ipad + ksize, 0, HMAC_SHA256_BLOCKSIZE - ksize);
42 * (2) XOR (bitwise exclusive-OR) the B byte string computed
43 * in step (1) with ipad
45 xor_block(k_ipad, IPAD);
48 * We start (4) here, appending text later:
50 * (3) append the stream of data 'text' to the B byte string resulting
52 * (4) apply H to the stream generated in step (3)
54 sha256_init(&ctx->sha);
55 sha256_update(&ctx->sha, k_ipad, HMAC_SHA256_BLOCKSIZE);
58 * (5) XOR (bitwise exclusive-OR) the B byte string computed in
61 xor_block(ctx->k_opad, IPAD^OPAD);
64 void hmac_sha256_update(struct hmac_sha256_ctx *ctx, const void *p, size_t size)
66 /* This is the appending-text part of this:
68 * (3) append the stream of data 'text' to the B byte string resulting
70 * (4) apply H to the stream generated in step (3)
72 sha256_update(&ctx->sha, p, size);
75 void hmac_sha256_done(struct hmac_sha256_ctx *ctx,
76 struct hmac_sha256 *hmac)
78 /* (4) apply H to the stream generated in step (3) */
79 sha256_done(&ctx->sha, &hmac->sha);
82 * (6) append the H result from step (4) to the B byte string
83 * resulting from step (5)
84 * (7) apply H to the stream generated in step (6) and output
87 sha256_init(&ctx->sha);
88 sha256_update(&ctx->sha, ctx->k_opad, sizeof(ctx->k_opad));
89 sha256_update(&ctx->sha, &hmac->sha, sizeof(hmac->sha));
90 sha256_done(&ctx->sha, &hmac->sha);
94 void hmac_sha256(struct hmac_sha256 *hmac,
95 const void *k, size_t ksize,
96 const void *d, size_t dsize)
98 struct hmac_sha256_ctx ctx;
100 hmac_sha256_init(&ctx, k, ksize);
101 hmac_sha256_update(&ctx, d, dsize);
102 hmac_sha256_done(&ctx, hmac);
105 /* Direct mapping from MD5 example in RFC2104 */
106 void hmac_sha256(struct hmac_sha256 *hmac,
107 const void *key, size_t key_len,
108 const void *text, size_t text_len)
110 struct sha256_ctx context;
111 unsigned char k_ipad[65]; /* inner padding -
114 unsigned char k_opad[65]; /* outer padding -
116 *//* start out by storing key in pads */
117 unsigned char tk[32];
120 /* if key is longer than 64 bytes reset it to key=MD5(key) */
123 struct sha256_ctx tctx;
126 sha256_update(&tctx, key, key_len);
127 sha256_done(&tctx, tk);
132 bzero( k_ipad, sizeof k_ipad);
133 bzero( k_opad, sizeof k_opad);
134 bcopy( key, k_ipad, key_len);
135 bcopy( key, k_opad, key_len);
137 /* XOR key with ipad and opad values */
138 for (i=0; i<64; i++) {
145 sha256_init(&context); /* init context for 1st
147 sha256_update(&context, k_ipad, 64); /* start with inner pad */
148 sha256_update(&context, text, text_len); /* then text of datagram */
149 sha256_done(&context, &hmac->sha); /* finish up 1st pass */
153 sha256_init(&context); /* init context for 2nd
155 sha256_update(&context, k_opad, 64); /* start with outer pad */
156 sha256_update(&context, &hmac->sha, 32); /* then results of 1st
158 sha256_done(&context, &hmac->sha); /* finish up 2nd pass */