hmac.c (7148B)
1 2 #include <string.h> 3 #include "hmac.h" 4 5 #define IPAD 0x3636363636363636ULL 6 #define OPAD 0x5C5C5C5C5C5C5C5CULL 7 8 #define BLOCK_256_U64S (HMAC_SHA256_BLOCKSIZE / sizeof(uint64_t)) 9 #define BLOCK_512_U64S (HMAC_SHA512_BLOCKSIZE / sizeof(uint64_t)) 10 11 static inline void xor_block_256(uint64_t block[BLOCK_256_U64S], uint64_t pad) 12 { 13 size_t i; 14 15 for (i = 0; i < BLOCK_256_U64S; i++) 16 block[i] ^= pad; 17 } 18 19 20 static inline void xor_block_512(uint64_t block[BLOCK_512_U64S], uint64_t pad) 21 { 22 size_t i; 23 24 for (i = 0; i < BLOCK_512_U64S; i++) 25 block[i] ^= pad; 26 } 27 28 void hmac_sha256_init(struct hmac_sha256_ctx *ctx, 29 const void *k, size_t ksize) 30 { 31 struct sha256 hashed_key; 32 /* We use k_opad as k_ipad temporarily. */ 33 uint64_t *k_ipad = ctx->k_opad; 34 35 /* (keys longer than B bytes are first hashed using H) */ 36 if (ksize > HMAC_SHA256_BLOCKSIZE) { 37 sha256(&hashed_key, k, ksize); 38 k = &hashed_key; 39 ksize = sizeof(hashed_key); 40 } 41 42 /* From RFC2104: 43 * 44 * (1) append zeros to the end of K to create a B byte string 45 * (e.g., if K is of length 20 bytes and B=64, then K will be 46 * appended with 44 zero bytes 0x00) 47 */ 48 memcpy(k_ipad, k, ksize); 49 memset((char *)k_ipad + ksize, 0, HMAC_SHA256_BLOCKSIZE - ksize); 50 51 /* 52 * (2) XOR (bitwise exclusive-OR) the B byte string computed 53 * in step (1) with ipad 54 */ 55 xor_block_256(k_ipad, IPAD); 56 57 /* 58 * We start (4) here, appending text later: 59 * 60 * (3) append the stream of data 'text' to the B byte string resulting 61 * from step (2) 62 * (4) apply H to the stream generated in step (3) 63 */ 64 sha256_init(&ctx->sha); 65 sha256_update(&ctx->sha, k_ipad, HMAC_SHA256_BLOCKSIZE); 66 67 /* 68 * (5) XOR (bitwise exclusive-OR) the B byte string computed in 69 * step (1) with opad 70 */ 71 xor_block_256(ctx->k_opad, IPAD^OPAD); 72 } 73 74 75 void hmac_sha512_init(struct hmac_sha512_ctx *ctx, 76 const void *k, size_t ksize) 77 { 78 struct sha512 hashed_key; 79 /* We use k_opad as k_ipad temporarily. */ 80 uint64_t *k_ipad = ctx->k_opad; 81 82 /* (keys longer than B bytes are first hashed using H) */ 83 if (ksize > HMAC_SHA512_BLOCKSIZE) { 84 sha512(&hashed_key, k, ksize); 85 k = &hashed_key; 86 ksize = sizeof(hashed_key); 87 } 88 89 /* From RFC2104: 90 * 91 * (1) append zeros to the end of K to create a B byte string 92 * (e.g., if K is of length 20 bytes and B=64, then K will be 93 * appended with 44 zero bytes 0x00) 94 */ 95 memcpy(k_ipad, k, ksize); 96 memset((char *)k_ipad + ksize, 0, HMAC_SHA512_BLOCKSIZE - ksize); 97 98 /* 99 * (2) XOR (bitwise exclusive-OR) the B byte string computed 100 * in step (1) with ipad 101 */ 102 xor_block_512(k_ipad, IPAD); 103 104 /* 105 * We start (4) here, appending text later: 106 * 107 * (3) append the stream of data 'text' to the B byte string resulting 108 * from step (2) 109 * (4) apply H to the stream generated in step (3) 110 */ 111 sha512_init(&ctx->sha); 112 sha512_update(&ctx->sha, k_ipad, HMAC_SHA512_BLOCKSIZE); 113 114 /* 115 * (5) XOR (bitwise exclusive-OR) the B byte string computed in 116 * step (1) with opad 117 */ 118 xor_block_512(ctx->k_opad, IPAD^OPAD); 119 } 120 121 122 void hmac_sha256_update(struct hmac_sha256_ctx *ctx, const void *p, size_t size) 123 { 124 /* This is the appending-text part of this: 125 * 126 * (3) append the stream of data 'text' to the B byte string resulting 127 * from step (2) 128 * (4) apply H to the stream generated in step (3) 129 */ 130 sha256_update(&ctx->sha, p, size); 131 } 132 133 134 void hmac_sha512_update(struct hmac_sha512_ctx *ctx, const void *p, size_t size) 135 { 136 sha512_update(&ctx->sha, p, size); 137 } 138 139 140 void hmac_sha256_done(struct hmac_sha256_ctx *ctx, 141 struct hmac_sha256 *hmac) 142 { 143 /* (4) apply H to the stream generated in step (3) */ 144 sha256_done(&ctx->sha, &hmac->sha); 145 146 /* 147 * (6) append the H result from step (4) to the B byte string 148 * resulting from step (5) 149 * (7) apply H to the stream generated in step (6) and output 150 * the result 151 */ 152 sha256_init(&ctx->sha); 153 sha256_update(&ctx->sha, ctx->k_opad, sizeof(ctx->k_opad)); 154 sha256_update(&ctx->sha, &hmac->sha, sizeof(hmac->sha)); 155 sha256_done(&ctx->sha, &hmac->sha); 156 } 157 158 159 void hmac_sha512_done(struct hmac_sha512_ctx *ctx, 160 struct hmac_sha512 *hmac) 161 { 162 /* (4) apply H to the stream generated in step (3) */ 163 sha512_done(&ctx->sha, &hmac->sha); 164 165 /* 166 * (6) append the H result from step (4) to the B byte string 167 * resulting from step (5) 168 * (7) apply H to the stream generated in step (6) and output 169 * the result 170 */ 171 sha512_init(&ctx->sha); 172 sha512_update(&ctx->sha, ctx->k_opad, sizeof(ctx->k_opad)); 173 sha512_update(&ctx->sha, &hmac->sha, sizeof(hmac->sha)); 174 sha512_done(&ctx->sha, &hmac->sha); 175 } 176 177 #if 1 178 void hmac_sha256(struct hmac_sha256 *hmac, 179 const void *k, size_t ksize, 180 const void *d, size_t dsize) 181 { 182 struct hmac_sha256_ctx ctx; 183 184 hmac_sha256_init(&ctx, k, ksize); 185 hmac_sha256_update(&ctx, d, dsize); 186 hmac_sha256_done(&ctx, hmac); 187 } 188 189 190 void hmac_sha512(struct hmac_sha512 *hmac, 191 const void *k, size_t ksize, 192 const void *d, size_t dsize) 193 { 194 struct hmac_sha512_ctx ctx; 195 196 hmac_sha512_init(&ctx, k, ksize); 197 hmac_sha512_update(&ctx, d, dsize); 198 hmac_sha512_done(&ctx, hmac); 199 } 200 201 202 #else 203 /* Direct mapping from MD5 example in RFC2104 */ 204 void hmac_sha256(struct hmac_sha256 *hmac, 205 const void *key, size_t key_len, 206 const void *text, size_t text_len) 207 { 208 struct sha256_ctx context; 209 unsigned char k_ipad[65]; /* inner padding - 210 * key XORd with ipad 211 */ 212 unsigned char k_opad[65]; /* outer padding - 213 * key XORd with opad 214 *//* start out by storing key in pads */ 215 unsigned char tk[32]; 216 int i; 217 218 /* if key is longer than 64 bytes reset it to key=MD5(key) */ 219 if (key_len > 64) { 220 221 struct sha256_ctx tctx; 222 223 sha256_init(&tctx); 224 sha256_update(&tctx, key, key_len); 225 sha256_done(&tctx, tk); 226 227 key = tk; 228 key_len = 32; 229 } 230 bzero( k_ipad, sizeof k_ipad); 231 bzero( k_opad, sizeof k_opad); 232 bcopy( key, k_ipad, key_len); 233 bcopy( key, k_opad, key_len); 234 235 /* XOR key with ipad and opad values */ 236 for (i=0; i<64; i++) { 237 k_ipad[i] ^= 0x36; 238 k_opad[i] ^= 0x5c; 239 } 240 /* 241 * perform inner MD5 242 */ 243 sha256_init(&context); /* init context for 1st 244 * pass */ 245 sha256_update(&context, k_ipad, 64); /* start with inner pad */ 246 sha256_update(&context, text, text_len); /* then text of datagram */ 247 sha256_done(&context, &hmac->sha); /* finish up 1st pass */ 248 /* 249 * perform outer MD5 250 */ 251 sha256_init(&context); /* init context for 2nd 252 * pass */ 253 sha256_update(&context, k_opad, 64); /* start with outer pad */ 254 sha256_update(&context, &hmac->sha, 32); /* then results of 1st 255 * hash */ 256 sha256_done(&context, &hmac->sha); /* finish up 2nd pass */ 257 } 258 #endif