Coverage Report

Created: 2025-06-24 06:49

/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_ED25519_pt_validate(const SECItem *px)
27
0
{
28
0
    if (!px || !px->data || px->len != Ed25519_PUBLIC_KEYLEN) {
29
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
30
0
        return SECFailure;
31
0
    }
32
0
    return SECSuccess;
33
0
}
34
35
SECStatus
36
ec_ED25519_scalar_validate(const SECItem *scalar)
37
0
{
38
0
    if (!scalar || !scalar->data || scalar->len != Ed25519_PRIVATE_KEYLEN) {
39
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
40
0
        return SECFailure;
41
0
    }
42
43
0
    return SECSuccess;
44
0
}
45
46
static const ECMethod kMethods[] = {
47
    { ECCurve25519,
48
      ec_Curve25519_pt_mul,
49
      ec_Curve25519_pt_validate,
50
      ec_Curve25519_scalar_validate,
51
      NULL,
52
      NULL },
53
    {
54
        ECCurve_NIST_P256,
55
        ec_secp256r1_pt_mul,
56
        ec_secp256r1_pt_validate,
57
        ec_secp256r1_scalar_validate,
58
        ec_secp256r1_sign_digest,
59
        ec_secp256r1_verify_digest,
60
    },
61
    {
62
        ECCurve_NIST_P384,
63
        ec_secp384r1_pt_mul,
64
        ec_secp384r1_pt_validate,
65
        ec_secp384r1_scalar_validate,
66
        ec_secp384r1_sign_digest,
67
        ec_secp384r1_verify_digest,
68
    },
69
    {
70
        ECCurve_NIST_P521,
71
        ec_secp521r1_pt_mul,
72
        ec_secp521r1_pt_validate,
73
        ec_secp521r1_scalar_validate,
74
        ec_secp521r1_sign_digest,
75
        ec_secp521r1_verify_digest,
76
    },
77
    { ECCurve_Ed25519,
78
      NULL,
79
      ec_ED25519_pt_validate,
80
      ec_ED25519_scalar_validate,
81
      NULL,
82
      NULL },
83
};
84
85
static const ECMethod *
86
ec_get_method_from_name(ECCurveName name)
87
406k
{
88
406k
    unsigned long i;
89
782k
    for (i = 0; i < sizeof(kMethods) / sizeof(kMethods[0]); ++i) {
90
782k
        if (kMethods[i].name == name) {
91
406k
            return &kMethods[i];
92
406k
        }
93
782k
    }
94
0
    return NULL;
95
406k
}
96
97
/* Generates a new EC key pair. The private key is a supplied
98
 * value and the public key is the result of performing a scalar
99
 * point multiplication of that value with the curve's base point.
100
 */
101
SECStatus
102
ec_NewKey(ECParams *ecParams, ECPrivateKey **privKey,
103
          const unsigned char *privKeyBytes, int privKeyLen)
104
89.7k
{
105
89.7k
    SECStatus rv = SECFailure;
106
89.7k
    PLArenaPool *arena;
107
89.7k
    ECPrivateKey *key;
108
89.7k
    int len;
109
110
89.7k
    if (!ecParams || ecParams->name == ECCurve_noName ||
111
89.7k
        !privKey || !privKeyBytes || privKeyLen <= 0) {
112
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
113
0
        return SECFailure;
114
0
    }
115
116
89.7k
    if (ecParams->fieldID.type != ec_field_plain) {
117
0
        PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE);
118
0
        return SECFailure;
119
0
    }
120
121
    /* Initialize an arena for the EC key. */
122
89.7k
    if (!(arena = PORT_NewArena(NSS_FREEBL_DEFAULT_CHUNKSIZE)))
123
0
        return SECFailure;
124
125
89.7k
    key = (ECPrivateKey *)PORT_ArenaZAlloc(arena, sizeof(ECPrivateKey));
126
89.7k
    if (!key) {
127
0
        goto cleanup;
128
0
    }
129
130
    /* Set the version number (SEC 1 section C.4 says it should be 1) */
131
89.7k
    SECITEM_AllocItem(arena, &key->version, 1);
