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