Coverage Report

Created: 2024-05-20 06:23

/src/nss/lib/freebl/ec.c
Line
Count
Source (jump to first uncovered line)
1
/* This Source Code Form is subject to the terms of the Mozilla Public
2
 * License, v. 2.0. If a copy of the MPL was not distributed with this
3
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5
#ifdef FREEBL_NO_DEPEND
6
#include "stubs.h"
7
#endif
8
9
#include "blapi.h"
10
#include "blapii.h"
11
#include "prerr.h"
12
#include "secerr.h"
13
#include "secmpi.h"
14
#include "secitem.h"
15
#include "mplogic.h"
16
#include "ec.h"
17
#include "ecl.h"
18
#include "verified/Hacl_P384.h"
19
#include "verified/Hacl_P521.h"
20
#include "secport.h"
21
#include "verified/Hacl_Ed25519.h"
22
23
#define EC_DOUBLECHECK PR_FALSE
24
25
SECStatus
26
ec_secp384r1_scalar_validate(const SECItem *scalar)
27
5.51k
{
28
5.51k
    if (!scalar || !scalar->data) {
29
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
30
0
        return SECFailure;
31
0
    }
32
33
5.51k
    if (scalar->len != 48) {
34
0
        PORT_SetError(SEC_ERROR_BAD_KEY);
35
0
        return SECFailure;
36
0
    }
37
38
5.51k
    bool b = Hacl_P384_validate_private_key(scalar->data);
39
40
5.51k
    if (!b) {
41
0
        PORT_SetError(SEC_ERROR_BAD_KEY);
42
0
        return SECFailure;
43
0
    }
44
5.51k
    return SECSuccess;
45
5.51k
}
46
47
SECStatus
48
ec_secp521r1_scalar_validate(const SECItem *scalar)
49
964
{
50
964
    if (!scalar || !scalar->data) {
51
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
52
0
        return SECFailure;
53
0
    }
54
55
964
    if (scalar->len != 66) {
56
0
        PORT_SetError(SEC_ERROR_BAD_KEY);
57
0
        return SECFailure;
58
0
    }
59
60
964
    bool b = Hacl_P521_validate_private_key(scalar->data);
61
62
964
    if (!b) {
63
0
        PORT_SetError(SEC_ERROR_BAD_KEY);
64
0
        return SECFailure;
65
0
    }
66
964
    return SECSuccess;
67
964
}
68
69
SECStatus
70
ec_ED25519_pt_validate(const SECItem *px)
71
0
{
72
0
    if (!px || !px->data || px->len != Ed25519_PUBLIC_KEYLEN) {
73
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
74
0
        return SECFailure;
75
0
    }
76
0
    return SECSuccess;
77
0
}
78
79
SECStatus
80
ec_ED25519_scalar_validate(const SECItem *scalar)
81
0
{
82
0
    if (!scalar || !scalar->data || scalar->len != Ed25519_PRIVATE_KEYLEN) {
83
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
84
0
        return SECFailure;
85
0
    }
86
87
0
    return SECSuccess;
88
0
}
89
90
static const ECMethod kMethods[] = {
91
    { ECCurve25519,
92
      ec_Curve25519_pt_mul,
93
      ec_Curve25519_pt_validate,
94
      ec_Curve25519_scalar_validate,
95
      NULL,
96
      NULL },
97
    {
98
        ECCurve_NIST_P256,
99
        ec_secp256r1_pt_mul,
100
        ec_secp256r1_pt_validate,
101
        ec_secp256r1_scalar_validate,
102
        ec_secp256r1_sign_digest,
103
        ec_secp256r1_verify_digest,
104
    },
105
    {
106
        ECCurve_NIST_P384,
107
        NULL,
108
        NULL,
109
        ec_secp384r1_scalar_validate,
110
        NULL,
111
        NULL,
112
    },
113
    {
114
        ECCurve_NIST_P521,
115
        NULL,
116
        NULL,
117
        ec_secp521r1_scalar_validate,
118
        NULL,
119
        NULL,
120
    },
121
    { ECCurve_Ed25519,
122
      NULL,
123
      ec_ED25519_pt_validate,
124
      ec_ED25519_scalar_validate,
125
      NULL,
126
      NULL },
127
};
128
129
static const ECMethod *
130
ec_get_method_from_name(ECCurveName name)
131
160k
{
132
160k
    unsigned long i;
133
222k
    for (i = 0; i < sizeof(kMethods) / sizeof(kMethods[0]); ++i) {
134
222k
        if (kMethods[i].name == name) {
135
160k
            return &kMethods[i];
136
160k
        }
137
222k
    }
138
0
    return NULL;
139
160k
}
140
141
/*
142
 * Returns true if pointP is the point at infinity, false otherwise
143
 */
144
PRBool
145
ec_point_at_infinity(SECItem *pointP)
146
14.2k
{
147
14.2k
    unsigned int i;
148
149
16.1k
    for (i = 1; i < pointP->len; i++) {
150
16.1k
        if (pointP->data[i] != 0x00)
151
14.2k
            return PR_FALSE;
152
16.1k
    }
153
154
0
    return PR_TRUE;
155
14.2k
}
156
157
/*
158
 * Computes scalar point multiplication pointQ = k1 * G + k2 * pointP for
159
 * the curve whose parameters are encoded in params with base point G.
160
 */
161
SECStatus
162
ec_points_mul(const ECParams *params, const mp_int *k1, const mp_int *k2,
163
              const SECItem *pointP, SECItem *pointQ)
