Coverage Report

Created: 2026-02-18 06:59

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/nss/lib/freebl/ecl/ecp_secp256r1.c
Line
Count
Source
1
/* P-256 from HACL* */
2
3
#ifdef FREEBL_NO_DEPEND
4
#include "../stubs.h"
5
#endif
6
7
#include "ecl-priv.h"
8
#include "secitem.h"
9
#include "secerr.h"
10
#include "secmpi.h"
11
#include "../verified/Hacl_P256.h"
12
13
/*
14
 * Point Validation for P-256.
15
 */
16
17
SECStatus
18
ec_secp256r1_pt_validate(const SECItem *pt)
19
252k
{
20
252k
    SECStatus res = SECSuccess;
21
252k
    if (!pt || !pt->data) {
22
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
23
0
        res = SECFailure;
24
0
        return res;
25
0
    }
26
27
252k
    if (pt->len != 65) {
28
818
        PORT_SetError(SEC_ERROR_BAD_KEY);
29
818
        res = SECFailure;
30
818
        return res;
31
818
    }
32
33
251k
    if (pt->data[0] != EC_POINT_FORM_UNCOMPRESSED) {
34
180
        PORT_SetError(SEC_ERROR_UNSUPPORTED_EC_POINT_FORM);
35
180
        res = SECFailure;
36
180
        return res;
37
180
    }
38
39
#ifndef UNSAFE_FUZZER_MODE
40
125k
    bool b = Hacl_P256_validate_public_key(pt->data + 1);
41
#else
42
125k
    bool b = PR_TRUE;
43
#endif
44
45
251k
    if (!b) {
46
498
        PORT_SetError(SEC_ERROR_BAD_KEY);
47
498
        res = SECFailure;
48
498
    }
49
125k
    return res;
50
251k
}
ec_secp256r1_pt_validate
Line
Count
Source
19
126k
{
20
126k
    SECStatus res = SECSuccess;
21
126k
    if (!pt || !pt->data) {
22
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
23
0
        res = SECFailure;
24
0
        return res;
25
0
    }
26
27
126k
    if (pt->len != 65) {
28
409
        PORT_SetError(SEC_ERROR_BAD_KEY);
29
409
        res = SECFailure;
30
409
        return res;
31
409
    }
32
33
125k
    if (pt->data[0] != EC_POINT_FORM_UNCOMPRESSED) {
34
90
        PORT_SetError(SEC_ERROR_UNSUPPORTED_EC_POINT_FORM);
35
90
        res = SECFailure;
36
90
        return res;
37
90
    }
38
39
125k
#ifndef UNSAFE_FUZZER_MODE
40
125k
    bool b = Hacl_P256_validate_public_key(pt->data + 1);
41
#else
42
    bool b = PR_TRUE;
43
#endif
44
45
125k
    if (!b) {
46
249
        PORT_SetError(SEC_ERROR_BAD_KEY);
47
249
        res = SECFailure;
48
249
    }
49
125k
    return res;
50
125k
}
ec_secp256r1_pt_validate
Line
Count
Source
19
126k
{
20
126k
    SECStatus res = SECSuccess;
21
126k
    if (!pt || !pt->data) {
22
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
23
0
        res = SECFailure;
24
0
        return res;
25
0
    }
26
27
126k
    if (pt->len != 65) {
28
409
        PORT_SetError(SEC_ERROR_BAD_KEY);
29
409
        res = SECFailure;
30
409
        return res;
31
409
    }
32
33
125k
    if (pt->data[0] != EC_POINT_FORM_UNCOMPRESSED) {
34
90
        PORT_SetError(SEC_ERROR_UNSUPPORTED_EC_POINT_FORM);
35
90
        res = SECFailure;
36
90
        return res;
37
90
    }
38
39
#ifndef UNSAFE_FUZZER_MODE
40
    bool b = Hacl_P256_validate_public_key(pt->data + 1);
41
#else
42
125k
    bool b = PR_TRUE;
43
125k
#endif
44
45
125k
    if (!b) {
46
249
        PORT_SetError(SEC_ERROR_BAD_KEY);
47
249
        res = SECFailure;
48
249
    }
49
125k
    return res;
50
125k
}
51
52
/*
53
 * Scalar Validation for P-256.
54
 */
