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