Coverage Report

Created: 2025-06-13 06:58

/src/openssl31/crypto/ec/ecdsa_ossl.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright 2002-2024 The OpenSSL Project Authors. All Rights Reserved.
3
 *
4
 * Licensed under the Apache License 2.0 (the "License").  You may not use
5
 * this file except in compliance with the License.  You can obtain a copy
6
 * in the file LICENSE in the source distribution or at
7
 * https://www.openssl.org/source/license.html
8
 */
9
10
/*
11
 * ECDSA low level APIs are deprecated for public use, but still ok for
12
 * internal use.
13
 */
14
#include "internal/deprecated.h"
15
16
#include <string.h>
17
#include <openssl/err.h>
18
#include <openssl/obj_mac.h>
19
#include <openssl/rand.h>
20
#include "crypto/bn.h"
21
#include "ec_local.h"
22
23
2.33k
#define MIN_ECDSA_SIGN_ORDERBITS 64
24
/*
25
 * It is highly unlikely that a retry will happen,
26
 * Multiple retries would indicate that something is wrong
27
 * with the group parameters (which would normally only happen
28
 * with a bad custom group).
29
 */
30
0
#define MAX_ECDSA_SIGN_RETRIES 8
31
32
int ossl_ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, BIGNUM **kinvp,
33
                          BIGNUM **rp)
34
0
{
35
0
    if (eckey->group->meth->ecdsa_sign_setup == NULL) {
36
0
        ERR_raise(ERR_LIB_EC, EC_R_CURVE_DOES_NOT_SUPPORT_ECDSA);
37
0
        return 0;
38
0
    }
39
40
0
    return eckey->group->meth->ecdsa_sign_setup(eckey, ctx_in, kinvp, rp);
41
0
}
42
43
ECDSA_SIG *ossl_ecdsa_sign_sig(const unsigned char *dgst, int dgst_len,
44
                               const BIGNUM *in_kinv, const BIGNUM *in_r,
45
                               EC_KEY *eckey)
46
2.93k
{
47
2.93k
    if (eckey->group->meth->ecdsa_sign_sig == NULL) {
48
0
        ERR_raise(ERR_LIB_EC, EC_R_CURVE_DOES_NOT_SUPPORT_ECDSA);
49
0
        return NULL;
50
0
    }
51
52
2.93k
    return eckey->group->meth->ecdsa_sign_sig(dgst, dgst_len,
53
2.93k
                                              in_kinv, in_r, eckey);
54
2.93k
}
55
56
int ossl_ecdsa_verify_sig(const unsigned char *dgst, int dgst_len,
57
                          const ECDSA_SIG *sig, EC_KEY *eckey)
58
586
{
59
586
    if (eckey->group->meth->ecdsa_verify_sig == NULL) {
60
0
        ERR_raise(ERR_LIB_EC, EC_R_CURVE_DOES_NOT_SUPPORT_ECDSA);
61
0
        return 0;
62
0
    }
63
64
586
    return eckey->group->meth->ecdsa_verify_sig(dgst, dgst_len, sig, eckey);
65
586
}
66
67
int ossl_ecdsa_sign(int type, const unsigned char *dgst, int dlen,
68
                    unsigned char *sig, unsigned int *siglen,
69
                    const BIGNUM *kinv, const BIGNUM *r, EC_KEY *eckey)
70
2.93k
{
71
2.93k
    ECDSA_SIG *s;
72
73
2.93k
    if (sig == NULL && (kinv == NULL || r == NULL)) {
74
0
        *siglen = ECDSA_size(eckey);
75
0
        return 1;
76
0
    }
77
78
2.93k
    s = ECDSA_do_sign_ex(dgst, dlen, kinv, r, eckey);
79
2.93k
    if (s == NULL) {
80
0
        *siglen = 0;
81
0
        return 0;
82
0
    }
83
2.93k
    *siglen = i2d_ECDSA_SIG(s, sig != NULL ? &sig : NULL);
84
2.93k
    ECDSA_SIG_free(s);
85
2.93k
    return 1;
86
2.93k
}
87
88
static int ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in,
89
                            BIGNUM **kinvp, BIGNUM **rp,
90
                            const unsigned char *dgst, int dlen)
