Coverage Report

Created: 2024-11-21 07:03

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