55
56
SECStatus
57
ec_secp256r1_scalar_validate(const SECItem *scalar)
58
141k
{
59
141k
    SECStatus res = SECSuccess;
60
141k
    if (!scalar || !scalar->data) {
61
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
62
0
        res = SECFailure;
63
0
        return res;
64
0
    }
65
66
141k
    if (scalar->len != 32) {
67
0
        PORT_SetError(SEC_ERROR_BAD_KEY);
68
0
        res = SECFailure;
69
0
        return res;
70
0
    }
71
72
#ifndef UNSAFE_FUZZER_MODE
73
70.8k
    bool b = Hacl_P256_validate_private_key(scalar->data);
74
#else
75
70.8k
    bool b = PR_TRUE;
76
#endif
77
78
141k
    if (!b) {
79
0
        PORT_SetError(SEC_ERROR_BAD_KEY);
80
0
        res = SECFailure;
81
0
    }
82
70.8k
    return res;
83
141k
}
ec_secp256r1_scalar_validate
Line
Count
Source
58
70.8k
{
59
70.8k
    SECStatus res = SECSuccess;
60
70.8k
    if (!scalar || !scalar->data) {
61
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
62
0
        res = SECFailure;
63
0
        return res;
64
0
    }
65
66
70.8k
    if (scalar->len != 32) {
67
0
        PORT_SetError(SEC_ERROR_BAD_KEY);
68
0
        res = SECFailure;
69
0
        return res;
70
0
    }
71
72
70.8k
#ifndef UNSAFE_FUZZER_MODE
73
70.8k
    bool b = Hacl_P256_validate_private_key(scalar->data);
74
#else
75
    bool b = PR_TRUE;
76
#endif
77
78
70.8k
    if (!b) {
79
0
        PORT_SetError(SEC_ERROR_BAD_KEY);
80
0
        res = SECFailure;
81
0
    }
82
70.8k
    return res;
83
70.8k
}
ec_secp256r1_scalar_validate
Line
Count
Source
58
70.8k
{
59
70.8k
    SECStatus res = SECSuccess;
60
70.8k
    if (!scalar || !scalar->data) {
61
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
62
0
        res = SECFailure;
63
0
        return res;
64
0
    }
65
66
70.8k
    if (scalar->len != 32) {
67
0
        PORT_SetError(SEC_ERROR_BAD_KEY);
68
0
        res = SECFailure;
69
0
        return res;
70
0
    }
71
72
#ifndef UNSAFE_FUZZER_MODE
73
    bool b = Hacl_P256_validate_private_key(scalar->data);
74
#else
75
70.8k
    bool b = PR_TRUE;
76
70.8k
#endif
77
78
70.8k
    if (!b) {
79
0
        PORT_SetError(SEC_ERROR_BAD_KEY);
80
0
        res = SECFailure;
81
0
    }
82
70.8k
    return res;
83
70.8k
}
84
85
/*
86
 * Scalar multiplication for P-256.
87
 * If P == NULL, the base point is used.
88
 * Returns X = k*P
89
 */