132
89.7k
    key->version.data[0] = 1;
133
134
    /* Copy all of the fields from the ECParams argument to the
135
     * ECParams structure within the private key.
136
     */
137
89.7k
    key->ecParams.arena = arena;
138
89.7k
    key->ecParams.type = ecParams->type;
139
89.7k
    key->ecParams.fieldID.size = ecParams->fieldID.size;
140
89.7k
    key->ecParams.fieldID.type = ecParams->fieldID.type;
141
89.7k
    CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.fieldID.u.prime,
142
89.7k
                                  &ecParams->fieldID.u.prime));
143
89.7k
    key->ecParams.fieldID.k1 = ecParams->fieldID.k1;
144
89.7k
    key->ecParams.fieldID.k2 = ecParams->fieldID.k2;
145
89.7k
    key->ecParams.fieldID.k3 = ecParams->fieldID.k3;
146
89.7k
    CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.curve.a,
147
89.7k
                                  &ecParams->curve.a));
148
89.7k
    CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.curve.b,
149
89.7k
                                  &ecParams->curve.b));
150
89.7k
    CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.curve.seed,
151
89.7k
                                  &ecParams->curve.seed));
152
89.7k
    CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.base,
153
89.7k
                                  &ecParams->base));
154
89.7k
    CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.order,
155
89.7k
                                  &ecParams->order));
156
89.7k
    key->ecParams.cofactor = ecParams->cofactor;
157
89.7k
    CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.DEREncoding,
158
89.7k
                                  &ecParams->DEREncoding));
159
89.7k
    key->ecParams.name = ecParams->name;
160
89.7k
    CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.curveOID,
161
89.7k
                                  &ecParams->curveOID));
162
163
89.7k
    SECITEM_AllocItem(arena, &key->publicValue, EC_GetPointSize(ecParams));
164
89.7k
    len = ecParams->order.len;
165
89.7k
    SECITEM_AllocItem(arena, &key->privateValue, len);
166
167
    /* Copy private key */
168
89.7k
    if (privKeyLen >= len) {
169
89.7k
        memcpy(key->privateValue.data, privKeyBytes, len);
170
89.7k
    } else {
171
0
        memset(key->privateValue.data, 0, (len - privKeyLen));
172
0
        memcpy(key->privateValue.data + (len - privKeyLen), privKeyBytes, privKeyLen);
173
0
    }
174
175
    /* Compute corresponding public key */
176
177
    /* Use curve specific code for point multiplication */
178
89.7k
    if (ecParams->name == ECCurve_Ed25519) {
179
0
        CHECK_SEC_OK(ED_DerivePublicKey(&key->privateValue, &key->publicValue));
180
89.7k
    } else {
181
89.7k
        const ECMethod *method = ec_get_method_from_name(ecParams->name);
182
89.7k
        if (method == NULL || method->pt_mul == NULL) {
183
0
            PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE);
184
0
            rv = SECFailure;
185
0
            goto cleanup;
186
0
        }
187
89.7k
        CHECK_SEC_OK(method->pt_mul(&key->publicValue, &key->privateValue, NULL));
188
89.7k
    }
189
190
89.3k
    NSS_DECLASSIFY(key->publicValue.data, key->publicValue.len); /* Declassifying public key to avoid false positive */
191
89.3k
    *privKey = key;
192
89.3k
    return SECSuccess;
193
194
398
cleanup:
195
398
    PORT_FreeArena(arena, PR_TRUE);
196
398
    return rv;
197
89.7k
}
198
199
/* Generates a new EC key pair. The private key is a supplied
200
 * random value (in seed) and the public key is the result of
201
 * performing a scalar point multiplication of that value with
202
 * the curve's base point.
203
 */
204
SECStatus
205
EC_NewKeyFromSeed(ECParams *ecParams, ECPrivateKey **privKey,
206
                  const unsigned char *seed, int seedlen)