164
14.1k
{
165
14.1k
    mp_int Px, Py, Qx, Qy;
166
14.1k
    mp_int Gx, Gy, order, irreducible, a, b;
167
14.1k
    ECGroup *group = NULL;
168
14.1k
    SECStatus rv = SECFailure;
169
14.1k
    mp_err err = MP_OKAY;
170
14.1k
    unsigned int len;
171
172
#if EC_DEBUG
173
    int i;
174
    char mpstr[256];
175
176
    printf("ec_points_mul: params [len=%d]:", params->DEREncoding.len);
177
    for (i = 0; i < params->DEREncoding.len; i++)
178
        printf("%02x:", params->DEREncoding.data[i]);
179
    printf("\n");
180
181
    if (k1 != NULL) {
182
        mp_tohex((mp_int *)k1, mpstr);
183
        printf("ec_points_mul: scalar k1: %s\n", mpstr);
184
        mp_todecimal((mp_int *)k1, mpstr);
185
        printf("ec_points_mul: scalar k1: %s (dec)\n", mpstr);
186
    }
187
188
    if (k2 != NULL) {
189
        mp_tohex((mp_int *)k2, mpstr);
190
        printf("ec_points_mul: scalar k2: %s\n", mpstr);
191
        mp_todecimal((mp_int *)k2, mpstr);
192
        printf("ec_points_mul: scalar k2: %s (dec)\n", mpstr);
193
    }
194
195
    if (pointP != NULL) {
196
        printf("ec_points_mul: pointP [len=%d]:", pointP->len);
197
        for (i = 0; i < pointP->len; i++)
198
            printf("%02x:", pointP->data[i]);
199
        printf("\n");
200
    }
201
#endif
202
203
    /* NOTE: We only support uncompressed points for now */
204
14.1k
    len = (((unsigned int)params->fieldID.size) + 7) >> 3;
205
14.1k
    if (pointP != NULL) {
206
7.68k
        if ((pointP->data[0] != EC_POINT_FORM_UNCOMPRESSED) ||
207
7.68k
            (pointP->len != (2 * len + 1))) {
208
0
            PORT_SetError(SEC_ERROR_UNSUPPORTED_EC_POINT_FORM);
209
0
            return SECFailure;
210
7.68k
        };
211
7.68k
    }
212
213
14.1k
    MP_DIGITS(&Px) = 0;
214
14.1k
    MP_DIGITS(&Py) = 0;
215
14.1k
    MP_DIGITS(&Qx) = 0;
216
14.1k
    MP_DIGITS(&Qy) = 0;
217
14.1k
    MP_DIGITS(&Gx) = 0;
218
14.1k
    MP_DIGITS(&Gy) = 0;
219
14.1k
    MP_DIGITS(&order) = 0;
220
14.1k
    MP_DIGITS(&irreducible) = 0;
221
14.1k
    MP_DIGITS(&a) = 0;
222
14.1k
    MP_DIGITS(&b) = 0;
223
14.1k
    CHECK_MPI_OK(mp_init(&Px));
224
14.1k
    CHECK_MPI_OK(mp_init(&Py));
225
14.1k
    CHECK_MPI_OK(mp_init(&Qx));
226
14.1k
    CHECK_MPI_OK(mp_init(&Qy));
227
14.1k
    CHECK_MPI_OK(mp_init(&Gx));
228
14.1k
    CHECK_MPI_OK(mp_init(&Gy));
229
14.1k
    CHECK_MPI_OK(mp_init(&order));
230
14.1k
    CHECK_MPI_OK(mp_init(&irreducible));
231
14.1k
    CHECK_MPI_OK(mp_init(&a));
232
14.1k
    CHECK_MPI_OK(mp_init(&b));
233
234
14.1k
    if ((k2 != NULL) && (pointP != NULL)) {
235
        /* Initialize Px and Py */
236
7.68k
        CHECK_MPI_OK(mp_read_unsigned_octets(&Px, pointP->data + 1, (mp_size)len));
237
7.68k
        CHECK_MPI_OK(mp_read_unsigned_octets(&Py, pointP->data + 1 + len, (mp_size)len));
238
7.68k
    }
239
240
    /* construct from named params, if possible */
241
14.1k
    if (params->name != ECCurve_noName) {
242
14.1k
        group = ECGroup_fromName(params->name);
243
14.1k
    }
244
245
14.1k
    if (group == NULL)
246
0
        goto cleanup;
247
248
14.1k
    if ((k2 != NULL) && (pointP != NULL)) {
249
7.68k
        CHECK_MPI_OK(ECPoints_mul(group, k1, k2, &Px, &Py, &Qx, &Qy));
250
7.68k
    } else {
251
6.47k
        CHECK_MPI_OK(ECPoints_mul(group, k1, NULL, NULL, NULL, &Qx, &Qy));
252
6.47k
    }
253
254
    /* our ECC codes uses large stack variables to store intermediate results,
255
     * clear our stack before returning to prevent CSP leakage */
256
14.1k
    BLAPI_CLEAR_STACK(2048)
257
258
    /* Construct the SECItem representation of point Q */
259
14.1k
    pointQ->data[0] = EC_POINT_FORM_UNCOMPRESSED;
260
14.1k
    CHECK_MPI_OK(mp_to_fixlen_octets(&Qx, pointQ->data + 1,
261
14.1k
                                     (mp_size)len));
262
14.1k
    CHECK_MPI_OK(mp_to_fixlen_octets(&Qy, pointQ->data + 1 + len,
263
14.1k
                                     (mp_size)len));
264
265
14.1k
    rv = SECSuccess;
266
267
#if EC_DEBUG
268
    printf("ec_points_mul: pointQ [len=%d]:", pointQ->len);
269
    for (i = 0; i < pointQ->len; i++)
270
        printf("%02x:", pointQ->data[i]);
271
    printf("\n");
272
#endif
273
274
14.1k
cleanup:
275
14.1k
    ECGroup_free(group);
276
14.1k
    mp_clear(&Px);
277
14.1k
    mp_clear(&Py);
278
14.1k
    mp_clear(&Qx);
279
14.1k
    mp_clear(&Qy);
280
14.1k
    mp_clear(&Gx);
281
14.1k
    mp_clear(&Gy);
282
14.1k
    mp_clear(&order);
283
14.1k
    mp_clear(&irreducible);
284
14.1k
    mp_clear(&a);
285
14.1k
    mp_clear(&b);
286
14.1k
    if (err) {
287
0
        MP_TO_SEC_ERROR(err);
288
0
        rv = SECFailure;
289
0
    }
290
291
14.1k
    return rv;
292
14.1k
}
293
294
/* Generates a new EC key pair. The private key is a supplied
295
 * value and the public key is the result of performing a scalar
296
 * point multiplication of that value with the curve's base point.
297
 */
298
SECStatus
299
ec_NewKey(ECParams *ecParams, ECPrivateKey **privKey,
300
          const unsigned char *privKeyBytes, int privKeyLen)
301
34.8k
{
302
34.8k
    SECStatus rv = SECFailure;
303
34.8k
    PLArenaPool *arena;
304
34.8k
    ECPrivateKey *key;
305
34.8k
    mp_int k;
306
34.8k
    mp_err err = MP_OKAY;
307
34.8k
    int len;
308
309
#if EC_DEBUG
310
    printf("ec_NewKey called\n");
311
#endif
312
34.8k
    MP_DIGITS(&k) = 0;
313
314
34.8k
    if (!ecParams || ecParams->name == ECCurve_noName ||
315
34.8k
        !privKey || !privKeyBytes || privKeyLen <= 0) {
316
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
317
0
        return SECFailure;
318
0
    }
319
320
    /* Initialize an arena for the EC key. */
321
34.8k
    if (!(arena = PORT_NewArena(NSS_FREEBL_DEFAULT_CHUNKSIZE)))
322
0
        return SECFailure;
323
324
34.8k
    key = (ECPrivateKey *)PORT_ArenaZAlloc(arena, sizeof(ECPrivateKey));
325
34.8k
    if (!key) {
326
0
        PORT_FreeArena(arena, PR_TRUE);
327
0
        return SECFailure;
328
0
    }
329
330
    /* Set the version number (SEC 1 section C.4 says it should be 1) */
331
34.8k
    SECITEM_AllocItem(arena, &key->version, 1);
332
34.8k
    key->version.data[0] = 1;
333
334
    /* Copy all of the fields from the ECParams argument to the
335
     * ECParams structure within the private key.
336
     */
337
34.8k
    key->ecParams.arena = arena;
338
34.8k
    key->ecParams.type = ecParams->type;
339
34.8k
    key->ecParams.fieldID.size = ecParams->fieldID.size;
340
34.8k
    key->ecParams.fieldID.type = ecParams->fieldID.type;
341
34.8k
    if (ecParams->fieldID.type == ec_field_GFp ||
342
34.8k
        ecParams->fieldID.type == ec_field_plain) {
343
34.8k
        CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.fieldID.u.prime,
344
34.8k
                                      &ecParams->fieldID.u.prime));
345
34.8k
    } else {
346
0
        CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.fieldID.u.poly,
347
0
                                      &ecParams->fieldID.u.poly));
348
0
    }
349
34.8k
    key->ecParams.fieldID.k1 = ecParams->fieldID.k1;
350
34.8k
    key->ecParams.fieldID.k2 = ecParams->fieldID.k2;
351
34.8k
    key->ecParams.fieldID.k3 = ecParams->fieldID.k3;
352
34.8k
    CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.curve.a,
353
34.8k
                                  &ecParams->curve.a));
354
34.8k
    CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.curve.b,
355
34.8k
                                  &ecParams->curve.b));
356
34.8k
    CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.curve.seed,
357
34.8k
                                  &ecParams->curve.seed));
358
34.8k
    CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.base,
359
34.8k
                                  &ecParams->base));
360
34.8k
    CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.order,
361
34.8k
                                  &ecParams->order));
362
34.8k
    key->ecParams.cofactor = ecParams->cofactor;
363
34.8k
    CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.DEREncoding,
364
34.8k
                                  &ecParams->DEREncoding));
365
34.8k
    key->ecParams.name = ecParams->name;
366
34.8k
    CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.curveOID,
367
34.8k
                                  &ecParams->curveOID));
368
369
34.8k
    SECITEM_AllocItem(arena, &key->publicValue, EC_GetPointSize(ecParams));
370
34.8k
    len = ecParams->order.len;
371
34.8k
    SECITEM_AllocItem(arena, &key->privateValue, len);
372
373
    /* Copy private key */
374
34.8k
    if (privKeyLen >= len) {
375
34.8k
        memcpy(key->privateValue.data, privKeyBytes, len);
376
34.8k
    } else {
377
0
        memset(key->privateValue.data, 0, (len - privKeyLen));
378
0
        memcpy(key->privateValue.data + (len - privKeyLen), privKeyBytes, privKeyLen);
379
0
    }
