Coverage Report

Created: 2025-12-31 06:58

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/openssl30/crypto/ec/ecdsa_ossl.c
Line
Count
Source
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
1.40k
#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
6.75k
{
47
6.75k
    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
6.75k
    return eckey->group->meth->ecdsa_sign_sig(dgst, dgst_len,
53
6.75k
        in_kinv, in_r, eckey);
54
6.75k
}
55
56
int ossl_ecdsa_verify_sig(const unsigned char *dgst, int dgst_len,
57
    const ECDSA_SIG *sig, EC_KEY *eckey)
58
1.53k
{
59
1.53k
    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
1.53k
    return eckey->group->meth->ecdsa_verify_sig(dgst, dgst_len, sig, eckey);
65
1.53k
}
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
6.75k
{
71
6.75k
    ECDSA_SIG *s;
72
73
6.75k
    if (sig == NULL && (kinv == NULL || r == NULL)) {
74
0
        *siglen = ECDSA_size(eckey);
75
0
        return 1;
76
0
    }
77
78
6.75k
    s = ECDSA_do_sign_ex(dgst, dlen, kinv, r, eckey);
79
6.75k
    if (s == NULL) {
80
0
        *siglen = 0;
81
0
        return 0;
82
0
    }
83
6.75k
    *siglen = i2d_ECDSA_SIG(s, sig != NULL ? &sig : NULL);
84
6.75k
    ECDSA_SIG_free(s);
85
6.75k
    return 1;
86
6.75k
}
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
701
{
92
701
    BN_CTX *ctx = NULL;
93
701
    BIGNUM *k = NULL, *r = NULL, *X = NULL;
94
701
    const BIGNUM *order;
95
701
    EC_POINT *tmp_point = NULL;
96
701
    const EC_GROUP *group;
97
701
    int ret = 0;
98
701
    int order_bits;
99
701
    const BIGNUM *priv_key;
100
101
701
    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
701
    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
701
    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
701
    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
701
    k = BN_secure_new(); /* this value is later returned in *kinvp */
123
701
    r = BN_new(); /* this value is later returned in *rp */
124
701
    X = BN_new();
125
701
    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
701
    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
701
    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
701
    order_bits = BN_num_bits(order);
141
    /* Check the number of bits here so that an infinite loop is not possible */
142
701
    if (order_bits < MIN_ECDSA_SIGN_ORDERBITS
143
701
        || !BN_set_bit(k, order_bits)
144
701
        || !BN_set_bit(r, order_bits)
145
701
        || !BN_set_bit(X, order_bits))
146
0
        goto err;
147
148
701
    do {
149
        /* get random k */
150
701
        do {
151
701
            if (dgst != NULL) {
152
701
                if (!ossl_bn_gen_dsa_nonce_fixed_top(k, order, priv_key,
153
701
                        dgst, dlen, ctx)) {
154
0
                    ERR_raise(ERR_LIB_EC, EC_R_RANDOM_NUMBER_GENERATION_FAILED);
155
0
                    goto err;
156
0
                }
157
701
            } 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
701
        } while (ossl_bn_is_word_fixed_top(k, 0));
164
165
        /* compute r the x-coordinate of generator * k */
166
701
        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
701
        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
701
        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
701
    } while (BN_is_zero(r));
181
182
    /* compute the inverse of k */
183
701
    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
701
    BN_clear_free(*rp);
190
701
    BN_clear_free(*kinvp);
191
    /* save the pre-computed values  */
192
701
    *rp = r;
193
701
    *kinvp = k;
194
701
    ret = 1;
195
701
err:
196
701
    if (!ret) {
197
0
        BN_clear_free(k);
198
0
        BN_clear_free(r);
199
0
    }
200
701
    if (ctx != ctx_in)
201
0
        BN_CTX_free(ctx);
202
701
    EC_POINT_free(tmp_point);
203
701
    BN_clear_free(X);
204
701
    return ret;
205
701
}
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
6.75k
{
217
6.75k
    int ok = 0, i;
218
6.75k
    int retries = 0;
219
6.75k
    BIGNUM *kinv = NULL, *s, *m = NULL;
220
6.75k
    const BIGNUM *order, *ckinv;
221
6.75k
    BN_CTX *ctx = NULL;
222
6.75k
    const EC_GROUP *group;
223
6.75k
    ECDSA_SIG *ret;
224
6.75k
    const BIGNUM *priv_key;
225
226
6.75k
    group = EC_KEY_get0_group(eckey);
227
6.75k
    priv_key = EC_KEY_get0_private_key(eckey);
228
229
6.75k
    if (group == NULL) {
230
0
        ERR_raise(ERR_LIB_EC, ERR_R_PASSED_NULL_PARAMETER);
231
0
        return NULL;
232
0
    }
233
6.75k
    if (priv_key == NULL) {
234
0
        ERR_raise(ERR_LIB_EC, EC_R_MISSING_PRIVATE_KEY);
235
0
        return NULL;
236
0
    }
237
238
6.75k
    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
6.75k
    ret = ECDSA_SIG_new();
244
6.75k
    if (ret == NULL) {
245
0
        ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
246
0
        return NULL;
247
0
    }
248
6.75k
    ret->r = BN_new();
249
6.75k
    ret->s = BN_new();
250
6.75k
    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
6.75k
    s = ret->s;
255
256
6.75k
    if ((ctx = BN_CTX_new_ex(eckey->libctx)) == NULL
257
6.75k
        || (m = BN_new()) == NULL) {
258
0
        ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
259
0
        goto err;
260
0
    }
261
262
6.75k
    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
6.75k
    i = BN_num_bits(order);
268
    /*
269
     * Need to truncate digest if it is too long: first truncate whole bytes.
270
     */
271
6.75k
    if (8 * dgst_len > i)
272
251
        dgst_len = (i + 7) / 8;
273
6.75k
    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
6.75k
    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
6.75k
    do {
283
6.75k
        if (in_kinv == NULL || in_r == NULL) {
284
6.75k
            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
6.75k
            ckinv = kinv;
289
6.75k
        } 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
6.75k
        if (!bn_to_mont_fixed_top(s, ret->r, group->mont_data, ctx)
305
6.75k
            || !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
6.75k
        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
6.75k
        if (!bn_to_mont_fixed_top(s, s, group->mont_data, ctx)
318
6.75k
            || !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
6.75k
        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
6.75k
        } else {
338
            /* s != 0 => we have a valid signature */
339
6.75k
            break;
340
6.75k
        }
341
6.75k
    } while (1);
342
343
6.75k
    ok = 1;
344
6.75k
err:
345
6.75k
    if (!ok) {
346
0
        ECDSA_SIG_free(ret);
347
0
        ret = NULL;
348
0
    }
349
6.75k
    BN_CTX_free(ctx);
350
6.75k
    BN_clear_free(m);
351
6.75k
    BN_clear_free(kinv);
352
6.75k
    return ret;
353
6.75k
}
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
2.60k
{
364
2.60k
    ECDSA_SIG *s;
365
2.60k
    const unsigned char *p = sigbuf;
366
2.60k
    unsigned char *der = NULL;
367
2.60k
    int derlen = -1;
368
2.60k
    int ret = -1;
369
370
2.60k
    s = ECDSA_SIG_new();
371
2.60k
    if (s == NULL)
372
0
        return ret;
373
2.60k
    if (d2i_ECDSA_SIG(&s, &p, sig_len) == NULL)
374
1.03k
        goto err;
375
    /* Ensure signature uses DER and doesn't have trailing garbage */
376
1.57k
    derlen = i2d_ECDSA_SIG(s, &der);
377
1.57k
    if (derlen != sig_len || memcmp(sigbuf, der, derlen) != 0)
378
38
        goto err;
379
1.53k
    ret = ECDSA_do_verify(dgst, dgst_len, s, eckey);
380
2.60k
err:
381
2.60k
    OPENSSL_free(der);
382
2.60k
    ECDSA_SIG_free(s);
383
2.60k
    return ret;
384
1.53k
}
385
386
int ossl_ecdsa_simple_verify_sig(const unsigned char *dgst, int dgst_len,
387
    const ECDSA_SIG *sig, EC_KEY *eckey)
388
1.53k
{
389
1.53k
    int ret = -1, i;
390
1.53k
    BN_CTX *ctx;
391
1.53k
    const BIGNUM *order;
392
1.53k
    BIGNUM *u1, *u2, *m, *X;
393
1.53k
    EC_POINT *point = NULL;
394
1.53k
    const EC_GROUP *group;
395
1.53k
    const EC_POINT *pub_key;
396
397
    /* check input values */
398
1.53k
    if (eckey == NULL || (group = EC_KEY_get0_group(eckey)) == NULL || (pub_key = EC_KEY_get0_public_key(eckey)) == NULL || sig == NULL) {
399
0
        ERR_raise(ERR_LIB_EC, EC_R_MISSING_PARAMETERS);
400
0
        return -1;
401
0
    }
402
403
1.53k
    if (!EC_KEY_can_sign(eckey)) {
404
0
        ERR_raise(ERR_LIB_EC, EC_R_CURVE_DOES_NOT_SUPPORT_SIGNING);
405
0
        return -1;
406
0
    }
407
408
1.53k
    ctx = BN_CTX_new_ex(eckey->libctx);
409
1.53k
    if (ctx == NULL) {
410
0
        ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
411
0
        return -1;
412
0
    }
413
1.53k
    BN_CTX_start(ctx);
414
1.53k
    u1 = BN_CTX_get(ctx);
415
1.53k
    u2 = BN_CTX_get(ctx);
416
1.53k
    m = BN_CTX_get(ctx);
417
1.53k
    X = BN_CTX_get(ctx);
418
1.53k
    if (X == NULL) {
419
0
        ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB);
420
0
        goto err;
421
0
    }
422
423
1.53k
    order = EC_GROUP_get0_order(group);
424
1.53k
    if (order == NULL) {
425
0
        ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
426
0
        goto err;
427
0
    }
428
429
1.53k
    if (BN_is_zero(sig->r) || BN_is_negative(sig->r) || BN_ucmp(sig->r, order) >= 0 || BN_is_zero(sig->s) || BN_is_negative(sig->s) || BN_ucmp(sig->s, order) >= 0) {
430
47
        ERR_raise(ERR_LIB_EC, EC_R_BAD_SIGNATURE);
431
47
        ret = 0; /* signature is invalid */
432
47
        goto err;
433
47
    }
434
    /* calculate tmp1 = inv(S) mod order */
435
1.48k
    if (!ossl_ec_group_do_inverse_ord(group, u2, sig->s, ctx)) {
436
0
        ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB);
437
0
        goto err;
438
0
    }
