Coverage Report

Created: 2025-07-11 07:04

/src/nss/lib/freebl/ecl/ecp_secp384r1.c
Line
Count
Source (jump to first uncovered line)
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
0
{
22
0
    SECStatus res = SECSuccess;
23
0
    if (!pt || !pt->data) {
24
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
25
0
        res = SECFailure;
26
0
        return res;
27
0
    }
28
29
0
    if (pt->len != 97) {
30
0
        PORT_SetError(SEC_ERROR_BAD_KEY);
31
0
        res = SECFailure;
32
0
        return res;
33
0
    }
34
35
0
    if (pt->data[0] != EC_POINT_FORM_UNCOMPRESSED) {
36
0
        PORT_SetError(SEC_ERROR_UNSUPPORTED_EC_POINT_FORM);
37
0
        res = SECFailure;
38
0
        return res;
39
0
    }
40
41
0
#ifndef UNSAFE_FUZZER_MODE
42
0
    bool b = Hacl_P384_validate_public_key(pt->data + 1);
43
#else
44
    bool b = PR_TRUE;
45
#endif
46
47
0
    if (!b) {
48
0
        PORT_SetError(SEC_ERROR_BAD_KEY);
49
0
        res = SECFailure;
50
0
    }
51
0
    return res;
52
0
}
53
54
/*
55
 * Scalar Validation for P-384.
56
 */
57
58
SECStatus
59
ec_secp384r1_scalar_validate(const SECItem *scalar)
60
0
{
61
0
    SECStatus res = SECSuccess;
62
0
    if (!scalar || !scalar->data) {
63
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
64
0
        res = SECFailure;
65
0
        return res;
66
0
    }
67
68
0
    if (scalar->len != 48) {
69
0
        PORT_SetError(SEC_ERROR_BAD_KEY);
70
0
        res = SECFailure;
71
0
        return res;
72
0
    }
73
74
0
#ifndef UNSAFE_FUZZER_MODE
75
0
    bool b = Hacl_P384_validate_private_key(scalar->data);
76
#else
77
    bool b = PR_TRUE;
78
#endif
79
80
0
    if (!b) {
81
0
        PORT_SetError(SEC_ERROR_BAD_KEY);
82
0
        res = SECFailure;
83
0
    }
84
0
    return res;
85
0
}
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
0
{
96
0
    SECStatus res = SECSuccess;
97
0
    if (!P) {
98
0
        uint8_t derived[96] = { 0 };
99
100
0
        if (!X || !k || !X->data || !k->data ||
101
0
            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
0
#ifndef UNSAFE_FUZZER_MODE
108
0
        bool b = Hacl_P384_dh_initiator(derived, k->data);
109
#else
110
        bool b = PR_TRUE;
111
#endif
112
113
0
        if (!b) {
114
0
            PORT_SetError(SEC_ERROR_BAD_KEY);
115
0
            res = SECFailure;
116
0
            return res;
117
0
        }
118
119
0
        X->len = 97;
120
0
        X->data[0] = EC_POINT_FORM_UNCOMPRESSED;
121
0
        memcpy(X->data + 1, derived, 96);
122
123
0
    } else {
124
0
        uint8_t full_key[48] = { 0 };
125
0
        uint8_t *key;
126
0
        uint8_t derived[96] = { 0 };
127
128
0
        if (!X || !k || !P || !X->data || !k->data || !P->data ||
129
0
            X->len < 48 || P->len != 97 ||
130
0
            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
0
        if (k->len < 48) {
138
0
            memcpy(full_key + 48 - k->len, k->data, k->len);
139
0
            key = full_key;
140
0
        } else if (k->len == 48) {
141
0
            key = k->data;
142
0
        } 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
0
#ifndef UNSAFE_FUZZER_MODE
151
0
        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
0
        if (!b) {
157
0
            PORT_SetError(SEC_ERROR_BAD_KEY);
158
0
            res = SECFailure;
159
0
            return res;
160
0
        }
161
162
0
        X->len = 48;
163
0
        memcpy(X->data, derived, 48);
164
0
    }
165
166
0
    return res;
167
0
}
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
0
#ifndef UNSAFE_FUZZER_MODE
228
0
    bool b = Hacl_P384_ecdsa_sign_p384_without_hash(
229
0
        signature->data, 48, hash, key, nonce);
230
#else
231
    bool b = key != NULL;     /* Avoiding unused variable warnings */
232
#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
0
{
252
0
    SECStatus res = SECSuccess;
253
254
0
    if (!key || !signature || !digest ||
255
0
        !key->publicValue.data ||
256
0
        !signature->data || !digest->data ||
257
0
        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
0
    if (signature->len == 0 || signature->len % 2 != 0 ||
264
0
        signature->len > 96 || digest->len == 0 ||
265
0
        key->publicValue.len != 97) {
266
0
        PORT_SetError(SEC_ERROR_INPUT_LEN);
267
0
        res = SECFailure;
268
0
        return res;
269
0
    }
270
271
0
    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
0
    uint8_t paddedSigData[96] = { 0 };
280
0
    uint8_t *sig;
281
0
    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
0
    } else {
289
0
        sig = signature->data;
290
0
    }
291
292
0
    uint8_t hash[48] = { 0 };
293
0
    if (digest->len < 48) {
294
0
        memcpy(hash + 48 - digest->len, digest->data, digest->len);
295
0
    } else {
296
0
        memcpy(hash, digest->data, 48);
297
0
    }
298
299
0
#ifndef UNSAFE_FUZZER_MODE
300
0
    bool b = Hacl_P384_ecdsa_verif_without_hash(
301
0
        48, hash, key->publicValue.data + 1, sig, sig + 48);
302
#else
303
    bool b = sig != NULL;     /* Avoiding unused variable warnings */
304
#endif
305
306
0
    if (!b) {
307
0
        PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
308
0
        res = SECFailure;
309
0
        return res;
310
0
    }
311
312
0
    return res;
313
0
}