380
381
    /* Compute corresponding public key */
382
383
    /* Use curve specific code for point multiplication */
384
385
34.8k
    if (ecParams->name == ECCurve_Ed25519) {
386
0
        rv = ED_DerivePublicKey(&key->privateValue, &key->publicValue);
387
0
        if (rv != SECSuccess) {
388
0
            goto cleanup;
389
0
        }
390
0
        NSS_DECLASSIFY(key->publicValue.data, key->publicValue.len); /* Declassifying public key to avoid false positive */
391
0
        goto done;
392
0
    }
393
394
34.8k
    if (ecParams->fieldID.type == ec_field_plain) {
395
28.3k
        const ECMethod *method = ec_get_method_from_name(ecParams->name);
396
28.3k
        if (method == NULL || method->pt_mul == NULL) {
397
            /* unknown curve */
398
0
            rv = SECFailure;
399
0
            goto cleanup;
400
0
        }
401
28.3k
        rv = method->pt_mul(&key->publicValue, &key->privateValue, NULL);
402
28.3k
        NSS_DECLASSIFY(key->publicValue.data, key->publicValue.len); /* Declassifying public key to avoid false positive */
403
28.3k
        if (rv != SECSuccess) {
404
0
            goto cleanup;
405
28.3k
        } else {
406
28.3k
            goto done;
407
28.3k
        }
408
28.3k
    }
409
410
6.47k
    CHECK_MPI_OK(mp_init(&k));
411
6.47k
    CHECK_MPI_OK(mp_read_unsigned_octets(&k, key->privateValue.data,
412
6.47k
                                         (mp_size)len));
413
414
6.47k
    rv = ec_points_mul(ecParams, &k, NULL, NULL, &(key->publicValue));
415
6.47k
    NSS_DECLASSIFY(key->publicValue.data, key->publicValue.len); /* Declassifying public key to avoid false positive */
416
6.47k
    if (rv != SECSuccess) {
417
0
        goto cleanup;
418
0
    }
419
420
34.8k
done:
421
34.8k
    *privKey = key;
422
423
34.8k
cleanup:
424
34.8k
    mp_clear(&k);
425
34.8k
    if (rv) {
426
0
        PORT_FreeArena(arena, PR_TRUE);
427
0
    }
428
429
#if EC_DEBUG
430
    printf("ec_NewKey returning %s\n",
431
           (rv == SECSuccess) ? "success" : "failure");
432
#endif
433
434
34.8k
    return rv;
435
34.8k
}
436
437
/* Generates a new EC key pair. The private key is a supplied
438
 * random value (in seed) and the public key is the result of
439
 * performing a scalar point multiplication of that value with
440
 * the curve's base point.
441
 */
442
SECStatus
443
EC_NewKeyFromSeed(ECParams *ecParams, ECPrivateKey **privKey,
444
                  const unsigned char *seed, int seedlen)
445
0
{
446
0
    SECStatus rv = SECFailure;
447
0
    rv = ec_NewKey(ecParams, privKey, seed, seedlen);
448
0
    return rv;
449
0
}
450
451
/* Generate a random private key using the algorithm A.4.1 or A.4.2 of ANSI X9.62,
452
 * modified a la FIPS 186-2 Change Notice 1 to eliminate the bias in the
453
 * random number generator.
454
 */
455
456
SECStatus
457
ec_GenerateRandomPrivateKey(ECParams *ecParams, SECItem *privKey)
458
36.1k
{
459
36.1k
    SECStatus rv = SECFailure;
460
461
36.1k
    unsigned int len = EC_GetScalarSize(ecParams);
462
463
36.1k
    if (privKey->len != len || privKey->data == NULL) {
464
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
465
0
        return SECFailure;
466
0
    }
467
468
36.1k
    const ECMethod *method = ec_get_method_from_name(ecParams->name);
469
36.1k
    if (method == NULL || method->scalar_validate == NULL) {
470
0
        PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE);
471
0
        return SECFailure;
472
0
    }
473
474
36.1k
    uint8_t leading_coeff_mask;
475
36.1k
    switch (ecParams->name) {
476
0
        case ECCurve_Ed25519:
477
20.8k
        case ECCurve25519:
478
29.6k
        case ECCurve_NIST_P256:
479
35.1k
        case ECCurve_NIST_P384:
480
35.1k
            leading_coeff_mask = 0xff;
481
35.1k
            break;
482
964
        case ECCurve_NIST_P521:
483
964
            leading_coeff_mask = 0x01;
484
964
            break;
485
0
        default:
486
0
            PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE);
487
0
            return SECFailure;
488
36.1k
    }
489
490
    /* The rejection sampling method from FIPS 186-5 A.4.2 */
491
36.1k
    int count = 100;
492
36.1k
    do {
493
36.1k
        rv = RNG_GenerateGlobalRandomBytes(privKey->data, len);
494
36.1k
        if (rv != SECSuccess) {
495
0
            PORT_SetError(SEC_ERROR_NEED_RANDOM);
496
0
            return SECFailure;
497
0
        }
498
36.1k
        privKey->data[0] &= leading_coeff_mask;
499
36.1k
        NSS_CLASSIFY(privKey->data, privKey->len);
500
36.1k
        rv = method->scalar_validate(privKey);
501
36.1k
    } while (rv != SECSuccess && --count > 0);
502
503
36.1k
    if (rv != SECSuccess) { // implies count == 0
504
0
        PORT_SetError(SEC_ERROR_BAD_KEY);
505
0
    }
506
507
36.1k
    return rv;
508
36.1k
}
509
510
/* Generates a new EC key pair. The private key is a random value and
511
 * the public key is the result of performing a scalar point multiplication
512
 * of that value with the curve's base point.
513
 */
514
SECStatus
515
EC_NewKey(ECParams *ecParams, ECPrivateKey **privKey)
516
34.8k
{
517
34.8k
    SECStatus rv = SECFailure;
518
34.8k
    SECItem privKeyRand = { siBuffer, NULL, 0 };
519
520
34.8k
    if (!ecParams || ecParams->name == ECCurve_noName || !privKey) {
521
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
522
0
        return SECFailure;
523
0
    }
524
525
34.8k
    SECITEM_AllocItem(NULL, &privKeyRand, EC_GetScalarSize(ecParams));
526
34.8k
    if (privKeyRand.data == NULL) {
527
0
        PORT_SetError(SEC_ERROR_NO_MEMORY);
528
0
        rv = SECFailure;
529
0
        goto cleanup;
530
0
    }
531
34.8k
    rv = ec_GenerateRandomPrivateKey(ecParams, &privKeyRand);
532
34.8k
    if (rv != SECSuccess || privKeyRand.data == NULL) {
533
0
        goto cleanup;
534
0
    }
535
    /* generate public key */
536
34.8k
    CHECK_SEC_OK(ec_NewKey(ecParams, privKey, privKeyRand.data, privKeyRand.len));
537
538
34.8k
cleanup:
539
34.8k
    if (privKeyRand.data) {
540
34.8k
        SECITEM_ZfreeItem(&privKeyRand, PR_FALSE);
541
34.8k
    }
542
#if EC_DEBUG
543
    printf("EC_NewKey returning %s\n",
544
           (rv == SECSuccess) ? "success" : "failure");
545
#endif
546
547
34.8k
    return rv;
548
34.8k
}
549
550
/* Validates an EC public key as described in Section 5.2.2 of
551
 * X9.62. The ECDH primitive when used without the cofactor does
552
 * not address small subgroup attacks, which may occur when the
553
 * public key is not valid. These attacks can be prevented by
554
 * validating the public key before using ECDH.
555
 */