207
9.79k
{
208
9.79k
    return ec_NewKey(ecParams, privKey, seed, seedlen);
209
9.79k
}
210
211
/* Generate a random private key using the algorithm A.4.1 or A.4.2 of ANSI X9.62,
212
 * modified a la FIPS 186-2 Change Notice 1 to eliminate the bias in the
213
 * random number generator.
214
 */
215
216
SECStatus
217
ec_GenerateRandomPrivateKey(ECParams *ecParams, SECItem *privKey)
218
89.4k
{
219
89.4k
    SECStatus rv = SECFailure;
220
221
89.4k
    unsigned int len = EC_GetScalarSize(ecParams);
222
223
89.4k
    if (privKey->len != len || privKey->data == NULL) {
224
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
225
0
        return SECFailure;
226
0
    }
227
228
89.4k
    const ECMethod *method = ec_get_method_from_name(ecParams->name);
229
89.4k
    if (method == NULL || method->scalar_validate == NULL) {
230
0
        PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE);
231
0
        return SECFailure;
232
0
    }
233
234
89.4k
    uint8_t leading_coeff_mask;
235
89.4k
    switch (ecParams->name) {
236
0
        case ECCurve_Ed25519:
237
20.6k
        case ECCurve25519:
238
80.3k
        case ECCurve_NIST_P256:
239
89.0k
        case ECCurve_NIST_P384:
240
89.0k
            leading_coeff_mask = 0xff;
241
89.0k
            break;
242
327
        case ECCurve_NIST_P521:
243
327
            leading_coeff_mask = 0x01;
244
327
            break;
245
0
        default:
246
0
            PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE);
247
0
            return SECFailure;
248
89.4k
    }
249
250
    /* The rejection sampling method from FIPS 186-5 A.4.2 */
251
89.4k
    int count = 100;
252
89.4k
    do {
253
89.4k
        rv = RNG_GenerateGlobalRandomBytes(privKey->data, len);
254
89.4k
        if (rv != SECSuccess) {
255
0
            PORT_SetError(SEC_ERROR_NEED_RANDOM);
256
0
            return SECFailure;
257
0
        }
258
89.4k
        privKey->data[0] &= leading_coeff_mask;
259
89.4k
        NSS_CLASSIFY(privKey->data, privKey->len);
260
89.4k
        rv = method->scalar_validate(privKey);
261
89.4k
    } while (rv != SECSuccess && --count > 0);
262
263
89.4k
    if (rv != SECSuccess) { // implies count == 0
264
0
        PORT_SetError(SEC_ERROR_BAD_KEY);
265
0
    }
266
267
89.4k
    return rv;
268
89.4k
}
269
270
/* Generates a new EC key pair. The private key is a random value and
271
 * the public key is the result of performing a scalar point multiplication
272
 * of that value with the curve's base point.
273
 */
274
SECStatus
275
EC_NewKey(ECParams *ecParams, ECPrivateKey **privKey)
276
79.9k
{
277
79.9k
    SECStatus rv = SECFailure;
278
79.9k
    SECItem privKeyRand = { siBuffer, NULL, 0 };
279
280
79.9k
    if (!ecParams || ecParams->name == ECCurve_noName || !privKey) {
281
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
282
0
        return SECFailure;
283
0
    }
284
285
79.9k
    SECITEM_AllocItem(NULL, &privKeyRand, EC_GetScalarSize(ecParams));
286
79.9k
    if (privKeyRand.data == NULL) {
287
0
        PORT_SetError(SEC_ERROR_NO_MEMORY);
288
0
        rv = SECFailure;
289
0
        goto cleanup;
290
0
    }
291
79.9k
    rv = ec_GenerateRandomPrivateKey(ecParams, &privKeyRand);
292
79.9k
    if (rv != SECSuccess || privKeyRand.data == NULL) {
293
0
        goto cleanup;
294
0
    }
295
    /* generate public key */
296
79.9k
    CHECK_SEC_OK(ec_NewKey(ecParams, privKey, privKeyRand.data, privKeyRand.len));
297
298
79.9k
cleanup:
299
79.9k
    if (privKeyRand.data) {
300
79.9k
        SECITEM_ZfreeItem(&privKeyRand, PR_FALSE);
301
79.9k
    }
302
#if EC_DEBUG
303
    printf("EC_NewKey returning %s\n",
304
           (rv == SECSuccess) ? "success" : "failure");
305
#endif
306
307
79.9k
    return rv;
308
79.9k
}
309
310
/* Validates an EC public key as described in Section 5.2.2 of
311
 * X9.62. The ECDH primitive when used without the cofactor does
312
 * not address small subgroup attacks, which may occur when the
313
 * public key is not valid. These attacks can be prevented by
314
 * validating the public key before using ECDH.
315
 */
