• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 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 #include "mbedtls_ec_adapter.h"
17 #include <stdio.h>
18 #include <mbedtls/bignum.h>
19 #include "securec.h"
20 #include "alg_defs.h"
21 #include "hal_error.h"
22 #include "hc_log.h"
23 
24 #define LEN_HALF_DIVISOR 2
25 #define PARAM_A_INDEX 2
26 #define PARAM_U_INDEX 4
27 #define PARAM_MINUS_A_INDEX 3
28 #define PARAM_ONE_INDEX 5
29 #define HASH_TO_POINT_PARA_NUMS 6
30 
31 #define LOG_AND_GOTO_CLEANUP_IF_FAIL(ret, fmt, ...) \
32 do { \
33     if ((ret) != 0) { \
34         LOGE(fmt, ##__VA_ARGS__); \
35         goto CLEAN_UP; \
36     } \
37 } while (0)
38 
39 static uint8_t g_hash2pointParas[HASH_TO_POINT_PARA_NUMS][BYTE_LENGTH_CURVE_25519] = {
40     { 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,    /* 0:p */
41       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
42       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
43       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xed },
44     { 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,    /* 1:divide_minus_p_1_2 */
45       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
46       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
47       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf6 },
48     { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,    /* 2:A */
49       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
50       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
51       0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x6d, 0x06 },
52     { 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,    /* 3:-A */
53       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
54       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
55       0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x92, 0xe7 },
56     { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,    /* 4:u = 2 */
57       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
58       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
59       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 },
60     { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,    /* 5:1 */
61       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
62       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
63       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 },
64 };
65 
FreeCleanFiveBns(mbedtls_mpi * bn1,mbedtls_mpi * bn2,mbedtls_mpi * bn3,mbedtls_mpi * bn4,mbedtls_mpi * bn5)66 static void FreeCleanFiveBns(mbedtls_mpi *bn1, mbedtls_mpi *bn2, mbedtls_mpi *bn3,
67                              mbedtls_mpi *bn4, mbedtls_mpi *bn5)
68 {
69     mbedtls_mpi_free(bn1);
70     mbedtls_mpi_free(bn2);
71     mbedtls_mpi_free(bn3);
72     mbedtls_mpi_free(bn4);
73     mbedtls_mpi_free(bn5);
74 }
75 
SwapEndian(uint8_t * pubKey,int len)76 static void SwapEndian(uint8_t *pubKey, int len)
77 {
78     if ((pubKey == NULL) || (len <= 0)) {
79         return;
80     }
81     for (int i = 0; i < len / LEN_HALF_DIVISOR; ++i) {
82         uint8_t tmp = pubKey[i];
83         pubKey[i] = pubKey[len - i - 1];
84         pubKey[len - i - 1] = tmp;
85     }
86 }
87 
IsInvalidBlob(const Uint8Buff * blob)88 static bool IsInvalidBlob(const Uint8Buff *blob)
89 {
90     return blob == NULL || blob->val == NULL || blob->length == 0;
91 }
92 
CalTmpParaX(mbedtls_mpi * tmpY,const mbedtls_mpi * tmpX,const mbedtls_mpi * modP)93 static int32_t CalTmpParaX(mbedtls_mpi *tmpY, const mbedtls_mpi *tmpX, const mbedtls_mpi *modP)
94 {
95     int32_t status;
96     mbedtls_mpi tmpBnA;
97     mbedtls_mpi tmpBnB;
98     mbedtls_mpi tmpBnC;
99     mbedtls_mpi tmpBnE;
100     mbedtls_mpi paraBnA;
101     mbedtls_mpi paraBnU;
102 
103     mbedtls_mpi_init(&tmpBnA);
104     mbedtls_mpi_init(&tmpBnB);
105     mbedtls_mpi_init(&tmpBnC);
106     mbedtls_mpi_init(&tmpBnE);
107     mbedtls_mpi_init(&paraBnA);
108     mbedtls_mpi_init(&paraBnU);
109 
110     status = mbedtls_mpi_read_binary(&paraBnA, g_hash2pointParas[PARAM_A_INDEX], BYTE_LENGTH_CURVE_25519);
111     LOG_AND_GOTO_CLEANUP_IF_FAIL(status, "CalTmpParaX error1");
112 
113     status = mbedtls_mpi_read_binary(&paraBnU, g_hash2pointParas[PARAM_U_INDEX], BYTE_LENGTH_CURVE_25519);
114     LOG_AND_GOTO_CLEANUP_IF_FAIL(status, "CalTmpParaX error2");
115 
116     status = mbedtls_mpi_copy(&tmpBnB, tmpX);
117     LOG_AND_GOTO_CLEANUP_IF_FAIL(status, "CalTmpParaX error3");
118     /* a := b ^ 3 + A * b ^ 2 + b */
119 
120     status = mbedtls_mpi_exp_mod(&tmpBnE, &tmpBnB, &paraBnU, modP, NULL);
121     LOG_AND_GOTO_CLEANUP_IF_FAIL(status, "CalTmpParaX error4"); // b^2
122 
123     status = mbedtls_mpi_mul_mpi(&tmpBnC, &tmpBnE, &tmpBnB);
124     LOG_AND_GOTO_CLEANUP_IF_FAIL(status, "CalTmpParaX error5");
125     status = mbedtls_mpi_mod_mpi(&tmpBnC, &tmpBnC, modP);
126     LOG_AND_GOTO_CLEANUP_IF_FAIL(status, "CalTmpParaX error6"); // b^3
127 
128     status = mbedtls_mpi_mul_mpi(&tmpBnA, &tmpBnE, &paraBnA); // A*b^2
129     LOG_AND_GOTO_CLEANUP_IF_FAIL(status, "CalTmpParaX error7");
130     status = mbedtls_mpi_mod_mpi(&tmpBnA, &tmpBnA, modP);
131     LOG_AND_GOTO_CLEANUP_IF_FAIL(status, "CalTmpParaX error8");
132 
133     status = mbedtls_mpi_add_mpi(&tmpBnE, &tmpBnC, &tmpBnA); // b^3 + A*b^2
134     LOG_AND_GOTO_CLEANUP_IF_FAIL(status, "CalTmpParaX error9");
135     status = mbedtls_mpi_mod_mpi(&tmpBnE, &tmpBnE, modP);
136     LOG_AND_GOTO_CLEANUP_IF_FAIL(status, "CalTmpParaX error10");
137 
138     status = mbedtls_mpi_add_mpi(tmpY, &tmpBnE, &tmpBnB); // b^3 + A*b^2 + b
139     LOG_AND_GOTO_CLEANUP_IF_FAIL(status, "CalTmpParaX error11");
140     status = mbedtls_mpi_mod_mpi(tmpY, tmpY, modP);
141     LOG_AND_GOTO_CLEANUP_IF_FAIL(status, "CalTmpParaX error12");
142 
143 CLEAN_UP:
144     FreeCleanFiveBns(&paraBnA, &tmpBnA, &tmpBnB, &tmpBnC, &tmpBnE);
145     mbedtls_mpi_free(&paraBnU);
146     return status;
147 }
148 
CalTmpParab(mbedtls_mpi * tmpX,const mbedtls_mpi * modP,const uint8_t * hash,uint32_t hashLen)149 static int32_t CalTmpParab(mbedtls_mpi *tmpX, const mbedtls_mpi *modP, const uint8_t *hash, uint32_t hashLen)
150 {
151     int32_t status;
152     mbedtls_mpi paraBnNegA;
153     mbedtls_mpi paraBNOne;
154     mbedtls_mpi paraBnU;
155     mbedtls_mpi tmpBnA;
156     mbedtls_mpi tmpBnB;
157 
158     mbedtls_mpi_init(&paraBnNegA);
159     mbedtls_mpi_init(&paraBNOne);
160     mbedtls_mpi_init(&paraBnU);
161     mbedtls_mpi_init(&tmpBnA);
162     mbedtls_mpi_init(&tmpBnB);
163 
164     status = mbedtls_mpi_read_binary(&paraBnNegA, g_hash2pointParas[PARAM_MINUS_A_INDEX], BYTE_LENGTH_CURVE_25519);
165     LOG_AND_GOTO_CLEANUP_IF_FAIL(status, "CalTmpParab error1");
166     status = mbedtls_mpi_read_binary(&paraBNOne, g_hash2pointParas[PARAM_ONE_INDEX], BYTE_LENGTH_CURVE_25519);
167     LOG_AND_GOTO_CLEANUP_IF_FAIL(status, "CalTmpParab error2");
168     status = mbedtls_mpi_read_binary(&paraBnU, g_hash2pointParas[PARAM_U_INDEX], BYTE_LENGTH_CURVE_25519);
169     LOG_AND_GOTO_CLEANUP_IF_FAIL(status, "CalTmpParab error3");
170     status = mbedtls_mpi_read_binary(&tmpBnA, hash, hashLen);
171     LOG_AND_GOTO_CLEANUP_IF_FAIL(status, "CalTmpParab error4");
172 
173     /* b := -A / (1 + u * a ^ 2) */
174     status = mbedtls_mpi_exp_mod(&tmpBnB, &tmpBnA, &paraBnU, modP, NULL);
175     LOG_AND_GOTO_CLEANUP_IF_FAIL(status, "CalTmpParab error5");
176 
177     status = mbedtls_mpi_mul_mpi(&tmpBnA, &tmpBnB, &paraBnU);
178     LOG_AND_GOTO_CLEANUP_IF_FAIL(status, "CalTmpParab error6");
179     status = mbedtls_mpi_mod_mpi(&tmpBnA, &tmpBnA, modP);
180     LOG_AND_GOTO_CLEANUP_IF_FAIL(status, "CalTmpParab error7");
181 
182     status = mbedtls_mpi_add_mpi(&tmpBnB, &tmpBnA, &paraBNOne);
183     LOG_AND_GOTO_CLEANUP_IF_FAIL(status, "CalTmpParab error8");
184     status = mbedtls_mpi_mod_mpi(&tmpBnB, &tmpBnB, modP);
185     LOG_AND_GOTO_CLEANUP_IF_FAIL(status, "CalTmpParab error9");
186 
187     status = mbedtls_mpi_inv_mod(&tmpBnA, &tmpBnB, modP);
188     LOG_AND_GOTO_CLEANUP_IF_FAIL(status, "CalTmpParab error10");
189 
190     status = mbedtls_mpi_mul_mpi(tmpX, &tmpBnA, &paraBnNegA);
191     LOG_AND_GOTO_CLEANUP_IF_FAIL(status, "CalTmpParab error11");
192     status = mbedtls_mpi_mod_mpi(tmpX, tmpX, modP);
193     LOG_AND_GOTO_CLEANUP_IF_FAIL(status, "CalTmpParab error12");
194 CLEAN_UP:
195     FreeCleanFiveBns(&paraBnNegA, &paraBNOne, &paraBnU, &tmpBnA, &tmpBnB);
196     return status;
197 }
198 
199 /*
200  * hash2point function, use BoringSSL big number algorithm library;
201  * p_point(little endian): the output pointer of Curve25519 point;
202  * p_hash (little endian): the input pointer of string;
203  */
Elligator(unsigned char * point,int pointLength,const unsigned char * hash,int hashLength)204 static int32_t Elligator(unsigned char *point, int pointLength, const unsigned char *hash, int hashLength)
205 {
206     mbedtls_mpi paraBnP;
207     mbedtls_mpi paraBnSquare;
208     mbedtls_mpi paraBnNegA;
209     mbedtls_mpi tmpBnA;
210     mbedtls_mpi tmpBnB;
211     mbedtls_mpi tmpBnC;
212     mbedtls_mpi tmpBnE;
213 
214     mbedtls_mpi_init(&paraBnP);
215     mbedtls_mpi_init(&paraBnSquare);
216     mbedtls_mpi_init(&paraBnNegA);
217     mbedtls_mpi_init(&tmpBnA);
218     mbedtls_mpi_init(&tmpBnB);
219     mbedtls_mpi_init(&tmpBnC);
220     mbedtls_mpi_init(&tmpBnE);
221 
222     int32_t status = mbedtls_mpi_read_binary(&paraBnP, g_hash2pointParas[0], BYTE_LENGTH_CURVE_25519);
223     LOG_AND_GOTO_CLEANUP_IF_FAIL(status, "Elligator error1");
224     status = mbedtls_mpi_read_binary(&paraBnSquare, g_hash2pointParas[1], BYTE_LENGTH_CURVE_25519);
225     LOG_AND_GOTO_CLEANUP_IF_FAIL(status, "Elligator error2");
226     status = mbedtls_mpi_read_binary(&paraBnNegA, g_hash2pointParas[PARAM_MINUS_A_INDEX], BYTE_LENGTH_CURVE_25519);
227     LOG_AND_GOTO_CLEANUP_IF_FAIL(status, "Elligator error3");
228 
229     status = CalTmpParab(&tmpBnB, &paraBnP, hash, hashLength);
230     LOG_AND_GOTO_CLEANUP_IF_FAIL(status, "Elligator error4");
231     status = CalTmpParaX(&tmpBnA, &tmpBnB, &paraBnP);
232     LOG_AND_GOTO_CLEANUP_IF_FAIL(status, "Elligator error5");
233 
234     status = mbedtls_mpi_sub_mpi(&tmpBnC, &paraBnP, &tmpBnB);
235     LOG_AND_GOTO_CLEANUP_IF_FAIL(status, "Elligator error6");
236     status = mbedtls_mpi_mod_mpi(&tmpBnC, &tmpBnC, &paraBnP);
237     LOG_AND_GOTO_CLEANUP_IF_FAIL(status, "Elligator error7");
238 
239     status = mbedtls_mpi_add_mpi(&tmpBnC, &tmpBnC, &paraBnNegA);
240     LOG_AND_GOTO_CLEANUP_IF_FAIL(status, "Elligator error8");
241     status = mbedtls_mpi_mod_mpi(&tmpBnC, &tmpBnC, &paraBnP);
242     LOG_AND_GOTO_CLEANUP_IF_FAIL(status, "Elligator error9");
243 
244     status = mbedtls_mpi_exp_mod(&tmpBnE, &tmpBnA, &paraBnSquare, &paraBnP, NULL);
245     LOG_AND_GOTO_CLEANUP_IF_FAIL(status, "Elligator error10");
246 
247     uint8_t swap = (mbedtls_mpi_cmp_mpi(&paraBnSquare, &tmpBnE) == 1);
248     status = mbedtls_mpi_safe_cond_swap(&tmpBnB, &tmpBnC, swap);
249     LOG_AND_GOTO_CLEANUP_IF_FAIL(status, "Elligator error11");
250 
251     status = mbedtls_mpi_write_binary(&tmpBnC, point, pointLength);
252     LOG_AND_GOTO_CLEANUP_IF_FAIL(status, "Elligator error12");
253 
254     SwapEndian(point, pointLength);
255 CLEAN_UP:
256     mbedtls_mpi_free(&paraBnP);
257     mbedtls_mpi_free(&paraBnSquare);
258     FreeCleanFiveBns(&paraBnNegA, &tmpBnA, &tmpBnB, &tmpBnC, &tmpBnE);
259     return status;
260 }
261 
MbedtlsHashToPoint(const Uint8Buff * hash,Uint8Buff * outEcPoint)262 int32_t MbedtlsHashToPoint(const Uint8Buff *hash, Uint8Buff *outEcPoint)
263 {
264     if (IsInvalidBlob(hash) || IsInvalidBlob(outEcPoint)) {
265         return HAL_ERR_INVALID_PARAM;
266     }
267     if (hash->length != BYTE_LENGTH_CURVE_25519 || outEcPoint->length != BYTE_LENGTH_CURVE_25519) {
268         LOGE("MbedtlsHashToPoint invalid length.");
269         return HAL_ERR_INVALID_PARAM;
270     }
271     uint8_t hashTmp[BYTE_LENGTH_CURVE_25519] = { 0 };
272     (void)memcpy_s(hashTmp, BYTE_LENGTH_CURVE_25519, hash->val, BYTE_LENGTH_CURVE_25519);
273 
274     hashTmp[BYTE_LENGTH_CURVE_25519 - 1] &= ~HASH2POINT_PARA_PREPRO;
275     SwapEndian(hashTmp, BYTE_LENGTH_CURVE_25519);
276     int status = Elligator(outEcPoint->val, BYTE_LENGTH_CURVE_25519, hashTmp, BYTE_LENGTH_CURVE_25519);
277     if (status != 0) {
278         LOGE("Elligator failed, status:%d", status);
279     }
280     return status;
281 }
282 
283 // only support P256 AgreeSharedSecret for standard system
MbedtlsAgreeSharedSecret(const KeyBuff * priKey,const KeyBuff * pubKey,Uint8Buff * sharedKey)284 int32_t MbedtlsAgreeSharedSecret(const KeyBuff *priKey, const KeyBuff *pubKey, Uint8Buff *sharedKey)
285 {
286     LOGE("MbedtlsAgreeSharedSecret for P256 is not supported now in small system.");
287     return HAL_ERR_NOT_SUPPORTED;
288 }