1 /*
2 * Copyright 2014-2022 The GmSSL Project. All Rights Reserved.
3 *
4 * Licensed under the Apache License, Version 2.0 (the License); you may
5 * not use this file except in compliance with the License.
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 */
9
10
11
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #include <gmssl/sm3.h>
16 #include <gmssl/hmac.h>
17 #include <gmssl/error.h>
18
19 /*
20
21 HKDF-Extract(salt, IKM) -> PRK
22
23 salt optional, len(salt) == hash_len is recommended
24 IKM input key material
25 PRK output pseudorandom key, len(PRK) = hashLen
26
27 PRK = HMAC_hash(salt, IKM)
28 salt as key?
29
30
31 HKDF-Expand(PRK, info, L) -> OKM
32 info optional
33 L output length, L <= 255 * hashLen
34 OKM output key
35
36
37 N = (L + hashLen - 1)//hashLen
38 T = T(1) || T(2) || ... | T(N)
39 OKM = T[0..L-1]
40
41 T(0) = empty string (len = 0)
42 T(1) = HMAC_hash(PRK, T(0) | info | 0x01)
43 T(2) = HMAC_hash(PRK, T(1) | info | 0x02)
44 T(3) = HMAC_hash(PRK, T(2) | info | 0x03)
45 ...
46
47
48 */
49
hkdf_extract(const DIGEST * digest,const uint8_t * salt,size_t saltlen,const uint8_t * ikm,size_t ikmlen,uint8_t * prk,size_t * prklen)50 int hkdf_extract(const DIGEST *digest, const uint8_t *salt, size_t saltlen,
51 const uint8_t *ikm, size_t ikmlen,
52 uint8_t *prk, size_t *prklen)
53 {
54 HMAC_CTX hmac_ctx;
55
56 if (!salt || saltlen == 0) {
57 uint8_t zeros[DIGEST_MAX_SIZE] = {0};
58 if (hmac_init(&hmac_ctx, digest, zeros, digest->digest_size) != 1) {
59 error_print();
60 return -1;
61 }
62 } else {
63 if (hmac_init(&hmac_ctx, digest, salt, saltlen) != 1) {
64 error_print();
65 return -1;
66 }
67 }
68
69 if (hmac_update(&hmac_ctx, ikm, ikmlen) != 1
70 || hmac_finish(&hmac_ctx, prk, prklen) != 1) {
71 error_print();
72 return -1;
73 }
74 return 1;
75 }
76
hkdf_expand(const DIGEST * digest,const uint8_t * prk,size_t prklen,const uint8_t * opt_info,size_t opt_infolen,size_t L,uint8_t * okm)77 int hkdf_expand(const DIGEST *digest, const uint8_t *prk, size_t prklen,
78 const uint8_t *opt_info, size_t opt_infolen,
79 size_t L, uint8_t *okm)
80 {
81 HMAC_CTX hmac_ctx;
82 uint8_t T[HMAC_MAX_SIZE];
83 uint8_t counter = 0x01;
84 size_t len;
85
86 if (L > 0) {
87 if (hmac_init(&hmac_ctx, digest, prk, prklen) != 1
88 || hmac_update(&hmac_ctx, opt_info, opt_infolen) < 0
89 || hmac_update(&hmac_ctx, &counter, 1) != 1
90 || hmac_finish(&hmac_ctx, T, &len) != 1) {
91 error_print();
92 return -1;
93 }
94 counter++;
95 if (len > L) {
96 len = L;
97 }
98 memcpy(okm, T, len);
99 okm += len;
100 L -= len;
101 }
102 while (L > 0) {
103 if (counter == 0) {
104 error_print();
105 return -1;
106 }
107 if (hmac_init(&hmac_ctx, digest, prk, prklen) != 1
108 || hmac_update(&hmac_ctx, T, len) != 1
109 || hmac_update(&hmac_ctx, opt_info, opt_infolen) < 0
110 || hmac_update(&hmac_ctx, &counter, 1) != 1
111 || hmac_finish(&hmac_ctx, T, &len) != 1) {
112 error_print();
113 return -1;
114 }
115 counter++;
116 if (len > L) {
117 len = L;
118 }
119 memcpy(okm, T, len);
120 okm += len;
121 L -= len;
122 }
123 return 1;
124 }
125
126 /*
127 int sm3_hkdf_extract(const uint8_t *salt, size_t saltlen,
128 const uint8_t *ikm, size_t ikmlen,
129 uint8_t *prk, size_t *prklen)
130 {
131 SM3_HMAC_CTX hmac_ctx;
132
133 if (!salt || saltlen == 0) {
134 uint8_t zeros[SM3_HMAC_SIZE] = {0};
135 if (sm3_hmac_init(&hmac_ctx, zeros, SM3_HMAC_SIZE) != 1) {
136 error_print();
137 return -1;
138 }
139 } else {
140 if (sm3_hmac_init(&hmac_ctx, salt, saltlen) != 1) {
141 error_print();
142 return -1;
143 }
144 }
145
146 if (sm3_hmac_update(&hmac_ctx, ikm, ikmlen) != 1
147 || sm3_hmac_finish(&hmac_ctx, prk) != 1) {
148 error_print();
149 return -1;
150 }
151 *prklen = SM3_HMAC_SIZE;
152 return 1;
153 }
154
155 int sm3_hkdf_expand(const uint8_t *prk, size_t prklen,
156 const uint8_t *opt_info, size_t opt_infolen,
157 size_t L, uint8_t *okm)
158 {
159 SM3_HMAC_CTX hmac_ctx;
160 uint8_t T[SM3_HMAC_SIZE];
161 uint8_t counter = 0x01;
162 size_t len;
163
164 if (L > 0) {
165 if (sm3_hmac_init(&hmac_ctx, prk, prklen) != 1
166 || sm3_hmac_update(&hmac_ctx, opt_info, opt_infolen) < 0
167 || sm3_hmac_update(&hmac_ctx, &counter, 1) != 1
168 || sm3_hmac_finish(&hmac_ctx, T) != 1) {
169 error_print();
170 return -1;
171 }
172 counter++;
173 len = SM3_HMAC_SIZE;
174 if (len > L) {
175 len = L;
176 }
177 memcpy(okm, T, len);
178 okm += len;
179 L -= len;
180 }
181 while (L > 0) {
182 if (counter == 0) {
183 error_print();
184 return -1;
185 }
186 if (sm3_hmac_init(&hmac_ctx, digest, prk, prklen) != 1
187 || sm3_hmac_update(&hmac_ctx, T, len) != 1
188 || sm3_hmac_update(&hmac_ctx, opt_info, opt_infolen) < 0
189 || sm3_hmac_update(&hmac_ctx, &counter, 1) != 1
190 || sm3_hmac_finish(&hmac_ctx, T) != 1) {
191 error_print();
192 return -1;
193 }
194 counter++;
195 len = SM3_HMAC_SIZE;
196 if (len > L) {
197 len = L;
198 }
199 memcpy(okm, T, len);
200 okm += len;
201 L -= len;
202 }
203 return 1;
204 }
205 */
206