/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 | } |