90
91
SECStatus
92
ec_secp256r1_pt_mul(SECItem *X, SECItem *k, SECItem *P)
93
261k
{
94
261k
    SECStatus res = SECSuccess;
95
261k
    if (!P) {
96
133k
        uint8_t derived[64] = { 0 };
97
98
133k
        if (!X || !k || !X->data || !k->data ||
99
133k
            X->len < 65 || k->len != 32) {
100
8
            PORT_SetError(SEC_ERROR_INVALID_ARGS);
101
8
            res = SECFailure;
102
8
            return res;
103
8
        }
104
105
#ifndef UNSAFE_FUZZER_MODE
106
66.9k
        bool b = Hacl_P256_dh_initiator(derived, k->data);
107
#else
108
66.9k
        bool b = PR_TRUE;
109
#endif
110
111
133k
        if (!b) {
112
32
            PORT_SetError(SEC_ERROR_BAD_KEY);
113
32
            res = SECFailure;
114
32
            return res;
115
32
        }
116
117
133k
        X->len = 65;
118
133k
        X->data[0] = EC_POINT_FORM_UNCOMPRESSED;
119
133k
        memcpy(X->data + 1, derived, 64);
120
121
133k
    } else {
122
127k
        uint8_t full_key[32] = { 0 };
123
127k
        uint8_t *key;
124
127k
        uint8_t derived[64] = { 0 };
125
126
127k
        if (!X || !k || !P || !X->data || !k->data || !P->data ||
127
127k
            X->len < 32 || P->len != 65 ||
128
127k
            P->data[0] != EC_POINT_FORM_UNCOMPRESSED) {
129
0
            PORT_SetError(SEC_ERROR_INVALID_ARGS);
130
0
            res = SECFailure;
131
0
            return res;
132
0
        }
133
134
        /* We consider keys of up to size 32, or of size 33 with a single leading 0 */
135
127k
        if (k->len < 32) {
136
0
            memcpy(full_key + 32 - k->len, k->data, k->len);
137
0
            key = full_key;
138
127k
        } else if (k->len == 32) {
139
127k
            key = k->data;
140
127k
        } else if (k->len == 33 && k->data[0] == 0) {
141
0
            key = k->data + 1;
142
0
        } else {
143
0
            PORT_SetError(SEC_ERROR_INVALID_ARGS);
144
0
            res = SECFailure;
145
0
            return res;
146
0
        }
147
148
127k
        bool b = Hacl_P256_dh_responder(derived, P->data + 1, key);
149
150
127k
        if (!b) {
151
22.6k
            PORT_SetError(SEC_ERROR_BAD_KEY);
152
22.6k
            res = SECFailure;
153
22.6k
            return res;
154
22.6k
        }
155
156
104k
        X->len = 32;
157
104k
        memcpy(X->data, derived, 32);
158
104k
    }
159
160
238k
    return res;
161
261k
}
ec_secp256r1_pt_mul
Line
Count
Source
93
130k
{
94
130k
    SECStatus res = SECSuccess;
95
130k
    if (!P) {
96
66.9k
        uint8_t derived[64] = { 0 };
97
98
66.9k
        if (!X || !k || !X->data || !k->data ||
99
66.9k
            X->len < 65 || k->len != 32) {
100
4
            PORT_SetError(SEC_ERROR_INVALID_ARGS);
101
4
            res = SECFailure;
102
4
            return res;
103
4
        }
104
105
66.9k
#ifndef UNSAFE_FUZZER_MODE
106
66.9k
        bool b = Hacl_P256_dh_initiator(derived, k->data);
107
#else
108
        bool b = PR_TRUE;
109
#endif
110
111
66.9k
        if (!b) {
112
16
            PORT_SetError(SEC_ERROR_BAD_KEY);
113
16
            res = SECFailure;
114
16
            return res;
115
16
        }
116
117
66.9k
        X->len = 65;
118
66.9k
        X->data[0] = EC_POINT_FORM_UNCOMPRESSED;
119
66.9k
        memcpy(X->data + 1, derived, 64);
120
121
66.9k
    } else {
122
63.6k
        uint8_t full_key[32] = { 0 };
123
63.6k
        uint8_t *key;
124
63.6k
        uint8_t derived[64] = { 0 };
125
126
63.6k
        if (!X || !k || !P || !X->data || !k->data || !P->data ||
127
63.6k
            X->len < 32 || P->len != 65 ||
128
63.6k
            P->data[0] != EC_POINT_FORM_UNCOMPRESSED) {
129
0
            PORT_SetError(SEC_ERROR_INVALID_ARGS);
130
0
            res = SECFailure;
131
0
            return res;
132
0
        }
133
134
        /* We consider keys of up to size 32, or of size 33 with a single leading 0 */
135
63.6k
        if (k->len < 32) {
136
0
            memcpy(full_key + 32 - k->len, k->data, k->len);
137
0
            key = full_key;
138
63.6k
        } else if (k->len == 32) {
139
63.6k
            key = k->data;
140
63.6k
        } else if (k->len == 33 && k->data[0] == 0) {
141
0
            key = k->data + 1;
142
0
        } else {
143
0
            PORT_SetError(SEC_ERROR_INVALID_ARGS);
144
0
            res = SECFailure;
145
0
            return res;
146
0
        }
147
148
63.6k
        bool b = Hacl_P256_dh_responder(derived, P->data + 1, key);
149
150
63.6k
        if (!b) {
151
11.3k
            PORT_SetError(SEC_ERROR_BAD_KEY);
152
11.3k
            res = SECFailure;
153
11.3k
            return res;
154
11.3k
        }
155
156
52.3k
        X->len = 32;
157
52.3k
        memcpy(X->data, derived, 32);
158
52.3k
    }
159
160
119k
    return res;
161
130k
}
ec_secp256r1_pt_mul
Line
Count
Source
93
130k
{
94
130k
    SECStatus res = SECSuccess;
95
130k
    if (!P) {
96
66.9k
        uint8_t derived[64] = { 0 };
97
98
66.9k
        if (!X || !k || !X->data || !k->data ||
99
66.9k
            X->len < 65 || k->len != 32) {
100
4
            PORT_SetError(SEC_ERROR_INVALID_ARGS);
101
4
            res = SECFailure;
102
4
            return res;
103
4
        }
104
105
#ifndef UNSAFE_FUZZER_MODE
106
        bool b = Hacl_P256_dh_initiator(derived, k->data);
107
#else
108
66.9k
        bool b = PR_TRUE;
109
66.9k
#endif
110
111
66.9k
        if (!b) {
112
16
            PORT_SetError(SEC_ERROR_BAD_KEY);
113
16
            res = SECFailure;
114
16
            return res;
115
16
        }
116
117
66.9k
        X->len = 65;
118
66.9k
        X->data[0] = EC_POINT_FORM_UNCOMPRESSED;
119
66.9k
        memcpy(X->data + 1, derived, 64);
120
121
66.9k
    } else {
122
63.6k
        uint8_t full_key[32] = { 0 };
123
63.6k
        uint8_t *key;
124
63.6k
        uint8_t derived[64] = { 0 };
125
126
63.6k
        if (!X || !k || !P || !X->data || !k->data || !P->data ||
127
63.6k
            X->len < 32 || P->len != 65 ||
128
63.6k
            P->data[0] != EC_POINT_FORM_UNCOMPRESSED) {
129
0
            PORT_SetError(SEC_ERROR_INVALID_ARGS);
130
0
            res = SECFailure;
131
0
            return res;
132
0
        }
133
134
        /* We consider keys of up to size 32, or of size 33 with a single leading 0 */
135
63.6k
        if (k->len < 32) {
136
0
            memcpy(full_key + 32 - k->len, k->data, k->len);
137
0
            key = full_key;
138
63.6k
        } else if (k->len == 32) {
139
63.6k
            key = k->data;
140
63.6k
        } else if (k->len == 33 && k->data[0] == 0) {
141
0
            key = k->data + 1;
142
0
        } else {
143
0
            PORT_SetError(SEC_ERROR_INVALID_ARGS);
144
0
            res = SECFailure;
145
0
            return res;
146
0
        }
147
148
63.6k
        bool b = Hacl_P256_dh_responder(derived, P->data + 1, key);
149
150
63.6k
        if (!b) {
151
11.3k
            PORT_SetError(SEC_ERROR_BAD_KEY);
152
11.3k
            res = SECFailure;
153
11.3k
            return res;
154
11.3k
        }
155
156
52.3k
        X->len = 32;
157
52.3k
        memcpy(X->data, derived, 32);
158
52.3k
    }
159
160
119k
    return res;
161
130k
}
162
163
/*
164
 * ECDSA Signature for P-256
165
 */
