Line data Source code
1 : /* Defines a family of functions implementing HMAC over a single hash
2 : function. See fd_hmac.c for example usage.
3 :
4 : #define HASH_ALG sha256
5 : #define HASH_SZ 32UL
6 : #define HASH_BLOCK_SZ 64UL
7 :
8 : HASH_ALG is used to resolve names of the hash algorithm functions
9 : following fd_sha256 conventions (fd_{HASH_ALG}_{init,append,fini}).
10 : HASH_SZ is the byte count of the hash function's output value, and
11 : HASH_BLOCK_SZ is the hash function's internal block size (used by
12 : HMAC for key expansion). */
13 :
14 : #ifndef HASH_ALG
15 : #error "Define HASH_ALG"
16 : #endif
17 :
18 : #ifndef HASH_SZ
19 : #error "Define HASH_SZ"
20 : #endif
21 :
22 : #ifndef HASH_BLOCK_SZ
23 : #error "Define HASH_BLOCK_SZ"
24 : #endif
25 :
26 : #define HMAC_FN FD_EXPAND_THEN_CONCAT2(fd_hmac_,HASH_ALG)
27 0 : #define HASH_(x) FD_EXPAND_THEN_CONCAT4(fd_,HASH_ALG,_,x)
28 :
29 : void *
30 : HMAC_FN( void const * data,
31 : ulong data_sz,
32 : void const * _key,
33 : ulong key_sz,
34 0 : void * hash ) {
35 :
36 : /* https://tools.ietf.org/html/rfc2104 */
37 : /* https://en.wikipedia.org/wiki/HMAC */
38 :
39 : /* Compress key */
40 :
41 0 : HASH_(t) _sha[ 1 ];
42 0 : HASH_(t) * sha = HASH_(join)( HASH_(new)( _sha ) );
43 :
44 0 : uchar key[ HASH_BLOCK_SZ ] __attribute__((aligned(32))) = {0};
45 0 : if( key_sz>HASH_BLOCK_SZ ) {
46 0 : HASH_(init)( sha );
47 0 : HASH_(append)( sha, _key, key_sz );
48 0 : HASH_(fini)( sha, key );
49 0 : key_sz = HASH_SZ;
50 0 : } else {
51 0 : fd_memcpy( key, _key, key_sz );
52 0 : }
53 :
54 : /* Pad key */
55 :
56 0 : uchar key_ipad[ HASH_BLOCK_SZ ];
57 0 : uchar key_opad[ HASH_BLOCK_SZ ];
58 0 : memset( key_ipad, 0x36, HASH_BLOCK_SZ );
59 0 : memset( key_opad, 0x5c, HASH_BLOCK_SZ );
60 0 : for( ulong i=0; i<HASH_BLOCK_SZ; i++ ) {
61 0 : key_ipad[ i ] = (uchar)( key_ipad[ i ] ^ key[ i ] );
62 0 : key_opad[ i ] = (uchar)( key_opad[ i ] ^ key[ i ] );
63 0 : }
64 :
65 : /* Inner SHA calculation */
66 :
67 0 : HASH_(init)( sha );
68 0 : HASH_(append)( sha, key_ipad, HASH_BLOCK_SZ );
69 0 : HASH_(append)( sha, data, data_sz );
70 0 : HASH_(fini)( sha, hash );
71 :
72 : /* Outer SHA calculation */
73 :
74 0 : HASH_(init)( sha );
75 0 : HASH_(append)( sha, key_opad, HASH_BLOCK_SZ );
76 0 : HASH_(append)( sha, hash, HASH_SZ );
77 0 : HASH_(fini)( sha, hash );
78 :
79 0 : fd_memzero_explicit( key, sizeof(key) );
80 0 : fd_memzero_explicit( key_ipad, sizeof(key_ipad) );
81 0 : fd_memzero_explicit( key_opad, sizeof(key_opad) );
82 0 : fd_memzero_explicit( _sha, sizeof(_sha) );
83 :
84 0 : return hash;
85 0 : }
86 :
87 : #undef HMAC_FN
88 : #undef HASH_
89 :
90 : #undef HASH_ALG
91 : #undef HASH_SZ
92 : #undef HASH_BLOCK_SZ
|