556
SECStatus
557
EC_ValidatePublicKey(ECParams *ecParams, SECItem *publicValue)
558
81.6k
{
559
81.6k
    mp_int Px, Py;
560
81.6k
    ECGroup *group = NULL;
561
81.6k
    SECStatus rv = SECFailure;
562
81.6k
    mp_err err = MP_OKAY;
563
81.6k
    unsigned int len;
564
565
81.6k
    if (!ecParams || ecParams->name == ECCurve_noName ||
566
81.6k
        !publicValue || !publicValue->len) {
567
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
568
0
        rv = SECFailure;
569
0
        return rv;
570
0
    }
571
572
    /* Uses curve specific code for point validation. */
573
81.6k
    if (ecParams->fieldID.type == ec_field_plain) {
574
61.9k
        const ECMethod *method = ec_get_method_from_name(ecParams->name);
575
61.9k
        if (method == NULL || method->pt_validate == NULL) {
576
            /* unknown curve */
577
0
            PORT_SetError(SEC_ERROR_INVALID_ARGS);
578
0
            rv = SECFailure;
579
0
            return rv;
580
0
        }
581
61.9k
        rv = method->pt_validate(publicValue);
582
61.9k
        if (rv != SECSuccess) {
583
343
            PORT_SetError(SEC_ERROR_BAD_KEY);
584
343
        }
585
61.9k
        return rv;
586
61.9k
    }
587
588
    /* NOTE: We only support uncompressed points for now */
589
19.7k
    len = (((unsigned int)ecParams->fieldID.size) + 7) >> 3;
590
19.7k
    if (publicValue->data[0] != EC_POINT_FORM_UNCOMPRESSED) {
591
21
        PORT_SetError(SEC_ERROR_UNSUPPORTED_EC_POINT_FORM);
592
21
        return SECFailure;
593
19.7k
    } else if (publicValue->len != (2 * len + 1)) {
594
30
        PORT_SetError(SEC_ERROR_BAD_KEY);
595
30
        return SECFailure;
596
30
    }
597
598
19.6k
    MP_DIGITS(&Px) = 0;
599
19.6k
    MP_DIGITS(&Py) = 0;
600
19.6k
    CHECK_MPI_OK(mp_init(&Px));
601
19.6k
    CHECK_MPI_OK(mp_init(&Py));
602
603
    /* Initialize Px and Py */
604
19.6k
    CHECK_MPI_OK(mp_read_unsigned_octets(&Px, publicValue->data + 1, (mp_size)len));
605
19.6k
    CHECK_MPI_OK(mp_read_unsigned_octets(&Py, publicValue->data + 1 + len, (mp_size)len));
606
607
    /* construct from named params */
608
19.6k
    group = ECGroup_fromName(ecParams->name);
609
19.6k
    if (group == NULL) {
610
        /*
611
         * ECGroup_fromName fails if ecParams->name is not a valid
612
         * ECCurveName value, or if we run out of memory, or perhaps
613
         * for other reasons.  Unfortunately if ecParams->name is a
614
         * valid ECCurveName value, we don't know what the right error
615
         * code should be because ECGroup_fromName doesn't return an
616
         * error code to the caller.  Set err to MP_UNDEF because
617
         * that's what ECGroup_fromName uses internally.
618
         */
619
0
        if ((ecParams->name <= ECCurve_noName) ||
620
0
            (ecParams->name >= ECCurve_pastLastCurve)) {
621
0
            err = MP_BADARG;
622
0
        } else {
623
0
            err = MP_UNDEF;
624
0
        }
625
0
        goto cleanup;
626
0
    }
627
628
    /* validate public point */
629
19.6k
    if ((err = ECPoint_validate(group, &Px, &Py)) < MP_YES) {
630
5.50k
        if (err == MP_NO) {
631
5.50k
            PORT_SetError(SEC_ERROR_BAD_KEY);
632
5.50k
            rv = SECFailure;
633
5.50k
            err = MP_OKAY; /* don't change the error code */
634
5.50k
        }
635
5.50k
        goto cleanup;
636
5.50k
    }
637
638
14.1k
    rv = SECSuccess;
639
640
19.6k
cleanup:
641
19.6k
    ECGroup_free(group);
642
19.6k
    mp_clear(&Px);
643
19.6k
    mp_clear(&Py);
644
645
19.6k
    if (err) {
646
0
        MP_TO_SEC_ERROR(err);
647
0
        rv = SECFailure;
648
0
    }
649
19.6k
    return rv;
650
19.6k
}
651
652
/*
653
** Performs an ECDH key derivation by computing the scalar point
654
** multiplication of privateValue and publicValue (with or without the
655
** cofactor) and returns the x-coordinate of the resulting elliptic
656
** curve point in derived secret.  If successful, derivedSecret->data
657
** is set to the address of the newly allocated buffer containing the
658
** derived secret, and derivedSecret->len is the size of the secret
659
** produced. It is the caller's responsibility to free the allocated
660
** buffer containing the derived secret.
661
*/
662
SECStatus
663
ECDH_Derive(SECItem *publicValue,
664
            ECParams *ecParams,
665
            SECItem *privateValue,
666
            PRBool withCofactor,
667
            SECItem *derivedSecret)
668
42.7k
{
669
42.7k
    SECStatus rv = SECFailure;
670
42.7k
    unsigned int len = 0;
671
42.7k
    mp_err err = MP_OKAY;
672
673
42.7k
    if (!publicValue || !publicValue->len ||
674
42.7k
        !ecParams || ecParams->name == ECCurve_noName ||
675
42.7k
        !privateValue || !privateValue->len || !derivedSecret) {
676
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
677
0
        rv = SECFailure;
678
0
        return rv;
679
0
    }
680
681
    /*
682
     * Make sure the point is on the requested curve to avoid
683
     * certain small subgroup attacks.
684
     */
685
42.7k
    if (EC_ValidatePublicKey(ecParams, publicValue) != SECSuccess) {
686
3.20k
        PORT_SetError(SEC_ERROR_BAD_KEY);
687
3.20k
        rv = SECFailure;
688
3.20k
        return rv;
689
3.20k
    }
690
691
    /* Perform curve specific multiplication using ECMethod */
692
39.5k
    if (ecParams->fieldID.type == ec_field_plain) {
693
32.9k
        const ECMethod *method;
694
32.9k
        memset(derivedSecret, 0, sizeof(*derivedSecret));
695
32.9k
        derivedSecret = SECITEM_AllocItem(NULL, derivedSecret, EC_GetScalarSize(ecParams));
696
32.9k
        if (derivedSecret == NULL) {
697
0
            PORT_SetError(SEC_ERROR_NO_MEMORY);
698
0
            rv = SECFailure;
699
0
            return rv;
700
0
        }
701
32.9k
        method = ec_get_method_from_name(ecParams->name);
702
32.9k
        if (method == NULL || method->pt_validate == NULL ||
703
32.9k
            method->pt_mul == NULL) {
704
0
            PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE);
705
0
            rv = SECFailure;
706
0
            goto done;
707
0
        }
708
32.9k
        rv = method->pt_mul(derivedSecret, privateValue, publicValue);
709
32.9k
        if (rv != SECSuccess) {
710
1
            PORT_SetError(SEC_ERROR_BAD_KEY);
711
1
        }
712
32.9k
        goto done;
713
32.9k
    }
714
715
6.60k
    SECItem pointQ = { siBuffer, NULL, 0 };
716
6.60k
    mp_int k; /* to hold the private value */
717
#if EC_DEBUG
718
    int i;
719
#endif
720
721
    /*
722
     * We fail if the public value is the point at infinity, since
723
     * this produces predictable results.
724
     */
725
6.60k
    if (ec_point_at_infinity(publicValue)) {
726
0
        PORT_SetError(SEC_ERROR_BAD_KEY);
727
0
        return SECFailure;
728
0
    }
729
730
6.60k
    MP_DIGITS(&k) = 0;
731
6.60k
    memset(derivedSecret, 0, sizeof *derivedSecret);
732
6.60k
    len = (ecParams->fieldID.size + 7) >> 3;
733
6.60k
    pointQ.len = EC_GetPointSize(ecParams);
734
6.60k
    if ((pointQ.data = PORT_Alloc(pointQ.len)) == NULL)
735
0
        goto cleanup;
736
737
6.60k
    CHECK_MPI_OK(mp_init(&k));
738
6.60k
    CHECK_MPI_OK(mp_read_unsigned_octets(&k, privateValue->data,
739
6.60k
                                         (mp_size)privateValue->len));
