Coverage Report

Created: 2025-09-17 07:05

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/nss/lib/freebl/ecl/ecp_secp384r1.c
Line
Count
Source
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 "ecl-priv.h"
10
#include "secitem.h"
11
#include "secerr.h"
12
#include "secmpi.h"
13
#include "../verified/Hacl_P384.h"
14
15
/*
16
 * Point Validation for P-384.
17
 */
18
19
SECStatus
20
ec_secp384r1_pt_validate(const SECItem *pt)
21
28.8k
{
22
28.8k
    SECStatus res = SECSuccess;
23
28.8k
    if (!pt || !pt->data) {
24
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
25
0
        res = SECFailure;
26
0
        return res;
27
0
    }
28
29
28.8k
    if (pt->len != 97) {
30
374
        PORT_SetError(SEC_ERROR_BAD_KEY);
31
374
        res = SECFailure;
32
374
        return res;
33
374
    }
34
35
28.4k
    if (pt->data[0] != EC_POINT_FORM_UNCOMPRESSED) {
36
148
        PORT_SetError(SEC_ERROR_UNSUPPORTED_EC_POINT_FORM);
37
148
        res = SECFailure;
38
148
        return res;
39
148
    }
40
41
#ifndef UNSAFE_FUZZER_MODE
42
14.1k
    bool b = Hacl_P384_validate_public_key(pt->data + 1);
43
#else
44
14.1k
    bool b = PR_TRUE;
45
#endif
46
47
28.3k
    if (!b) {
48
478
        PORT_SetError(SEC_ERROR_BAD_KEY);
49
478
        res = SECFailure;
50
478
    }
51
14.1k
    return res;
52
28.4k
}
ec_secp384r1_pt_validate
Line
Count
Source
21
14.4k
{
22
14.4k
    SECStatus res = SECSuccess;
23
14.4k
    if (!pt || !pt->data) {
24
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
25
0
        res = SECFailure;
26
0
        return res;
27
0
    }
28
29
14.4k
    if (pt->len != 97) {
30
187
        PORT_SetError(SEC_ERROR_BAD_KEY);
31
187
        res = SECFailure;
32
187
        return res;
33
187
    }
34
35
14.2k
    if (pt->data[0] != EC_POINT_FORM_UNCOMPRESSED) {
36
74
        PORT_SetError(SEC_ERROR_UNSUPPORTED_EC_POINT_FORM);
37
74
        res = SECFailure;
38
74
        return res;
39
74
    }
40
41
#ifndef UNSAFE_FUZZER_MODE
42
    bool b = Hacl_P384_validate_public_key(pt->data + 1);
43
#else
44
14.2k
    bool b = PR_TRUE;
45
14.1k
#endif
46
47
14.1k
    if (!b) {
48
239
        PORT_SetError(SEC_ERROR_BAD_KEY);
49
239
        res = SECFailure;
50
239
    }
51
14.1k
    return res;
52
14.2k
}
ec_secp384r1_pt_validate
Line
Count
Source
21
14.4k
{
22
14.4k
    SECStatus res = SECSuccess;
23
14.4k
    if (!pt || !pt->data) {
24
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
25
0
        res = SECFailure;
26
0
        return res;
27
0
    }
28
29
14.4k
    if (pt->len != 97) {
30
187
        PORT_SetError(SEC_ERROR_BAD_KEY);
31
187
        res = SECFailure;
32
187
        return res;
33
187
    }
34
35
14.2k
    if (pt->data[0] != EC_POINT_FORM_UNCOMPRESSED) {
36
74
        PORT_SetError(SEC_ERROR_UNSUPPORTED_EC_POINT_FORM);
37
74
        res = SECFailure;
38
74
        return res;
39
74
    }
40
41
14.1k
#ifndef UNSAFE_FUZZER_MODE
42
14.2k
    bool b = Hacl_P384_validate_public_key(pt->data + 1);
43
#else
44
    bool b = PR_TRUE;
45
#endif
46
47
14.1k
    if (!b) {
48
239
        PORT_SetError(SEC_ERROR_BAD_KEY);
49
239
        res = SECFailure;
50
239
    }
51
14.1k
    return res;
52
14.2k
}
53
54
/*
55
 * Scalar Validation for P-384.
56
 */
