• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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