316
SECStatus
317
EC_ValidatePublicKey(ECParams *ecParams, SECItem *publicValue)
318
149k
{
319
149k
    if (!ecParams || ecParams->name == ECCurve_noName ||
320
149k
        !publicValue || !publicValue->len) {
321
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
322
0
        return SECFailure;
323
0
    }
324
325
    /* Uses curve specific code for point validation. */
326
149k
    if (ecParams->fieldID.type != ec_field_plain) {
327
0
        PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE);
328
0
        return SECFailure;
329
0
    }
330
331
149k
    const ECMethod *method = ec_get_method_from_name(ecParams->name);
332
149k
    if (method == NULL || method->pt_validate == NULL) {
333
        /* unknown curve */
334
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
335
0
        return SECFailure;
336
0
    }
337
338
149k
    SECStatus rv = method->pt_validate(publicValue);
339
149k
    if (rv != SECSuccess) {
340
1.50k
        PORT_SetError(SEC_ERROR_BAD_KEY);
341
1.50k
    }
342
149k
    return rv;
343
149k
}
344
345
/*
346
** Performs an ECDH key derivation by computing the scalar point
347
** multiplication of privateValue and publicValue (with or without the
348
** cofactor) and returns the x-coordinate of the resulting elliptic
349
** curve point in derived secret.  If successful, derivedSecret->data
350
** is set to the address of the newly allocated buffer containing the
351
** derived secret, and derivedSecret->len is the size of the secret
352
** produced. It is the caller's responsibility to free the allocated
353
** buffer containing the derived secret.
354
*/
355
SECStatus
356
ECDH_Derive(SECItem *publicValue,
357
            ECParams *ecParams,
358
            SECItem *privateValue,
359
            PRBool withCofactor,
360
            SECItem *derivedSecret)
361
69.1k
{
362
69.1k
    if (!publicValue || !publicValue->len ||
363
69.1k
        !ecParams || ecParams->name == ECCurve_noName ||
364
69.1k
        !privateValue || !privateValue->len || !derivedSecret) {
365
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
366
0
        return SECFailure;
367
0
    }
368
369
    /*
370
     * Make sure the point is on the requested curve to avoid
371
     * certain small subgroup attacks.
372
     */
373
69.1k
    if (EC_ValidatePublicKey(ecParams, publicValue) != SECSuccess) {
374
1.37k
        PORT_SetError(SEC_ERROR_BAD_KEY);
375
1.37k
        return SECFailure;
376
1.37k
    }
377
378
    /* Perform curve specific multiplication using ECMethod */
379
67.7k
    if (ecParams->fieldID.type != ec_field_plain) {
380
0
        PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE);
381
0
        return SECFailure;
382
0
    }
383
384
67.7k
    const ECMethod *method = ec_get_method_from_name(ecParams->name);
385
67.7k
    if (method == NULL || method->pt_validate == NULL ||
386
67.7k
        method->pt_mul == NULL) {
387
0
        PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE);
388
0
        return SECFailure;
389
0
    }
390
391
67.7k
    memset(derivedSecret, 0, sizeof(*derivedSecret));
392
67.7k
    derivedSecret = SECITEM_AllocItem(NULL, derivedSecret, EC_GetScalarSize(ecParams));
393
67.7k
    if (derivedSecret == NULL) {
394
0
        PORT_SetError(SEC_ERROR_NO_MEMORY);
395
0
        return SECFailure;
396
0
    }
397
398
67.7k
    SECStatus rv = method->pt_mul(derivedSecret, privateValue, publicValue);