740
741
6.60k
    if (withCofactor && (ecParams->cofactor != 1)) {
742
0
        mp_int cofactor;
743
        /* multiply k with the cofactor */
744
0
        MP_DIGITS(&cofactor) = 0;
745
0
        CHECK_MPI_OK(mp_init(&cofactor));
746
0
        mp_set(&cofactor, ecParams->cofactor);
747
0
        CHECK_MPI_OK(mp_mul(&k, &cofactor, &k));
748
0
        mp_clear(&cofactor);
749
0
    }
750
751
    /* Multiply our private key and peer's public point */
752
6.60k
    if (ec_points_mul(ecParams, NULL, &k, publicValue, &pointQ) != SECSuccess) {
753
0
        goto cleanup;
754
0
    }
755
6.60k
    if (ec_point_at_infinity(&pointQ)) {
756
0
        PORT_SetError(SEC_ERROR_BAD_KEY); /* XXX better error code? */
757
0
        goto cleanup;
758
0
    }
759
760
    /* Allocate memory for the derived secret and copy
761
     * the x co-ordinate of pointQ into it.
762
     */
763
6.60k
    SECITEM_AllocItem(NULL, derivedSecret, len);
764
6.60k
    memcpy(derivedSecret->data, pointQ.data + 1, len);
765
766
6.60k
    rv = SECSuccess;
767
768
#if EC_DEBUG
769
    printf("derived_secret:\n");
770
    for (i = 0; i < derivedSecret->len; i++)
771
        printf("%02x:", derivedSecret->data[i]);
772
    printf("\n");
773
#endif
774
775
6.60k
cleanup:
776
6.60k
    mp_clear(&k);
777
778
6.60k
    if (pointQ.data) {
779
6.60k
        PORT_ZFree(pointQ.data, pointQ.len);
780
6.60k
    }
781
782
39.5k
done:
783
784
39.5k
    if (err) {
785
0
        MP_TO_SEC_ERROR(err);
786
0
    }
787
39.5k
    if (rv != SECSuccess) {
788
1
        SECITEM_ZfreeItem(derivedSecret, PR_FALSE);
789
1
    }
790
39.5k
    return rv;
791
39.5k
}
792
793
/* Computes the ECDSA signature (a concatenation of two values r and s)
794
 * on the digest using the given key and the random value kb (used in
795
 * computing s).
796
 */
797
798
static SECStatus
799
ec_SignDigestWithSeed(ECPrivateKey *key, SECItem *signature,
800
                      const SECItem *digest, const unsigned char *kb, const int kblen)
801
1.30k
{
802
1.30k
    SECStatus rv = SECFailure;
803
1.30k
    ECParams *ecParams = NULL;
804
1.30k
    mp_err err = MP_OKAY;
805
1.30k
    int flen = 0;  /* length in bytes of the field size */
806
1.30k
    unsigned olen; /* length in bytes of the base point order */
807
808
    /* Check args */
809
1.30k
    if (!key || !signature || !digest || !kb || (kblen <= 0)) {
810
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
811
0
        rv = SECFailure;
812
0
        goto done;
813
0
    }
814
815
1.30k
    ecParams = &(key->ecParams);
816
1.30k
    flen = (ecParams->fieldID.size + 7) >> 3;
817
1.30k
    olen = ecParams->order.len;
818
1.30k
    if (signature->data == NULL) {
819
        /* a call to get the signature length only */
820
0
        signature->len = 2 * olen;
821
0
        rv = SECSuccess;
822
0
        goto done;
823
0
    }
824
1.30k
    if (signature->len < 2 * olen) {
825
0
        PORT_SetError(SEC_ERROR_OUTPUT_LEN);
826
0
        rv = SECFailure;
827
0
        goto done;
828
0
    }
829
830
    /* Perform curve specific signature using ECMethod */
831
1.30k
    if (ecParams->fieldID.type == ec_field_plain) {
832
1.30k
        const ECMethod *method = ec_get_method_from_name(ecParams->name);
833
1.30k
        if (method == NULL || method->sign_digest == NULL) {
834
0
            PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE);
835
0
            rv = SECFailure;
836
0
            goto done;
837
0
        }
838
1.30k
        rv = method->sign_digest(key, signature, digest, kb, kblen);
839
1.30k
        if (rv != SECSuccess) {
840
0
            PORT_SetError(SEC_ERROR_INVALID_ARGS);
841
0
        }
842
1.30k
        goto done;
843
1.30k
    }
844
845
0
    mp_int x1;
846
0
    mp_int d, k; /* private key, random integer */
847
0
    mp_int r, s; /* tuple (r, s) is the signature */
848
0
    mp_int t;    /* holding tmp values */
849
0
    mp_int n;
850
0
    mp_int ar; /* blinding value */
851
0
    SECItem kGpoint = { siBuffer, NULL, 0 };
852
0
    unsigned char *t2 = NULL;
853
0
    unsigned obits; /* length in bits  of the base point order */
854
855
#if EC_DEBUG
856
    char mpstr[256];
857
#endif
858
859
    /* Initialize MPI integers. */
860
    /* must happen before the first potential call to cleanup */
861
0
    MP_DIGITS(&x1) = 0;
862
0
    MP_DIGITS(&d) = 0;
863
0
    MP_DIGITS(&k) = 0;
864
0
    MP_DIGITS(&r) = 0;
865
0
    MP_DIGITS(&s) = 0;
866
0
    MP_DIGITS(&n) = 0;
867
0
    MP_DIGITS(&t) = 0;
868
0
    MP_DIGITS(&ar) = 0;
869
870
0
    CHECK_MPI_OK(mp_init(&x1));
871
0
    CHECK_MPI_OK(mp_init(&d));
872
0
    CHECK_MPI_OK(mp_init(&k));
873
0
    CHECK_MPI_OK(mp_init(&r));
874
0
    CHECK_MPI_OK(mp_init(&s));
875
0
    CHECK_MPI_OK(mp_init(&n));
876
0
    CHECK_MPI_OK(mp_init(&t));
877
0
    CHECK_MPI_OK(mp_init(&ar));
878
879
0
    SECITEM_TO_MPINT(ecParams->order, &n);
880
0
    SECITEM_TO_MPINT(key->privateValue, &d);
881
882
0
    CHECK_MPI_OK(mp_read_unsigned_octets(&k, kb, kblen));
883
    /* Make sure k is in the interval [1, n-1] */
884
0
    if ((mp_cmp_z(&k) <= 0) || (mp_cmp(&k, &n) >= 0)) {
885
#if EC_DEBUG
886
        printf("k is outside [1, n-1]\n");
887
        mp_tohex(&k, mpstr);
888
        printf("k : %s \n", mpstr);
889
        mp_tohex(&n, mpstr);
890
        printf("n : %s \n", mpstr);
891
#endif
892
0
        PORT_SetError(SEC_ERROR_NEED_RANDOM);
893
0
        goto cleanup;
894
0
    }
895
896
    /*
897
    ** ANSI X9.62, Section 5.3.2, Step 2
898
    **
899
    ** Compute kG
900
    */
901
0
    kGpoint.len = EC_GetPointSize(ecParams);
902
0
    kGpoint.data = PORT_Alloc(kGpoint.len);
903
0
    if ((kGpoint.data == NULL) ||
904
0
        (ec_points_mul(ecParams, &k, NULL, NULL, &kGpoint) != SECSuccess))
905
0
        goto cleanup;
906
0
    NSS_DECLASSIFY(kGpoint.data, kGpoint.len); /* Declassifying the r component */
907
    /*
908
    ** ANSI X9.62, Section 5.3.3, Step 1
909
    **
910
    ** Extract the x co-ordinate of kG into x1
911
    */
912
0
    CHECK_MPI_OK(mp_read_unsigned_octets(&x1, kGpoint.data + 1,
913
0
                                         (mp_size)flen));
914
915
    /*
916
    ** ANSI X9.62, Section 5.3.3, Step 2
917
    **
918
    ** r = x1 mod n  NOTE: n is the order of the curve
919
    */
920
0
    CHECK_MPI_OK(mp_mod(&x1, &n, &r));
921
922
    /*
923
    ** ANSI X9.62, Section 5.3.3, Step 3
924
    **
925
    ** verify r != 0
926
    */
927
0
    if (mp_cmp_z(&r) == 0) {
928
0
        PORT_SetError(SEC_ERROR_NEED_RANDOM);
929
0
        goto cleanup;
930
0
    }