91
1.16k
{
92
1.16k
    BN_CTX *ctx = NULL;
93
1.16k
    BIGNUM *k = NULL, *r = NULL, *X = NULL;
94
1.16k
    const BIGNUM *order;
95
1.16k
    EC_POINT *tmp_point = NULL;
96
1.16k
    const EC_GROUP *group;
97
1.16k
    int ret = 0;
98
1.16k
    int order_bits;
99
1.16k
    const BIGNUM *priv_key;
100
101
1.16k
    if (eckey == NULL || (group = EC_KEY_get0_group(eckey)) == NULL) {
102
0
        ERR_raise(ERR_LIB_EC, ERR_R_PASSED_NULL_PARAMETER);
103
0
        return 0;
104
0
    }
105
1.16k
    if ((priv_key = EC_KEY_get0_private_key(eckey)) == NULL) {
106
0
        ERR_raise(ERR_LIB_EC, EC_R_MISSING_PRIVATE_KEY);
107
0
        return 0;
108
0
    }
109
110
1.16k
    if (!EC_KEY_can_sign(eckey)) {
111
0
        ERR_raise(ERR_LIB_EC, EC_R_CURVE_DOES_NOT_SUPPORT_SIGNING);
112
0
        return 0;
113
0
    }
114
115
1.16k
    if ((ctx = ctx_in) == NULL) {
116
0
        if ((ctx = BN_CTX_new_ex(eckey->libctx)) == NULL) {
117
0
            ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
118
0
            return 0;
119
0
        }
120
0
    }
121
122
1.16k
    k = BN_secure_new();        /* this value is later returned in *kinvp */
123
1.16k
    r = BN_new();               /* this value is later returned in *rp */
124
1.16k
    X = BN_new();
125
1.16k
    if (k == NULL || r == NULL || X == NULL) {
126
0
        ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
127
0
        goto err;
128
0
    }
129
1.16k
    if ((tmp_point = EC_POINT_new(group)) == NULL) {
130
0
        ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
131
0
        goto err;
132
0
    }
133
134
1.16k
    if ((order = EC_GROUP_get0_order(group)) == NULL) {
135
0
        ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
136
0
        goto err;
137
0
    }
138
139
    /* Preallocate space */
140
1.16k
    order_bits = BN_num_bits(order);
141
    /* Check the number of bits here so that an infinite loop is not possible */
142
1.16k
    if (order_bits < MIN_ECDSA_SIGN_ORDERBITS
143
1.16k
        || !BN_set_bit(k, order_bits)
144
1.16k
        || !BN_set_bit(r, order_bits)
145
1.16k
        || !BN_set_bit(X, order_bits))
146
0
        goto err;
147
148
1.16k
    do {
149
        /* get random k */
150
1.16k
        do {
151
1.16k
            if (dgst != NULL) {
152
1.16k
                if (!ossl_bn_gen_dsa_nonce_fixed_top(k, order, priv_key,
153
1.16k
                                                     dgst, dlen, ctx)) {
154
0
                    ERR_raise(ERR_LIB_EC, EC_R_RANDOM_NUMBER_GENERATION_FAILED);
155
0
                    goto err;
156
0
                }
157
1.16k
            } else {
158
0
                if (!ossl_bn_priv_rand_range_fixed_top(k, order, 0, ctx)) {
159
0
                    ERR_raise(ERR_LIB_EC, EC_R_RANDOM_NUMBER_GENERATION_FAILED);
160
0
                    goto err;
161
0
                }
162
0
            }
163
1.16k
        } while (ossl_bn_is_word_fixed_top(k, 0));
164
165
        /* compute r the x-coordinate of generator * k */
166
1.16k
        if (!EC_POINT_mul(group, tmp_point, k, NULL, NULL, ctx)) {
167
0
            ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
168
0
            goto err;
169
0
        }
170
171
1.16k
        if (!EC_POINT_get_affine_coordinates(group, tmp_point, X, NULL, ctx)) {
172
0
            ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
173
0
            goto err;
174
0
        }
175
176
1.16k
        if (!BN_nnmod(r, X, order, ctx)) {
177
0
            ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB);
178
0
            goto err;
179
0
        }
180
1.16k
    } while (BN_is_zero(r));
181
182
    /* compute the inverse of k */
183
1.16k
    if (!ossl_ec_group_do_inverse_ord(group, k, k, ctx)) {
184
0
        ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB);
185
0
        goto err;
186
0
    }
187
188
    /* clear old values if necessary */
189
1.16k
    BN_clear_free(*rp);
190
1.16k
    BN_clear_free(*kinvp);