57
58
SECStatus
59
ec_secp384r1_scalar_validate(const SECItem *scalar)
60
14.1k
{
61
14.1k
    SECStatus res = SECSuccess;
62
14.1k
    if (!scalar || !scalar->data) {
63
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
64
0
        res = SECFailure;
65
0
        return res;
66
0
    }
67
68
14.1k
    if (scalar->len != 48) {
69
0
        PORT_SetError(SEC_ERROR_BAD_KEY);
70
0
        res = SECFailure;
71
0
        return res;
72
0
    }
73
74
#ifndef UNSAFE_FUZZER_MODE
75
7.07k
    bool b = Hacl_P384_validate_private_key(scalar->data);
76
#else
77
7.07k
    bool b = PR_TRUE;
78
#endif
79
80
14.1k
    if (!b) {
81
0
        PORT_SetError(SEC_ERROR_BAD_KEY);
82
0
        res = SECFailure;
83
0
    }
84
7.07k
    return res;
85
14.1k
}
ec_secp384r1_scalar_validate
Line
Count
Source
60
7.07k
{
61
7.07k
    SECStatus res = SECSuccess;
62
7.07k
    if (!scalar || !scalar->data) {
63
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
64
0
        res = SECFailure;
65
0
        return res;
66
0
    }
67
68
7.07k
    if (scalar->len != 48) {
69
0
        PORT_SetError(SEC_ERROR_BAD_KEY);
70
0
        res = SECFailure;
71
0
        return res;
72
0
    }
73
74
#ifndef UNSAFE_FUZZER_MODE
75
    bool b = Hacl_P384_validate_private_key(scalar->data);
76
#else
77
7.07k
    bool b = PR_TRUE;
78
7.07k
#endif
79
80
7.07k
    if (!b) {
81
0
        PORT_SetError(SEC_ERROR_BAD_KEY);
82
0
        res = SECFailure;
83
0
    }
84
7.07k
    return res;
85
7.07k
}
ec_secp384r1_scalar_validate
Line
Count
Source
60
7.07k
{
61
7.07k
    SECStatus res = SECSuccess;
62
7.07k
    if (!scalar || !scalar->data) {
63
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
64
0
        res = SECFailure;
65
0
        return res;
66
0
    }
67
68
7.07k
    if (scalar->len != 48) {
69
0
        PORT_SetError(SEC_ERROR_BAD_KEY);
70
0
        res = SECFailure;
71
0
        return res;
72
0
    }
73
74
7.07k
#ifndef UNSAFE_FUZZER_MODE
75
7.07k
    bool b = Hacl_P384_validate_private_key(scalar->data);
76
#else
77
    bool b = PR_TRUE;
78
#endif
79
80
7.07k
    if (!b) {
81
0
        PORT_SetError(SEC_ERROR_BAD_KEY);
82
0
        res = SECFailure;
83
0
    }
84
7.07k
    return res;
85
7.07k
}
86
87
/*
88
 * Scalar multiplication for P-384.
89
 * If P == NULL, the base point is used.
90
 * Returns X = k*P
91
 */
