lnsocket

A minimal C library for connecting to the lightning network
git clone git://jb55.com/lnsocket
Log | Files | Refs | Submodules | README | LICENSE

hmac.c (8222B)


      1 /* Copyright Rusty Russell (Blockstream) 2015.
      2 
      3 Permission is hereby granted, free of charge, to any person obtaining a copy
      4 of this software and associated documentation files (the "Software"), to deal
      5 in the Software without restriction, including without limitation the rights
      6 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
      7 copies of the Software, and to permit persons to whom the Software is
      8 furnished to do so, subject to the following conditions:
      9 
     10 The above copyright notice and this permission notice shall be included in
     11 all copies or substantial portions of the Software.
     12 
     13 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     14 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     15 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
     16 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     17 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     18 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
     19 THE SOFTWARE.
     20 */
     21 
     22 #include <string.h>
     23 #include "hmac.h"
     24 
     25 #define IPAD 0x3636363636363636ULL
     26 #define OPAD 0x5C5C5C5C5C5C5C5CULL
     27 
     28 #define BLOCK_256_U64S (HMAC_SHA256_BLOCKSIZE / sizeof(uint64_t))
     29 #define BLOCK_512_U64S (HMAC_SHA512_BLOCKSIZE / sizeof(uint64_t))
     30 
     31 static inline void xor_block_256(uint64_t block[BLOCK_256_U64S], uint64_t pad)
     32 {
     33 	size_t i;
     34 
     35 	for (i = 0; i < BLOCK_256_U64S; i++)
     36 		block[i] ^= pad;
     37 }
     38 
     39 
     40 static inline void xor_block_512(uint64_t block[BLOCK_512_U64S], uint64_t pad)
     41 {
     42 	size_t i;
     43 
     44 	for (i = 0; i < BLOCK_512_U64S; i++)
     45 		block[i] ^= pad;
     46 }
     47 
     48 void hmac_sha256_init(struct hmac_sha256_ctx *ctx,
     49 		      const void *k, size_t ksize)
     50 {
     51 	struct sha256 hashed_key;
     52 	/* We use k_opad as k_ipad temporarily. */
     53 	uint64_t *k_ipad = ctx->k_opad;
     54 
     55 	/* (keys longer than B bytes are first hashed using H) */
     56 	if (ksize > HMAC_SHA256_BLOCKSIZE) {
     57 		sha256(&hashed_key, k, ksize);
     58 		k = &hashed_key;
     59 		ksize = sizeof(hashed_key);
     60 	}
     61 
     62 	/* From RFC2104:
     63 	 *
     64 	 * (1) append zeros to the end of K to create a B byte string
     65 	 *  (e.g., if K is of length 20 bytes and B=64, then K will be
     66 	 *   appended with 44 zero bytes 0x00)
     67 	 */
     68 	memcpy(k_ipad, k, ksize);
     69 	memset((char *)k_ipad + ksize, 0, HMAC_SHA256_BLOCKSIZE - ksize);
     70 
     71 	/*
     72 	 * (2) XOR (bitwise exclusive-OR) the B byte string computed
     73 	 * in step (1) with ipad
     74 	 */
     75 	xor_block_256(k_ipad, IPAD);
     76 
     77 	/*
     78 	 * We start (4) here, appending text later:
     79 	 *
     80 	 * (3) append the stream of data 'text' to the B byte string resulting
     81 	 * from step (2)
     82 	 * (4) apply H to the stream generated in step (3)
     83 	 */
     84 	sha256_init(&ctx->sha);
     85 	sha256_update(&ctx->sha, k_ipad, HMAC_SHA256_BLOCKSIZE);
     86 
     87 	/*
     88 	 * (5) XOR (bitwise exclusive-OR) the B byte string computed in
     89 	 * step (1) with opad
     90 	 */
     91 	xor_block_256(ctx->k_opad, IPAD^OPAD);
     92 }
     93 
     94 
     95 void hmac_sha512_init(struct hmac_sha512_ctx *ctx,
     96 		      const void *k, size_t ksize)
     97 {
     98 	struct sha512 hashed_key;
     99 	/* We use k_opad as k_ipad temporarily. */
    100 	uint64_t *k_ipad = ctx->k_opad;
    101 
    102 	/* (keys longer than B bytes are first hashed using H) */
    103 	if (ksize > HMAC_SHA512_BLOCKSIZE) {
    104 		sha512(&hashed_key, k, ksize);
    105 		k = &hashed_key;
    106 		ksize = sizeof(hashed_key);
    107 	}
    108 
    109 	/* From RFC2104:
    110 	 *
    111 	 * (1) append zeros to the end of K to create a B byte string
    112 	 *  (e.g., if K is of length 20 bytes and B=64, then K will be
    113 	 *   appended with 44 zero bytes 0x00)
    114 	 */
    115 	memcpy(k_ipad, k, ksize);
    116 	memset((char *)k_ipad + ksize, 0, HMAC_SHA512_BLOCKSIZE - ksize);
    117 
    118 	/*
    119 	 * (2) XOR (bitwise exclusive-OR) the B byte string computed
    120 	 * in step (1) with ipad
    121 	 */
    122 	xor_block_512(k_ipad, IPAD);
    123 
    124 	/*
    125 	 * We start (4) here, appending text later:
    126 	 *
    127 	 * (3) append the stream of data 'text' to the B byte string resulting
    128 	 * from step (2)
    129 	 * (4) apply H to the stream generated in step (3)
    130 	 */
    131 	sha512_init(&ctx->sha);
    132 	sha512_update(&ctx->sha, k_ipad, HMAC_SHA512_BLOCKSIZE);
    133 
    134 	/*
    135 	 * (5) XOR (bitwise exclusive-OR) the B byte string computed in
    136 	 * step (1) with opad
    137 	 */
    138 	xor_block_512(ctx->k_opad, IPAD^OPAD);
    139 }
    140 
    141 
    142 void hmac_sha256_update(struct hmac_sha256_ctx *ctx, const void *p, size_t size)
    143 {
    144 	/* This is the appending-text part of this:
    145 	 *
    146 	 * (3) append the stream of data 'text' to the B byte string resulting
    147 	 * from step (2)
    148 	 * (4) apply H to the stream generated in step (3)
    149 	 */
    150 	sha256_update(&ctx->sha, p, size);
    151 }
    152 
    153 
    154 void hmac_sha512_update(struct hmac_sha512_ctx *ctx, const void *p, size_t size)
    155 {
    156 	sha512_update(&ctx->sha, p, size);
    157 }
    158 
    159 
    160 void hmac_sha256_done(struct hmac_sha256_ctx *ctx,
    161 		      struct hmac_sha256 *hmac)
    162 {
    163 	/* (4) apply H to the stream generated in step (3) */
    164 	sha256_done(&ctx->sha, &hmac->sha);
    165 
    166 	/*
    167 	 * (6) append the H result from step (4) to the B byte string
    168 	 * resulting from step (5)
    169 	 * (7) apply H to the stream generated in step (6) and output
    170 	 * the result
    171 	 */
    172 	sha256_init(&ctx->sha);
    173 	sha256_update(&ctx->sha, ctx->k_opad, sizeof(ctx->k_opad));
    174 	sha256_update(&ctx->sha, &hmac->sha, sizeof(hmac->sha));
    175 	sha256_done(&ctx->sha, &hmac->sha);
    176 }
    177 
    178 
    179 void hmac_sha512_done(struct hmac_sha512_ctx *ctx,
    180 		      struct hmac_sha512 *hmac)
    181 {
    182 	/* (4) apply H to the stream generated in step (3) */
    183 	sha512_done(&ctx->sha, &hmac->sha);
    184 
    185 	/*
    186 	 * (6) append the H result from step (4) to the B byte string
    187 	 * resulting from step (5)
    188 	 * (7) apply H to the stream generated in step (6) and output
    189 	 * the result
    190 	 */
    191 	sha512_init(&ctx->sha);
    192 	sha512_update(&ctx->sha, ctx->k_opad, sizeof(ctx->k_opad));
    193 	sha512_update(&ctx->sha, &hmac->sha, sizeof(hmac->sha));
    194 	sha512_done(&ctx->sha, &hmac->sha);
    195 }
    196 
    197 #if 1
    198 void hmac_sha256(struct hmac_sha256 *hmac,
    199 		 const void *k, size_t ksize,
    200 		 const void *d, size_t dsize)
    201 {
    202 	struct hmac_sha256_ctx ctx;
    203 
    204 	hmac_sha256_init(&ctx, k, ksize);
    205 	hmac_sha256_update(&ctx, d, dsize);
    206 	hmac_sha256_done(&ctx, hmac);
    207 }
    208 
    209 
    210 void hmac_sha512(struct hmac_sha512 *hmac,
    211 		 const void *k, size_t ksize,
    212 		 const void *d, size_t dsize)
    213 {
    214 	struct hmac_sha512_ctx ctx;
    215 
    216 	hmac_sha512_init(&ctx, k, ksize);
    217 	hmac_sha512_update(&ctx, d, dsize);
    218 	hmac_sha512_done(&ctx, hmac);
    219 }
    220 
    221 
    222 #else
    223 /* Direct mapping from MD5 example in RFC2104 */
    224 void hmac_sha256(struct hmac_sha256 *hmac,
    225 		 const void *key, size_t key_len,
    226 		 const void *text, size_t text_len)
    227 {
    228 	struct sha256_ctx context;
    229         unsigned char k_ipad[65];    /* inner padding -
    230                                       * key XORd with ipad
    231                                       */
    232         unsigned char k_opad[65];    /* outer padding -
    233                                       * key XORd with opad
    234                                       *//* start out by storing key in pads */
    235 	unsigned char tk[32];
    236         int i;
    237 
    238         /* if key is longer than 64 bytes reset it to key=MD5(key) */
    239         if (key_len > 64) {
    240 
    241                 struct sha256_ctx      tctx;
    242 
    243                 sha256_init(&tctx);
    244                 sha256_update(&tctx, key, key_len);
    245                 sha256_done(&tctx, tk);
    246 
    247                 key = tk;
    248                 key_len = 32;
    249         }
    250         bzero( k_ipad, sizeof k_ipad);
    251         bzero( k_opad, sizeof k_opad);
    252         bcopy( key, k_ipad, key_len);
    253         bcopy( key, k_opad, key_len);
    254 
    255         /* XOR key with ipad and opad values */
    256         for (i=0; i<64; i++) {
    257                 k_ipad[i] ^= 0x36;
    258                 k_opad[i] ^= 0x5c;
    259         }
    260         /*
    261          * perform inner MD5
    262          */
    263         sha256_init(&context);                   /* init context for 1st
    264                                               * pass */
    265         sha256_update(&context, k_ipad, 64);      /* start with inner pad */
    266         sha256_update(&context, text, text_len); /* then text of datagram */
    267         sha256_done(&context, &hmac->sha);          /* finish up 1st pass */
    268         /*
    269          * perform outer MD5
    270          */
    271         sha256_init(&context);                   /* init context for 2nd
    272                                               * pass */
    273         sha256_update(&context, k_opad, 64);     /* start with outer pad */
    274         sha256_update(&context, &hmac->sha, 32);     /* then results of 1st
    275                                               * hash */
    276         sha256_done(&context, &hmac->sha);          /* finish up 2nd pass */
    277 }
    278 #endif