439
    /* digest -> m */
440
1.48k
    i = BN_num_bits(order);
441
    /*
442
     * Need to truncate digest if it is too long: first truncate whole bytes.
443
     */
444
1.48k
    if (8 * dgst_len > i)
445
388
        dgst_len = (i + 7) / 8;
446
1.48k
    if (!BN_bin2bn(dgst, dgst_len, m)) {
447
0
        ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB);
448
0
        goto err;
449
0
    }
450
    /* If still too long truncate remaining bits with a shift */
451
1.48k
    if ((8 * dgst_len > i) && !BN_rshift(m, m, 8 - (i & 0x7))) {
452
0
        ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB);
453
0
        goto err;
454
0
    }
455
    /* u1 = m * tmp mod order */
456
1.48k
    if (!BN_mod_mul(u1, m, u2, order, ctx)) {
457
0
        ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB);
458
0
        goto err;
459
0
    }
460
    /* u2 = r * w mod q */
461
1.48k
    if (!BN_mod_mul(u2, sig->r, u2, order, ctx)) {
462
0
        ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB);
463
0
        goto err;
464
0
    }
465
466
1.48k
    if ((point = EC_POINT_new(group)) == NULL) {
467
0
        ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
468
0
        goto err;
469
0
    }
470
1.48k
    if (!EC_POINT_mul(group, point, u1, pub_key, u2, ctx)) {
471
0
        ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
472
0
        goto err;
473
0
    }
474
475
1.48k
    if (!EC_POINT_get_affine_coordinates(group, point, X, NULL, ctx)) {
476
0
        ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
477
0
        goto err;
478
0
    }
479
480
1.48k
    if (!BN_nnmod(u1, X, order, ctx)) {
481
0
        ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB);
482
0
        goto err;
483
0
    }
484
    /*  if the signature is correct u1 is equal to sig->r */
485
1.48k
    ret = (BN_ucmp(u1, sig->r) == 0);
486
1.53k
err:
487
1.53k
    BN_CTX_end(ctx);
488
1.53k
    BN_CTX_free(ctx);
489
1.53k
    EC_POINT_free(point);
490
1.53k
    return ret;
491
1.48k
}