Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/native/sun/security/ec/impl/ec.c
38918 views
1
/*
2
* Copyright (c) 2007, 2019, Oracle and/or its affiliates. All rights reserved.
3
* Use is subject to license terms.
4
*
5
* This library is free software; you can redistribute it and/or
6
* modify it under the terms of the GNU Lesser General Public
7
* License as published by the Free Software Foundation; either
8
* version 2.1 of the License, or (at your option) any later version.
9
*
10
* This library is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
* Lesser General Public License for more details.
14
*
15
* You should have received a copy of the GNU Lesser General Public License
16
* along with this library; if not, write to the Free Software Foundation,
17
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18
*
19
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20
* or visit www.oracle.com if you need additional information or have any
21
* questions.
22
*/
23
24
/* *********************************************************************
25
*
26
* The Original Code is the Elliptic Curve Cryptography library.
27
*
28
* The Initial Developer of the Original Code is
29
* Sun Microsystems, Inc.
30
* Portions created by the Initial Developer are Copyright (C) 2003
31
* the Initial Developer. All Rights Reserved.
32
*
33
* Contributor(s):
34
* Dr Vipul Gupta <[email protected]> and
35
* Douglas Stebila <[email protected]>, Sun Microsystems Laboratories
36
*
37
* Last Modified Date from the Original Code: May 2017
38
*********************************************************************** */
39
40
#include "mplogic.h"
41
#include "ec.h"
42
#include "ecl.h"
43
44
#include <sys/types.h>
45
#ifndef _KERNEL
46
#include <stdlib.h>
47
#include <string.h>
48
49
#ifndef _WIN32
50
#include <stdio.h>
51
#include <strings.h>
52
#endif /* _WIN32 */
53
54
#endif
55
#include "ecl-exp.h"
56
#include "mpi.h"
57
#include "ecc_impl.h"
58
59
#ifdef _KERNEL
60
#define PORT_ZFree(p, l) bzero((p), (l)); kmem_free((p), (l))
61
#else
62
#ifndef _WIN32
63
#define PORT_ZFree(p, l) bzero((p), (l)); free((p))
64
#else
65
#define PORT_ZFree(p, l) memset((p), 0, (l)); free((p))
66
#endif /* _WIN32 */
67
#endif
68
69
/*
70
* Returns true if pointP is the point at infinity, false otherwise
71
*/
72
PRBool
73
ec_point_at_infinity(SECItem *pointP)
74
{
75
unsigned int i;
76
77
for (i = 1; i < pointP->len; i++) {
78
if (pointP->data[i] != 0x00) return PR_FALSE;
79
}
80
81
return PR_TRUE;
82
}
83
84
/*
85
* Computes scalar point multiplication pointQ = k1 * G + k2 * pointP for
86
* the curve whose parameters are encoded in params with base point G.
87
*/
88
SECStatus
89
ec_points_mul(const ECParams *params, const mp_int *k1, const mp_int *k2,
90
const SECItem *pointP, SECItem *pointQ, int kmflag, int timing)
91
{
92
mp_int Px, Py, Qx, Qy;
93
mp_int Gx, Gy, order, irreducible, a, b;
94
#if 0 /* currently don't support non-named curves */
95
unsigned int irr_arr[5];
96
#endif
97
ECGroup *group = NULL;
98
SECStatus rv = SECFailure;
99
mp_err err = MP_OKAY;
100
unsigned int len;
101
102
#if EC_DEBUG
103
int i;
104
char mpstr[256];
105
106
printf("ec_points_mul: params [len=%d]:", params->DEREncoding.len);
107
for (i = 0; i < params->DEREncoding.len; i++)
108
printf("%02x:", params->DEREncoding.data[i]);
109
printf("\n");
110
111
if (k1 != NULL) {
112
mp_tohex(k1, mpstr);
113
printf("ec_points_mul: scalar k1: %s\n", mpstr);
114
mp_todecimal(k1, mpstr);
115
printf("ec_points_mul: scalar k1: %s (dec)\n", mpstr);
116
}
117
118
if (k2 != NULL) {
119
mp_tohex(k2, mpstr);
120
printf("ec_points_mul: scalar k2: %s\n", mpstr);
121
mp_todecimal(k2, mpstr);
122
printf("ec_points_mul: scalar k2: %s (dec)\n", mpstr);
123
}
124
125
if (pointP != NULL) {
126
printf("ec_points_mul: pointP [len=%d]:", pointP->len);
127
for (i = 0; i < pointP->len; i++)
128
printf("%02x:", pointP->data[i]);
129
printf("\n");
130
}
131
#endif
132
133
/* NOTE: We only support uncompressed points for now */
134
len = (params->fieldID.size + 7) >> 3;
135
if (pointP != NULL) {
136
if ((pointP->data[0] != EC_POINT_FORM_UNCOMPRESSED) ||
137
(pointP->len != (2 * len + 1))) {
138
return SECFailure;
139
};
140
}
141
142
MP_DIGITS(&Px) = 0;
143
MP_DIGITS(&Py) = 0;
144
MP_DIGITS(&Qx) = 0;
145
MP_DIGITS(&Qy) = 0;
146
MP_DIGITS(&Gx) = 0;
147
MP_DIGITS(&Gy) = 0;
148
MP_DIGITS(&order) = 0;
149
MP_DIGITS(&irreducible) = 0;
150
MP_DIGITS(&a) = 0;
151
MP_DIGITS(&b) = 0;
152
CHECK_MPI_OK( mp_init(&Px, kmflag) );
153
CHECK_MPI_OK( mp_init(&Py, kmflag) );
154
CHECK_MPI_OK( mp_init(&Qx, kmflag) );
155
CHECK_MPI_OK( mp_init(&Qy, kmflag) );
156
CHECK_MPI_OK( mp_init(&Gx, kmflag) );
157
CHECK_MPI_OK( mp_init(&Gy, kmflag) );
158
CHECK_MPI_OK( mp_init(&order, kmflag) );
159
CHECK_MPI_OK( mp_init(&irreducible, kmflag) );
160
CHECK_MPI_OK( mp_init(&a, kmflag) );
161
CHECK_MPI_OK( mp_init(&b, kmflag) );
162
163
if ((k2 != NULL) && (pointP != NULL)) {
164
/* Initialize Px and Py */
165
CHECK_MPI_OK( mp_read_unsigned_octets(&Px, pointP->data + 1, (mp_size) len) );
166
CHECK_MPI_OK( mp_read_unsigned_octets(&Py, pointP->data + 1 + len, (mp_size) len) );
167
}
168
169
/* construct from named params, if possible */
170
if (params->name != ECCurve_noName) {
171
group = ECGroup_fromName(params->name, kmflag);
172
}
173
174
#if 0 /* currently don't support non-named curves */
175
if (group == NULL) {
176
/* Set up mp_ints containing the curve coefficients */
177
CHECK_MPI_OK( mp_read_unsigned_octets(&Gx, params->base.data + 1,
178
(mp_size) len) );
179
CHECK_MPI_OK( mp_read_unsigned_octets(&Gy, params->base.data + 1 + len,
180
(mp_size) len) );
181
SECITEM_TO_MPINT( params->order, &order );
182
SECITEM_TO_MPINT( params->curve.a, &a );
183
SECITEM_TO_MPINT( params->curve.b, &b );
184
if (params->fieldID.type == ec_field_GFp) {
185
SECITEM_TO_MPINT( params->fieldID.u.prime, &irreducible );
186
group = ECGroup_consGFp(&irreducible, &a, &b, &Gx, &Gy, &order, params->cofactor);
187
} else {
188
SECITEM_TO_MPINT( params->fieldID.u.poly, &irreducible );
189
irr_arr[0] = params->fieldID.size;
190
irr_arr[1] = params->fieldID.k1;
191
irr_arr[2] = params->fieldID.k2;
192
irr_arr[3] = params->fieldID.k3;
193
irr_arr[4] = 0;
194
group = ECGroup_consGF2m(&irreducible, irr_arr, &a, &b, &Gx, &Gy, &order, params->cofactor);
195
}
196
}
197
#endif
198
if (group == NULL)
199
goto cleanup;
200
201
if ((k2 != NULL) && (pointP != NULL)) {
202
CHECK_MPI_OK( ECPoints_mul(group, k1, k2, &Px, &Py, &Qx, &Qy, timing) );
203
} else {
204
CHECK_MPI_OK( ECPoints_mul(group, k1, NULL, NULL, NULL, &Qx, &Qy, timing) );
205
}
206
207
/* Construct the SECItem representation of point Q */
208
pointQ->data[0] = EC_POINT_FORM_UNCOMPRESSED;
209
CHECK_MPI_OK( mp_to_fixlen_octets(&Qx, pointQ->data + 1,
210
(mp_size) len) );
211
CHECK_MPI_OK( mp_to_fixlen_octets(&Qy, pointQ->data + 1 + len,
212
(mp_size) len) );
213
214
rv = SECSuccess;
215
216
#if EC_DEBUG
217
printf("ec_points_mul: pointQ [len=%d]:", pointQ->len);
218
for (i = 0; i < pointQ->len; i++)
219
printf("%02x:", pointQ->data[i]);
220
printf("\n");
221
#endif
222
223
cleanup:
224
ECGroup_free(group);
225
mp_clear(&Px);
226
mp_clear(&Py);
227
mp_clear(&Qx);
228
mp_clear(&Qy);
229
mp_clear(&Gx);
230
mp_clear(&Gy);
231
mp_clear(&order);
232
mp_clear(&irreducible);
233
mp_clear(&a);
234
mp_clear(&b);
235
if (err) {
236
MP_TO_SEC_ERROR(err);
237
rv = SECFailure;
238
}
239
240
return rv;
241
}
242
243
/* Generates a new EC key pair. The private key is a supplied
244
* value and the public key is the result of performing a scalar
245
* point multiplication of that value with the curve's base point.
246
*/
247
SECStatus
248
ec_NewKey(ECParams *ecParams, ECPrivateKey **privKey,
249
const unsigned char *privKeyBytes, int privKeyLen, int kmflag)
250
{
251
SECStatus rv = SECFailure;
252
PRArenaPool *arena;
253
ECPrivateKey *key;
254
mp_int k;
255
mp_err err = MP_OKAY;
256
int len;
257
258
#if EC_DEBUG
259
printf("ec_NewKey called\n");
260
#endif
261
262
if (!ecParams || !privKey || !privKeyBytes || (privKeyLen < 0)) {
263
PORT_SetError(SEC_ERROR_INVALID_ARGS);
264
return SECFailure;
265
}
266
267
/* Initialize an arena for the EC key. */
268
if (!(arena = PORT_NewArena(NSS_FREEBL_DEFAULT_CHUNKSIZE)))
269
return SECFailure;
270
271
key = (ECPrivateKey *)PORT_ArenaZAlloc(arena, sizeof(ECPrivateKey),
272
kmflag);
273
if (!key) {
274
PORT_FreeArena(arena, PR_TRUE);
275
return SECFailure;
276
}
277
278
/* Set the version number (SEC 1 section C.4 says it should be 1) */
279
SECITEM_AllocItem(arena, &key->version, 1, kmflag);
280
key->version.data[0] = 1;
281
282
/* Copy all of the fields from the ECParams argument to the
283
* ECParams structure within the private key.
284
*/
285
key->ecParams.arena = arena;
286
key->ecParams.type = ecParams->type;
287
key->ecParams.fieldID.size = ecParams->fieldID.size;
288
key->ecParams.fieldID.type = ecParams->fieldID.type;
289
if (ecParams->fieldID.type == ec_field_GFp) {
290
CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.fieldID.u.prime,
291
&ecParams->fieldID.u.prime, kmflag));
292
} else {
293
CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.fieldID.u.poly,
294
&ecParams->fieldID.u.poly, kmflag));
295
}
296
key->ecParams.fieldID.k1 = ecParams->fieldID.k1;
297
key->ecParams.fieldID.k2 = ecParams->fieldID.k2;
298
key->ecParams.fieldID.k3 = ecParams->fieldID.k3;
299
CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.curve.a,
300
&ecParams->curve.a, kmflag));
301
CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.curve.b,
302
&ecParams->curve.b, kmflag));
303
CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.curve.seed,
304
&ecParams->curve.seed, kmflag));
305
CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.base,
306
&ecParams->base, kmflag));
307
CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.order,
308
&ecParams->order, kmflag));
309
key->ecParams.cofactor = ecParams->cofactor;
310
CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.DEREncoding,
311
&ecParams->DEREncoding, kmflag));
312
key->ecParams.name = ecParams->name;
313
CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.curveOID,
314
&ecParams->curveOID, kmflag));
315
316
len = (ecParams->fieldID.size + 7) >> 3;
317
SECITEM_AllocItem(arena, &key->publicValue, 2*len + 1, kmflag);
318
len = ecParams->order.len;
319
SECITEM_AllocItem(arena, &key->privateValue, len, kmflag);
320
321
/* Copy private key */
322
if (privKeyLen >= len) {
323
memcpy(key->privateValue.data, privKeyBytes, len);
324
} else {
325
memset(key->privateValue.data, 0, (len - privKeyLen));
326
memcpy(key->privateValue.data + (len - privKeyLen), privKeyBytes, privKeyLen);
327
}
328
329
/* Compute corresponding public key */
330
MP_DIGITS(&k) = 0;
331
CHECK_MPI_OK( mp_init(&k, kmflag) );
332
CHECK_MPI_OK( mp_read_unsigned_octets(&k, key->privateValue.data,
333
(mp_size) len) );
334
335
/* key generation does not support timing mitigation */
336
rv = ec_points_mul(ecParams, &k, NULL, NULL, &(key->publicValue), kmflag, /*timing*/ 0);
337
if (rv != SECSuccess) goto cleanup;
338
*privKey = key;
339
340
cleanup:
341
mp_clear(&k);
342
if (rv) {
343
PORT_FreeArena(arena, PR_TRUE);
344
}
345
346
#if EC_DEBUG
347
printf("ec_NewKey returning %s\n",
348
(rv == SECSuccess) ? "success" : "failure");
349
#endif
350
351
return rv;
352
353
}
354
355
/* Generates a new EC key pair. The private key is a supplied
356
* random value (in seed) and the public key is the result of
357
* performing a scalar point multiplication of that value with
358
* the curve's base point.
359
*/
360
SECStatus
361
EC_NewKeyFromSeed(ECParams *ecParams, ECPrivateKey **privKey,
362
const unsigned char *seed, int seedlen, int kmflag)
363
{
364
SECStatus rv = SECFailure;
365
rv = ec_NewKey(ecParams, privKey, seed, seedlen, kmflag);
366
return rv;
367
}
368
369
/* Generate a random private key using the algorithm A.4.1 of ANSI X9.62,
370
* modified a la FIPS 186-2 Change Notice 1 to eliminate the bias in the
371
* random number generator.
372
*
373
* Parameters
374
* - order: a buffer that holds the curve's group order
375
* - len: the length in octets of the order buffer
376
* - random: a buffer of 2 * len random bytes
377
* - randomlen: the length in octets of the random buffer
378
*
379
* Return Value
380
* Returns a buffer of len octets that holds the private key. The caller
381
* is responsible for freeing the buffer with PORT_ZFree.
382
*/
383
static unsigned char *
384
ec_GenerateRandomPrivateKey(const unsigned char *order, int len,
385
const unsigned char *random, int randomlen, int kmflag)
386
{
387
SECStatus rv = SECSuccess;
388
mp_err err;
389
unsigned char *privKeyBytes = NULL;
390
mp_int privKeyVal, order_1, one;
391
392
MP_DIGITS(&privKeyVal) = 0;
393
MP_DIGITS(&order_1) = 0;
394
MP_DIGITS(&one) = 0;
395
CHECK_MPI_OK( mp_init(&privKeyVal, kmflag) );
396
CHECK_MPI_OK( mp_init(&order_1, kmflag) );
397
CHECK_MPI_OK( mp_init(&one, kmflag) );
398
399
/*
400
* Reduces the 2*len buffer of random bytes modulo the group order.
401
*/
402
if ((privKeyBytes = PORT_Alloc(2*len, kmflag)) == NULL) goto cleanup;
403
if (randomlen != 2 * len) {
404
randomlen = 2 * len;
405
}
406
/* No need to generate - random bytes are now supplied */
407
/* CHECK_SEC_OK( RNG_GenerateGlobalRandomBytes(privKeyBytes, 2*len) );*/
408
memcpy(privKeyBytes, random, randomlen);
409
410
CHECK_MPI_OK( mp_read_unsigned_octets(&privKeyVal, privKeyBytes, 2*len) );
411
CHECK_MPI_OK( mp_read_unsigned_octets(&order_1, order, len) );
412
CHECK_MPI_OK( mp_set_int(&one, 1) );
413
CHECK_MPI_OK( mp_sub(&order_1, &one, &order_1) );
414
CHECK_MPI_OK( mp_mod(&privKeyVal, &order_1, &privKeyVal) );
415
CHECK_MPI_OK( mp_add(&privKeyVal, &one, &privKeyVal) );
416
CHECK_MPI_OK( mp_to_fixlen_octets(&privKeyVal, privKeyBytes, len) );
417
memset(privKeyBytes+len, 0, len);
418
cleanup:
419
mp_clear(&privKeyVal);
420
mp_clear(&order_1);
421
mp_clear(&one);
422
if (err < MP_OKAY) {
423
MP_TO_SEC_ERROR(err);
424
rv = SECFailure;
425
}
426
if (rv != SECSuccess && privKeyBytes) {
427
#ifdef _KERNEL
428
kmem_free(privKeyBytes, 2*len);
429
#else
430
free(privKeyBytes);
431
#endif
432
privKeyBytes = NULL;
433
}
434
return privKeyBytes;
435
}
436
437
/* Generates a new EC key pair. The private key is a random value and
438
* the public key is the result of performing a scalar point multiplication
439
* of that value with the curve's base point.
440
*/
441
SECStatus
442
EC_NewKey(ECParams *ecParams, ECPrivateKey **privKey,
443
const unsigned char* random, int randomlen, int kmflag)
444
{
445
SECStatus rv = SECFailure;
446
int len;
447
unsigned char *privKeyBytes = NULL;
448
449
if (!ecParams) {
450
PORT_SetError(SEC_ERROR_INVALID_ARGS);
451
return SECFailure;
452
}
453
454
len = ecParams->order.len;
455
privKeyBytes = ec_GenerateRandomPrivateKey(ecParams->order.data, len,
456
random, randomlen, kmflag);
457
if (privKeyBytes == NULL) goto cleanup;
458
/* generate public key */
459
CHECK_SEC_OK( ec_NewKey(ecParams, privKey, privKeyBytes, len, kmflag) );
460
461
cleanup:
462
if (privKeyBytes) {
463
PORT_ZFree(privKeyBytes, len * 2);
464
}
465
#if EC_DEBUG
466
printf("EC_NewKey returning %s\n",
467
(rv == SECSuccess) ? "success" : "failure");
468
#endif
469
470
return rv;
471
}
472
473
/* Validates an EC public key as described in Section 5.2.2 of
474
* X9.62. The ECDH primitive when used without the cofactor does
475
* not address small subgroup attacks, which may occur when the
476
* public key is not valid. These attacks can be prevented by
477
* validating the public key before using ECDH.
478
*/
479
SECStatus
480
EC_ValidatePublicKey(ECParams *ecParams, SECItem *publicValue, int kmflag)
481
{
482
mp_int Px, Py;
483
ECGroup *group = NULL;
484
SECStatus rv = SECFailure;
485
mp_err err = MP_OKAY;
486
unsigned int len;
487
488
if (!ecParams || !publicValue) {
489
PORT_SetError(SEC_ERROR_INVALID_ARGS);
490
return SECFailure;
491
}
492
493
/* NOTE: We only support uncompressed points for now */
494
len = (ecParams->fieldID.size + 7) >> 3;
495
if (publicValue->data[0] != EC_POINT_FORM_UNCOMPRESSED) {
496
PORT_SetError(SEC_ERROR_UNSUPPORTED_EC_POINT_FORM);
497
return SECFailure;
498
} else if (publicValue->len != (2 * len + 1)) {
499
PORT_SetError(SEC_ERROR_BAD_KEY);
500
return SECFailure;
501
}
502
503
MP_DIGITS(&Px) = 0;
504
MP_DIGITS(&Py) = 0;
505
CHECK_MPI_OK( mp_init(&Px, kmflag) );
506
CHECK_MPI_OK( mp_init(&Py, kmflag) );
507
508
/* Initialize Px and Py */
509
CHECK_MPI_OK( mp_read_unsigned_octets(&Px, publicValue->data + 1, (mp_size) len) );
510
CHECK_MPI_OK( mp_read_unsigned_octets(&Py, publicValue->data + 1 + len, (mp_size) len) );
511
512
/* construct from named params */
513
group = ECGroup_fromName(ecParams->name, kmflag);
514
if (group == NULL) {
515
/*
516
* ECGroup_fromName fails if ecParams->name is not a valid
517
* ECCurveName value, or if we run out of memory, or perhaps
518
* for other reasons. Unfortunately if ecParams->name is a
519
* valid ECCurveName value, we don't know what the right error
520
* code should be because ECGroup_fromName doesn't return an
521
* error code to the caller. Set err to MP_UNDEF because
522
* that's what ECGroup_fromName uses internally.
523
*/
524
if ((ecParams->name <= ECCurve_noName) ||
525
(ecParams->name >= ECCurve_pastLastCurve)) {
526
err = MP_BADARG;
527
} else {
528
err = MP_UNDEF;
529
}
530
goto cleanup;
531
}
532
533
/* validate public point */
534
if ((err = ECPoint_validate(group, &Px, &Py)) < MP_YES) {
535
if (err == MP_NO) {
536
PORT_SetError(SEC_ERROR_BAD_KEY);
537
rv = SECFailure;
538
err = MP_OKAY; /* don't change the error code */
539
}
540
goto cleanup;
541
}
542
543
rv = SECSuccess;
544
545
cleanup:
546
ECGroup_free(group);
547
mp_clear(&Px);
548
mp_clear(&Py);
549
if (err) {
550
MP_TO_SEC_ERROR(err);
551
rv = SECFailure;
552
}
553
return rv;
554
}
555
556
/*
557
** Performs an ECDH key derivation by computing the scalar point
558
** multiplication of privateValue and publicValue (with or without the
559
** cofactor) and returns the x-coordinate of the resulting elliptic
560
** curve point in derived secret. If successful, derivedSecret->data
561
** is set to the address of the newly allocated buffer containing the
562
** derived secret, and derivedSecret->len is the size of the secret
563
** produced. It is the caller's responsibility to free the allocated
564
** buffer containing the derived secret.
565
*/
566
SECStatus
567
ECDH_Derive(SECItem *publicValue,
568
ECParams *ecParams,
569
SECItem *privateValue,
570
PRBool withCofactor,
571
SECItem *derivedSecret,
572
int kmflag)
573
{
574
SECStatus rv = SECFailure;
575
unsigned int len = 0;
576
SECItem pointQ = {siBuffer, NULL, 0};
577
mp_int k; /* to hold the private value */
578
mp_int cofactor;
579
mp_err err = MP_OKAY;
580
#if EC_DEBUG
581
int i;
582
#endif
583
584
if (!publicValue || !ecParams || !privateValue ||
585
!derivedSecret) {
586
PORT_SetError(SEC_ERROR_INVALID_ARGS);
587
return SECFailure;
588
}
589
590
if (EC_ValidatePublicKey(ecParams, publicValue, kmflag) != SECSuccess) {
591
return SECFailure;
592
}
593
594
memset(derivedSecret, 0, sizeof *derivedSecret);
595
len = (ecParams->fieldID.size + 7) >> 3;
596
pointQ.len = 2*len + 1;
597
if ((pointQ.data = PORT_Alloc(2*len + 1, kmflag)) == NULL) goto cleanup;
598
599
MP_DIGITS(&k) = 0;
600
CHECK_MPI_OK( mp_init(&k, kmflag) );
601
CHECK_MPI_OK( mp_read_unsigned_octets(&k, privateValue->data,
602
(mp_size) privateValue->len) );
603
604
if (withCofactor && (ecParams->cofactor != 1)) {
605
/* multiply k with the cofactor */
606
MP_DIGITS(&cofactor) = 0;
607
CHECK_MPI_OK( mp_init(&cofactor, kmflag) );
608
mp_set(&cofactor, ecParams->cofactor);
609
CHECK_MPI_OK( mp_mul(&k, &cofactor, &k) );
610
}
611
612
/* Multiply our private key and peer's public point */
613
/* ECDH doesn't support timing mitigation */
614
if ((ec_points_mul(ecParams, NULL, &k, publicValue, &pointQ, kmflag, /*timing*/ 0) != SECSuccess) ||
615
ec_point_at_infinity(&pointQ))
616
goto cleanup;
617
618
/* Allocate memory for the derived secret and copy
619
* the x co-ordinate of pointQ into it.
620
*/
621
SECITEM_AllocItem(NULL, derivedSecret, len, kmflag);
622
memcpy(derivedSecret->data, pointQ.data + 1, len);
623
624
rv = SECSuccess;
625
626
#if EC_DEBUG
627
printf("derived_secret:\n");
628
for (i = 0; i < derivedSecret->len; i++)
629
printf("%02x:", derivedSecret->data[i]);
630
printf("\n");
631
#endif
632
633
cleanup:
634
mp_clear(&k);
635
636
if (pointQ.data) {
637
PORT_ZFree(pointQ.data, 2*len + 1);
638
}
639
640
return rv;
641
}
642
643
/* Computes the ECDSA signature (a concatenation of two values r and s)
644
* on the digest using the given key and the random value kb (used in
645
* computing s).
646
*/
647
SECStatus
648
ECDSA_SignDigestWithSeed(ECPrivateKey *key, SECItem *signature,
649
const SECItem *digest, const unsigned char *kb, const int kblen, int kmflag,
650
int timing)
651
{
652
SECStatus rv = SECFailure;
653
mp_int x1;
654
mp_int d, k; /* private key, random integer */
655
mp_int r, s; /* tuple (r, s) is the signature */
656
mp_int n;
657
mp_err err = MP_OKAY;
658
ECParams *ecParams = NULL;
659
SECItem kGpoint = { siBuffer, NULL, 0};
660
int flen = 0; /* length in bytes of the field size */
661
unsigned olen; /* length in bytes of the base point order */
662
unsigned int orderBitSize;
663
664
#if EC_DEBUG
665
char mpstr[256];
666
#endif
667
668
/* Initialize MPI integers. */
669
/* must happen before the first potential call to cleanup */
670
MP_DIGITS(&x1) = 0;
671
MP_DIGITS(&d) = 0;
672
MP_DIGITS(&k) = 0;
673
MP_DIGITS(&r) = 0;
674
MP_DIGITS(&s) = 0;
675
MP_DIGITS(&n) = 0;
676
677
/* Check args */
678
if (!key || !signature || !digest || !kb || (kblen < 0)) {
679
PORT_SetError(SEC_ERROR_INVALID_ARGS);
680
goto cleanup;
681
}
682
683
ecParams = &(key->ecParams);
684
flen = (ecParams->fieldID.size + 7) >> 3;
685
olen = ecParams->order.len;
686
if (signature->data == NULL) {
687
/* a call to get the signature length only */
688
goto finish;
689
}
690
if (signature->len < 2*olen) {
691
PORT_SetError(SEC_ERROR_OUTPUT_LEN);
692
rv = SECBufferTooSmall;
693
goto cleanup;
694
}
695
696
697
CHECK_MPI_OK( mp_init(&x1, kmflag) );
698
CHECK_MPI_OK( mp_init(&d, kmflag) );
699
CHECK_MPI_OK( mp_init(&k, kmflag) );
700
CHECK_MPI_OK( mp_init(&r, kmflag) );
701
CHECK_MPI_OK( mp_init(&s, kmflag) );
702
CHECK_MPI_OK( mp_init(&n, kmflag) );
703
704
SECITEM_TO_MPINT( ecParams->order, &n );
705
SECITEM_TO_MPINT( key->privateValue, &d );
706
CHECK_MPI_OK( mp_read_unsigned_octets(&k, kb, kblen) );
707
/* Make sure k is in the interval [1, n-1] */
708
if ((mp_cmp_z(&k) <= 0) || (mp_cmp(&k, &n) >= 0)) {
709
#if EC_DEBUG
710
printf("k is outside [1, n-1]\n");
711
mp_tohex(&k, mpstr);
712
printf("k : %s \n", mpstr);
713
mp_tohex(&n, mpstr);
714
printf("n : %s \n", mpstr);
715
#endif
716
PORT_SetError(SEC_ERROR_NEED_RANDOM);
717
goto cleanup;
718
}
719
720
/*
721
** ANSI X9.62, Section 5.3.2, Step 2
722
**
723
** Compute kG
724
*/
725
kGpoint.len = 2*flen + 1;
726
kGpoint.data = PORT_Alloc(2*flen + 1, kmflag);
727
if ((kGpoint.data == NULL) ||
728
(ec_points_mul(ecParams, &k, NULL, NULL, &kGpoint, kmflag, timing)
729
!= SECSuccess))
730
goto cleanup;
731
732
/*
733
** ANSI X9.62, Section 5.3.3, Step 1
734
**
735
** Extract the x co-ordinate of kG into x1
736
*/
737
CHECK_MPI_OK( mp_read_unsigned_octets(&x1, kGpoint.data + 1,
738
(mp_size) flen) );
739
740
/*
741
** ANSI X9.62, Section 5.3.3, Step 2
742
**
743
** r = x1 mod n NOTE: n is the order of the curve
744
*/
745
CHECK_MPI_OK( mp_mod(&x1, &n, &r) );
746
747
/*
748
** ANSI X9.62, Section 5.3.3, Step 3
749
**
750
** verify r != 0
751
*/
752
if (mp_cmp_z(&r) == 0) {
753
PORT_SetError(SEC_ERROR_NEED_RANDOM);
754
goto cleanup;
755
}
756
757
/*
758
** ANSI X9.62, Section 5.3.3, Step 4
759
**
760
** s = (k**-1 * (HASH(M) + d*r)) mod n
761
*/
762
SECITEM_TO_MPINT(*digest, &s); /* s = HASH(M) */
763
764
/* In the definition of EC signing, digests are truncated
765
* to the order length
766
* (see SEC 1 "Elliptic Curve Digit Signature Algorithm" section 4.1.*/
767
orderBitSize = mpl_significant_bits(&n);
768
if (digest->len*8 > orderBitSize) {
769
mpl_rsh(&s,&s,digest->len*8 - orderBitSize);
770
}
771
772
#if EC_DEBUG
773
mp_todecimal(&n, mpstr);
774
printf("n : %s (dec)\n", mpstr);
775
mp_todecimal(&d, mpstr);
776
printf("d : %s (dec)\n", mpstr);
777
mp_tohex(&x1, mpstr);
778
printf("x1: %s\n", mpstr);
779
mp_todecimal(&s, mpstr);
780
printf("digest: %s (decimal)\n", mpstr);
781
mp_todecimal(&r, mpstr);
782
printf("r : %s (dec)\n", mpstr);
783
mp_tohex(&r, mpstr);
784
printf("r : %s\n", mpstr);
785
#endif
786
787
CHECK_MPI_OK( mp_invmod(&k, &n, &k) ); /* k = k**-1 mod n */
788
CHECK_MPI_OK( mp_mulmod(&d, &r, &n, &d) ); /* d = d * r mod n */
789
CHECK_MPI_OK( mp_addmod(&s, &d, &n, &s) ); /* s = s + d mod n */
790
CHECK_MPI_OK( mp_mulmod(&s, &k, &n, &s) ); /* s = s * k mod n */
791
792
#if EC_DEBUG
793
mp_todecimal(&s, mpstr);
794
printf("s : %s (dec)\n", mpstr);
795
mp_tohex(&s, mpstr);
796
printf("s : %s\n", mpstr);
797
#endif
798
799
/*
800
** ANSI X9.62, Section 5.3.3, Step 5
801
**
802
** verify s != 0
803
*/
804
if (mp_cmp_z(&s) == 0) {
805
PORT_SetError(SEC_ERROR_NEED_RANDOM);
806
goto cleanup;
807
}
808
809
/*
810
**
811
** Signature is tuple (r, s)
812
*/
813
CHECK_MPI_OK( mp_to_fixlen_octets(&r, signature->data, olen) );
814
CHECK_MPI_OK( mp_to_fixlen_octets(&s, signature->data + olen, olen) );
815
finish:
816
signature->len = 2*olen;
817
818
rv = SECSuccess;
819
err = MP_OKAY;
820
cleanup:
821
mp_clear(&x1);
822
mp_clear(&d);
823
mp_clear(&k);
824
mp_clear(&r);
825
mp_clear(&s);
826
mp_clear(&n);
827
828
if (kGpoint.data) {
829
PORT_ZFree(kGpoint.data, 2*flen + 1);
830
}
831
832
if (err) {
833
MP_TO_SEC_ERROR(err);
834
rv = SECFailure;
835
}
836
837
#if EC_DEBUG
838
printf("ECDSA signing with seed %s\n",
839
(rv == SECSuccess) ? "succeeded" : "failed");
840
#endif
841
842
return rv;
843
}
844
845
/*
846
** Computes the ECDSA signature on the digest using the given key
847
** and a random seed.
848
*/
849
SECStatus
850
ECDSA_SignDigest(ECPrivateKey *key, SECItem *signature, const SECItem *digest,
851
const unsigned char* random, int randomLen, int kmflag, int timing)
852
{
853
SECStatus rv = SECFailure;
854
int len;
855
unsigned char *kBytes= NULL;
856
857
if (!key) {
858
PORT_SetError(SEC_ERROR_INVALID_ARGS);
859
return SECFailure;
860
}
861
862
/* Generate random value k */
863
len = key->ecParams.order.len;
864
kBytes = ec_GenerateRandomPrivateKey(key->ecParams.order.data, len,
865
random, randomLen, kmflag);
866
if (kBytes == NULL) goto cleanup;
867
868
/* Generate ECDSA signature with the specified k value */
869
rv = ECDSA_SignDigestWithSeed(key, signature, digest, kBytes, len, kmflag, timing);
870
871
cleanup:
872
if (kBytes) {
873
PORT_ZFree(kBytes, len * 2);
874
}
875
876
#if EC_DEBUG
877
printf("ECDSA signing %s\n",
878
(rv == SECSuccess) ? "succeeded" : "failed");
879
#endif
880
881
return rv;
882
}
883
884
/*
885
** Checks the signature on the given digest using the key provided.
886
*/
887
SECStatus
888
ECDSA_VerifyDigest(ECPublicKey *key, const SECItem *signature,
889
const SECItem *digest, int kmflag)
890
{
891
SECStatus rv = SECFailure;
892
mp_int r_, s_; /* tuple (r', s') is received signature) */
893
mp_int c, u1, u2, v; /* intermediate values used in verification */
894
mp_int x1;
895
mp_int n;
896
mp_err err = MP_OKAY;
897
ECParams *ecParams = NULL;
898
SECItem pointC = { siBuffer, NULL, 0 };
899
int slen; /* length in bytes of a half signature (r or s) */
900
int flen; /* length in bytes of the field size */
901
unsigned olen; /* length in bytes of the base point order */
902
unsigned int orderBitSize;
903
904
#if EC_DEBUG
905
char mpstr[256];
906
printf("ECDSA verification called\n");
907
#endif
908
909
/* Initialize MPI integers. */
910
/* must happen before the first potential call to cleanup */
911
MP_DIGITS(&r_) = 0;
912
MP_DIGITS(&s_) = 0;
913
MP_DIGITS(&c) = 0;
914
MP_DIGITS(&u1) = 0;
915
MP_DIGITS(&u2) = 0;
916
MP_DIGITS(&x1) = 0;
917
MP_DIGITS(&v) = 0;
918
MP_DIGITS(&n) = 0;
919
920
/* Check args */
921
if (!key || !signature || !digest) {
922
PORT_SetError(SEC_ERROR_INVALID_ARGS);
923
goto cleanup;
924
}
925
926
ecParams = &(key->ecParams);
927
flen = (ecParams->fieldID.size + 7) >> 3;
928
olen = ecParams->order.len;
929
if (signature->len == 0 || signature->len%2 != 0 ||
930
signature->len > 2*olen) {
931
PORT_SetError(SEC_ERROR_INPUT_LEN);
932
goto cleanup;
933
}
934
slen = signature->len/2;
935
936
SECITEM_AllocItem(NULL, &pointC, 2*flen + 1, kmflag);
937
if (pointC.data == NULL)
938
goto cleanup;
939
940
CHECK_MPI_OK( mp_init(&r_, kmflag) );
941
CHECK_MPI_OK( mp_init(&s_, kmflag) );
942
CHECK_MPI_OK( mp_init(&c, kmflag) );
943
CHECK_MPI_OK( mp_init(&u1, kmflag) );
944
CHECK_MPI_OK( mp_init(&u2, kmflag) );
945
CHECK_MPI_OK( mp_init(&x1, kmflag) );
946
CHECK_MPI_OK( mp_init(&v, kmflag) );
947
CHECK_MPI_OK( mp_init(&n, kmflag) );
948
949
/*
950
** Convert received signature (r', s') into MPI integers.
951
*/
952
CHECK_MPI_OK( mp_read_unsigned_octets(&r_, signature->data, slen) );
953
CHECK_MPI_OK( mp_read_unsigned_octets(&s_, signature->data + slen, slen) );
954
955
/*
956
** ANSI X9.62, Section 5.4.2, Steps 1 and 2
957
**
958
** Verify that 0 < r' < n and 0 < s' < n
959
*/
960
SECITEM_TO_MPINT(ecParams->order, &n);
961
if (mp_cmp_z(&r_) <= 0 || mp_cmp_z(&s_) <= 0 ||
962
mp_cmp(&r_, &n) >= 0 || mp_cmp(&s_, &n) >= 0) {
963
PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
964
goto cleanup; /* will return rv == SECFailure */
965
}
966
967
/*
968
** ANSI X9.62, Section 5.4.2, Step 3
969
**
970
** c = (s')**-1 mod n
971
*/
972
CHECK_MPI_OK( mp_invmod(&s_, &n, &c) ); /* c = (s')**-1 mod n */
973
974
/*
975
** ANSI X9.62, Section 5.4.2, Step 4
976
**
977
** u1 = ((HASH(M')) * c) mod n
978
*/
979
SECITEM_TO_MPINT(*digest, &u1); /* u1 = HASH(M) */
980
981
/* In the definition of EC signing, digests are truncated
982
* to the order length, in bits.
983
* (see SEC 1 "Elliptic Curve Digit Signature Algorithm" section 4.1.*/
984
/* u1 = HASH(M') */
985
orderBitSize = mpl_significant_bits(&n);
986
if (digest->len*8 > orderBitSize) {
987
mpl_rsh(&u1,&u1,digest->len*8- orderBitSize);
988
}
989
990
#if EC_DEBUG
991
mp_todecimal(&r_, mpstr);
992
printf("r_: %s (dec)\n", mpstr);
993
mp_todecimal(&s_, mpstr);
994
printf("s_: %s (dec)\n", mpstr);
995
mp_todecimal(&c, mpstr);
996
printf("c : %s (dec)\n", mpstr);
997
mp_todecimal(&u1, mpstr);
998
printf("digest: %s (dec)\n", mpstr);
999
#endif
1000
1001
CHECK_MPI_OK( mp_mulmod(&u1, &c, &n, &u1) ); /* u1 = u1 * c mod n */
1002
1003
/*
1004
** ANSI X9.62, Section 5.4.2, Step 4
1005
**
1006
** u2 = ((r') * c) mod n
1007
*/
1008
CHECK_MPI_OK( mp_mulmod(&r_, &c, &n, &u2) );
1009
1010
/*
1011
** ANSI X9.62, Section 5.4.3, Step 1
1012
**
1013
** Compute u1*G + u2*Q
1014
** Here, A = u1.G B = u2.Q and C = A + B
1015
** If the result, C, is the point at infinity, reject the signature
1016
*/
1017
/* verification does not support timing mitigation */
1018
if (ec_points_mul(ecParams, &u1, &u2, &key->publicValue, &pointC, kmflag, /*timing*/ 0)
1019
!= SECSuccess) {
1020
rv = SECFailure;
1021
goto cleanup;
1022
}
1023
if (ec_point_at_infinity(&pointC)) {
1024
PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
1025
rv = SECFailure;
1026
goto cleanup;
1027
}
1028
1029
CHECK_MPI_OK( mp_read_unsigned_octets(&x1, pointC.data + 1, flen) );
1030
1031
/*
1032
** ANSI X9.62, Section 5.4.4, Step 2
1033
**
1034
** v = x1 mod n
1035
*/
1036
CHECK_MPI_OK( mp_mod(&x1, &n, &v) );
1037
1038
#if EC_DEBUG
1039
mp_todecimal(&r_, mpstr);
1040
printf("r_: %s (dec)\n", mpstr);
1041
mp_todecimal(&v, mpstr);
1042
printf("v : %s (dec)\n", mpstr);
1043
#endif
1044
1045
/*
1046
** ANSI X9.62, Section 5.4.4, Step 3
1047
**
1048
** Verification: v == r'
1049
*/
1050
if (mp_cmp(&v, &r_)) {
1051
PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
1052
rv = SECFailure; /* Signature failed to verify. */
1053
} else {
1054
rv = SECSuccess; /* Signature verified. */
1055
}
1056
1057
#if EC_DEBUG
1058
mp_todecimal(&u1, mpstr);
1059
printf("u1: %s (dec)\n", mpstr);
1060
mp_todecimal(&u2, mpstr);
1061
printf("u2: %s (dec)\n", mpstr);
1062
mp_tohex(&x1, mpstr);
1063
printf("x1: %s\n", mpstr);
1064
mp_todecimal(&v, mpstr);
1065
printf("v : %s (dec)\n", mpstr);
1066
#endif
1067
1068
cleanup:
1069
mp_clear(&r_);
1070
mp_clear(&s_);
1071
mp_clear(&c);
1072
mp_clear(&u1);
1073
mp_clear(&u2);
1074
mp_clear(&x1);
1075
mp_clear(&v);
1076
mp_clear(&n);
1077
1078
if (pointC.data) SECITEM_FreeItem(&pointC, PR_FALSE);
1079
if (err) {
1080
MP_TO_SEC_ERROR(err);
1081
rv = SECFailure;
1082
}
1083
1084
#if EC_DEBUG
1085
printf("ECDSA verification %s\n",
1086
(rv == SECSuccess) ? "succeeded" : "failed");
1087
#endif
1088
1089
return rv;
1090
}
1091
1092