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