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