92
93
SECStatus
94
ec_secp384r1_pt_mul(SECItem *X, SECItem *k, SECItem *P)
95
13.8k
{
96
13.8k
    SECStatus res = SECSuccess;
97
13.8k
    if (!P) {
98
7.13k
        uint8_t derived[96] = { 0 };
99
100
7.13k
        if (!X || !k || !X->data || !k->data ||
101
7.13k
            X->len < 97 || k->len != 48) {
102
3
            PORT_SetError(SEC_ERROR_INVALID_ARGS);
103
3
            res = SECFailure;
104
3
            return res;
105
3
        }
106
107
#ifndef UNSAFE_FUZZER_MODE
108
302
        bool b = Hacl_P384_dh_initiator(derived, k->data);
109
#else
110
6.82k
        bool b = PR_TRUE;
111
#endif
112
113
7.13k
        if (!b) {
114
2
            PORT_SetError(SEC_ERROR_BAD_KEY);
115
2
            res = SECFailure;
116
2
            return res;
117
2
        }
118
119
7.12k
        X->len = 97;
120
7.12k
        X->data[0] = EC_POINT_FORM_UNCOMPRESSED;
121
7.12k
        memcpy(X->data + 1, derived, 96);
122
123
7.12k
    } else {
124
6.70k
        uint8_t full_key[48] = { 0 };
125
6.70k
        uint8_t *key;
126
6.70k
        uint8_t derived[96] = { 0 };
127
128
6.70k
        if (!X || !k || !P || !X->data || !k->data || !P->data ||
129
6.70k
            X->len < 48 || P->len != 97 ||
130
6.70k
            P->data[0] != EC_POINT_FORM_UNCOMPRESSED) {
131
0
            PORT_SetError(SEC_ERROR_INVALID_ARGS);
132
0
            res = SECFailure;
133
0
            return res;
134
0
        }
135
136
        /* We consider keys of up to size 48, or of size 49 with a single leading 0 */
137
6.70k
        if (k->len < 48) {
138
0
            memcpy(full_key + 48 - k->len, k->data, k->len);
139
0
            key = full_key;
140
6.70k
        } else if (k->len == 48) {
141
6.70k
            key = k->data;
142
6.70k
        } else if (k->len == 49 && k->data[0] == 0) {
143
0
            key = k->data + 1;
144
0
        } else {
145
0
            PORT_SetError(SEC_ERROR_INVALID_ARGS);
146
0
            res = SECFailure;
147
0
            return res;
148
0
        }
149
150
#ifndef UNSAFE_FUZZER_MODE
151
19
        bool b = Hacl_P384_dh_responder(derived, P->data + 1, key);
152
#else
153
6.68k
        bool b = key != NULL; /* Avoiding unused variable warnings */
154
6.68k
#endif
155
156
6.70k
        if (!b) {
157
0
            PORT_SetError(SEC_ERROR_BAD_KEY);
158
0
            res = SECFailure;
159
0
            return res;
160
0
        }
161
162
6.70k
        X->len = 48;
163
6.70k
        memcpy(X->data, derived, 48);
164
6.70k
    }
165
166
13.8k
    return res;
167
13.8k
}
ec_secp384r1_pt_mul
Line
Count
Source
95
13.5k
{
96
13.5k
    SECStatus res = SECSuccess;
97
13.5k
    if (!P) {
98
6.82k
        uint8_t derived[96] = { 0 };
99
100
6.82k
        if (!X || !k || !X->data || !k->data ||
101
6.82k
            X->len < 97 || k->len != 48) {
102
0
            PORT_SetError(SEC_ERROR_INVALID_ARGS);
103
0
            res = SECFailure;
104
0
            return res;
105
0
        }
106
107
#ifndef UNSAFE_FUZZER_MODE
108
        bool b = Hacl_P384_dh_initiator(derived, k->data);
109
#else
110
6.82k
        bool b = PR_TRUE;
111
6.82k
#endif
112
113
6.82k
        if (!b) {
114
0
            PORT_SetError(SEC_ERROR_BAD_KEY);
115
0
            res = SECFailure;
116
0
            return res;
117
0
        }
118
119
6.82k
        X->len = 97;
120
6.82k
        X->data[0] = EC_POINT_FORM_UNCOMPRESSED;
121
6.82k
        memcpy(X->data + 1, derived, 96);
122
123
6.82k
    } else {
124
6.68k
        uint8_t full_key[48] = { 0 };
125
6.68k
        uint8_t *key;
126
6.68k
        uint8_t derived[96] = { 0 };
127
128
6.68k
        if (!X || !k || !P || !X->data || !k->data || !P->data ||
129
6.68k
            X->len < 48 || P->len != 97 ||
130
6.68k
            P->data[0] != EC_POINT_FORM_UNCOMPRESSED) {
131
0
            PORT_SetError(SEC_ERROR_INVALID_ARGS);
132
0
            res = SECFailure;
133
0
            return res;
134
0
        }
135
136
        /* We consider keys of up to size 48, or of size 49 with a single leading 0 */
137
6.68k
        if (k->len < 48) {
138
0
            memcpy(full_key + 48 - k->len, k->data, k->len);
139
0
            key = full_key;
140
6.68k
        } else if (k->len == 48) {
141
6.68k
            key = k->data;
142
6.68k
        } else if (k->len == 49 && k->data[0] == 0) {
143
0
            key = k->data + 1;
144
0
        } else {
145
0
            PORT_SetError(SEC_ERROR_INVALID_ARGS);
146
0
            res = SECFailure;
147
0
            return res;
148
0
        }
149
150
#ifndef UNSAFE_FUZZER_MODE
151
        bool b = Hacl_P384_dh_responder(derived, P->data + 1, key);
152
#else
153
6.68k
        bool b = key != NULL; /* Avoiding unused variable warnings */
154
6.68k
#endif
155
156
6.68k
        if (!b) {
157
0
            PORT_SetError(SEC_ERROR_BAD_KEY);
158
0
            res = SECFailure;
159
0
            return res;
160
0
        }
161
162
6.68k
        X->len = 48;
163
6.68k
        memcpy(X->data, derived, 48);
164
6.68k
    }
165
166
13.5k
    return res;
167
13.5k
}
ec_secp384r1_pt_mul
Line
Count
Source
95
324
{
96
324
    SECStatus res = SECSuccess;
97
324
    if (!P) {
98
305
        uint8_t derived[96] = { 0 };
99
100
305
        if (!X || !k || !X->data || !k->data ||
101
305
            X->len < 97 || k->len != 48) {
102
3
            PORT_SetError(SEC_ERROR_INVALID_ARGS);
103
3
            res = SECFailure;
104
3
            return res;
105
3
        }
106
107
302
#ifndef UNSAFE_FUZZER_MODE
108
305
        bool b = Hacl_P384_dh_initiator(derived, k->data);
109
#else
110
        bool b = PR_TRUE;
111
#endif
112
113
302
        if (!b) {
114
2
            PORT_SetError(SEC_ERROR_BAD_KEY);
115
2
            res = SECFailure;
116
2
            return res;
117
2
        }
118
119
300
        X->len = 97;
120
300
        X->data[0] = EC_POINT_FORM_UNCOMPRESSED;
121
300
        memcpy(X->data + 1, derived, 96);
122
123
300
    } else {
124
19
        uint8_t full_key[48] = { 0 };
125
19
        uint8_t *key;
126
19
        uint8_t derived[96] = { 0 };
127
128
19
        if (!X || !k || !P || !X->data || !k->data || !P->data ||
129
19
            X->len < 48 || P->len != 97 ||
130
19
            P->data[0] != EC_POINT_FORM_UNCOMPRESSED) {
131
0
            PORT_SetError(SEC_ERROR_INVALID_ARGS);
132
0
            res = SECFailure;
133
0
            return res;
134
0
        }
135
136
        /* We consider keys of up to size 48, or of size 49 with a single leading 0 */
137
19
        if (k->len < 48) {
138
0
            memcpy(full_key + 48 - k->len, k->data, k->len);
139
0
            key = full_key;
140
19
        } else if (k->len == 48) {
141
19
            key = k->data;
142
19
        } else if (k->len == 49 && k->data[0] == 0) {
143
0
            key = k->data + 1;
144
0
        } else {
145
0
            PORT_SetError(SEC_ERROR_INVALID_ARGS);
146
0
            res = SECFailure;
147
0
            return res;
148
0
        }
149
150
19
#ifndef UNSAFE_FUZZER_MODE
151
19
        bool b = Hacl_P384_dh_responder(derived, P->data + 1, key);
152
#else
153
        bool b = key != NULL; /* Avoiding unused variable warnings */
154
#endif
155
156
19
        if (!b) {
157
0
            PORT_SetError(SEC_ERROR_BAD_KEY);
158
0
            res = SECFailure;
159
0
            return res;
160
0
        }
161
162
19
        X->len = 48;
163
19
        memcpy(X->data, derived, 48);
164
19
    }
165
166
319
    return res;
167
324
}
168
169
/*
170
 * ECDSA Signature for P-384
171
 */
