-
Notifications
You must be signed in to change notification settings - Fork 22
/
hmac_sha256.c
104 lines (86 loc) · 2.63 KB
/
hmac_sha256.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
/*
hmac_sha256.c
Originally written by https://github.com/h5p9sl
*/
#include "hmac_sha256.h"
#include "sha256.h"
#include <stdlib.h>
#include <string.h>
#define SHA256_BLOCK_SIZE 64
/* LOCAL FUNCTIONS */
// Concatenate X & Y, return hash.
static void* H(const void* x,
const size_t xlen,
const void* y,
const size_t ylen,
void* out,
const size_t outlen);
// Wrapper for sha256
static void* sha256(const void* data,
const size_t datalen,
void* out,
const size_t outlen);
// Declared in hmac_sha256.h
size_t hmac_sha256(const void* key,
const size_t keylen,
const void* data,
const size_t datalen,
void* out,
const size_t outlen) {
uint8_t k[SHA256_BLOCK_SIZE];
uint8_t k_ipad[SHA256_BLOCK_SIZE];
uint8_t k_opad[SHA256_BLOCK_SIZE];
uint8_t ihash[SHA256_HASH_SIZE];
uint8_t ohash[SHA256_HASH_SIZE];
size_t sz;
int i;
memset(k, 0, sizeof(k));
memset(k_ipad, 0x36, SHA256_BLOCK_SIZE);
memset(k_opad, 0x5c, SHA256_BLOCK_SIZE);
if (keylen > SHA256_BLOCK_SIZE) {
// If the key is larger than the hash algorithm's
// block size, we must digest it first.
sha256(key, keylen, k, sizeof(k));
} else {
memcpy(k, key, keylen);
}
for (i = 0; i < SHA256_BLOCK_SIZE; i++) {
k_ipad[i] ^= k[i];
k_opad[i] ^= k[i];
}
// Perform HMAC algorithm: ( https://tools.ietf.org/html/rfc2104 )
// `H(K XOR opad, H(K XOR ipad, data))`
H(k_ipad, sizeof(k_ipad), data, datalen, ihash, sizeof(ihash));
H(k_opad, sizeof(k_opad), ihash, sizeof(ihash), ohash, sizeof(ohash));
sz = (outlen > SHA256_HASH_SIZE) ? SHA256_HASH_SIZE : outlen;
memcpy(out, ohash, sz);
return sz;
}
static void* H(const void* x,
const size_t xlen,
const void* y,
const size_t ylen,
void* out,
const size_t outlen) {
void* result;
size_t buflen = (xlen + ylen);
uint8_t* buf = (uint8_t*)malloc(buflen);
memcpy(buf, x, xlen);
memcpy(buf + xlen, y, ylen);
result = sha256(buf, buflen, out, outlen);
free(buf);
return result;
}
static void* sha256(const void* data,
const size_t datalen,
void* out,
const size_t outlen) {
size_t sz;
Sha256Context ctx;
SHA256_HASH hash;
Sha256Initialise(&ctx);
Sha256Update(&ctx, data, datalen);
Sha256Finalise(&ctx, &hash);
sz = (outlen > SHA256_HASH_SIZE) ? SHA256_HASH_SIZE : outlen;
return memcpy(out, hash.bytes, sz);
}