191
    /* save the pre-computed values  */
192
1.16k
    *rp = r;
193
1.16k
    *kinvp = k;
194
1.16k
    ret = 1;
195
1.16k
 err:
196
1.16k
    if (!ret) {
197
0
        BN_clear_free(k);
198
0
        BN_clear_free(r);
199
0
    }
200
1.16k
    if (ctx != ctx_in)
201
0
        BN_CTX_free(ctx);
202
1.16k
    EC_POINT_free(tmp_point);
203
1.16k
    BN_clear_free(X);
204
1.16k
    return ret;
205
1.16k
}
206
207
int ossl_ecdsa_simple_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, BIGNUM **kinvp,
208
                                 BIGNUM **rp)
209
0
{
210
0
    return ecdsa_sign_setup(eckey, ctx_in, kinvp, rp, NULL, 0);
211
0
}
212
213
ECDSA_SIG *ossl_ecdsa_simple_sign_sig(const unsigned char *dgst, int dgst_len,
214
                                      const BIGNUM *in_kinv, const BIGNUM *in_r,
215
                                      EC_KEY *eckey)
216
2.93k
{
217
2.93k
    int ok = 0, i;
218
2.93k
    int retries = 0;
219
2.93k
    BIGNUM *kinv = NULL, *s, *m = NULL;
220
2.93k
    const BIGNUM *order, *ckinv;
221
2.93k
    BN_CTX *ctx = NULL;
222
2.93k
    const EC_GROUP *group;
223
2.93k
    ECDSA_SIG *ret;
224
2.93k
    const BIGNUM *priv_key;
225
226
2.93k
    group = EC_KEY_get0_group(eckey);
227
2.93k
    priv_key = EC_KEY_get0_private_key(eckey);
228
229
2.93k
    if (group == NULL) {
230
0
        ERR_raise(ERR_LIB_EC, ERR_R_PASSED_NULL_PARAMETER);
231
0
        return NULL;
232
0
    }
233
2.93k
    if (priv_key == NULL) {
234
0
        ERR_raise(ERR_LIB_EC, EC_R_MISSING_PRIVATE_KEY);
235
0
        return NULL;
236
0
    }
237
238
2.93k
    if (!EC_KEY_can_sign(eckey)) {
239
0
        ERR_raise(ERR_LIB_EC, EC_R_CURVE_DOES_NOT_SUPPORT_SIGNING);
240
0
        return NULL;
241
0
    }
242
243
2.93k
    ret = ECDSA_SIG_new();
244
2.93k
    if (ret == NULL) {
245
0
        ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
246
0
        return NULL;
247
0
    }
248
2.93k
    ret->r = BN_new();
249
2.93k
    ret->s = BN_new();
250
2.93k
    if (ret->r == NULL || ret->s == NULL) {
251
0
        ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
252
0
        goto err;
253
0
    }
254
2.93k
    s = ret->s;
255
256
2.93k
    if ((ctx = BN_CTX_new_ex(eckey->libctx)) == NULL
257
2.93k
        || (m = BN_new()) == NULL) {
258
0
        ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
259
0
        goto err;
260
0
    }
261
262
2.93k
    if ((order = EC_GROUP_get0_order(group)) == NULL) {
263
0
        ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
264
0
        goto err;
265
0
    }
266
267
2.93k
    i = BN_num_bits(order);
268
    /*
269
     * Need to truncate digest if it is too long: first truncate whole bytes.
270
     */
271
2.93k
    if (8 * dgst_len > i)
272
150
        dgst_len = (i + 7) / 8;
273
2.93k
    if (!BN_bin2bn(dgst, dgst_len, m)) {
274
0
        ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB);
275
0
        goto err;
276
0
    }
277
    /* If still too long, truncate remaining bits with a shift */
278
2.93k
    if ((8 * dgst_len > i) && !BN_rshift(m, m, 8 - (i & 0x7))) {
279
0
        ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB);
280
0
        goto err;
281
0
    }
