1 /*
2 * Copyright (c) 2020-2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #ifdef HKS_CONFIG_FILE
17 #include HKS_CONFIG_FILE
18 #else
19 #include "hks_config.h"
20 #endif
21
22 #ifdef _CUT_AUTHENTICATE_
23 #undef HKS_SUPPORT_X25519_C
24 #endif /* _CUT_AUTHENTICATE_ */
25
26 #ifdef HKS_SUPPORT_X25519_C
27
28 #include "hks_mbedtls_x25519.h"
29
30 #include <mbedtls/bignum.h>
31 #include <mbedtls/ctr_drbg.h>
32 #include <mbedtls/ecdh.h>
33 #include <mbedtls/ecp.h>
34 #include <mbedtls/entropy.h>
35
36 #ifdef HKS_SUPPORT_ED25519_TO_X25519
37 #include "hks_crypto_adapter.h"
38 #endif
39
40 #include "hks_log.h"
41 #include "hks_mbedtls_common.h"
42 #include "hks_mem.h"
43 #include "hks_template.h"
44
45 #define HKS_X25519_KEY_BITS 256
46 #define HKS_X25519_KEY_BYTES 32
47 #define HASH512_OUT_SIZE 64
48
49 struct HksCurveConstPara {
50 mbedtls_mpi mpiP;
51 mbedtls_mpi mpiOne;
52 mbedtls_mpi mpiD;
53 mbedtls_mpi mpiK;
54 mbedtls_mpi mpiCapitalA;
55 mbedtls_mpi mpiMinusA;
56 mbedtls_mpi mpiU;
57 mbedtls_mpi mpiQ;
58 };
59
60 #ifdef HKS_SUPPORT_ED25519_TO_X25519
61 #define CURVE25519_KEY_BYTE_SIZE HKS_KEY_BYTES(HKS_CURVE25519_KEY_SIZE_256)
62 static const uint8_t g_hksCurveParamP[CURVE25519_KEY_BYTE_SIZE] = {
63 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
64 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xed
65 };
66
67 /* RFC 8032, one = 1 */
68 static const uint8_t g_hksCurveParamOne[CURVE25519_KEY_BYTE_SIZE] = {
69 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
70 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01
71 };
72
73 /* RFC 8032, A non-zero element in the finite field GF(p), not equal to 1 */
74 static const uint8_t g_hksCurveParamD[CURVE25519_KEY_BYTE_SIZE] = {
75 0xa3, 0x78, 0x59, 0x13, 0xca, 0x4d, 0xeb, 0x75, 0xab, 0xd8, 0x41, 0x41, 0x4d, 0x0a, 0x70, 0x00,
76 0x98, 0xe8, 0x79, 0x77, 0x79, 0x40, 0xc7, 0x8c, 0x73, 0xfe, 0x6f, 0x2b, 0xee, 0x6c, 0x03, 0x52
77 };
78
79 /* RFC 8032, k = (p - 1) / 2 */
80 static const uint8_t g_hksCurveParamK[CURVE25519_KEY_BYTE_SIZE] = {
81 0xf6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
82 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f
83 };
84
85 /* RFC 8032, A = 486662 */
86 static const uint8_t g_hksCurveParamCapitalA[CURVE25519_KEY_BYTE_SIZE] = {
87 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
88 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x6d, 0x06
89 };
90
91 /* RFC 8032, -A = -486662 */
92 static const uint8_t g_hksCurveParamMinusA[CURVE25519_KEY_BYTE_SIZE] = {
93 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
94 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x92, 0xe7
95 };
96
97 /* RFC 8032, u = 2 */
98 static const uint8_t g_hksCurveParamU[CURVE25519_KEY_BYTE_SIZE] = {
99 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
100 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02
101 };
102
103 /* RFC 8032, q = endian_swap(k) */
104 static const uint8_t g_hksCurveParamQ[CURVE25519_KEY_BYTE_SIZE] = {
105 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
106 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf6
107 };
108 #endif
109
X25519CheckKeyMaterialPubPriSize(const struct KeyMaterial25519 * keyMaterial)110 static int32_t X25519CheckKeyMaterialPubPriSize(const struct KeyMaterial25519 *keyMaterial)
111 {
112 if ((keyMaterial->pubKeySize > HKS_X25519_KEY_BYTES) ||
113 (keyMaterial->priKeySize > HKS_X25519_KEY_BYTES)) {
114 HKS_LOG_E("Invalid x25519 keyMaterial! pubKeySize = 0x%" LOG_PUBLIC "X, priKeySize = 0x%" LOG_PUBLIC "X",
115 keyMaterial->pubKeySize, keyMaterial->priKeySize);
116 return HKS_ERROR_INVALID_ARGUMENT;
117 }
118
119 return HKS_SUCCESS;
120 }
121
EndianSwap(uint8_t * pData,const int32_t length)122 static int32_t EndianSwap(uint8_t *pData, const int32_t length)
123 {
124 if ((pData == NULL) || (length <= 0)) {
125 HKS_LOG_E("Endian swap invalid input!");
126 return HKS_ERROR_INVALID_ARGUMENT;
127 }
128
129 const int32_t end = length - 1;
130 const int32_t count = length / 2; /* 2: count is half of length */
131
132 for (int32_t i = 0; i < count; ++i) {
133 uint8_t tmp = pData[i];
134 pData[i] = pData[end - i];
135 pData[end - i] = tmp;
136 }
137
138 return HKS_SUCCESS;
139 }
140
X25519CheckKeySize(const struct HksBlob * key,const struct KeyMaterial25519 * keyMaterial,bool isPubKey)141 static int32_t X25519CheckKeySize(const struct HksBlob *key, const struct KeyMaterial25519 *keyMaterial, bool isPubKey)
142 {
143 if (key->size < (sizeof(struct KeyMaterial25519) + keyMaterial->pubKeySize +
144 (isPubKey ? 0 : keyMaterial->priKeySize))) {
145 HKS_LOG_E("X25519 key size too small! key size = 0x%" LOG_PUBLIC "X", key->size);
146 return HKS_ERROR_INVALID_KEY_INFO;
147 }
148
149 return HKS_SUCCESS;
150 }
151
X25519CheckKeyMaterialSize(const struct HksBlob * priKey,const struct HksBlob * pubKey)152 static int32_t X25519CheckKeyMaterialSize(const struct HksBlob *priKey, const struct HksBlob *pubKey)
153 {
154 const struct KeyMaterial25519 *priKm = (struct KeyMaterial25519 *)(priKey->data);
155 const struct KeyMaterial25519 *pubKm = (struct KeyMaterial25519 *)(pubKey->data);
156
157 /* x25519's keySize is fixed at 256, so don't need to check */
158 int32_t ret = X25519CheckKeyMaterialPubPriSize(priKm);
159 HKS_IF_NOT_SUCC_LOGE_RETURN(ret, ret, "invalid privateKey size")
160 ret = X25519CheckKeyMaterialPubPriSize(pubKm);
161 HKS_IF_NOT_SUCC_LOGE_RETURN(ret, ret, "invalid publicKey size")
162
163 ret = X25519CheckKeySize(priKey, priKm, false);
164 HKS_IF_NOT_SUCC_RETURN(ret, ret)
165
166 return X25519CheckKeySize(pubKey, pubKm, true);
167 }
168
169 #ifdef HKS_SUPPORT_X25519_GENERATE_KEY
X25519SaveKeyMaterial(const mbedtls_ecp_point * pub,const mbedtls_mpi * pri,struct HksBlob * key)170 static int32_t X25519SaveKeyMaterial(const mbedtls_ecp_point *pub,
171 const mbedtls_mpi *pri, struct HksBlob *key)
172 {
173 const uint32_t keyByteLen = HKS_X25519_KEY_BITS / HKS_BITS_PER_BYTE;
174 const uint32_t rawMaterialLen = sizeof(struct KeyMaterial25519) + keyByteLen + keyByteLen;
175 uint8_t *rawMaterial = (uint8_t *)HksMalloc(rawMaterialLen);
176 HKS_IF_NULL_RETURN(rawMaterial, HKS_ERROR_MALLOC_FAIL)
177 (void)memset_s(rawMaterial, rawMaterialLen, 0, rawMaterialLen);
178
179 struct KeyMaterial25519 *keyMaterial = (struct KeyMaterial25519 *)rawMaterial;
180 keyMaterial->keyAlg = HKS_ALG_X25519;
181 keyMaterial->keySize = HKS_X25519_KEY_BITS;
182 keyMaterial->pubKeySize = keyByteLen;
183 keyMaterial->priKeySize = keyByteLen;
184
185 /* mbedtls mbedtls_ecp_point.X is x25519's public key */
186 uint32_t offset = sizeof(struct KeyMaterial25519);
187 int32_t ret = mbedtls_mpi_write_binary(&(pub->MBEDTLS_PRIVATE(X)), rawMaterial + offset, keyMaterial->pubKeySize);
188 if (ret != HKS_MBEDTLS_SUCCESS) {
189 HKS_LOG_E("Mbedtls mpi write to x25519 public key failed! mbedtls ret = 0x%" LOG_PUBLIC "X", ret);
190 (void)memset_s(rawMaterial, rawMaterialLen, 0, rawMaterialLen);
191 HKS_FREE_PTR(rawMaterial);
192 return ret;
193 }
194
195 ret = EndianSwap(rawMaterial + offset, keyMaterial->pubKeySize);
196 if (ret != HKS_SUCCESS) {
197 (void)memset_s(rawMaterial, rawMaterialLen, 0, rawMaterialLen);
198 HKS_FREE_PTR(rawMaterial);
199 return ret;
200 }
201
202 offset = offset + keyMaterial->pubKeySize;
203 ret = mbedtls_mpi_write_binary(pri, rawMaterial + offset, keyMaterial->priKeySize);
204 if (ret != HKS_MBEDTLS_SUCCESS) {
205 HKS_LOG_E("Mbedtls mpi write to x25519 private key failed! mbedtls ret = 0x%" LOG_PUBLIC "X", ret);
206 (void)memset_s(rawMaterial, rawMaterialLen, 0, rawMaterialLen);
207 HKS_FREE_PTR(rawMaterial);
208 return ret;
209 }
210
211 key->data = rawMaterial;
212 key->size = rawMaterialLen;
213
214 return HKS_SUCCESS;
215 }
216
HksMbedtlsX25519GenerateKey(const struct HksKeySpec * spec,struct HksBlob * key)217 int32_t HksMbedtlsX25519GenerateKey(const struct HksKeySpec *spec, struct HksBlob *key)
218 {
219 (void)spec;
220 mbedtls_ecp_group grp;
221 mbedtls_ecp_point pub;
222 mbedtls_mpi pri;
223
224 mbedtls_ctr_drbg_context ctrDrbg;
225 mbedtls_entropy_context entropy;
226 (void)memset_s(&entropy, sizeof(mbedtls_entropy_context), 0, sizeof(mbedtls_entropy_context));
227 (void)memset_s(&ctrDrbg, sizeof(mbedtls_ctr_drbg_context), 0, sizeof(mbedtls_ctr_drbg_context));
228 int32_t ret = HksCtrDrbgSeed(&ctrDrbg, &entropy);
229 HKS_IF_NOT_SUCC_RETURN(ret, ret)
230
231 mbedtls_ecp_group_init(&grp);
232 mbedtls_ecp_point_init(&pub);
233 mbedtls_mpi_init(&pri);
234
235 do {
236 ret = mbedtls_ecp_group_load(&grp, MBEDTLS_ECP_DP_CURVE25519);
237 if (ret != HKS_MBEDTLS_SUCCESS) {
238 HKS_LOG_E("Mbedtls load x25519 group failed! mbedtls ret = 0x%" LOG_PUBLIC "X", ret);
239 break;
240 }
241
242 ret = mbedtls_ecdh_gen_public(&grp, &pri, &pub, mbedtls_ctr_drbg_random, &ctrDrbg);
243 if (ret != HKS_MBEDTLS_SUCCESS) {
244 HKS_LOG_E("Mbedtls generate x25519 key failed! mbedtls ret = 0x%" LOG_PUBLIC "X", ret);
245 break;
246 }
247
248 ret = X25519SaveKeyMaterial(&pub, &pri, key);
249 } while (0);
250
251 mbedtls_ecp_group_free(&grp);
252 mbedtls_ecp_point_free(&pub);
253 mbedtls_mpi_free(&pri);
254 mbedtls_ctr_drbg_free(&ctrDrbg);
255 mbedtls_entropy_free(&entropy);
256 return ret;
257 }
258 #endif /* HKS_SUPPORT_X25519_GENERATE_KEY */
259
260 #ifdef HKS_SUPPORT_X25519_AGREE_KEY
X25519KeyMaterialToPub(const struct HksBlob * pubKey,mbedtls_ecp_point * pub)261 static int32_t X25519KeyMaterialToPub(const struct HksBlob *pubKey, mbedtls_ecp_point *pub)
262 {
263 const struct KeyMaterial25519 *keyMaterial = (struct KeyMaterial25519 *)(pubKey->data);
264 uint32_t offset = sizeof(struct KeyMaterial25519);
265
266 uint8_t *tmpPubKey = (uint8_t *)HksMalloc(keyMaterial->pubKeySize);
267 HKS_IF_NULL_RETURN(tmpPubKey, HKS_ERROR_MALLOC_FAIL)
268
269 int32_t ret;
270 do {
271 if (memcpy_s(tmpPubKey, keyMaterial->pubKeySize, pubKey->data + offset, keyMaterial->pubKeySize) != EOK) {
272 ret = HKS_ERROR_INSUFFICIENT_MEMORY;
273 break;
274 }
275
276 ret = EndianSwap(tmpPubKey, keyMaterial->pubKeySize);
277 HKS_IF_NOT_SUCC_BREAK(ret)
278
279 ret = mbedtls_mpi_read_binary(&(pub->MBEDTLS_PRIVATE(X)), tmpPubKey, keyMaterial->pubKeySize);
280 if (ret != HKS_MBEDTLS_SUCCESS) {
281 HKS_LOG_E("Mbedtls mpi read from x25519 public key failed! mbedtls ret = 0x%" LOG_PUBLIC "X", ret);
282 break;
283 }
284
285 /* set initial coordinates. Z = 1, X and Y are its standard(affine) coordinates. */
286 ret = mbedtls_mpi_lset(&(pub->MBEDTLS_PRIVATE(Z)), 1);
287 if (ret != HKS_MBEDTLS_SUCCESS) {
288 HKS_LOG_E("Mbedtls mpi set Z = 1 failed! mbedtls ret = 0x%" LOG_PUBLIC "X", ret);
289 }
290 } while (0);
291
292 HKS_FREE_PTR(tmpPubKey);
293 return ret;
294 }
295
X25519KeyMaterialToPri(const struct HksBlob * nativeKey,mbedtls_mpi * pri)296 static int32_t X25519KeyMaterialToPri(const struct HksBlob *nativeKey, mbedtls_mpi *pri)
297 {
298 const struct KeyMaterial25519 *keyMaterial = (struct KeyMaterial25519 *)(nativeKey->data);
299
300 uint32_t offset = sizeof(struct KeyMaterial25519) + keyMaterial->pubKeySize;
301 int32_t ret = mbedtls_mpi_read_binary(pri, nativeKey->data + offset, keyMaterial->priKeySize);
302 if (ret != HKS_MBEDTLS_SUCCESS) {
303 HKS_LOG_E("Mbedtls mpi read from x25519 private key failed! mbedtls ret = 0x%" LOG_PUBLIC "X", ret);
304 return ret;
305 }
306
307 return HKS_SUCCESS;
308 }
309
HksMbedtlsX25519KeyAgreement(const struct HksBlob * nativeKey,const struct HksBlob * pubKey,const struct HksKeySpec * spec,struct HksBlob * sharedKey)310 int32_t HksMbedtlsX25519KeyAgreement(const struct HksBlob *nativeKey,
311 const struct HksBlob *pubKey, const struct HksKeySpec *spec, struct HksBlob *sharedKey)
312 {
313 (void)spec;
314 int32_t ret = X25519CheckKeyMaterialSize(nativeKey, pubKey);
315 HKS_IF_NOT_SUCC_RETURN(ret, ret)
316
317 mbedtls_ecdh_context ctx;
318 (void)memset_s(&ctx, sizeof(mbedtls_ecdh_context), 0, sizeof(mbedtls_ecdh_context));
319 mbedtls_ecdh_init(&ctx);
320
321 mbedtls_ctr_drbg_context ctrDrbg;
322 mbedtls_entropy_context entropy;
323 (void)memset_s(&entropy, sizeof(mbedtls_entropy_context), 0, sizeof(mbedtls_entropy_context));
324 (void)memset_s(&ctrDrbg, sizeof(mbedtls_ctr_drbg_context), 0, sizeof(mbedtls_ctr_drbg_context));
325 ret = HksCtrDrbgSeed(&ctrDrbg, &entropy);
326 if (ret != HKS_SUCCESS) {
327 mbedtls_ecdh_free(&ctx);
328 return ret;
329 }
330
331 do {
332 ret = mbedtls_ecp_group_load(&(ctx.MBEDTLS_PRIVATE(grp)), MBEDTLS_ECP_DP_CURVE25519);
333 if (ret != HKS_MBEDTLS_SUCCESS) {
334 HKS_LOG_E("Mbedtls load x25519 group failed! mbedtls ret = 0x%" LOG_PUBLIC "X", ret);
335 break;
336 }
337
338 ret = X25519KeyMaterialToPub(pubKey, &(ctx.MBEDTLS_PRIVATE(Qp)));
339 HKS_IF_NOT_SUCC_BREAK(ret)
340
341 ret = X25519KeyMaterialToPri(nativeKey, &(ctx.MBEDTLS_PRIVATE(d)));
342 HKS_IF_NOT_SUCC_BREAK(ret)
343
344 ret = mbedtls_ecdh_compute_shared(&(ctx.MBEDTLS_PRIVATE(grp)), &(ctx.MBEDTLS_PRIVATE(z)),
345 &(ctx.MBEDTLS_PRIVATE(Qp)), &(ctx.MBEDTLS_PRIVATE(d)), mbedtls_ctr_drbg_random, &ctrDrbg);
346 if (ret != HKS_MBEDTLS_SUCCESS) {
347 HKS_LOG_E("Mbedtls x25519 shared key failed! mbedtls ret = 0x%" LOG_PUBLIC "X", ret);
348 break;
349 }
350
351 ret = mbedtls_mpi_write_binary(&(ctx.MBEDTLS_PRIVATE(z)), sharedKey->data, HKS_X25519_KEY_BYTES);
352 if (ret != HKS_MBEDTLS_SUCCESS) {
353 HKS_LOG_E("Mbedtls mpi write to shared key failed! mbedtls ret = 0x%" LOG_PUBLIC "X", ret);
354 (void)memset_s(sharedKey->data, sharedKey->size, 0, sharedKey->size);
355 break;
356 }
357 sharedKey->size = HKS_X25519_KEY_BYTES;
358
359 ret = EndianSwap(sharedKey->data, sharedKey->size);
360 } while (0);
361
362 mbedtls_ecdh_free(&ctx);
363 mbedtls_ctr_drbg_free(&ctrDrbg);
364 mbedtls_entropy_free(&entropy);
365 return ret;
366 }
367 #endif /* HKS_SUPPORT_X25519_AGREE_KEY */
368
369 #ifdef HKS_SUPPORT_X25519_GET_PUBLIC_KEY
GetX25519PubKeyCheckParams(const struct HksBlob * keyIn,const struct HksBlob * keyOut)370 static int32_t GetX25519PubKeyCheckParams(const struct HksBlob *keyIn, const struct HksBlob *keyOut)
371 {
372 const struct KeyMaterial25519 *keyMaterial = (struct KeyMaterial25519 *)(keyIn->data);
373 int32_t ret = X25519CheckKeyMaterialPubPriSize(keyMaterial);
374 HKS_IF_NOT_SUCC_RETURN(ret, ret)
375
376 ret = X25519CheckKeySize(keyIn, keyMaterial, false);
377 HKS_IF_NOT_SUCC_RETURN(ret, ret)
378
379 /* check keyOut */
380 if (keyOut->size < (sizeof(struct KeyMaterial25519) + keyMaterial->pubKeySize)) {
381 HKS_LOG_E("X25519 public keyOut size too small! keyOut size = 0x%" LOG_PUBLIC "X", keyOut->size);
382 return HKS_ERROR_BUFFER_TOO_SMALL;
383 }
384
385 return HKS_SUCCESS;
386 }
387
HksMbedtlsGetX25519PubKey(const struct HksBlob * keyIn,struct HksBlob * keyOut)388 int32_t HksMbedtlsGetX25519PubKey(const struct HksBlob *keyIn, struct HksBlob *keyOut)
389 {
390 int32_t ret = GetX25519PubKeyCheckParams(keyIn, keyOut);
391 HKS_IF_NOT_SUCC_RETURN(ret, ret)
392
393 const struct KeyMaterial25519 *keyMaterial = (struct KeyMaterial25519 *)(keyIn->data);
394 const uint32_t outLen = sizeof(struct KeyMaterial25519) + keyMaterial->pubKeySize;
395 if (memcpy_s(keyOut->data, keyOut->size, (void *)keyMaterial, outLen) != EOK) {
396 HKS_LOG_E("Memcpy x25519 pub key failed!");
397 return HKS_ERROR_INSUFFICIENT_MEMORY;
398 }
399 ((struct KeyMaterial25519 *)(keyOut->data))->priKeySize = 0;
400 keyOut->size = outLen;
401
402 return HKS_SUCCESS;
403 }
404 #endif /* HKS_SUPPORT_X25519_GET_PUBLIC_KEY */
405
406 #if defined(HKS_SUPPORT_ED25519_TO_X25519)
HksCurveInitConstPara(struct HksCurveConstPara * para)407 static void HksCurveInitConstPara(struct HksCurveConstPara *para)
408 {
409 mbedtls_mpi_init(&(para->mpiP));
410 mbedtls_mpi_init(&(para->mpiOne));
411 mbedtls_mpi_init(&(para->mpiD));
412 mbedtls_mpi_init(&(para->mpiK));
413 mbedtls_mpi_init(&(para->mpiCapitalA));
414 mbedtls_mpi_init(&(para->mpiMinusA));
415 mbedtls_mpi_init(&(para->mpiU));
416 mbedtls_mpi_init(&(para->mpiQ));
417 }
418
HksCurveFreeConstPara(struct HksCurveConstPara * para)419 static void HksCurveFreeConstPara(struct HksCurveConstPara *para)
420 {
421 mbedtls_mpi_free(&(para->mpiP));
422 mbedtls_mpi_free(&(para->mpiOne));
423 mbedtls_mpi_free(&(para->mpiD));
424 mbedtls_mpi_free(&(para->mpiK));
425 mbedtls_mpi_free(&(para->mpiCapitalA));
426 mbedtls_mpi_free(&(para->mpiMinusA));
427 mbedtls_mpi_free(&(para->mpiU));
428 mbedtls_mpi_free(&(para->mpiQ));
429 }
430
HksCurveSetConstPara(struct HksCurveConstPara * para)431 static int32_t HksCurveSetConstPara(struct HksCurveConstPara *para)
432 {
433 int32_t ret = mbedtls_mpi_read_binary(&(para->mpiP), g_hksCurveParamP, CURVE25519_KEY_BYTE_SIZE);
434 if (ret != HKS_MBEDTLS_SUCCESS) {
435 return ret;
436 }
437
438 ret = mbedtls_mpi_read_binary(&(para->mpiOne), g_hksCurveParamOne, CURVE25519_KEY_BYTE_SIZE);
439 if (ret != HKS_MBEDTLS_SUCCESS) {
440 return ret;
441 }
442
443 ret = mbedtls_mpi_read_binary(&(para->mpiD), g_hksCurveParamD, CURVE25519_KEY_BYTE_SIZE);
444 if (ret != HKS_MBEDTLS_SUCCESS) {
445 return ret;
446 }
447
448 ret = mbedtls_mpi_read_binary(&(para->mpiK), g_hksCurveParamK, CURVE25519_KEY_BYTE_SIZE);
449 if (ret != HKS_MBEDTLS_SUCCESS) {
450 return ret;
451 }
452
453 ret = mbedtls_mpi_read_binary(&(para->mpiCapitalA), g_hksCurveParamCapitalA, CURVE25519_KEY_BYTE_SIZE);
454 if (ret != HKS_MBEDTLS_SUCCESS) {
455 return ret;
456 }
457
458 ret = mbedtls_mpi_read_binary(&(para->mpiMinusA), g_hksCurveParamMinusA, CURVE25519_KEY_BYTE_SIZE);
459 if (ret != HKS_MBEDTLS_SUCCESS) {
460 return ret;
461 }
462
463 ret = mbedtls_mpi_read_binary(&(para->mpiU), g_hksCurveParamU, CURVE25519_KEY_BYTE_SIZE);
464 if (ret != HKS_MBEDTLS_SUCCESS) {
465 return ret;
466 }
467
468 ret = mbedtls_mpi_read_binary(&(para->mpiQ), g_hksCurveParamQ, CURVE25519_KEY_BYTE_SIZE);
469 if (ret != HKS_MBEDTLS_SUCCESS) {
470 return ret;
471 }
472
473 return HKS_SUCCESS;
474 }
475 #endif /* HKS_SUPPORT_ED25519_TO_X25519 */
476
477 #ifdef HKS_SUPPORT_ED25519_TO_X25519
478 struct HksEd25519ToX25519Blob {
479 struct HksBlob rawNativeKey;
480 struct HksBlob rawPubKey;
481 struct HksBlob rawX25519NativeKey;
482 struct HksBlob rawX25519PubKey;
483 struct HksBlob kmX25519NativeKey;
484 struct HksBlob kmX25519PubKey;
485 };
486
HksCurvePskCalcA(const mbedtls_mpi * edwardsY,const struct HksCurveConstPara * curvePara,mbedtls_mpi * mpiA)487 static int32_t HksCurvePskCalcA(const mbedtls_mpi *edwardsY,
488 const struct HksCurveConstPara *curvePara, mbedtls_mpi *mpiA)
489 {
490 mbedtls_mpi mpiE;
491 mbedtls_mpi swap;
492
493 mbedtls_mpi_init(&mpiE);
494 mbedtls_mpi_init(&swap);
495
496 int32_t ret = HKS_ERROR_CRYPTO_ENGINE_ERROR;
497 do {
498 /* mpiA := (y ^ 2 - 1) / (1 + d * y ^ 2) */
499 if (mbedtls_mpi_mul_mpi(&mpiE, edwardsY, edwardsY) != HKS_MBEDTLS_SUCCESS) {
500 break;
501 }
502
503 if (mbedtls_mpi_mod_mpi(&mpiE, &mpiE, &(curvePara->mpiP)) != HKS_MBEDTLS_SUCCESS) {
504 break;
505 }
506
507 if (mbedtls_mpi_mul_mpi(&swap, &(curvePara->mpiD), &mpiE) != HKS_MBEDTLS_SUCCESS) {
508 break;
509 }
510
511 if (mbedtls_mpi_add_mpi(&swap, &swap, &(curvePara->mpiOne)) != HKS_MBEDTLS_SUCCESS) {
512 break;
513 }
514
515 if (mbedtls_mpi_mod_mpi(&swap, &swap, &(curvePara->mpiP)) != HKS_MBEDTLS_SUCCESS) {
516 break;
517 }
518
519 if (mbedtls_mpi_inv_mod(&swap, &swap, &(curvePara->mpiP)) != HKS_MBEDTLS_SUCCESS) {
520 break;
521 }
522
523 if (mbedtls_mpi_sub_mpi(&mpiE, &mpiE, &(curvePara->mpiOne)) != HKS_MBEDTLS_SUCCESS) {
524 break;
525 }
526
527 if (mbedtls_mpi_mod_mpi(&mpiE, &mpiE, &(curvePara->mpiP)) != HKS_MBEDTLS_SUCCESS) {
528 break;
529 }
530
531 if (mbedtls_mpi_mul_mpi(&mpiE, &mpiE, &swap) != HKS_MBEDTLS_SUCCESS) {
532 break;
533 }
534
535 if (mbedtls_mpi_mod_mpi(&mpiE, &mpiE, &(curvePara->mpiP)) != HKS_MBEDTLS_SUCCESS) {
536 break;
537 }
538
539 if (mbedtls_mpi_add_mpi(&mpiE, &mpiE, &(curvePara->mpiP)) != HKS_MBEDTLS_SUCCESS) {
540 break;
541 }
542
543 /* Sliding-window exponentiation: mpiA = e^k mod p */
544 ret = mbedtls_mpi_exp_mod(mpiA, &mpiE, &(curvePara->mpiK), &(curvePara->mpiP), NULL);
545 } while (0);
546
547 mbedtls_mpi_free(&mpiE);
548 mbedtls_mpi_free(&swap);
549
550 return ret;
551 }
552
HksCurvePskCheckA(mbedtls_mpi * mpiA,const uint8_t * ed25519PublicKey,size_t len,const struct HksCurveConstPara * curvePara)553 static int32_t HksCurvePskCheckA(mbedtls_mpi *mpiA, const uint8_t *ed25519PublicKey,
554 size_t len, const struct HksCurveConstPara *curvePara)
555 {
556 /* Check, whether a is a square modulo p (including a = 0) */
557 int32_t ret = mbedtls_mpi_cmp_mpi(&(curvePara->mpiOne), mpiA);
558 if (ret > 0) {
559 HKS_LOG_E("a is not a square modulo p");
560 return HKS_ERROR_INVALID_PUBLIC_KEY;
561 }
562
563 /* If a == p, the parity bit must be 0 */
564 ret = mbedtls_mpi_cmp_mpi(mpiA, &(curvePara->mpiP));
565 if (ret == 0) {
566 uint32_t value = ed25519PublicKey[len - 1] >> 7; /* 7: RFC8032 */
567 /* The previous check has guaranteed that a must be greater than or equal to one */
568 value = (value & (uint32_t)mbedtls_mpi_sub_mpi(mpiA, mpiA, &(curvePara->mpiOne)));
569 if (value != 0) {
570 HKS_LOG_E("the parity bit not zero");
571 return HKS_ERROR_INVALID_PUBLIC_KEY;
572 }
573 }
574
575 return HKS_SUCCESS;
576 }
577
HksCurvePskCheckPoint(const mbedtls_mpi * edwardsY,const uint8_t * ed25519PublicKey,size_t len,const struct HksCurveConstPara * curvePara)578 static int32_t HksCurvePskCheckPoint(const mbedtls_mpi *edwardsY, const uint8_t *ed25519PublicKey,
579 size_t len, const struct HksCurveConstPara *curvePara)
580 {
581 mbedtls_mpi mpiA;
582 mbedtls_mpi_init(&mpiA);
583
584 int32_t ret;
585 do {
586 /* if y >= p, return error */
587 ret = mbedtls_mpi_cmp_mpi(edwardsY, &(curvePara->mpiP));
588 if (ret >= 0) {
589 HKS_LOG_E("edwardsY is greater than or equal to p, ret is %" LOG_PUBLIC "d", ret);
590 ret = HKS_ERROR_INVALID_PUBLIC_KEY;
591 break;
592 }
593
594 /* if y == 1, return error */
595 ret = mbedtls_mpi_cmp_mpi(edwardsY, &(curvePara->mpiOne));
596 if (ret == 0) {
597 HKS_LOG_E("edwards_y equals one");
598 ret = HKS_ERROR_INVALID_PUBLIC_KEY;
599 break;
600 }
601
602 /* a := (y ^ 2 - 1) / (1 + d * y ^ 2) */
603 ret = HksCurvePskCalcA(edwardsY, curvePara, &mpiA);
604 if (ret != HKS_SUCCESS)
605 break;
606
607 ret = HksCurvePskCheckA(&mpiA, ed25519PublicKey, len, curvePara);
608 } while (0);
609
610 mbedtls_mpi_free(&mpiA);
611 return ret;
612 }
613
HksCurvePskCalcC(const mbedtls_mpi * edwardsY,struct HksBlob * x25519Key,const struct HksCurveConstPara * curvePara)614 static int32_t HksCurvePskCalcC(const mbedtls_mpi *edwardsY, struct HksBlob *x25519Key,
615 const struct HksCurveConstPara *curvePara)
616 {
617 mbedtls_mpi curveX;
618 mbedtls_mpi result;
619
620 mbedtls_mpi_init(&curveX);
621 mbedtls_mpi_init(&result);
622
623 int32_t ret;
624 do {
625 /* If y != 1, c := (1 + y) / (1 - y), otherwise c := 0 */
626 ret = mbedtls_mpi_sub_mpi(&result, &(curvePara->mpiOne), edwardsY);
627 if (ret != HKS_MBEDTLS_SUCCESS) {
628 break;
629 }
630
631 ret = mbedtls_mpi_mod_mpi(&result, &result, &(curvePara->mpiP));
632 if (ret != HKS_MBEDTLS_SUCCESS) {
633 break;
634 }
635
636 ret = mbedtls_mpi_inv_mod(&result, &result, &(curvePara->mpiP));
637 if (ret != HKS_MBEDTLS_SUCCESS) {
638 break;
639 }
640
641 ret = mbedtls_mpi_add_mpi(&curveX, &(curvePara->mpiOne), edwardsY);
642 if (ret != HKS_MBEDTLS_SUCCESS) {
643 break;
644 }
645
646 ret = mbedtls_mpi_mul_mpi(&result, &curveX, &result);
647 if (ret != HKS_MBEDTLS_SUCCESS) {
648 break;
649 }
650
651 ret = mbedtls_mpi_mod_mpi(&result, &result, &(curvePara->mpiP));
652 if (ret != HKS_MBEDTLS_SUCCESS) {
653 break;
654 }
655
656 ret = mbedtls_mpi_write_binary(&result, x25519Key->data, x25519Key->size);
657 } while (0);
658
659 mbedtls_mpi_free(&curveX);
660 mbedtls_mpi_free(&result);
661
662 return ret;
663 }
664
ConvertPublicKey(const struct HksBlob * publicKeyIn,struct HksBlob * x25519PublicKey)665 static int32_t ConvertPublicKey(const struct HksBlob *publicKeyIn, struct HksBlob *x25519PublicKey)
666 {
667 /* RFC 8032 */
668 publicKeyIn->data[publicKeyIn->size - 1] = publicKeyIn->data[publicKeyIn->size - 1] & 0x7f;
669 int32_t ret = EndianSwap(publicKeyIn->data, publicKeyIn->size);
670 HKS_IF_NOT_SUCC_RETURN(ret, ret)
671
672 mbedtls_mpi edwardsY;
673 struct HksCurveConstPara curvePara;
674
675 mbedtls_mpi_init(&edwardsY);
676 HksCurveInitConstPara(&curvePara);
677
678 do {
679 ret = HksCurveSetConstPara(&curvePara);
680 HKS_IF_NOT_SUCC_BREAK(ret)
681
682 ret = mbedtls_mpi_read_binary(&edwardsY, publicKeyIn->data, publicKeyIn->size);
683 if (ret != HKS_MBEDTLS_SUCCESS) {
684 break;
685 }
686
687 ret = HksCurvePskCheckPoint(&edwardsY, publicKeyIn->data, publicKeyIn->size, &curvePara);
688 HKS_IF_NOT_SUCC_BREAK(ret)
689
690 x25519PublicKey->size = CURVE25519_KEY_BYTE_SIZE;
691 x25519PublicKey->data = (uint8_t *)HksMalloc(x25519PublicKey->size);
692 if (x25519PublicKey->data == NULL) {
693 HKS_LOG_E("malloc failed");
694 ret = HKS_ERROR_MALLOC_FAIL;
695 break;
696 }
697
698 ret = HksCurvePskCalcC(&edwardsY, x25519PublicKey, &curvePara);
699 HKS_IF_NOT_SUCC_BREAK(ret)
700
701 ret = EndianSwap(x25519PublicKey->data, x25519PublicKey->size);
702 } while (0);
703
704 HksCurveFreeConstPara(&curvePara);
705 mbedtls_mpi_free(&edwardsY);
706 if ((ret != HKS_SUCCESS) && (x25519PublicKey->data != NULL)) {
707 (void)memset_s(x25519PublicKey->data, x25519PublicKey->size, 0, x25519PublicKey->size);
708 HKS_FREE_BLOB(*x25519PublicKey);
709 }
710
711 return ret;
712 }
713
ConvertPrivateKey(const struct HksBlob * privateKeyIn,struct HksBlob * x25519PrivateKey)714 static int32_t ConvertPrivateKey(const struct HksBlob *privateKeyIn, struct HksBlob *x25519PrivateKey)
715 {
716 uint8_t hash512Data[HASH512_OUT_SIZE] = {0};
717 struct HksBlob hash512 = { HASH512_OUT_SIZE, hash512Data };
718
719 /* Get 32-bit private key data as the hash input parameter (little endian) */
720 int32_t ret = HksCryptoHalHash(HKS_DIGEST_SHA512, privateKeyIn, &hash512);
721 HKS_IF_NOT_SUCC_LOGE_RETURN(ret, ret, "convert private key calc hash failed")
722
723 x25519PrivateKey->size = CURVE25519_KEY_BYTE_SIZE;
724 x25519PrivateKey->data = (uint8_t *)HksMalloc(x25519PrivateKey->size);
725 HKS_IF_NULL_LOGE_RETURN(x25519PrivateKey->data, HKS_ERROR_MALLOC_FAIL, "malloc failed")
726
727 do {
728 /* Get the first 32 bytes of the hash value (little endian) */
729 if (memcpy_s(x25519PrivateKey->data, x25519PrivateKey->size, hash512.data, CURVE25519_KEY_BYTE_SIZE) != EOK) {
730 ret = HKS_ERROR_INSUFFICIENT_MEMORY;
731 break;
732 }
733
734 x25519PrivateKey->data[0] &= 248; /* 248: RFC 8032 */
735 x25519PrivateKey->data[x25519PrivateKey->size - 1] &= 127; /* 127: RFC 8032 */
736 x25519PrivateKey->data[x25519PrivateKey->size - 1] |= 64; /* 64: RFC 8032 */
737
738 ret = EndianSwap(x25519PrivateKey->data, x25519PrivateKey->size);
739 } while (0);
740
741 if ((ret != HKS_SUCCESS) && (x25519PrivateKey->data != NULL)) {
742 (void)memset_s(x25519PrivateKey->data, x25519PrivateKey->size, 0, x25519PrivateKey->size);
743 HKS_FREE_BLOB(*x25519PrivateKey);
744 }
745 return ret;
746 }
747
MbedtlsEd25519KeyToX25519(const struct HksBlob * ed25519NativeKey,const struct HksBlob * ed25519PubKey,struct HksBlob * x25519NativeKey,struct HksBlob * x25519PubKey)748 int32_t MbedtlsEd25519KeyToX25519(const struct HksBlob *ed25519NativeKey,
749 const struct HksBlob *ed25519PubKey, struct HksBlob *x25519NativeKey, struct HksBlob *x25519PubKey)
750 {
751 int32_t ret = ConvertPublicKey(ed25519PubKey, x25519PubKey);
752 HKS_IF_NOT_SUCC_LOGE_RETURN(ret, ret,
753 "convert ed25519 public key to x25519 public key failed! ret = %" LOG_PUBLIC "d", ret)
754
755 HKS_IF_NOT_SUCC_LOGE_RETURN(ret, ret,
756 "convert ed25519 private key to x25519 private key failed! ret = %" LOG_PUBLIC "d", ret)
757
758 ret = ConvertPrivateKey(ed25519NativeKey, x25519NativeKey);
759
760 return HKS_SUCCESS;
761 }
762
HksFreeKeyInfo(struct HksEd25519ToX25519Blob * key)763 void HksFreeKeyInfo(struct HksEd25519ToX25519Blob *key)
764 {
765 if (key->rawNativeKey.data != NULL) {
766 (void)memset_s(key->rawNativeKey.data, key->rawNativeKey.size, 0, key->rawNativeKey.size);
767 HKS_FREE_PTR(key->rawNativeKey.data);
768 }
769 if (key->rawPubKey.data != NULL) {
770 (void)memset_s(key->rawPubKey.data, key->rawPubKey.size, 0, key->rawPubKey.size);
771 HKS_FREE_PTR(key->rawPubKey.data);
772 }
773 if (key->rawX25519NativeKey.data != NULL) {
774 (void)memset_s(key->rawX25519NativeKey.data, key->rawX25519NativeKey.size, 0, key->rawX25519NativeKey.size);
775 HKS_FREE_PTR(key->rawX25519NativeKey.data);
776 }
777 if (key->rawX25519PubKey.data != NULL) {
778 (void)memset_s(key->rawX25519PubKey.data, key->rawX25519PubKey.size, 0, key->rawX25519PubKey.size);
779 HKS_FREE_PTR(key->rawX25519PubKey.data);
780 }
781 if (key->kmX25519NativeKey.data != NULL) {
782 (void)memset_s(key->kmX25519NativeKey.data, key->kmX25519NativeKey.size, 0, key->kmX25519NativeKey.size);
783 HKS_FREE_PTR(key->kmX25519NativeKey.data);
784 }
785 if (key->kmX25519PubKey.data != NULL) {
786 (void)memset_s(key->kmX25519PubKey.data, key->kmX25519PubKey.size, 0, key->kmX25519PubKey.size);
787 HKS_FREE_PTR(key->kmX25519PubKey.data);
788 }
789 }
790
HksMbedtlsEd25519KeyAgreement(const struct HksBlob * nativeKey,const struct HksBlob * pubKey,const struct HksKeySpec * spec,struct HksBlob * sharedKey)791 int32_t HksMbedtlsEd25519KeyAgreement(const struct HksBlob *nativeKey,
792 const struct HksBlob *pubKey, const struct HksKeySpec *spec, struct HksBlob *sharedKey)
793 {
794 (void)spec;
795 int32_t ret = X25519CheckKeyMaterialSize(nativeKey, pubKey);
796 HKS_IF_NOT_SUCC_RETURN(ret, ret)
797
798 struct HksEd25519ToX25519Blob key;
799 (void)memset_s(&key, sizeof(key), 0, sizeof(key));
800
801 do {
802 ret = HksGetKeyFromMaterial(HKS_ALG_ED25519, false, nativeKey, &(key.rawNativeKey));
803 HKS_IF_NOT_SUCC_LOGE_BREAK(ret, "get private key from material failed, ret = 0x%" LOG_PUBLIC "X", ret)
804 ret = HksGetKeyFromMaterial(HKS_ALG_ED25519, true, pubKey, &(key.rawPubKey));
805 HKS_IF_NOT_SUCC_LOGE_BREAK(ret, "get public key from material failed, ret = 0x%" LOG_PUBLIC "X", ret)
806
807 ret = MbedtlsEd25519KeyToX25519(&(key.rawNativeKey), &(key.rawPubKey),
808 &(key.rawX25519NativeKey), &(key.rawX25519PubKey));
809 HKS_IF_NOT_SUCC_LOGE_BREAK(ret, "covert from ed25519 to x25519 failed, ret = 0x%" LOG_PUBLIC "X", ret)
810
811 ret = HksSetKeyToMaterial(HKS_ALG_X25519, false, &(key.rawX25519NativeKey), &(key.kmX25519NativeKey));
812 HKS_IF_NOT_SUCC_LOGE_BREAK(ret, "set private key to material failed, ret = 0x%" LOG_PUBLIC "X", ret)
813
814 ret = HksSetKeyToMaterial(HKS_ALG_X25519, true, &(key.rawX25519PubKey), &(key.kmX25519PubKey));
815 HKS_IF_NOT_SUCC_LOGE_BREAK(ret, "set publicy key to material failed, ret = 0x%" LOG_PUBLIC "X", ret)
816
817 ret = HksMbedtlsX25519KeyAgreement(&(key.kmX25519NativeKey), &(key.kmX25519PubKey), NULL, sharedKey);
818 } while (0);
819
820 HksFreeKeyInfo(&key);
821 return ret;
822 }
823 #endif
824
825 #endif /* HKS_SUPPORT_X25519_C */
826