hkdf_sha256.c (2881B)
1 /* MIT (BSD) license - see LICENSE file for details */ 2 #include "hkdf_sha256.h" 3 #include "hmac_sha256.h" 4 #include <assert.h> 5 #include <string.h> 6 7 void hkdf_expand(void *okm, size_t okm_size, 8 const void *prk, size_t prksize, 9 const void *info, size_t isize) 10 { 11 struct hmac_sha256_ctx ctx; 12 struct hmac_sha256 t; 13 unsigned char c; 14 15 assert(okm_size < 255 * sizeof(t)); 16 /* 17 * 2.3. Step 2: Expand 18 * 19 * HKDF-Expand(PRK, info, L) -> OKM 20 * 21 * Options: 22 * Hash a hash function; HashLen denotes the length of the 23 * hash function output in octets 24 * 25 * Inputs: 26 * PRK a pseudorandom key of at least HashLen octets 27 * (usually, the output from the extract step) 28 * info optional context and application specific information 29 * (can be a zero-length string) 30 * L length of output keying material in octets 31 * (<= 255*HashLen) 32 * 33 * Output: 34 * OKM output keying material (of L octets) 35 * 36 * The output OKM is calculated as follows: 37 * 38 * N = ceil(L/HashLen) 39 * T = T(1) | T(2) | T(3) | ... | T(N) 40 * OKM = first L octets of T 41 * 42 * where: 43 * T(0) = empty string (zero length) 44 * T(1) = HMAC-Hash(PRK, T(0) | info | 0x01) 45 * T(2) = HMAC-Hash(PRK, T(1) | info | 0x02) 46 * T(3) = HMAC-Hash(PRK, T(2) | info | 0x03) 47 * ... 48 * 49 * (where the constant concatenated to the end of each T(n) is a 50 * single octet.) 51 */ 52 c = 1; 53 hmac_sha256_init(&ctx, prk, prksize); 54 hmac_sha256_update(&ctx, info, isize); 55 hmac_sha256_update(&ctx, &c, 1); 56 hmac_sha256_done(&ctx, &t); 57 58 while (okm_size > sizeof(t)) { 59 memcpy(okm, &t, sizeof(t)); 60 okm = (char *)okm + sizeof(t); 61 okm_size -= sizeof(t); 62 63 c++; 64 hmac_sha256_init(&ctx, prk, prksize); 65 hmac_sha256_update(&ctx, &t, sizeof(t)); 66 hmac_sha256_update(&ctx, info, isize); 67 hmac_sha256_update(&ctx, &c, 1); 68 hmac_sha256_done(&ctx, &t); 69 } 70 memcpy(okm, &t, okm_size); 71 } 72 73 void hkdf_sha256(void *okm, size_t okm_size, 74 const void *s, size_t ssize, 75 const void *k, size_t ksize, 76 const void *info, size_t isize) 77 { 78 struct hmac_sha256 prk; 79 80 /* RFC 5869: 81 * 82 * 2.2. Step 1: Extract 83 * 84 * HKDF-Extract(salt, IKM) -> PRK 85 * 86 * Options: 87 * Hash a hash function; HashLen denotes the length of the 88 * hash function output in octets 89 * 90 * Inputs: 91 * salt optional salt value (a non-secret random value); 92 * if not provided, it is set to a string of HashLen zeros. 93 * IKM input keying material 94 * 95 * Output: 96 * PRK a pseudorandom key (of HashLen octets) 97 * 98 * The output PRK is calculated as follows: 99 * 100 * PRK = HMAC-Hash(salt, IKM) 101 */ 102 hmac_sha256(&prk, s, ssize, k, ksize); 103 hkdf_expand(okm, okm_size, &prk, sizeof(prk), info, isize); 104 }