172
173
SECStatus
174
ec_secp384r1_sign_digest(ECPrivateKey *ecPrivKey, SECItem *signature,
175
                         const SECItem *digest, const unsigned char *kb,
176
                         const unsigned int kblen)
177
0
{
178
0
    SECStatus res = SECSuccess;
179
180
0
    if (!ecPrivKey || !signature || !digest || !kb ||
181
0
        !ecPrivKey->privateValue.data ||
182
0
        !signature->data || !digest->data ||
183
0
        ecPrivKey->ecParams.name != ECCurve_NIST_P384) {
184
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
185
0
        res = SECFailure;
186
0
        return res;
187
0
    }
188
189
0
    if (kblen == 0 || digest->len == 0 || signature->len < 96) {
190
0
        PORT_SetError(SEC_ERROR_INPUT_LEN);
191
0
        res = SECFailure;
192
0
        return res;
193
0
    }
194
195
    // Private keys should be 48 bytes, but some software trims leading zeros,
196
    // and some software produces 49 byte keys with a leading zero. We'll
197
    // accept these variants.
198
0
    uint8_t padded_key_data[48] = { 0 };
199
0
    uint8_t *key;
200
0
    SECItem *privKey = &ecPrivKey->privateValue;
201
0
    if (privKey->len == 48) {
202
0
        key = privKey->data;
203
0
    } else if (privKey->len == 49 && privKey->data[0] == 0) {
204
0
        key = privKey->data + 1;
205
0
    } else if (privKey->len < 48) {
206
0
        memcpy(padded_key_data + 48 - privKey->len, privKey->data, privKey->len);
207
0
        key = padded_key_data;
208
0
    } else {
209
0
        PORT_SetError(SEC_ERROR_INPUT_LEN);
210
0
        return SECFailure;
211
0
    }
212
213
0
    uint8_t hash[48] = { 0 };
214
0
    if (digest->len < 48) {
215
0
        memcpy(hash + 48 - digest->len, digest->data, digest->len);
216
0
    } else {
217
0
        memcpy(hash, digest->data, 48);
218
0
    }
219
220
0
    uint8_t nonce[48] = { 0 };
221
0
    if (kblen < 48) {
222
0
        memcpy(nonce + 48 - kblen, kb, kblen);
223
0
    } else {
224
0
        memcpy(nonce, kb, 48);
225
0
    }
226
227
#ifndef UNSAFE_FUZZER_MODE
228
    bool b = Hacl_P384_ecdsa_sign_p384_without_hash(
229
        signature->data, 48, hash, key, nonce);
230
#else
231
0
    bool b = key != NULL;     /* Avoiding unused variable warnings */
232
0
#endif
233
234
0
    if (!b) {
235
0
        PORT_SetError(SEC_ERROR_BAD_KEY);
236
0
        res = SECFailure;
237
0
        return res;
238
0
    }
239
240
0
    signature->len = 96;
241
0
    return res;
242
0
}
243
244
/*
245
 * ECDSA Signature Verification for P-384
246
 */