399
67.7k
    if (rv != SECSuccess) {
400
12.5k
        PORT_SetError(SEC_ERROR_BAD_KEY);
401
12.5k
        SECITEM_ZfreeItem(derivedSecret, PR_FALSE);
402
12.5k
    }
403
67.7k
    return rv;
404
67.7k
}
405
406
/* Computes the ECDSA signature (a concatenation of two values r and s)
407
 * on the digest using the given key and the random value kb (used in
408
 * computing s).
409
 */
410
411
static SECStatus
412
ec_SignDigestWithSeed(ECPrivateKey *key, SECItem *signature,
413
                      const SECItem *digest, const unsigned char *kb, const int kblen)
414
9.50k
{
415
9.50k
    ECParams *ecParams = NULL;
416
9.50k
    unsigned olen; /* length in bytes of the base point order */
417
418
    /* Check args */
419
9.50k
    if (!key || !signature || !digest || !kb || (kblen <= 0)) {
420
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
421
0
        return SECFailure;
422
0
    }
423
424
9.50k
    ecParams = &(key->ecParams);
425
9.50k
    olen = ecParams->order.len;
426
9.50k
    if (signature->data == NULL) {
427
        /* a call to get the signature length only */
428
0
        signature->len = 2 * olen;
429
0
        return SECSuccess;
430
0
    }
431
9.50k
    if (signature->len < 2 * olen) {
432
0
        PORT_SetError(SEC_ERROR_OUTPUT_LEN);
433
0
        return SECFailure;
434
0
    }
435
436
    /* Perform curve specific signature using ECMethod */
437
9.50k
    if (ecParams->fieldID.type != ec_field_plain) {
438
0
        PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE);
439
0
        return SECFailure;
440
0
    }
441
442
9.50k
    const ECMethod *method = ec_get_method_from_name(ecParams->name);
443
9.50k
    if (method == NULL || method->sign_digest == NULL) {
444
0
        PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE);
445
0
        return SECFailure;
446
0
    }
447
448
9.50k
    SECStatus rv = method->sign_digest(key, signature, digest, kb, kblen);
449
9.50k
    if (rv != SECSuccess) {
450
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
451
0
    }
452
453
#if EC_DEBUG
454
    printf("ECDSA signing with seed %s\n",
455
           (rv == SECSuccess) ? "succeeded" : "failed");
456
#endif
457
9.50k
    return rv;
458
9.50k
}
459
460
SECStatus
461
ECDSA_SignDigestWithSeed(ECPrivateKey *key, SECItem *signature,
462
                         const SECItem *digest, const unsigned char *kb, const int kblen)