931
932
    /*
933
    ** ANSI X9.62, Section 5.3.3, Step 4
934
    **
935
    ** s = (k**-1 * (HASH(M) + d*r)) mod n
936
    */
937
0
    SECITEM_TO_MPINT(*digest, &s); /* s = HASH(M)     */
938
939
    /* In the definition of EC signing, digests are truncated
940
     * to the length of n in bits.
941
     * (see SEC 1 "Elliptic Curve Digit Signature Algorithm" section 4.1.*/
942
0
    CHECK_MPI_OK((obits = mpl_significant_bits(&n)));
943
0
    if (digest->len * 8 > obits) {
944
0
        mpl_rsh(&s, &s, digest->len * 8 - obits);
945
0
    }
946
947
#if EC_DEBUG
948
    mp_todecimal(&n, mpstr);
949
    printf("n : %s (dec)\n", mpstr);
950
    mp_todecimal(&d, mpstr);
951
    printf("d : %s (dec)\n", mpstr);
952
    mp_tohex(&x1, mpstr);
953
    printf("x1: %s\n", mpstr);
954
    mp_todecimal(&s, mpstr);
955
    printf("digest: %s (decimal)\n", mpstr);
956
    mp_todecimal(&r, mpstr);
957
    printf("r : %s (dec)\n", mpstr);
958
    mp_tohex(&r, mpstr);
959
    printf("r : %s\n", mpstr);
960
#endif
961
962
0
    if ((t2 = PORT_Alloc(2 * ecParams->order.len)) == NULL) {
963
0
        rv = SECFailure;
964
0
        goto cleanup;
965
0
    }
966
0
    if (RNG_GenerateGlobalRandomBytes(t2, 2 * ecParams->order.len) != SECSuccess) {
967
0
        PORT_SetError(SEC_ERROR_NEED_RANDOM);
968
0
        rv = SECFailure;
969
0
        goto cleanup;
970
0
    }
971
0
    CHECK_MPI_OK(mp_read_unsigned_octets(&t, t2, 2 * ecParams->order.len)); /* t <-$ Zn */
972
0
    PORT_Memset(t2, 0, 2 * ecParams->order.len);
973
0
    if (RNG_GenerateGlobalRandomBytes(t2, 2 * ecParams->order.len) != SECSuccess) {
974
0
        PORT_SetError(SEC_ERROR_NEED_RANDOM);
975
0
        rv = SECFailure;
976
0
        goto cleanup;
977
0
    }
978
0
    CHECK_MPI_OK(mp_read_unsigned_octets(&ar, t2, 2 * ecParams->order.len)); /* ar <-$ Zn */
979
980
    /* Using mp_invmod on k directly would leak bits from k. */
981
0
    CHECK_MPI_OK(mp_mul(&k, &ar, &k));                              /* k = k * ar */
982
0
    NSS_DECLASSIFY(MP_DIGITS(&k), MP_ALLOC(&k) * sizeof(mp_digit)); /* declassifying k here because it is masked by multiplying with ar */
983
0
    CHECK_MPI_OK(mp_mulmod(&k, &t, &n, &k));                        /* k = k * t mod n */
984
0
    CHECK_MPI_OK(mp_invmod(&k, &n, &k));                            /* k = k**-1 mod n */
985
0
    CHECK_MPI_OK(mp_mulmod(&k, &t, &n, &k));                        /* k = k * t mod n */
986
    /* To avoid leaking secret bits here the addition is blinded. */
987
0
    CHECK_MPI_OK(mp_mul(&d, &ar, &t));                              /* t = d * ar */
988
0
    NSS_DECLASSIFY(MP_DIGITS(&t), MP_ALLOC(&t) * sizeof(mp_digit)); /* declassifying d here because it is masked by multiplying with ar */
989
0
    CHECK_MPI_OK(mp_mulmod(&t, &r, &n, &d));                        /* d = t * r mod n */
990
0
    CHECK_MPI_OK(mp_mulmod(&s, &ar, &n, &t));                       /* t = s * ar mod n */
991
0
    CHECK_MPI_OK(mp_add(&t, &d, &s));                               /* s = t + d */
992
0
    CHECK_MPI_OK(mp_mulmod(&s, &k, &n, &s));                        /* s = s * k mod n */
993
994
#if EC_DEBUG
995
    mp_todecimal(&s, mpstr);
996
    printf("s : %s (dec)\n", mpstr);
997
    mp_tohex(&s, mpstr);
998
    printf("s : %s\n", mpstr);
999
#endif
1000
1001
    /*
1002
    ** ANSI X9.62, Section 5.3.3, Step 5
1003
    **
1004
    ** verify s != 0
1005
    */
1006
0
    if (mp_cmp_z(&s) == 0) {
1007
0
        PORT_SetError(SEC_ERROR_NEED_RANDOM);
1008
0
        goto cleanup;
1009
0
    }
1010
1011
    /*
1012
    **
1013
    ** Signature is tuple (r, s)
1014
    */
1015
0
    CHECK_MPI_OK(mp_to_fixlen_octets(&r, signature->data, olen));
1016
0
    CHECK_MPI_OK(mp_to_fixlen_octets(&s, signature->data + olen, olen));
1017
1018
0
    signature->len = 2 * olen;
1019
0
    rv = SECSuccess;
1020
0
    err = MP_OKAY;
1021
1022
0
cleanup:
1023
0
    mp_clear(&x1);
1024
0
    mp_clear(&d);
1025
0
    mp_clear(&k);
1026
0
    mp_clear(&r);
1027
0
    mp_clear(&s);
1028
0
    mp_clear(&n);
1029
0
    mp_clear(&t);
1030
0
    mp_clear(&ar);
1031
1032
0
    if (t2) {
1033
0
        PORT_ZFree(t2, 2 * ecParams->order.len);
1034
0
    }
1035
1036
0
    if (kGpoint.data) {
1037
0
        PORT_ZFree(kGpoint.data, kGpoint.len);
1038
0
    }
1039
1040
1.30k
done:
1041
1.30k
    if (err) {
1042
0
        MP_TO_SEC_ERROR(err);
1043
0
        rv = SECFailure;
1044
0
    }
1045
1046
#if EC_DEBUG
1047
    printf("ECDSA signing with seed %s\n",
1048
           (rv == SECSuccess) ? "succeeded" : "failed");
1049
#endif
1050
1051
1.30k
    return rv;
1052
1.30k
}
1053
1054
SECStatus
1055
ECDSA_SignDigestWithSeed(ECPrivateKey *key, SECItem *signature,
1056
                         const SECItem *digest, const unsigned char *kb, const int kblen)
