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