463
9.50k
{
464
#if EC_DEBUG || EC_DOUBLECHECK
465
    SECItem *signature2 = SECITEM_AllocItem(NULL, NULL, signature->len);
466
    SECStatus signSuccess = ec_SignDigestWithSeed(key, signature, digest, kb, kblen);
467
    SECStatus signSuccessDouble = ec_SignDigestWithSeed(key, signature2, digest, kb, kblen);
468
    int signaturesEqual = NSS_SecureMemcmp(signature->data, signature2->data, signature->len);
469
    SECStatus rv;
470
471
    if ((signaturesEqual == 0) && (signSuccess == SECSuccess) && (signSuccessDouble == SECSuccess)) {
472
        rv = SECSuccess;
473
    } else {
474
        rv = SECFailure;
475
    }
476
477
#if EC_DEBUG
478
    printf("ECDSA signing with seed %s after signing twice\n", (rv == SECSuccess) ? "succeeded" : "failed");
479
#endif
480
481
    SECITEM_FreeItem(signature2, PR_TRUE);
482
    return rv;
483
#else
484
9.50k
    return ec_SignDigestWithSeed(key, signature, digest, kb, kblen);
485
9.50k
#endif
486
9.50k
}
487
488
/*
489
** Computes the ECDSA signature on the digest using the given key
490
** and a random seed.
491
*/
492
SECStatus
493
ECDSA_SignDigest(ECPrivateKey *key, SECItem *signature, const SECItem *digest)
494
9.50k
{
495
9.50k
    SECItem nonceRand = { siBuffer, NULL, 0 };
496
497
9.50k
    if (!key) {
498
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
499
0
        return SECFailure;
500
0
    }
501
502
    /* Generate random value k */
503
9.50k
    SECITEM_AllocItem(NULL, &nonceRand, EC_GetScalarSize(&key->ecParams));
504
9.50k
    if (nonceRand.data == NULL) {
505
0
        PORT_SetError(SEC_ERROR_NO_MEMORY);
506
0
        return SECFailure;
507
0
    }
508
509
9.50k
    SECStatus rv = ec_GenerateRandomPrivateKey(&key->ecParams, &nonceRand);
510
9.50k
    if (rv != SECSuccess) {
511
0
        goto cleanup;
512
0
    }
513
514
    /* Generate ECDSA signature with the specified k value */
515
9.50k
    rv = ECDSA_SignDigestWithSeed(key, signature, digest, nonceRand.data, nonceRand.len);
516
9.50k
    NSS_DECLASSIFY(signature->data, signature->len);
517
518
9.50k
cleanup:
519
9.50k
    SECITEM_ZfreeItem(&nonceRand, PR_FALSE);
520
521
#if EC_DEBUG
522
    printf("ECDSA signing %s\n",
523
           (rv == SECSuccess) ? "succeeded" : "failed");
524
#endif
525
526
9.50k
    return rv;
527
9.50k
}
528
529
/*
530
** Checks the signature on the given digest using the key provided.
531
**
532
** The key argument must represent a valid EC public key (a point on
533
** the relevant curve).  If it is not a valid point, then the behavior
534
** of this function is undefined.  In cases where a public key might
535
** not be valid, use EC_ValidatePublicKey to check.
536
*/
537
SECStatus
538
ECDSA_VerifyDigest(ECPublicKey *key, const SECItem *signature,
539
                   const SECItem *digest)
540
661
{
541
661
    SECStatus rv = SECFailure;
542
661
    ECParams *ecParams = NULL;
543
544
    /* Check args */
545
661
    if (!key || !signature || !digest) {
546
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
547
0
        return SECFailure;
548
0
    }
549
550
661
    ecParams = &(key->ecParams);
551
552
    /* Perform curve specific signature verification using ECMethod */
553
661
    if (ecParams->fieldID.type != ec_field_plain) {
554
0
        PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE);
555
0
        return SECFailure;
556
0
    }
557
558
661
    const ECMethod *method = ec_get_method_from_name(ecParams->name);
559
661
    if (method == NULL || method->verify_digest == NULL) {
560
0
        PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE);
561
0
        return SECFailure;
562
0
    }
563
564
661
    rv = method->verify_digest(key, signature, digest);
565
661
    if (rv != SECSuccess) {
566
562
        PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
567
562
    }
568
569
#if EC_DEBUG
570
    printf("ECDSA verification %s\n",
571
           (rv == SECSuccess) ? "succeeded" : "failed");
572
#endif
573
574
661
    return rv;
575
661
}
576
577
/*EdDSA: Currently only Ed22519 is implemented.*/
578
579
/*
580
** Computes the EdDSA signature on the message using the given key.
581
*/
582
583
SECStatus
584
ec_ED25519_public_key_validate(const ECPublicKey *key)
585
0
{
586
0
    if (!key || !(key->ecParams.name == ECCurve_Ed25519)) {
587
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
588
0
        return SECFailure;
589
0
    }
590
0
    return ec_ED25519_pt_validate(&key->publicValue);
591
0
}
592
593
SECStatus
594
ec_ED25519_private_key_validate(const ECPrivateKey *key)
595
0
{
596
0
    if (!key || !(key->ecParams.name == ECCurve_Ed25519)) {
597
598
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
599
0
        return SECFailure;
600
0
    }
601
0
    return ec_ED25519_scalar_validate(&key->privateValue);
602
0
}
603
604
SECStatus
605
ED_SignMessage(ECPrivateKey *key, SECItem *signature, const SECItem *msg)
606
0
{
607
0
    if (!msg || !signature || signature->len != Ed25519_SIGN_LEN) {
608
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
609
0
        return SECFailure;
610
0
    }
611
612
0
    if (ec_ED25519_private_key_validate(key) != SECSuccess) {
613
0
        return SECFailure; /* error code set by ec_ED25519_scalar_validate. */
614
0
    }
615
616
0
    if (signature->data) {
617
0
        Hacl_Ed25519_sign(signature->data, key->privateValue.data, msg->len,
618
0
                          msg->data);
619
0
    }
620
0
    signature->len = ED25519_SIGN_LEN;
621
0
    BLAPI_CLEAR_STACK(2048);
622
0
    return SECSuccess;
623
0
}
624
625
/*
626
** Checks the signature on the given message using the key provided.
627
*/
628
629
SECStatus
630
ED_VerifyMessage(ECPublicKey *key, const SECItem *signature,
631
                 const SECItem *msg)
