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