282
2.93k
    do {
283
2.93k
        if (in_kinv == NULL || in_r == NULL) {
284
2.93k
            if (!ecdsa_sign_setup(eckey, ctx, &kinv, &ret->r, dgst, dgst_len)) {
285
0
                ERR_raise(ERR_LIB_EC, ERR_R_ECDSA_LIB);
286
0
                goto err;
287
0
            }
288
2.93k
            ckinv = kinv;
289
2.93k
        } else {
290
0
            ckinv = in_kinv;
291
0
            if (BN_copy(ret->r, in_r) == NULL) {
292
0
                ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
293
0
                goto err;
294
0
            }
295
0
        }
296
297
        /*
298
         * With only one multiplicant being in Montgomery domain
299
         * multiplication yields real result without post-conversion.
300
         * Also note that all operations but last are performed with
301
         * zero-padded vectors. Last operation, BN_mod_mul_montgomery
302
         * below, returns user-visible value with removed zero padding.
303
         */
304
2.93k
        if (!bn_to_mont_fixed_top(s, ret->r, group->mont_data, ctx)
305
2.93k
            || !bn_mul_mont_fixed_top(s, s, priv_key, group->mont_data, ctx)) {
306
0
            ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB);
307
0
            goto err;
308
0
        }
309
2.93k
        if (!bn_mod_add_fixed_top(s, s, m, order)) {
310
0
            ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB);
311
0
            goto err;
312
0
        }
313
        /*
314
         * |s| can still be larger than modulus, because |m| can be. In
315
         * such case we count on Montgomery reduction to tie it up.
316
         */
317
2.93k
        if (!bn_to_mont_fixed_top(s, s, group->mont_data, ctx)
318
2.93k
            || !BN_mod_mul_montgomery(s, s, ckinv, group->mont_data, ctx)) {
319
0
            ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB);
320
0
            goto err;
321
0
        }
322
323
2.93k
        if (BN_is_zero(s)) {
324
            /*
325
             * if kinv and r have been supplied by the caller, don't
326
             * generate new kinv and r values
327
             */
328
0
            if (in_kinv != NULL && in_r != NULL) {
329
0
                ERR_raise(ERR_LIB_EC, EC_R_NEED_NEW_SETUP_VALUES);
330
0
                goto err;
331
0
            }
332
            /* Avoid infinite loops cause by invalid group parameters */
333
0
            if (retries++ > MAX_ECDSA_SIGN_RETRIES) {
334
0
                ERR_raise(ERR_LIB_EC, EC_R_TOO_MANY_RETRIES);
335
0
                goto err;
336
0
            }
337
2.93k
        } else {
338
            /* s != 0 => we have a valid signature */
339
2.93k
            break;
340
2.93k
        }
341
2.93k
    } while (1);
342
343
2.93k
    ok = 1;
344
2.93k
 err:
345
2.93k
    if (!ok) {
346
0
        ECDSA_SIG_free(ret);
347
0
        ret = NULL;
348
0
    }
349
2.93k
    BN_CTX_free(ctx);
350
2.93k
    BN_clear_free(m);
351
2.93k
    BN_clear_free(kinv);
352
2.93k
    return ret;
353
2.93k
}
354
355
/*-
356
 * returns
357
 *      1: correct signature
358
 *      0: incorrect signature
359
 *     -1: error
360
 */
361
int ossl_ecdsa_verify(int type, const unsigned char *dgst, int dgst_len,
362
                      const unsigned char *sigbuf, int sig_len, EC_KEY *eckey)
363
1.28k
{
364
1.28k
    ECDSA_SIG *s;
365
1.28k
    const unsigned char *p = sigbuf;
366
1.28k
    unsigned char *der = NULL;
367
1.28k
    int derlen = -1;
368
1.28k
    int ret = -1;
369
370
1.28k
    s = ECDSA_SIG_new();
371
1.28k
    if (s == NULL)
372
0
        return ret;
373
1.28k
    if (d2i_ECDSA_SIG(&s, &p, sig_len) == NULL)
374
660
        goto err;
375
    /* Ensure signature uses DER and doesn't have trailing garbage */
376
623
    derlen = i2d_ECDSA_SIG(s, &der);
377
623
    if (derlen != sig_len || memcmp(sigbuf, der, derlen) != 0)
378
37
        goto err;
379
586
    ret = ECDSA_do_verify(dgst, dgst_len, s, eckey);
380
1.28k
 err:
381
1.28k
    OPENSSL_free(der);
382
1.28k
    ECDSA_SIG_free(s);
383
1.28k
    return ret;
384
586
}
385
386
int ossl_ecdsa_simple_verify_sig(const unsigned char *dgst, int dgst_len,
387
                                 const ECDSA_SIG *sig, EC_KEY *eckey)