247
248
SECStatus
249
ec_secp384r1_verify_digest(ECPublicKey *key, const SECItem *signature,
250
                           const SECItem *digest)
251
10
{
252
10
    SECStatus res = SECSuccess;
253
254
10
    if (!key || !signature || !digest ||
255
10
        !key->publicValue.data ||
256
10
        !signature->data || !digest->data ||
257
10
        key->ecParams.name != ECCurve_NIST_P384) {
258
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
259
0
        res = SECFailure;
260
0
        return res;
261
0
    }
262
263
10
    if (signature->len == 0 || signature->len % 2 != 0 ||
264
10
        signature->len > 96 || digest->len == 0 ||
265
10
        key->publicValue.len != 97) {
266
0
        PORT_SetError(SEC_ERROR_INPUT_LEN);
267
0
        res = SECFailure;
268
0
        return res;
269
0
    }
270
271
10
    if (key->publicValue.data[0] != EC_POINT_FORM_UNCOMPRESSED) {
272
0
        PORT_SetError(SEC_ERROR_UNSUPPORTED_EC_POINT_FORM);
273
0
        res = SECFailure;
274
0
        return res;
275
0
    }
276
277
    // Signatures should be 96 bytes, but some software produces short signatures.
278
    // Pad components with zeros if necessary.
279
10
    uint8_t paddedSigData[96] = { 0 };
280
10
    uint8_t *sig;
281
10
    if (signature->len != 96) {
282
0
        size_t split = signature->len / 2;
283
284
0
        memcpy(paddedSigData + 48 - split, signature->data, split);
285
0
        memcpy(paddedSigData + 96 - split, signature->data + split, split);
286
287
0
        sig = paddedSigData;
288
10
    } else {
289
10
        sig = signature->data;
290
10
    }
291
292
10
    uint8_t hash[48] = { 0 };
293
10
    if (digest->len < 48) {
294
10
        memcpy(hash + 48 - digest->len, digest->data, digest->len);
295
10
    } else {
296
0
        memcpy(hash, digest->data, 48);
297
0
    }
298
299
#ifndef UNSAFE_FUZZER_MODE
300
    bool b = Hacl_P384_ecdsa_verif_without_hash(
301
        48, hash, key->publicValue.data + 1, sig, sig + 48);
302
#else
303
10
    bool b = sig != NULL;     /* Avoiding unused variable warnings */
304
10
#endif
305
306
10
    if (!b) {
307
0
        PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
308
0
        res = SECFailure;
309
0
        return res;
310
0
    }
311
312
10
    return res;
313
10
}