632
0
{
633
0
    if (!msg || !signature || !signature->data || signature->len != Ed25519_SIGN_LEN) {
634
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
635
0
        return SECFailure;
636
0
    }
637
638
0
    if (ec_ED25519_public_key_validate(key) != SECSuccess) {
639
0
        return SECFailure; /* error code set by ec_ED25519_pt_validate. */
640
0
    }
641
642
0
    bool rv = Hacl_Ed25519_verify(key->publicValue.data, msg->len, msg->data,
643
0
                                  signature->data);
644
0
    BLAPI_CLEAR_STACK(2048);
645
646
#if EC_DEBUG
647
    printf("ED_VerifyMessage returning %s\n",
648
           (rv) ? "success" : "failure");
649
#endif
650
651
0
    if (rv) {
652
0
        return SECSuccess;
653
0
    }
654
655
0
    PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
656
0
    return SECFailure;
657
0
}
658
659
SECStatus
660
ED_DerivePublicKey(const SECItem *privateKey, SECItem *publicKey)
661
0
{
662
    /* Currently supporting only Ed25519.*/
663
0
    if (!privateKey || privateKey->len == 0 || !publicKey || publicKey->len != Ed25519_PUBLIC_KEYLEN) {
664
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
665
0
        return SECFailure;
666
0
    }
667
668
0
    if (ec_ED25519_scalar_validate(privateKey) != SECSuccess) {
669
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
670
0
        return SECFailure;
671
0
    }
672
673
0
    Hacl_Ed25519_secret_to_public(publicKey->data, privateKey->data);
674
0
    return SECSuccess;
675
0
}
676
677
SECStatus
678
X25519_DerivePublicKey(const SECItem *privateKey, SECItem *publicKey)
679
0
{
680
0
    SECStatus rv = SECFailure;
681
    /* Currently supporting only X25519.*/
682
0
    if (!privateKey || privateKey->len == 0 || !publicKey || publicKey->len != X25519_PUBLIC_KEYLEN) {
683
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
684
0
        return SECFailure;
685
0
    }
686
687
0
    const ECMethod *method = ec_get_method_from_name(ECCurve25519);
688
0
    if (method == NULL || method->pt_mul == NULL) {
689
0
        PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE);
690
0
        return SECFailure;
691
0
    }
692
693
0
    rv = method->pt_mul(publicKey, (SECItem *)privateKey, NULL);
694
0
    return rv;
695
0
}
696
697
SECStatus
698
EC_DerivePublicKey(const SECItem *privateKey, const ECParams *ecParams, SECItem *publicKey)
699
69
{
700
69
    if (!privateKey || privateKey->len == 0 || !publicKey || publicKey->len != EC_GetPointSize(ecParams)) {
701
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
702
0
        return SECFailure;
703
0
    }
704
705
69
    const ECMethod *method = ec_get_method_from_name(ecParams->name);
706
69
    if (method == NULL || method->pt_mul == NULL) {
707
0
        PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE);
708
0
        return SECFailure;
709
0
    }
710
711
69
    return method->pt_mul(publicKey, (SECItem *)privateKey, NULL);
712
69
}