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(¶BnA);
108 mbedtls_mpi_init(¶BnU);
109
110 status = mbedtls_mpi_read_binary(¶BnA, 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(¶BnU, 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, ¶BnU, 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, ¶BnA); // 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(¶BnA, &tmpBnA, &tmpBnB, &tmpBnC, &tmpBnE);
145 mbedtls_mpi_free(¶BnU);
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(¶BnNegA);
159 mbedtls_mpi_init(¶BNOne);
160 mbedtls_mpi_init(¶BnU);
161 mbedtls_mpi_init(&tmpBnA);
162 mbedtls_mpi_init(&tmpBnB);
163
164 status = mbedtls_mpi_read_binary(¶BnNegA, 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(¶BNOne, 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(¶BnU, 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, ¶BnU, modP, NULL);
175 LOG_AND_GOTO_CLEANUP_IF_FAIL(status, "CalTmpParab error5");
176
177 status = mbedtls_mpi_mul_mpi(&tmpBnA, &tmpBnB, ¶BnU);
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, ¶BNOne);
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, ¶BnNegA);
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(¶BnNegA, ¶BNOne, ¶BnU, &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(¶BnP);
215 mbedtls_mpi_init(¶BnSquare);
216 mbedtls_mpi_init(¶BnNegA);
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(¶BnP, g_hash2pointParas[0], BYTE_LENGTH_CURVE_25519);
223 LOG_AND_GOTO_CLEANUP_IF_FAIL(status, "Elligator error1");
224 status = mbedtls_mpi_read_binary(¶BnSquare, g_hash2pointParas[1], BYTE_LENGTH_CURVE_25519);
225 LOG_AND_GOTO_CLEANUP_IF_FAIL(status, "Elligator error2");
226 status = mbedtls_mpi_read_binary(¶BnNegA, 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, ¶BnP, hash, hashLength);
230 LOG_AND_GOTO_CLEANUP_IF_FAIL(status, "Elligator error4");
231 status = CalTmpParaX(&tmpBnA, &tmpBnB, ¶BnP);
232 LOG_AND_GOTO_CLEANUP_IF_FAIL(status, "Elligator error5");
233
234 status = mbedtls_mpi_sub_mpi(&tmpBnC, ¶BnP, &tmpBnB);
235 LOG_AND_GOTO_CLEANUP_IF_FAIL(status, "Elligator error6");
236 status = mbedtls_mpi_mod_mpi(&tmpBnC, &tmpBnC, ¶BnP);
237 LOG_AND_GOTO_CLEANUP_IF_FAIL(status, "Elligator error7");
238
239 status = mbedtls_mpi_add_mpi(&tmpBnC, &tmpBnC, ¶BnNegA);
240 LOG_AND_GOTO_CLEANUP_IF_FAIL(status, "Elligator error8");
241 status = mbedtls_mpi_mod_mpi(&tmpBnC, &tmpBnC, ¶BnP);
242 LOG_AND_GOTO_CLEANUP_IF_FAIL(status, "Elligator error9");
243
244 status = mbedtls_mpi_exp_mod(&tmpBnE, &tmpBnA, ¶BnSquare, ¶BnP, NULL);
245 LOG_AND_GOTO_CLEANUP_IF_FAIL(status, "Elligator error10");
246
247 uint8_t swap = (mbedtls_mpi_cmp_mpi(¶BnSquare, &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(¶BnP);
257 mbedtls_mpi_free(¶BnSquare);
258 FreeCleanFiveBns(¶BnNegA, &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 }