1057
1.30k
{
1058
#if EC_DEBUG || EC_DOUBLECHECK
1059
    SECItem *signature2 = SECITEM_AllocItem(NULL, NULL, signature->len);
1060
    SECStatus signSuccess = ec_SignDigestWithSeed(key, signature, digest, kb, kblen);
1061
    SECStatus signSuccessDouble = ec_SignDigestWithSeed(key, signature2, digest, kb, kblen);
1062
    int signaturesEqual = NSS_SecureMemcmp(signature->data, signature2->data, signature->len);
1063
    SECStatus rv;
1064
1065
    if ((signaturesEqual == 0) && (signSuccess == SECSuccess) && (signSuccessDouble == SECSuccess)) {
1066
        rv = SECSuccess;
1067
    } else {
1068
        rv = SECFailure;
1069
    }
1070
1071
#if EC_DEBUG
1072
    printf("ECDSA signing with seed %s after signing twice\n", (rv == SECSuccess) ? "succeeded" : "failed");
1073
#endif
1074
1075
    SECITEM_FreeItem(signature2, PR_TRUE);
1076
    return rv;
1077
#else
1078
1.30k
    return ec_SignDigestWithSeed(key, signature, digest, kb, kblen);
1079
1.30k
#endif
1080
1.30k
}
1081
1082
/*
1083
** Computes the ECDSA signature on the digest using the given key
1084
** and a random seed.
1085
*/
1086
SECStatus
1087
ECDSA_SignDigest(ECPrivateKey *key, SECItem *signature, const SECItem *digest)
1088
1.30k
{
1089
1.30k
    SECStatus rv = SECFailure;
1090
1.30k
    SECItem nonceRand = { siBuffer, NULL, 0 };
1091
1092
1.30k
    if (!key) {
1093
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
1094
0
        return SECFailure;
1095
0
    }
1096
1097
    /* Generate random value k */
1098
1.30k
    SECITEM_AllocItem(NULL, &nonceRand, EC_GetScalarSize(&key->ecParams));
1099
1.30k
    if (nonceRand.data == NULL) {
1100
0
        PORT_SetError(SEC_ERROR_NO_MEMORY);
1101
0
        rv = SECFailure;
1102
0
        goto cleanup;
1103
0
    }
1104
1.30k
    rv = ec_GenerateRandomPrivateKey(&key->ecParams, &nonceRand);
1105
1.30k
    if (rv != SECSuccess || nonceRand.data == NULL)
1106
0
        goto cleanup;
1107
1108
    /* Generate ECDSA signature with the specified k value */
1109
1.30k
    rv = ECDSA_SignDigestWithSeed(key, signature, digest, nonceRand.data, nonceRand.len);
1110
1.30k
    NSS_DECLASSIFY(signature->data, signature->len);
1111
1112
1.30k
cleanup:
1113
1.30k
    if (nonceRand.data) {
1114
1.30k
        SECITEM_ZfreeItem(&nonceRand, PR_FALSE);
1115
1.30k
    }
1116
1117
#if EC_DEBUG
1118
    printf("ECDSA signing %s\n",
1119
           (rv == SECSuccess) ? "succeeded" : "failed");
1120
#endif
1121
1122
1.30k
    return rv;
1123
1.30k
}
1124
1125
/*
1126
** Checks the signature on the given digest using the key provided.
1127
**
1128
** The key argument must represent a valid EC public key (a point on
1129
** the relevant curve).  If it is not a valid point, then the behavior
1130
** of this function is undefined.  In cases where a public key might
1131
** not be valid, use EC_ValidatePublicKey to check.
1132
*/
1133
SECStatus
1134
ECDSA_VerifyDigest(ECPublicKey *key, const SECItem *signature,
1135
                   const SECItem *digest)
1136
1.37k
{
1137
1.37k
    SECStatus rv = SECFailure;
1138
1.37k
    ECParams *ecParams = NULL;
1139
1.37k
    mp_err err = MP_OKAY;
1140
1141
    /* Check args */
1142
1.37k
    if (!key || !signature || !digest) {
1143
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
1144
0
        rv = SECFailure;
1145
0
        goto done;
1146
0
    }
1147
1148
1.37k
    ecParams = &(key->ecParams);
1149
1150
    /* Perform curve specific signature verification using ECMethod */
1151
1.37k
    if (ecParams->fieldID.type == ec_field_plain) {
1152
287
        const ECMethod *method = ec_get_method_from_name(ecParams->name);
1153
287
        if (method == NULL || method->verify_digest == NULL) {
1154
0
            PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE);
1155
0
            rv = SECFailure;
1156
0
            goto done;
1157
0
        }
1158
287
        rv = method->verify_digest(key, signature, digest);
1159
287
        if (rv != SECSuccess) {
1160
287
            PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
1161
287
        }
1162
287
        goto done;
1163
287
    }
1164
1165
1.08k
    mp_int r_, s_;       /* tuple (r', s') is received signature) */
1166
1.08k
    mp_int c, u1, u2, v; /* intermediate values used in verification */
1167
1.08k
    mp_int x1;
1168
1.08k
    mp_int n;
1169
1.08k
    SECItem pointC = { siBuffer, NULL, 0 };
1170
1.08k
    int slen;       /* length in bytes of a half signature (r or s) */
1171
1.08k
    int flen;       /* length in bytes of the field size */
1172
1.08k
    unsigned olen;  /* length in bytes of the base point order */
1173
1.08k
    unsigned obits; /* length in bits  of the base point order */
1174
1175
#if EC_DEBUG
1176
    char mpstr[256];
1177
    printf("ECDSA verification called\n");
1178
#endif
1179
1180
    /* Initialize MPI integers. */
1181
    /* must happen before the first potential call to cleanup */
1182
1.08k
    MP_DIGITS(&r_) = 0;
1183
1.08k
    MP_DIGITS(&s_) = 0;
1184
1.08k
    MP_DIGITS(&c) = 0;
1185
1.08k
    MP_DIGITS(&u1) = 0;
1186
1.08k
    MP_DIGITS(&u2) = 0;
1187
1.08k
    MP_DIGITS(&x1) = 0;
1188
1.08k
    MP_DIGITS(&v) = 0;
1189
1.08k
    MP_DIGITS(&n) = 0;
1190
1191
1.08k
    CHECK_MPI_OK(mp_init(&r_));
1192
1.08k
    CHECK_MPI_OK(mp_init(&s_));
1193
1.08k
    CHECK_MPI_OK(mp_init(&c));
1194
1.08k
    CHECK_MPI_OK(mp_init(&u1));
1195
1.08k
    CHECK_MPI_OK(mp_init(&u2));
1196
1.08k
    CHECK_MPI_OK(mp_init(&x1));
1197
1.08k
    CHECK_MPI_OK(mp_init(&v));
1198
1.08k
    CHECK_MPI_OK(mp_init(&n));
1199
1200
1.08k
    flen = (ecParams->fieldID.size + 7) >> 3;
1201
1.08k
    olen = ecParams->order.len;
1202
1.08k
    if (signature->len == 0 || signature->len % 2 != 0 ||
1203
1.08k
        signature->len > 2 * olen) {
1204
0
        PORT_SetError(SEC_ERROR_INPUT_LEN);
1205
0
        goto cleanup;
1206
0
    }
1207
1.08k
    slen = signature->len / 2;
1208
1209
    /*
1210
     * The incoming point has been verified in sftk_handlePublicKeyObject.
1211
     */
1212
1213
1.08k
    SECITEM_AllocItem(NULL, &pointC, EC_GetPointSize(ecParams));
1214
1.08k
    if (pointC.data == NULL) {
1215
0
        goto cleanup;
1216
0
    }
1217
1218
    /*
1219
    ** Convert received signature (r', s') into MPI integers.
1220
    */
1221
1.08k
    CHECK_MPI_OK(mp_read_unsigned_octets(&r_, signature->data, slen));
1222
1.08k
    CHECK_MPI_OK(mp_read_unsigned_octets(&s_, signature->data + slen, slen));
1223
1224
    /*
1225
    ** ANSI X9.62, Section 5.4.2, Steps 1 and 2
1226
    **
1227
    ** Verify that 0 < r' < n and 0 < s' < n
1228
    */
1229
1.08k
    SECITEM_TO_MPINT(ecParams->order, &n);
1230
1.08k
    if (mp_cmp_z(&r_) <= 0 || mp_cmp_z(&s_) <= 0 ||
1231
1.08k
        mp_cmp(&r_, &n) >= 0 || mp_cmp(&s_, &n) >= 0) {
1232
9
        PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
1233
9
        goto cleanup; /* will return rv == SECFailure */
1234
9
    }
1235
1236
    /*
1237
    ** ANSI X9.62, Section 5.4.2, Step 3
1238
    **
1239
    ** c = (s')**-1 mod n
1240
    */
1241
1.07k
    CHECK_MPI_OK(mp_invmod(&s_, &n, &c)); /* c = (s')**-1 mod n */
1242
1243
    /*
1244
    ** ANSI X9.62, Section 5.4.2, Step 4
1245
    **
1246
    ** u1 = ((HASH(M')) * c) mod n
1247
    */
1248
1.07k
    SECITEM_TO_MPINT(*digest, &u1); /* u1 = HASH(M)     */
1249
1250
    /* In the definition of EC signing, digests are truncated
1251
     * to the length of n in bits.
1252
     * (see SEC 1 "Elliptic Curve Digit Signature Algorithm" section 4.1.*/
1253
1.07k
    CHECK_MPI_OK((obits = mpl_significant_bits(&n)));
1254
1.07k
    if (digest->len * 8 > obits) { /* u1 = HASH(M')     */
1255
126
        mpl_rsh(&u1, &u1, digest->len * 8 - obits);
1256
126
    }