388
586
{
389
586
    int ret = -1, i;
390
586
    BN_CTX *ctx;
391
586
    const BIGNUM *order;
392
586
    BIGNUM *u1, *u2, *m, *X;
393
586
    EC_POINT *point = NULL;
394
586
    const EC_GROUP *group;
395
586
    const EC_POINT *pub_key;
396
397
    /* check input values */
398
586
    if (eckey == NULL || (group = EC_KEY_get0_group(eckey)) == NULL ||
399
586
        (pub_key = EC_KEY_get0_public_key(eckey)) == NULL || sig == NULL) {
400
0
        ERR_raise(ERR_LIB_EC, EC_R_MISSING_PARAMETERS);
401
0
        return -1;
402
0
    }
403
404
586
    if (!EC_KEY_can_sign(eckey)) {
405
0
        ERR_raise(ERR_LIB_EC, EC_R_CURVE_DOES_NOT_SUPPORT_SIGNING);
406
0
        return -1;
407
0
    }
408
409
586
    ctx = BN_CTX_new_ex(eckey->libctx);
410
586
    if (ctx == NULL) {
411
0
        ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
412
0
        return -1;
413
0
    }
414
586
    BN_CTX_start(ctx);
415
586
    u1 = BN_CTX_get(ctx);
416
586
    u2 = BN_CTX_get(ctx);
417
586
    m = BN_CTX_get(ctx);
418
586
    X = BN_CTX_get(ctx);
419
586
    if (X == NULL) {
420
0
        ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB);
421
0
        goto err;
422
0
    }
423
424
586
    order = EC_GROUP_get0_order(group);
425
586
    if (order == NULL) {
426
0
        ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
427
0
        goto err;
428
0
    }
429
430
586
    if (BN_is_zero(sig->r) || BN_is_negative(sig->r) ||
431
586
        BN_ucmp(sig->r, order) >= 0 || BN_is_zero(sig->s) ||
432
586
        BN_is_negative(sig->s) || BN_ucmp(sig->s, order) >= 0) {
433
31
        ERR_raise(ERR_LIB_EC, EC_R_BAD_SIGNATURE);
434
31
        ret = 0;                /* signature is invalid */
435
31
        goto err;
436
31
    }
437
    /* calculate tmp1 = inv(S) mod order */
438
555
    if (!ossl_ec_group_do_inverse_ord(group, u2, sig->s, ctx)) {
439
0
        ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB);
440
0
        goto err;
441
0
    }
442
    /* digest -> m */
443
555
    i = BN_num_bits(order);
444
    /*
445
     * Need to truncate digest if it is too long: first truncate whole bytes.
446
     */
447
555
    if (8 * dgst_len > i)
448
77
        dgst_len = (i + 7) / 8;
449
555
    if (!BN_bin2bn(dgst, dgst_len, m)) {
450
0
        ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB);
451
0
        goto err;
452
0
    }
453
    /* If still too long truncate remaining bits with a shift */
454
555
    if ((8 * dgst_len > i) && !BN_rshift(m, m, 8 - (i & 0x7))) {
455
0
        ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB);
456
0
        goto err;
457
0
    }
458
    /* u1 = m * tmp mod order */
459
555
    if (!BN_mod_mul(u1, m, u2, order, ctx)) {
460
0
        ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB);
461
0
        goto err;
462
0
    }
463
    /* u2 = r * w mod q */
464
555
    if (!BN_mod_mul(u2, sig->r, u2, order, ctx)) {
465
0
        ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB);
466
0
        goto err;
467
0
    }
468
469
555
    if ((point = EC_POINT_new(group)) == NULL) {
470
0
        ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
471
0
        goto err;
472
0
    }
473
555
    if (!EC_POINT_mul(group, point, u1, pub_key, u2, ctx)) {
474
0
        ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
475
0
        goto err;
476
0
    }
477
478
555
    if (!EC_POINT_get_affine_coordinates(group, point, X, NULL, ctx)) {
479
0
        ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
480
0
        goto err;
481
0
    }
482
483
555
    if (!BN_nnmod(u1, X, order, ctx)) {
484
0
        ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB);
485
0
        goto err;
486
0
    }
487
    /*  if the signature is correct u1 is equal to sig->r */
488
555
    ret = (BN_ucmp(u1, sig->r) == 0);
489
586
 err:
490
586
    BN_CTX_end(ctx);
491
586
    BN_CTX_free(ctx);
492
586
    EC_POINT_free(point);
493
586
    return ret;
494
555
}