comparison libtomcrypt/src/misc/hkdf/hkdf.c @ 1471:6dba84798cd5

Update to libtomcrypt 1.18.1, merged with Dropbear changes
author Matt Johnston <matt@ucc.asn.au>
date Fri, 09 Feb 2018 21:44:05 +0800
parents
children
comparison
equal deleted inserted replaced
1470:8bba51a55704 1471:6dba84798cd5
1 /* LibTomCrypt, modular cryptographic library -- Tom St Denis
2 *
3 * LibTomCrypt is a library that provides various cryptographic
4 * algorithms in a highly modular and flexible manner.
5 *
6 * The library is free for all purposes without any express
7 * guarantee it works.
8 */
9
10 #include <assert.h>
11 #include <stdio.h>
12 #include <stdlib.h>
13
14 #include "tomcrypt.h"
15
16 #ifdef LTC_HKDF
17
18 /* This is mostly just a wrapper around hmac_memory */
19 int hkdf_extract(int hash_idx, const unsigned char *salt, unsigned long saltlen,
20 const unsigned char *in, unsigned long inlen,
21 unsigned char *out, unsigned long *outlen)
22 {
23 /* libtomcrypt chokes on a zero length HMAC key, so we need to check for
24 that. HMAC specifies that keys shorter than the hash's blocksize are
25 0 padded to the block size. HKDF specifies that a NULL salt is to be
26 substituted with a salt comprised of hashLen 0 bytes. HMAC's padding
27 means that in either case the HMAC is actually using a blocksize long
28 zero filled key. Unless blocksize < hashLen (which wouldn't make any
29 sense), we can use a single 0 byte as the HMAC key and still generate
30 valid results for HKDF. */
31 if (salt == NULL || saltlen == 0) {
32 return hmac_memory(hash_idx, (const unsigned char *)"", 1, in, inlen, out, outlen);
33 } else {
34 return hmac_memory(hash_idx, salt, saltlen, in, inlen, out, outlen);
35 }
36 }
37
38 int hkdf_expand(int hash_idx, const unsigned char *info, unsigned long infolen,
39 const unsigned char *in, unsigned long inlen,
40 unsigned char *out, unsigned long outlen)
41 {
42 unsigned long hashsize;
43 int err;
44 unsigned char N;
45 unsigned long Noutlen, outoff;
46
47 unsigned char *T, *dat;
48 unsigned long Tlen, datlen;
49
50 /* make sure hash descriptor is valid */
51 if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) {
52 return err;
53 }
54
55 hashsize = hash_descriptor[hash_idx].hashsize;
56
57 /* RFC5869 parameter restrictions */
58 if (inlen < hashsize || outlen > hashsize * 255)
59 return CRYPT_INVALID_ARG;
60 if (info == NULL && infolen != 0)
61 return CRYPT_INVALID_ARG;
62 LTC_ARGCHK(out != NULL);
63
64 Tlen = hashsize + infolen + 1;
65 T = XMALLOC(Tlen); /* Replace with static buffer? */
66 if (T == NULL) {
67 return CRYPT_MEM;
68 }
69 if (info != NULL) {
70 XMEMCPY(T + hashsize, info, infolen);
71 }
72
73 /* HMAC data T(1) doesn't include a previous hash value */
74 dat = T + hashsize;
75 datlen = Tlen - hashsize;
76
77 N = 0;
78 outoff = 0; /* offset in out to write to */
79 while (1) { /* an exit condition breaks mid-loop */
80 Noutlen = MIN(hashsize, outlen - outoff);
81 T[Tlen - 1] = ++N;
82 if ((err = hmac_memory(hash_idx, in, inlen, dat, datlen,
83 out + outoff, &Noutlen)) != CRYPT_OK) {
84 zeromem(T, Tlen);
85 XFREE(T);
86 return err;
87 }
88 outoff += Noutlen;
89
90 if (outoff >= outlen) /* loop exit condition */
91 break;
92
93 /* All subsequent HMAC data T(N) DOES include the previous hash value */
94 XMEMCPY(T, out + hashsize * (N-1), hashsize);
95 if (N == 1) {
96 dat = T;
97 datlen = Tlen;
98 }
99 }
100 zeromem(T, Tlen);
101 XFREE(T);
102 return CRYPT_OK;
103 }
104
105 /* all in one step */
106 int hkdf(int hash_idx, const unsigned char *salt, unsigned long saltlen,
107 const unsigned char *info, unsigned long infolen,
108 const unsigned char *in, unsigned long inlen,
109 unsigned char *out, unsigned long outlen)
110 {
111 unsigned long hashsize;
112 int err;
113 unsigned char *extracted;
114
115 /* make sure hash descriptor is valid */
116 if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) {
117 return err;
118 }
119
120 hashsize = hash_descriptor[hash_idx].hashsize;
121
122 extracted = XMALLOC(hashsize); /* replace with static buffer? */
123 if (extracted == NULL) {
124 return CRYPT_MEM;
125 }
126 if ((err = hkdf_extract(hash_idx, salt, saltlen, in, inlen, extracted, &hashsize)) != 0) {
127 zeromem(extracted, hashsize);
128 XFREE(extracted);
129 return err;
130 }
131 err = hkdf_expand(hash_idx, info, infolen, extracted, hashsize, out, outlen);
132 zeromem(extracted, hashsize);
133 XFREE(extracted);
134 return err;
135 }
136 #endif /* LTC_HKDF */
137
138
139 /* vim: set ts=2 sw=2 et ai si: */
140
141 /* ref: $Format:%D$ */
142 /* git commit: $Format:%H$ */
143 /* commit time: $Format:%ai$ */