• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022-2023 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 #include "mbedtls_ec_adapter.h"
17 
18 #include <mbedtls/bignum.h>
19 #include <mbedtls/ctr_drbg.h>
20 #include <mbedtls/entropy.h>
21 #include <mbedtls/error.h>
22 #include <mbedtls/pk.h>
23 #include <mbedtls/x509.h>
24 
25 #include "hal_error.h"
26 #include "hc_log.h"
27 #include "huks_adapter.h"
28 
29 #define LOG_AND_RETURN_IF_MBED_FAIL(ret, fmt, ...) \
30 do { \
31     if ((ret) != 0) { \
32         LOGE(fmt, ##__VA_ARGS__); \
33         return HAL_ERR_MBEDTLS; \
34     } \
35 } while (0)
36 
37 #define LOG_AND_GOTO_CLEANUP_IF_FAIL(ret, fmt, ...) \
38 do { \
39     if ((ret) != 0) { \
40         LOGE(fmt, ##__VA_ARGS__); \
41         goto CLEAN_UP; \
42     } \
43 } while (0)
44 
45 #define LEN_HALF_DIVISOR 2
46 #define BITS_PER_BYTE 8
47 #define EC_LEN 64
48 #define SHA256_HASH_LEN 32
49 #define P256_KEY_SIZE 32
50 #define P256_PUBLIC_SIZE 64 // P256_KEY_SIZE * 2
51 #define PARAM_A_INDEX 2
52 #define PARAM_U_INDEX 4
53 #define PARAM_MINUS_A_INDEX 3
54 #define PARAM_ONE_INDEX 5
55 #define HASH_TO_POINT_PARA_NUMS 6
56 
57 typedef struct Blob {
58     uint32_t dataSize;
59     uint8_t *data;
60 } Blob;
61 
62 static const uint8_t POINT_A[] = {
63     0x04, 0x53, 0xf9, 0xe4, 0xf4, 0xbc, 0x3a, 0xb5, 0x9d, 0x44, 0x78, 0x45, 0x21, 0x13, 0x8b, 0x49,
64     0xba, 0xa3, 0x1c, 0xe2, 0xa8, 0xdb, 0xbd, 0xb8, 0xd6, 0x73, 0x31, 0x46, 0x3a, 0x69, 0x53, 0xf1,
65     0xed, 0xef, 0x96, 0x1e, 0xdb, 0x42, 0xbe, 0x3a, 0x24, 0x43, 0xc4, 0x08, 0x23, 0xfb, 0x58, 0xee,
66     0x61, 0x24, 0x8b, 0x59, 0x64, 0x65, 0x2d, 0xbc, 0x6b, 0xa5, 0x1d, 0x6e, 0x04, 0x22, 0x53, 0xae,
67     0x27
68 };
69 static const uint8_t POINT_B[] = {
70     0x04, 0x03, 0x4d, 0x11, 0x11, 0xa6, 0x3f, 0x5f, 0x72, 0x43, 0x59, 0x73, 0x8b, 0x46, 0xc3, 0xfd,
71     0x70, 0x58, 0xb0, 0xb6, 0x11, 0xd3, 0x4f, 0xf3, 0x49, 0xa0, 0xd2, 0x86, 0xd7, 0x35, 0x33, 0xc5,
72     0x36, 0xe4, 0x99, 0xcc, 0x13, 0x47, 0xe4, 0xab, 0xde, 0x8f, 0x3a, 0xd6, 0x65, 0x1a, 0x77, 0x0b,
73     0xc4, 0x82, 0xd5, 0xac, 0x4b, 0x5d, 0xe4, 0xcc, 0x48, 0xb0, 0x54, 0x6c, 0x9b, 0x76, 0x76, 0x1a,
74     0xba
75 };
76 
77 static uint8_t g_hash2pointParas[HASH_TO_POINT_PARA_NUMS][BYTE_LENGTH_CURVE_25519] = {
78     { 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,    /* 0:p */
79       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
80       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
81       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xed },
82     { 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,    /* 1:divide_minus_p_1_2 */
83       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
84       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
85       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf6 },
86     { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,    /* 2:A */
87       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
88       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
89       0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x6d, 0x06 },
90     { 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,    /* 3:-A */
91       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
92       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
93       0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x92, 0xe7 },
94     { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,    /* 4:u = 2 */
95       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
96       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
97       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 },
98     { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,    /* 5:1 */
99       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
100       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
101       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 },
102 };
103 
104 static const uint8_t RANDOM_SEED_CUSTOM[] = { 0x4C, 0x54, 0x4B, 0x53 }; // LTKS means LiteKeystore
105 
IsValidBlob(const Blob * blob)106 static bool IsValidBlob(const Blob *blob)
107 {
108     return (blob != NULL) && (blob->data != NULL) && (blob->dataSize != 0);
109 }
110 
IsValidUint8Buff(const Uint8Buff * buff)111 static bool IsValidUint8Buff(const Uint8Buff *buff)
112 {
113     return (buff != NULL) && (buff->val != NULL) && (buff->length != 0);
114 }
115 
InitPointParams(mbedtls_mpi * scalarA,mbedtls_mpi * scalarB,mbedtls_ecp_point * pointA,mbedtls_ecp_point * pointB,mbedtls_ecp_point * result)116 static void InitPointParams(mbedtls_mpi *scalarA, mbedtls_mpi *scalarB, mbedtls_ecp_point *pointA,
117     mbedtls_ecp_point *pointB, mbedtls_ecp_point *result)
118 {
119     mbedtls_mpi_init(scalarA);
120     mbedtls_mpi_init(scalarB);
121     mbedtls_ecp_point_init(pointA);
122     mbedtls_ecp_point_init(pointB);
123     mbedtls_ecp_point_init(result);
124 }
125 
FreePointParams(mbedtls_mpi * scalarA,mbedtls_mpi * scalarB,mbedtls_ecp_point * pointA,mbedtls_ecp_point * pointB,mbedtls_ecp_point * result)126 static void FreePointParams(mbedtls_mpi *scalarA, mbedtls_mpi *scalarB, mbedtls_ecp_point *pointA,
127     mbedtls_ecp_point *pointB, mbedtls_ecp_point *result)
128 {
129     mbedtls_mpi_free(scalarA);
130     mbedtls_mpi_free(scalarB);
131     mbedtls_ecp_point_free(pointA);
132     mbedtls_ecp_point_free(pointB);
133     mbedtls_ecp_point_free(result);
134 }
135 
SwapEndian(uint8_t * pubKey,int len)136 static void SwapEndian(uint8_t *pubKey, int len)
137 {
138     if ((pubKey == NULL) || (len <= 0)) {
139         return;
140     }
141     for (int i = 0; i < len / LEN_HALF_DIVISOR; ++i) {
142         uint8_t tmp = pubKey[i];
143         pubKey[i] = pubKey[len - i - 1];
144         pubKey[len - i - 1] = tmp;
145     }
146 }
147 
FreeCleanFiveBns(mbedtls_mpi * bn1,mbedtls_mpi * bn2,mbedtls_mpi * bn3,mbedtls_mpi * bn4,mbedtls_mpi * bn5)148 static void FreeCleanFiveBns(mbedtls_mpi *bn1, mbedtls_mpi *bn2, mbedtls_mpi *bn3,
149                              mbedtls_mpi *bn4, mbedtls_mpi *bn5)
150 {
151     mbedtls_mpi_free(bn1);
152     mbedtls_mpi_free(bn2);
153     mbedtls_mpi_free(bn3);
154     mbedtls_mpi_free(bn4);
155     mbedtls_mpi_free(bn5);
156 }
157 
CalTmpParaX(mbedtls_mpi * tmpY,const mbedtls_mpi * tmpX,const mbedtls_mpi * modP)158 static int32_t CalTmpParaX(mbedtls_mpi *tmpY, const mbedtls_mpi *tmpX, const mbedtls_mpi *modP)
159 {
160     int32_t status;
161     mbedtls_mpi tmpBnA;
162     mbedtls_mpi tmpBnB;
163     mbedtls_mpi tmpBnC;
164     mbedtls_mpi tmpBnE;
165     mbedtls_mpi paraBnA;
166     mbedtls_mpi paraBnU;
167 
168     mbedtls_mpi_init(&tmpBnA);
169     mbedtls_mpi_init(&tmpBnB);
170     mbedtls_mpi_init(&tmpBnC);
171     mbedtls_mpi_init(&tmpBnE);
172     mbedtls_mpi_init(&paraBnA);
173     mbedtls_mpi_init(&paraBnU);
174 
175     status = mbedtls_mpi_read_binary(&paraBnA, g_hash2pointParas[PARAM_A_INDEX], BYTE_LENGTH_CURVE_25519);
176     LOG_AND_GOTO_CLEANUP_IF_FAIL(status, "CalTmpParaX error1");
177 
178     status = mbedtls_mpi_read_binary(&paraBnU, g_hash2pointParas[PARAM_U_INDEX], BYTE_LENGTH_CURVE_25519);
179     LOG_AND_GOTO_CLEANUP_IF_FAIL(status, "CalTmpParaX error2");
180 
181     status = mbedtls_mpi_copy(&tmpBnB, tmpX);
182     LOG_AND_GOTO_CLEANUP_IF_FAIL(status, "CalTmpParaX error3");
183     /* a := b ^ 3 + A * b ^ 2 + b */
184 
185     status = mbedtls_mpi_exp_mod(&tmpBnE, &tmpBnB, &paraBnU, modP, NULL);
186     LOG_AND_GOTO_CLEANUP_IF_FAIL(status, "CalTmpParaX error4"); // b^2
187 
188     status = mbedtls_mpi_mul_mpi(&tmpBnC, &tmpBnE, &tmpBnB);
189     LOG_AND_GOTO_CLEANUP_IF_FAIL(status, "CalTmpParaX error5");
190     status = mbedtls_mpi_mod_mpi(&tmpBnC, &tmpBnC, modP);
191     LOG_AND_GOTO_CLEANUP_IF_FAIL(status, "CalTmpParaX error6"); // b^3
192 
193     status = mbedtls_mpi_mul_mpi(&tmpBnA, &tmpBnE, &paraBnA); // A*b^2
194     LOG_AND_GOTO_CLEANUP_IF_FAIL(status, "CalTmpParaX error7");
195     status = mbedtls_mpi_mod_mpi(&tmpBnA, &tmpBnA, modP);
196     LOG_AND_GOTO_CLEANUP_IF_FAIL(status, "CalTmpParaX error8");
197 
198     status = mbedtls_mpi_add_mpi(&tmpBnE, &tmpBnC, &tmpBnA); // b^3 + A*b^2
199     LOG_AND_GOTO_CLEANUP_IF_FAIL(status, "CalTmpParaX error9");
200     status = mbedtls_mpi_mod_mpi(&tmpBnE, &tmpBnE, modP);
201     LOG_AND_GOTO_CLEANUP_IF_FAIL(status, "CalTmpParaX error10");
202 
203     status = mbedtls_mpi_add_mpi(tmpY, &tmpBnE, &tmpBnB); // b^3 + A*b^2 + b
204     LOG_AND_GOTO_CLEANUP_IF_FAIL(status, "CalTmpParaX error11");
205     status = mbedtls_mpi_mod_mpi(tmpY, tmpY, modP);
206     LOG_AND_GOTO_CLEANUP_IF_FAIL(status, "CalTmpParaX error12");
207 
208 CLEAN_UP:
209     FreeCleanFiveBns(&paraBnA, &tmpBnA, &tmpBnB, &tmpBnC, &tmpBnE);
210     mbedtls_mpi_free(&paraBnU);
211     return status;
212 }
213 
CalTmpParab(mbedtls_mpi * tmpX,const mbedtls_mpi * modP,const uint8_t * hash,uint32_t hashLen)214 static int32_t CalTmpParab(mbedtls_mpi *tmpX, const mbedtls_mpi *modP, const uint8_t *hash, uint32_t hashLen)
215 {
216     int32_t status;
217     mbedtls_mpi paraBnNegA;
218     mbedtls_mpi paraBNOne;
219     mbedtls_mpi paraBnU;
220     mbedtls_mpi tmpBnA;
221     mbedtls_mpi tmpBnB;
222 
223     mbedtls_mpi_init(&paraBnNegA);
224     mbedtls_mpi_init(&paraBNOne);
225     mbedtls_mpi_init(&paraBnU);
226     mbedtls_mpi_init(&tmpBnA);
227     mbedtls_mpi_init(&tmpBnB);
228 
229     status = mbedtls_mpi_read_binary(&paraBnNegA, g_hash2pointParas[PARAM_MINUS_A_INDEX], BYTE_LENGTH_CURVE_25519);
230     LOG_AND_GOTO_CLEANUP_IF_FAIL(status, "CalTmpParab error1");
231     status = mbedtls_mpi_read_binary(&paraBNOne, g_hash2pointParas[PARAM_ONE_INDEX], BYTE_LENGTH_CURVE_25519);
232     LOG_AND_GOTO_CLEANUP_IF_FAIL(status, "CalTmpParab error2");
233     status = mbedtls_mpi_read_binary(&paraBnU, g_hash2pointParas[PARAM_U_INDEX], BYTE_LENGTH_CURVE_25519);
234     LOG_AND_GOTO_CLEANUP_IF_FAIL(status, "CalTmpParab error3");
235     status = mbedtls_mpi_read_binary(&tmpBnA, hash, hashLen);
236     LOG_AND_GOTO_CLEANUP_IF_FAIL(status, "CalTmpParab error4");
237 
238     /* b := -A / (1 + u * a ^ 2) */
239     status = mbedtls_mpi_exp_mod(&tmpBnB, &tmpBnA, &paraBnU, modP, NULL);
240     LOG_AND_GOTO_CLEANUP_IF_FAIL(status, "CalTmpParab error5");
241 
242     status = mbedtls_mpi_mul_mpi(&tmpBnA, &tmpBnB, &paraBnU);
243     LOG_AND_GOTO_CLEANUP_IF_FAIL(status, "CalTmpParab error6");
244     status = mbedtls_mpi_mod_mpi(&tmpBnA, &tmpBnA, modP);
245     LOG_AND_GOTO_CLEANUP_IF_FAIL(status, "CalTmpParab error7");
246 
247     status = mbedtls_mpi_add_mpi(&tmpBnB, &tmpBnA, &paraBNOne);
248     LOG_AND_GOTO_CLEANUP_IF_FAIL(status, "CalTmpParab error8");
249     status = mbedtls_mpi_mod_mpi(&tmpBnB, &tmpBnB, modP);
250     LOG_AND_GOTO_CLEANUP_IF_FAIL(status, "CalTmpParab error9");
251 
252     status = mbedtls_mpi_inv_mod(&tmpBnA, &tmpBnB, modP);
253     LOG_AND_GOTO_CLEANUP_IF_FAIL(status, "CalTmpParab error10");
254 
255     status = mbedtls_mpi_mul_mpi(tmpX, &tmpBnA, &paraBnNegA);
256     LOG_AND_GOTO_CLEANUP_IF_FAIL(status, "CalTmpParab error11");
257     status = mbedtls_mpi_mod_mpi(tmpX, tmpX, modP);
258     LOG_AND_GOTO_CLEANUP_IF_FAIL(status, "CalTmpParab error12");
259 CLEAN_UP:
260     FreeCleanFiveBns(&paraBnNegA, &paraBNOne, &paraBnU, &tmpBnA, &tmpBnB);
261     return status;
262 }
263 
264 /*
265  * hash2point function, use BoringSSL big number algorithm library;
266  * p_point(little endian): the output pointer of Curve25519 point;
267  * p_hash (little endian): the input pointer of string;
268  */
Elligator(unsigned char * point,int pointLength,const unsigned char * hash,int hashLength)269 static int32_t Elligator(unsigned char *point, int pointLength, const unsigned char *hash, int hashLength)
270 {
271     mbedtls_mpi paraBnP;
272     mbedtls_mpi paraBnSquare;
273     mbedtls_mpi paraBnNegA;
274     mbedtls_mpi tmpBnA;
275     mbedtls_mpi tmpBnB;
276     mbedtls_mpi tmpBnC;
277     mbedtls_mpi tmpBnE;
278 
279     mbedtls_mpi_init(&paraBnP);
280     mbedtls_mpi_init(&paraBnSquare);
281     mbedtls_mpi_init(&paraBnNegA);
282     mbedtls_mpi_init(&tmpBnA);
283     mbedtls_mpi_init(&tmpBnB);
284     mbedtls_mpi_init(&tmpBnC);
285     mbedtls_mpi_init(&tmpBnE);
286 
287     int32_t status = mbedtls_mpi_read_binary(&paraBnP, g_hash2pointParas[0], BYTE_LENGTH_CURVE_25519);
288     LOG_AND_GOTO_CLEANUP_IF_FAIL(status, "Elligator error1");
289     status = mbedtls_mpi_read_binary(&paraBnSquare, g_hash2pointParas[1], BYTE_LENGTH_CURVE_25519);
290     LOG_AND_GOTO_CLEANUP_IF_FAIL(status, "Elligator error2");
291     status = mbedtls_mpi_read_binary(&paraBnNegA, g_hash2pointParas[PARAM_MINUS_A_INDEX], BYTE_LENGTH_CURVE_25519);
292     LOG_AND_GOTO_CLEANUP_IF_FAIL(status, "Elligator error3");
293 
294     status = CalTmpParab(&tmpBnB, &paraBnP, hash, hashLength);
295     LOG_AND_GOTO_CLEANUP_IF_FAIL(status, "Elligator error4");
296     status = CalTmpParaX(&tmpBnA, &tmpBnB, &paraBnP);
297     LOG_AND_GOTO_CLEANUP_IF_FAIL(status, "Elligator error5");
298 
299     status = mbedtls_mpi_sub_mpi(&tmpBnC, &paraBnP, &tmpBnB);
300     LOG_AND_GOTO_CLEANUP_IF_FAIL(status, "Elligator error6");
301     status = mbedtls_mpi_mod_mpi(&tmpBnC, &tmpBnC, &paraBnP);
302     LOG_AND_GOTO_CLEANUP_IF_FAIL(status, "Elligator error7");
303 
304     status = mbedtls_mpi_add_mpi(&tmpBnC, &tmpBnC, &paraBnNegA);
305     LOG_AND_GOTO_CLEANUP_IF_FAIL(status, "Elligator error8");
306     status = mbedtls_mpi_mod_mpi(&tmpBnC, &tmpBnC, &paraBnP);
307     LOG_AND_GOTO_CLEANUP_IF_FAIL(status, "Elligator error9");
308 
309     status = mbedtls_mpi_exp_mod(&tmpBnE, &tmpBnA, &paraBnSquare, &paraBnP, NULL);
310     LOG_AND_GOTO_CLEANUP_IF_FAIL(status, "Elligator error10");
311 
312     uint8_t swap = (mbedtls_mpi_cmp_mpi(&paraBnSquare, &tmpBnE) == 1);
313     status = mbedtls_mpi_safe_cond_swap(&tmpBnB, &tmpBnC, swap);
314     LOG_AND_GOTO_CLEANUP_IF_FAIL(status, "Elligator error11");
315 
316     status = mbedtls_mpi_write_binary(&tmpBnC, point, pointLength);
317     LOG_AND_GOTO_CLEANUP_IF_FAIL(status, "Elligator error12");
318 
319     SwapEndian(point, pointLength);
320 CLEAN_UP:
321     mbedtls_mpi_free(&paraBnP);
322     mbedtls_mpi_free(&paraBnSquare);
323     FreeCleanFiveBns(&paraBnNegA, &tmpBnA, &tmpBnB, &tmpBnC, &tmpBnE);
324     return status;
325 }
326 
CalculateMessageDigest(mbedtls_md_type_t type,const Blob * input,Blob * output)327 static int32_t CalculateMessageDigest(mbedtls_md_type_t type, const Blob *input, Blob *output)
328 {
329     const mbedtls_md_info_t *info = mbedtls_md_info_from_type(type);
330     if (info == NULL) {
331         return HAL_ERR_NOT_SUPPORTED;
332     }
333 
334     uint32_t outSize = mbedtls_md_get_size(info);
335     if (output->dataSize < outSize) {
336         return HAL_ERR_SHORT_BUFFER;
337     }
338 
339     int32_t ret = mbedtls_md(info, input->data, input->dataSize, output->data);
340     LOG_AND_RETURN_IF_MBED_FAIL(ret, "Calculate message digest failed.\n");
341 
342     output->dataSize = outSize;
343     return HAL_SUCCESS;
344 }
345 
Sha256(const Blob * input,Blob * output)346 static int32_t Sha256(const Blob *input, Blob *output)
347 {
348     if (!IsValidBlob(input) || !IsValidBlob(output)) {
349         LOGE("Input params for sha256 is invalid.");
350         return HAL_ERR_INVALID_PARAM;
351     }
352     return CalculateMessageDigest(MBEDTLS_MD_SHA256, input, output);
353 }
354 
ReadBigNums(mbedtls_mpi * x,mbedtls_mpi * y,const Blob * blob)355 static int32_t ReadBigNums(mbedtls_mpi *x, mbedtls_mpi *y, const Blob *blob)
356 {
357     int32_t ret = mbedtls_mpi_read_binary(x, blob->data, P256_KEY_SIZE);
358     LOG_AND_RETURN_IF_MBED_FAIL(ret, "Read x coordinate of public key failed.");
359     ret = mbedtls_mpi_read_binary(y, blob->data + P256_KEY_SIZE, P256_KEY_SIZE);
360     LOG_AND_RETURN_IF_MBED_FAIL(ret, "Read y coordinate of public key failed.");
361     return HAL_SUCCESS;
362 }
363 
ReadEcPublicKey(mbedtls_ecp_point * point,const Blob * publicKey)364 static int32_t ReadEcPublicKey(mbedtls_ecp_point *point, const Blob *publicKey)
365 {
366     int32_t ret = ReadBigNums(&point->MBEDTLS_PRIVATE(X), &point->MBEDTLS_PRIVATE(Y), publicKey);
367     LOG_AND_RETURN_IF_MBED_FAIL(ret, "Read coordinate of public key failed.");
368     ret = mbedtls_mpi_lset(&point->MBEDTLS_PRIVATE(Z), 1);
369     LOG_AND_RETURN_IF_MBED_FAIL(ret, "Lset point z failed.");
370     return HAL_SUCCESS;
371 }
372 
WriteOutBigNums(const mbedtls_mpi * x,const mbedtls_mpi * y,Blob * out)373 static int32_t WriteOutBigNums(const mbedtls_mpi *x, const mbedtls_mpi *y, Blob *out)
374 {
375     int32_t ret = mbedtls_mpi_write_binary(x, out->data, P256_KEY_SIZE);
376     LOG_AND_RETURN_IF_MBED_FAIL(ret, "Write x coordinate of public key failed.");
377 
378     ret = mbedtls_mpi_write_binary(y, out->data + P256_KEY_SIZE, P256_KEY_SIZE);
379     LOG_AND_RETURN_IF_MBED_FAIL(ret, "Write y coordinate of public key failed.");
380 
381     out->dataSize = P256_PUBLIC_SIZE;
382     return HAL_SUCCESS;
383 }
384 
WriteOutEcPublicKey(const mbedtls_ecp_point * point,Blob * publicKey)385 static int32_t WriteOutEcPublicKey(const mbedtls_ecp_point *point, Blob *publicKey)
386 {
387     return WriteOutBigNums(&point->MBEDTLS_PRIVATE(X), &point->MBEDTLS_PRIVATE(Y), publicKey);
388 }
389 
EcKeyAgreementLog(mbedtls_ecp_keypair * keyPair,mbedtls_ecp_point * p,mbedtls_ctr_drbg_context * ctrDrbg)390 static int EcKeyAgreementLog(mbedtls_ecp_keypair *keyPair, mbedtls_ecp_point *p, mbedtls_ctr_drbg_context *ctrDrbg)
391 {
392     return mbedtls_ecp_mul_restartable(&keyPair->MBEDTLS_PRIVATE(grp), p, &keyPair->MBEDTLS_PRIVATE(d),
393         &keyPair->MBEDTLS_PRIVATE(Q), mbedtls_ctr_drbg_random, ctrDrbg, NULL);
394 }
395 
EcKeyAgreement(const Blob * privateKey,const Blob * publicKey,Blob * secretKey)396 static int32_t EcKeyAgreement(const Blob *privateKey, const Blob *publicKey, Blob *secretKey)
397 {
398     if (!IsValidBlob(publicKey) || publicKey->dataSize != P256_PUBLIC_SIZE || !IsValidBlob(secretKey) ||
399         secretKey->dataSize != P256_PUBLIC_SIZE || !IsValidBlob(privateKey)) {
400         LOGE("Input params for ec key agree is invalid.");
401         return HAL_ERR_INVALID_PARAM;
402     }
403     mbedtls_mpi *secret = HcMalloc(sizeof(mbedtls_mpi), 0);
404     mbedtls_ecp_keypair *keyPair = HcMalloc(sizeof(mbedtls_ecp_keypair), 0);
405     mbedtls_entropy_context *entropy = HcMalloc(sizeof(mbedtls_entropy_context), 0);
406     mbedtls_ctr_drbg_context *ctrDrbg = HcMalloc(sizeof(mbedtls_ctr_drbg_context), 0);
407     if ((secret == NULL) || (keyPair == NULL) || (entropy == NULL) || (ctrDrbg == NULL)) {
408         LOGE("Malloc for mbedtls ec key param failed.");
409         HcFree(secret);
410         HcFree(keyPair);
411         HcFree(entropy);
412         HcFree(ctrDrbg);
413         return HAL_ERR_BAD_ALLOC;
414     }
415     mbedtls_mpi_init(secret);
416     mbedtls_ecp_keypair_init(keyPair);
417     mbedtls_entropy_init(entropy);
418     mbedtls_ctr_drbg_init(ctrDrbg);
419     mbedtls_ecp_point p;
420     mbedtls_ecp_point_init(&p);
421     int32_t ret = ReadEcPublicKey(&keyPair->MBEDTLS_PRIVATE(Q), publicKey);
422     LOG_AND_GOTO_CLEANUP_IF_FAIL(ret, "Read the public key failed.\n");
423     ret = mbedtls_ecp_group_load(&keyPair->MBEDTLS_PRIVATE(grp), MBEDTLS_ECP_DP_SECP256R1);
424     LOG_AND_GOTO_CLEANUP_IF_FAIL(ret, "Load the ecp group failed.\n");
425     ret = mbedtls_mpi_read_binary(&keyPair->MBEDTLS_PRIVATE(d), privateKey->data, privateKey->dataSize);
426     LOG_AND_GOTO_CLEANUP_IF_FAIL(ret, "Read the private key failed.\n");
427     ret = mbedtls_ctr_drbg_seed(ctrDrbg, mbedtls_entropy_func, entropy,
428         RANDOM_SEED_CUSTOM, sizeof(RANDOM_SEED_CUSTOM));
429     LOG_AND_GOTO_CLEANUP_IF_FAIL(ret, "Set custom string failed.\n");
430     LOG_AND_GOTO_CLEANUP_IF_FAIL(EcKeyAgreementLog(keyPair, &p, ctrDrbg), "Compute secret key failed.\n");
431     LOG_AND_GOTO_CLEANUP_IF_FAIL(mbedtls_mpi_copy(secret, &p.MBEDTLS_PRIVATE(X)), "Copy secret failed.\n");
432     LOG_AND_GOTO_CLEANUP_IF_FAIL(WriteOutEcPublicKey(&p, secretKey), "Write out ec public key failed.\n");
433 CLEAN_UP:
434     mbedtls_mpi_free(secret);
435     mbedtls_ecp_keypair_free(keyPair);
436     mbedtls_entropy_free(entropy);
437     mbedtls_ctr_drbg_free(ctrDrbg);
438     mbedtls_ecp_point_free(&p);
439     HcFree(secret);
440     HcFree(keyPair);
441     HcFree(entropy);
442     HcFree(ctrDrbg);
443     LOG_AND_RETURN_IF_MBED_FAIL(ret, "Ec key agree failed.");
444     return HAL_SUCCESS;
445 }
446 
EcHashToPoint(const Blob * hash,Blob * point)447 static int32_t EcHashToPoint(const Blob *hash, Blob *point)
448 {
449     mbedtls_mpi scalarA;
450     mbedtls_mpi scalarB;
451     mbedtls_ecp_point pointA;
452     mbedtls_ecp_point pointB;
453     mbedtls_ecp_point result;
454     InitPointParams(&scalarA, &scalarB, &pointA, &pointB, &result);
455 
456     mbedtls_ecp_group grp;
457     mbedtls_ecp_group_init(&grp);
458     uint8_t digest[SHA256_HASH_LEN] = { 0 };
459     Blob digestBlob = { sizeof(digest), digest };
460 
461     int32_t ret = mbedtls_ecp_group_load(&grp, MBEDTLS_ECP_DP_SECP256R1);
462     LOG_AND_GOTO_CLEANUP_IF_FAIL(ret, "Load ecp group failed.\n");
463     ret = mbedtls_ecp_point_read_binary(&grp, &pointA, POINT_A, sizeof(POINT_A));
464     LOG_AND_GOTO_CLEANUP_IF_FAIL(ret, "Read point A failed.\n");
465     ret = mbedtls_ecp_point_read_binary(&grp, &pointB, POINT_B, sizeof(POINT_B));
466     LOG_AND_GOTO_CLEANUP_IF_FAIL(ret, "Read point B failed.\n");
467     ret = Sha256(hash, &digestBlob);
468     LOG_AND_GOTO_CLEANUP_IF_FAIL(ret, "Compute message digest failed.\n");
469     ret = mbedtls_mpi_lset(&scalarA, 1);
470     LOG_AND_GOTO_CLEANUP_IF_FAIL(ret, "Set number one failed.\n");
471     ret = mbedtls_mpi_read_binary(&scalarB, digest, SHA256_HASH_LEN);
472     LOG_AND_GOTO_CLEANUP_IF_FAIL(ret, "Read digest failed.\n");
473     ret = mbedtls_ecp_muladd(&grp, &result, &scalarA, &pointA, &scalarB, &pointB);
474     LOG_AND_GOTO_CLEANUP_IF_FAIL(ret, "Double-scalar multiplication failed.\n");
475     ret = mbedtls_ecp_check_pubkey(&grp, &result);
476     LOG_AND_GOTO_CLEANUP_IF_FAIL(ret, "Invalid point on P256 is returned.\n");
477     ret = WriteOutEcPublicKey(&result, point);
478     LOG_AND_GOTO_CLEANUP_IF_FAIL(ret, "Write out public key failed.\n");
479 CLEAN_UP:
480     FreePointParams(&scalarA, &scalarB, &pointA, &pointB, &result);
481     mbedtls_ecp_group_free(&grp);
482     LOG_AND_RETURN_IF_MBED_FAIL(ret, "Ec hash to point failed.");
483     return HAL_SUCCESS;
484 }
485 
486 // only support P256 HashToPoint for standard system
MbedtlsHashToPoint(const Uint8Buff * hash,Uint8Buff * outEcPoint)487 int32_t MbedtlsHashToPoint(const Uint8Buff *hash, Uint8Buff *outEcPoint)
488 {
489     CHECK_PTR_RETURN_HAL_ERROR_CODE(hash, "hash");
490     CHECK_PTR_RETURN_HAL_ERROR_CODE(hash->val, "hash->val");
491     CHECK_LEN_EQUAL_RETURN(hash->length, SHA256_LEN, "hash->length");
492     CHECK_PTR_RETURN_HAL_ERROR_CODE(outEcPoint, "outEcPoint");
493     CHECK_PTR_RETURN_HAL_ERROR_CODE(outEcPoint->val, "outEcPoint->val");
494     CHECK_LEN_EQUAL_RETURN(outEcPoint->length, EC_LEN, "outEcPoint->length");
495 
496     struct Blob hashBlob = {
497         .dataSize = hash->length,
498         .data = hash->val
499     };
500     struct Blob pointBlob = {
501         .dataSize = outEcPoint->length,
502         .data = outEcPoint->val
503     };
504 
505     int32_t ret = EcHashToPoint(&hashBlob, &pointBlob);
506     if (ret != 0 || pointBlob.dataSize != EC_LEN) {
507         LOGE("HashToPoint with mbedtls for P256 failed, ret: %d", ret);
508         return HAL_FAILED;
509     }
510 
511     return HAL_SUCCESS;
512 }
513 
MbedtlsHashToPoint25519(const Uint8Buff * hash,Uint8Buff * outEcPoint)514 int32_t MbedtlsHashToPoint25519(const Uint8Buff *hash, Uint8Buff *outEcPoint)
515 {
516     if (!IsValidUint8Buff(hash) || !IsValidUint8Buff(outEcPoint)) {
517         return HAL_ERR_INVALID_PARAM;
518     }
519     if (hash->length != BYTE_LENGTH_CURVE_25519 || outEcPoint->length != BYTE_LENGTH_CURVE_25519) {
520         LOGE("MbedtlsHashToPoint invalid length.");
521         return HAL_ERR_INVALID_PARAM;
522     }
523     uint8_t hashTmp[BYTE_LENGTH_CURVE_25519] = { 0 };
524     (void)memcpy_s(hashTmp, BYTE_LENGTH_CURVE_25519, hash->val, BYTE_LENGTH_CURVE_25519);
525 
526     hashTmp[BYTE_LENGTH_CURVE_25519 - 1] &= ~HASH2POINT_PARA_PREPRO;
527     SwapEndian(hashTmp, BYTE_LENGTH_CURVE_25519);
528     int status = Elligator(outEcPoint->val, BYTE_LENGTH_CURVE_25519, hashTmp, BYTE_LENGTH_CURVE_25519);
529     if (status != 0) {
530         LOGE("Elligator failed, status:%d", status);
531     }
532     return status;
533 }
534 
535 // only support P256 AgreeSharedSecret for standard system
MbedtlsAgreeSharedSecret(const KeyBuff * priKey,const KeyBuff * pubKey,Uint8Buff * sharedKey)536 int32_t MbedtlsAgreeSharedSecret(const KeyBuff *priKey, const KeyBuff *pubKey, Uint8Buff *sharedKey)
537 {
538     CHECK_PTR_RETURN_HAL_ERROR_CODE(priKey, "priKey");
539     CHECK_PTR_RETURN_HAL_ERROR_CODE(priKey->key, "priKey->key");
540     CHECK_LEN_ZERO_RETURN_ERROR_CODE(priKey->keyLen, "priKey->keyLen");
541     CHECK_PTR_RETURN_HAL_ERROR_CODE(pubKey, "devicePk");
542     CHECK_PTR_RETURN_HAL_ERROR_CODE(pubKey->key, "devicePk->key");
543     CHECK_LEN_ZERO_RETURN_ERROR_CODE(pubKey->keyLen, "devicePk->keyLen");
544     CHECK_PTR_RETURN_HAL_ERROR_CODE(sharedKey, "sharedKey");
545     CHECK_PTR_RETURN_HAL_ERROR_CODE(sharedKey->val, "sharedKey->val");
546     CHECK_LEN_ZERO_RETURN_ERROR_CODE(sharedKey->length, "sharedKey->length");
547 
548     struct Blob priKeyBlob = {
549         .dataSize = priKey->keyLen,
550         .data = priKey->key
551     };
552     struct Blob pubKeyBlob = {
553         .dataSize = pubKey->keyLen,
554         .data = pubKey->key
555     };
556     struct Blob sharedKeyBlob = {
557         .dataSize = sharedKey->length,
558         .data = sharedKey->val
559     };
560     int32_t ret = EcKeyAgreement(&priKeyBlob, &pubKeyBlob, &sharedKeyBlob);
561     if (ret != 0) {
562         LOGE("Agree key failed, ret = %d", ret);
563         return HAL_FAILED;
564     }
565     return HAL_SUCCESS;
566 }
567