Coverage Report

Created: 2025-06-24 06:49

/src/nss/lib/freebl/ecl/ecp_secp256r1.c
Line
Count
Source (jump to first uncovered line)
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
208k
{
20
208k
    SECStatus res = SECSuccess;
21
208k
    if (!pt || !pt->data) {
22
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
23
0
        res = SECFailure;
24
0
        return res;
25
0
    }
26
27
208k
    if (pt->len != 65) {
28
660
        PORT_SetError(SEC_ERROR_BAD_KEY);
29
660
        res = SECFailure;
30
660
        return res;
31
660
    }
32
33
207k
    if (pt->data[0] != EC_POINT_FORM_UNCOMPRESSED) {
34
240
        PORT_SetError(SEC_ERROR_UNSUPPORTED_EC_POINT_FORM);
35
240
        res = SECFailure;
36
240
        return res;
37
240
    }
38
39
#ifndef UNSAFE_FUZZER_MODE
40
103k
    bool b = Hacl_P256_validate_public_key(pt->data + 1);
41
#else
42
103k
    bool b = PR_TRUE;
43
#endif
44
45
207k
    if (!b) {
46
412
        PORT_SetError(SEC_ERROR_BAD_KEY);
47
412
        res = SECFailure;
48
412
    }
49
103k
    return res;
50
207k
}
ec_secp256r1_pt_validate
Line
Count
Source
19
104k
{
20
104k
    SECStatus res = SECSuccess;
21
104k
    if (!pt || !pt->data) {
22
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
23
0
        res = SECFailure;
24
0
        return res;
25
0
    }
26
27
104k
    if (pt->len != 65) {
28
330
        PORT_SetError(SEC_ERROR_BAD_KEY);
29
330
        res = SECFailure;
30
330
        return res;
31
330
    }
32
33
103k
    if (pt->data[0] != EC_POINT_FORM_UNCOMPRESSED) {
34
120
        PORT_SetError(SEC_ERROR_UNSUPPORTED_EC_POINT_FORM);
35
120
        res = SECFailure;
36
120
        return res;
37
120
    }
38
39
#ifndef UNSAFE_FUZZER_MODE
40
    bool b = Hacl_P256_validate_public_key(pt->data + 1);
41
#else
42
103k
    bool b = PR_TRUE;
43
103k
#endif
44
45
103k
    if (!b) {
46
206
        PORT_SetError(SEC_ERROR_BAD_KEY);
47
206
        res = SECFailure;
48
206
    }
49
103k
    return res;
50
103k
}
ec_secp256r1_pt_validate
Line
Count
Source
19
104k
{
20
104k
    SECStatus res = SECSuccess;
21
104k
    if (!pt || !pt->data) {
22
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
23
0
        res = SECFailure;
24
0
        return res;
25
0
    }
26
27
104k
    if (pt->len != 65) {
28
330
        PORT_SetError(SEC_ERROR_BAD_KEY);
29
330
        res = SECFailure;
30
330
        return res;
31
330
    }
32
33
103k
    if (pt->data[0] != EC_POINT_FORM_UNCOMPRESSED) {
34
120
        PORT_SetError(SEC_ERROR_UNSUPPORTED_EC_POINT_FORM);
35
120
        res = SECFailure;
36
120
        return res;
37
120
    }
38
39
103k
#ifndef UNSAFE_FUZZER_MODE
40
103k
    bool b = Hacl_P256_validate_public_key(pt->data + 1);
41
#else
42
    bool b = PR_TRUE;
43
#endif
44
45
103k
    if (!b) {
46
206
        PORT_SetError(SEC_ERROR_BAD_KEY);
47
206
        res = SECFailure;
48
206
    }
49
103k
    return res;
50
103k
}
51
52
/*
53
 * Scalar Validation for P-256.
54
 */