166
167
SECStatus
168
ec_secp256r1_sign_digest(ECPrivateKey *ecPrivKey, SECItem *signature,
169
                         const SECItem *digest, const unsigned char *kb,
170
                         const unsigned int kblen)
171
984
{
172
984
    SECStatus res = SECSuccess;
173
174
984
    if (!ecPrivKey || !signature || !digest || !kb ||
175
984
        !ecPrivKey->privateValue.data ||
176
984
        !signature->data || !digest->data ||
177
984
        ecPrivKey->ecParams.name != ECCurve_NIST_P256) {
178
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
179
0
        res = SECFailure;
180
0
        return res;
181
0
    }
182
183
984
    if (kblen == 0 || digest->len == 0 || signature->len < 64) {
184
0
        PORT_SetError(SEC_ERROR_INPUT_LEN);
185
0
        res = SECFailure;
186
0
        return res;
187
0
    }
188
189
    // Private keys should be 32 bytes, but some software trims leading zeros,
190
    // and some software produces 33 byte keys with a leading zero. We'll
191
    // accept these variants.
192
984
    uint8_t padded_key_data[32] = { 0 };
193
984
    uint8_t *key;
194
984
    SECItem *privKey = &ecPrivKey->privateValue;
195
984
    if (privKey->len == 32) {
196
984
        key = privKey->data;
197
984
    } else if (privKey->len == 33 && privKey->data[0] == 0) {
198
0
        key = privKey->data + 1;
199
0
    } else if (privKey->len < 32) {
200
0
        memcpy(padded_key_data + 32 - privKey->len, privKey->data, privKey->len);
201
0
        key = padded_key_data;
202
0
    } else {
203
0
        PORT_SetError(SEC_ERROR_INPUT_LEN);
204
0
        return SECFailure;
205
0
    }
206
207
984
    uint8_t hash[32] = { 0 };
208
984
    if (digest->len < 32) {
209
555
        memcpy(hash + 32 - digest->len, digest->data, digest->len);
210
555
    } else {
211
429
        memcpy(hash, digest->data, 32);
212
429
    }
213
214
984
    uint8_t nonce[32] = { 0 };
215
984
    if (kblen < 32) {
216
24
        memcpy(nonce + 32 - kblen, kb, kblen);
217
960
    } else {
218
960
        memcpy(nonce, kb, 32);
219
960
    }
220
221
984
#ifndef UNSAFE_FUZZER_MODE
222
984
    bool b = Hacl_P256_ecdsa_sign_p256_without_hash(
223
984
        signature->data, 32, hash, key, nonce);
224
#else
225
    bool b = key != NULL;                        /* Avoiding unused variable warnings */
226
#endif
227
228
984
    if (!b) {
229
6
        PORT_SetError(SEC_ERROR_BAD_KEY);
230
6
        res = SECFailure;
231
6
        return res;
232
6
    }
233
234
978
    signature->len = 64;
235
978
    return res;
236
984
}
237
238
/*
239
 * ECDSA Signature Verification for P-256
240
 */
