/src/wolfssl-openssl-api/src/pk_ec.c
Line | Count | Source |
1 | | /* pk_ec.c |
2 | | * |
3 | | * Copyright (C) 2006-2026 wolfSSL Inc. |
4 | | * |
5 | | * This file is part of wolfSSL. |
6 | | * |
7 | | * wolfSSL is free software; you can redistribute it and/or modify |
8 | | * it under the terms of the GNU General Public License as published by |
9 | | * the Free Software Foundation; either version 3 of the License, or |
10 | | * (at your option) any later version. |
11 | | * |
12 | | * wolfSSL is distributed in the hope that it will be useful, |
13 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
15 | | * GNU General Public License for more details. |
16 | | * |
17 | | * You should have received a copy of the GNU General Public License |
18 | | * along with this program; if not, write to the Free Software |
19 | | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA |
20 | | */ |
21 | | |
22 | | #include <wolfssl/wolfcrypt/libwolfssl_sources.h> |
23 | | |
24 | | #include <wolfssl/internal.h> |
25 | | #ifndef WC_NO_RNG |
26 | | #include <wolfssl/wolfcrypt/random.h> |
27 | | #endif |
28 | | |
29 | | #ifdef HAVE_ECC |
30 | | #include <wolfssl/wolfcrypt/ecc.h> |
31 | | #ifdef HAVE_SELFTEST |
32 | | /* point compression types. */ |
33 | | #define ECC_POINT_COMP_EVEN 0x02 |
34 | | #define ECC_POINT_COMP_ODD 0x03 |
35 | | #define ECC_POINT_UNCOMP 0x04 |
36 | | #endif |
37 | | #endif |
38 | | #ifndef WOLFSSL_HAVE_ECC_KEY_GET_PRIV |
39 | | /* FIPS build has replaced ecc.h. */ |
40 | | #define wc_ecc_key_get_priv(key) (&((key)->k)) |
41 | | #define WOLFSSL_HAVE_ECC_KEY_GET_PRIV |
42 | | #endif |
43 | | |
44 | | #if !defined(WOLFSSL_PK_EC_INCLUDED) |
45 | | #ifndef WOLFSSL_IGNORE_FILE_WARN |
46 | | #warning pk_ec.c does not need to be compiled separately from ssl.c |
47 | | #endif |
48 | | #else |
49 | | |
50 | | /******************************************************************************* |
51 | | * START OF EC API |
52 | | ******************************************************************************/ |
53 | | |
54 | | #ifdef HAVE_ECC |
55 | | |
56 | | #if defined(OPENSSL_EXTRA) |
57 | | |
58 | | /* Start EC_curve */ |
59 | | |
60 | | /* Get the NIST name for the numeric ID. |
61 | | * |
62 | | * @param [in] nid Numeric ID of an EC curve. |
63 | | * @return String representing NIST name of EC curve on success. |
64 | | * @return NULL on error. |
65 | | */ |
66 | | const char* wolfSSL_EC_curve_nid2nist(int nid) |
67 | 0 | { |
68 | 0 | const char* name = NULL; |
69 | 0 | const WOLF_EC_NIST_NAME* nist_name; |
70 | | |
71 | | /* Attempt to find the curve info matching the NID passed in. */ |
72 | 0 | for (nist_name = kNistCurves; nist_name->name != NULL; nist_name++) { |
73 | 0 | if (nist_name->nid == nid) { |
74 | | /* NID found - return name. */ |
75 | 0 | name = nist_name->name; |
76 | 0 | break; |
77 | 0 | } |
78 | 0 | } |
79 | |
|
80 | 0 | return name; |
81 | 0 | } |
82 | | |
83 | | /* Get the numeric ID for the NIST name. |
84 | | * |
85 | | * @param [in] name NIST name of EC curve. |
86 | | * @return NID matching NIST name on success. |
87 | | * @return 0 on error. |
88 | | */ |
89 | | int wolfSSL_EC_curve_nist2nid(const char* name) |
90 | 0 | { |
91 | 0 | int nid = 0; |
92 | 0 | const WOLF_EC_NIST_NAME* nist_name; |
93 | | |
94 | | /* Attempt to find the curve info matching the NIST name passed in. */ |
95 | 0 | for (nist_name = kNistCurves; nist_name->name != NULL; nist_name++) { |
96 | 0 | if (XSTRCMP(nist_name->name, name) == 0) { |
97 | | /* Name found - return NID. */ |
98 | 0 | nid = nist_name->nid; |
99 | 0 | break; |
100 | 0 | } |
101 | 0 | } |
102 | |
|
103 | 0 | return nid; |
104 | 0 | } |
105 | | |
106 | | #endif /* OPENSSL_EXTRA */ |
107 | | |
108 | | /* End EC_curve */ |
109 | | |
110 | | /* Start EC_METHOD */ |
111 | | |
112 | | #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) |
113 | | /* Get the EC method of the EC group object. |
114 | | * |
115 | | * wolfSSL doesn't use method tables. Implementation used is dependent upon |
116 | | * the NID. |
117 | | * |
118 | | * @param [in] group EC group object. |
119 | | * @return EC method. |
120 | | */ |
121 | | const WOLFSSL_EC_METHOD* wolfSSL_EC_GROUP_method_of( |
122 | | const WOLFSSL_EC_GROUP *group) |
123 | 0 | { |
124 | | /* No method table used so just return the same object. */ |
125 | 0 | return group; |
126 | 0 | } |
127 | | |
128 | | /* Get field type for method. |
129 | | * |
130 | | * Only prime fields are supported. |
131 | | * |
132 | | * @param [in] meth EC method. |
133 | | * @return X9.63 prime field NID on success. |
134 | | * @return 0 on error. |
135 | | */ |
136 | | int wolfSSL_EC_METHOD_get_field_type(const WOLFSSL_EC_METHOD *meth) |
137 | 0 | { |
138 | 0 | int nid = 0; |
139 | |
|
140 | 0 | if (meth != NULL) { |
141 | | /* Only field type supported by code base. */ |
142 | 0 | nid = WC_NID_X9_62_prime_field; |
143 | 0 | } |
144 | |
|
145 | 0 | return nid; |
146 | 0 | } |
147 | | #endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */ |
148 | | |
149 | | /* End EC_METHOD */ |
150 | | |
151 | | /* Start EC_GROUP */ |
152 | | |
153 | | #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) |
154 | | /* Converts ECC curve enum values in ecc_curve_id to the associated OpenSSL NID |
155 | | * value. |
156 | | * |
157 | | * @param [in] n ECC curve id. |
158 | | * @return ECC curve NID (OpenSSL compatible value). |
159 | | */ |
160 | | int EccEnumToNID(int n) |
161 | 2.46k | { |
162 | 2.46k | WOLFSSL_ENTER("EccEnumToNID"); |
163 | | |
164 | 2.46k | switch(n) { |
165 | 0 | case ECC_SECP192R1: |
166 | 0 | return WC_NID_X9_62_prime192v1; |
167 | 0 | case ECC_PRIME192V2: |
168 | 0 | return WC_NID_X9_62_prime192v2; |
169 | 0 | case ECC_PRIME192V3: |
170 | 0 | return WC_NID_X9_62_prime192v3; |
171 | 0 | case ECC_PRIME239V1: |
172 | 0 | return WC_NID_X9_62_prime239v1; |
173 | 0 | case ECC_PRIME239V2: |
174 | 0 | return WC_NID_X9_62_prime239v2; |
175 | 0 | case ECC_PRIME239V3: |
176 | 0 | return WC_NID_X9_62_prime239v3; |
177 | 0 | case ECC_SECP256R1: |
178 | 0 | return WC_NID_X9_62_prime256v1; |
179 | 0 | case ECC_SECP112R1: |
180 | 0 | return WC_NID_secp112r1; |
181 | 0 | case ECC_SECP112R2: |
182 | 0 | return WC_NID_secp112r2; |
183 | 0 | case ECC_SECP128R1: |
184 | 0 | return WC_NID_secp128r1; |
185 | 0 | case ECC_SECP128R2: |
186 | 0 | return WC_NID_secp128r2; |
187 | 0 | case ECC_SECP160R1: |
188 | 0 | return WC_NID_secp160r1; |
189 | 0 | case ECC_SECP160R2: |
190 | 0 | return WC_NID_secp160r2; |
191 | 0 | case ECC_SECP224R1: |
192 | 0 | return WC_NID_secp224r1; |
193 | 0 | case ECC_SECP384R1: |
194 | 0 | return WC_NID_secp384r1; |
195 | 0 | case ECC_SECP521R1: |
196 | 0 | return WC_NID_secp521r1; |
197 | 0 | case ECC_SECP160K1: |
198 | 0 | return WC_NID_secp160k1; |
199 | 0 | case ECC_SECP192K1: |
200 | 0 | return WC_NID_secp192k1; |
201 | 0 | case ECC_SECP224K1: |
202 | 0 | return WC_NID_secp224k1; |
203 | 0 | case ECC_SECP256K1: |
204 | 0 | return WC_NID_secp256k1; |
205 | 0 | case ECC_BRAINPOOLP160R1: |
206 | 0 | return WC_NID_brainpoolP160r1; |
207 | 0 | case ECC_BRAINPOOLP192R1: |
208 | 0 | return WC_NID_brainpoolP192r1; |
209 | 0 | case ECC_BRAINPOOLP224R1: |
210 | 0 | return WC_NID_brainpoolP224r1; |
211 | 0 | case ECC_BRAINPOOLP256R1: |
212 | 0 | return WC_NID_brainpoolP256r1; |
213 | 0 | case ECC_BRAINPOOLP320R1: |
214 | 0 | return WC_NID_brainpoolP320r1; |
215 | 0 | case ECC_BRAINPOOLP384R1: |
216 | 0 | return WC_NID_brainpoolP384r1; |
217 | 0 | case ECC_BRAINPOOLP512R1: |
218 | 0 | return WC_NID_brainpoolP512r1; |
219 | 0 | #ifdef WOLFSSL_SM2 |
220 | 0 | case ECC_SM2P256V1: |
221 | 0 | return WC_NID_sm2; |
222 | 0 | #endif |
223 | 2.46k | default: |
224 | 2.46k | WOLFSSL_MSG("NID not found"); |
225 | 2.46k | return WOLFSSL_FATAL_ERROR; |
226 | 2.46k | } |
227 | 2.46k | } |
228 | | #endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */ |
229 | | |
230 | | #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL) |
231 | | /* Converts OpenSSL NID of EC curve to the enum value in ecc_curve_id |
232 | | * |
233 | | * Used by ecc_sets[]. |
234 | | * |
235 | | * @param [in] n OpenSSL NID of EC curve. |
236 | | * @return wolfCrypt EC curve id. |
237 | | * @return -1 on error. |
238 | | */ |
239 | | int NIDToEccEnum(int nid) |
240 | 2.71k | { |
241 | 2.71k | int id; |
242 | | |
243 | 2.71k | WOLFSSL_ENTER("NIDToEccEnum"); |
244 | | |
245 | 2.71k | switch (nid) { |
246 | 30 | case WC_NID_X9_62_prime192v1: |
247 | 30 | id = ECC_SECP192R1; |
248 | 30 | break; |
249 | 101 | case WC_NID_X9_62_prime192v2: |
250 | 101 | id = ECC_PRIME192V2; |
251 | 101 | break; |
252 | 29 | case WC_NID_X9_62_prime192v3: |
253 | 29 | id = ECC_PRIME192V3; |
254 | 29 | break; |
255 | 27 | case WC_NID_X9_62_prime239v1: |
256 | 27 | id = ECC_PRIME239V1; |
257 | 27 | break; |
258 | 55 | case WC_NID_X9_62_prime239v2: |
259 | 55 | id = ECC_PRIME239V2; |
260 | 55 | break; |
261 | 10 | case WC_NID_X9_62_prime239v3: |
262 | 10 | id = ECC_PRIME239V3; |
263 | 10 | break; |
264 | 123 | case WC_NID_X9_62_prime256v1: |
265 | 123 | id = ECC_SECP256R1; |
266 | 123 | break; |
267 | 20 | case WC_NID_secp112r1: |
268 | 20 | id = ECC_SECP112R1; |
269 | 20 | break; |
270 | 44 | case WC_NID_secp112r2: |
271 | 44 | id = ECC_SECP112R2; |
272 | 44 | break; |
273 | 58 | case WC_NID_secp128r1: |
274 | 58 | id = ECC_SECP128R1; |
275 | 58 | break; |
276 | 81 | case WC_NID_secp128r2: |
277 | 81 | id = ECC_SECP128R2; |
278 | 81 | break; |
279 | 94 | case WC_NID_secp160r1: |
280 | 94 | id = ECC_SECP160R1; |
281 | 94 | break; |
282 | 16 | case WC_NID_secp160r2: |
283 | 16 | id = ECC_SECP160R2; |
284 | 16 | break; |
285 | 6 | case WC_NID_secp224r1: |
286 | 6 | id = ECC_SECP224R1; |
287 | 6 | break; |
288 | 74 | case WC_NID_secp384r1: |
289 | 74 | id = ECC_SECP384R1; |
290 | 74 | break; |
291 | 316 | case WC_NID_secp521r1: |
292 | 316 | id = ECC_SECP521R1; |
293 | 316 | break; |
294 | 24 | case WC_NID_secp160k1: |
295 | 24 | id = ECC_SECP160K1; |
296 | 24 | break; |
297 | 121 | case WC_NID_secp192k1: |
298 | 121 | id = ECC_SECP192K1; |
299 | 121 | break; |
300 | 31 | case WC_NID_secp224k1: |
301 | 31 | id = ECC_SECP224K1; |
302 | 31 | break; |
303 | 167 | case WC_NID_secp256k1: |
304 | 167 | id = ECC_SECP256K1; |
305 | 167 | break; |
306 | 34 | case WC_NID_brainpoolP160r1: |
307 | 34 | id = ECC_BRAINPOOLP160R1; |
308 | 34 | break; |
309 | 12 | case WC_NID_brainpoolP192r1: |
310 | 12 | id = ECC_BRAINPOOLP192R1; |
311 | 12 | break; |
312 | 44 | case WC_NID_brainpoolP224r1: |
313 | 44 | id = ECC_BRAINPOOLP224R1; |
314 | 44 | break; |
315 | 47 | case WC_NID_brainpoolP256r1: |
316 | 47 | id = ECC_BRAINPOOLP256R1; |
317 | 47 | break; |
318 | 29 | case WC_NID_brainpoolP320r1: |
319 | 29 | id = ECC_BRAINPOOLP320R1; |
320 | 29 | break; |
321 | 61 | case WC_NID_brainpoolP384r1: |
322 | 61 | id = ECC_BRAINPOOLP384R1; |
323 | 61 | break; |
324 | 20 | case WC_NID_brainpoolP512r1: |
325 | 20 | id = ECC_BRAINPOOLP512R1; |
326 | 20 | break; |
327 | 1.04k | default: |
328 | 1.04k | WOLFSSL_MSG("NID not found"); |
329 | | /* -1 on error. */ |
330 | 1.04k | id = WOLFSSL_FATAL_ERROR; |
331 | 2.71k | } |
332 | | |
333 | 2.71k | return id; |
334 | 2.71k | } |
335 | | |
336 | | /* Set the fields of the EC group based on numeric ID. |
337 | | * |
338 | | * @param [in, out] group EC group. |
339 | | * @param [in] nid Numeric ID of an EC curve. |
340 | | */ |
341 | | static void ec_group_set_nid(WOLFSSL_EC_GROUP* group, int nid) |
342 | 2.71k | { |
343 | 2.71k | int eccEnum; |
344 | 2.71k | int realNid; |
345 | | |
346 | | /* Convert ecc_curve_id enum to NID. */ |
347 | 2.71k | if ((realNid = EccEnumToNID(nid)) != -1) { |
348 | | /* ecc_curve_id enum passed in - have real NID value set. */ |
349 | 0 | eccEnum = nid; |
350 | 0 | } |
351 | 2.71k | else { |
352 | | /* NID passed in is OpenSSL type. */ |
353 | 2.71k | realNid = nid; |
354 | | /* Convert NID to ecc_curve_id enum. */ |
355 | 2.71k | eccEnum = NIDToEccEnum(nid); |
356 | 2.71k | } |
357 | | |
358 | | /* Set the numeric ID of the curve */ |
359 | 2.71k | group->curve_nid = realNid; |
360 | | /* Initialize index to -1 (i.e. wolfCrypt doesn't support curve). */ |
361 | 2.71k | group->curve_idx = -1; |
362 | | |
363 | | /* Find index and OID sum for curve if wolfCrypt supports it. */ |
364 | 2.71k | if (eccEnum != -1) { |
365 | 1.67k | int i; |
366 | | |
367 | | /* Find id and set the internal curve idx and OID sum. */ |
368 | 28.2k | for (i = 0; ecc_sets[i].size != 0; i++) { |
369 | 28.2k | if (ecc_sets[i].id == eccEnum) { |
370 | | /* Found id in wolfCrypt supported EC curves. */ |
371 | 1.67k | group->curve_idx = i; |
372 | 1.67k | group->curve_oid = (int)ecc_sets[i].oidSum; |
373 | 1.67k | break; |
374 | 1.67k | } |
375 | 28.2k | } |
376 | 1.67k | } |
377 | 2.71k | } |
378 | | |
379 | | /* Create a new EC group with the numeric ID for an EC curve. |
380 | | * |
381 | | * @param [in] nid Numeric ID of an EC curve. |
382 | | * @return New, allocated EC group on success. |
383 | | * @return NULL on error. |
384 | | */ |
385 | | WOLFSSL_EC_GROUP* wolfSSL_EC_GROUP_new_by_curve_name(int nid) |
386 | 2.71k | { |
387 | 2.71k | int err = 0; |
388 | 2.71k | WOLFSSL_EC_GROUP* group; |
389 | | |
390 | 2.71k | WOLFSSL_ENTER("wolfSSL_EC_GROUP_new_by_curve_name"); |
391 | | |
392 | | /* Allocate EC group. */ |
393 | 2.71k | group = (WOLFSSL_EC_GROUP*)XMALLOC(sizeof(WOLFSSL_EC_GROUP), NULL, |
394 | 2.71k | DYNAMIC_TYPE_ECC); |
395 | 2.71k | if (group == NULL) { |
396 | 0 | WOLFSSL_MSG("wolfSSL_EC_GROUP_new_by_curve_name malloc failure"); |
397 | 0 | err = 1; |
398 | 0 | } |
399 | | |
400 | 2.71k | if (!err) { |
401 | | /* Reset all fields. */ |
402 | 2.71k | XMEMSET(group, 0, sizeof(WOLFSSL_EC_GROUP)); |
403 | | |
404 | | /* Set the fields of group based on the numeric ID. */ |
405 | 2.71k | ec_group_set_nid(group, nid); |
406 | 2.71k | } |
407 | | |
408 | 2.71k | return group; |
409 | 2.71k | } |
410 | | #endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL */ |
411 | | |
412 | | #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) |
413 | | /* Dispose of the EC group. |
414 | | * |
415 | | * Cannot use group after this call. |
416 | | * |
417 | | * @param [in] group EC group to free. |
418 | | */ |
419 | | void wolfSSL_EC_GROUP_free(WOLFSSL_EC_GROUP *group) |
420 | 2.71k | { |
421 | 2.71k | WOLFSSL_ENTER("wolfSSL_EC_GROUP_free"); |
422 | | |
423 | | /* Dispose of EC group. */ |
424 | 2.71k | XFREE(group, NULL, DYNAMIC_TYPE_ECC); |
425 | 2.71k | } |
426 | | #endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */ |
427 | | |
428 | | #ifdef OPENSSL_EXTRA |
429 | | |
430 | | /* Creates an EC group from the DER encoding. |
431 | | * |
432 | | * Only named curves supported. |
433 | | * |
434 | | * @param [out] group Reference to EC group object. |
435 | | * @param [in] in Buffer holding DER encoding of curve. |
436 | | * @param [in] inSz Length of data in buffer. |
437 | | * @return EC group on success. |
438 | | * @return NULL on error. |
439 | | */ |
440 | | static WOLFSSL_EC_GROUP* wolfssl_ec_group_d2i(WOLFSSL_EC_GROUP** group, |
441 | | const unsigned char** in_pp, long inSz) |
442 | 0 | { |
443 | 0 | int err = 0; |
444 | 0 | WOLFSSL_EC_GROUP* ret = NULL; |
445 | 0 | word32 idx = 0; |
446 | 0 | word32 oid = 0; |
447 | 0 | int id = 0; |
448 | 0 | const unsigned char* in; |
449 | |
|
450 | 0 | if (in_pp == NULL || *in_pp == NULL) |
451 | 0 | return NULL; |
452 | 0 | if (inSz <= 0) |
453 | 0 | return NULL; |
454 | | |
455 | 0 | in = *in_pp; |
456 | | |
457 | | /* Use the group passed in. */ |
458 | 0 | if ((group != NULL) && (*group != NULL)) { |
459 | 0 | ret = *group; |
460 | 0 | } |
461 | | |
462 | | /* Only support named curves. */ |
463 | 0 | if (in[0] != ASN_OBJECT_ID) { |
464 | 0 | WOLFSSL_ERROR_MSG("Invalid or unsupported encoding"); |
465 | 0 | err = 1; |
466 | 0 | } |
467 | | /* Decode the OBJECT ID - expecting an EC curve OID. */ |
468 | 0 | if ((!err) && (GetObjectId(in, &idx, &oid, oidCurveType, (word32)inSz) != |
469 | 0 | 0)) { |
470 | 0 | err = 1; |
471 | 0 | } |
472 | 0 | if (!err) { |
473 | | /* Get the internal ID for OID. */ |
474 | 0 | id = wc_ecc_get_oid(oid, NULL, NULL); |
475 | 0 | if (id < 0) { |
476 | 0 | err = 1; |
477 | 0 | } |
478 | 0 | } |
479 | 0 | if (!err) { |
480 | | /* Get the NID for the internal ID. */ |
481 | 0 | int nid = EccEnumToNID(id); |
482 | 0 | if (ret == NULL) { |
483 | | /* Create a new EC group with the numeric ID. */ |
484 | 0 | ret = wolfSSL_EC_GROUP_new_by_curve_name(nid); |
485 | 0 | if (ret == NULL) { |
486 | 0 | err = 1; |
487 | 0 | } |
488 | 0 | } |
489 | 0 | else { |
490 | 0 | ec_group_set_nid(ret, nid); |
491 | 0 | } |
492 | 0 | } |
493 | 0 | if ((!err) && (group != NULL)) { |
494 | | /* Return the EC group through reference. */ |
495 | 0 | *group = ret; |
496 | 0 | } |
497 | |
|
498 | 0 | if (err) { |
499 | 0 | if ((ret != NULL) && (ret != *group)) { |
500 | 0 | wolfSSL_EC_GROUP_free(ret); |
501 | 0 | } |
502 | 0 | ret = NULL; |
503 | 0 | } |
504 | 0 | else { |
505 | 0 | *in_pp += idx; |
506 | 0 | } |
507 | 0 | return ret; |
508 | 0 | } |
509 | | |
510 | | #ifndef NO_BIO |
511 | | /* Creates a new EC group from the PEM encoding in the BIO. |
512 | | * |
513 | | * @param [in] bio BIO to read PEM encoding from. |
514 | | * @param [out] group Reference to EC group object. |
515 | | * @param [in] cb Password callback when PEM encrypted. |
516 | | * @param [in] pass NUL terminated string for passphrase when PEM encrypted. |
517 | | * @return EC group on success. |
518 | | * @return NULL on error. |
519 | | */ |
520 | | WOLFSSL_EC_GROUP* wolfSSL_PEM_read_bio_ECPKParameters(WOLFSSL_BIO* bio, |
521 | | WOLFSSL_EC_GROUP** group, wc_pem_password_cb* cb, void* pass) |
522 | 0 | { |
523 | 0 | int err = 0; |
524 | 0 | WOLFSSL_EC_GROUP* ret = NULL; |
525 | 0 | DerBuffer* der = NULL; |
526 | 0 | int keyFormat = 0; |
527 | |
|
528 | 0 | if (bio == NULL) { |
529 | 0 | err = 1; |
530 | 0 | } |
531 | | |
532 | | /* Read parameters from BIO and convert PEM to DER. */ |
533 | 0 | if ((!err) && (pem_read_bio_key(bio, cb, pass, ECC_PARAM_TYPE, |
534 | 0 | &keyFormat, &der) < 0)) { |
535 | 0 | err = 1; |
536 | 0 | } |
537 | 0 | if (!err) { |
538 | | /* Create EC group from DER encoding. */ |
539 | 0 | const byte** p = (const byte**)&der->buffer; |
540 | 0 | ret = wolfssl_ec_group_d2i(group, p, der->length); |
541 | 0 | if (ret == NULL) { |
542 | 0 | WOLFSSL_ERROR_MSG("Error loading DER buffer into WOLFSSL_EC_GROUP"); |
543 | 0 | } |
544 | 0 | } |
545 | | |
546 | | /* Dispose of any allocated data. */ |
547 | 0 | FreeDer(&der); |
548 | 0 | return ret; |
549 | 0 | } |
550 | | #endif /* !NO_BIO */ |
551 | | |
552 | | WOLFSSL_EC_GROUP *wolfSSL_d2i_ECPKParameters(WOLFSSL_EC_GROUP **out, |
553 | | const unsigned char **in, long len) |
554 | 0 | { |
555 | 0 | return wolfssl_ec_group_d2i(out, in, len); |
556 | 0 | } |
557 | | |
558 | | int wolfSSL_i2d_ECPKParameters(const WOLFSSL_EC_GROUP* grp, unsigned char** pp) |
559 | 0 | { |
560 | 0 | unsigned char* out = NULL; |
561 | 0 | int len = 0; |
562 | 0 | int idx; |
563 | 0 | const byte* oid = NULL; |
564 | 0 | word32 oidSz = 0; |
565 | |
|
566 | 0 | if (grp == NULL || !wc_ecc_is_valid_idx(grp->curve_idx) || |
567 | 0 | grp->curve_idx < 0) |
568 | 0 | return WOLFSSL_FATAL_ERROR; |
569 | | |
570 | | /* Get the actual DER encoding of the OID. ecc_sets[grp->curve_idx].oid |
571 | | * is just the numerical representation. */ |
572 | 0 | if (wc_ecc_get_oid((word32)grp->curve_oid, &oid, &oidSz) < 0) |
573 | 0 | return WOLFSSL_FATAL_ERROR; |
574 | | |
575 | 0 | len = SetObjectId((int)oidSz, NULL) + (int)oidSz; |
576 | |
|
577 | 0 | if (pp == NULL) |
578 | 0 | return len; |
579 | | |
580 | 0 | if (*pp == NULL) { |
581 | 0 | out = (unsigned char*)XMALLOC((size_t)len, NULL, DYNAMIC_TYPE_ASN1); |
582 | 0 | if (out == NULL) |
583 | 0 | return WOLFSSL_FATAL_ERROR; |
584 | 0 | } |
585 | 0 | else { |
586 | 0 | out = *pp; |
587 | 0 | } |
588 | | |
589 | 0 | idx = SetObjectId((int)oidSz, out); |
590 | 0 | XMEMCPY(out + idx, oid, oidSz); |
591 | 0 | if (*pp == NULL) |
592 | 0 | *pp = out; |
593 | 0 | else |
594 | 0 | *pp += len; |
595 | |
|
596 | 0 | return len; |
597 | 0 | } |
598 | | |
599 | | #if defined(OPENSSL_ALL) && !defined(NO_CERTS) |
600 | | /* Copy an EC group. |
601 | | * |
602 | | * Only used by wolfSSL_EC_KEY_dup at this time. |
603 | | * |
604 | | * @param [in, out] dst Destination EC group. |
605 | | * @param [in] src Source EC group. |
606 | | * @return 0 on success. |
607 | | */ |
608 | | static int wolfssl_ec_group_copy(WOLFSSL_EC_GROUP* dst, |
609 | | const WOLFSSL_EC_GROUP* src) |
610 | 0 | { |
611 | | /* Copy the fields. */ |
612 | 0 | dst->curve_idx = src->curve_idx; |
613 | 0 | dst->curve_nid = src->curve_nid; |
614 | 0 | dst->curve_oid = src->curve_oid; |
615 | |
|
616 | 0 | return 0; |
617 | 0 | } |
618 | | #endif /* OPENSSL_ALL && !NO_CERTS */ |
619 | | |
620 | | /* Copies ecc_key into new WOLFSSL_EC_GROUP object |
621 | | * |
622 | | * @param [in] src EC group to duplicate. |
623 | | * |
624 | | * @return EC group on success. |
625 | | * @return NULL on error. |
626 | | */ |
627 | | WOLFSSL_EC_GROUP* wolfSSL_EC_GROUP_dup(const WOLFSSL_EC_GROUP *src) |
628 | 778 | { |
629 | 778 | WOLFSSL_EC_GROUP* newGroup = NULL; |
630 | | |
631 | 778 | if (src != NULL) { |
632 | | /* Create new group base on NID in original EC group. */ |
633 | 778 | newGroup = wolfSSL_EC_GROUP_new_by_curve_name(src->curve_nid); |
634 | 778 | } |
635 | | |
636 | 778 | return newGroup; |
637 | 778 | } |
638 | | |
639 | | /* Compare two EC groups. |
640 | | * |
641 | | * Return code compliant with OpenSSL. |
642 | | * |
643 | | * @param [in] a First EC group. |
644 | | * @param [in] b Second EC group. |
645 | | * @param [in] ctx Big number context to use when comparing fields. Unused. |
646 | | * |
647 | | * @return 0 if equal. |
648 | | * @return 1 if not equal. |
649 | | * @return -1 on error. |
650 | | */ |
651 | | int wolfSSL_EC_GROUP_cmp(const WOLFSSL_EC_GROUP *a, const WOLFSSL_EC_GROUP *b, |
652 | | WOLFSSL_BN_CTX *ctx) |
653 | 0 | { |
654 | 0 | int ret; |
655 | | |
656 | | /* No BN operations performed. */ |
657 | 0 | (void)ctx; |
658 | |
|
659 | 0 | WOLFSSL_ENTER("wolfSSL_EC_GROUP_cmp"); |
660 | | |
661 | | /* Validate parameters. */ |
662 | 0 | if ((a == NULL) || (b == NULL)) { |
663 | 0 | WOLFSSL_MSG("wolfSSL_EC_GROUP_cmp Bad arguments"); |
664 | | /* Return error value. */ |
665 | 0 | ret = WOLFSSL_FATAL_ERROR; |
666 | 0 | } |
667 | | /* Compare NID and wolfSSL curve index. */ |
668 | 0 | else { |
669 | | /* 0 when same, 1 when not. */ |
670 | 0 | ret = ((a->curve_nid == b->curve_nid) && |
671 | 0 | (a->curve_idx == b->curve_idx)) ? 0 : 1; |
672 | 0 | } |
673 | |
|
674 | 0 | return ret; |
675 | 0 | } |
676 | | |
677 | | #ifndef NO_WOLFSSL_STUB |
678 | | /* Set the ASN.1 flag that indicate encoding of curve. |
679 | | * |
680 | | * Stub function - flag not used elsewhere. |
681 | | * Always encoded as named curve. |
682 | | * |
683 | | * @param [in] group EC group to modify. |
684 | | * @param [in] flag ASN.1 flag to set. Valid values: |
685 | | * OPENSSL_EC_EXPLICIT_CURVE, OPENSSL_EC_NAMED_CURVE |
686 | | */ |
687 | | void wolfSSL_EC_GROUP_set_asn1_flag(WOLFSSL_EC_GROUP *group, int flag) |
688 | 0 | { |
689 | 0 | (void)group; |
690 | 0 | (void)flag; |
691 | |
|
692 | 0 | WOLFSSL_ENTER("wolfSSL_EC_GROUP_set_asn1_flag"); |
693 | 0 | WOLFSSL_STUB("EC_GROUP_set_asn1_flag"); |
694 | 0 | } |
695 | | #endif |
696 | | |
697 | | /* Get the curve NID of the group. |
698 | | * |
699 | | * Return code compliant with OpenSSL. |
700 | | * |
701 | | * @param [in] group EC group. |
702 | | * @return Curve NID on success. |
703 | | * @return 0 on error. |
704 | | */ |
705 | | int wolfSSL_EC_GROUP_get_curve_name(const WOLFSSL_EC_GROUP *group) |
706 | 0 | { |
707 | 0 | int nid = 0; |
708 | 0 | WOLFSSL_ENTER("wolfSSL_EC_GROUP_get_curve_name"); |
709 | |
|
710 | 0 | if (group == NULL) { |
711 | 0 | WOLFSSL_MSG("wolfSSL_EC_GROUP_get_curve_name Bad arguments"); |
712 | 0 | } |
713 | 0 | else { |
714 | 0 | nid = group->curve_nid; |
715 | 0 | } |
716 | |
|
717 | 0 | return nid; |
718 | 0 | } |
719 | | |
720 | | /* Get the degree (curve size in bits) of the EC group. |
721 | | * |
722 | | * Return code compliant with OpenSSL. |
723 | | * |
724 | | * @return Degree of the curve on success. |
725 | | * @return 0 on error. |
726 | | */ |
727 | | int wolfSSL_EC_GROUP_get_degree(const WOLFSSL_EC_GROUP *group) |
728 | 0 | { |
729 | 0 | int degree = 0; |
730 | |
|
731 | 0 | WOLFSSL_ENTER("wolfSSL_EC_GROUP_get_degree"); |
732 | |
|
733 | 0 | if (group == NULL) { |
734 | 0 | WOLFSSL_MSG("wolfSSL_EC_GROUP_get_degree Bad arguments"); |
735 | 0 | } |
736 | 0 | else { |
737 | 0 | switch (group->curve_nid) { |
738 | 0 | case WC_NID_secp112r1: |
739 | 0 | case WC_NID_secp112r2: |
740 | 0 | degree = 112; |
741 | 0 | break; |
742 | 0 | case WC_NID_secp128r1: |
743 | 0 | case WC_NID_secp128r2: |
744 | 0 | degree = 128; |
745 | 0 | break; |
746 | 0 | case WC_NID_secp160k1: |
747 | 0 | case WC_NID_secp160r1: |
748 | 0 | case WC_NID_secp160r2: |
749 | 0 | case WC_NID_brainpoolP160r1: |
750 | 0 | degree = 160; |
751 | 0 | break; |
752 | 0 | case WC_NID_secp192k1: |
753 | 0 | case WC_NID_brainpoolP192r1: |
754 | 0 | case WC_NID_X9_62_prime192v1: |
755 | 0 | case WC_NID_X9_62_prime192v2: |
756 | 0 | case WC_NID_X9_62_prime192v3: |
757 | 0 | degree = 192; |
758 | 0 | break; |
759 | 0 | case WC_NID_secp224k1: |
760 | 0 | case WC_NID_secp224r1: |
761 | 0 | case WC_NID_brainpoolP224r1: |
762 | 0 | degree = 224; |
763 | 0 | break; |
764 | 0 | case WC_NID_X9_62_prime239v1: |
765 | 0 | case WC_NID_X9_62_prime239v2: |
766 | 0 | case WC_NID_X9_62_prime239v3: |
767 | 0 | degree = 239; |
768 | 0 | break; |
769 | 0 | case WC_NID_secp256k1: |
770 | 0 | case WC_NID_brainpoolP256r1: |
771 | 0 | case WC_NID_X9_62_prime256v1: |
772 | 0 | degree = 256; |
773 | 0 | break; |
774 | 0 | case WC_NID_brainpoolP320r1: |
775 | 0 | degree = 320; |
776 | 0 | break; |
777 | 0 | case WC_NID_secp384r1: |
778 | 0 | case WC_NID_brainpoolP384r1: |
779 | 0 | degree = 384; |
780 | 0 | break; |
781 | 0 | case WC_NID_brainpoolP512r1: |
782 | 0 | degree = 512; |
783 | 0 | break; |
784 | 0 | case WC_NID_secp521r1: |
785 | 0 | degree = 521; |
786 | 0 | break; |
787 | 0 | } |
788 | 0 | } |
789 | | |
790 | 0 | return degree; |
791 | 0 | } |
792 | | #endif /* OPENSSL_EXTRA */ |
793 | | |
794 | | #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL) |
795 | | /* Get the length of the order in bits of the EC group. |
796 | | * |
797 | | * TODO: consider switch statement or calculating directly from hex string |
798 | | * array instead of using mp_int. |
799 | | * |
800 | | * @param [in] group EC group. |
801 | | * @return Length of order in bits on success. |
802 | | * @return 0 on error. |
803 | | */ |
804 | | int wolfSSL_EC_GROUP_order_bits(const WOLFSSL_EC_GROUP *group) |
805 | 0 | { |
806 | 0 | int ret = 0; |
807 | 0 | WC_DECLARE_VAR(order, mp_int, 1, 0); |
808 | | |
809 | | /* Validate parameter. */ |
810 | 0 | if ((group == NULL) || (group->curve_idx < 0)) { |
811 | 0 | WOLFSSL_MSG("wolfSSL_EC_GROUP_order_bits NULL error"); |
812 | 0 | ret = WOLFSSL_FATAL_ERROR; |
813 | 0 | } |
814 | |
|
815 | 0 | #ifdef WOLFSSL_SMALL_STACK |
816 | 0 | if (ret == 0) { |
817 | | /* Allocate memory for mp_int that will hold order value. */ |
818 | 0 | order = (mp_int *)XMALLOC(sizeof(*order), NULL, |
819 | 0 | DYNAMIC_TYPE_TMP_BUFFER); |
820 | 0 | if (order == NULL) { |
821 | 0 | ret = WOLFSSL_FATAL_ERROR; |
822 | 0 | } |
823 | 0 | } |
824 | 0 | #endif |
825 | |
|
826 | 0 | if (ret == 0) { |
827 | | /* Initialize mp_int. */ |
828 | 0 | ret = mp_init(order); |
829 | 0 | } |
830 | |
|
831 | 0 | if (ret == 0) { |
832 | | /* Read hex string of order from wolfCrypt array of curves. */ |
833 | 0 | ret = mp_read_radix(order, ecc_sets[group->curve_idx].order, |
834 | 0 | MP_RADIX_HEX); |
835 | 0 | if (ret == 0) { |
836 | | /* Get bits of order. */ |
837 | 0 | ret = mp_count_bits(order); |
838 | 0 | } |
839 | | /* Clear and free mp_int. */ |
840 | 0 | mp_clear(order); |
841 | 0 | } |
842 | |
|
843 | 0 | WC_FREE_VAR_EX(order, NULL, DYNAMIC_TYPE_TMP_BUFFER); |
844 | | |
845 | | /* Convert error code to length of 0. */ |
846 | 0 | if (ret < 0) { |
847 | 0 | ret = 0; |
848 | 0 | } |
849 | |
|
850 | 0 | return ret; |
851 | 0 | } |
852 | | #endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL */ |
853 | | |
854 | | #if defined(OPENSSL_EXTRA) |
855 | | /* Get the order of the group as a BN. |
856 | | * |
857 | | * Return code compliant with OpenSSL. |
858 | | * |
859 | | * @param [in] group EC group. |
860 | | * @param [in, out] order BN to hold order value. |
861 | | * @param [in] ctx Context to use for BN operations. Unused. |
862 | | * @return 1 on success. |
863 | | * @return 0 on error. |
864 | | */ |
865 | | int wolfSSL_EC_GROUP_get_order(const WOLFSSL_EC_GROUP *group, |
866 | | WOLFSSL_BIGNUM *order, WOLFSSL_BN_CTX *ctx) |
867 | 0 | { |
868 | 0 | int ret = 1; |
869 | 0 | mp_int* mp = NULL; |
870 | | |
871 | | /* No BN operations performed - done with mp_int in BN. */ |
872 | 0 | (void)ctx; |
873 | | |
874 | | /* Validate parameters. */ |
875 | 0 | if ((group == NULL) || (order == NULL) || (order->internal == NULL)) { |
876 | 0 | WOLFSSL_MSG("wolfSSL_EC_GROUP_get_order NULL error"); |
877 | 0 | ret = 0; |
878 | 0 | } |
879 | |
|
880 | 0 | if (ret == 1 && |
881 | 0 | (group->curve_idx < 0 || !wc_ecc_is_valid_idx(group->curve_idx))) { |
882 | 0 | WOLFSSL_MSG("wolfSSL_EC_GROUP_get_order Bad group idx"); |
883 | 0 | ret = 0; |
884 | 0 | } |
885 | |
|
886 | 0 | if (ret == 1) { |
887 | 0 | mp = (mp_int*)order->internal; |
888 | 0 | } |
889 | | /* Initialize */ |
890 | 0 | if ((ret == 1) && (mp_init(mp) != MP_OKAY)) { |
891 | 0 | WOLFSSL_MSG("wolfSSL_EC_GROUP_get_order mp_init failure"); |
892 | 0 | ret = 0; |
893 | 0 | } |
894 | | /* Read hex string of order from wolfCrypt array of curves. */ |
895 | 0 | if ((ret == 1) && (mp_read_radix(mp, ecc_sets[group->curve_idx].order, |
896 | 0 | MP_RADIX_HEX) != MP_OKAY)) { |
897 | 0 | WOLFSSL_MSG("wolfSSL_EC_GROUP_get_order mp_read order failure"); |
898 | | /* Zero out any partial value but don't free. */ |
899 | 0 | mp_zero(mp); |
900 | 0 | ret = 0; |
901 | 0 | } |
902 | |
|
903 | 0 | return ret; |
904 | 0 | } |
905 | | |
906 | | #endif /* OPENSSL_EXTRA */ |
907 | | |
908 | | /* End EC_GROUP */ |
909 | | |
910 | | /* Start EC_POINT */ |
911 | | |
912 | | #if defined(OPENSSL_EXTRA) |
913 | | |
914 | | /* Set data of EC point into internal, wolfCrypt EC point object. |
915 | | * |
916 | | * EC_POINT Openssl -> WolfSSL |
917 | | * |
918 | | * @param [in, out] p EC point to update. |
919 | | * @return 1 on success. |
920 | | * @return -1 on failure. |
921 | | */ |
922 | | static int ec_point_internal_set(WOLFSSL_EC_POINT *p) |
923 | 2.33k | { |
924 | 2.33k | int ret = 1; |
925 | | |
926 | 2.33k | WOLFSSL_ENTER("ec_point_internal_set"); |
927 | | |
928 | | /* Validate parameter. */ |
929 | 2.33k | if ((p == NULL) || (p->internal == NULL)) { |
930 | 0 | WOLFSSL_MSG("ECPoint NULL error"); |
931 | 0 | ret = WOLFSSL_FATAL_ERROR; |
932 | 0 | } |
933 | 2.33k | else { |
934 | | /* Get internal point as a wolfCrypt EC point. */ |
935 | 2.33k | ecc_point* point = (ecc_point*)p->internal; |
936 | | |
937 | | /* Set X ordinate if available. */ |
938 | 2.33k | if ((p->X != NULL) && (wolfssl_bn_get_value(p->X, point->x) != 1)) { |
939 | 0 | WOLFSSL_MSG("ecc point X error"); |
940 | 0 | ret = WOLFSSL_FATAL_ERROR; |
941 | 0 | } |
942 | | /* Set Y ordinate if available. */ |
943 | 2.33k | if ((ret == 1) && (p->Y != NULL) && (wolfssl_bn_get_value(p->Y, |
944 | 955 | point->y) != 1)) { |
945 | 0 | WOLFSSL_MSG("ecc point Y error"); |
946 | 0 | ret = WOLFSSL_FATAL_ERROR; |
947 | 0 | } |
948 | | /* Set Z ordinate if available. */ |
949 | 2.33k | if ((ret == 1) && (p->Z != NULL) && (wolfssl_bn_get_value(p->Z, |
950 | 955 | point->z) != 1)) { |
951 | 0 | WOLFSSL_MSG("ecc point Z error"); |
952 | 0 | ret = WOLFSSL_FATAL_ERROR; |
953 | 0 | } |
954 | | /* Internal values set when operations succeeded. */ |
955 | 2.33k | p->inSet = (ret == 1); |
956 | 2.33k | } |
957 | | |
958 | 2.33k | return ret; |
959 | 2.33k | } |
960 | | |
961 | | /* Set data of internal, wolfCrypt EC point object into EC point. |
962 | | * |
963 | | * EC_POINT WolfSSL -> OpenSSL |
964 | | * |
965 | | * @param [in, out] p EC point to update. |
966 | | * @return 1 on success. |
967 | | * @return -1 on failure. |
968 | | */ |
969 | | static int ec_point_external_set(WOLFSSL_EC_POINT *p) |
970 | 2.14k | { |
971 | 2.14k | int ret = 1; |
972 | | |
973 | 2.14k | WOLFSSL_ENTER("ec_point_external_set"); |
974 | | |
975 | | /* Validate parameter. */ |
976 | 2.14k | if ((p == NULL) || (p->internal == NULL)) { |
977 | 0 | WOLFSSL_MSG("ECPoint NULL error"); |
978 | 0 | ret = WOLFSSL_FATAL_ERROR; |
979 | 0 | } |
980 | 2.14k | else { |
981 | | /* Get internal point as a wolfCrypt EC point. */ |
982 | 2.14k | ecc_point* point = (ecc_point*)p->internal; |
983 | | |
984 | | /* Set X ordinate. */ |
985 | 2.14k | if (wolfssl_bn_set_value(&p->X, point->x) != 1) { |
986 | 0 | WOLFSSL_MSG("ecc point X error"); |
987 | 0 | ret = WOLFSSL_FATAL_ERROR; |
988 | 0 | } |
989 | | /* Set Y ordinate. */ |
990 | 2.14k | if ((ret == 1) && (wolfssl_bn_set_value(&p->Y, point->y) != 1)) { |
991 | 0 | WOLFSSL_MSG("ecc point Y error"); |
992 | 0 | ret = WOLFSSL_FATAL_ERROR; |
993 | 0 | } |
994 | | /* Set Z ordinate. */ |
995 | 2.14k | if ((ret == 1) && (wolfssl_bn_set_value(&p->Z, point->z) != 1)) { |
996 | 0 | WOLFSSL_MSG("ecc point Z error"); |
997 | 0 | ret = WOLFSSL_FATAL_ERROR; |
998 | 0 | } |
999 | | /* External values set when operations succeeded. */ |
1000 | 2.14k | p->exSet = (ret == 1); |
1001 | 2.14k | } |
1002 | | |
1003 | 2.14k | return ret; |
1004 | 2.14k | } |
1005 | | |
1006 | | /* Setup internals of EC point. |
1007 | | * |
1008 | | * Assumes point is not NULL. |
1009 | | * |
1010 | | * @param [in, out] point EC point to update. |
1011 | | * @return 1 on success. |
1012 | | * @return 0 on failure. |
1013 | | */ |
1014 | 2.46k | static int ec_point_setup(const WOLFSSL_EC_POINT *point) { |
1015 | 2.46k | int ret = 1; |
1016 | | |
1017 | | /* Check if internal values need setting. */ |
1018 | 2.46k | if (!point->inSet) { |
1019 | 654 | WOLFSSL_MSG("No ECPoint internal set, do it"); |
1020 | | |
1021 | | /* Forcing to non-constant type to update internals. */ |
1022 | 654 | if (ec_point_internal_set((WOLFSSL_EC_POINT *)point) != 1) { |
1023 | 0 | WOLFSSL_MSG("ec_point_internal_set failed"); |
1024 | 0 | ret = 0; |
1025 | 0 | } |
1026 | 654 | } |
1027 | | |
1028 | 2.46k | return ret; |
1029 | 2.46k | } |
1030 | | |
1031 | | /* Create a new EC point from the group. |
1032 | | * |
1033 | | * @param [in] group EC group. |
1034 | | * @return EC point on success. |
1035 | | * @return NULL on error. |
1036 | | */ |
1037 | | WOLFSSL_EC_POINT* wolfSSL_EC_POINT_new(const WOLFSSL_EC_GROUP* group) |
1038 | 3.26k | { |
1039 | 3.26k | int err = 0; |
1040 | 3.26k | WOLFSSL_EC_POINT* point = NULL; |
1041 | | |
1042 | 3.26k | WOLFSSL_ENTER("wolfSSL_EC_POINT_new"); |
1043 | | |
1044 | | /* Validate parameter. */ |
1045 | 3.26k | if (group == NULL) { |
1046 | 0 | WOLFSSL_MSG("wolfSSL_EC_POINT_new NULL error"); |
1047 | 0 | err = 1; |
1048 | 0 | } |
1049 | | |
1050 | 3.26k | if (!err) { |
1051 | | /* Allocate memory for new EC point. */ |
1052 | 3.26k | point = (WOLFSSL_EC_POINT*)XMALLOC(sizeof(WOLFSSL_EC_POINT), NULL, |
1053 | 3.26k | DYNAMIC_TYPE_ECC); |
1054 | 3.26k | if (point == NULL) { |
1055 | 0 | WOLFSSL_MSG("wolfSSL_EC_POINT_new malloc ecc point failure"); |
1056 | 0 | err = 1; |
1057 | 0 | } |
1058 | 3.26k | } |
1059 | 3.26k | if (!err) { |
1060 | | /* Clear fields of EC point. */ |
1061 | 3.26k | XMEMSET(point, 0, sizeof(WOLFSSL_EC_POINT)); |
1062 | | |
1063 | | /* Allocate internal EC point. */ |
1064 | 3.26k | point->internal = wc_ecc_new_point(); |
1065 | 3.26k | if (point->internal == NULL) { |
1066 | 0 | WOLFSSL_MSG("ecc_new_point failure"); |
1067 | 0 | err = 1; |
1068 | 0 | } |
1069 | 3.26k | } |
1070 | | |
1071 | 3.26k | if (err) { |
1072 | 0 | XFREE(point, NULL, DYNAMIC_TYPE_ECC); |
1073 | 0 | point = NULL; |
1074 | 0 | } |
1075 | 3.26k | return point; |
1076 | 3.26k | } |
1077 | | |
1078 | | #endif /* OPENSSL_EXTRA */ |
1079 | | |
1080 | | #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) |
1081 | | /* Dispose of the EC point. |
1082 | | * |
1083 | | * Cannot use point after this call. |
1084 | | * |
1085 | | * @param [in, out] point EC point to free. |
1086 | | */ |
1087 | | void wolfSSL_EC_POINT_free(WOLFSSL_EC_POINT *point) |
1088 | 3.26k | { |
1089 | 3.26k | WOLFSSL_ENTER("wolfSSL_EC_POINT_free"); |
1090 | | |
1091 | 3.26k | if (point != NULL) { |
1092 | 3.26k | if (point->internal != NULL) { |
1093 | 3.26k | wc_ecc_del_point((ecc_point*)point->internal); |
1094 | 3.26k | point->internal = NULL; |
1095 | 3.26k | } |
1096 | | |
1097 | | /* Free ordinates. */ |
1098 | 3.26k | wolfSSL_BN_free(point->X); |
1099 | 3.26k | wolfSSL_BN_free(point->Y); |
1100 | 3.26k | wolfSSL_BN_free(point->Z); |
1101 | | /* Clear fields. */ |
1102 | 3.26k | point->X = NULL; |
1103 | 3.26k | point->Y = NULL; |
1104 | 3.26k | point->Z = NULL; |
1105 | 3.26k | point->inSet = 0; |
1106 | 3.26k | point->exSet = 0; |
1107 | | |
1108 | | /* Dispose of EC point. */ |
1109 | 3.26k | XFREE(point, NULL, DYNAMIC_TYPE_ECC); |
1110 | 3.26k | } |
1111 | 3.26k | } |
1112 | | #endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */ |
1113 | | |
1114 | | #ifdef OPENSSL_EXTRA |
1115 | | |
1116 | | /* Clear and dispose of the EC point. |
1117 | | * |
1118 | | * Cannot use point after this call. |
1119 | | * |
1120 | | * @param [in, out] point EC point to free. |
1121 | | */ |
1122 | | void wolfSSL_EC_POINT_clear_free(WOLFSSL_EC_POINT *point) |
1123 | 0 | { |
1124 | 0 | WOLFSSL_ENTER("wolfSSL_EC_POINT_clear_free"); |
1125 | |
|
1126 | 0 | if (point != NULL) { |
1127 | 0 | if (point->internal != NULL) { |
1128 | | /* Force internal point to be zeros. */ |
1129 | 0 | #if !defined(HAVE_SELFTEST) && (!defined(HAVE_FIPS) || FIPS_VERSION_GT(2,0)) |
1130 | 0 | wc_ecc_forcezero_point((ecc_point*)point->internal); |
1131 | | #else |
1132 | | ecc_point* p = (ecc_point*)point->internal; |
1133 | | mp_forcezero(p->x); |
1134 | | mp_forcezero(p->y); |
1135 | | mp_forcezero(p->z); |
1136 | | #endif |
1137 | 0 | wc_ecc_del_point((ecc_point*)point->internal); |
1138 | 0 | point->internal = NULL; |
1139 | 0 | } |
1140 | | |
1141 | | /* Clear the ordinates before freeing. */ |
1142 | 0 | wolfSSL_BN_clear_free(point->X); |
1143 | 0 | wolfSSL_BN_clear_free(point->Y); |
1144 | 0 | wolfSSL_BN_clear_free(point->Z); |
1145 | | /* Clear fields. */ |
1146 | 0 | point->X = NULL; |
1147 | 0 | point->Y = NULL; |
1148 | 0 | point->Z = NULL; |
1149 | 0 | point->inSet = 0; |
1150 | 0 | point->exSet = 0; |
1151 | | |
1152 | | /* Dispose of EC point. */ |
1153 | 0 | XFREE(point, NULL, DYNAMIC_TYPE_ECC); |
1154 | 0 | } |
1155 | 0 | } |
1156 | | |
1157 | | /* Print out the internals of EC point in debug and when logging callback set. |
1158 | | * |
1159 | | * Not an OpenSSL API. |
1160 | | * |
1161 | | * TODO: Use WOLFSSL_MSG_EX()? |
1162 | | * |
1163 | | * @param [in] msg Message to prepend. |
1164 | | * @param [in] point EC point to print. |
1165 | | */ |
1166 | | void wolfSSL_EC_POINT_dump(const char *msg, const WOLFSSL_EC_POINT *point) |
1167 | 784 | { |
1168 | | #if defined(DEBUG_WOLFSSL) |
1169 | | char *num; |
1170 | | |
1171 | | WOLFSSL_ENTER("wolfSSL_EC_POINT_dump"); |
1172 | | |
1173 | | /* Only print when debugging on. */ |
1174 | | if (WOLFSSL_IS_DEBUG_ON()) { |
1175 | | if (point == NULL) { |
1176 | | /* No point passed in so just put out "NULL". */ |
1177 | | WOLFSSL_MSG_EX("%s = NULL\n", msg); |
1178 | | } |
1179 | | else { |
1180 | | /* Put out message and status of internal/external data set. */ |
1181 | | WOLFSSL_MSG_EX("%s:\n\tinSet=%d, exSet=%d\n", msg, point->inSet, |
1182 | | point->exSet); |
1183 | | /* Get x-ordinate as a hex string and print. */ |
1184 | | num = wolfSSL_BN_bn2hex(point->X); |
1185 | | WOLFSSL_MSG_EX("\tX = %s\n", num); |
1186 | | XFREE(num, NULL, DYNAMIC_TYPE_OPENSSL); |
1187 | | /* Get x-ordinate as a hex string and print. */ |
1188 | | num = wolfSSL_BN_bn2hex(point->Y); |
1189 | | WOLFSSL_MSG_EX("\tY = %s\n", num); |
1190 | | XFREE(num, NULL, DYNAMIC_TYPE_OPENSSL); |
1191 | | /* Get z-ordinate as a hex string and print. */ |
1192 | | num = wolfSSL_BN_bn2hex(point->Z); |
1193 | | WOLFSSL_MSG_EX("\tZ = %s\n", num); |
1194 | | XFREE(num, NULL, DYNAMIC_TYPE_OPENSSL); |
1195 | | } |
1196 | | } |
1197 | | #else |
1198 | 784 | (void)msg; |
1199 | 784 | (void)point; |
1200 | 784 | #endif |
1201 | 784 | } |
1202 | | |
1203 | | /* Convert EC point to hex string that as either uncompressed or compressed. |
1204 | | * |
1205 | | * ECC point compression types were not included in selftest ecc.h |
1206 | | * |
1207 | | * @param [in] group EC group for point. |
1208 | | * @param [in] point EC point to encode. |
1209 | | * @param [in] form Format of encoding. Valid values: |
1210 | | * POINT_CONVERSION_UNCOMPRESSED, POINT_CONVERSION_COMPRESSED |
1211 | | * @param [in] ctx Context to use for BN operations. Unused. |
1212 | | * @return Allocated hex string on success. |
1213 | | * @return NULL on error. |
1214 | | */ |
1215 | | char* wolfSSL_EC_POINT_point2hex(const WOLFSSL_EC_GROUP* group, |
1216 | | const WOLFSSL_EC_POINT* point, int form, WOLFSSL_BN_CTX* ctx) |
1217 | 0 | { |
1218 | 0 | static const char* hexDigit = "0123456789ABCDEF"; |
1219 | 0 | char* hex = NULL; |
1220 | 0 | int i; |
1221 | 0 | int sz = 0; |
1222 | 0 | int len = 0; |
1223 | 0 | int err = 0; |
1224 | | |
1225 | | /* No BN operations performed. */ |
1226 | 0 | (void)ctx; |
1227 | | |
1228 | | /* Validate parameters. */ |
1229 | 0 | if ((group == NULL) || (point == NULL)) { |
1230 | 0 | err = 1; |
1231 | 0 | } |
1232 | | /* Get curve id expects a positive index. */ |
1233 | 0 | if ((!err) && (group->curve_idx < 0)) { |
1234 | 0 | err = 1; |
1235 | 0 | } |
1236 | |
|
1237 | 0 | if (!err) { |
1238 | | /* Get curve id to look up ordinate size. */ |
1239 | 0 | int id = wc_ecc_get_curve_id(group->curve_idx); |
1240 | | /* Get size of ordinate. */ |
1241 | 0 | if ((sz = wc_ecc_get_curve_size_from_id(id)) < 0) { |
1242 | 0 | err = 1; |
1243 | 0 | } |
1244 | 0 | } |
1245 | 0 | if (!err) { |
1246 | | /* <format byte> <x-ordinate> [<y-ordinate>] */ |
1247 | 0 | len = sz + 1; |
1248 | 0 | if (form == WC_POINT_CONVERSION_UNCOMPRESSED) { |
1249 | | /* Include y ordinate when uncompressed. */ |
1250 | 0 | len += sz; |
1251 | 0 | } |
1252 | | |
1253 | | /* Hex string: allocate 2 bytes to represent each byte plus 1 for '\0'. |
1254 | | */ |
1255 | 0 | hex = (char*)XMALLOC((size_t)(2 * len + 1), NULL, DYNAMIC_TYPE_ECC); |
1256 | 0 | if (hex == NULL) { |
1257 | 0 | err = 1; |
1258 | 0 | } |
1259 | 0 | } |
1260 | 0 | if (!err) { |
1261 | | /* Make bytes all zeros to allow for ordinate values less than max size. |
1262 | | */ |
1263 | 0 | XMEMSET(hex, 0, (size_t)(2 * len + 1)); |
1264 | | |
1265 | | /* Calculate offset as leading zeros not encoded. */ |
1266 | 0 | i = sz - mp_unsigned_bin_size((mp_int*)point->X->internal) + 1; |
1267 | | /* Put in x-ordinate after format byte. */ |
1268 | 0 | if (mp_to_unsigned_bin((mp_int*)point->X->internal, (byte*)(hex + i)) < |
1269 | 0 | 0) { |
1270 | 0 | err = 1; |
1271 | 0 | } |
1272 | 0 | } |
1273 | 0 | if (!err) { |
1274 | 0 | if (form == WC_POINT_CONVERSION_COMPRESSED) { |
1275 | | /* Compressed format byte value dependent on whether y-ordinate is |
1276 | | * odd. |
1277 | | */ |
1278 | 0 | hex[0] = mp_isodd((mp_int*)point->Y->internal) ? |
1279 | 0 | ECC_POINT_COMP_ODD : ECC_POINT_COMP_EVEN; |
1280 | | /* No y-ordinate. */ |
1281 | 0 | } |
1282 | 0 | else { |
1283 | | /* Put in uncompressed format byte. */ |
1284 | 0 | hex[0] = ECC_POINT_UNCOMP; |
1285 | | /* Calculate offset as leading zeros not encoded. */ |
1286 | 0 | i = 1 + 2 * sz - mp_unsigned_bin_size((mp_int*)point->Y->internal); |
1287 | | /* Put in y-ordinate after x-ordinate. */ |
1288 | 0 | if (mp_to_unsigned_bin((mp_int*)point->Y->internal, |
1289 | 0 | (byte*)(hex + i)) < 0) { |
1290 | 0 | err = 1; |
1291 | 0 | } |
1292 | 0 | } |
1293 | 0 | } |
1294 | 0 | if (!err) { |
1295 | | /* Convert binary encoding to hex string. */ |
1296 | | /* Start at end so as not to overwrite. */ |
1297 | 0 | for (i = len-1; i >= 0; i--) { |
1298 | | /* Get byte value and store has hex string. */ |
1299 | 0 | byte b = (byte)hex[i]; |
1300 | 0 | hex[i * 2 + 1] = hexDigit[b & 0xf]; |
1301 | 0 | hex[i * 2 ] = hexDigit[b >> 4]; |
1302 | 0 | } |
1303 | | /* Memset put trailing zero or '\0' on end of string. */ |
1304 | 0 | } |
1305 | |
|
1306 | 0 | if (err && (hex != NULL)) { |
1307 | | /* Dispose of allocated data not being returned. */ |
1308 | 0 | XFREE(hex, NULL, DYNAMIC_TYPE_ECC); |
1309 | 0 | hex = NULL; |
1310 | 0 | } |
1311 | | /* Return hex string encoding. */ |
1312 | 0 | return hex; |
1313 | 0 | } |
1314 | | |
1315 | | static size_t hex_to_bytes(const char *hex, unsigned char *output, size_t sz) |
1316 | 0 | { |
1317 | 0 | word32 i; |
1318 | 0 | for (i = 0; i < sz; i++) { |
1319 | 0 | signed char ch1, ch2; |
1320 | 0 | ch1 = HexCharToByte(hex[i * 2]); |
1321 | 0 | ch2 = HexCharToByte(hex[i * 2 + 1]); |
1322 | 0 | if ((ch1 < 0) || (ch2 < 0)) { |
1323 | 0 | WOLFSSL_MSG("hex_to_bytes: syntax error"); |
1324 | 0 | return 0; |
1325 | 0 | } |
1326 | 0 | output[i] = (unsigned char)((ch1 << 4) + ch2); |
1327 | 0 | } |
1328 | 0 | return sz; |
1329 | 0 | } |
1330 | | |
1331 | | WOLFSSL_EC_POINT* wolfSSL_EC_POINT_hex2point(const WOLFSSL_EC_GROUP *group, |
1332 | | const char *hex, WOLFSSL_EC_POINT*p, WOLFSSL_BN_CTX *ctx) |
1333 | 0 | { |
1334 | | /* for uncompressed mode */ |
1335 | 0 | size_t str_sz; |
1336 | 0 | WOLFSSL_BIGNUM *Gx = NULL; |
1337 | 0 | WOLFSSL_BIGNUM *Gy = NULL; |
1338 | 0 | char strGx[MAX_ECC_BYTES * 2 + 1]; |
1339 | | |
1340 | | /* for compressed mode */ |
1341 | 0 | int key_sz; |
1342 | 0 | byte *octGx = (byte *)strGx; /* octGx[MAX_ECC_BYTES] */ |
1343 | |
|
1344 | 0 | int p_alloc = 0; |
1345 | 0 | int ret; |
1346 | |
|
1347 | 0 | WOLFSSL_ENTER("wolfSSL_EC_POINT_hex2point"); |
1348 | |
|
1349 | 0 | if (group == NULL || hex == NULL || ctx == NULL) |
1350 | 0 | return NULL; |
1351 | | |
1352 | 0 | if (p == NULL) { |
1353 | 0 | if ((p = wolfSSL_EC_POINT_new(group)) == NULL) { |
1354 | 0 | WOLFSSL_MSG("wolfSSL_EC_POINT_new"); |
1355 | 0 | goto err; |
1356 | 0 | } |
1357 | 0 | p_alloc = 1; |
1358 | 0 | } |
1359 | | |
1360 | 0 | key_sz = (wolfSSL_EC_GROUP_get_degree(group) + 7) / 8; |
1361 | 0 | if (key_sz <= 0 || (size_t)key_sz > MAX_ECC_BYTES) |
1362 | 0 | goto err; |
1363 | | |
1364 | 0 | if (hex[0] == '0' && hex[1] == '4') { /* uncompressed mode */ |
1365 | 0 | str_sz = (size_t)key_sz * 2; |
1366 | | |
1367 | | /* The uncompressed encoding is exactly 2 + 4*key_sz hex chars |
1368 | | * ("04" prefix plus X and Y as 2*key_sz hex chars each). Reject |
1369 | | * any other length so XMEMCPY/BN_hex2bn cannot read past the end |
1370 | | * of the input and trailing garbage is not silently absorbed. */ |
1371 | 0 | if (XSTRLEN(hex + 2) != str_sz * 2) |
1372 | 0 | goto err; |
1373 | | |
1374 | 0 | XMEMSET(strGx, 0x0, str_sz + 1); |
1375 | 0 | XMEMCPY(strGx, hex + 2, str_sz); |
1376 | |
|
1377 | 0 | if (wolfSSL_BN_hex2bn(&Gx, strGx) == 0) |
1378 | 0 | goto err; |
1379 | | |
1380 | 0 | if (wolfSSL_BN_hex2bn(&Gy, hex + 2 + str_sz) == 0) |
1381 | 0 | goto err; |
1382 | | |
1383 | 0 | ret = wolfSSL_EC_POINT_set_affine_coordinates_GFp |
1384 | 0 | (group, p, Gx, Gy, ctx); |
1385 | |
|
1386 | 0 | if (ret != WOLFSSL_SUCCESS) { |
1387 | 0 | WOLFSSL_MSG("wolfSSL_EC_POINT_set_affine_coordinates_GFp"); |
1388 | 0 | goto err; |
1389 | 0 | } |
1390 | 0 | } |
1391 | 0 | else if (hex[0] == '0' && (hex[1] == '2' || hex[1] == '3')) { |
1392 | | /* The SEC 1 compressed encoding is exactly 1 + key_sz bytes, so |
1393 | | * the hex payload after the "02"/"03" prefix must be exactly |
1394 | | * 2*key_sz hex chars. Compare the input length directly (rather |
1395 | | * than XSTRLEN/2) so that odd-length inputs cannot slip past via |
1396 | | * integer truncation. The exact-match rejects oversized inputs |
1397 | | * (preventing a hex_to_bytes() write past strGx) and undersized |
1398 | | * inputs (preventing wolfSSL_ECPoint_d2i() from reading |
1399 | | * uninitialized stack bytes as the X coordinate). */ |
1400 | 0 | if (XSTRLEN(hex + 2) != (size_t)key_sz * 2) |
1401 | 0 | goto err; |
1402 | 0 | octGx[0] = (hex[1] == '2') ? ECC_POINT_COMP_EVEN |
1403 | 0 | : ECC_POINT_COMP_ODD; |
1404 | 0 | if (hex_to_bytes(hex + 2, octGx + 1, (size_t)key_sz) |
1405 | 0 | != (size_t)key_sz) { |
1406 | 0 | goto err; |
1407 | 0 | } |
1408 | 0 | if (wolfSSL_ECPoint_d2i(octGx, (word32)key_sz + 1, group, p) |
1409 | 0 | != WOLFSSL_SUCCESS) { |
1410 | 0 | goto err; |
1411 | 0 | } |
1412 | 0 | } |
1413 | 0 | else |
1414 | 0 | goto err; |
1415 | | |
1416 | 0 | wolfSSL_BN_free(Gx); |
1417 | 0 | wolfSSL_BN_free(Gy); |
1418 | 0 | return p; |
1419 | | |
1420 | 0 | err: |
1421 | 0 | wolfSSL_BN_free(Gx); |
1422 | 0 | wolfSSL_BN_free(Gy); |
1423 | 0 | if (p_alloc) { |
1424 | 0 | wolfSSL_EC_POINT_free(p); |
1425 | 0 | } |
1426 | 0 | return NULL; |
1427 | |
|
1428 | 0 | } |
1429 | | |
1430 | | /* Encode the EC point as an uncompressed point in DER. |
1431 | | * |
1432 | | * Return code compliant with OpenSSL. |
1433 | | * Not OpenSSL API. |
1434 | | * |
1435 | | * @param [in] group EC group point belongs to. |
1436 | | * @param [in] point EC point to encode. |
1437 | | * @param [out] out Buffer to encode into. May be NULL. |
1438 | | * @param [in, out] len On in, length of buffer in bytes. |
1439 | | * On out, length of encoding in bytes. |
1440 | | * @return 1 on success. |
1441 | | * @return 0 on error. |
1442 | | */ |
1443 | | int wolfSSL_ECPoint_i2d(const WOLFSSL_EC_GROUP *group, |
1444 | | const WOLFSSL_EC_POINT *point, unsigned char *out, unsigned int *len) |
1445 | 0 | { |
1446 | 0 | int res = 1; |
1447 | |
|
1448 | 0 | WOLFSSL_ENTER("wolfSSL_ECPoint_i2d"); |
1449 | | |
1450 | | /* Validate parameters. */ |
1451 | 0 | if ((group == NULL) || (point == NULL) || (len == NULL)) { |
1452 | 0 | WOLFSSL_MSG("wolfSSL_ECPoint_i2d NULL error"); |
1453 | 0 | res = 0; |
1454 | 0 | } |
1455 | | |
1456 | | /* Ensure points internals are set up. */ |
1457 | 0 | if ((res == 1) && (ec_point_setup(point) != 1)) { |
1458 | 0 | res = 0; |
1459 | 0 | } |
1460 | | |
1461 | | /* Dump the point if encoding. */ |
1462 | 0 | if ((res == 1) && (out != NULL)) { |
1463 | 0 | wolfSSL_EC_POINT_dump("i2d p", point); |
1464 | 0 | } |
1465 | |
|
1466 | 0 | if (res == 1) { |
1467 | | /* DER encode point in uncompressed format. */ |
1468 | 0 | int ret = wc_ecc_export_point_der(group->curve_idx, |
1469 | 0 | (ecc_point*)point->internal, out, len); |
1470 | | /* Check return. When out is NULL, return will be length only error. */ |
1471 | 0 | if ((ret != MP_OKAY) && ((out != NULL) || |
1472 | 0 | (ret != WC_NO_ERR_TRACE(LENGTH_ONLY_E)))) { |
1473 | 0 | WOLFSSL_MSG("wolfSSL_ECPoint_i2d wc_ecc_export_point_der failed"); |
1474 | 0 | res = 0; |
1475 | 0 | } |
1476 | 0 | } |
1477 | |
|
1478 | 0 | return res; |
1479 | 0 | } |
1480 | | |
1481 | | /* Decode the uncompressed point in DER into EC point. |
1482 | | * |
1483 | | * Return code compliant with OpenSSL. |
1484 | | * Not OpenSSL API. |
1485 | | * |
1486 | | * @param [in] in Buffer containing DER encoded point. |
1487 | | * @param [in] len Length of data in bytes. |
1488 | | * @param [in] group EC group associated with point. |
1489 | | * @param [in, out] point EC point to set data into. |
1490 | | * @return 1 on success. |
1491 | | * @return 0 on error. |
1492 | | */ |
1493 | | int wolfSSL_ECPoint_d2i(const unsigned char *in, unsigned int len, |
1494 | | const WOLFSSL_EC_GROUP *group, WOLFSSL_EC_POINT *point) |
1495 | 0 | { |
1496 | 0 | int ret = 1; |
1497 | 0 | WOLFSSL_BIGNUM* x = NULL; |
1498 | 0 | WOLFSSL_BIGNUM* y = NULL; |
1499 | |
|
1500 | 0 | WOLFSSL_ENTER("wolfSSL_ECPoint_d2i"); |
1501 | | |
1502 | | /* Validate parameters. */ |
1503 | 0 | if ((in == NULL) || (group == NULL) || (point == NULL) || |
1504 | 0 | (point->internal == NULL)) { |
1505 | 0 | WOLFSSL_MSG("wolfSSL_ECPoint_d2i NULL error"); |
1506 | 0 | ret = 0; |
1507 | 0 | } |
1508 | |
|
1509 | 0 | if (ret == 1) { |
1510 | 0 | #if !defined(HAVE_SELFTEST) && (!defined(HAVE_FIPS) || FIPS_VERSION_GT(2,0)) |
1511 | | /* Import point into internal EC point. */ |
1512 | 0 | if (wc_ecc_import_point_der_ex(in, len, group->curve_idx, |
1513 | 0 | (ecc_point*)point->internal, 0) != MP_OKAY) { |
1514 | 0 | WOLFSSL_MSG("wc_ecc_import_point_der_ex failed"); |
1515 | 0 | ret = 0; |
1516 | 0 | } |
1517 | | #else |
1518 | | /* ECC_POINT_UNCOMP is not defined CAVP self test so use magic number */ |
1519 | | if (in[0] == 0x04) { |
1520 | | /* Import point into internal EC point. */ |
1521 | | if (wc_ecc_import_point_der((unsigned char *)in, len, |
1522 | | group->curve_idx, (ecc_point*)point->internal) != MP_OKAY) { |
1523 | | WOLFSSL_MSG("wc_ecc_import_point_der failed"); |
1524 | | ret = 0; |
1525 | | } |
1526 | | } |
1527 | | else { |
1528 | | WOLFSSL_MSG("Only uncompressed points supported with " |
1529 | | "HAVE_SELFTEST"); |
1530 | | ret = 0; |
1531 | | } |
1532 | | #endif |
1533 | 0 | } |
1534 | |
|
1535 | 0 | if (ret == 1) |
1536 | 0 | point->inSet = 1; |
1537 | | |
1538 | | /* Set new external point. */ |
1539 | 0 | if (ret == 1 && ec_point_external_set(point) != 1) { |
1540 | 0 | WOLFSSL_MSG("ec_point_external_set failed"); |
1541 | 0 | ret = 0; |
1542 | 0 | } |
1543 | |
|
1544 | 0 | if (ret == 1 && !wolfSSL_BN_is_one(point->Z)) { |
1545 | 0 | #if !defined(WOLFSSL_SP_MATH) && !defined(WOLF_CRYPTO_CB_ONLY_ECC) |
1546 | 0 | x = wolfSSL_BN_new(); |
1547 | 0 | y = wolfSSL_BN_new(); |
1548 | 0 | if (x == NULL || y == NULL) |
1549 | 0 | ret = 0; |
1550 | |
|
1551 | 0 | if (ret == 1 && wolfSSL_EC_POINT_get_affine_coordinates_GFp(group, |
1552 | 0 | point, x, y, NULL) != 1) { |
1553 | 0 | WOLFSSL_MSG("wolfSSL_EC_POINT_get_affine_coordinates_GFp failed"); |
1554 | 0 | ret = 0; |
1555 | 0 | } |
1556 | | |
1557 | | /* wolfSSL_EC_POINT_set_affine_coordinates_GFp checks that the point is |
1558 | | * on the curve. */ |
1559 | 0 | if (ret == 1 && wolfSSL_EC_POINT_set_affine_coordinates_GFp(group, |
1560 | 0 | point, x, y, NULL) != 1) { |
1561 | 0 | WOLFSSL_MSG("wolfSSL_EC_POINT_set_affine_coordinates_GFp failed"); |
1562 | 0 | ret = 0; |
1563 | 0 | } |
1564 | | #else |
1565 | | WOLFSSL_MSG("Importing non-affine point. This may cause issues in math " |
1566 | | "operations later on."); |
1567 | | #endif |
1568 | 0 | } |
1569 | 0 | #if !defined(HAVE_SELFTEST) && (!defined(HAVE_FIPS) || FIPS_VERSION_GT(2,0)) |
1570 | | /* Validate that the imported point lies on the curve. The Z!=1 path |
1571 | | * above validates via set_affine_coordinates_GFp, but for affine |
1572 | | * imports (Z==1), the common case for uncompressed points, that |
1573 | | * block is skipped. Check unconditionally so no import path can |
1574 | | * bypass validation. */ |
1575 | 0 | if (ret == 1 && wolfSSL_EC_POINT_is_on_curve(group, |
1576 | 0 | (WOLFSSL_EC_POINT *)point, NULL) != 1) { |
1577 | 0 | WOLFSSL_MSG("wolfSSL_ECPoint_d2i: point not on curve"); |
1578 | 0 | ret = 0; |
1579 | 0 | } |
1580 | 0 | #endif |
1581 | |
|
1582 | 0 | if (ret == 1) { |
1583 | | /* Dump new point. */ |
1584 | 0 | wolfSSL_EC_POINT_dump("d2i p", point); |
1585 | 0 | } |
1586 | |
|
1587 | 0 | wolfSSL_BN_free(x); |
1588 | 0 | wolfSSL_BN_free(y); |
1589 | |
|
1590 | 0 | return ret; |
1591 | 0 | } |
1592 | | |
1593 | | /* Encode point as octet string. |
1594 | | * |
1595 | | * HYBRID not supported. |
1596 | | * |
1597 | | * @param [in] group EC group that point belongs to. |
1598 | | * @param [in] point EC point to encode. |
1599 | | * @param [in] form Format of encoding. Valid values: |
1600 | | * POINT_CONVERSION_UNCOMPRESSED,POINT_CONVERSION_COMPRESSED |
1601 | | * @param [out] buf Buffer to write encoding into. |
1602 | | * @param [in] len Length of buffer. |
1603 | | * @param [in] ctx Context to use for BN operations. Unused. |
1604 | | * @return Length of encoded data on success. |
1605 | | * @return 0 on error. |
1606 | | */ |
1607 | | size_t wolfSSL_EC_POINT_point2oct(const WOLFSSL_EC_GROUP *group, |
1608 | | const WOLFSSL_EC_POINT *point, int form, byte *buf, size_t len, |
1609 | | WOLFSSL_BN_CTX *ctx) |
1610 | 0 | { |
1611 | 0 | int err = 0; |
1612 | 0 | word32 enc_len = (word32)len; |
1613 | 0 | #if !defined(HAVE_SELFTEST) && (!defined(HAVE_FIPS) || FIPS_VERSION_GT(2,0)) |
1614 | 0 | int compressed = ((form == WC_POINT_CONVERSION_COMPRESSED) ? 1 : 0); |
1615 | 0 | #endif /* !HAVE_SELFTEST */ |
1616 | |
|
1617 | 0 | WOLFSSL_ENTER("wolfSSL_EC_POINT_point2oct"); |
1618 | | |
1619 | | /* No BN operations performed. */ |
1620 | 0 | (void)ctx; |
1621 | | |
1622 | | /* Validate parameters. */ |
1623 | 0 | if ((group == NULL) || (point == NULL)) { |
1624 | 0 | err = 1; |
1625 | 0 | } |
1626 | | |
1627 | | /* Ensure points internals are set up. */ |
1628 | 0 | if ((!err) && (ec_point_setup(point) != 1)) { |
1629 | 0 | err = 1; |
1630 | 0 | } |
1631 | | |
1632 | | /* Special case when point is infinity. */ |
1633 | 0 | if ((!err) && wolfSSL_EC_POINT_is_at_infinity(group, point)) { |
1634 | | /* Encoding is a single octet: 0x00. */ |
1635 | 0 | enc_len = 1; |
1636 | 0 | if (buf != NULL) { |
1637 | | /* Check whether buffer has space. */ |
1638 | 0 | if (len < 1) { |
1639 | 0 | wolfSSL_ECerr(WOLFSSL_EC_F_EC_GFP_SIMPLE_POINT2OCT, BUFFER_E); |
1640 | 0 | err = 1; |
1641 | 0 | } |
1642 | 0 | else { |
1643 | | /* Put in encoding of infinity. */ |
1644 | 0 | buf[0] = 0x00; |
1645 | 0 | } |
1646 | 0 | } |
1647 | 0 | } |
1648 | | /* Not infinity. */ |
1649 | 0 | else if (!err) { |
1650 | | /* Validate format. */ |
1651 | 0 | if (form != WC_POINT_CONVERSION_UNCOMPRESSED |
1652 | 0 | #ifndef HAVE_SELFTEST |
1653 | 0 | && form != WC_POINT_CONVERSION_COMPRESSED |
1654 | 0 | #endif /* !HAVE_SELFTEST */ |
1655 | 0 | ) { |
1656 | 0 | WOLFSSL_MSG("Unsupported point form"); |
1657 | 0 | err = 1; |
1658 | 0 | } |
1659 | |
|
1660 | 0 | if (!err) { |
1661 | 0 | int ret; |
1662 | |
|
1663 | 0 | #if !defined(HAVE_SELFTEST) && (!defined(HAVE_FIPS) || FIPS_VERSION_GT(2,0)) |
1664 | | /* Encode as compressed or uncompressed. */ |
1665 | 0 | ret = wc_ecc_export_point_der_ex(group->curve_idx, |
1666 | 0 | (ecc_point*)point->internal, buf, &enc_len, compressed); |
1667 | | #else |
1668 | | /* Encode uncompressed point in DER format. */ |
1669 | | ret = wc_ecc_export_point_der(group->curve_idx, |
1670 | | (ecc_point*)point->internal, buf, &enc_len); |
1671 | | #endif /* !HAVE_SELFTEST */ |
1672 | | /* Check return. When buf is NULL, return will be length only |
1673 | | * error. |
1674 | | */ |
1675 | 0 | if (ret != ((buf != NULL) ? MP_OKAY : |
1676 | 0 | WC_NO_ERR_TRACE(LENGTH_ONLY_E))) { |
1677 | 0 | err = 1; |
1678 | 0 | } |
1679 | 0 | } |
1680 | 0 | } |
1681 | |
|
1682 | | #if defined(DEBUG_WOLFSSL) |
1683 | | if (!err) { |
1684 | | wolfSSL_EC_POINT_dump("wolfSSL_EC_POINT_point2oct point", point); |
1685 | | WOLFSSL_MSG("\twolfSSL_EC_POINT_point2oct output:"); |
1686 | | WOLFSSL_BUFFER(buf, enc_len); |
1687 | | } |
1688 | | #endif |
1689 | | |
1690 | | /* On error, return encoding length of 0. */ |
1691 | 0 | if (err) { |
1692 | 0 | enc_len = 0; |
1693 | 0 | } |
1694 | 0 | return (size_t)enc_len; |
1695 | 0 | } |
1696 | | |
1697 | | |
1698 | | /* Convert octet string to EC point. |
1699 | | * |
1700 | | * @param [in] group EC group. |
1701 | | * @param [in, out] point EC point to set data into. |
1702 | | * @param [in] buf Buffer holding octet string. |
1703 | | * @param [in] len Length of data in buffer in bytes. |
1704 | | * @param [in] ctx Context to use for BN operations. Unused. |
1705 | | */ |
1706 | | int wolfSSL_EC_POINT_oct2point(const WOLFSSL_EC_GROUP *group, |
1707 | | WOLFSSL_EC_POINT *point, const unsigned char *buf, size_t len, |
1708 | | WOLFSSL_BN_CTX *ctx) |
1709 | 0 | { |
1710 | 0 | int ret; |
1711 | |
|
1712 | 0 | WOLFSSL_ENTER("wolfSSL_EC_POINT_oct2point"); |
1713 | | |
1714 | | /* No BN operations performed. */ |
1715 | 0 | (void)ctx; |
1716 | | |
1717 | | /* Validate parameters. */ |
1718 | 0 | if ((group == NULL) || (point == NULL)) { |
1719 | 0 | ret = 0; |
1720 | 0 | } |
1721 | 0 | else { |
1722 | | /* Decode DER encoding into EC point. */ |
1723 | 0 | ret = wolfSSL_ECPoint_d2i((unsigned char*)buf, (unsigned int)len, group, |
1724 | 0 | point); |
1725 | 0 | } |
1726 | |
|
1727 | 0 | return ret; |
1728 | 0 | } |
1729 | | |
1730 | | /* Convert an EC point to a single BN. |
1731 | | * |
1732 | | * @param [in] group EC group. |
1733 | | * @param [in] point EC point. |
1734 | | * @param [in] form Format of encoding. Valid values: |
1735 | | * WC_POINT_CONVERSION_UNCOMPRESSED, |
1736 | | * WC_POINT_CONVERSION_COMPRESSED. |
1737 | | * @param [in, out] bn BN to hold point value. |
1738 | | * When NULL a new BN is allocated otherwise this is |
1739 | | * returned on success. |
1740 | | * @param [in] ctx Context to use for BN operations. Unused. |
1741 | | * @return BN object with point as a value on success. |
1742 | | * @return NULL on error. |
1743 | | */ |
1744 | | WOLFSSL_BIGNUM *wolfSSL_EC_POINT_point2bn(const WOLFSSL_EC_GROUP* group, |
1745 | | const WOLFSSL_EC_POINT* point, int form, WOLFSSL_BIGNUM* bn, |
1746 | | WOLFSSL_BN_CTX* ctx) |
1747 | 0 | { |
1748 | 0 | int err = 0; |
1749 | 0 | size_t len = 0; |
1750 | 0 | byte *buf = NULL; |
1751 | 0 | WOLFSSL_BIGNUM *ret = NULL; |
1752 | |
|
1753 | 0 | WOLFSSL_ENTER("wolfSSL_EC_POINT_oct2point"); |
1754 | | |
1755 | | /* Validate parameters. */ |
1756 | 0 | if ((group == NULL) || (point == NULL)) { |
1757 | 0 | err = 1; |
1758 | 0 | } |
1759 | | |
1760 | | /* Calculate length of octet encoding. */ |
1761 | 0 | if ((!err) && ((len = wolfSSL_EC_POINT_point2oct(group, point, form, NULL, |
1762 | 0 | 0, ctx)) == 0)) { |
1763 | 0 | err = 1; |
1764 | 0 | } |
1765 | | /* Allocate buffer to hold octet encoding. */ |
1766 | 0 | if ((!err) && ((buf = (byte*)XMALLOC(len, NULL, DYNAMIC_TYPE_TMP_BUFFER)) == |
1767 | 0 | NULL)) { |
1768 | 0 | WOLFSSL_MSG("malloc failed"); |
1769 | 0 | err = 1; |
1770 | 0 | } |
1771 | | /* Encode EC point as an octet string. */ |
1772 | 0 | if ((!err) && (wolfSSL_EC_POINT_point2oct(group, point, form, buf, len, |
1773 | 0 | ctx) != len)) { |
1774 | 0 | err = 1; |
1775 | 0 | } |
1776 | | /* Load BN with octet string data. */ |
1777 | 0 | if (!err) { |
1778 | 0 | ret = wolfSSL_BN_bin2bn(buf, (int)len, bn); |
1779 | 0 | } |
1780 | | |
1781 | | /* Dispose of any allocated data. */ |
1782 | 0 | XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER); |
1783 | |
|
1784 | 0 | return ret; |
1785 | 0 | } |
1786 | | |
1787 | | #if !defined(HAVE_SELFTEST) && (!defined(HAVE_FIPS) || FIPS_VERSION_GT(2,0)) |
1788 | | /* Check if EC point is on the the curve defined by the EC group. |
1789 | | * |
1790 | | * @param [in] group EC group defining curve. |
1791 | | * @param [in] point EC point to check. |
1792 | | * @param [in] ctx Context to use for BN operations. Unused. |
1793 | | * @return 1 when point is on curve. |
1794 | | * @return 0 when point is not on curve or error. |
1795 | | */ |
1796 | | int wolfSSL_EC_POINT_is_on_curve(const WOLFSSL_EC_GROUP *group, |
1797 | | const WOLFSSL_EC_POINT *point, WOLFSSL_BN_CTX *ctx) |
1798 | 573 | { |
1799 | 573 | int err = 0; |
1800 | | |
1801 | 573 | WOLFSSL_ENTER("wolfSSL_EC_POINT_is_on_curve"); |
1802 | | |
1803 | | /* No BN operations performed. */ |
1804 | 573 | (void)ctx; |
1805 | | |
1806 | | /* Validate parameters. */ |
1807 | 573 | if ((group == NULL) || (point == NULL)) { |
1808 | 0 | WOLFSSL_MSG("Invalid arguments"); |
1809 | 0 | err = 1; |
1810 | 0 | } |
1811 | | |
1812 | | /* Ensure internal EC point set. */ |
1813 | 573 | if ((!err) && (!point->inSet) && ec_point_internal_set( |
1814 | 0 | (WOLFSSL_EC_POINT*)point) != 1) { |
1815 | 0 | WOLFSSL_MSG("ec_point_internal_set error"); |
1816 | 0 | err = 1; |
1817 | 0 | } |
1818 | | |
1819 | | /* Check point is on curve from group. */ |
1820 | 573 | if ((!err) && (wc_ecc_point_is_on_curve((ecc_point*)point->internal, |
1821 | 573 | group->curve_idx) != MP_OKAY)) { |
1822 | 78 | err = 1; |
1823 | 78 | } |
1824 | | |
1825 | | /* Return boolean of on curve. No error means on curve. */ |
1826 | 573 | return !err; |
1827 | 573 | } |
1828 | | #endif /* !HAVE_SELFTEST && !(HAVE_FIPS && FIPS_VERSION <= 2) */ |
1829 | | |
1830 | | #if !defined(WOLFSSL_SP_MATH) && !defined(WOLF_CRYPTO_CB_ONLY_ECC) |
1831 | | /* Convert Jacobian ordinates to affine. |
1832 | | * |
1833 | | * @param [in] group EC group. |
1834 | | * @param [in] point EC point to get coordinates from. |
1835 | | * @return 1 on success. |
1836 | | * @return 0 on error. |
1837 | | */ |
1838 | | int ec_point_convert_to_affine(const WOLFSSL_EC_GROUP *group, |
1839 | | WOLFSSL_EC_POINT *point) |
1840 | 0 | { |
1841 | 0 | int err = 0; |
1842 | 0 | mp_digit mp = 0; |
1843 | 0 | WC_DECLARE_VAR(modulus, mp_int, 1, 0); |
1844 | | |
1845 | | /* Allocate memory for curve's prime modulus. */ |
1846 | 0 | WC_ALLOC_VAR_EX(modulus, mp_int, 1, NULL, DYNAMIC_TYPE_BIGINT, err=1); |
1847 | | /* Initialize the MP integer. */ |
1848 | 0 | if ((!err) && (mp_init(modulus) != MP_OKAY)) { |
1849 | 0 | WOLFSSL_MSG("mp_init failed"); |
1850 | 0 | err = 1; |
1851 | 0 | } |
1852 | |
|
1853 | 0 | if (!err) { |
1854 | | /* Get the modulus from the hex string in the EC curve set. */ |
1855 | 0 | if (mp_read_radix(modulus, ecc_sets[group->curve_idx].prime, |
1856 | 0 | MP_RADIX_HEX) != MP_OKAY) { |
1857 | 0 | WOLFSSL_MSG("mp_read_radix failed"); |
1858 | 0 | err = 1; |
1859 | 0 | } |
1860 | | /* Get Montgomery multiplier for the modulus as ordinates in |
1861 | | * Montgomery form. |
1862 | | */ |
1863 | 0 | if ((!err) && (mp_montgomery_setup(modulus, &mp) != MP_OKAY)) { |
1864 | 0 | WOLFSSL_MSG("mp_montgomery_setup failed"); |
1865 | 0 | err = 1; |
1866 | 0 | } |
1867 | | /* Map internal EC point from Jacobian to affine. */ |
1868 | 0 | if ((!err) && (ecc_map((ecc_point*)point->internal, modulus, mp) != |
1869 | 0 | MP_OKAY)) { |
1870 | 0 | WOLFSSL_MSG("ecc_map failed"); |
1871 | 0 | err = 1; |
1872 | 0 | } |
1873 | | /* Set new ordinates into external EC point. */ |
1874 | 0 | if ((!err) && (ec_point_external_set((WOLFSSL_EC_POINT *)point) != 1)) { |
1875 | 0 | WOLFSSL_MSG("ec_point_external_set failed"); |
1876 | 0 | err = 1; |
1877 | 0 | } |
1878 | |
|
1879 | 0 | point->exSet = !err; |
1880 | 0 | mp_clear(modulus); |
1881 | 0 | } |
1882 | |
|
1883 | 0 | WC_FREE_VAR_EX(modulus, NULL, DYNAMIC_TYPE_BIGINT); |
1884 | |
|
1885 | 0 | return err; |
1886 | 0 | } |
1887 | | |
1888 | | /* Get the affine coordinates of the EC point on a Prime curve. |
1889 | | * |
1890 | | * When z-ordinate is not one then coordinates are Jacobian and need to be |
1891 | | * converted to affine before storing in BNs. |
1892 | | * |
1893 | | * Return code compliant with OpenSSL. |
1894 | | * |
1895 | | * TODO: OpenSSL doesn't change point when Jacobian. Do the same? |
1896 | | * |
1897 | | * @param [in] group EC group. |
1898 | | * @param [in] point EC point to get coordinates from. |
1899 | | * @param [in, out] x BN to hold x-ordinate. |
1900 | | * @param [in, out] y BN to hold y-ordinate. |
1901 | | * @param [in] ctx Context to use for BN operations. Unused. |
1902 | | * @return 1 on success. |
1903 | | * @return 0 on error. |
1904 | | */ |
1905 | | int wolfSSL_EC_POINT_get_affine_coordinates_GFp(const WOLFSSL_EC_GROUP* group, |
1906 | | const WOLFSSL_EC_POINT* point, WOLFSSL_BIGNUM* x, WOLFSSL_BIGNUM* y, |
1907 | | WOLFSSL_BN_CTX* ctx) |
1908 | 358 | { |
1909 | 358 | int ret = 1; |
1910 | | |
1911 | | /* BN operations don't need context. */ |
1912 | 358 | (void)ctx; |
1913 | | |
1914 | 358 | WOLFSSL_ENTER("wolfSSL_EC_POINT_get_affine_coordinates_GFp"); |
1915 | | |
1916 | | /* Validate parameters. */ |
1917 | 358 | if ((group == NULL) || (point == NULL) || (point->internal == NULL) || |
1918 | 358 | (x == NULL) || (y == NULL)) { |
1919 | 0 | WOLFSSL_MSG("wolfSSL_EC_POINT_get_affine_coordinates_GFp NULL error"); |
1920 | 0 | ret = 0; |
1921 | 0 | } |
1922 | | /* Don't return point at infinity. */ |
1923 | 358 | if ((ret == 1) && wolfSSL_EC_POINT_is_at_infinity(group, point)) { |
1924 | 7 | ret = 0; |
1925 | 7 | } |
1926 | | |
1927 | | /* Ensure internal EC point has values of external EC point. */ |
1928 | 358 | if ((ret == 1) && (ec_point_setup(point) != 1)) { |
1929 | 0 | ret = 0; |
1930 | 0 | } |
1931 | | |
1932 | | /* Check whether ordinates are in Jacobian form. */ |
1933 | 358 | if ((ret == 1) && (!wolfSSL_BN_is_one(point->Z))) { |
1934 | | /* Convert from Jacobian to affine. */ |
1935 | 0 | if (ec_point_convert_to_affine(group, (WOLFSSL_EC_POINT*)point) == 1) { |
1936 | 0 | ret = 0; |
1937 | 0 | } |
1938 | 0 | } |
1939 | | |
1940 | | /* Copy the externally set x and y ordinates. */ |
1941 | 358 | if ((ret == 1) && (wolfSSL_BN_copy(x, point->X) == NULL)) { |
1942 | 0 | ret = 0; |
1943 | 0 | } |
1944 | 358 | if ((ret == 1) && (wolfSSL_BN_copy(y, point->Y) == NULL)) { |
1945 | 0 | ret = 0; |
1946 | 0 | } |
1947 | | |
1948 | 358 | return ret; |
1949 | 358 | } |
1950 | | #endif /* !WOLFSSL_SP_MATH && !WOLF_CRYPTO_CB_ONLY_ECC */ |
1951 | | |
1952 | | /* Sets the affine coordinates that belong on a prime curve. |
1953 | | * |
1954 | | * @param [in] group EC group. |
1955 | | * @param [in, out] point EC point to set coordinates into. |
1956 | | * @param [in] x BN holding x-ordinate. |
1957 | | * @param [in] y BN holding y-ordinate. |
1958 | | * @param [in] ctx Context to use for BN operations. Unused. |
1959 | | * @return 1 on success. |
1960 | | * @return 0 on error. |
1961 | | */ |
1962 | | int wolfSSL_EC_POINT_set_affine_coordinates_GFp(const WOLFSSL_EC_GROUP* group, |
1963 | | WOLFSSL_EC_POINT* point, const WOLFSSL_BIGNUM* x, const WOLFSSL_BIGNUM* y, |
1964 | | WOLFSSL_BN_CTX* ctx) |
1965 | 563 | { |
1966 | 563 | int ret = 1; |
1967 | | |
1968 | | /* BN operations don't need context. */ |
1969 | 563 | (void)ctx; |
1970 | | |
1971 | 563 | WOLFSSL_ENTER("wolfSSL_EC_POINT_set_affine_coordinates_GFp"); |
1972 | | |
1973 | | /* Validate parameters. */ |
1974 | 563 | if ((group == NULL) || (point == NULL) || (point->internal == NULL) || |
1975 | 563 | (x == NULL) || (y == NULL)) { |
1976 | 0 | WOLFSSL_MSG("wolfSSL_EC_POINT_set_affine_coordinates_GFp NULL error"); |
1977 | 0 | ret = 0; |
1978 | 0 | } |
1979 | | |
1980 | | /* Ensure we have a object for x-ordinate. */ |
1981 | 563 | if ((ret == 1) && (point->X == NULL) && |
1982 | 159 | ((point->X = wolfSSL_BN_new()) == NULL)) { |
1983 | 0 | WOLFSSL_MSG("wolfSSL_BN_new failed"); |
1984 | 0 | ret = 0; |
1985 | 0 | } |
1986 | | /* Ensure we have a object for y-ordinate. */ |
1987 | 563 | if ((ret == 1) && (point->Y == NULL) && |
1988 | 159 | ((point->Y = wolfSSL_BN_new()) == NULL)) { |
1989 | 0 | WOLFSSL_MSG("wolfSSL_BN_new failed"); |
1990 | 0 | ret = 0; |
1991 | 0 | } |
1992 | | /* Ensure we have a object for z-ordinate. */ |
1993 | 563 | if ((ret == 1) && (point->Z == NULL) && |
1994 | 159 | ((point->Z = wolfSSL_BN_new()) == NULL)) { |
1995 | 0 | WOLFSSL_MSG("wolfSSL_BN_new failed"); |
1996 | 0 | ret = 0; |
1997 | 0 | } |
1998 | | |
1999 | | /* Copy the x-ordinate. */ |
2000 | 563 | if ((ret == 1) && ((wolfSSL_BN_copy(point->X, x)) == NULL)) { |
2001 | 0 | WOLFSSL_MSG("wolfSSL_BN_copy failed"); |
2002 | 0 | ret = 0; |
2003 | 0 | } |
2004 | | /* Copy the y-ordinate. */ |
2005 | 563 | if ((ret == 1) && ((wolfSSL_BN_copy(point->Y, y)) == NULL)) { |
2006 | 0 | WOLFSSL_MSG("wolfSSL_BN_copy failed"); |
2007 | 0 | ret = 0; |
2008 | 0 | } |
2009 | | /* z-ordinate is one for affine coordinates. */ |
2010 | 563 | if ((ret == 1) && ((wolfSSL_BN_one(point->Z)) == 0)) { |
2011 | 0 | WOLFSSL_MSG("wolfSSL_BN_one failed"); |
2012 | 0 | ret = 0; |
2013 | 0 | } |
2014 | | |
2015 | | /* Copy the new point data to internal object. */ |
2016 | 563 | if ((ret == 1) && (ec_point_internal_set((WOLFSSL_EC_POINT *)point) != 1)) { |
2017 | 0 | WOLFSSL_MSG("ec_point_internal_set failed"); |
2018 | 0 | ret = 0; |
2019 | 0 | } |
2020 | | |
2021 | 563 | #if !defined(HAVE_SELFTEST) && (!defined(HAVE_FIPS) || FIPS_VERSION_GT(2,0)) |
2022 | | /* Check that the point is valid. */ |
2023 | 563 | if ((ret == 1) && (wolfSSL_EC_POINT_is_on_curve(group, |
2024 | 563 | (WOLFSSL_EC_POINT *)point, ctx) != 1)) { |
2025 | 78 | WOLFSSL_MSG("EC_POINT_is_on_curve failed"); |
2026 | 78 | ret = 0; |
2027 | 78 | } |
2028 | 563 | #endif |
2029 | | |
2030 | 563 | return ret; |
2031 | 563 | } |
2032 | | |
2033 | | #if !defined(WOLFSSL_ATECC508A) && !defined(WOLFSSL_ATECC608A) && \ |
2034 | | !defined(HAVE_SELFTEST) && !defined(WOLFSSL_SP_MATH) && \ |
2035 | | !defined(WOLF_CRYPTO_CB_ONLY_ECC) |
2036 | | /* Add two points on the same together. |
2037 | | * |
2038 | | * @param [in] curveIdx Index of curve in ecc_set. |
2039 | | * @param [out] r Result point. |
2040 | | * @param [in] p1 First point to add. |
2041 | | * @param [in] p2 Second point to add. |
2042 | | * @return 1 on success. |
2043 | | * @return 0 on error. |
2044 | | */ |
2045 | | static int wolfssl_ec_point_add(int curveIdx, ecc_point* r, ecc_point* p1, |
2046 | | ecc_point* p2) |
2047 | 29 | { |
2048 | 29 | int ret = 1; |
2049 | 29 | #ifdef WOLFSSL_SMALL_STACK |
2050 | 29 | mp_int* a = NULL; |
2051 | 29 | mp_int* prime = NULL; |
2052 | 29 | mp_int* mu = NULL; |
2053 | | #else |
2054 | | mp_int a[1]; |
2055 | | mp_int prime[1]; |
2056 | | mp_int mu[1]; |
2057 | | #endif |
2058 | 29 | mp_digit mp = 0; |
2059 | 29 | ecc_point* montP1 = NULL; |
2060 | 29 | ecc_point* montP2 = NULL; |
2061 | | |
2062 | 29 | #ifdef WOLFSSL_SMALL_STACK |
2063 | 29 | if (ret == 1) { |
2064 | | /* Allocate memory for curve parameter: a. */ |
2065 | 29 | a = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_BIGINT); |
2066 | 29 | if (a == NULL) { |
2067 | 0 | WOLFSSL_MSG("Failed to allocate memory for mp_int a"); |
2068 | 0 | ret = 0; |
2069 | 0 | } |
2070 | 29 | } |
2071 | 29 | if (ret == 1) { |
2072 | | /* Allocate memory for curve parameter: prime. */ |
2073 | 29 | prime = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_BIGINT); |
2074 | 29 | if (prime == NULL) { |
2075 | 0 | WOLFSSL_MSG("Failed to allocate memory for mp_int prime"); |
2076 | 0 | ret = 0; |
2077 | 0 | } |
2078 | 29 | } |
2079 | 29 | if (ret == 1) { |
2080 | | /* Allocate memory for mu (Montgomery normalizer). */ |
2081 | 29 | mu = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_BIGINT); |
2082 | 29 | if (mu == NULL) { |
2083 | 0 | WOLFSSL_MSG("Failed to allocate memory for mp_int mu"); |
2084 | 0 | ret = 0; |
2085 | 0 | } |
2086 | 29 | } |
2087 | 29 | if (ret == 1) { |
2088 | | /* Zero out all MP int data in case initialization fails. */ |
2089 | 29 | XMEMSET(a, 0, sizeof(mp_int)); |
2090 | 29 | XMEMSET(prime, 0, sizeof(mp_int)); |
2091 | 29 | XMEMSET(mu, 0, sizeof(mp_int)); |
2092 | 29 | } |
2093 | 29 | #endif |
2094 | | |
2095 | | /* Initialize the MP ints. */ |
2096 | 29 | if ((ret == 1) && (mp_init_multi(prime, a, mu, NULL, NULL, NULL) != |
2097 | 29 | MP_OKAY)) { |
2098 | 0 | WOLFSSL_MSG("mp_init_multi error"); |
2099 | 0 | ret = 0; |
2100 | 0 | } |
2101 | | |
2102 | | /* Read the curve parameter: a. */ |
2103 | 29 | if ((ret == 1) && (mp_read_radix(a, ecc_sets[curveIdx].Af, MP_RADIX_HEX) != |
2104 | 29 | MP_OKAY)) { |
2105 | 0 | WOLFSSL_MSG("mp_read_radix a error"); |
2106 | 0 | ret = 0; |
2107 | 0 | } |
2108 | | |
2109 | | /* Read the curve parameter: prime. */ |
2110 | 29 | if ((ret == 1) && (mp_read_radix(prime, ecc_sets[curveIdx].prime, |
2111 | 29 | MP_RADIX_HEX) != MP_OKAY)) { |
2112 | 0 | WOLFSSL_MSG("mp_read_radix prime error"); |
2113 | 0 | ret = 0; |
2114 | 0 | } |
2115 | | |
2116 | | /* Calculate the Montgomery product. */ |
2117 | 29 | if ((ret == 1) && (mp_montgomery_setup(prime, &mp) != MP_OKAY)) { |
2118 | 0 | WOLFSSL_MSG("mp_montgomery_setup nqm error"); |
2119 | 0 | ret = 0; |
2120 | 0 | } |
2121 | | |
2122 | | /* TODO: use the heap filed of one of the points? */ |
2123 | | /* Allocate new points to hold the Montgomery form values. */ |
2124 | 29 | if ((ret == 1) && (((montP1 = wc_ecc_new_point_h(NULL)) == NULL) || |
2125 | 29 | ((montP2 = wc_ecc_new_point_h(NULL)) == NULL))) { |
2126 | 0 | WOLFSSL_MSG("wc_ecc_new_point_h nqm error"); |
2127 | 0 | ret = 0; |
2128 | 0 | } |
2129 | | |
2130 | | /* Calculate the Montgomery normalizer. */ |
2131 | 29 | if ((ret == 1) && (mp_montgomery_calc_normalization(mu, prime) != |
2132 | 29 | MP_OKAY)) { |
2133 | 0 | WOLFSSL_MSG("mp_montgomery_calc_normalization error"); |
2134 | 0 | ret = 0; |
2135 | 0 | } |
2136 | | |
2137 | | /* Convert to Montgomery form. */ |
2138 | 29 | if ((ret == 1) && (mp_cmp_d(mu, 1) == MP_EQ)) { |
2139 | | /* Copy the points if the normalizer is 1. */ |
2140 | 10 | if ((wc_ecc_copy_point(p1, montP1) != MP_OKAY) || |
2141 | 10 | (wc_ecc_copy_point(p2, montP2) != MP_OKAY)) { |
2142 | 0 | WOLFSSL_MSG("wc_ecc_copy_point error"); |
2143 | 0 | ret = 0; |
2144 | 0 | } |
2145 | 10 | } |
2146 | 19 | else if (ret == 1) { |
2147 | | /* Multiply each ordinate by the Montgomery normalizer. */ |
2148 | 19 | if ((mp_mulmod(p1->x, mu, prime, montP1->x) != MP_OKAY) || |
2149 | 19 | (mp_mulmod(p1->y, mu, prime, montP1->y) != MP_OKAY) || |
2150 | 19 | (mp_mulmod(p1->z, mu, prime, montP1->z) != MP_OKAY)) { |
2151 | 0 | WOLFSSL_MSG("mp_mulmod error"); |
2152 | 0 | ret = 0; |
2153 | 0 | } |
2154 | | /* Multiply each ordinate by the Montgomery normalizer. */ |
2155 | 19 | if ((mp_mulmod(p2->x, mu, prime, montP2->x) != MP_OKAY) || |
2156 | 19 | (mp_mulmod(p2->y, mu, prime, montP2->y) != MP_OKAY) || |
2157 | 19 | (mp_mulmod(p2->z, mu, prime, montP2->z) != MP_OKAY)) { |
2158 | 0 | WOLFSSL_MSG("mp_mulmod error"); |
2159 | 0 | ret = 0; |
2160 | 0 | } |
2161 | 19 | } |
2162 | | |
2163 | | /* Perform point addition with internal EC point objects - Jacobian form |
2164 | | * result. |
2165 | | */ |
2166 | 29 | if ((ret == 1) && (ecc_projective_add_point(montP1, montP2, r, a, prime, |
2167 | 29 | mp) != MP_OKAY)) { |
2168 | 0 | WOLFSSL_MSG("ecc_projective_add_point error"); |
2169 | 0 | ret = 0; |
2170 | 0 | } |
2171 | | |
2172 | | /* Map point back to affine coordinates. Converts from Montogomery form. */ |
2173 | 29 | if ((ret == 1) && (ecc_map(r, prime, mp) != MP_OKAY)) { |
2174 | 0 | WOLFSSL_MSG("ecc_map error"); |
2175 | 0 | ret = 0; |
2176 | 0 | } |
2177 | | |
2178 | | /* Dispose of allocated memory. */ |
2179 | 29 | mp_clear(a); |
2180 | 29 | mp_clear(prime); |
2181 | 29 | mp_clear(mu); |
2182 | 29 | wc_ecc_del_point_h(montP1, NULL); |
2183 | 29 | wc_ecc_del_point_h(montP2, NULL); |
2184 | 29 | WC_FREE_VAR_EX(a, NULL, DYNAMIC_TYPE_BIGINT); |
2185 | 29 | WC_FREE_VAR_EX(prime, NULL, DYNAMIC_TYPE_BIGINT); |
2186 | 29 | WC_FREE_VAR_EX(mu, NULL, DYNAMIC_TYPE_BIGINT); |
2187 | 29 | return ret; |
2188 | 29 | } |
2189 | | |
2190 | | /* Add two points on the same curve together. |
2191 | | * |
2192 | | * @param [in] group EC group. |
2193 | | * @param [out] r EC point that is result of point addition. |
2194 | | * @param [in] p1 First EC point to add. |
2195 | | * @param [in] p2 Second EC point to add. |
2196 | | * @param [in] ctx Context to use for BN operations. Unused. |
2197 | | * @return 1 on success. |
2198 | | * @return 0 on error. |
2199 | | */ |
2200 | | int wolfSSL_EC_POINT_add(const WOLFSSL_EC_GROUP* group, WOLFSSL_EC_POINT* r, |
2201 | | const WOLFSSL_EC_POINT* p1, const WOLFSSL_EC_POINT* p2, WOLFSSL_BN_CTX* ctx) |
2202 | 29 | { |
2203 | 29 | int ret = 1; |
2204 | | |
2205 | | /* No BN operations performed. */ |
2206 | 29 | (void)ctx; |
2207 | | |
2208 | | /* Validate parameters. */ |
2209 | 29 | if ((group == NULL) || (r == NULL) || (p1 == NULL) || (p2 == NULL)) { |
2210 | 0 | WOLFSSL_MSG("wolfSSL_EC_POINT_add error"); |
2211 | 0 | ret = 0; |
2212 | 0 | } |
2213 | | |
2214 | | /* Ensure the internal objects of the EC points are setup. */ |
2215 | 29 | if ((ret == 1) && ((ec_point_setup(r) != 1) || (ec_point_setup(p1) != 1) || |
2216 | 29 | (ec_point_setup(p2) != 1))) { |
2217 | 0 | WOLFSSL_MSG("ec_point_setup error"); |
2218 | 0 | ret = 0; |
2219 | 0 | } |
2220 | | |
2221 | | #ifdef DEBUG_WOLFSSL |
2222 | | if (ret == 1) { |
2223 | | int nid = wolfSSL_EC_GROUP_get_curve_name(group); |
2224 | | const char* curve = wolfSSL_OBJ_nid2ln(nid); |
2225 | | const char* nistName = wolfSSL_EC_curve_nid2nist(nid); |
2226 | | wolfSSL_EC_POINT_dump("wolfSSL_EC_POINT_add p1", p1); |
2227 | | wolfSSL_EC_POINT_dump("wolfSSL_EC_POINT_add p2", p2); |
2228 | | if (curve != NULL) |
2229 | | WOLFSSL_MSG_EX("curve name: %s", curve); |
2230 | | if (nistName != NULL) |
2231 | | WOLFSSL_MSG_EX("nist curve name: %s", nistName); |
2232 | | } |
2233 | | #endif |
2234 | | |
2235 | 29 | if (ret == 1) { |
2236 | | /* Add points using wolfCrypt objects. */ |
2237 | 29 | ret = wolfssl_ec_point_add(group->curve_idx, (ecc_point*)r->internal, |
2238 | 29 | (ecc_point*)p1->internal, (ecc_point*)p2->internal); |
2239 | 29 | } |
2240 | | |
2241 | | /* Copy internal EC point values out to external EC point. */ |
2242 | 29 | if ((ret == 1) && (ec_point_external_set(r) != 1)) { |
2243 | 0 | WOLFSSL_MSG("ec_point_external_set error"); |
2244 | 0 | ret = 0; |
2245 | 0 | } |
2246 | | |
2247 | | #ifdef DEBUG_WOLFSSL |
2248 | | if (ret == 1) { |
2249 | | wolfSSL_EC_POINT_dump("wolfSSL_EC_POINT_add result", r); |
2250 | | } |
2251 | | #endif |
2252 | | |
2253 | 29 | return ret; |
2254 | 29 | } |
2255 | | |
2256 | | /* Sum the scalar multiplications of the base point and n, and q and m. |
2257 | | * |
2258 | | * r = base point * n + q * m |
2259 | | * |
2260 | | * @param [out] r EC point that is result of operation. |
2261 | | * @param [in] b Base point of curve. |
2262 | | * @param [in] n Scalar to multiply by base point. |
2263 | | * @param [in] q EC point to be scalar multiplied. |
2264 | | * @param [in] m Scalar to multiply q by. |
2265 | | * @param [in] a Parameter A of curve. |
2266 | | * @param [in] prime Prime (modulus) of curve. |
2267 | | * @return 1 on success. |
2268 | | * @return 0 on error. |
2269 | | */ |
2270 | | static int ec_mul2add(ecc_point* r, ecc_point* b, mp_int* n, ecc_point* q, |
2271 | | mp_int* m, mp_int* a, mp_int* prime) |
2272 | 0 | { |
2273 | 0 | int ret = 1; |
2274 | 0 | #if defined(ECC_SHAMIR) && !defined(WOLFSSL_KCAPI_ECC) |
2275 | 0 | if (ecc_mul2add(b, n, q, m, r, a, prime, NULL) != MP_OKAY) { |
2276 | 0 | WOLFSSL_MSG("ecc_mul2add error"); |
2277 | 0 | ret = 0; |
2278 | 0 | } |
2279 | | #else |
2280 | | ecc_point* tmp = NULL; |
2281 | | mp_digit mp = 0; |
2282 | | |
2283 | | /* Calculate Montgomery product. */ |
2284 | | if (mp_montgomery_setup(prime, &mp) != MP_OKAY) { |
2285 | | WOLFSSL_MSG("mp_montgomery_setup nqm error"); |
2286 | | ret = 0; |
2287 | | } |
2288 | | /* Create temporary point to hold: q * m */ |
2289 | | if ((ret == 1) && ((tmp = wc_ecc_new_point()) == NULL)) { |
2290 | | WOLFSSL_MSG("wolfSSL_EC_POINT_new nqm error"); |
2291 | | ret = 0; |
2292 | | } |
2293 | | /* r = base point * n */ |
2294 | | if ((ret == 1) && (wc_ecc_mulmod(n, b, r, a, prime, 0) != |
2295 | | MP_OKAY)) { |
2296 | | WOLFSSL_MSG("wc_ecc_mulmod nqm error"); |
2297 | | ret = 0; |
2298 | | } |
2299 | | /* tmp = q * m */ |
2300 | | if ((ret == 1) && (wc_ecc_mulmod(m, q, tmp, a, prime, 0) != MP_OKAY)) { |
2301 | | WOLFSSL_MSG("wc_ecc_mulmod nqm error"); |
2302 | | ret = 0; |
2303 | | } |
2304 | | /* r = r + tmp */ |
2305 | | if ((ret == 1) && (ecc_projective_add_point(tmp, r, r, a, prime, mp) != |
2306 | | MP_OKAY)) { |
2307 | | WOLFSSL_MSG("wc_ecc_mulmod nqm error"); |
2308 | | ret = 0; |
2309 | | } |
2310 | | /* Map point back to affine coordinates. Converts from Montogomery |
2311 | | * form. */ |
2312 | | if ((ret == 1) && (ecc_map(r, prime, mp) != MP_OKAY)) { |
2313 | | WOLFSSL_MSG("ecc_map nqm error"); |
2314 | | ret = 0; |
2315 | | } |
2316 | | |
2317 | | /* Dispose of allocated temporary point. */ |
2318 | | wc_ecc_del_point(tmp); |
2319 | | #endif |
2320 | |
|
2321 | 0 | return ret; |
2322 | 0 | } |
2323 | | |
2324 | | /* Sum the scalar multiplications of the base point and n, and q and m. |
2325 | | * |
2326 | | * r = base point * n + q * m |
2327 | | * |
2328 | | * @param [in] curveIdx Index of curve in ecc_set. |
2329 | | * @param [out] r EC point that is result of operation. |
2330 | | * @param [in] n Scalar to multiply by base point. May be NULL. |
2331 | | * @param [in] q EC point to be scalar multiplied. May be NULL. |
2332 | | * @param [in] m Scalar to multiply q by. May be NULL. |
2333 | | * @return 1 on success. |
2334 | | * @return 0 on error. |
2335 | | */ |
2336 | | static int wolfssl_ec_point_mul(int curveIdx, ecc_point* r, mp_int* n, |
2337 | | ecc_point* q, mp_int* m) |
2338 | 351 | { |
2339 | 351 | int ret = 1; |
2340 | 351 | #ifdef WOLFSSL_SMALL_STACK |
2341 | 351 | mp_int* a = NULL; |
2342 | 351 | mp_int* prime = NULL; |
2343 | | #else |
2344 | | mp_int a[1], prime[1]; |
2345 | | #endif |
2346 | | |
2347 | 351 | #ifdef WOLFSSL_SMALL_STACK |
2348 | | /* Allocate MP integer for curve parameter: a. */ |
2349 | 351 | a = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_BIGINT); |
2350 | 351 | if (a == NULL) { |
2351 | 0 | ret = 0; |
2352 | 0 | } |
2353 | 351 | if (ret == 1) { |
2354 | | /* Allocate MP integer for curve parameter: prime. */ |
2355 | 351 | prime = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_BIGINT); |
2356 | 351 | if (prime == NULL) { |
2357 | 0 | ret = 0; |
2358 | 0 | } |
2359 | 351 | } |
2360 | 351 | #endif |
2361 | | |
2362 | | /* Initialize the MP ints. */ |
2363 | 351 | if ((ret == 1) && (mp_init_multi(prime, a, NULL, NULL, NULL, NULL) != |
2364 | 351 | MP_OKAY)) { |
2365 | 0 | WOLFSSL_MSG("mp_init_multi error"); |
2366 | 0 | ret = 0; |
2367 | 0 | } |
2368 | | |
2369 | | /* Read the curve parameter: prime. */ |
2370 | 351 | if ((ret == 1) && (mp_read_radix(prime, ecc_sets[curveIdx].prime, |
2371 | 351 | MP_RADIX_HEX) != MP_OKAY)) { |
2372 | 0 | WOLFSSL_MSG("mp_read_radix prime error"); |
2373 | 0 | ret = 0; |
2374 | 0 | } |
2375 | | |
2376 | | /* Read the curve parameter: a. */ |
2377 | 351 | if ((ret == 1) && (mp_read_radix(a, ecc_sets[curveIdx].Af, |
2378 | 351 | MP_RADIX_HEX) != MP_OKAY)) { |
2379 | 0 | WOLFSSL_MSG("mp_read_radix a error"); |
2380 | 0 | ret = 0; |
2381 | 0 | } |
2382 | | |
2383 | 351 | if ((ret == 1) && (n != NULL)) { |
2384 | | /* Get generator - base point. */ |
2385 | 337 | #if !defined(HAVE_FIPS) || FIPS_VERSION_GT(2,0) |
2386 | 337 | if ((ret == 1) && (wc_ecc_get_generator(r, curveIdx) != MP_OKAY)) { |
2387 | 0 | WOLFSSL_MSG("wc_ecc_get_generator error"); |
2388 | 0 | ret = 0; |
2389 | 0 | } |
2390 | | #else |
2391 | | /* wc_ecc_get_generator is not defined in the FIPS v2 module. */ |
2392 | | /* Read generator (base point) x-ordinate. */ |
2393 | | if ((ret == 1) && (mp_read_radix(r->x, ecc_sets[curveIdx].Gx, |
2394 | | MP_RADIX_HEX) != MP_OKAY)) { |
2395 | | WOLFSSL_MSG("mp_read_radix Gx error"); |
2396 | | ret = 0; |
2397 | | } |
2398 | | /* Read generator (base point) y-ordinate. */ |
2399 | | if ((ret == 1) && (mp_read_radix(r->y, ecc_sets[curveIdx].Gy, |
2400 | | MP_RADIX_HEX) != MP_OKAY)) { |
2401 | | WOLFSSL_MSG("mp_read_radix Gy error"); |
2402 | | ret = 0; |
2403 | | } |
2404 | | /* z-ordinate is one as point is affine. */ |
2405 | | if ((ret == 1) && (mp_set(r->z, 1) != MP_OKAY)) { |
2406 | | WOLFSSL_MSG("mp_set Gz error"); |
2407 | | ret = 0; |
2408 | | } |
2409 | | #endif /* NOPT_FIPS_VERSION == 2 */ |
2410 | 337 | } |
2411 | | |
2412 | 351 | if ((ret == 1) && (n != NULL) && (q != NULL) && (m != NULL)) { |
2413 | | /* r = base point * n + q * m */ |
2414 | 0 | ret = ec_mul2add(r, r, n, q, m, a, prime); |
2415 | 0 | } |
2416 | | /* Not all values present, see if we are only doing base point * n. */ |
2417 | 351 | else if ((ret == 1) && (n != NULL)) { |
2418 | | /* r = base point * n */ |
2419 | 337 | if (wc_ecc_mulmod(n, r, r, a, prime, 1) != MP_OKAY) { |
2420 | 20 | WOLFSSL_MSG("wc_ecc_mulmod gn error"); |
2421 | 20 | ret = 0; |
2422 | 20 | } |
2423 | 337 | } |
2424 | | /* Not all values present, see if we are only doing q * m. */ |
2425 | 14 | else if ((ret == 1) && (q != NULL) && (m != NULL)) { |
2426 | | /* r = q * m */ |
2427 | 14 | if (wc_ecc_mulmod(m, q, r, a, prime, 1) != MP_OKAY) { |
2428 | 4 | WOLFSSL_MSG("wc_ecc_mulmod qm error"); |
2429 | 4 | ret = 0; |
2430 | 4 | } |
2431 | 14 | } |
2432 | | /* No values to use. */ |
2433 | 0 | else if (ret == 1) { |
2434 | | /* Set result to infinity as no values passed in. */ |
2435 | 0 | mp_zero(r->x); |
2436 | 0 | mp_zero(r->y); |
2437 | 0 | mp_zero(r->z); |
2438 | 0 | } |
2439 | | |
2440 | 351 | mp_clear(a); |
2441 | 351 | mp_clear(prime); |
2442 | 351 | WC_FREE_VAR_EX(a, NULL, DYNAMIC_TYPE_BIGINT); |
2443 | 351 | WC_FREE_VAR_EX(prime, NULL, DYNAMIC_TYPE_BIGINT); |
2444 | 351 | return ret; |
2445 | 351 | } |
2446 | | |
2447 | | /* Sum the scalar multiplications of the base point and n, and q and m. |
2448 | | * |
2449 | | * r = base point * n + q * m |
2450 | | * |
2451 | | * Return code compliant with OpenSSL. |
2452 | | * |
2453 | | * @param [in] group EC group. |
2454 | | * @param [out] r EC point that is result of operation. |
2455 | | * @param [in] n Scalar to multiply by base point. May be NULL. |
2456 | | * @param [in] q EC point to be scalar multiplied. May be NULL. |
2457 | | * @param [in] m Scalar to multiply q by. May be NULL. |
2458 | | * @param [in] ctx Context to use for BN operations. Unused. |
2459 | | * @return 1 on success. |
2460 | | * @return 0 on error. |
2461 | | */ |
2462 | | int wolfSSL_EC_POINT_mul(const WOLFSSL_EC_GROUP *group, WOLFSSL_EC_POINT *r, |
2463 | | const WOLFSSL_BIGNUM *n, const WOLFSSL_EC_POINT *q, const WOLFSSL_BIGNUM *m, |
2464 | | WOLFSSL_BN_CTX *ctx) |
2465 | 351 | { |
2466 | 351 | int ret = 1; |
2467 | | |
2468 | | /* No BN operations performed. */ |
2469 | 351 | (void)ctx; |
2470 | | |
2471 | 351 | WOLFSSL_ENTER("wolfSSL_EC_POINT_mul"); |
2472 | | |
2473 | | /* Validate parameters. */ |
2474 | 351 | if ((group == NULL) || (r == NULL)) { |
2475 | 0 | WOLFSSL_MSG("wolfSSL_EC_POINT_mul NULL error"); |
2476 | 0 | ret = 0; |
2477 | 0 | } |
2478 | | |
2479 | | /* Ensure the internal representation of the EC point q is setup. */ |
2480 | 351 | if ((ret == 1) && (q != NULL) && (ec_point_setup(q) != 1)) { |
2481 | 0 | WOLFSSL_MSG("ec_point_setup error"); |
2482 | 0 | ret = 0; |
2483 | 0 | } |
2484 | | |
2485 | | #ifdef DEBUG_WOLFSSL |
2486 | | if (ret == 1) { |
2487 | | int nid = wolfSSL_EC_GROUP_get_curve_name(group); |
2488 | | const char* curve = wolfSSL_OBJ_nid2ln(nid); |
2489 | | const char* nistName = wolfSSL_EC_curve_nid2nist(nid); |
2490 | | char* num; |
2491 | | wolfSSL_EC_POINT_dump("wolfSSL_EC_POINT_mul input q", q); |
2492 | | num = wolfSSL_BN_bn2hex(n); |
2493 | | WOLFSSL_MSG_EX("\tn = %s", num); |
2494 | | XFREE(num, NULL, DYNAMIC_TYPE_OPENSSL); |
2495 | | num = wolfSSL_BN_bn2hex(m); |
2496 | | WOLFSSL_MSG_EX("\tm = %s", num); |
2497 | | XFREE(num, NULL, DYNAMIC_TYPE_OPENSSL); |
2498 | | if (curve != NULL) |
2499 | | WOLFSSL_MSG_EX("curve name: %s", curve); |
2500 | | if (nistName != NULL) |
2501 | | WOLFSSL_MSG_EX("nist curve name: %s", nistName); |
2502 | | } |
2503 | | #endif |
2504 | | |
2505 | 351 | if (ret == 1) { |
2506 | 351 | mp_int* ni = (n != NULL) ? (mp_int*)n->internal : NULL; |
2507 | 351 | ecc_point* qi = (q != NULL) ? (ecc_point*)q->internal : NULL; |
2508 | 351 | mp_int* mi = (m != NULL) ? (mp_int*)m->internal : NULL; |
2509 | | |
2510 | | /* Perform multiplication with wolfCrypt objects. */ |
2511 | 351 | ret = wolfssl_ec_point_mul(group->curve_idx, (ecc_point*)r->internal, |
2512 | 351 | ni, qi, mi); |
2513 | 351 | } |
2514 | | |
2515 | | /* Only on success is the internal point guaranteed to be set. */ |
2516 | 351 | if (r != NULL) { |
2517 | 351 | r->inSet = (ret == 1); |
2518 | 351 | } |
2519 | | /* Copy internal EC point values out to external EC point. */ |
2520 | 351 | if ((ret == 1) && (ec_point_external_set(r) != 1)) { |
2521 | 0 | WOLFSSL_MSG("ec_point_external_set error"); |
2522 | 0 | ret = 0; |
2523 | 0 | } |
2524 | | |
2525 | | #ifdef DEBUG_WOLFSSL |
2526 | | if (ret == 1) { |
2527 | | wolfSSL_EC_POINT_dump("wolfSSL_EC_POINT_mul result", r); |
2528 | | } |
2529 | | #endif |
2530 | | |
2531 | 351 | return ret; |
2532 | 351 | } |
2533 | | #endif /* !WOLFSSL_ATECC508A && !WOLFSSL_ATECC608A && !HAVE_SELFTEST && |
2534 | | * !WOLFSSL_SP_MATH */ |
2535 | | |
2536 | | /* Invert the point on the curve. |
2537 | | * (x, y) -> (x, -y) = (x, (prime - y) % prime) |
2538 | | * |
2539 | | * @param [in] curveIdx Index of curve in ecc_set. |
2540 | | * @param [in, out] point EC point to invert. |
2541 | | * @return 1 on success. |
2542 | | * @return 0 on error. |
2543 | | */ |
2544 | | static int wolfssl_ec_point_invert(int curveIdx, ecc_point* point) |
2545 | 2 | { |
2546 | 2 | int ret = 1; |
2547 | 2 | WC_DECLARE_VAR(prime, mp_int, 1, 0); |
2548 | | |
2549 | | /* Allocate memory for an MP int to hold the prime of the curve. */ |
2550 | 2 | WC_ALLOC_VAR_EX(prime, mp_int, 1, NULL, DYNAMIC_TYPE_BIGINT, ret=0); |
2551 | | |
2552 | | /* Initialize MP int. */ |
2553 | 2 | if ((ret == 1) && (mp_init(prime) != MP_OKAY)) { |
2554 | 0 | WOLFSSL_MSG("mp_init_multi error"); |
2555 | 0 | ret = 0; |
2556 | 0 | } |
2557 | | |
2558 | | /* Read the curve parameter: prime. */ |
2559 | 2 | if ((ret == 1) && (mp_read_radix(prime, ecc_sets[curveIdx].prime, |
2560 | 2 | MP_RADIX_HEX) != MP_OKAY)) { |
2561 | 0 | WOLFSSL_MSG("mp_read_radix prime error"); |
2562 | 0 | ret = 0; |
2563 | 0 | } |
2564 | | |
2565 | | /* y = (prime - y) mod prime. */ |
2566 | 2 | if ((ret == 1) && (!mp_iszero(point->y)) && (mp_sub(prime, point->y, |
2567 | 0 | point->y) != MP_OKAY)) { |
2568 | 0 | WOLFSSL_MSG("mp_sub error"); |
2569 | 0 | ret = 0; |
2570 | 0 | } |
2571 | | |
2572 | | /* Dispose of memory associated with MP. */ |
2573 | 2 | mp_free(prime); |
2574 | 2 | WC_FREE_VAR_EX(prime, NULL, DYNAMIC_TYPE_BIGINT); |
2575 | 2 | return ret; |
2576 | 2 | } |
2577 | | |
2578 | | /* Invert the point on the curve. |
2579 | | * (x, y) -> (x, -y) = (x, (prime - y) % prime) |
2580 | | * |
2581 | | * @param [in] group EC group. |
2582 | | * @param [in, out] point EC point to invert. |
2583 | | * @param [in] ctx Context to use for BN operations. Unused. |
2584 | | * @return 1 on success. |
2585 | | * @return 0 on error. |
2586 | | */ |
2587 | | int wolfSSL_EC_POINT_invert(const WOLFSSL_EC_GROUP *group, |
2588 | | WOLFSSL_EC_POINT *point, WOLFSSL_BN_CTX *ctx) |
2589 | 2 | { |
2590 | 2 | int ret = 1; |
2591 | | |
2592 | | /* No BN operations performed. */ |
2593 | 2 | (void)ctx; |
2594 | | |
2595 | 2 | WOLFSSL_ENTER("wolfSSL_EC_POINT_invert"); |
2596 | | |
2597 | | /* Validate parameters. */ |
2598 | 2 | if ((group == NULL) || (point == NULL) || (point->internal == NULL)) { |
2599 | 0 | ret = 0; |
2600 | 0 | } |
2601 | | |
2602 | | /* Ensure internal representation of point is setup. */ |
2603 | 2 | if ((ret == 1) && (ec_point_setup(point) != 1)) { |
2604 | 0 | ret = 0; |
2605 | 0 | } |
2606 | | |
2607 | | #ifdef DEBUG_WOLFSSL |
2608 | | if (ret == 1) { |
2609 | | int nid = wolfSSL_EC_GROUP_get_curve_name(group); |
2610 | | const char* curve = wolfSSL_OBJ_nid2ln(nid); |
2611 | | const char* nistName = wolfSSL_EC_curve_nid2nist(nid); |
2612 | | wolfSSL_EC_POINT_dump("wolfSSL_EC_POINT_invert input", point); |
2613 | | if (curve != NULL) |
2614 | | WOLFSSL_MSG_EX("curve name: %s", curve); |
2615 | | if (nistName != NULL) |
2616 | | WOLFSSL_MSG_EX("nist curve name: %s", nistName); |
2617 | | |
2618 | | } |
2619 | | #endif |
2620 | | |
2621 | 2 | if (ret == 1 && !wolfSSL_BN_is_one(point->Z)) { |
2622 | 0 | #if !defined(WOLFSSL_SP_MATH) && !defined(WOLF_CRYPTO_CB_ONLY_ECC) |
2623 | 0 | if (ec_point_convert_to_affine(group, point) != 0) |
2624 | 0 | ret = 0; |
2625 | | #else |
2626 | | WOLFSSL_MSG("wolfSSL_EC_POINT_invert called on non-affine point"); |
2627 | | ret = 0; |
2628 | | #endif |
2629 | 0 | } |
2630 | | |
2631 | 2 | if (ret == 1) { |
2632 | | /* Perform inversion using wolfCrypt objects. */ |
2633 | 2 | ret = wolfssl_ec_point_invert(group->curve_idx, |
2634 | 2 | (ecc_point*)point->internal); |
2635 | 2 | } |
2636 | | |
2637 | | /* Set the external EC point representation based on internal. */ |
2638 | 2 | if ((ret == 1) && (ec_point_external_set(point) != 1)) { |
2639 | 0 | WOLFSSL_MSG("ec_point_external_set error"); |
2640 | 0 | ret = 0; |
2641 | 0 | } |
2642 | | |
2643 | | #ifdef DEBUG_WOLFSSL |
2644 | | if (ret == 1) { |
2645 | | wolfSSL_EC_POINT_dump("wolfSSL_EC_POINT_invert result", point); |
2646 | | } |
2647 | | #endif |
2648 | | |
2649 | 2 | return ret; |
2650 | 2 | } |
2651 | | |
2652 | | #ifdef WOLFSSL_EC_POINT_CMP_JACOBIAN |
2653 | | /* Compare two points on a the same curve. |
2654 | | * |
2655 | | * (Ax, Ay, Az) => (Ax / (Az ^ 2), Ay / (Az ^ 3)) |
2656 | | * (Bx, By, Bz) => (Bx / (Bz ^ 2), By / (Bz ^ 3)) |
2657 | | * When equal: |
2658 | | * (Ax / (Az ^ 2), Ay / (Az ^ 3)) = (Bx / (Bz ^ 2), By / (Bz ^ 3)) |
2659 | | * => (Ax * (Bz ^ 2), Ay * (Bz ^ 3)) = (Bx * (Az ^ 2), By * (Az ^ 3)) |
2660 | | * |
2661 | | * @param [in] group EC group. |
2662 | | * @param [in] a EC point to compare. |
2663 | | * @param [in] b EC point to compare. |
2664 | | * @return 0 when equal. |
2665 | | * @return 1 when different. |
2666 | | * @return -1 on error. |
2667 | | */ |
2668 | | static int ec_point_cmp_jacobian(const WOLFSSL_EC_GROUP* group, |
2669 | | const WOLFSSL_EC_POINT *a, const WOLFSSL_EC_POINT *b, WOLFSSL_BN_CTX *ctx) |
2670 | | { |
2671 | | int ret = 0; |
2672 | | BIGNUM* at = BN_new(); |
2673 | | BIGNUM* bt = BN_new(); |
2674 | | BIGNUM* az = BN_new(); |
2675 | | BIGNUM* bz = BN_new(); |
2676 | | BIGNUM* mod = BN_new(); |
2677 | | |
2678 | | /* Check that the big numbers were allocated. */ |
2679 | | if ((at == NULL) || (bt == NULL) || (az == NULL) || (bz == NULL) || |
2680 | | (mod == NULL)) { |
2681 | | ret = WOLFSSL_FATAL_ERROR; |
2682 | | } |
2683 | | /* Get the modulus for the curve. */ |
2684 | | if ((ret == 0) && |
2685 | | (BN_hex2bn(&mod, ecc_sets[group->curve_idx].prime) != 1)) { |
2686 | | ret = WOLFSSL_FATAL_ERROR; |
2687 | | } |
2688 | | if (ret == 0) { |
2689 | | /* bt = Bx * (Az ^ 2). When Az is one then just copy. */ |
2690 | | if (BN_is_one(a->Z)) { |
2691 | | if (BN_copy(bt, b->X) == NULL) { |
2692 | | ret = WOLFSSL_FATAL_ERROR; |
2693 | | } |
2694 | | } |
2695 | | /* az = Az ^ 2 */ |
2696 | | else if ((BN_mod_mul(az, a->Z, a->Z, mod, ctx) != 1)) { |
2697 | | ret = WOLFSSL_FATAL_ERROR; |
2698 | | } |
2699 | | /* bt = Bx * az = Bx * (Az ^ 2) */ |
2700 | | else if (BN_mod_mul(bt, b->X, az, mod, ctx) != 1) { |
2701 | | ret = WOLFSSL_FATAL_ERROR; |
2702 | | } |
2703 | | } |
2704 | | if (ret == 0) { |
2705 | | /* at = Ax * (Bz ^ 2). When Bz is one then just copy. */ |
2706 | | if (BN_is_one(b->Z)) { |
2707 | | if (BN_copy(at, a->X) == NULL) { |
2708 | | ret = WOLFSSL_FATAL_ERROR; |
2709 | | } |
2710 | | } |
2711 | | /* bz = Bz ^ 2 */ |
2712 | | else if (BN_mod_mul(bz, b->Z, b->Z, mod, ctx) != 1) { |
2713 | | ret = WOLFSSL_FATAL_ERROR; |
2714 | | } |
2715 | | /* at = Ax * bz = Ax * (Bz ^ 2) */ |
2716 | | else if (BN_mod_mul(at, a->X, bz, mod, ctx) != 1) { |
2717 | | ret = WOLFSSL_FATAL_ERROR; |
2718 | | } |
2719 | | } |
2720 | | /* Compare x-ordinates. */ |
2721 | | if ((ret == 0) && (BN_cmp(at, bt) != 0)) { |
2722 | | ret = 1; |
2723 | | } |
2724 | | if (ret == 0) { |
2725 | | /* bt = By * (Az ^ 3). When Az is one then just copy. */ |
2726 | | if (BN_is_one(a->Z)) { |
2727 | | if (BN_copy(bt, b->Y) == NULL) { |
2728 | | ret = WOLFSSL_FATAL_ERROR; |
2729 | | } |
2730 | | } |
2731 | | /* az = az * Az = Az ^ 3 */ |
2732 | | else if ((BN_mod_mul(az, az, a->Z, mod, ctx) != 1)) { |
2733 | | ret = WOLFSSL_FATAL_ERROR; |
2734 | | } |
2735 | | /* bt = By * az = By * (Az ^ 3) */ |
2736 | | else if (BN_mod_mul(bt, b->Y, az, mod, ctx) != 1) { |
2737 | | ret = WOLFSSL_FATAL_ERROR; |
2738 | | } |
2739 | | } |
2740 | | if (ret == 0) { |
2741 | | /* at = Ay * (Bz ^ 3). When Bz is one then just copy. */ |
2742 | | if (BN_is_one(b->Z)) { |
2743 | | if (BN_copy(at, a->Y) == NULL) { |
2744 | | ret = WOLFSSL_FATAL_ERROR; |
2745 | | } |
2746 | | } |
2747 | | /* bz = bz * Bz = Bz ^ 3 */ |
2748 | | else if (BN_mod_mul(bz, bz, b->Z, mod, ctx) != 1) { |
2749 | | ret = WOLFSSL_FATAL_ERROR; |
2750 | | } |
2751 | | /* at = Ay * bz = Ay * (Bz ^ 3) */ |
2752 | | else if (BN_mod_mul(at, a->Y, bz, mod, ctx) != 1) { |
2753 | | ret = WOLFSSL_FATAL_ERROR; |
2754 | | } |
2755 | | } |
2756 | | /* Compare y-ordinates. */ |
2757 | | if ((ret == 0) && (BN_cmp(at, bt) != 0)) { |
2758 | | ret = 1; |
2759 | | } |
2760 | | |
2761 | | BN_free(mod); |
2762 | | BN_free(bz); |
2763 | | BN_free(az); |
2764 | | BN_free(bt); |
2765 | | BN_free(at); |
2766 | | return ret; |
2767 | | } |
2768 | | #endif |
2769 | | |
2770 | | /* Compare two points on a the same curve. |
2771 | | * |
2772 | | * Return code compliant with OpenSSL. |
2773 | | * |
2774 | | * @param [in] group EC group. |
2775 | | * @param [in] a EC point to compare. |
2776 | | * @param [in] b EC point to compare. |
2777 | | * @param [in] ctx Context to use for BN operations. Unused. |
2778 | | * @return 0 when equal. |
2779 | | * @return 1 when different. |
2780 | | * @return -1 on error. |
2781 | | */ |
2782 | | int wolfSSL_EC_POINT_cmp(const WOLFSSL_EC_GROUP *group, |
2783 | | const WOLFSSL_EC_POINT *a, const WOLFSSL_EC_POINT *b, WOLFSSL_BN_CTX *ctx) |
2784 | 7 | { |
2785 | 7 | int ret = 0; |
2786 | | |
2787 | 7 | WOLFSSL_ENTER("wolfSSL_EC_POINT_cmp"); |
2788 | | |
2789 | | /* Validate parameters. */ |
2790 | 7 | if ((group == NULL) || (a == NULL) || (a->internal == NULL) || |
2791 | 7 | (b == NULL) || (b->internal == NULL)) { |
2792 | 0 | WOLFSSL_MSG("wolfSSL_EC_POINT_cmp Bad arguments"); |
2793 | 0 | ret = WOLFSSL_FATAL_ERROR; |
2794 | 0 | } |
2795 | 7 | if (ret != -1) { |
2796 | | #ifdef WOLFSSL_EC_POINT_CMP_JACOBIAN |
2797 | | /* If same Z ordinate then no need to convert to affine. */ |
2798 | | if (BN_cmp(a->Z, b->Z) == 0) { |
2799 | | /* Compare */ |
2800 | | ret = ((BN_cmp(a->X, b->X) != 0) || (BN_cmp(a->Y, b->Y) != 0)); |
2801 | | } |
2802 | | else { |
2803 | | ret = ec_point_cmp_jacobian(group, a, b, ctx); |
2804 | | } |
2805 | | #else |
2806 | | /* No BN operations performed. */ |
2807 | 7 | (void)ctx; |
2808 | | |
2809 | 7 | ret = (wc_ecc_cmp_point((ecc_point*)a->internal, |
2810 | 7 | (ecc_point*)b->internal) != MP_EQ); |
2811 | 7 | #endif |
2812 | 7 | } |
2813 | | |
2814 | 7 | return ret; |
2815 | 7 | } |
2816 | | |
2817 | | /* Copy EC point. |
2818 | | * |
2819 | | * @param [out] dest EC point to copy into. |
2820 | | * @param [in] src EC point to copy. |
2821 | | * @return 1 on success. |
2822 | | * @return 0 on error. |
2823 | | */ |
2824 | | int wolfSSL_EC_POINT_copy(WOLFSSL_EC_POINT *dest, const WOLFSSL_EC_POINT *src) |
2825 | 1.26k | { |
2826 | 1.26k | int ret = 1; |
2827 | | |
2828 | 1.26k | WOLFSSL_ENTER("wolfSSL_EC_POINT_copy"); |
2829 | | |
2830 | | /* Validate parameters. */ |
2831 | 1.26k | if ((dest == NULL) || (src == NULL)) { |
2832 | 0 | ret = 0; |
2833 | 0 | } |
2834 | | |
2835 | | /* Ensure internal EC point of src is setup. */ |
2836 | 1.26k | if ((ret == 1) && (ec_point_setup(src) != 1)) { |
2837 | 0 | ret = 0; |
2838 | 0 | } |
2839 | | |
2840 | | /* Copy internal EC points. */ |
2841 | 1.26k | if ((ret == 1) && (wc_ecc_copy_point((ecc_point*)src->internal, |
2842 | 1.26k | (ecc_point*)dest->internal) != MP_OKAY)) { |
2843 | 0 | ret = 0; |
2844 | 0 | } |
2845 | | |
2846 | 1.26k | if (ret == 1) { |
2847 | | /* Destinatation internal point is set. */ |
2848 | 1.26k | dest->inSet = 1; |
2849 | | |
2850 | | /* Set the external EC point of dest based on internal. */ |
2851 | 1.26k | if (ec_point_external_set(dest) != 1) { |
2852 | 0 | ret = 0; |
2853 | 0 | } |
2854 | 1.26k | } |
2855 | | |
2856 | 1.26k | return ret; |
2857 | 1.26k | } |
2858 | | |
2859 | | /* Duplicates an EC point. |
2860 | | * |
2861 | | * @param [in] src EC point to duplicate. |
2862 | | * @param [in] group EC group for the new point. |
2863 | | * @return New EC point on success. |
2864 | | * @return NULL on failure. |
2865 | | */ |
2866 | | WOLFSSL_EC_POINT *wolfSSL_EC_POINT_dup(const WOLFSSL_EC_POINT *src, |
2867 | | const WOLFSSL_EC_GROUP *group) |
2868 | 0 | { |
2869 | 0 | WOLFSSL_EC_POINT *dest; |
2870 | |
|
2871 | 0 | WOLFSSL_ENTER("wolfSSL_EC_POINT_dup"); |
2872 | |
|
2873 | 0 | if ((src == NULL) || (group == NULL)) { |
2874 | 0 | return NULL; |
2875 | 0 | } |
2876 | | |
2877 | 0 | dest = wolfSSL_EC_POINT_new(group); |
2878 | 0 | if (dest == NULL) { |
2879 | 0 | return NULL; |
2880 | 0 | } |
2881 | | |
2882 | 0 | if (wolfSSL_EC_POINT_copy(dest, src) != 1) { |
2883 | 0 | wolfSSL_EC_POINT_free(dest); |
2884 | 0 | return NULL; |
2885 | 0 | } |
2886 | | |
2887 | 0 | return dest; |
2888 | 0 | } |
2889 | | |
2890 | | /* Checks whether point is at infinity. |
2891 | | * |
2892 | | * Return code compliant with OpenSSL. |
2893 | | * |
2894 | | * @param [in] group EC group. |
2895 | | * @param [in] point EC point to check. |
2896 | | * @return 1 when at infinity. |
2897 | | * @return 0 when not at infinity. |
2898 | | */ |
2899 | | int wolfSSL_EC_POINT_is_at_infinity(const WOLFSSL_EC_GROUP *group, |
2900 | | const WOLFSSL_EC_POINT *point) |
2901 | 358 | { |
2902 | 358 | int ret = 1; |
2903 | | |
2904 | 358 | WOLFSSL_ENTER("wolfSSL_EC_POINT_is_at_infinity"); |
2905 | | |
2906 | | /* Validate parameters. */ |
2907 | 358 | if ((group == NULL) || (point == NULL) || (point->internal == NULL)) { |
2908 | 0 | WOLFSSL_MSG("wolfSSL_EC_POINT_is_at_infinity NULL error"); |
2909 | 0 | ret = 0; |
2910 | 0 | } |
2911 | | |
2912 | | /* Ensure internal EC point is setup. */ |
2913 | 358 | if ((ret == 1) && (ec_point_setup(point) != 1)) { |
2914 | 0 | ret = 0; |
2915 | 0 | } |
2916 | 358 | if (ret == 1) { |
2917 | 358 | #ifndef WOLF_CRYPTO_CB_ONLY_ECC |
2918 | | /* Check for infinity. */ |
2919 | 358 | ret = wc_ecc_point_is_at_infinity((ecc_point*)point->internal); |
2920 | 358 | if (ret < 0) { |
2921 | 0 | WOLFSSL_MSG("ecc_point_is_at_infinity failure"); |
2922 | | /* Error return is 0 by OpenSSL. */ |
2923 | 0 | ret = 0; |
2924 | 0 | } |
2925 | | #else |
2926 | | WOLFSSL_MSG("ecc_point_is_at_infinitiy compiled out"); |
2927 | | ret = 0; |
2928 | | #endif |
2929 | 358 | } |
2930 | | |
2931 | 358 | return ret; |
2932 | 358 | } |
2933 | | |
2934 | | #endif /* OPENSSL_EXTRA */ |
2935 | | |
2936 | | /* End EC_POINT */ |
2937 | | |
2938 | | /* Start EC_KEY */ |
2939 | | |
2940 | | #ifdef OPENSSL_EXTRA |
2941 | | |
2942 | | /* |
2943 | | * EC key constructor/deconstructor APIs |
2944 | | */ |
2945 | | |
2946 | | /* Allocate a new EC key. |
2947 | | * |
2948 | | * Not OpenSSL API. |
2949 | | * |
2950 | | * @param [in] heap Heap hint for dynamic memory allocation. |
2951 | | * @param [in] devId Device identifier value. |
2952 | | * @return New, allocated EC key on success. |
2953 | | * @return NULL on error. |
2954 | | */ |
2955 | | WOLFSSL_EC_KEY *wolfSSL_EC_KEY_new_ex(void* heap, int devId) |
2956 | 1.04k | { |
2957 | 1.04k | WOLFSSL_EC_KEY *key = NULL; |
2958 | 1.04k | int err = 0; |
2959 | | |
2960 | 1.04k | WOLFSSL_ENTER("wolfSSL_EC_KEY_new"); |
2961 | | |
2962 | | /* Allocate memory for EC key. */ |
2963 | 1.04k | key = (WOLFSSL_EC_KEY*)XMALLOC(sizeof(WOLFSSL_EC_KEY), heap, |
2964 | 1.04k | DYNAMIC_TYPE_ECC); |
2965 | 1.04k | if (key == NULL) { |
2966 | 0 | WOLFSSL_MSG("wolfSSL_EC_KEY_new malloc WOLFSSL_EC_KEY failure"); |
2967 | 0 | err = 1; |
2968 | 0 | } |
2969 | 1.04k | if (!err) { |
2970 | | /* Reset all fields to 0. */ |
2971 | 1.04k | XMEMSET(key, 0, sizeof(WOLFSSL_EC_KEY)); |
2972 | | /* Cache heap hint. */ |
2973 | 1.04k | key->heap = heap; |
2974 | | /* Initialize fields to defaults. */ |
2975 | 1.04k | key->form = WC_POINT_CONVERSION_UNCOMPRESSED; |
2976 | | |
2977 | | /* Initialize reference count. */ |
2978 | 1.04k | wolfSSL_RefInit(&key->ref, &err); |
2979 | | #ifdef WOLFSSL_REFCNT_ERROR_RETURN |
2980 | | } |
2981 | | if (!err) { |
2982 | | #endif |
2983 | | /* Allocate memory for internal EC key representation. */ |
2984 | 1.04k | key->internal = (ecc_key*)XMALLOC(sizeof(ecc_key), heap, |
2985 | 1.04k | DYNAMIC_TYPE_ECC); |
2986 | 1.04k | if (key->internal == NULL) { |
2987 | 0 | WOLFSSL_MSG("wolfSSL_EC_KEY_new malloc ecc key failure"); |
2988 | 0 | err = 1; |
2989 | 0 | } |
2990 | 1.04k | } |
2991 | 1.04k | if (!err) { |
2992 | | /* Initialize wolfCrypt EC key. */ |
2993 | 1.04k | if (wc_ecc_init_ex((ecc_key*)key->internal, heap, devId) != 0) { |
2994 | 0 | WOLFSSL_MSG("wolfSSL_EC_KEY_new init ecc key failure"); |
2995 | 0 | err = 1; |
2996 | 0 | } |
2997 | 1.04k | } |
2998 | | |
2999 | 1.04k | if (!err) { |
3000 | | /* Group unknown at creation */ |
3001 | 1.04k | key->group = wolfSSL_EC_GROUP_new_by_curve_name(WC_NID_undef); |
3002 | 1.04k | if (key->group == NULL) { |
3003 | 0 | WOLFSSL_MSG("wolfSSL_EC_KEY_new malloc WOLFSSL_EC_GROUP failure"); |
3004 | 0 | err = 1; |
3005 | 0 | } |
3006 | 1.04k | } |
3007 | | |
3008 | 1.04k | if (!err) { |
3009 | | /* Allocate a point as public key. */ |
3010 | 1.04k | key->pub_key = wolfSSL_EC_POINT_new(key->group); |
3011 | 1.04k | if (key->pub_key == NULL) { |
3012 | 0 | WOLFSSL_MSG("wolfSSL_EC_POINT_new failure"); |
3013 | 0 | err = 1; |
3014 | 0 | } |
3015 | 1.04k | } |
3016 | | |
3017 | 1.04k | if (!err) { |
3018 | | /* Allocate a BN as private key. */ |
3019 | 1.04k | key->priv_key = wolfSSL_BN_new(); |
3020 | 1.04k | if (key->priv_key == NULL) { |
3021 | 0 | WOLFSSL_MSG("wolfSSL_BN_new failure"); |
3022 | 0 | err = 1; |
3023 | 0 | } |
3024 | 1.04k | } |
3025 | | |
3026 | 1.04k | if (err) { |
3027 | | /* Dispose of EC key on error. */ |
3028 | 0 | wolfSSL_EC_KEY_free(key); |
3029 | 0 | key = NULL; |
3030 | 0 | } |
3031 | | /* Return new EC key object. */ |
3032 | 1.04k | return key; |
3033 | 1.04k | } |
3034 | | |
3035 | | /* Allocate a new EC key. |
3036 | | * |
3037 | | * @return New, allocated EC key on success. |
3038 | | * @return NULL on error. |
3039 | | */ |
3040 | | WOLFSSL_EC_KEY *wolfSSL_EC_KEY_new(void) |
3041 | 1.04k | { |
3042 | 1.04k | return wolfSSL_EC_KEY_new_ex(NULL, INVALID_DEVID); |
3043 | 1.04k | } |
3044 | | |
3045 | | /* Create new EC key with the group having the specified numeric ID. |
3046 | | * |
3047 | | * @param [in] nid Numeric ID. |
3048 | | * @return New, allocated EC key on success. |
3049 | | * @return NULL on error. |
3050 | | */ |
3051 | | WOLFSSL_EC_KEY *wolfSSL_EC_KEY_new_by_curve_name(int nid) |
3052 | 0 | { |
3053 | 0 | WOLFSSL_EC_KEY *key; |
3054 | 0 | int err = 0; |
3055 | |
|
3056 | 0 | WOLFSSL_ENTER("wolfSSL_EC_KEY_new_by_curve_name"); |
3057 | | |
3058 | | /* Allocate empty, EC key. */ |
3059 | 0 | key = wolfSSL_EC_KEY_new(); |
3060 | 0 | if (key == NULL) { |
3061 | 0 | WOLFSSL_MSG("wolfSSL_EC_KEY_new failure"); |
3062 | 0 | err = 1; |
3063 | 0 | } |
3064 | |
|
3065 | 0 | if (!err) { |
3066 | | /* Set group to be nid. */ |
3067 | 0 | ec_group_set_nid(key->group, nid); |
3068 | 0 | if (key->group->curve_idx == -1) { |
3069 | 0 | wolfSSL_EC_KEY_free(key); |
3070 | 0 | key = NULL; |
3071 | 0 | } |
3072 | 0 | } |
3073 | | |
3074 | | /* Return the new EC key object. */ |
3075 | 0 | return key; |
3076 | 0 | } |
3077 | | |
3078 | | /* Dispose of the EC key and allocated data. |
3079 | | * |
3080 | | * Cannot use key after this call. |
3081 | | * |
3082 | | * @param [in] key EC key to free. |
3083 | | */ |
3084 | | void wolfSSL_EC_KEY_free(WOLFSSL_EC_KEY *key) |
3085 | 1.04k | { |
3086 | 1.04k | int doFree = 0; |
3087 | 1.04k | int err; |
3088 | | |
3089 | 1.04k | (void)err; |
3090 | | |
3091 | 1.04k | WOLFSSL_ENTER("wolfSSL_EC_KEY_free"); |
3092 | | |
3093 | 1.04k | if (key != NULL) { |
3094 | 1.04k | void* heap = key->heap; |
3095 | | |
3096 | | /* Decrement reference count. */ |
3097 | 1.04k | wolfSSL_RefDec(&key->ref, &doFree, &err); |
3098 | 1.04k | if (doFree) { |
3099 | | /* Dispose of allocated reference counting data. */ |
3100 | 1.04k | wolfSSL_RefFree(&key->ref); |
3101 | | |
3102 | | /* Dispose of private key. */ |
3103 | 1.04k | wolfSSL_BN_free(key->priv_key); |
3104 | 1.04k | wolfSSL_EC_POINT_free(key->pub_key); |
3105 | 1.04k | wolfSSL_EC_GROUP_free(key->group); |
3106 | 1.04k | if (key->internal != NULL) { |
3107 | | /* Dispose of wolfCrypt representation of EC key. */ |
3108 | 1.04k | wc_ecc_free((ecc_key*)key->internal); |
3109 | 1.04k | XFREE(key->internal, heap, DYNAMIC_TYPE_ECC); |
3110 | 1.04k | } |
3111 | | |
3112 | | /* Set back to NULLs for safety. */ |
3113 | 1.04k | ForceZero(key, sizeof(*key)); |
3114 | | |
3115 | | /* Dispose of the memory associated with the EC key. */ |
3116 | 1.04k | XFREE(key, heap, DYNAMIC_TYPE_ECC); |
3117 | 1.04k | (void)heap; |
3118 | 1.04k | } |
3119 | 1.04k | } |
3120 | 1.04k | } |
3121 | | |
3122 | | /* Increments ref count of EC key. |
3123 | | * |
3124 | | * @param [in, out] key EC key. |
3125 | | * @return 1 on success |
3126 | | * @return 0 on error |
3127 | | */ |
3128 | | int wolfSSL_EC_KEY_up_ref(WOLFSSL_EC_KEY* key) |
3129 | 0 | { |
3130 | 0 | int err = 1; |
3131 | |
|
3132 | 0 | if (key != NULL) { |
3133 | 0 | wolfSSL_RefInc(&key->ref, &err); |
3134 | 0 | } |
3135 | |
|
3136 | 0 | return !err; |
3137 | 0 | } |
3138 | | |
3139 | | #ifndef NO_CERTS |
3140 | | |
3141 | | #if defined(OPENSSL_ALL) |
3142 | | /* Copy the internal, wolfCrypt EC key. |
3143 | | * |
3144 | | * @param [in, out] dst Destination wolfCrypt EC key. |
3145 | | * @param [in] src Source wolfCrypt EC key. |
3146 | | * @return 0 on success. |
3147 | | * @return Negative on error. |
3148 | | */ |
3149 | | static int wolfssl_ec_key_int_copy(ecc_key* dst, const ecc_key* src) |
3150 | 0 | { |
3151 | 0 | int ret; |
3152 | | |
3153 | | /* Copy public key. */ |
3154 | 0 | #if !defined(HAVE_FIPS) || FIPS_VERSION_GT(2,0) |
3155 | 0 | ret = wc_ecc_copy_point(&src->pubkey, &dst->pubkey); |
3156 | | #else |
3157 | | ret = wc_ecc_copy_point((ecc_point*)&src->pubkey, &dst->pubkey); |
3158 | | #endif |
3159 | 0 | if (ret != MP_OKAY) { |
3160 | 0 | WOLFSSL_MSG("wc_ecc_copy_point error"); |
3161 | 0 | } |
3162 | |
|
3163 | 0 | if (ret == 0) { |
3164 | | /* Copy private key. */ |
3165 | 0 | ret = mp_copy(wc_ecc_key_get_priv((ecc_key*)src), |
3166 | 0 | wc_ecc_key_get_priv(dst)); |
3167 | 0 | if (ret != MP_OKAY) { |
3168 | 0 | WOLFSSL_MSG("mp_copy error"); |
3169 | 0 | } |
3170 | 0 | } |
3171 | |
|
3172 | 0 | if (ret == 0) { |
3173 | | /* Copy domain parameters. */ |
3174 | 0 | if (src->dp) { |
3175 | 0 | ret = wc_ecc_set_curve(dst, 0, src->dp->id); |
3176 | 0 | if (ret != 0) { |
3177 | 0 | WOLFSSL_MSG("wc_ecc_set_curve error"); |
3178 | 0 | } |
3179 | 0 | } |
3180 | 0 | } |
3181 | |
|
3182 | 0 | if (ret == 0) { |
3183 | | /* Copy the other components. */ |
3184 | 0 | dst->type = src->type; |
3185 | 0 | dst->idx = src->idx; |
3186 | 0 | dst->state = src->state; |
3187 | 0 | dst->flags = src->flags; |
3188 | 0 | } |
3189 | |
|
3190 | 0 | return ret; |
3191 | 0 | } |
3192 | | |
3193 | | /* Copies ecc_key into new WOLFSSL_EC_KEY object |
3194 | | * |
3195 | | * Copies the internal representation as well. |
3196 | | * |
3197 | | * @param [in] src EC key to duplicate. |
3198 | | * |
3199 | | * @return EC key on success. |
3200 | | * @return NULL on error. |
3201 | | */ |
3202 | | WOLFSSL_EC_KEY *wolfSSL_EC_KEY_dup(const WOLFSSL_EC_KEY *src) |
3203 | 0 | { |
3204 | 0 | int err = 0; |
3205 | 0 | WOLFSSL_EC_KEY* newKey = NULL; |
3206 | |
|
3207 | 0 | WOLFSSL_ENTER("wolfSSL_EC_KEY_dup"); |
3208 | | |
3209 | | /* Validate EC key. */ |
3210 | 0 | if ((src == NULL) || (src->internal == NULL) || (src->group == NULL) || |
3211 | 0 | (src->pub_key == NULL) || (src->priv_key == NULL)) { |
3212 | 0 | WOLFSSL_MSG("src NULL error"); |
3213 | 0 | err = 1; |
3214 | 0 | } |
3215 | |
|
3216 | 0 | if (!err) { |
3217 | | /* Create a new, empty key. */ |
3218 | 0 | newKey = wolfSSL_EC_KEY_new(); |
3219 | 0 | if (newKey == NULL) { |
3220 | 0 | WOLFSSL_MSG("wolfSSL_EC_KEY_new error"); |
3221 | 0 | err = 1; |
3222 | 0 | } |
3223 | 0 | } |
3224 | |
|
3225 | 0 | if (!err) { |
3226 | | /* Copy internal EC key. */ |
3227 | 0 | if (wolfssl_ec_key_int_copy((ecc_key*)newKey->internal, |
3228 | 0 | (ecc_key*)src->internal) != 0) { |
3229 | 0 | WOLFSSL_MSG("Copying internal EC key error"); |
3230 | 0 | err = 1; |
3231 | 0 | } |
3232 | 0 | } |
3233 | 0 | if (!err) { |
3234 | | /* Internal key set. */ |
3235 | 0 | newKey->inSet = 1; |
3236 | | |
3237 | | /* Copy group */ |
3238 | 0 | err = wolfssl_ec_group_copy(newKey->group, src->group); |
3239 | 0 | } |
3240 | | /* Copy public key. */ |
3241 | 0 | if ((!err) && (wolfSSL_EC_POINT_copy(newKey->pub_key, src->pub_key) != 1)) { |
3242 | 0 | WOLFSSL_MSG("Copying EC public key error"); |
3243 | 0 | err = 1; |
3244 | 0 | } |
3245 | |
|
3246 | 0 | if (!err) { |
3247 | | /* Set header size of private key in PKCS#8 format.*/ |
3248 | 0 | newKey->pkcs8HeaderSz = src->pkcs8HeaderSz; |
3249 | | |
3250 | | /* Copy private key. */ |
3251 | 0 | if (wolfSSL_BN_copy(newKey->priv_key, src->priv_key) == NULL) { |
3252 | 0 | WOLFSSL_MSG("Copying EC private key error"); |
3253 | 0 | err = 1; |
3254 | 0 | } |
3255 | 0 | } |
3256 | |
|
3257 | 0 | if (err) { |
3258 | | /* Dispose of EC key on error. */ |
3259 | 0 | wolfSSL_EC_KEY_free(newKey); |
3260 | 0 | newKey = NULL; |
3261 | 0 | } |
3262 | | /* Return the new EC key. */ |
3263 | 0 | return newKey; |
3264 | 0 | } |
3265 | | |
3266 | | #endif /* OPENSSL_ALL */ |
3267 | | |
3268 | | #endif /* !NO_CERTS */ |
3269 | | |
3270 | | /* |
3271 | | * EC key to/from bin/octet APIs |
3272 | | */ |
3273 | | |
3274 | | /* Create an EC key from the octet encoded public key. |
3275 | | * |
3276 | | * Behaviour checked against OpenSSL. |
3277 | | * |
3278 | | * @param [out] key Reference to EC key. Must pass in a valid object with |
3279 | | * group set. |
3280 | | * @param [in, out] in On in, reference to buffer that contains data. |
3281 | | * On out, reference to buffer after public key data. |
3282 | | * @param [in] len Length of data in the buffer. Must be length of the |
3283 | | * encoded public key. |
3284 | | * @return Allocated EC key on success. |
3285 | | * @return NULL on error. |
3286 | | */ |
3287 | | WOLFSSL_EC_KEY *wolfSSL_o2i_ECPublicKey(WOLFSSL_EC_KEY **key, |
3288 | | const unsigned char **in, long len) |
3289 | 0 | { |
3290 | 0 | int err = 0; |
3291 | 0 | WOLFSSL_EC_KEY* ret = NULL; |
3292 | |
|
3293 | 0 | WOLFSSL_ENTER("wolfSSL_o2i_ECPublicKey"); |
3294 | | |
3295 | | /* Validate parameters: EC group needed to perform import. */ |
3296 | 0 | if ((key == NULL) || (*key == NULL) || ((*key)->group == NULL) || |
3297 | 0 | (in == NULL) || (*in == NULL) || (len <= 0)) { |
3298 | 0 | WOLFSSL_MSG("wolfSSL_o2i_ECPublicKey Bad arguments"); |
3299 | 0 | err = 1; |
3300 | 0 | } |
3301 | |
|
3302 | 0 | if (!err) { |
3303 | | /* Return the EC key object passed in. */ |
3304 | 0 | ret = *key; |
3305 | | |
3306 | | /* Import point into public key field. */ |
3307 | 0 | if (wolfSSL_EC_POINT_oct2point(ret->group, ret->pub_key, *in, |
3308 | 0 | (size_t)len, NULL) != 1) { |
3309 | 0 | WOLFSSL_MSG("wolfSSL_EC_POINT_oct2point error"); |
3310 | 0 | ret = NULL; |
3311 | 0 | err = 1; |
3312 | 0 | } |
3313 | 0 | } |
3314 | 0 | if (!err) { |
3315 | | /* Assumed length passed in is all the data. */ |
3316 | 0 | *in += len; |
3317 | 0 | } |
3318 | |
|
3319 | 0 | return ret; |
3320 | 0 | } |
3321 | | |
3322 | | /* Puts the encoded public key into out. |
3323 | | * |
3324 | | * Passing in NULL for out returns length only. |
3325 | | * Passing in NULL for *out has buffer allocated, encoded into and passed back. |
3326 | | * Passing non-NULL for *out has it encoded into and pointer moved past. |
3327 | | * |
3328 | | * @param [in] key EC key to encode. |
3329 | | * @param [in, out] out Reference to buffer to encode into. May be NULL or |
3330 | | * point to NULL. |
3331 | | * @return Length of encoding in bytes on success. |
3332 | | * @return 0 on error. |
3333 | | */ |
3334 | | int wolfSSL_i2o_ECPublicKey(const WOLFSSL_EC_KEY *key, unsigned char **out) |
3335 | 0 | { |
3336 | 0 | int ret = 1; |
3337 | 0 | size_t len = 0; |
3338 | 0 | int form = WC_POINT_CONVERSION_UNCOMPRESSED; |
3339 | |
|
3340 | 0 | WOLFSSL_ENTER("wolfSSL_i2o_ECPublicKey"); |
3341 | | |
3342 | | /* Validate parameters. */ |
3343 | 0 | if (key == NULL) { |
3344 | 0 | WOLFSSL_MSG("wolfSSL_i2o_ECPublicKey Bad arguments"); |
3345 | 0 | ret = 0; |
3346 | 0 | } |
3347 | | |
3348 | | /* Ensure the external key data is set from the internal EC key. */ |
3349 | 0 | if ((ret == 1) && (!key->exSet) && (SetECKeyExternal((WOLFSSL_EC_KEY*) |
3350 | 0 | key) != 1)) { |
3351 | 0 | WOLFSSL_MSG("SetECKeyExternal failure"); |
3352 | 0 | ret = 0; |
3353 | 0 | } |
3354 | |
|
3355 | 0 | if (ret == 1) { |
3356 | 0 | #ifdef HAVE_COMP_KEY |
3357 | | /* Default to compressed form if not set */ |
3358 | 0 | form = (key->form == WC_POINT_CONVERSION_UNCOMPRESSED) ? |
3359 | 0 | WC_POINT_CONVERSION_UNCOMPRESSED : |
3360 | 0 | WC_POINT_CONVERSION_COMPRESSED; |
3361 | 0 | #endif |
3362 | | |
3363 | | /* Calculate length of point encoding. */ |
3364 | 0 | len = wolfSSL_EC_POINT_point2oct(key->group, key->pub_key, form, NULL, |
3365 | 0 | 0, NULL); |
3366 | 0 | } |
3367 | | /* Encode if length calculated and pointer supplied to update. */ |
3368 | 0 | if ((ret == 1) && (len != 0) && (out != NULL)) { |
3369 | 0 | unsigned char *tmp = NULL; |
3370 | | |
3371 | | /* Allocate buffer for encoding if no buffer supplied. */ |
3372 | 0 | if (*out == NULL) { |
3373 | 0 | tmp = (unsigned char*)XMALLOC(len, NULL, DYNAMIC_TYPE_OPENSSL); |
3374 | 0 | if (tmp == NULL) { |
3375 | 0 | WOLFSSL_MSG("malloc failed"); |
3376 | 0 | ret = 0; |
3377 | 0 | } |
3378 | 0 | } |
3379 | 0 | else { |
3380 | | /* Get buffer to encode into. */ |
3381 | 0 | tmp = *out; |
3382 | 0 | } |
3383 | | |
3384 | | /* Encode public key into buffer. */ |
3385 | 0 | if ((ret == 1) && (wolfSSL_EC_POINT_point2oct(key->group, key->pub_key, |
3386 | 0 | form, tmp, len, NULL) == 0)) { |
3387 | 0 | ret = 0; |
3388 | 0 | } |
3389 | |
|
3390 | 0 | if (ret == 1) { |
3391 | | /* Return buffer if allocated. */ |
3392 | 0 | if (*out == NULL) { |
3393 | 0 | *out = tmp; |
3394 | 0 | } |
3395 | 0 | else { |
3396 | | /* Step over encoded data if not allocated. */ |
3397 | 0 | *out += len; |
3398 | 0 | } |
3399 | 0 | } |
3400 | 0 | else if (*out == NULL) { |
3401 | | /* Dispose of allocated buffer. */ |
3402 | 0 | XFREE(tmp, NULL, DYNAMIC_TYPE_OPENSSL); |
3403 | 0 | } |
3404 | 0 | } |
3405 | |
|
3406 | 0 | if (ret == 1) { |
3407 | | /* Return length on success. */ |
3408 | 0 | ret = (int)len; |
3409 | 0 | } |
3410 | 0 | return ret; |
3411 | 0 | } |
3412 | | |
3413 | | #ifdef HAVE_ECC_KEY_IMPORT |
3414 | | /* Create a EC key from the DER encoded private key. |
3415 | | * |
3416 | | * @param [out] key Reference to EC key. |
3417 | | * @param [in, out] in On in, reference to buffer that contains DER data. |
3418 | | * On out, reference to buffer after private key data. |
3419 | | * @param [in] long Length of data in the buffer. May be larger than the |
3420 | | * length of the encoded private key. |
3421 | | * @return Allocated EC key on success. |
3422 | | * @return NULL on error. |
3423 | | */ |
3424 | | WOLFSSL_EC_KEY* wolfSSL_d2i_ECPrivateKey(WOLFSSL_EC_KEY** key, |
3425 | | const unsigned char** in, long len) |
3426 | 0 | { |
3427 | 0 | int err = 0; |
3428 | 0 | word32 idx = 0; |
3429 | 0 | WOLFSSL_EC_KEY* ret = NULL; |
3430 | |
|
3431 | 0 | WOLFSSL_ENTER("wolfSSL_d2i_ECPrivateKey"); |
3432 | | |
3433 | | /* Validate parameters. */ |
3434 | 0 | if ((in == NULL) || (*in == NULL) || (len <= 0)) { |
3435 | 0 | WOLFSSL_MSG("wolfSSL_d2i_ECPrivateKey Bad arguments"); |
3436 | 0 | err = 1; |
3437 | 0 | } |
3438 | | |
3439 | | /* Create a new, empty EC key. */ |
3440 | 0 | if ((!err) && ((ret = wolfSSL_EC_KEY_new()) == NULL)) { |
3441 | 0 | WOLFSSL_MSG("wolfSSL_EC_KEY_new error"); |
3442 | 0 | err = 1; |
3443 | 0 | } |
3444 | | |
3445 | | /* Decode the private key DER data into internal EC key. */ |
3446 | 0 | if ((!err) && (wc_EccPrivateKeyDecode(*in, &idx, (ecc_key*)ret->internal, |
3447 | 0 | (word32)len) != 0)) { |
3448 | 0 | WOLFSSL_MSG("wc_EccPrivateKeyDecode error"); |
3449 | 0 | err = 1; |
3450 | 0 | } |
3451 | |
|
3452 | 0 | if (!err) { |
3453 | | /* Internal EC key setup. */ |
3454 | 0 | ret->inSet = 1; |
3455 | | |
3456 | | /* Set the EC key from the internal values. */ |
3457 | 0 | if (SetECKeyExternal(ret) != 1) { |
3458 | 0 | WOLFSSL_MSG("SetECKeyExternal error"); |
3459 | 0 | err = 1; |
3460 | 0 | } |
3461 | 0 | } |
3462 | |
|
3463 | 0 | if (!err) { |
3464 | | /* Move buffer on to next byte after data used. */ |
3465 | 0 | *in += idx; |
3466 | 0 | if (key) { |
3467 | | /* Return new EC key through reference. */ |
3468 | 0 | *key = ret; |
3469 | 0 | } |
3470 | 0 | } |
3471 | |
|
3472 | 0 | if (err && (ret != NULL)) { |
3473 | | /* Dispose of allocated EC key. */ |
3474 | 0 | wolfSSL_EC_KEY_free(ret); |
3475 | 0 | ret = NULL; |
3476 | 0 | } |
3477 | 0 | return ret; |
3478 | 0 | } |
3479 | | #endif /* HAVE_ECC_KEY_IMPORT */ |
3480 | | |
3481 | | /* Enecode the private key of the EC key into the buffer as DER. |
3482 | | * |
3483 | | * @param [in] key EC key to encode. |
3484 | | * @param [in, out] out On in, reference to buffer to place DER encoding into. |
3485 | | * On out, reference to buffer after the encoding. |
3486 | | * May be NULL. |
3487 | | * @return Length of DER encoding on success. |
3488 | | * @return 0 on error. |
3489 | | */ |
3490 | | int wolfSSL_i2d_ECPrivateKey(const WOLFSSL_EC_KEY *key, unsigned char **out) |
3491 | 0 | { |
3492 | 0 | int err = 0; |
3493 | 0 | word32 len = 0; |
3494 | |
|
3495 | 0 | WOLFSSL_ENTER("wolfSSL_i2d_ECPrivateKey"); |
3496 | | |
3497 | | /* Validate parameters. */ |
3498 | 0 | if (key == NULL) { |
3499 | 0 | WOLFSSL_MSG("wolfSSL_i2d_ECPrivateKey Bad arguments"); |
3500 | 0 | err = 1; |
3501 | 0 | } |
3502 | | |
3503 | | /* Update the internal EC key if not set. */ |
3504 | 0 | if ((!err) && (!key->inSet) && (SetECKeyInternal((WOLFSSL_EC_KEY*)key) != |
3505 | 0 | 1)) { |
3506 | 0 | WOLFSSL_MSG("SetECKeyInternal error"); |
3507 | 0 | err = 1; |
3508 | 0 | } |
3509 | | |
3510 | | /* Calculate the length of the private key DER encoding using internal EC |
3511 | | * key. */ |
3512 | 0 | if ((!err) && ((int)(len = (word32)wc_EccKeyDerSize((ecc_key*)key->internal, |
3513 | 0 | 0)) <= 0)) { |
3514 | 0 | WOLFSSL_MSG("wc_EccKeyDerSize error"); |
3515 | 0 | err = 1; |
3516 | 0 | } |
3517 | | |
3518 | | /* Only return length when out is NULL. */ |
3519 | 0 | if ((!err) && (out != NULL)) { |
3520 | 0 | unsigned char* buf = NULL; |
3521 | | |
3522 | | /* Must have a buffer to encode into. */ |
3523 | 0 | if (*out == NULL) { |
3524 | | /* Allocate a new buffer of appropriate length. */ |
3525 | 0 | buf = (byte*)XMALLOC(len, NULL, DYNAMIC_TYPE_TMP_BUFFER); |
3526 | 0 | if (buf == NULL) { |
3527 | | /* Error and return 0. */ |
3528 | 0 | err = 1; |
3529 | 0 | len = 0; |
3530 | 0 | } |
3531 | 0 | else { |
3532 | | /* Return the allocated buffer. */ |
3533 | 0 | *out = buf; |
3534 | 0 | } |
3535 | 0 | } |
3536 | | /* Encode the internal EC key as a private key in DER format. */ |
3537 | 0 | if ((!err) && wc_EccPrivateKeyToDer((ecc_key*)key->internal, *out, |
3538 | 0 | len) < 0) { |
3539 | 0 | WOLFSSL_MSG("wc_EccPrivateKeyToDer error"); |
3540 | 0 | err = 1; |
3541 | 0 | } |
3542 | 0 | else if (buf != *out) { |
3543 | | /* Move the reference to byte past encoded private key. */ |
3544 | 0 | *out += len; |
3545 | 0 | } |
3546 | | |
3547 | | /* Dispose of any allocated buffer on error. */ |
3548 | 0 | if (err && (*out == buf)) { |
3549 | 0 | if (buf != NULL) { |
3550 | 0 | ForceZero(buf, len); |
3551 | 0 | } |
3552 | 0 | XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER); |
3553 | 0 | *out = NULL; |
3554 | 0 | } |
3555 | 0 | } |
3556 | |
|
3557 | 0 | return (int)len; |
3558 | 0 | } |
3559 | | |
3560 | | /* Load private key into EC key from DER encoding. |
3561 | | * |
3562 | | * Not an OpenSSL compatibility API. |
3563 | | * |
3564 | | * @param [in, out] key EC key to put private key values into. |
3565 | | * @param [in] derBuf Buffer holding DER encoding. |
3566 | | * @param [in] derSz Size of DER encoding in bytes. |
3567 | | * @return 1 on success. |
3568 | | * @return -1 on error. |
3569 | | */ |
3570 | | int wolfSSL_EC_KEY_LoadDer(WOLFSSL_EC_KEY* key, const unsigned char* derBuf, |
3571 | | int derSz) |
3572 | 0 | { |
3573 | 0 | return wolfSSL_EC_KEY_LoadDer_ex(key, derBuf, derSz, |
3574 | 0 | WOLFSSL_EC_KEY_LOAD_PRIVATE); |
3575 | 0 | } |
3576 | | |
3577 | | /* Load private/public key into EC key from DER encoding. |
3578 | | * |
3579 | | * Not an OpenSSL compatibility API. |
3580 | | * |
3581 | | * @param [in, out] key EC key to put private/public key values into. |
3582 | | * @param [in] derBuf Buffer holding DER encoding. |
3583 | | * @param [in] derSz Size of DER encoding in bytes. |
3584 | | * @param [in] opt Key type option. Valid values: |
3585 | | * WOLFSSL_EC_KEY_LOAD_PRIVATE, |
3586 | | * WOLFSSL_EC_KEY_LOAD_PUBLIC. |
3587 | | * @return 1 on success. |
3588 | | * @return -1 on error. |
3589 | | */ |
3590 | | int wolfSSL_EC_KEY_LoadDer_ex(WOLFSSL_EC_KEY* key, const unsigned char* derBuf, |
3591 | | int derSz, int opt) |
3592 | 253 | { |
3593 | 253 | int res = 1; |
3594 | 253 | int ret; |
3595 | 253 | word32 idx = 0; |
3596 | 253 | word32 algId; |
3597 | | |
3598 | 253 | WOLFSSL_ENTER("wolfSSL_EC_KEY_LoadDer"); |
3599 | | |
3600 | | /* Validate parameters. */ |
3601 | 253 | if ((key == NULL) || (key->internal == NULL) || (derBuf == NULL) || |
3602 | 253 | (derSz <= 0)) { |
3603 | 0 | WOLFSSL_MSG("Bad function arguments"); |
3604 | 0 | res = WOLFSSL_FATAL_ERROR; |
3605 | 0 | } |
3606 | 253 | if ((res == 1) && (opt != WOLFSSL_EC_KEY_LOAD_PRIVATE) && |
3607 | 253 | (opt != WOLFSSL_EC_KEY_LOAD_PUBLIC)) { |
3608 | 0 | res = WOLFSSL_FATAL_ERROR; |
3609 | 0 | } |
3610 | | |
3611 | 253 | if (res == 1) { |
3612 | | /* Assume no PKCS#8 header. */ |
3613 | 253 | key->pkcs8HeaderSz = 0; |
3614 | | |
3615 | | /* Check if input buffer has PKCS8 header. In the case that it does not |
3616 | | * have a PKCS8 header then do not error out. |
3617 | | */ |
3618 | 253 | if ((ret = ToTraditionalInline_ex((const byte*)derBuf, &idx, |
3619 | 253 | (word32)derSz, &algId)) >= 0) { |
3620 | 0 | WOLFSSL_MSG("Found PKCS8 header"); |
3621 | 0 | key->pkcs8HeaderSz = (word16)idx; |
3622 | 0 | res = 1; |
3623 | 0 | } |
3624 | | /* Error out on parsing error. */ |
3625 | 253 | else if (ret != WC_NO_ERR_TRACE(ASN_PARSE_E)) { |
3626 | 0 | WOLFSSL_MSG("Unexpected error with trying to remove PKCS8 header"); |
3627 | 0 | res = WOLFSSL_FATAL_ERROR; |
3628 | 0 | } |
3629 | 253 | } |
3630 | | |
3631 | 253 | if (res == 1) { |
3632 | | /* Load into internal EC key based on key type option. */ |
3633 | 253 | if (opt == WOLFSSL_EC_KEY_LOAD_PRIVATE) { |
3634 | 0 | ret = wc_EccPrivateKeyDecode(derBuf, &idx, (ecc_key*)key->internal, |
3635 | 0 | (word32)derSz); |
3636 | 0 | } |
3637 | 253 | else { |
3638 | 253 | ret = wc_EccPublicKeyDecode(derBuf, &idx, (ecc_key*)key->internal, |
3639 | 253 | (word32)derSz); |
3640 | 253 | if (ret < 0) { |
3641 | 125 | ecc_key *tmp = (ecc_key*)XMALLOC(sizeof(ecc_key), |
3642 | 125 | ((ecc_key*)key->internal)->heap, DYNAMIC_TYPE_ECC); |
3643 | 125 | if (tmp == NULL) { |
3644 | 0 | ret = WOLFSSL_FATAL_ERROR; |
3645 | 0 | } |
3646 | 125 | else { |
3647 | | /* We now try again as x.963 [point type][x][opt y]. */ |
3648 | 125 | ret = wc_ecc_init_ex(tmp, ((ecc_key*)key->internal)->heap, |
3649 | 125 | INVALID_DEVID); |
3650 | 125 | if (ret == 0) { |
3651 | 125 | ret = wc_ecc_import_x963(derBuf, (word32)derSz, tmp); |
3652 | 125 | if (ret == 0) { |
3653 | | /* Take ownership of new key - set tmp to the old |
3654 | | * key which will then be freed below. */ |
3655 | 0 | ecc_key *old = (ecc_key *)key->internal; |
3656 | 0 | key->internal = tmp; |
3657 | 0 | tmp = old; |
3658 | |
|
3659 | 0 | idx = (word32)derSz; |
3660 | 0 | } |
3661 | 125 | wc_ecc_free(tmp); |
3662 | 125 | } |
3663 | 125 | XFREE(tmp, ((ecc_key*)key->internal)->heap, |
3664 | 125 | DYNAMIC_TYPE_ECC); |
3665 | 125 | } |
3666 | 125 | } |
3667 | 253 | } |
3668 | 253 | if (ret < 0) { |
3669 | | /* Error returned from wolfSSL. */ |
3670 | 125 | if (opt == WOLFSSL_EC_KEY_LOAD_PRIVATE) { |
3671 | 0 | WOLFSSL_MSG("wc_EccPrivateKeyDecode failed"); |
3672 | 0 | } |
3673 | 125 | else { |
3674 | 125 | WOLFSSL_MSG("wc_EccPublicKeyDecode failed"); |
3675 | 125 | } |
3676 | 125 | res = WOLFSSL_FATAL_ERROR; |
3677 | 125 | } |
3678 | | |
3679 | | /* Internal key updated - update whether it is a valid key. */ |
3680 | 253 | key->inSet = (res == 1); |
3681 | 253 | } |
3682 | | |
3683 | | /* Set the external EC key based on value in internal. */ |
3684 | 253 | if ((res == 1) && (SetECKeyExternal(key) != 1)) { |
3685 | 0 | WOLFSSL_MSG("SetECKeyExternal failed"); |
3686 | 0 | res = WOLFSSL_FATAL_ERROR; |
3687 | 0 | } |
3688 | | |
3689 | 253 | return res; |
3690 | 253 | } |
3691 | | |
3692 | | |
3693 | | #ifndef NO_BIO |
3694 | | |
3695 | | WOLFSSL_EC_KEY *wolfSSL_d2i_EC_PUBKEY_bio(WOLFSSL_BIO *bio, |
3696 | | WOLFSSL_EC_KEY **out) |
3697 | 0 | { |
3698 | 0 | char* data = NULL; |
3699 | 0 | int dataSz = 0; |
3700 | 0 | int memAlloced = 0; |
3701 | 0 | WOLFSSL_EC_KEY* ec = NULL; |
3702 | 0 | int err = 0; |
3703 | |
|
3704 | 0 | WOLFSSL_ENTER("wolfSSL_d2i_EC_PUBKEY_bio"); |
3705 | |
|
3706 | 0 | if (bio == NULL) |
3707 | 0 | return NULL; |
3708 | | |
3709 | 0 | if (err == 0 && wolfssl_read_bio(bio, &data, &dataSz, &memAlloced) != 0) { |
3710 | 0 | WOLFSSL_ERROR_MSG("wolfssl_read_bio failed"); |
3711 | 0 | err = 1; |
3712 | 0 | } |
3713 | |
|
3714 | 0 | if (err == 0 && (ec = wolfSSL_EC_KEY_new()) == NULL) { |
3715 | 0 | WOLFSSL_ERROR_MSG("wolfSSL_EC_KEY_new failed"); |
3716 | 0 | err = 1; |
3717 | 0 | } |
3718 | | |
3719 | | /* Load the EC key with the public key from the DER encoding. */ |
3720 | 0 | if (err == 0 && wolfSSL_EC_KEY_LoadDer_ex(ec, (const unsigned char*)data, |
3721 | 0 | dataSz, WOLFSSL_EC_KEY_LOAD_PUBLIC) != 1) { |
3722 | 0 | WOLFSSL_ERROR_MSG("wolfSSL_EC_KEY_LoadDer_ex failed"); |
3723 | 0 | err = 1; |
3724 | 0 | } |
3725 | |
|
3726 | 0 | if (memAlloced) |
3727 | 0 | XFREE(data, NULL, DYNAMIC_TYPE_TMP_BUFFER); |
3728 | 0 | if (err) { /* on error */ |
3729 | 0 | wolfSSL_EC_KEY_free(ec); |
3730 | 0 | ec = NULL; |
3731 | 0 | } |
3732 | 0 | else { /* on success */ |
3733 | 0 | if (out != NULL) |
3734 | 0 | *out = ec; |
3735 | 0 | } |
3736 | |
|
3737 | 0 | return ec; |
3738 | 0 | } |
3739 | | |
3740 | | #endif /* !NO_BIO */ |
3741 | | |
3742 | | /* |
3743 | | * EC key PEM APIs |
3744 | | */ |
3745 | | |
3746 | | #ifdef HAVE_ECC_KEY_EXPORT |
3747 | | #if defined(WOLFSSL_KEY_GEN) && (!defined(NO_FILESYSTEM) || !defined(NO_BIO)) |
3748 | | /* Encode the EC public key as DER. |
3749 | | * |
3750 | | * @param [in] key EC key to encode. |
3751 | | * @param [out] der Pointer through which buffer is returned. |
3752 | | * @param [in] heap Heap hint. |
3753 | | * @return Size of encoding on success. |
3754 | | * @return 0 on error. |
3755 | | */ |
3756 | | static int wolfssl_ec_key_to_pubkey_der(WOLFSSL_EC_KEY* key, |
3757 | | unsigned char** der, void* heap) |
3758 | 0 | { |
3759 | 0 | int sz; |
3760 | 0 | unsigned char* buf = NULL; |
3761 | |
|
3762 | 0 | (void)heap; |
3763 | | |
3764 | | /* Calculate encoded size to allocate. */ |
3765 | 0 | sz = wc_EccPublicKeyDerSize((ecc_key*)key->internal, 1); |
3766 | 0 | if (sz <= 0) { |
3767 | 0 | WOLFSSL_MSG("wc_EccPublicKeyDerSize failed"); |
3768 | 0 | sz = 0; |
3769 | 0 | } |
3770 | 0 | if (sz > 0) { |
3771 | | /* Allocate memory to hold encoding. */ |
3772 | 0 | buf = (byte*)XMALLOC((size_t)sz, heap, DYNAMIC_TYPE_TMP_BUFFER); |
3773 | 0 | if (buf == NULL) { |
3774 | 0 | WOLFSSL_MSG("malloc failed"); |
3775 | 0 | sz = 0; |
3776 | 0 | } |
3777 | 0 | } |
3778 | 0 | if (sz > 0) { |
3779 | | /* Encode public key to DER using wolfSSL. */ |
3780 | 0 | sz = wc_EccPublicKeyToDer((ecc_key*)key->internal, buf, (word32)sz, 1); |
3781 | 0 | if (sz < 0) { |
3782 | 0 | WOLFSSL_MSG("wc_EccPublicKeyToDer failed"); |
3783 | 0 | sz = 0; |
3784 | 0 | } |
3785 | 0 | } |
3786 | | |
3787 | | /* Return buffer on success. */ |
3788 | 0 | if (sz > 0) { |
3789 | 0 | *der = buf; |
3790 | 0 | } |
3791 | 0 | else { |
3792 | | /* Dispose of any dynamically allocated data not returned. */ |
3793 | 0 | XFREE(buf, heap, DYNAMIC_TYPE_TMP_BUFFER); |
3794 | 0 | } |
3795 | |
|
3796 | 0 | return sz; |
3797 | 0 | } |
3798 | | #endif |
3799 | | |
3800 | | #if !defined(NO_FILESYSTEM) && defined(WOLFSSL_KEY_GEN) |
3801 | | /* |
3802 | | * Return code compliant with OpenSSL. |
3803 | | * |
3804 | | * @param [in] fp File pointer to write PEM encoding to. |
3805 | | * @param [in] key EC key to encode and write. |
3806 | | * @return 1 on success. |
3807 | | * @return 0 on error. |
3808 | | */ |
3809 | | int wolfSSL_PEM_write_EC_PUBKEY(XFILE fp, WOLFSSL_EC_KEY* key) |
3810 | 0 | { |
3811 | 0 | int ret = 1; |
3812 | 0 | unsigned char* derBuf = NULL; |
3813 | 0 | int derSz = 0; |
3814 | |
|
3815 | 0 | WOLFSSL_ENTER("wolfSSL_PEM_write_EC_PUBKEY"); |
3816 | | |
3817 | | /* Validate parameters. */ |
3818 | 0 | if ((fp == XBADFILE) || (key == NULL)) { |
3819 | 0 | WOLFSSL_MSG("Bad argument."); |
3820 | 0 | return 0; |
3821 | 0 | } |
3822 | | |
3823 | | /* Encode public key in EC key as DER. */ |
3824 | 0 | derSz = wolfssl_ec_key_to_pubkey_der(key, &derBuf, key->heap); |
3825 | 0 | if (derSz == 0) { |
3826 | 0 | ret = 0; |
3827 | 0 | } |
3828 | | |
3829 | | /* Write out to file the PEM encoding of the DER. */ |
3830 | 0 | if ((ret == 1) && (der_write_to_file_as_pem(derBuf, derSz, fp, |
3831 | 0 | ECC_PUBLICKEY_TYPE, key->heap) != 1)) { |
3832 | 0 | ret = 0; |
3833 | 0 | } |
3834 | | |
3835 | | /* Dispose of any dynamically allocated data. */ |
3836 | 0 | XFREE(derBuf, key->heap, DYNAMIC_TYPE_TMP_BUFFER); |
3837 | |
|
3838 | 0 | WOLFSSL_LEAVE("wolfSSL_PEM_write_EC_PUBKEY", ret); |
3839 | |
|
3840 | 0 | return ret; |
3841 | 0 | } |
3842 | | #endif |
3843 | | #endif |
3844 | | |
3845 | | #ifndef NO_BIO |
3846 | | /* Read a PEM encoded EC public key from a BIO. |
3847 | | * |
3848 | | * @param [in] bio BIO to read EC public key from. |
3849 | | * @param [out] out Pointer to return EC key object through. May be NULL. |
3850 | | * @param [in] cb Password callback when PEM encrypted. |
3851 | | * @param [in] pass NUL terminated string for passphrase when PEM |
3852 | | * encrypted. |
3853 | | * @return New EC key object on success. |
3854 | | * @return NULL on error. |
3855 | | */ |
3856 | | WOLFSSL_EC_KEY* wolfSSL_PEM_read_bio_EC_PUBKEY(WOLFSSL_BIO* bio, |
3857 | | WOLFSSL_EC_KEY** out, wc_pem_password_cb* cb, void *pass) |
3858 | 0 | { |
3859 | 0 | int err = 0; |
3860 | 0 | WOLFSSL_EC_KEY* ec = NULL; |
3861 | 0 | DerBuffer* der = NULL; |
3862 | 0 | int keyFormat = 0; |
3863 | |
|
3864 | 0 | WOLFSSL_ENTER("wolfSSL_PEM_read_bio_EC_PUBKEY"); |
3865 | | |
3866 | | /* Validate parameters. */ |
3867 | 0 | if (bio == NULL) { |
3868 | 0 | err = 1; |
3869 | 0 | } |
3870 | |
|
3871 | 0 | if (!err) { |
3872 | | /* Create an empty EC key. */ |
3873 | 0 | ec = wolfSSL_EC_KEY_new(); |
3874 | 0 | if (ec == NULL) { |
3875 | 0 | err = 1; |
3876 | 0 | } |
3877 | 0 | } |
3878 | | /* Read a PEM key in to a new DER buffer. */ |
3879 | 0 | if ((!err) && (pem_read_bio_key(bio, cb, pass, ECC_PUBLICKEY_TYPE, |
3880 | 0 | &keyFormat, &der) <= 0)) { |
3881 | 0 | err = 1; |
3882 | 0 | } |
3883 | | /* Load the EC key with the public key from the DER encoding. */ |
3884 | 0 | if ((!err) && (wolfSSL_EC_KEY_LoadDer_ex(ec, der->buffer, (int)der->length, |
3885 | 0 | WOLFSSL_EC_KEY_LOAD_PUBLIC) != 1)) { |
3886 | 0 | WOLFSSL_ERROR_MSG("Error loading DER buffer into WOLFSSL_EC_KEY"); |
3887 | 0 | err = 1; |
3888 | 0 | } |
3889 | | |
3890 | | /* Dispose of dynamically allocated data not needed anymore. */ |
3891 | 0 | FreeDer(&der); |
3892 | 0 | if (err) { |
3893 | 0 | wolfSSL_EC_KEY_free(ec); |
3894 | 0 | ec = NULL; |
3895 | 0 | } |
3896 | | |
3897 | | /* Return EC key through out if required. */ |
3898 | 0 | if ((out != NULL) && (ec != NULL)) { |
3899 | 0 | *out = ec; |
3900 | 0 | } |
3901 | 0 | return ec; |
3902 | 0 | } |
3903 | | |
3904 | | /* Read a PEM encoded EC private key from a BIO. |
3905 | | * |
3906 | | * @param [in] bio BIO to read EC private key from. |
3907 | | * @param [out] out Pointer to return EC key object through. May be NULL. |
3908 | | * @param [in] cb Password callback when PEM encrypted. |
3909 | | * @param [in] pass NUL terminated string for passphrase when PEM |
3910 | | * encrypted. |
3911 | | * @return New EC key object on success. |
3912 | | * @return NULL on error. |
3913 | | */ |
3914 | | WOLFSSL_EC_KEY* wolfSSL_PEM_read_bio_ECPrivateKey(WOLFSSL_BIO* bio, |
3915 | | WOLFSSL_EC_KEY** out, wc_pem_password_cb* cb, void *pass) |
3916 | 0 | { |
3917 | 0 | int err = 0; |
3918 | 0 | WOLFSSL_EC_KEY* ec = NULL; |
3919 | 0 | DerBuffer* der = NULL; |
3920 | 0 | int keyFormat = 0; |
3921 | |
|
3922 | 0 | WOLFSSL_ENTER("wolfSSL_PEM_read_bio_ECPrivateKey"); |
3923 | | |
3924 | | /* Validate parameters. */ |
3925 | 0 | if (bio == NULL) { |
3926 | 0 | err = 1; |
3927 | 0 | } |
3928 | |
|
3929 | 0 | if (!err) { |
3930 | | /* Create an empty EC key. */ |
3931 | 0 | ec = wolfSSL_EC_KEY_new(); |
3932 | 0 | if (ec == NULL) { |
3933 | 0 | err = 1; |
3934 | 0 | } |
3935 | 0 | } |
3936 | | /* Read a PEM key in to a new DER buffer. |
3937 | | * To check ENC EC PRIVATE KEY, it uses PRIVATEKEY_TYPE to call |
3938 | | * pem_read_bio_key(), and then check key format if it is EC. |
3939 | | */ |
3940 | 0 | if ((!err) && (pem_read_bio_key(bio, cb, pass, PRIVATEKEY_TYPE, |
3941 | 0 | &keyFormat, &der) <= 0)) { |
3942 | 0 | err = 1; |
3943 | 0 | } |
3944 | 0 | if (keyFormat != ECDSAk) { |
3945 | 0 | WOLFSSL_ERROR_MSG("Error not EC key format"); |
3946 | 0 | err = 1; |
3947 | 0 | } |
3948 | | /* Load the EC key with the private key from the DER encoding. */ |
3949 | 0 | if ((!err) && (wolfSSL_EC_KEY_LoadDer_ex(ec, der->buffer, (int)der->length, |
3950 | 0 | WOLFSSL_EC_KEY_LOAD_PRIVATE) != 1)) { |
3951 | 0 | WOLFSSL_ERROR_MSG("Error loading DER buffer into WOLFSSL_EC_KEY"); |
3952 | 0 | err = 1; |
3953 | 0 | } |
3954 | | |
3955 | | /* Dispose of dynamically allocated data not needed anymore. */ |
3956 | 0 | FreeDer(&der); |
3957 | 0 | if (err) { |
3958 | 0 | wolfSSL_EC_KEY_free(ec); |
3959 | 0 | ec = NULL; |
3960 | 0 | } |
3961 | | |
3962 | | /* Return EC key through out if required. */ |
3963 | 0 | if ((out != NULL) && (ec != NULL)) { |
3964 | 0 | *out = ec; |
3965 | 0 | } |
3966 | 0 | return ec; |
3967 | 0 | } |
3968 | | #endif /* !NO_BIO */ |
3969 | | |
3970 | | #if defined(WOLFSSL_KEY_GEN) && defined(HAVE_ECC_KEY_EXPORT) |
3971 | | #ifndef NO_BIO |
3972 | | /* Write out the EC public key as PEM to the BIO. |
3973 | | * |
3974 | | * @param [in] bio BIO to write PEM encoding to. |
3975 | | * @param [in] ec EC public key to encode. |
3976 | | * @return 1 on success. |
3977 | | * @return 0 on error. |
3978 | | */ |
3979 | | int wolfSSL_PEM_write_bio_EC_PUBKEY(WOLFSSL_BIO* bio, WOLFSSL_EC_KEY* ec) |
3980 | 0 | { |
3981 | 0 | int ret = 1; |
3982 | 0 | unsigned char* derBuf = NULL; |
3983 | 0 | int derSz = 0; |
3984 | |
|
3985 | 0 | WOLFSSL_ENTER("wolfSSL_PEM_write_bio_EC_PUBKEY"); |
3986 | | |
3987 | | /* Validate parameters. */ |
3988 | 0 | if ((bio == NULL) || (ec == NULL)) { |
3989 | 0 | WOLFSSL_MSG("Bad Function Arguments"); |
3990 | 0 | return 0; |
3991 | 0 | } |
3992 | | |
3993 | | /* Encode public key in EC key as DER. */ |
3994 | 0 | derSz = wolfssl_ec_key_to_pubkey_der(ec, &derBuf, ec->heap); |
3995 | 0 | if (derSz == 0) { |
3996 | 0 | ret = 0; |
3997 | 0 | } |
3998 | | |
3999 | | /* Write out to BIO the PEM encoding of the EC public key. */ |
4000 | 0 | if ((ret == 1) && (der_write_to_bio_as_pem(derBuf, derSz, bio, |
4001 | 0 | ECC_PUBLICKEY_TYPE) != 1)) { |
4002 | 0 | ret = 0; |
4003 | 0 | } |
4004 | | |
4005 | | /* Dispose of any dynamically allocated data. */ |
4006 | 0 | XFREE(derBuf, ec->heap, DYNAMIC_TYPE_TMP_BUFFER); |
4007 | |
|
4008 | 0 | return ret; |
4009 | 0 | } |
4010 | | |
4011 | | /* Write out the EC private key as PEM to the BIO. |
4012 | | * |
4013 | | * Return code compliant with OpenSSL. |
4014 | | * |
4015 | | * @param [in] bio BIO to write PEM encoding to. |
4016 | | * @param [in] ec EC private key to encode. |
4017 | | * @param [in] cipher Cipher to use when PEM encrypted. May be NULL. |
4018 | | * @param [in] passwd Password string when PEM encrypted. May be NULL. |
4019 | | * @param [in] passwdSz Length of password string when PEM encrypted. |
4020 | | * @param [in] cb Password callback when PEM encrypted. Unused. |
4021 | | * @param [in] pass NUL terminated string for passphrase when PEM |
4022 | | * encrypted. Unused. |
4023 | | * @return 1 on success. |
4024 | | * @return 0 on error. |
4025 | | */ |
4026 | | int wolfSSL_PEM_write_bio_ECPrivateKey(WOLFSSL_BIO* bio, WOLFSSL_EC_KEY* ec, |
4027 | | const WOLFSSL_EVP_CIPHER* cipher, unsigned char* passwd, int passwdSz, |
4028 | | wc_pem_password_cb* cb, void* arg) |
4029 | 0 | { |
4030 | 0 | int ret = 1; |
4031 | 0 | unsigned char* pem = NULL; |
4032 | 0 | int pLen = 0; |
4033 | |
|
4034 | 0 | (void)cb; |
4035 | 0 | (void)arg; |
4036 | | |
4037 | | /* Validate parameters. */ |
4038 | 0 | if ((bio == NULL) || (ec == NULL)) { |
4039 | 0 | ret = 0; |
4040 | 0 | } |
4041 | | |
4042 | | /* Write EC private key to PEM. */ |
4043 | 0 | if ((ret == 1) && (wolfSSL_PEM_write_mem_ECPrivateKey(ec, cipher, passwd, |
4044 | 0 | passwdSz, &pem, &pLen) != 1)) { |
4045 | 0 | ret = 0; |
4046 | 0 | } |
4047 | | /* Write PEM to BIO. */ |
4048 | 0 | if ((ret == 1) && (wolfSSL_BIO_write(bio, pem, pLen) != pLen)) { |
4049 | 0 | WOLFSSL_ERROR_MSG("EC private key BIO write failed"); |
4050 | 0 | ret = 0; |
4051 | 0 | } |
4052 | |
|
4053 | 0 | XFREE(pem, NULL, DYNAMIC_TYPE_KEY); |
4054 | |
|
4055 | 0 | return ret; |
4056 | 0 | } |
4057 | | |
4058 | | #endif /* !NO_BIO */ |
4059 | | |
4060 | | /* Encode the EC private key as PEM into buffer. |
4061 | | * |
4062 | | * Return code compliant with OpenSSL. |
4063 | | * Not an OpenSSL API. |
4064 | | * |
4065 | | * @param [in] ec EC private key to encode. |
4066 | | * @param [in] cipher Cipher to use when PEM encrypted. May be NULL. |
4067 | | * @param [in] passwd Password string when PEM encrypted. May be NULL. |
4068 | | * @param [in] passwdSz Length of password string when PEM encrypted. |
4069 | | * @param [out] pem Newly allocated buffer holding PEM encoding. |
4070 | | * @param [out] pLen Length of PEM encoding in bytes. |
4071 | | * @return 1 on success. |
4072 | | * @return 0 on error. |
4073 | | */ |
4074 | | int wolfSSL_PEM_write_mem_ECPrivateKey(WOLFSSL_EC_KEY* ec, |
4075 | | const WOLFSSL_EVP_CIPHER* cipher, unsigned char* passwd, int passwdSz, |
4076 | | unsigned char **pem, int *pLen) |
4077 | 0 | { |
4078 | 0 | #if defined(WOLFSSL_PEM_TO_DER) || defined(WOLFSSL_DER_TO_PEM) |
4079 | 0 | int ret = 1; |
4080 | 0 | byte* derBuf = NULL; |
4081 | 0 | word32 der_max_len = 0; |
4082 | 0 | int derSz = 0; |
4083 | |
|
4084 | 0 | WOLFSSL_MSG("wolfSSL_PEM_write_mem_ECPrivateKey"); |
4085 | | |
4086 | | /* Validate parameters. */ |
4087 | 0 | if ((pem == NULL) || (pLen == NULL) || (ec == NULL) || |
4088 | 0 | (ec->internal == NULL)) { |
4089 | 0 | WOLFSSL_MSG("Bad function arguments"); |
4090 | 0 | ret = 0; |
4091 | 0 | } |
4092 | | |
4093 | | /* Ensure internal EC key is set from external. */ |
4094 | 0 | if ((ret == 1) && (ec->inSet == 0)) { |
4095 | 0 | WOLFSSL_MSG("No ECC internal set, do it"); |
4096 | |
|
4097 | 0 | if (SetECKeyInternal(ec) != 1) { |
4098 | 0 | WOLFSSL_MSG("SetECKeyInternal failed"); |
4099 | 0 | ret = 0; |
4100 | 0 | } |
4101 | 0 | } |
4102 | |
|
4103 | 0 | if (ret == 1) { |
4104 | | /* Calculate maximum size of DER encoding. |
4105 | | * 4 > size of pub, priv + ASN.1 additional information */ |
4106 | 0 | der_max_len = 4 * (word32)wc_ecc_size((ecc_key*)ec->internal) + |
4107 | 0 | WC_AES_BLOCK_SIZE; |
4108 | | |
4109 | | /* Allocate buffer big enough to hold encoding. */ |
4110 | 0 | derBuf = (byte*)XMALLOC((size_t)der_max_len, NULL, |
4111 | 0 | DYNAMIC_TYPE_TMP_BUFFER); |
4112 | 0 | if (derBuf == NULL) { |
4113 | 0 | WOLFSSL_MSG("malloc failed"); |
4114 | 0 | ret = 0; |
4115 | 0 | } |
4116 | 0 | } |
4117 | |
|
4118 | 0 | if (ret == 1) { |
4119 | | /* Encode EC private key as DER. */ |
4120 | 0 | derSz = wc_EccKeyToDer((ecc_key*)ec->internal, derBuf, der_max_len); |
4121 | 0 | if (derSz < 0) { |
4122 | 0 | WOLFSSL_MSG("wc_EccKeyToDer failed"); |
4123 | 0 | ForceZero(derBuf, der_max_len); |
4124 | 0 | XFREE(derBuf, NULL, DYNAMIC_TYPE_DER); |
4125 | 0 | ret = 0; |
4126 | 0 | } |
4127 | 0 | } |
4128 | | |
4129 | | /* Convert DER to PEM - possibly encrypting. */ |
4130 | 0 | if ((ret == 1) && (der_to_enc_pem_alloc(derBuf, derSz, cipher, passwd, |
4131 | 0 | passwdSz, ECC_PRIVATEKEY_TYPE, NULL, pem, pLen) != 1)) { |
4132 | 0 | WOLFSSL_ERROR_MSG("der_to_enc_pem_alloc failed"); |
4133 | 0 | ret = 0; |
4134 | 0 | } |
4135 | |
|
4136 | 0 | return ret; |
4137 | | #else |
4138 | | (void)ec; |
4139 | | (void)cipher; |
4140 | | (void)passwd; |
4141 | | (void)passwdSz; |
4142 | | (void)pem; |
4143 | | (void)pLen; |
4144 | | return 0; |
4145 | | #endif /* WOLFSSL_PEM_TO_DER || WOLFSSL_DER_TO_PEM */ |
4146 | 0 | } |
4147 | | |
4148 | | #ifndef NO_FILESYSTEM |
4149 | | /* Write out the EC private key as PEM to file. |
4150 | | * |
4151 | | * Return code compliant with OpenSSL. |
4152 | | * |
4153 | | * @param [in] fp File pointer to write PEM encoding to. |
4154 | | * @param [in] ec EC private key to encode. |
4155 | | * @param [in] cipher Cipher to use when PEM encrypted. May be NULL. |
4156 | | * @param [in] passwd Password string when PEM encrypted. May be NULL. |
4157 | | * @param [in] passwdSz Length of password string when PEM encrypted. |
4158 | | * @param [in] cb Password callback when PEM encrypted. Unused. |
4159 | | * @param [in] pass NUL terminated string for passphrase when PEM |
4160 | | * encrypted. Unused. |
4161 | | * @return 1 on success. |
4162 | | * @return 0 on error. |
4163 | | */ |
4164 | | int wolfSSL_PEM_write_ECPrivateKey(XFILE fp, WOLFSSL_EC_KEY *ec, |
4165 | | const WOLFSSL_EVP_CIPHER *cipher, unsigned char *passwd, int passwdSz, |
4166 | | wc_pem_password_cb *cb, void *pass) |
4167 | 0 | { |
4168 | 0 | int ret = 1; |
4169 | 0 | byte *pem = NULL; |
4170 | 0 | int pLen = 0; |
4171 | |
|
4172 | 0 | (void)cb; |
4173 | 0 | (void)pass; |
4174 | |
|
4175 | 0 | WOLFSSL_MSG("wolfSSL_PEM_write_ECPrivateKey"); |
4176 | | |
4177 | | /* Validate parameters. */ |
4178 | 0 | if ((fp == XBADFILE) || (ec == NULL) || (ec->internal == NULL)) { |
4179 | 0 | WOLFSSL_MSG("Bad function arguments"); |
4180 | 0 | ret = 0; |
4181 | 0 | } |
4182 | | |
4183 | | /* Write EC private key to PEM. */ |
4184 | 0 | if ((ret == 1) && (wolfSSL_PEM_write_mem_ECPrivateKey(ec, cipher, passwd, |
4185 | 0 | passwdSz, &pem, &pLen) != 1)) { |
4186 | 0 | WOLFSSL_MSG("wolfSSL_PEM_write_mem_ECPrivateKey failed"); |
4187 | 0 | ret = 0; |
4188 | 0 | } |
4189 | | |
4190 | | /* Write out to file the PEM encoding of the EC private key. */ |
4191 | 0 | if ((ret == 1) && ((int)XFWRITE(pem, 1, (size_t)pLen, fp) != pLen)) { |
4192 | 0 | WOLFSSL_MSG("ECC private key file write failed"); |
4193 | 0 | ret = 0; |
4194 | 0 | } |
4195 | | |
4196 | | /* Dispose of any dynamically allocated data. */ |
4197 | 0 | XFREE(pem, NULL, DYNAMIC_TYPE_KEY); |
4198 | |
|
4199 | 0 | return ret; |
4200 | 0 | } |
4201 | | |
4202 | | #endif /* NO_FILESYSTEM */ |
4203 | | #endif /* WOLFSSL_KEY_GEN && HAVE_ECC_KEY_EXPORT */ |
4204 | | |
4205 | | /* |
4206 | | * EC key print APIs |
4207 | | */ |
4208 | | |
4209 | | #ifndef NO_CERTS |
4210 | | |
4211 | | #if defined(XFPRINTF) && !defined(NO_FILESYSTEM) && \ |
4212 | | !defined(NO_STDIO_FILESYSTEM) |
4213 | | /* Print the EC key to a file pointer as text. |
4214 | | * |
4215 | | * @param [in] fp File pointer. |
4216 | | * @param [in] key EC key to print. |
4217 | | * @param [in] indent Number of spaces to place before each line printed. |
4218 | | * @return 1 on success. |
4219 | | * @return 0 on failure. |
4220 | | */ |
4221 | | int wolfSSL_EC_KEY_print_fp(XFILE fp, WOLFSSL_EC_KEY* key, int indent) |
4222 | 0 | { |
4223 | 0 | int ret = 1; |
4224 | 0 | int bits = 0; |
4225 | 0 | int priv = 0; |
4226 | |
|
4227 | 0 | WOLFSSL_ENTER("wolfSSL_EC_KEY_print_fp"); |
4228 | | |
4229 | | /* Validate parameters. */ |
4230 | 0 | if ((fp == XBADFILE) || (key == NULL) || (key->group == NULL) || |
4231 | 0 | (indent < 0)) { |
4232 | 0 | ret = 0; |
4233 | 0 | } |
4234 | |
|
4235 | 0 | if (ret == 1) { |
4236 | | /* Get EC groups order size in bits. */ |
4237 | 0 | bits = wolfSSL_EC_GROUP_order_bits(key->group); |
4238 | 0 | if (bits <= 0) { |
4239 | 0 | WOLFSSL_MSG("Failed to get group order bits."); |
4240 | 0 | ret = 0; |
4241 | 0 | } |
4242 | 0 | } |
4243 | 0 | if (ret == 1) { |
4244 | 0 | const char* keyType; |
4245 | | |
4246 | | /* Determine whether this is a private or public key. */ |
4247 | 0 | if ((key->priv_key != NULL) && (!wolfSSL_BN_is_zero(key->priv_key))) { |
4248 | 0 | keyType = "Private-Key"; |
4249 | 0 | priv = 1; |
4250 | 0 | } |
4251 | 0 | else { |
4252 | 0 | keyType = "Public-Key"; |
4253 | 0 | } |
4254 | | |
4255 | | /* Print key header. */ |
4256 | 0 | if (XFPRINTF(fp, "%*s%s: (%d bit)\n", indent, "", keyType, bits) < 0) { |
4257 | 0 | ret = 0; |
4258 | 0 | } |
4259 | 0 | } |
4260 | 0 | if ((ret == 1) && priv) { |
4261 | | /* Print the private key BN. */ |
4262 | 0 | ret = pk_bn_field_print_fp(fp, indent, "priv", key->priv_key); |
4263 | 0 | } |
4264 | | /* Check for public key data in EC key. */ |
4265 | 0 | if ((ret == 1) && (key->pub_key != NULL) && (key->pub_key->exSet)) { |
4266 | | /* Get the public key point as one BN. */ |
4267 | 0 | WOLFSSL_BIGNUM* pubBn = wolfSSL_EC_POINT_point2bn(key->group, |
4268 | 0 | key->pub_key, WC_POINT_CONVERSION_UNCOMPRESSED, NULL, NULL); |
4269 | 0 | if (pubBn == NULL) { |
4270 | 0 | WOLFSSL_MSG("wolfSSL_EC_POINT_point2bn failed."); |
4271 | 0 | ret = 0; |
4272 | 0 | } |
4273 | 0 | else { |
4274 | | /* Print the public key in a BN. */ |
4275 | 0 | ret = pk_bn_field_print_fp(fp, indent, "pub", pubBn); |
4276 | 0 | wolfSSL_BN_free(pubBn); |
4277 | 0 | } |
4278 | 0 | } |
4279 | 0 | if (ret == 1) { |
4280 | | /* Get the NID of the group. */ |
4281 | 0 | int nid = wolfSSL_EC_GROUP_get_curve_name(key->group); |
4282 | 0 | if (nid > 0) { |
4283 | | /* Convert the NID into a long name and NIST name. */ |
4284 | 0 | const char* curve = wolfSSL_OBJ_nid2ln(nid); |
4285 | 0 | const char* nistName = wolfSSL_EC_curve_nid2nist(nid); |
4286 | | |
4287 | | /* Print OID name if known. */ |
4288 | 0 | if ((curve != NULL) && |
4289 | 0 | (XFPRINTF(fp, "%*sASN1 OID: %s\n", indent, "", curve) < 0)) { |
4290 | 0 | ret = 0; |
4291 | 0 | } |
4292 | | /* Print NIST curve name if known. */ |
4293 | 0 | if ((nistName != NULL) && |
4294 | 0 | (XFPRINTF(fp, "%*sNIST CURVE: %s\n", indent, "", |
4295 | 0 | nistName) < 0)) { |
4296 | 0 | ret = 0; |
4297 | 0 | } |
4298 | 0 | } |
4299 | 0 | } |
4300 | | |
4301 | |
|
4302 | 0 | WOLFSSL_LEAVE("wolfSSL_EC_KEY_print_fp", ret); |
4303 | |
|
4304 | 0 | return ret; |
4305 | 0 | } |
4306 | | #endif /* XFPRINTF && !NO_FILESYSTEM && !NO_STDIO_FILESYSTEM */ |
4307 | | |
4308 | | #endif /* !NO_CERTS */ |
4309 | | |
4310 | | /* |
4311 | | * EC_KEY get/set/test APIs |
4312 | | */ |
4313 | | |
4314 | | /* Set data of internal, wolfCrypt EC key object into EC key. |
4315 | | * |
4316 | | * EC_KEY wolfSSL -> OpenSSL |
4317 | | * |
4318 | | * @param [in, out] p EC key to update. |
4319 | | * @return 1 on success. |
4320 | | * @return -1 on failure. |
4321 | | */ |
4322 | | int SetECKeyExternal(WOLFSSL_EC_KEY* eckey) |
4323 | 128 | { |
4324 | 128 | int ret = 1; |
4325 | | |
4326 | 128 | WOLFSSL_ENTER("SetECKeyExternal"); |
4327 | | |
4328 | | /* Validate parameter. */ |
4329 | 128 | if ((eckey == NULL) || (eckey->internal == NULL)) { |
4330 | 0 | WOLFSSL_MSG("ec key NULL error"); |
4331 | 0 | ret = WOLFSSL_FATAL_ERROR; |
4332 | 0 | } |
4333 | 128 | else { |
4334 | 128 | ecc_key* key = (ecc_key*)eckey->internal; |
4335 | | |
4336 | | /* Set group (OID, nid and idx) from wolfCrypt EC key. */ |
4337 | 128 | eckey->group->curve_oid = (int)key->dp->oidSum; |
4338 | 128 | eckey->group->curve_nid = EccEnumToNID(key->dp->id); |
4339 | 128 | eckey->group->curve_idx = key->idx; |
4340 | | |
4341 | 128 | if (eckey->pub_key->internal != NULL) { |
4342 | | /* Copy internal public point from internal key's public point. */ |
4343 | 128 | if (wc_ecc_copy_point(&key->pubkey, |
4344 | 128 | (ecc_point*)eckey->pub_key->internal) != MP_OKAY) { |
4345 | 0 | WOLFSSL_MSG("SetECKeyExternal ecc_copy_point failed"); |
4346 | 0 | ret = WOLFSSL_FATAL_ERROR; |
4347 | 0 | } |
4348 | | |
4349 | | /* Set external public key from internal wolfCrypt, public key. */ |
4350 | 128 | if ((ret == 1) && (ec_point_external_set(eckey->pub_key) != 1)) { |
4351 | 0 | WOLFSSL_MSG("SetECKeyExternal ec_point_external_set failed"); |
4352 | 0 | ret = WOLFSSL_FATAL_ERROR; |
4353 | 0 | } |
4354 | 128 | } |
4355 | | |
4356 | | /* set the external privkey */ |
4357 | 128 | if ((ret == 1) && (key->type == ECC_PRIVATEKEY) && |
4358 | 0 | (wolfssl_bn_set_value(&eckey->priv_key, |
4359 | 0 | wc_ecc_key_get_priv(key)) != 1)) { |
4360 | 0 | WOLFSSL_MSG("ec priv key error"); |
4361 | 0 | ret = WOLFSSL_FATAL_ERROR; |
4362 | 0 | } |
4363 | | |
4364 | | /* External values set when operations succeeded. */ |
4365 | 128 | eckey->exSet = (ret == 1); |
4366 | 128 | } |
4367 | | |
4368 | 128 | return ret; |
4369 | 128 | } |
4370 | | |
4371 | | /* Set data of EC key into internal, wolfCrypt EC key object. |
4372 | | * |
4373 | | * EC_KEY Openssl -> WolfSSL |
4374 | | * |
4375 | | * @param [in, out] p EC key to update. |
4376 | | * @return 1 on success. |
4377 | | * @return -1 on failure. |
4378 | | */ |
4379 | | int SetECKeyInternal(WOLFSSL_EC_KEY* eckey) |
4380 | 1.12k | { |
4381 | 1.12k | int ret = 1; |
4382 | | |
4383 | 1.12k | WOLFSSL_ENTER("SetECKeyInternal"); |
4384 | | |
4385 | | /* Validate parameter. */ |
4386 | 1.12k | if ((eckey == NULL) || (eckey->internal == NULL) || |
4387 | 1.12k | (eckey->group == NULL)) { |
4388 | 0 | WOLFSSL_MSG("ec key NULL error"); |
4389 | 0 | ret = WOLFSSL_FATAL_ERROR; |
4390 | 0 | } |
4391 | 1.12k | else { |
4392 | 1.12k | ecc_key* key = (ecc_key*)eckey->internal; |
4393 | 1.12k | int pubSet = 0; |
4394 | | |
4395 | | /* Validate group. */ |
4396 | 1.12k | if ((eckey->group->curve_idx < 0) || |
4397 | 1.12k | (wc_ecc_is_valid_idx(eckey->group->curve_idx) == 0)) { |
4398 | 0 | WOLFSSL_MSG("invalid curve idx"); |
4399 | 0 | ret = WOLFSSL_FATAL_ERROR; |
4400 | 0 | } |
4401 | | |
4402 | 1.12k | if (ret == 1) { |
4403 | | /* Set group (idx of curve and corresponding domain parameters). */ |
4404 | 1.12k | key->idx = eckey->group->curve_idx; |
4405 | 1.12k | key->dp = &ecc_sets[key->idx]; |
4406 | 1.12k | pubSet = (eckey->pub_key != NULL); |
4407 | 1.12k | } |
4408 | | /* Set public key (point). */ |
4409 | 1.12k | if ((ret == 1) && pubSet) { |
4410 | 1.12k | if (ec_point_internal_set(eckey->pub_key) != 1) { |
4411 | 0 | WOLFSSL_MSG("ec key pub error"); |
4412 | 0 | ret = WOLFSSL_FATAL_ERROR; |
4413 | 0 | } |
4414 | | /* Copy public point to key. */ |
4415 | 1.12k | if ((ret == 1) && (wc_ecc_copy_point( |
4416 | 1.12k | (ecc_point*)eckey->pub_key->internal, &key->pubkey) != |
4417 | 1.12k | MP_OKAY)) { |
4418 | 0 | WOLFSSL_MSG("wc_ecc_copy_point error"); |
4419 | 0 | ret = WOLFSSL_FATAL_ERROR; |
4420 | 0 | } |
4421 | | |
4422 | 1.12k | if (ret == 1) { |
4423 | | /* Set that the internal key is a public key */ |
4424 | 1.12k | key->type = ECC_PUBLICKEY; |
4425 | 1.12k | } |
4426 | 1.12k | } |
4427 | | |
4428 | | /* set privkey */ |
4429 | 1.12k | if ((ret == 1) && (eckey->priv_key != NULL)) { |
4430 | 1.12k | if (wolfssl_bn_get_value(eckey->priv_key, |
4431 | 1.12k | wc_ecc_key_get_priv(key)) != 1) { |
4432 | 0 | WOLFSSL_MSG("ec key priv error"); |
4433 | 0 | ret = WOLFSSL_FATAL_ERROR; |
4434 | 0 | } |
4435 | | /* private key */ |
4436 | 1.12k | if ((ret == 1) && (!mp_iszero(wc_ecc_key_get_priv(key)))) { |
4437 | 337 | if (pubSet) { |
4438 | 337 | key->type = ECC_PRIVATEKEY; |
4439 | 337 | } |
4440 | 0 | else { |
4441 | 0 | key->type = ECC_PRIVATEKEY_ONLY; |
4442 | 0 | } |
4443 | 337 | } |
4444 | 1.12k | } |
4445 | | |
4446 | | /* Internal values set when operations succeeded. */ |
4447 | 1.12k | eckey->inSet = (ret == 1); |
4448 | 1.12k | } |
4449 | | |
4450 | 1.12k | return ret; |
4451 | 1.12k | } |
4452 | | |
4453 | | /* Get point conversion format of EC key. |
4454 | | * |
4455 | | * @param [in] key EC key. |
4456 | | * @return Point conversion format on success. |
4457 | | * @return -1 on error. |
4458 | | */ |
4459 | | wc_point_conversion_form_t wolfSSL_EC_KEY_get_conv_form( |
4460 | | const WOLFSSL_EC_KEY* key) |
4461 | 0 | { |
4462 | 0 | if (key == NULL) |
4463 | 0 | return WOLFSSL_FATAL_ERROR; |
4464 | 0 | return key->form; |
4465 | 0 | } |
4466 | | |
4467 | | /* Set point conversion format into EC key. |
4468 | | * |
4469 | | * @param [in, out] key EC key to set format into. |
4470 | | * @param [in] form Point conversion format. Valid values: |
4471 | | * WC_POINT_CONVERSION_UNCOMPRESSED, |
4472 | | * WC_POINT_CONVERSION_COMPRESSED (when HAVE_COMP_KEY) |
4473 | | */ |
4474 | | void wolfSSL_EC_KEY_set_conv_form(WOLFSSL_EC_KEY *key, int form) |
4475 | 0 | { |
4476 | 0 | if (key == NULL) { |
4477 | 0 | WOLFSSL_MSG("Key passed in NULL"); |
4478 | 0 | } |
4479 | 0 | else if (form == WC_POINT_CONVERSION_UNCOMPRESSED |
4480 | 0 | #ifdef HAVE_COMP_KEY |
4481 | 0 | || form == WC_POINT_CONVERSION_COMPRESSED |
4482 | 0 | #endif |
4483 | 0 | ) { |
4484 | 0 | key->form = (unsigned char)form; |
4485 | 0 | } |
4486 | 0 | else { |
4487 | 0 | WOLFSSL_MSG("Incorrect form or HAVE_COMP_KEY not compiled in"); |
4488 | 0 | } |
4489 | 0 | } |
4490 | | |
4491 | | /* Get the EC group object that is in EC key. |
4492 | | * |
4493 | | * @param [in] key EC key. |
4494 | | * @return EC group object on success. |
4495 | | * @return NULL when key is NULL. |
4496 | | */ |
4497 | | const WOLFSSL_EC_GROUP *wolfSSL_EC_KEY_get0_group(const WOLFSSL_EC_KEY *key) |
4498 | 0 | { |
4499 | 0 | WOLFSSL_EC_GROUP* group = NULL; |
4500 | |
|
4501 | 0 | WOLFSSL_ENTER("wolfSSL_EC_KEY_get0_group"); |
4502 | |
|
4503 | 0 | if (key != NULL) { |
4504 | 0 | group = key->group; |
4505 | 0 | } |
4506 | |
|
4507 | 0 | return group; |
4508 | 0 | } |
4509 | | |
4510 | | /* Set the group in WOLFSSL_EC_KEY |
4511 | | * |
4512 | | * @param [in, out] key EC key to update. |
4513 | | * @param [in] group EC group to copy. |
4514 | | * @return 1 on success |
4515 | | * @return 0 on failure. |
4516 | | */ |
4517 | | int wolfSSL_EC_KEY_set_group(WOLFSSL_EC_KEY *key, WOLFSSL_EC_GROUP *group) |
4518 | 778 | { |
4519 | 778 | int ret = 1; |
4520 | | |
4521 | 778 | WOLFSSL_ENTER("wolfSSL_EC_KEY_set_group"); |
4522 | | |
4523 | | /* Validate parameters. */ |
4524 | 778 | if ((key == NULL) || (group == NULL)) { |
4525 | 0 | ret = 0; |
4526 | 0 | } |
4527 | | |
4528 | 778 | if (ret == 1) { |
4529 | | /* Dispose of the current group. */ |
4530 | 778 | if (key->group != NULL) { |
4531 | 778 | wolfSSL_EC_GROUP_free(key->group); |
4532 | 778 | } |
4533 | | /* Duplicate the passed in group into EC key. */ |
4534 | 778 | key->group = wolfSSL_EC_GROUP_dup(group); |
4535 | 778 | if (key->group == NULL) { |
4536 | 0 | ret = 0; |
4537 | 0 | } |
4538 | 778 | } |
4539 | | |
4540 | 778 | return ret; |
4541 | 778 | } |
4542 | | |
4543 | | /* Get the BN object that is the private key in the EC key. |
4544 | | * |
4545 | | * @param [in] key EC key. |
4546 | | * @return BN object on success. |
4547 | | * @return NULL when key is NULL or private key is not set. |
4548 | | */ |
4549 | | WOLFSSL_BIGNUM *wolfSSL_EC_KEY_get0_private_key(const WOLFSSL_EC_KEY *key) |
4550 | 0 | { |
4551 | 0 | WOLFSSL_BIGNUM* priv_key = NULL; |
4552 | |
|
4553 | 0 | WOLFSSL_ENTER("wolfSSL_EC_KEY_get0_private_key"); |
4554 | | |
4555 | | /* Validate parameter. */ |
4556 | 0 | if (key == NULL) { |
4557 | 0 | WOLFSSL_MSG("wolfSSL_EC_KEY_get0_private_key Bad arguments"); |
4558 | 0 | } |
4559 | | /* Only return private key if it is not 0. */ |
4560 | 0 | else if (!wolfSSL_BN_is_zero(key->priv_key)) { |
4561 | 0 | priv_key = key->priv_key; |
4562 | 0 | } |
4563 | |
|
4564 | 0 | return priv_key; |
4565 | 0 | } |
4566 | | |
4567 | | /* Sets the private key value into EC key. |
4568 | | * |
4569 | | * Return code compliant with OpenSSL. |
4570 | | * |
4571 | | * @param [in, out] key EC key to set. |
4572 | | * @param [in] priv_key Private key value in a BN. |
4573 | | * @return 1 on success |
4574 | | * @return 0 on failure. |
4575 | | */ |
4576 | | int wolfSSL_EC_KEY_set_private_key(WOLFSSL_EC_KEY *key, |
4577 | | const WOLFSSL_BIGNUM *priv_key) |
4578 | 342 | { |
4579 | 342 | int ret = 1; |
4580 | | |
4581 | 342 | WOLFSSL_ENTER("wolfSSL_EC_KEY_set_private_key"); |
4582 | | |
4583 | | /* Validate parameters. */ |
4584 | 342 | if ((key == NULL) || (priv_key == NULL)) { |
4585 | 0 | WOLFSSL_MSG("Bad arguments"); |
4586 | 0 | ret = 0; |
4587 | 0 | } |
4588 | | |
4589 | | /* Check for obvious invalid values. */ |
4590 | 342 | if (wolfSSL_BN_is_negative(priv_key) || wolfSSL_BN_is_zero(priv_key) || |
4591 | 337 | wolfSSL_BN_is_one(priv_key)) { |
4592 | 5 | WOLFSSL_MSG("Invalid private key value"); |
4593 | 5 | ret = 0; |
4594 | 5 | } |
4595 | | |
4596 | 342 | if (ret == 1) { |
4597 | | /* Free key if previously set. */ |
4598 | 337 | if (key->priv_key != NULL) { |
4599 | 337 | wolfSSL_BN_free(key->priv_key); |
4600 | 337 | } |
4601 | | |
4602 | | /* Duplicate the BN passed in. */ |
4603 | 337 | key->priv_key = wolfSSL_BN_dup(priv_key); |
4604 | 337 | if (key->priv_key == NULL) { |
4605 | 0 | WOLFSSL_MSG("key ecc priv key NULL"); |
4606 | 0 | ret = 0; |
4607 | 0 | } |
4608 | 337 | } |
4609 | | /* Set the external values into internal EC key. */ |
4610 | 342 | if ((ret == 1) && (SetECKeyInternal(key) != 1)) { |
4611 | 0 | WOLFSSL_MSG("SetECKeyInternal failed"); |
4612 | | /* Dispose of new private key on error. */ |
4613 | 0 | wolfSSL_BN_free(key->priv_key); |
4614 | 0 | key->priv_key = NULL; |
4615 | 0 | ret = 0; |
4616 | 0 | } |
4617 | | |
4618 | 342 | return ret; |
4619 | 342 | } |
4620 | | |
4621 | | /* Get the public key EC point object that is in EC key. |
4622 | | * |
4623 | | * @param [in] key EC key. |
4624 | | * @return EC point object that is the public key on success. |
4625 | | * @return NULL when key is NULL. |
4626 | | */ |
4627 | | WOLFSSL_EC_POINT* wolfSSL_EC_KEY_get0_public_key(const WOLFSSL_EC_KEY *key) |
4628 | 0 | { |
4629 | 0 | WOLFSSL_EC_POINT* pub_key = NULL; |
4630 | |
|
4631 | 0 | WOLFSSL_ENTER("wolfSSL_EC_KEY_get0_public_key"); |
4632 | |
|
4633 | 0 | if (key != NULL) { |
4634 | 0 | pub_key = key->pub_key; |
4635 | 0 | } |
4636 | |
|
4637 | 0 | return pub_key; |
4638 | 0 | } |
4639 | | |
4640 | | /* |
4641 | | * Return code compliant with OpenSSL. |
4642 | | * |
4643 | | * @param [in, out] key EC key. |
4644 | | * @param [in] pub Public key as an EC point. |
4645 | | * @return 1 on success |
4646 | | * @return 0 on failure. |
4647 | | */ |
4648 | | int wolfSSL_EC_KEY_set_public_key(WOLFSSL_EC_KEY *key, |
4649 | | const WOLFSSL_EC_POINT *pub) |
4650 | 392 | { |
4651 | 392 | int ret = 1; |
4652 | 392 | ecc_point *pub_p = NULL; |
4653 | 392 | ecc_point *key_p = NULL; |
4654 | | |
4655 | 392 | WOLFSSL_ENTER("wolfSSL_EC_KEY_set_public_key"); |
4656 | | |
4657 | | /* Validate parameters. */ |
4658 | 392 | if ((key == NULL) || (key->internal == NULL) || (pub == NULL) || |
4659 | 392 | (pub->internal == NULL)) { |
4660 | 0 | WOLFSSL_MSG("wolfSSL_EC_KEY_set_public_key Bad arguments"); |
4661 | 0 | ret = 0; |
4662 | 0 | } |
4663 | | |
4664 | | /* Ensure the internal EC key is set. */ |
4665 | 392 | if ((ret == 1) && (key->inSet == 0) && (SetECKeyInternal(key) != 1)) { |
4666 | 0 | WOLFSSL_MSG("SetECKeyInternal failed"); |
4667 | 0 | ret = 0; |
4668 | 0 | } |
4669 | | |
4670 | | /* Ensure the internal EC point of pub is setup. */ |
4671 | 392 | if ((ret == 1) && (ec_point_setup(pub) != 1)) { |
4672 | 0 | ret = 0; |
4673 | 0 | } |
4674 | | |
4675 | 392 | if (ret == 1) { |
4676 | | /* Get the internal point of pub and the public key in key. */ |
4677 | 392 | pub_p = (ecc_point*)pub->internal; |
4678 | 392 | key_p = (ecc_point*)key->pub_key->internal; |
4679 | | |
4680 | | /* Create new point if required. */ |
4681 | 392 | if (key_p == NULL) { |
4682 | 0 | key_p = wc_ecc_new_point(); |
4683 | 0 | key->pub_key->internal = (void*)key_p; |
4684 | 0 | } |
4685 | | /* Check point available. */ |
4686 | 392 | if (key_p == NULL) { |
4687 | 0 | WOLFSSL_MSG("key ecc point NULL"); |
4688 | 0 | ret = 0; |
4689 | 0 | } |
4690 | 392 | } |
4691 | | |
4692 | | /* Copy the internal pub point into internal key point. */ |
4693 | 392 | if ((ret == 1) && (wc_ecc_copy_point(pub_p, key_p) != MP_OKAY)) { |
4694 | 0 | WOLFSSL_MSG("ecc_copy_point failure"); |
4695 | 0 | ret = 0; |
4696 | 0 | } |
4697 | | |
4698 | | /* Copy the internal point data into external. */ |
4699 | 392 | if ((ret == 1) && (ec_point_external_set(key->pub_key) != 1)) { |
4700 | 0 | WOLFSSL_MSG("SetECKeyInternal failed"); |
4701 | 0 | ret = 0; |
4702 | 0 | } |
4703 | | |
4704 | | /* Copy the internal key into external. */ |
4705 | 392 | if ((ret == 1) && (SetECKeyInternal(key) != 1)) { |
4706 | 0 | WOLFSSL_MSG("SetECKeyInternal failed"); |
4707 | 0 | ret = 0; |
4708 | 0 | } |
4709 | | |
4710 | 392 | if (ret == 1) { |
4711 | | /* Dump out the point and the key's public key for debug. */ |
4712 | 392 | wolfSSL_EC_POINT_dump("pub", pub); |
4713 | 392 | wolfSSL_EC_POINT_dump("key->pub_key", key->pub_key); |
4714 | 392 | } |
4715 | | |
4716 | 392 | return ret; |
4717 | 392 | } |
4718 | | |
4719 | | #ifndef NO_WOLFSSL_STUB |
4720 | | /* Set the ASN.1 encoding flag against the EC key. |
4721 | | * |
4722 | | * No implementation as only named curves supported for encoding. |
4723 | | * |
4724 | | * @param [in, out] key EC key. |
4725 | | * @param [in] flag ASN.1 flag to set. Valid values: |
4726 | | * OPENSSL_EC_EXPLICIT_CURVE, OPENSSL_EC_NAMED_CURVE |
4727 | | */ |
4728 | | void wolfSSL_EC_KEY_set_asn1_flag(WOLFSSL_EC_KEY *key, int asn1_flag) |
4729 | 0 | { |
4730 | 0 | (void)key; |
4731 | 0 | (void)asn1_flag; |
4732 | |
|
4733 | 0 | WOLFSSL_ENTER("wolfSSL_EC_KEY_set_asn1_flag"); |
4734 | 0 | WOLFSSL_STUB("EC_KEY_set_asn1_flag"); |
4735 | 0 | } |
4736 | | #endif |
4737 | | |
4738 | | /* |
4739 | | * EC key generate key APIs |
4740 | | */ |
4741 | | |
4742 | | /* Generate an EC key. |
4743 | | * |
4744 | | * Uses the internal curve index set in the EC key or the default. |
4745 | | * |
4746 | | * @param [in, out] key EC key. |
4747 | | * @return 1 on success |
4748 | | * @return 0 on failure. |
4749 | | */ |
4750 | | int wolfSSL_EC_KEY_generate_key(WOLFSSL_EC_KEY *key) |
4751 | 0 | { |
4752 | 0 | int res = 1; |
4753 | 0 | int initTmpRng = 0; |
4754 | 0 | WC_RNG* rng = NULL; |
4755 | 0 | WC_DECLARE_VAR(tmpRng, WC_RNG, 1, 0); |
4756 | |
|
4757 | 0 | WOLFSSL_ENTER("wolfSSL_EC_KEY_generate_key"); |
4758 | | |
4759 | | /* Validate parameters. */ |
4760 | 0 | if ((key == NULL) || (key->internal == NULL) || (key->group == NULL)) { |
4761 | 0 | WOLFSSL_MSG("wolfSSL_EC_KEY_generate_key Bad arguments"); |
4762 | 0 | res = 0; |
4763 | 0 | } |
4764 | 0 | if (res == 1) { |
4765 | | /* Check if we know which internal curve index to use. */ |
4766 | 0 | if (key->group->curve_idx < 0) { |
4767 | | /* Generate key using the default curve. */ |
4768 | | #if FIPS_VERSION3_GE(6,0,0) |
4769 | | key->group->curve_idx = ECC_SECP256R1; /* FIPS default to 256 */ |
4770 | | #else |
4771 | 0 | key->group->curve_idx = ECC_CURVE_DEF; |
4772 | 0 | #endif |
4773 | 0 | } |
4774 | | |
4775 | | /* Create a random number generator. */ |
4776 | 0 | rng = wolfssl_make_rng(tmpRng, &initTmpRng); |
4777 | 0 | if (rng == NULL) { |
4778 | 0 | WOLFSSL_MSG("wolfSSL_EC_KEY_generate_key failed to make RNG"); |
4779 | 0 | res = 0; |
4780 | 0 | } |
4781 | 0 | } |
4782 | 0 | if (res == 1) { |
4783 | | /* NIDToEccEnum returns -1 for invalid NID so if key->group->curve_nid |
4784 | | * is 0 then pass ECC_CURVE_DEF as arg */ |
4785 | 0 | int eccEnum = key->group->curve_nid ? |
4786 | | #if FIPS_VERSION3_GE(6,0,0) |
4787 | | NIDToEccEnum(key->group->curve_nid) : ECC_SECP256R1; |
4788 | | #else |
4789 | 0 | NIDToEccEnum(key->group->curve_nid) : ECC_CURVE_DEF; |
4790 | 0 | #endif |
4791 | | /* Get the internal EC key. */ |
4792 | 0 | ecc_key* ecKey = (ecc_key*)key->internal; |
4793 | | /* Make the key using internal API. */ |
4794 | 0 | int ret = 0; |
4795 | |
|
4796 | | #if FIPS_VERSION3_GE(6,0,0) |
4797 | | /* In the case of FIPS only allow key generation with approved curves */ |
4798 | | if (eccEnum != ECC_SECP256R1 && eccEnum != ECC_SECP224R1 && |
4799 | | eccEnum != ECC_SECP384R1 && eccEnum != ECC_SECP521R1) { |
4800 | | WOLFSSL_MSG("Unsupported curve selected in FIPS mode"); |
4801 | | res = 0; |
4802 | | } |
4803 | | if (res == 1) { |
4804 | | #endif |
4805 | 0 | ret = wc_ecc_make_key_ex(rng, 0, ecKey, eccEnum); |
4806 | | #if FIPS_VERSION3_GE(6,0,0) |
4807 | | } |
4808 | | #endif |
4809 | |
|
4810 | | #if defined(WOLFSSL_ASYNC_CRYPT) |
4811 | | /* Wait on asynchronouse operation. */ |
4812 | | ret = wc_AsyncWait(ret, &ecKey->asyncDev, WC_ASYNC_FLAG_NONE); |
4813 | | #endif |
4814 | 0 | if (ret != 0) { |
4815 | 0 | WOLFSSL_MSG("wolfSSL_EC_KEY_generate_key wc_ecc_make_key failed"); |
4816 | 0 | res = 0; |
4817 | 0 | } |
4818 | 0 | } |
4819 | | |
4820 | | /* Dispose of local random number generator if initialized. */ |
4821 | 0 | if (initTmpRng) { |
4822 | 0 | wc_FreeRng(rng); |
4823 | 0 | WC_FREE_VAR_EX(rng, NULL, DYNAMIC_TYPE_RNG); |
4824 | 0 | } |
4825 | | |
4826 | | /* Set the external key from new internal key values. */ |
4827 | 0 | if ((res == 1) && (SetECKeyExternal(key) != 1)) { |
4828 | 0 | WOLFSSL_MSG("wolfSSL_EC_KEY_generate_key SetECKeyExternal failed"); |
4829 | 0 | res = 0; |
4830 | 0 | } |
4831 | |
|
4832 | 0 | return res; |
4833 | 0 | } |
4834 | | |
4835 | | /* |
4836 | | * EC key check key APIs |
4837 | | */ |
4838 | | |
4839 | | /* Check that the EC key is valid. |
4840 | | * |
4841 | | * @param [in] key EC key. |
4842 | | * @return 1 on valid. |
4843 | | * @return 0 on invalid or error. |
4844 | | */ |
4845 | | int wolfSSL_EC_KEY_check_key(const WOLFSSL_EC_KEY *key) |
4846 | 0 | { |
4847 | 0 | int ret = 1; |
4848 | |
|
4849 | 0 | WOLFSSL_ENTER("wolfSSL_EC_KEY_check_key"); |
4850 | | |
4851 | | /* Validate parameter. */ |
4852 | 0 | if ((key == NULL) || (key->internal == NULL)) { |
4853 | 0 | WOLFSSL_MSG("Bad parameter"); |
4854 | 0 | ret = 0; |
4855 | 0 | } |
4856 | | |
4857 | | /* Set the external EC key values into internal if not already. */ |
4858 | 0 | if ((ret == 1) && (key->inSet == 0) && (SetECKeyInternal( |
4859 | 0 | (WOLFSSL_EC_KEY*)key) != 1)) { |
4860 | 0 | WOLFSSL_MSG("SetECKeyInternal failed"); |
4861 | 0 | ret = 0; |
4862 | 0 | } |
4863 | |
|
4864 | 0 | if (ret == 1) { |
4865 | | /* Have internal EC implementation check key. */ |
4866 | 0 | ret = wc_ecc_check_key((ecc_key*)key->internal) == 0; |
4867 | 0 | } |
4868 | |
|
4869 | 0 | return ret; |
4870 | 0 | } |
4871 | | |
4872 | | /* End EC_KEY */ |
4873 | | |
4874 | | #if !defined(HAVE_FIPS) || FIPS_VERSION_GT(2,0) |
4875 | | /* Get the supported, built-in EC curves |
4876 | | * |
4877 | | * @param [in, out] curves Pre-allocated list to put supported curves into. |
4878 | | * @param [in] len Maximum number of items to place in list. |
4879 | | * @return Number of built-in EC curves when curves is NULL or len is 0. |
4880 | | * @return Number of items placed in list otherwise. |
4881 | | */ |
4882 | | size_t wolfSSL_EC_get_builtin_curves(WOLFSSL_EC_BUILTIN_CURVE *curves, |
4883 | | size_t len) |
4884 | 0 | { |
4885 | 0 | size_t i; |
4886 | 0 | size_t cnt; |
4887 | | #ifdef HAVE_SELFTEST |
4888 | | /* Defined in ecc.h when available. */ |
4889 | | size_t ecc_sets_count; |
4890 | | |
4891 | | /* Count the pre-defined curves since global not available. */ |
4892 | | for (i = 0; ecc_sets[i].size != 0 && ecc_sets[i].name != NULL; i++) { |
4893 | | /* Do nothing. */ |
4894 | | } |
4895 | | ecc_sets_count = i; |
4896 | | #endif |
4897 | | |
4898 | | /* Assume we are going to return total count. */ |
4899 | 0 | cnt = ecc_sets_count; |
4900 | | /* Check we have a list that can hold data. */ |
4901 | 0 | if ((curves != NULL) && (len != 0)) { |
4902 | | /* Limit count to length of list. */ |
4903 | 0 | if (cnt > len) { |
4904 | 0 | cnt = len; |
4905 | 0 | } |
4906 | | |
4907 | | /* Put in built-in EC curve nid and short name. */ |
4908 | 0 | for (i = 0; i < cnt; i++) { |
4909 | 0 | curves[i].nid = EccEnumToNID(ecc_sets[i].id); |
4910 | 0 | curves[i].comment = wolfSSL_OBJ_nid2sn(curves[i].nid); |
4911 | 0 | } |
4912 | 0 | } |
4913 | |
|
4914 | 0 | return cnt; |
4915 | 0 | } |
4916 | | #endif /* !HAVE_FIPS || FIPS_VERSION_GT(2,0) */ |
4917 | | |
4918 | | /* Start ECDSA_SIG */ |
4919 | | |
4920 | | /* Allocate a new ECDSA signature object. |
4921 | | * |
4922 | | * @return New, allocated ECDSA signature object on success. |
4923 | | * @return NULL on error. |
4924 | | */ |
4925 | | WOLFSSL_ECDSA_SIG *wolfSSL_ECDSA_SIG_new(void) |
4926 | 622 | { |
4927 | 622 | int err = 0; |
4928 | 622 | WOLFSSL_ECDSA_SIG *sig; |
4929 | | |
4930 | 622 | WOLFSSL_ENTER("wolfSSL_ECDSA_SIG_new"); |
4931 | | |
4932 | | /* Allocate memory for ECDSA signature object. */ |
4933 | 622 | sig = (WOLFSSL_ECDSA_SIG*)XMALLOC(sizeof(WOLFSSL_ECDSA_SIG), NULL, |
4934 | 622 | DYNAMIC_TYPE_ECC); |
4935 | 622 | if (sig == NULL) { |
4936 | 0 | WOLFSSL_MSG("wolfSSL_ECDSA_SIG_new malloc ECDSA signature failure"); |
4937 | 0 | return NULL; |
4938 | 0 | } |
4939 | | |
4940 | | /* Set s to NULL in case of error. */ |
4941 | 622 | sig->s = NULL; |
4942 | | /* Allocate BN into r. */ |
4943 | 622 | sig->r = wolfSSL_BN_new(); |
4944 | 622 | if (sig->r == NULL) { |
4945 | 0 | WOLFSSL_MSG("wolfSSL_ECDSA_SIG_new malloc ECDSA r failure"); |
4946 | 0 | err = 1; |
4947 | 0 | } |
4948 | 622 | if (!err) { |
4949 | | /* Allocate BN into s. */ |
4950 | 622 | sig->s = wolfSSL_BN_new(); |
4951 | 622 | if (sig->s == NULL) { |
4952 | 0 | WOLFSSL_MSG("wolfSSL_ECDSA_SIG_new malloc ECDSA s failure"); |
4953 | 0 | err = 1; |
4954 | 0 | } |
4955 | 622 | } |
4956 | | |
4957 | 622 | if (err) { |
4958 | | /* Dispose of allocated memory. */ |
4959 | 0 | wolfSSL_ECDSA_SIG_free(sig); |
4960 | 0 | sig = NULL; |
4961 | 0 | } |
4962 | 622 | return sig; |
4963 | 622 | } |
4964 | | |
4965 | | /* Dispose of ECDSA signature object. |
4966 | | * |
4967 | | * Cannot use object after this call. |
4968 | | * |
4969 | | * @param [in] sig ECDSA signature object to free. |
4970 | | */ |
4971 | | void wolfSSL_ECDSA_SIG_free(WOLFSSL_ECDSA_SIG *sig) |
4972 | 622 | { |
4973 | 622 | WOLFSSL_ENTER("wolfSSL_ECDSA_SIG_free"); |
4974 | | |
4975 | 622 | if (sig != NULL) { |
4976 | | /* Dispose of BNs allocated for r and s. */ |
4977 | 622 | wolfSSL_BN_free(sig->r); |
4978 | 622 | wolfSSL_BN_free(sig->s); |
4979 | | |
4980 | | /* Dispose of memory associated with ECDSA signature object. */ |
4981 | 622 | XFREE(sig, NULL, DYNAMIC_TYPE_ECC); |
4982 | 622 | } |
4983 | 622 | } |
4984 | | |
4985 | | /* Create an ECDSA signature from the DER encoding. |
4986 | | * |
4987 | | * @param [in, out] sig Reference to ECDSA signature object. May be NULL. |
4988 | | * @param [in, out] pp On in, reference to buffer containing DER encoding. |
4989 | | * On out, reference to buffer after signature data. |
4990 | | * @param [in] len Length of the data in the buffer. May be more than |
4991 | | * the length of the signature. |
4992 | | * @return ECDSA signature object on success. |
4993 | | * @return NULL on error. |
4994 | | */ |
4995 | | WOLFSSL_ECDSA_SIG* wolfSSL_d2i_ECDSA_SIG(WOLFSSL_ECDSA_SIG** sig, |
4996 | | const unsigned char** pp, long len) |
4997 | 227 | { |
4998 | 227 | int err = 0; |
4999 | | /* ECDSA signature object to return. */ |
5000 | 227 | WOLFSSL_ECDSA_SIG *s = NULL; |
5001 | | |
5002 | | /* Validate parameter. */ |
5003 | 227 | if (pp == NULL || *pp == NULL) { |
5004 | 0 | err = 1; |
5005 | 0 | } |
5006 | 227 | if ((!err) && (len <= 0)) { |
5007 | 0 | err = 1; |
5008 | 0 | } |
5009 | 227 | if (!err) { |
5010 | 227 | if (sig != NULL) { |
5011 | | /* Use the ECDSA signature object passed in. */ |
5012 | 0 | s = *sig; |
5013 | 0 | } |
5014 | 227 | if (s == NULL) { |
5015 | | /* No ECDSA signature object passed in - create a new one. */ |
5016 | 227 | s = wolfSSL_ECDSA_SIG_new(); |
5017 | 227 | if (s == NULL) { |
5018 | 0 | err = 1; |
5019 | 0 | } |
5020 | 227 | } |
5021 | 227 | } |
5022 | 227 | if (!err) { |
5023 | | /* DecodeECC_DSA_Sig calls mp_init, so free these. */ |
5024 | 227 | mp_free((mp_int*)s->r->internal); |
5025 | 227 | mp_free((mp_int*)s->s->internal); |
5026 | | |
5027 | | /* Decode the signature into internal r and s fields. */ |
5028 | 227 | if (DecodeECC_DSA_Sig(*pp, (word32)len, (mp_int*)s->r->internal, |
5029 | 227 | (mp_int*)s->s->internal) != MP_OKAY) { |
5030 | 0 | err = 1; |
5031 | 0 | } |
5032 | 227 | } |
5033 | | |
5034 | 227 | if (!err) { |
5035 | | /* Move pointer passed signature data successfully decoded. */ |
5036 | 227 | *pp += wolfssl_der_length(*pp, (int)len); |
5037 | 227 | if (sig != NULL) { |
5038 | | /* Update reference to ECDSA signature object. */ |
5039 | 0 | *sig = s; |
5040 | 0 | } |
5041 | 227 | } |
5042 | | |
5043 | | /* Dispose of newly allocated object on error. */ |
5044 | 227 | if (err) { |
5045 | 0 | if ((s != NULL) && ((sig == NULL) || (*sig != s))) { |
5046 | 0 | wolfSSL_ECDSA_SIG_free(s); |
5047 | 0 | } |
5048 | | /* Return NULL for object on error. */ |
5049 | 0 | s = NULL; |
5050 | 0 | } |
5051 | 227 | return s; |
5052 | 227 | } |
5053 | | |
5054 | | /* Encode the ECDSA signature as DER. |
5055 | | * |
5056 | | * @param [in] sig ECDSA signature object. |
5057 | | * @param [in, out] pp On in, reference to buffer in which to place encoding. |
5058 | | * On out, reference to buffer after encoding. |
5059 | | * May be NULL or point to NULL in which case no encoding |
5060 | | * is done. |
5061 | | * @return Length of encoding on success. |
5062 | | * @return 0 on error. |
5063 | | */ |
5064 | | int wolfSSL_i2d_ECDSA_SIG(const WOLFSSL_ECDSA_SIG *sig, unsigned char **pp) |
5065 | 0 | { |
5066 | 0 | word32 len = 0; |
5067 | 0 | int update_p = 1; |
5068 | | |
5069 | | /* Validate parameter. */ |
5070 | 0 | if (sig != NULL) { |
5071 | | /* ASN.1: SEQ + INT + INT |
5072 | | * ASN.1 Integer must be a positive value - prepend zero if number has |
5073 | | * top bit set. |
5074 | | */ |
5075 | | /* Get total length of r including any prepended zero. */ |
5076 | 0 | word32 rLen = (word32)(mp_leading_bit((mp_int*)sig->r->internal) + |
5077 | 0 | mp_unsigned_bin_size((mp_int*)sig->r->internal)); |
5078 | | /* Get total length of s including any prepended zero. */ |
5079 | 0 | word32 sLen = (word32)(mp_leading_bit((mp_int*)sig->s->internal) + |
5080 | 0 | mp_unsigned_bin_size((mp_int*)sig->s->internal)); |
5081 | | /* Calculate length of data in sequence. */ |
5082 | 0 | len = (word32)1 + ASN_LEN_SIZE(rLen) + rLen + |
5083 | 0 | (word32)1 + ASN_LEN_SIZE(sLen) + sLen; |
5084 | | /* Add in the length of the SEQUENCE. */ |
5085 | 0 | len += (word32)1 + ASN_LEN_SIZE(len); |
5086 | |
|
5087 | | #ifdef WOLFSSL_I2D_ECDSA_SIG_ALLOC |
5088 | | if ((pp != NULL) && (*pp == NULL)) { |
5089 | | *pp = (unsigned char *)XMALLOC(len, NULL, DYNAMIC_TYPE_OPENSSL); |
5090 | | if (*pp == NULL) { |
5091 | | WOLFSSL_MSG("malloc error"); |
5092 | | return 0; |
5093 | | } |
5094 | | update_p = 0; |
5095 | | } |
5096 | | #endif |
5097 | | |
5098 | | /* Encode only if there is a buffer to encode into. */ |
5099 | 0 | if ((pp != NULL) && (*pp != NULL)) { |
5100 | | /* Encode using the internal representations of r and s. */ |
5101 | 0 | if (StoreECC_DSA_Sig(*pp, &len, (mp_int*)sig->r->internal, |
5102 | 0 | (mp_int*)sig->s->internal) != MP_OKAY) { |
5103 | | /* No bytes encoded. */ |
5104 | 0 | len = 0; |
5105 | 0 | } |
5106 | 0 | else if (update_p) { |
5107 | | /* Update pointer to after encoding. */ |
5108 | 0 | *pp += len; |
5109 | 0 | } |
5110 | 0 | } |
5111 | 0 | } |
5112 | |
|
5113 | 0 | return (int)len; |
5114 | 0 | } |
5115 | | |
5116 | | /* Get the pointer to the fields of the ECDSA signature. |
5117 | | * |
5118 | | * r and s untouched when sig is NULL. |
5119 | | * |
5120 | | * @param [in] sig ECDSA signature object. |
5121 | | * @param [out] r R field of ECDSA signature as a BN. May be NULL. |
5122 | | * @param [out] s S field of ECDSA signature as a BN. May be NULL. |
5123 | | */ |
5124 | | void wolfSSL_ECDSA_SIG_get0(const WOLFSSL_ECDSA_SIG* sig, |
5125 | | const WOLFSSL_BIGNUM** r, const WOLFSSL_BIGNUM** s) |
5126 | 227 | { |
5127 | | /* Validate parameter. */ |
5128 | 227 | if (sig != NULL) { |
5129 | | /* Return the r BN when pointer to return through. */ |
5130 | 227 | if (r != NULL) { |
5131 | 227 | *r = sig->r; |
5132 | 227 | } |
5133 | | /* Return the s BN when pointer to return through. */ |
5134 | 227 | if (s != NULL) { |
5135 | 227 | *s = sig->s; |
5136 | 227 | } |
5137 | 227 | } |
5138 | 227 | } |
5139 | | |
5140 | | /* Set the pointers to the fields of the ECDSA signature. |
5141 | | * |
5142 | | * @param [in, out] sig ECDSA signature object to update. |
5143 | | * @param [in] r R field of ECDSA signature as a BN. |
5144 | | * @param [in] s S field of ECDSA signature as a BN. |
5145 | | * @return 1 on success. |
5146 | | * @return 0 on error. |
5147 | | */ |
5148 | | int wolfSSL_ECDSA_SIG_set0(WOLFSSL_ECDSA_SIG* sig, WOLFSSL_BIGNUM* r, |
5149 | | WOLFSSL_BIGNUM* s) |
5150 | 395 | { |
5151 | 395 | int ret = 1; |
5152 | | |
5153 | | /* Validate parameters. */ |
5154 | 395 | if ((sig == NULL) || (r == NULL) || (s == NULL)) { |
5155 | 0 | ret = 0; |
5156 | 0 | } |
5157 | | |
5158 | 395 | if (ret == 1) { |
5159 | | /* Dispose of old BN objects. */ |
5160 | 395 | wolfSSL_BN_free(sig->r); |
5161 | 395 | wolfSSL_BN_free(sig->s); |
5162 | | |
5163 | | /* Assign new BN objects. */ |
5164 | 395 | sig->r = r; |
5165 | 395 | sig->s = s; |
5166 | 395 | } |
5167 | | |
5168 | 395 | return ret; |
5169 | 395 | } |
5170 | | |
5171 | | /* End ECDSA_SIG */ |
5172 | | |
5173 | | /* Start ECDSA */ |
5174 | | |
5175 | | /* Calculate maximum size of the DER encoded ECDSA signature for the curve. |
5176 | | * |
5177 | | * @param [in] key EC key. |
5178 | | * @return Size of DER encoded signature on success. |
5179 | | * @return 0 on error. |
5180 | | */ |
5181 | | int wolfSSL_ECDSA_size(const WOLFSSL_EC_KEY *key) |
5182 | 0 | { |
5183 | 0 | int err = 0; |
5184 | 0 | int len = 0; |
5185 | 0 | const WOLFSSL_EC_GROUP *group = NULL; |
5186 | 0 | int bits = 0; |
5187 | | |
5188 | | /* Validate parameter. */ |
5189 | 0 | if (key == NULL) { |
5190 | 0 | err = 1; |
5191 | 0 | } |
5192 | | |
5193 | | /* Get group from key to get order bits. */ |
5194 | 0 | if ((!err) && ((group = wolfSSL_EC_KEY_get0_group(key)) == NULL)) { |
5195 | 0 | err = 1; |
5196 | 0 | } |
5197 | | /* Get order bits of group. */ |
5198 | 0 | if ((!err) && ((bits = wolfSSL_EC_GROUP_order_bits(group)) == 0)) { |
5199 | | /* Group is not set. */ |
5200 | 0 | err = 1; |
5201 | 0 | } |
5202 | |
|
5203 | 0 | if (!err) { |
5204 | | /* r and s are mod order. */ |
5205 | 0 | int bytes = (bits + 7) / 8; /* Bytes needed to hold bits. */ |
5206 | 0 | len = SIG_HEADER_SZ + /* 2*ASN_TAG + 2*LEN(ENUM) */ |
5207 | 0 | ECC_MAX_PAD_SZ + /* possible leading zeroes in r and s */ |
5208 | 0 | bytes + bytes; /* max r and s in bytes */ |
5209 | 0 | } |
5210 | |
|
5211 | 0 | return len; |
5212 | 0 | } |
5213 | | |
5214 | | /* Create ECDSA signature by signing digest with key. |
5215 | | * |
5216 | | * @param [in] dgst Digest to sign. |
5217 | | * @param [in] dLen Length of digest in bytes. |
5218 | | * @param [in] key EC key to sign with. |
5219 | | * @return ECDSA signature object on success. |
5220 | | * @return NULL on error. |
5221 | | */ |
5222 | | WOLFSSL_ECDSA_SIG *wolfSSL_ECDSA_do_sign(const unsigned char *dgst, int dLen, |
5223 | | WOLFSSL_EC_KEY *key) |
5224 | 283 | { |
5225 | 283 | int err = 0; |
5226 | 283 | WOLFSSL_ECDSA_SIG *sig = NULL; |
5227 | 283 | WC_DECLARE_VAR(out, byte, ECC_BUFSIZE, 0); |
5228 | 283 | unsigned int outLen = ECC_BUFSIZE; |
5229 | | |
5230 | 283 | WOLFSSL_ENTER("wolfSSL_ECDSA_do_sign"); |
5231 | | |
5232 | | /* Validate parameters. */ |
5233 | 283 | if ((dgst == NULL) || (key == NULL) || (key->internal == NULL)) { |
5234 | 10 | WOLFSSL_MSG("wolfSSL_ECDSA_do_sign Bad arguments"); |
5235 | 10 | err = 1; |
5236 | 10 | } |
5237 | | |
5238 | | /* Ensure internal EC key is set from external. */ |
5239 | 283 | if ((!err) && (key->inSet == 0)) { |
5240 | 0 | WOLFSSL_MSG("wolfSSL_ECDSA_do_sign No EC key internal set, do it"); |
5241 | |
|
5242 | 0 | if (SetECKeyInternal(key) != 1) { |
5243 | 0 | WOLFSSL_MSG("wolfSSL_ECDSA_do_sign SetECKeyInternal failed"); |
5244 | 0 | err = 1; |
5245 | 0 | } |
5246 | 0 | } |
5247 | | |
5248 | 283 | #ifdef WOLFSSL_SMALL_STACK |
5249 | 283 | if (!err) { |
5250 | | /* Allocate buffer to hold encoded signature. */ |
5251 | 273 | out = (byte*)XMALLOC(outLen, NULL, DYNAMIC_TYPE_TMP_BUFFER); |
5252 | 273 | if (out == NULL) { |
5253 | 0 | err = 1; |
5254 | 0 | } |
5255 | 273 | } |
5256 | 283 | #endif |
5257 | | |
5258 | | /* Sign the digest with the key to create encoded ECDSA signature. */ |
5259 | 283 | if ((!err) && (wolfSSL_ECDSA_sign(0, dgst, dLen, out, &outLen, key) != 1)) { |
5260 | 46 | err = 1; |
5261 | 46 | } |
5262 | | |
5263 | 283 | if (!err) { |
5264 | 227 | const byte* p = out; |
5265 | | /* Decode the ECDSA signature into a new object. */ |
5266 | 227 | sig = wolfSSL_d2i_ECDSA_SIG(NULL, &p, outLen); |
5267 | 227 | } |
5268 | | |
5269 | 283 | WC_FREE_VAR_EX(out, NULL, DYNAMIC_TYPE_TMP_BUFFER); |
5270 | | |
5271 | 283 | return sig; |
5272 | 283 | } |
5273 | | |
5274 | | /* Verify ECDSA signature in the object using digest and key. |
5275 | | * |
5276 | | * Return code compliant with OpenSSL. |
5277 | | * |
5278 | | * @param [in] dgst Digest to verify. |
5279 | | * @param [in] dLen Length of the digest in bytes. |
5280 | | * @param [in] sig ECDSA signature object. |
5281 | | * @param [in] key EC key containing public key. |
5282 | | * @return 1 when signature is valid. |
5283 | | * @return 0 when signature is invalid. |
5284 | | * @return -1 on error. |
5285 | | */ |
5286 | | int wolfSSL_ECDSA_do_verify(const unsigned char *dgst, int dLen, |
5287 | | const WOLFSSL_ECDSA_SIG *sig, WOLFSSL_EC_KEY *key) |
5288 | 356 | { |
5289 | 356 | int ret = 1; |
5290 | 356 | int verified = 0; |
5291 | | #ifdef WOLF_CRYPTO_CB_ONLY_ECC |
5292 | | byte signature[ECC_MAX_SIG_SIZE]; |
5293 | | int signatureLen; |
5294 | | byte* p = signature; |
5295 | | #endif |
5296 | | |
5297 | 356 | WOLFSSL_ENTER("wolfSSL_ECDSA_do_verify"); |
5298 | | |
5299 | | /* Validate parameters. */ |
5300 | 356 | if ((dgst == NULL) || (sig == NULL) || (key == NULL) || |
5301 | 341 | (key->internal == NULL)) { |
5302 | 15 | WOLFSSL_MSG("wolfSSL_ECDSA_do_verify Bad arguments"); |
5303 | 15 | ret = WOLFSSL_FATAL_ERROR; |
5304 | 15 | } |
5305 | | |
5306 | | /* Check hash length */ |
5307 | 356 | if ((ret == 1) && |
5308 | 341 | ((dLen > WC_MAX_DIGEST_SIZE) || |
5309 | 329 | (dLen < WC_MIN_DIGEST_SIZE_FOR_VERIFY))) { |
5310 | 18 | WOLFSSL_MSG("wolfSSL_ECDSA_do_verify Bad digest size"); |
5311 | 18 | ret = WOLFSSL_FATAL_ERROR; |
5312 | 18 | } |
5313 | | |
5314 | | /* Ensure internal EC key is set from external. */ |
5315 | 356 | if ((ret == 1) && (key->inSet == 0)) { |
5316 | 0 | WOLFSSL_MSG("No EC key internal set, do it"); |
5317 | |
|
5318 | 0 | if (SetECKeyInternal(key) != 1) { |
5319 | 0 | WOLFSSL_MSG("SetECKeyInternal failed"); |
5320 | 0 | ret = WOLFSSL_FATAL_ERROR; |
5321 | 0 | } |
5322 | 0 | } |
5323 | | |
5324 | 356 | if (ret == 1) { |
5325 | 323 | #ifndef WOLF_CRYPTO_CB_ONLY_ECC |
5326 | | /* Verify hash using digest, r and s as MP ints and internal EC key. */ |
5327 | 323 | if (wc_ecc_verify_hash_ex((mp_int*)sig->r->internal, |
5328 | 323 | (mp_int*)sig->s->internal, dgst, (word32)dLen, &verified, |
5329 | 323 | (ecc_key *)key->internal) != MP_OKAY) { |
5330 | 53 | WOLFSSL_MSG("wc_ecc_verify_hash failed"); |
5331 | 53 | ret = WOLFSSL_FATAL_ERROR; |
5332 | 53 | } |
5333 | 270 | else if (verified == 0) { |
5334 | 64 | WOLFSSL_MSG("wc_ecc_verify_hash incorrect signature detected"); |
5335 | 64 | ret = 0; |
5336 | 64 | } |
5337 | | #else |
5338 | | signatureLen = i2d_ECDSA_SIG(sig, &p); |
5339 | | if (signatureLen > 0) { |
5340 | | /* verify hash. expects to call wc_CryptoCb_EccVerify internally */ |
5341 | | ret = wc_ecc_verify_hash(signature, signatureLen, dgst, |
5342 | | (word32)dLen, &verified, (ecc_key*)key->internal); |
5343 | | if (ret != MP_OKAY) { |
5344 | | WOLFSSL_MSG("wc_ecc_verify_hash failed"); |
5345 | | ret = WOLFSSL_FATAL_ERROR; |
5346 | | } |
5347 | | else if (verified == 0) { |
5348 | | WOLFSSL_MSG("wc_ecc_verify_hash incorrect signature detected"); |
5349 | | ret = 0; |
5350 | | } |
5351 | | } |
5352 | | else { |
5353 | | WOLFSSL_MSG("i2d_ECDSA_SIG failed"); |
5354 | | ret = WOLFSSL_FATAL_ERROR; |
5355 | | } |
5356 | | #endif /* WOLF_CRYPTO_CB_ONLY_ECC */ |
5357 | 323 | } |
5358 | | |
5359 | 356 | return ret; |
5360 | 356 | } |
5361 | | |
5362 | | /* Sign the digest with the key to produce a DER encode signature. |
5363 | | * |
5364 | | * @param [in] type Digest algorithm used to create digest. Unused. |
5365 | | * @param [in] digest Digest of the message to sign. |
5366 | | * @param [in] digestSz Size of the digest in bytes. |
5367 | | * @param [out] sig Buffer to hold signature. |
5368 | | * @param [in, out] sigSz On in, size of buffer in bytes. |
5369 | | * On out, size of signatre in bytes. |
5370 | | * @param [in] key EC key containing private key. |
5371 | | * @return 1 on success. |
5372 | | * @return 0 on error. |
5373 | | */ |
5374 | | int wolfSSL_ECDSA_sign(int type, const unsigned char *digest, int digestSz, |
5375 | | unsigned char *sig, unsigned int *sigSz, WOLFSSL_EC_KEY *key) |
5376 | 273 | { |
5377 | 273 | int ret = 1; |
5378 | 273 | WC_RNG* rng = NULL; |
5379 | 273 | WC_DECLARE_VAR(tmpRng, WC_RNG, 1, 0); |
5380 | 273 | int initTmpRng = 0; |
5381 | | |
5382 | 273 | WOLFSSL_ENTER("wolfSSL_ECDSA_sign"); |
5383 | | |
5384 | | /* Digest algorithm not used in DER encoding. */ |
5385 | 273 | (void)type; |
5386 | | |
5387 | | /* Validate parameters. */ |
5388 | 273 | if (key == NULL) { |
5389 | 0 | ret = 0; |
5390 | 0 | } |
5391 | | |
5392 | 273 | if (ret == 1) { |
5393 | | /* Make an RNG - create local or get global. */ |
5394 | 273 | rng = wolfssl_make_rng(tmpRng, &initTmpRng); |
5395 | 273 | if (rng == NULL) { |
5396 | 0 | ret = 0; |
5397 | 0 | } |
5398 | 273 | } |
5399 | | /* Sign the digest with the key using the RNG and put signature into buffer |
5400 | | * update sigSz to be actual length. |
5401 | | */ |
5402 | 273 | if ((ret == 1) && (wc_ecc_sign_hash(digest, (word32)digestSz, sig, sigSz, |
5403 | 273 | rng, (ecc_key*)key->internal) != 0)) { |
5404 | 46 | ret = 0; |
5405 | 46 | } |
5406 | | |
5407 | 273 | if (initTmpRng) { |
5408 | 273 | wc_FreeRng(rng); |
5409 | 273 | WC_FREE_VAR_EX(rng, NULL, DYNAMIC_TYPE_RNG); |
5410 | 273 | } |
5411 | | |
5412 | 273 | return ret; |
5413 | 273 | } |
5414 | | |
5415 | | /* Verify the signature with the digest and key. |
5416 | | * |
5417 | | * @param [in] type Digest algorithm used to create digest. Unused. |
5418 | | * @param [in] digest Digest of the message to verify. |
5419 | | * @param [in] digestSz Size of the digest in bytes. |
5420 | | * @param [in] sig Buffer holding signature. |
5421 | | * @param [in] sigSz Size of signature data in bytes. |
5422 | | * @param [in] key EC key containing public key. |
5423 | | * @return 1 when signature is valid. |
5424 | | * @return 0 when signature is invalid or error. |
5425 | | */ |
5426 | | int wolfSSL_ECDSA_verify(int type, const unsigned char *digest, int digestSz, |
5427 | | const unsigned char *sig, int sigSz, WOLFSSL_EC_KEY *key) |
5428 | 0 | { |
5429 | 0 | int ret = 1; |
5430 | 0 | int verify = 0; |
5431 | |
|
5432 | 0 | WOLFSSL_ENTER("wolfSSL_ECDSA_verify"); |
5433 | | |
5434 | | /* Digest algorithm not used in DER encoding. */ |
5435 | 0 | (void)type; |
5436 | | |
5437 | | /* Validate parameters. */ |
5438 | 0 | if (key == NULL) { |
5439 | 0 | ret = 0; |
5440 | 0 | } |
5441 | | |
5442 | | /* Check hash length */ |
5443 | 0 | if ((ret == 1) && |
5444 | 0 | ((digestSz > WC_MAX_DIGEST_SIZE) || |
5445 | 0 | (digestSz < WC_MIN_DIGEST_SIZE_FOR_VERIFY))) { |
5446 | 0 | WOLFSSL_MSG("wolfSSL_ECDSA_verify Bad digest size"); |
5447 | 0 | ret = 0; |
5448 | 0 | } |
5449 | | |
5450 | | /* Verify signature using digest and key. */ |
5451 | 0 | if ((ret == 1) && (wc_ecc_verify_hash(sig, (word32)sigSz, digest, |
5452 | 0 | (word32)digestSz, &verify, (ecc_key*)key->internal) != 0)) { |
5453 | 0 | ret = 0; |
5454 | 0 | } |
5455 | | /* When no error, verification may still have failed - check now. */ |
5456 | 0 | if ((ret == 1) && (verify != 1)) { |
5457 | 0 | WOLFSSL_MSG("wolfSSL_ECDSA_verify failed"); |
5458 | 0 | ret = 0; |
5459 | 0 | } |
5460 | |
|
5461 | 0 | return ret; |
5462 | 0 | } |
5463 | | |
5464 | | /* End ECDSA */ |
5465 | | |
5466 | | /* Start ECDH */ |
5467 | | |
5468 | | #ifndef WOLF_CRYPTO_CB_ONLY_ECC |
5469 | | /* Compute the shared secret (key) using ECDH. |
5470 | | * |
5471 | | * KDF not supported. |
5472 | | * |
5473 | | * Return code compliant with OpenSSL. |
5474 | | * |
5475 | | * @param [out] out Buffer to hold key. |
5476 | | * @param [in] outLen Length of buffer in bytes. |
5477 | | * @param [in] pubKey Public key as an EC point. |
5478 | | * @param [in] privKey EC key holding a private key. |
5479 | | * @param [in] kdf Key derivation function to apply to secret. |
5480 | | * @return Length of computed key on success |
5481 | | * @return 0 on error. |
5482 | | */ |
5483 | | int wolfSSL_ECDH_compute_key(void *out, size_t outLen, |
5484 | | const WOLFSSL_EC_POINT *pubKey, WOLFSSL_EC_KEY *privKey, |
5485 | | void *(*kdf) (const void *in, size_t inlen, void *out, size_t *outLen)) |
5486 | 0 | { |
5487 | 0 | int err = 0; |
5488 | 0 | word32 len = 0; |
5489 | 0 | ecc_key* key = NULL; |
5490 | 0 | #if defined(ECC_TIMING_RESISTANT) && !defined(HAVE_SELFTEST) && \ |
5491 | 0 | (!defined(HAVE_FIPS) || FIPS_VERSION_GE(5,0)) |
5492 | 0 | WC_RNG* rng = NULL; |
5493 | 0 | WC_DECLARE_VAR(tmpRng, WC_RNG, 1, 0); |
5494 | 0 | int initTmpRng = 0; |
5495 | 0 | int setKeyRng = 0; |
5496 | 0 | #endif |
5497 | | |
5498 | | /* TODO: support using the KDF. */ |
5499 | 0 | (void)kdf; |
5500 | |
|
5501 | 0 | WOLFSSL_ENTER("wolfSSL_ECDH_compute_key"); |
5502 | | |
5503 | | /* Validate parameters. */ |
5504 | 0 | if ((out == NULL) || (pubKey == NULL) || (pubKey->internal == NULL) || |
5505 | 0 | (privKey == NULL) || (privKey->internal == NULL)) { |
5506 | 0 | WOLFSSL_MSG("Bad function arguments"); |
5507 | 0 | err = 1; |
5508 | 0 | } |
5509 | | |
5510 | | /* Ensure internal EC key is set from external. */ |
5511 | 0 | if ((!err) && (privKey->inSet == 0)) { |
5512 | 0 | WOLFSSL_MSG("No EC key internal set, do it"); |
5513 | |
|
5514 | 0 | if (SetECKeyInternal(privKey) != 1) { |
5515 | 0 | WOLFSSL_MSG("SetECKeyInternal failed"); |
5516 | 0 | err = 1; |
5517 | 0 | } |
5518 | 0 | } |
5519 | |
|
5520 | 0 | if (!err) { |
5521 | 0 | int ret; |
5522 | | |
5523 | | /* Get the internal key. */ |
5524 | 0 | key = (ecc_key*)privKey->internal; |
5525 | | /* Set length into variable of type suitable for wolfSSL API. */ |
5526 | 0 | len = (word32)outLen; |
5527 | |
|
5528 | 0 | #if defined(ECC_TIMING_RESISTANT) && !defined(HAVE_SELFTEST) && \ |
5529 | 0 | (!defined(HAVE_FIPS) || FIPS_VERSION_GE(5,0)) |
5530 | | /* An RNG is needed - create local or get global. */ |
5531 | 0 | if (key->rng == NULL) { |
5532 | 0 | rng = wolfssl_make_rng(tmpRng, &initTmpRng); |
5533 | 0 | if (rng == NULL) { |
5534 | 0 | WOLFSSL_MSG("wolfSSL_ECDH_compute_key failed to make RNG"); |
5535 | 0 | err = 1; |
5536 | 0 | } |
5537 | 0 | else { |
5538 | 0 | key->rng = rng; |
5539 | | /* RNG set and needs to be unset. */ |
5540 | 0 | setKeyRng = 1; |
5541 | 0 | } |
5542 | 0 | } |
5543 | 0 | #endif |
5544 | |
|
5545 | 0 | if (!err) { |
5546 | 0 | PRIVATE_KEY_UNLOCK(); |
5547 | | /* Create secret using wolfSSL. */ |
5548 | 0 | ret = wc_ecc_shared_secret_ex(key, (ecc_point*)pubKey->internal, |
5549 | 0 | (byte *)out, &len); |
5550 | 0 | PRIVATE_KEY_LOCK(); |
5551 | 0 | if (ret != MP_OKAY) { |
5552 | 0 | WOLFSSL_MSG("wc_ecc_shared_secret failed"); |
5553 | 0 | err = 1; |
5554 | 0 | } |
5555 | 0 | } |
5556 | 0 | } |
5557 | |
|
5558 | 0 | #if defined(ECC_TIMING_RESISTANT) && !defined(HAVE_SELFTEST) && \ |
5559 | 0 | (!defined(HAVE_FIPS) || FIPS_VERSION_GE(5,0)) |
5560 | | /* Clear before the RNG is disposed of - key must not keep a dangling |
5561 | | * reference to a local RNG. */ |
5562 | 0 | if (setKeyRng) { |
5563 | 0 | key->rng = NULL; |
5564 | 0 | } |
5565 | 0 | if (initTmpRng) { |
5566 | 0 | wc_FreeRng(rng); |
5567 | 0 | WC_FREE_VAR_EX(rng, NULL, DYNAMIC_TYPE_RNG); |
5568 | 0 | } |
5569 | 0 | #endif |
5570 | |
|
5571 | 0 | if (err) { |
5572 | | /* Make returned value zero. */ |
5573 | 0 | len = 0; |
5574 | 0 | } |
5575 | 0 | return (int)len; |
5576 | 0 | } |
5577 | | #endif /* WOLF_CRYPTO_CB_ONLY_ECC */ |
5578 | | |
5579 | | /* End ECDH */ |
5580 | | |
5581 | | #ifndef NO_WOLFSSL_STUB |
5582 | | const WOLFSSL_EC_KEY_METHOD *wolfSSL_EC_KEY_OpenSSL(void) |
5583 | 0 | { |
5584 | 0 | WOLFSSL_STUB("wolfSSL_EC_KEY_OpenSSL"); |
5585 | |
|
5586 | 0 | return NULL; |
5587 | 0 | } |
5588 | | |
5589 | | WOLFSSL_EC_KEY_METHOD *wolfSSL_EC_KEY_METHOD_new( |
5590 | | const WOLFSSL_EC_KEY_METHOD *meth) |
5591 | 0 | { |
5592 | 0 | WOLFSSL_STUB("wolfSSL_EC_KEY_METHOD_new"); |
5593 | |
|
5594 | 0 | (void)meth; |
5595 | |
|
5596 | 0 | return NULL; |
5597 | 0 | } |
5598 | | |
5599 | | void wolfSSL_EC_KEY_METHOD_free(WOLFSSL_EC_KEY_METHOD *meth) |
5600 | 0 | { |
5601 | 0 | WOLFSSL_STUB("wolfSSL_EC_KEY_METHOD_free"); |
5602 | |
|
5603 | 0 | (void)meth; |
5604 | 0 | } |
5605 | | |
5606 | | void wolfSSL_EC_KEY_METHOD_set_init(WOLFSSL_EC_KEY_METHOD *meth, |
5607 | | void* a1, void* a2, void* a3, void* a4, void* a5, void* a6) |
5608 | 0 | { |
5609 | 0 | WOLFSSL_STUB("wolfSSL_EC_KEY_METHOD_set_init"); |
5610 | |
|
5611 | 0 | (void)meth; |
5612 | 0 | (void)a1; |
5613 | 0 | (void)a2; |
5614 | 0 | (void)a3; |
5615 | 0 | (void)a4; |
5616 | 0 | (void)a5; |
5617 | 0 | (void)a6; |
5618 | 0 | } |
5619 | | |
5620 | | void wolfSSL_EC_KEY_METHOD_set_sign(WOLFSSL_EC_KEY_METHOD *meth, |
5621 | | void* a1, void* a2, void* a3) |
5622 | 0 | { |
5623 | 0 | WOLFSSL_STUB("wolfSSL_EC_KEY_METHOD_set_sign"); |
5624 | |
|
5625 | 0 | (void)meth; |
5626 | 0 | (void)a1; |
5627 | 0 | (void)a2; |
5628 | 0 | (void)a3; |
5629 | 0 | } |
5630 | | |
5631 | | const WOLFSSL_EC_KEY_METHOD *wolfSSL_EC_KEY_get_method( |
5632 | | const WOLFSSL_EC_KEY *key) |
5633 | 0 | { |
5634 | 0 | WOLFSSL_STUB("wolfSSL_EC_KEY_get_method"); |
5635 | |
|
5636 | 0 | (void)key; |
5637 | |
|
5638 | 0 | return NULL; |
5639 | 0 | } |
5640 | | |
5641 | | int wolfSSL_EC_KEY_set_method(WOLFSSL_EC_KEY *key, |
5642 | | const WOLFSSL_EC_KEY_METHOD *meth) |
5643 | 0 | { |
5644 | 0 | WOLFSSL_STUB("wolfSSL_EC_KEY_set_method"); |
5645 | |
|
5646 | 0 | (void)key; |
5647 | 0 | (void)meth; |
5648 | |
|
5649 | 0 | return 0; |
5650 | 0 | } |
5651 | | |
5652 | | #endif /* !NO_WOLFSSL_STUB */ |
5653 | | |
5654 | | #endif /* OPENSSL_EXTRA */ |
5655 | | |
5656 | | #endif /* HAVE_ECC */ |
5657 | | |
5658 | | /******************************************************************************* |
5659 | | * END OF EC API |
5660 | | ******************************************************************************/ |
5661 | | |
5662 | | #endif /* !WOLFSSL_PK_EC_INCLUDED */ |
5663 | | |