55
56
SECStatus
57
ec_secp256r1_scalar_validate(const SECItem *scalar)
58
119k
{
59
119k
    SECStatus res = SECSuccess;
60
119k
    if (!scalar || !scalar->data) {
61
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
62
0
        res = SECFailure;
63
0
        return res;
64
0
    }
65
66
119k
    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
59.7k
    bool b = Hacl_P256_validate_private_key(scalar->data);
74
#else
75
59.7k
    bool b = PR_TRUE;
76
#endif
77
78
119k
    if (!b) {
79
0
        PORT_SetError(SEC_ERROR_BAD_KEY);
80
0
        res = SECFailure;
81
0
    }
82
59.7k
    return res;
83
119k
}
ec_secp256r1_scalar_validate
Line
Count
Source
58
59.7k
{
59
59.7k
    SECStatus res = SECSuccess;
60
59.7k
    if (!scalar || !scalar->data) {
61
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
62
0
        res = SECFailure;
63
0
        return res;
64
0
    }
65
66
59.7k
    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
59.7k
    bool b = PR_TRUE;
76
59.7k
#endif
77
78
59.7k
    if (!b) {
79
0
        PORT_SetError(SEC_ERROR_BAD_KEY);
80
0
        res = SECFailure;
81
0
    }
82
59.7k
    return res;
83
59.7k
}
ec_secp256r1_scalar_validate
Line
Count
Source
58
59.7k
{
59
59.7k
    SECStatus res = SECSuccess;
60
59.7k
    if (!scalar || !scalar->data) {
61
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
62
0
        res = SECFailure;
63
0
        return res;
64
0
    }
65
66
59.7k
    if (scalar->len != 32) {
67
0
        PORT_SetError(SEC_ERROR_BAD_KEY);
68
0
        res = SECFailure;
69
0
        return res;
70
0
    }
71
72
59.7k
#ifndef UNSAFE_FUZZER_MODE
73
59.7k
    bool b = Hacl_P256_validate_private_key(scalar->data);
74
#else
75
    bool b = PR_TRUE;
76
#endif
77
78
59.7k
    if (!b) {
79
0
        PORT_SetError(SEC_ERROR_BAD_KEY);
80
0
        res = SECFailure;
81
0
    }
82
59.7k
    return res;
83
59.7k
}
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
218k
{
94
218k
    SECStatus res = SECSuccess;
95
218k
    if (!P) {
96
112k
        uint8_t derived[64] = { 0 };
97
98
112k
        if (!X || !k || !X->data || !k->data ||
99
112k
            X->len < 65 || k->len != 32) {
100
6
            PORT_SetError(SEC_ERROR_INVALID_ARGS);
101
6
            res = SECFailure;
102
6
            return res;
103
6
        }
104
105
#ifndef UNSAFE_FUZZER_MODE
106
56.2k
        bool b = Hacl_P256_dh_initiator(derived, k->data);
107
#else
108
56.2k
        bool b = PR_TRUE;
109
#endif
110
111
112k
        if (!b) {
112
0
            PORT_SetError(SEC_ERROR_BAD_KEY);
113
0
            res = SECFailure;
114
0
            return res;
115
0
        }
116
117
112k
        X->len = 65;
118
112k
        X->data[0] = EC_POINT_FORM_UNCOMPRESSED;
119
112k
        memcpy(X->data + 1, derived, 64);
120
121
112k
    } else {
122
105k
        uint8_t full_key[32] = { 0 };
123
105k
        uint8_t *key;
124
105k
        uint8_t derived[64] = { 0 };
125
126
105k
        if (!X || !k || !P || !X->data || !k->data || !P->data ||
127
105k
            X->len < 32 || P->len != 65 ||
128
105k
            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
105k
        if (k->len < 32) {
136
0
            memcpy(full_key + 32 - k->len, k->data, k->len);
137
0
            key = full_key;
138
105k
        } else if (k->len == 32) {
139
105k
            key = k->data;
140
105k
        } 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
105k
        bool b = Hacl_P256_dh_responder(derived, P->data + 1, key);
149
150
105k
        if (!b) {
151
25.0k
            PORT_SetError(SEC_ERROR_BAD_KEY);
152
25.0k
            res = SECFailure;
153
25.0k
            return res;
154
25.0k
        }
155
156
80.7k
        X->len = 32;
157
80.7k
        memcpy(X->data, derived, 32);
158
80.7k
    }
159
160
193k
    return res;
161
218k
}
ec_secp256r1_pt_mul
Line
Count
Source
93
109k
{
94
109k
    SECStatus res = SECSuccess;
95
109k
    if (!P) {
96
56.2k
        uint8_t derived[64] = { 0 };
97
98
56.2k
        if (!X || !k || !X->data || !k->data ||
99
56.2k
            X->len < 65 || k->len != 32) {
100
3
            PORT_SetError(SEC_ERROR_INVALID_ARGS);
101
3
            res = SECFailure;
102
3
            return res;
103
3
        }
104
105
#ifndef UNSAFE_FUZZER_MODE
106
        bool b = Hacl_P256_dh_initiator(derived, k->data);
107
#else
108
56.2k
        bool b = PR_TRUE;
109
56.2k
#endif
110
111
56.2k
        if (!b) {
112
0
            PORT_SetError(SEC_ERROR_BAD_KEY);
113
0
            res = SECFailure;
114
0
            return res;
115
0
        }
116
117
56.2k
        X->len = 65;
118
56.2k
        X->data[0] = EC_POINT_FORM_UNCOMPRESSED;
119
56.2k
        memcpy(X->data + 1, derived, 64);
120
121
56.2k
    } else {
122
52.9k
        uint8_t full_key[32] = { 0 };
123
52.9k
        uint8_t *key;
124
52.9k
        uint8_t derived[64] = { 0 };
125
126
52.9k
        if (!X || !k || !P || !X->data || !k->data || !P->data ||
127
52.9k
            X->len < 32 || P->len != 65 ||
128
52.9k
            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
52.9k
        if (k->len < 32) {
136
0
            memcpy(full_key + 32 - k->len, k->data, k->len);
137
0
            key = full_key;
138
52.9k
        } else if (k->len == 32) {
139
52.9k
            key = k->data;
140
52.9k
        } 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
52.9k
        bool b = Hacl_P256_dh_responder(derived, P->data + 1, key);
149
150
52.9k
        if (!b) {
151
12.5k
            PORT_SetError(SEC_ERROR_BAD_KEY);
152
12.5k
            res = SECFailure;
153
12.5k
            return res;
154
12.5k
        }
155
156
40.3k
        X->len = 32;
157
40.3k
        memcpy(X->data, derived, 32);
158
40.3k
    }
159
160
96.6k
    return res;
161
109k
}
ec_secp256r1_pt_mul
Line
Count
Source
93
109k
{
94
109k
    SECStatus res = SECSuccess;
95
109k
    if (!P) {
96
56.2k
        uint8_t derived[64] = { 0 };
97
98
56.2k
        if (!X || !k || !X->data || !k->data ||
99
56.2k
            X->len < 65 || k->len != 32) {
100
3
            PORT_SetError(SEC_ERROR_INVALID_ARGS);
101
3
            res = SECFailure;
102
3
            return res;
103
3
        }
104
105
56.2k
#ifndef UNSAFE_FUZZER_MODE
106
56.2k
        bool b = Hacl_P256_dh_initiator(derived, k->data);
107
#else
108
        bool b = PR_TRUE;
109
#endif
110
111
56.2k
        if (!b) {
112
0
            PORT_SetError(SEC_ERROR_BAD_KEY);
113
0
            res = SECFailure;
114
0
            return res;
115
0
        }
116
117
56.2k
        X->len = 65;
118
56.2k
        X->data[0] = EC_POINT_FORM_UNCOMPRESSED;
119
56.2k
        memcpy(X->data + 1, derived, 64);
120
121
56.2k
    } else {
122
52.9k
        uint8_t full_key[32] = { 0 };
123
52.9k
        uint8_t *key;
124
52.9k
        uint8_t derived[64] = { 0 };
125
126
52.9k
        if (!X || !k || !P || !X->data || !k->data || !P->data ||
127
52.9k
            X->len < 32 || P->len != 65 ||
128
52.9k
            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
52.9k
        if (k->len < 32) {
136
0
            memcpy(full_key + 32 - k->len, k->data, k->len);
137
0
            key = full_key;
138
52.9k
        } else if (k->len == 32) {
139
52.9k
            key = k->data;
140
52.9k
        } 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
52.9k
        bool b = Hacl_P256_dh_responder(derived, P->data + 1, key);
149
150
52.9k
        if (!b) {
151
12.5k
            PORT_SetError(SEC_ERROR_BAD_KEY);
152
12.5k
            res = SECFailure;
153
12.5k
            return res;
154
12.5k
        }
155
156
40.3k
        X->len = 32;
157
40.3k
        memcpy(X->data, derived, 32);
158
40.3k
    }
159
160
96.6k
    return res;
161
109k
}
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
8.65k
{
172
8.65k
    SECStatus res = SECSuccess;
173
174
8.65k
    if (!ecPrivKey || !signature || !digest || !kb ||
175
8.65k
        !ecPrivKey->privateValue.data ||
176
8.65k
        !signature->data || !digest->data ||
177
8.65k
        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
8.65k
    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
8.65k
    uint8_t padded_key_data[32] = { 0 };
193
8.65k
    uint8_t *key;
194
8.65k
    SECItem *privKey = &ecPrivKey->privateValue;
195
8.65k
    if (privKey->len == 32) {
196
8.65k
        key = privKey->data;
197
8.65k
    } 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
8.65k
    uint8_t hash[32] = { 0 };
208
8.65k
    if (digest->len < 32) {
209
8.38k
        memcpy(hash + 32 - digest->len, digest->data, digest->len);
210
8.38k
    } else {
211
268
        memcpy(hash, digest->data, 32);
212
268
    }
213
214
8.65k
    uint8_t nonce[32] = { 0 };
215
8.65k
    if (kblen < 32) {
216
0
        memcpy(nonce + 32 - kblen, kb, kblen);
217
8.65k
    } else {
218
8.65k
        memcpy(nonce, kb, 32);
219
8.65k
    }
220
221
#ifndef UNSAFE_FUZZER_MODE
222
    bool b = Hacl_P256_ecdsa_sign_p256_without_hash(
223
        signature->data, 32, hash, key, nonce);
224
#else
225
8.65k
    bool b = key != NULL;                        /* Avoiding unused variable warnings */
226
8.65k
#endif
227
228
8.65k
    if (!b) {
229
0
        PORT_SetError(SEC_ERROR_BAD_KEY);
230
0
        res = SECFailure;
231
0
        return res;
232
0
    }
233
234
8.65k
    signature->len = 64;
235
8.65k
    return res;
236
8.65k
}
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
36
{
246
36
    SECStatus res = SECSuccess;
247
248
36
    unsigned char _padded_sig_data[64] = { 0 };
249
36
    unsigned char *sig_r, *sig_s;
250
251
36
    if (!key || !signature || !digest ||
252
36
        !key->publicValue.data ||
253
36
        !signature->data || !digest->data ||
254
36
        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
36
    unsigned int olen = key->ecParams.order.len;
261
36
    if (signature->len == 0 || signature->len % 2 != 0 ||
262
36
        signature->len > 2 * olen ||
263
36
        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
36
    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
36
    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
36
    } else {
289
36
        sig_r = signature->data;
290
36
        sig_s = signature->data + 32;
291
36
    }
292
293
36
    uint8_t hash[32] = { 0 };
294
36
    if (digest->len < 32) {
295
23
        memcpy(hash + 32 - digest->len, digest->data, digest->len);
296
23
    } else {
297
13
        memcpy(hash, digest->data, 32);
298
13
    }
299
300
#ifndef UNSAFE_FUZZER_MODE
301
    bool b = Hacl_P256_ecdsa_verif_without_hash(
302
        32, hash,
303
        key->publicValue.data + 1,
304
        sig_r, sig_s);
305
#else
306
36
    bool b = (sig_r != NULL) && (sig_s != NULL); /* Avoiding unused variable warnings */
307
36
#endif
308
309
36
    if (!b) {
310
0
        PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
311
0
        res = SECFailure;
312
0
        return res;
313
0
    }
314
315
36
    return res;
316
36
}