241
242
SECStatus
243
ec_secp256r1_verify_digest(ECPublicKey *key, const SECItem *signature,
244
                           const SECItem *digest)
245
394
{
246
394
    SECStatus res = SECSuccess;
247
248
394
    unsigned char _padded_sig_data[64] = { 0 };
249
394
    unsigned char *sig_r, *sig_s;
250
251
394
    if (!key || !signature || !digest ||
252
394
        !key->publicValue.data ||
253
394
        !signature->data || !digest->data ||
254
394
        key->ecParams.name != ECCurve_NIST_P256) {
255
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
256
0
        res = SECFailure;
257
0
        return res;
258
0
    }
259
260
394
    unsigned int olen = key->ecParams.order.len;
261
394
    if (signature->len == 0 || signature->len % 2 != 0 ||
262
394
        signature->len > 2 * olen ||
263
394
        digest->len == 0 || key->publicValue.len != 65) {
264
0
        PORT_SetError(SEC_ERROR_INPUT_LEN);
265
0
        res = SECFailure;
266
0
        return res;
267
0
    }
268
269
394
    if (key->publicValue.data[0] != EC_POINT_FORM_UNCOMPRESSED) {
270
0
        PORT_SetError(SEC_ERROR_UNSUPPORTED_EC_POINT_FORM);
271
0
        res = SECFailure;
272
0
        return res;
273
0
    }
274
275
    /* P-256 signature has to be 64 bytes long, pad it with 0s if it isn't */
276
394
    if (signature->len != 64) {
277
0
        unsigned split = signature->len / 2;
278
0
        unsigned pad = 32 - split;
279
280
0
        unsigned char *o_sig = signature->data;
281
0
        unsigned char *p_sig = _padded_sig_data;
282
283
0
        memcpy(p_sig + pad, o_sig, split);
284
0
        memcpy(p_sig + 32 + pad, o_sig + split, split);
285
286
0
        sig_r = p_sig;
287
0
        sig_s = p_sig + 32;
288
394
    } else {
289
394
        sig_r = signature->data;
290
394
        sig_s = signature->data + 32;
291
394
    }
292
293
394
    uint8_t hash[32] = { 0 };
294
394
    if (digest->len < 32) {
295
108
        memcpy(hash + 32 - digest->len, digest->data, digest->len);
296
286
    } else {
297
286
        memcpy(hash, digest->data, 32);
298
286
    }
299
300
394
#ifndef UNSAFE_FUZZER_MODE
301
394
    bool b = Hacl_P256_ecdsa_verif_without_hash(
302
394
        32, hash,
303
394
        key->publicValue.data + 1,
304
394
        sig_r, sig_s);
305
#else
306
    bool b = (sig_r != NULL) && (sig_s != NULL); /* Avoiding unused variable warnings */
307
#endif
308
309
394
    if (!b) {
310
301
        PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
311
301
        res = SECFailure;
312
301
        return res;
313
301
    }
314
315
93
    return res;
316
394
}
317
318
/*
319
    Point decompression for P-256.
320
321
    publicCompressed must be 33 bytes (1 byte for a sign and 32 bytes for the x coordinate.
322
    publicUncompressed must be 64 bytes (32 * 2).
323
    The function returns SECSuccess if the decompression was success and the decompresse
324
    point is a valid P-256 curve point.
325
*/
326
327
SECStatus
328
ec_secp256r1_decompress(const SECItem *publicCompressed, SECItem *publicUncompressed)
329
106
{
330
106
    if (!publicCompressed || !publicCompressed->data) {
331
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
332
0
        return SECFailure;
333
0
    }
334
335
106
    if (publicCompressed->len != 33) {
336
106
        PORT_SetError(SEC_ERROR_BAD_KEY);
337
106
        return SECFailure;
338
106
    }
339
340
0
    if (!publicUncompressed || !publicUncompressed->data) {
341
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
342
0
        return SECFailure;
343
0
    }
344
345
0
    if (publicUncompressed->len != 65) {
346
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
347
0
        return SECFailure;
348
0
    }
349
350
0
    if (publicCompressed->data[0] != EC_POINT_FORM_COMPRESSED_Y0 &&
351
0
        publicCompressed->data[0] != EC_POINT_FORM_COMPRESSED_Y1) {
352
0
        PORT_SetError(SEC_ERROR_UNSUPPORTED_EC_POINT_FORM);
353
0
        return SECFailure;
354
0
    }
355
356
0
    bool b = Hacl_P256_compressed_to_raw(publicCompressed->data, publicUncompressed->data + 1);
357
358
0
    if (!b) {
359
0
        PORT_SetError(SEC_ERROR_BAD_KEY);
360
0
        return SECFailure;
361
0
    }
362
363
0
    publicUncompressed->data[0] = EC_POINT_FORM_UNCOMPRESSED;
364
0
    return SECSuccess;
365
0
}