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/base64.h>
19  #include <mbedtls/bignum.h>
20  #include <mbedtls/ctr_drbg.h>
21  #include <mbedtls/entropy.h>
22  #include <mbedtls/error.h>
23  #include <mbedtls/pk.h>
24  #include <mbedtls/x509.h>
25  
26  #include "hal_error.h"
27  #include "hc_log.h"
28  #include "huks_adapter.h"
29  
30  #define LOG_AND_RETURN_IF_MBED_FAIL(ret, fmt, ...) \
31  do { \
32      if ((ret) != 0) { \
33          LOGE(fmt, ##__VA_ARGS__); \
34          return HAL_ERR_MBEDTLS; \
35      } \
36  } while (0)
37  
38  #define LOG_AND_GOTO_CLEANUP_IF_FAIL(ret, fmt, ...) \
39  do { \
40      if ((ret) != 0) { \
41          LOGE(fmt, ##__VA_ARGS__); \
42          goto CLEAN_UP; \
43      } \
44  } while (0)
45  
46  #define LEN_HALF_DIVISOR 2
47  #define BITS_PER_BYTE 8
48  #define EC_LEN 64
49  #define SHA256_HASH_LEN 32
50  #define P256_KEY_SIZE 32
51  #define P256_PUBLIC_SIZE 64 // P256_KEY_SIZE * 2
52  #define PARAM_A_INDEX 2
53  #define PARAM_U_INDEX 4
54  #define PARAM_MINUS_A_INDEX 3
55  #define PARAM_ONE_INDEX 5
56  #define HASH_TO_POINT_PARA_NUMS 6
57  
58  typedef struct Blob {
59      uint32_t dataSize;
60      uint8_t *data;
61  } Blob;
62  
63  static const uint8_t POINT_A[] = {
64      0x04, 0x53, 0xf9, 0xe4, 0xf4, 0xbc, 0x3a, 0xb5, 0x9d, 0x44, 0x78, 0x45, 0x21, 0x13, 0x8b, 0x49,
65      0xba, 0xa3, 0x1c, 0xe2, 0xa8, 0xdb, 0xbd, 0xb8, 0xd6, 0x73, 0x31, 0x46, 0x3a, 0x69, 0x53, 0xf1,
66      0xed, 0xef, 0x96, 0x1e, 0xdb, 0x42, 0xbe, 0x3a, 0x24, 0x43, 0xc4, 0x08, 0x23, 0xfb, 0x58, 0xee,
67      0x61, 0x24, 0x8b, 0x59, 0x64, 0x65, 0x2d, 0xbc, 0x6b, 0xa5, 0x1d, 0x6e, 0x04, 0x22, 0x53, 0xae,
68      0x27
69  };
70  static const uint8_t POINT_B[] = {
71      0x04, 0x03, 0x4d, 0x11, 0x11, 0xa6, 0x3f, 0x5f, 0x72, 0x43, 0x59, 0x73, 0x8b, 0x46, 0xc3, 0xfd,
72      0x70, 0x58, 0xb0, 0xb6, 0x11, 0xd3, 0x4f, 0xf3, 0x49, 0xa0, 0xd2, 0x86, 0xd7, 0x35, 0x33, 0xc5,
73      0x36, 0xe4, 0x99, 0xcc, 0x13, 0x47, 0xe4, 0xab, 0xde, 0x8f, 0x3a, 0xd6, 0x65, 0x1a, 0x77, 0x0b,
74      0xc4, 0x82, 0xd5, 0xac, 0x4b, 0x5d, 0xe4, 0xcc, 0x48, 0xb0, 0x54, 0x6c, 0x9b, 0x76, 0x76, 0x1a,
75      0xba
76  };
77  
78  static uint8_t g_hash2pointParas[HASH_TO_POINT_PARA_NUMS][BYTE_LENGTH_CURVE_25519] = {
79      { 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,    /* 0:p */
80        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
81        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
82        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xed },
83      { 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,    /* 1:divide_minus_p_1_2 */
84        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
85        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
86        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf6 },
87      { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,    /* 2:A */
88        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
89        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
90        0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x6d, 0x06 },
91      { 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,    /* 3:-A */
92        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
93        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
94        0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x92, 0xe7 },
95      { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,    /* 4:u = 2 */
96        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
97        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
98        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 },
99      { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,    /* 5:1 */
100        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
101        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
102        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 },
103  };
104  
105  static const uint8_t RANDOM_SEED_CUSTOM[] = { 0x4C, 0x54, 0x4B, 0x53 }; // LTKS means LiteKeystore
106  
IsValidBlob(const Blob * blob)107  static bool IsValidBlob(const Blob *blob)
108  {
109      return (blob != NULL) && (blob->data != NULL) && (blob->dataSize != 0);
110  }
111  
IsValidUint8Buff(const Uint8Buff * buff)112  static bool IsValidUint8Buff(const Uint8Buff *buff)
113  {
114      return (buff != NULL) && (buff->val != NULL) && (buff->length != 0);
115  }
116  
InitPointParams(mbedtls_mpi * scalarA,mbedtls_mpi * scalarB,mbedtls_ecp_point * pointA,mbedtls_ecp_point * pointB,mbedtls_ecp_point * result)117  static void InitPointParams(mbedtls_mpi *scalarA, mbedtls_mpi *scalarB, mbedtls_ecp_point *pointA,
118      mbedtls_ecp_point *pointB, mbedtls_ecp_point *result)
119  {
120      mbedtls_mpi_init(scalarA);
121      mbedtls_mpi_init(scalarB);
122      mbedtls_ecp_point_init(pointA);
123      mbedtls_ecp_point_init(pointB);
124      mbedtls_ecp_point_init(result);
125  }
126  
FreePointParams(mbedtls_mpi * scalarA,mbedtls_mpi * scalarB,mbedtls_ecp_point * pointA,mbedtls_ecp_point * pointB,mbedtls_ecp_point * result)127  static void FreePointParams(mbedtls_mpi *scalarA, mbedtls_mpi *scalarB, mbedtls_ecp_point *pointA,
128      mbedtls_ecp_point *pointB, mbedtls_ecp_point *result)
129  {
130      mbedtls_mpi_free(scalarA);
131      mbedtls_mpi_free(scalarB);
132      mbedtls_ecp_point_free(pointA);
133      mbedtls_ecp_point_free(pointB);
134      mbedtls_ecp_point_free(result);
135  }
136  
SwapEndian(uint8_t * pubKey,int len)137  static void SwapEndian(uint8_t *pubKey, int len)
138  {
139      if ((pubKey == NULL) || (len <= 0)) {
140          return;
141      }
142      for (int i = 0; i < len / LEN_HALF_DIVISOR; ++i) {
143          uint8_t tmp = pubKey[i];
144          pubKey[i] = pubKey[len - i - 1];
145          pubKey[len - i - 1] = tmp;
146      }
147  }
148  
FreeCleanFiveBns(mbedtls_mpi * bn1,mbedtls_mpi * bn2,mbedtls_mpi * bn3,mbedtls_mpi * bn4,mbedtls_mpi * bn5)149  static void FreeCleanFiveBns(mbedtls_mpi *bn1, mbedtls_mpi *bn2, mbedtls_mpi *bn3,
150                               mbedtls_mpi *bn4, mbedtls_mpi *bn5)
151  {
152      mbedtls_mpi_free(bn1);
153      mbedtls_mpi_free(bn2);
154      mbedtls_mpi_free(bn3);
155      mbedtls_mpi_free(bn4);
156      mbedtls_mpi_free(bn5);
157  }
158  
CalTmpParaX(mbedtls_mpi * tmpY,const mbedtls_mpi * tmpX,const mbedtls_mpi * modP)159  static int32_t CalTmpParaX(mbedtls_mpi *tmpY, const mbedtls_mpi *tmpX, const mbedtls_mpi *modP)
160  {
161      int32_t status;
162      mbedtls_mpi tmpBnA;
163      mbedtls_mpi tmpBnB;
164      mbedtls_mpi tmpBnC;
165      mbedtls_mpi tmpBnE;
166      mbedtls_mpi paraBnA;
167      mbedtls_mpi paraBnU;
168  
169      mbedtls_mpi_init(&tmpBnA);
170      mbedtls_mpi_init(&tmpBnB);
171      mbedtls_mpi_init(&tmpBnC);
172      mbedtls_mpi_init(&tmpBnE);
173      mbedtls_mpi_init(&paraBnA);
174      mbedtls_mpi_init(&paraBnU);
175  
176      status = mbedtls_mpi_read_binary(&paraBnA, g_hash2pointParas[PARAM_A_INDEX], BYTE_LENGTH_CURVE_25519);
177      LOG_AND_GOTO_CLEANUP_IF_FAIL(status, "CalTmpParaX error1");
178  
179      status = mbedtls_mpi_read_binary(&paraBnU, g_hash2pointParas[PARAM_U_INDEX], BYTE_LENGTH_CURVE_25519);
180      LOG_AND_GOTO_CLEANUP_IF_FAIL(status, "CalTmpParaX error2");
181  
182      status = mbedtls_mpi_copy(&tmpBnB, tmpX);
183      LOG_AND_GOTO_CLEANUP_IF_FAIL(status, "CalTmpParaX error3");
184      /* a := b ^ 3 + A * b ^ 2 + b */
185  
186      status = mbedtls_mpi_exp_mod(&tmpBnE, &tmpBnB, &paraBnU, modP, NULL);
187      LOG_AND_GOTO_CLEANUP_IF_FAIL(status, "CalTmpParaX error4"); // b^2
188  
189      status = mbedtls_mpi_mul_mpi(&tmpBnC, &tmpBnE, &tmpBnB);
190      LOG_AND_GOTO_CLEANUP_IF_FAIL(status, "CalTmpParaX error5");
191      status = mbedtls_mpi_mod_mpi(&tmpBnC, &tmpBnC, modP);
192      LOG_AND_GOTO_CLEANUP_IF_FAIL(status, "CalTmpParaX error6"); // b^3
193  
194      status = mbedtls_mpi_mul_mpi(&tmpBnA, &tmpBnE, &paraBnA); // A*b^2
195      LOG_AND_GOTO_CLEANUP_IF_FAIL(status, "CalTmpParaX error7");
196      status = mbedtls_mpi_mod_mpi(&tmpBnA, &tmpBnA, modP);
197      LOG_AND_GOTO_CLEANUP_IF_FAIL(status, "CalTmpParaX error8");
198  
199      status = mbedtls_mpi_add_mpi(&tmpBnE, &tmpBnC, &tmpBnA); // b^3 + A*b^2
200      LOG_AND_GOTO_CLEANUP_IF_FAIL(status, "CalTmpParaX error9");
201      status = mbedtls_mpi_mod_mpi(&tmpBnE, &tmpBnE, modP);
202      LOG_AND_GOTO_CLEANUP_IF_FAIL(status, "CalTmpParaX error10");
203  
204      status = mbedtls_mpi_add_mpi(tmpY, &tmpBnE, &tmpBnB); // b^3 + A*b^2 + b
205      LOG_AND_GOTO_CLEANUP_IF_FAIL(status, "CalTmpParaX error11");
206      status = mbedtls_mpi_mod_mpi(tmpY, tmpY, modP);
207      LOG_AND_GOTO_CLEANUP_IF_FAIL(status, "CalTmpParaX error12");
208  
209  CLEAN_UP:
210      FreeCleanFiveBns(&paraBnA, &tmpBnA, &tmpBnB, &tmpBnC, &tmpBnE);
211      mbedtls_mpi_free(&paraBnU);
212      return status;
213  }
214  
CalTmpParab(mbedtls_mpi * tmpX,const mbedtls_mpi * modP,const uint8_t * hash,uint32_t hashLen)215  static int32_t CalTmpParab(mbedtls_mpi *tmpX, const mbedtls_mpi *modP, const uint8_t *hash, uint32_t hashLen)
216  {
217      int32_t status;
218      mbedtls_mpi paraBnNegA;
219      mbedtls_mpi paraBNOne;
220      mbedtls_mpi paraBnU;
221      mbedtls_mpi tmpBnA;
222      mbedtls_mpi tmpBnB;
223  
224      mbedtls_mpi_init(&paraBnNegA);
225      mbedtls_mpi_init(&paraBNOne);
226      mbedtls_mpi_init(&paraBnU);
227      mbedtls_mpi_init(&tmpBnA);
228      mbedtls_mpi_init(&tmpBnB);
229  
230      status = mbedtls_mpi_read_binary(&paraBnNegA, g_hash2pointParas[PARAM_MINUS_A_INDEX], BYTE_LENGTH_CURVE_25519);
231      LOG_AND_GOTO_CLEANUP_IF_FAIL(status, "CalTmpParab error1");
232      status = mbedtls_mpi_read_binary(&paraBNOne, g_hash2pointParas[PARAM_ONE_INDEX], BYTE_LENGTH_CURVE_25519);
233      LOG_AND_GOTO_CLEANUP_IF_FAIL(status, "CalTmpParab error2");
234      status = mbedtls_mpi_read_binary(&paraBnU, g_hash2pointParas[PARAM_U_INDEX], BYTE_LENGTH_CURVE_25519);
235      LOG_AND_GOTO_CLEANUP_IF_FAIL(status, "CalTmpParab error3");
236      status = mbedtls_mpi_read_binary(&tmpBnA, hash, hashLen);
237      LOG_AND_GOTO_CLEANUP_IF_FAIL(status, "CalTmpParab error4");
238  
239      /* b := -A / (1 + u * a ^ 2) */
240      status = mbedtls_mpi_exp_mod(&tmpBnB, &tmpBnA, &paraBnU, modP, NULL);
241      LOG_AND_GOTO_CLEANUP_IF_FAIL(status, "CalTmpParab error5");
242  
243      status = mbedtls_mpi_mul_mpi(&tmpBnA, &tmpBnB, &paraBnU);
244      LOG_AND_GOTO_CLEANUP_IF_FAIL(status, "CalTmpParab error6");
245      status = mbedtls_mpi_mod_mpi(&tmpBnA, &tmpBnA, modP);
246      LOG_AND_GOTO_CLEANUP_IF_FAIL(status, "CalTmpParab error7");
247  
248      status = mbedtls_mpi_add_mpi(&tmpBnB, &tmpBnA, &paraBNOne);
249      LOG_AND_GOTO_CLEANUP_IF_FAIL(status, "CalTmpParab error8");
250      status = mbedtls_mpi_mod_mpi(&tmpBnB, &tmpBnB, modP);
251      LOG_AND_GOTO_CLEANUP_IF_FAIL(status, "CalTmpParab error9");
252  
253      status = mbedtls_mpi_inv_mod(&tmpBnA, &tmpBnB, modP);
254      LOG_AND_GOTO_CLEANUP_IF_FAIL(status, "CalTmpParab error10");
255  
256      status = mbedtls_mpi_mul_mpi(tmpX, &tmpBnA, &paraBnNegA);
257      LOG_AND_GOTO_CLEANUP_IF_FAIL(status, "CalTmpParab error11");
258      status = mbedtls_mpi_mod_mpi(tmpX, tmpX, modP);
259      LOG_AND_GOTO_CLEANUP_IF_FAIL(status, "CalTmpParab error12");
260  CLEAN_UP:
261      FreeCleanFiveBns(&paraBnNegA, &paraBNOne, &paraBnU, &tmpBnA, &tmpBnB);
262      return status;
263  }
264  
265  /*
266   * hash2point function, use BoringSSL big number algorithm library;
267   * p_point(little endian): the output pointer of Curve25519 point;
268   * p_hash (little endian): the input pointer of string;
269   */
Elligator(unsigned char * point,int pointLength,const unsigned char * hash,int hashLength)270  static int32_t Elligator(unsigned char *point, int pointLength, const unsigned char *hash, int hashLength)
271  {
272      mbedtls_mpi paraBnP;
273      mbedtls_mpi paraBnSquare;
274      mbedtls_mpi paraBnNegA;
275      mbedtls_mpi tmpBnA;
276      mbedtls_mpi tmpBnB;
277      mbedtls_mpi tmpBnC;
278      mbedtls_mpi tmpBnE;
279  
280      mbedtls_mpi_init(&paraBnP);
281      mbedtls_mpi_init(&paraBnSquare);
282      mbedtls_mpi_init(&paraBnNegA);
283      mbedtls_mpi_init(&tmpBnA);
284      mbedtls_mpi_init(&tmpBnB);
285      mbedtls_mpi_init(&tmpBnC);
286      mbedtls_mpi_init(&tmpBnE);
287  
288      int32_t status = mbedtls_mpi_read_binary(&paraBnP, g_hash2pointParas[0], BYTE_LENGTH_CURVE_25519);
289      LOG_AND_GOTO_CLEANUP_IF_FAIL(status, "Elligator error1");
290      status = mbedtls_mpi_read_binary(&paraBnSquare, g_hash2pointParas[1], BYTE_LENGTH_CURVE_25519);
291      LOG_AND_GOTO_CLEANUP_IF_FAIL(status, "Elligator error2");
292      status = mbedtls_mpi_read_binary(&paraBnNegA, g_hash2pointParas[PARAM_MINUS_A_INDEX], BYTE_LENGTH_CURVE_25519);
293      LOG_AND_GOTO_CLEANUP_IF_FAIL(status, "Elligator error3");
294  
295      status = CalTmpParab(&tmpBnB, &paraBnP, hash, hashLength);
296      LOG_AND_GOTO_CLEANUP_IF_FAIL(status, "Elligator error4");
297      status = CalTmpParaX(&tmpBnA, &tmpBnB, &paraBnP);
298      LOG_AND_GOTO_CLEANUP_IF_FAIL(status, "Elligator error5");
299  
300      status = mbedtls_mpi_sub_mpi(&tmpBnC, &paraBnP, &tmpBnB);
301      LOG_AND_GOTO_CLEANUP_IF_FAIL(status, "Elligator error6");
302      status = mbedtls_mpi_mod_mpi(&tmpBnC, &tmpBnC, &paraBnP);
303      LOG_AND_GOTO_CLEANUP_IF_FAIL(status, "Elligator error7");
304  
305      status = mbedtls_mpi_add_mpi(&tmpBnC, &tmpBnC, &paraBnNegA);
306      LOG_AND_GOTO_CLEANUP_IF_FAIL(status, "Elligator error8");
307      status = mbedtls_mpi_mod_mpi(&tmpBnC, &tmpBnC, &paraBnP);
308      LOG_AND_GOTO_CLEANUP_IF_FAIL(status, "Elligator error9");
309  
310      status = mbedtls_mpi_exp_mod(&tmpBnE, &tmpBnA, &paraBnSquare, &paraBnP, NULL);
311      LOG_AND_GOTO_CLEANUP_IF_FAIL(status, "Elligator error10");
312  
313      status = mbedtls_mpi_safe_cond_swap(&tmpBnB, &tmpBnC, (mbedtls_mpi_cmp_mpi(&paraBnSquare, &tmpBnE) == 1));
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  
MbedtlsBase64Encode(const uint8_t * byte,uint32_t byteLen,char * base64Str,uint32_t strLen,uint32_t * outLen)568  int32_t MbedtlsBase64Encode(const uint8_t *byte, uint32_t byteLen, char *base64Str, uint32_t strLen, uint32_t *outLen)
569  {
570      CHECK_PTR_RETURN_HAL_ERROR_CODE(byte, "byte");
571      CHECK_LEN_ZERO_RETURN_ERROR_CODE(byteLen, "byteLen");
572      CHECK_PTR_RETURN_HAL_ERROR_CODE(base64Str, "base64Str");
573      CHECK_LEN_ZERO_RETURN_ERROR_CODE(strLen, "strLen");
574      CHECK_PTR_RETURN_HAL_ERROR_CODE(outLen, "outLen");
575  
576      size_t needBuffLen = 0;
577      (void)mbedtls_base64_encode(NULL, 0, &needBuffLen, byte, byteLen);
578      if (needBuffLen > strLen) {
579          LOGE("The content to be written is larger than the input buffer size. Need: %zd, Buffer: %u",
580              needBuffLen, strLen);
581          return HAL_ERR_SHORT_BUFFER;
582      }
583  
584      int res = mbedtls_base64_encode((unsigned char *)base64Str, strLen, &needBuffLen, byte, byteLen);
585      if (res != 0) {
586          LOGE("call mbedtls's mbedtls_base64_encode fail. res: %d", res);
587          return HAL_ERR_MBEDTLS;
588      }
589  
590      *outLen = needBuffLen;
591      return HAL_SUCCESS;
592  }
593  
MbedtlsBase64Decode(const char * base64Str,uint32_t strLen,uint8_t * byte,uint32_t byteLen,uint32_t * outLen)594  int32_t MbedtlsBase64Decode(const char *base64Str, uint32_t strLen, uint8_t *byte, uint32_t byteLen, uint32_t *outLen)
595  {
596      CHECK_PTR_RETURN_HAL_ERROR_CODE(base64Str, "base64Str");
597      CHECK_LEN_ZERO_RETURN_ERROR_CODE(strLen, "strLen");
598      CHECK_PTR_RETURN_HAL_ERROR_CODE(byte, "byte");
599      CHECK_LEN_ZERO_RETURN_ERROR_CODE(byteLen, "byteLen");
600      CHECK_PTR_RETURN_HAL_ERROR_CODE(outLen, "outLen");
601  
602      size_t needBuffLen = 0;
603      int res = mbedtls_base64_decode(NULL, 0, &needBuffLen, (const unsigned char *)base64Str, strLen);
604      if (res == MBEDTLS_ERR_BASE64_INVALID_CHARACTER) {
605          LOGE("The input string is not in base64 encoding format.");
606          return HAL_ERR_BASE64_FORMAT;
607      }
608  
609      if (needBuffLen > byteLen) {
610          LOGE("The content to be written is larger than the input buffer size. Need: %zd, Buffer: %u",
611              needBuffLen, byteLen);
612          return HAL_ERR_SHORT_BUFFER;
613      }
614  
615      res = mbedtls_base64_decode(byte, byteLen, &needBuffLen, (const unsigned char *)base64Str, strLen);
616      if (res != 0) {
617          LOGE("call mbedtls's mbedtls_base64_decode fail. res: %d", res);
618          return HAL_ERR_MBEDTLS;
619      }
620  
621      *outLen = (uint32_t)needBuffLen;
622      return HAL_SUCCESS;
623  }
624