1257
1258
#if EC_DEBUG
1259
    mp_todecimal(&r_, mpstr);
1260
    printf("r_: %s (dec)\n", mpstr);
1261
    mp_todecimal(&s_, mpstr);
1262
    printf("s_: %s (dec)\n", mpstr);
1263
    mp_todecimal(&c, mpstr);
1264
    printf("c : %s (dec)\n", mpstr);
1265
    mp_todecimal(&u1, mpstr);
1266
    printf("digest: %s (dec)\n", mpstr);
1267
#endif
1268
1269
1.07k
    CHECK_MPI_OK(mp_mulmod(&u1, &c, &n, &u1)); /* u1 = u1 * c mod n */
1270
1271
    /*
1272
    ** ANSI X9.62, Section 5.4.2, Step 4
1273
    **
1274
    ** u2 = ((r') * c) mod n
1275
    */
1276
1.07k
    CHECK_MPI_OK(mp_mulmod(&r_, &c, &n, &u2));
1277
1278
    /*
1279
    ** ANSI X9.62, Section 5.4.3, Step 1
1280
    **
1281
    ** Compute u1*G + u2*Q
1282
    ** Here, A = u1.G     B = u2.Q    and   C = A + B
1283
    ** If the result, C, is the point at infinity, reject the signature
1284
    */
1285
1.07k
    if (ec_points_mul(ecParams, &u1, &u2, &key->publicValue, &pointC) != SECSuccess) {
1286
0
        rv = SECFailure;
1287
0
        goto cleanup;
1288
0
    }
1289
1.07k
    if (ec_point_at_infinity(&pointC)) {
1290
0
        PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
1291
0
        rv = SECFailure;
1292
0
        goto cleanup;
1293
0
    }
1294
1295
1.07k
    CHECK_MPI_OK(mp_read_unsigned_octets(&x1, pointC.data + 1, flen));
1296
1297
    /*
1298
    ** ANSI X9.62, Section 5.4.4, Step 2
1299
    **
1300
    ** v = x1 mod n
1301
    */
1302
1.07k
    CHECK_MPI_OK(mp_mod(&x1, &n, &v));
1303
1304
#if EC_DEBUG
1305
    mp_todecimal(&r_, mpstr);
1306
    printf("r_: %s (dec)\n", mpstr);
1307
    mp_todecimal(&v, mpstr);
1308
    printf("v : %s (dec)\n", mpstr);
1309
#endif
1310
1311
    /*
1312
    ** ANSI X9.62, Section 5.4.4, Step 3
1313
    **
1314
    ** Verification:  v == r'
1315
    */
1316
1.07k
    if (mp_cmp(&v, &r_)) {
1317
1.07k
        PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
1318
1.07k
        rv = SECFailure; /* Signature failed to verify. */
1319
1.07k
    } else {
1320
0
        rv = SECSuccess; /* Signature verified. */
1321
0
    }
1322
1323
#if EC_DEBUG
1324
    mp_todecimal(&u1, mpstr);
1325
    printf("u1: %s (dec)\n", mpstr);
1326
    mp_todecimal(&u2, mpstr);
1327
    printf("u2: %s (dec)\n", mpstr);
1328
    mp_tohex(&x1, mpstr);
1329
    printf("x1: %s\n", mpstr);
1330
    mp_todecimal(&v, mpstr);
1331
    printf("v : %s (dec)\n", mpstr);
1332
#endif
1333
1334
1.08k
cleanup:
1335
1.08k
    mp_clear(&r_);
1336
1.08k
    mp_clear(&s_);
1337
1.08k
    mp_clear(&c);
1338
1.08k
    mp_clear(&u1);
1339
1.08k
    mp_clear(&u2);
1340
1.08k
    mp_clear(&x1);
1341
1.08k
    mp_clear(&v);
1342
1.08k
    mp_clear(&n);
1343
1344
1.08k
    if (pointC.data)
1345
1.08k
        SECITEM_ZfreeItem(&pointC, PR_FALSE);
1346
1347
1.37k
done:
1348
1.37k
    if (err) {
1349
0
        MP_TO_SEC_ERROR(err);
1350
0
        rv = SECFailure;
1351
0
    }
1352
1353
#if EC_DEBUG
1354
    printf("ECDSA verification %s\n",
1355
           (rv == SECSuccess) ? "succeeded" : "failed");
1356
#endif
1357
1358
1.37k
    return rv;
1359
1.37k
}
1360
1361
/*EdDSA: Currently only Ed22519 is implemented.*/
1362
1363
/*
1364
** Computes the EdDSA signature on the message using the given key.
1365
*/
1366
1367
SECStatus
1368
ec_ED25519_public_key_validate(const ECPublicKey *key)
1369
0
{
1370
0
    if (!key || !(key->ecParams.name == ECCurve_Ed25519)) {
1371
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
1372
0
        return SECFailure;
1373
0
    }
1374
0
    return ec_ED25519_pt_validate(&key->publicValue);
1375
0
}
1376
1377
SECStatus
1378
ec_ED25519_private_key_validate(const ECPrivateKey *key)
1379
0
{
1380
0
    if (!key || !(key->ecParams.name == ECCurve_Ed25519)) {
1381
1382
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
1383
0
        return SECFailure;
1384
0
    }
1385
0
    return ec_ED25519_scalar_validate(&key->privateValue);
1386
0
}
1387
1388
SECStatus
1389
ED_SignMessage(ECPrivateKey *key, SECItem *signature, const SECItem *msg)
1390
0
{
1391
0
    if (!msg || !signature || signature->len != Ed25519_SIGN_LEN) {
1392
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
1393
0
        return SECFailure;
1394
0
    }
1395
1396
0
    if (ec_ED25519_private_key_validate(key) != SECSuccess) {
1397
0
        return SECFailure; /* error code set by ec_ED25519_scalar_validate. */
1398
0
    }
1399
1400
0
    if (signature->data) {
1401
0
        Hacl_Ed25519_sign(signature->data, key->privateValue.data, msg->len,
1402
0
                          msg->data);
1403
0
    }
1404
0
    signature->len = ED25519_SIGN_LEN;
1405
0
    BLAPI_CLEAR_STACK(2048);
1406
0
    return SECSuccess;
1407
0
}
1408
1409
/*
1410
** Checks the signature on the given message using the key provided.
1411
*/
1412
1413
SECStatus
1414
ED_VerifyMessage(ECPublicKey *key, const SECItem *signature,
1415
                 const SECItem *msg)
1416
0
{
1417
0
    if (!msg || !signature || !signature->data || signature->len != Ed25519_SIGN_LEN) {
1418
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
1419
0
        return SECFailure;
1420
0
    }
1421
1422
0
    if (ec_ED25519_public_key_validate(key) != SECSuccess) {
1423
0
        return SECFailure; /* error code set by ec_ED25519_pt_validate. */
1424
0
    }
1425
1426
0
    bool rv = Hacl_Ed25519_verify(key->publicValue.data, msg->len, msg->data,
1427
0
                                  signature->data);
1428
0
    BLAPI_CLEAR_STACK(2048);
1429
1430
#if EC_DEBUG
1431
    printf("ED_VerifyMessage returning %s\n",
1432
           (rv) ? "success" : "failure");
1433
#endif
1434
1435
0
    if (rv) {
1436
0
        return SECSuccess;
1437
0
    }
1438
1439
0
    PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
1440
0
    return SECFailure;
1441
0
}
1442
1443
SECStatus
1444
ED_DerivePublicKey(const SECItem *privateKey, SECItem *publicKey)
1445
0
{
1446
    /* Currently supporting only Ed25519.*/
1447
0
    if (!privateKey || privateKey->len == 0 || !publicKey || publicKey->len != Ed25519_PUBLIC_KEYLEN) {
1448
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
1449
0
        return SECFailure;
1450
0
    }
1451
1452
0
    if (ec_ED25519_scalar_validate(privateKey) != SECSuccess) {
1453
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
1454
0
        return SECFailure;
1455
0
    }
1456
1457
0
    Hacl_Ed25519_secret_to_public(publicKey->data, privateKey->data);
1458
0
    return SECSuccess;
1459
0
}