/src/nss/lib/freebl/ecl/ecp_secp521r1.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_P521.h" |
14 | | |
15 | | /* |
16 | | * Point Validation for P-521. |
17 | | */ |
18 | | |
19 | | SECStatus |
20 | | ec_secp521r1_pt_validate(const SECItem *pt) |
21 | 2.44k | { |
22 | 2.44k | SECStatus res = SECSuccess; |
23 | 2.44k | if (!pt || !pt->data) { |
24 | 0 | PORT_SetError(SEC_ERROR_INVALID_ARGS); |
25 | 0 | res = SECFailure; |
26 | 0 | return res; |
27 | 0 | } |
28 | | |
29 | 2.44k | if (pt->len != 133) { |
30 | 158 | PORT_SetError(SEC_ERROR_BAD_KEY); |
31 | 158 | res = SECFailure; |
32 | 158 | return res; |
33 | 158 | } |
34 | | |
35 | 2.28k | if (pt->data[0] != EC_POINT_FORM_UNCOMPRESSED) { |
36 | 44 | PORT_SetError(SEC_ERROR_UNSUPPORTED_EC_POINT_FORM); |
37 | 44 | res = SECFailure; |
38 | 44 | return res; |
39 | 44 | } |
40 | | |
41 | | #ifndef UNSAFE_FUZZER_MODE |
42 | 1.12k | bool b = Hacl_P521_validate_public_key(pt->data + 1); |
43 | | #else |
44 | 1.12k | bool b = PR_TRUE; |
45 | | #endif |
46 | | |
47 | 2.24k | if (!b) { |
48 | 680 | PORT_SetError(SEC_ERROR_BAD_KEY); |
49 | 680 | res = SECFailure; |
50 | 680 | } |
51 | 1.12k | return res; |
52 | 2.28k | } Line | Count | Source | 21 | 1.22k | { | 22 | 1.22k | SECStatus res = SECSuccess; | 23 | 1.22k | if (!pt || !pt->data) { | 24 | 0 | PORT_SetError(SEC_ERROR_INVALID_ARGS); | 25 | 0 | res = SECFailure; | 26 | 0 | return res; | 27 | 0 | } | 28 | | | 29 | 1.22k | if (pt->len != 133) { | 30 | 79 | PORT_SetError(SEC_ERROR_BAD_KEY); | 31 | 79 | res = SECFailure; | 32 | 79 | return res; | 33 | 79 | } | 34 | | | 35 | 1.14k | if (pt->data[0] != EC_POINT_FORM_UNCOMPRESSED) { | 36 | 22 | PORT_SetError(SEC_ERROR_UNSUPPORTED_EC_POINT_FORM); | 37 | 22 | res = SECFailure; | 38 | 22 | return res; | 39 | 22 | } | 40 | | | 41 | 1.12k | #ifndef UNSAFE_FUZZER_MODE | 42 | 1.14k | bool b = Hacl_P521_validate_public_key(pt->data + 1); | 43 | | #else | 44 | | bool b = PR_TRUE; | 45 | | #endif | 46 | | | 47 | 1.12k | if (!b) { | 48 | 340 | PORT_SetError(SEC_ERROR_BAD_KEY); | 49 | 340 | res = SECFailure; | 50 | 340 | } | 51 | 1.12k | return res; | 52 | 1.14k | } |
Line | Count | Source | 21 | 1.22k | { | 22 | 1.22k | SECStatus res = SECSuccess; | 23 | 1.22k | if (!pt || !pt->data) { | 24 | 0 | PORT_SetError(SEC_ERROR_INVALID_ARGS); | 25 | 0 | res = SECFailure; | 26 | 0 | return res; | 27 | 0 | } | 28 | | | 29 | 1.22k | if (pt->len != 133) { | 30 | 79 | PORT_SetError(SEC_ERROR_BAD_KEY); | 31 | 79 | res = SECFailure; | 32 | 79 | return res; | 33 | 79 | } | 34 | | | 35 | 1.14k | if (pt->data[0] != EC_POINT_FORM_UNCOMPRESSED) { | 36 | 22 | PORT_SetError(SEC_ERROR_UNSUPPORTED_EC_POINT_FORM); | 37 | 22 | res = SECFailure; | 38 | 22 | return res; | 39 | 22 | } | 40 | | | 41 | | #ifndef UNSAFE_FUZZER_MODE | 42 | | bool b = Hacl_P521_validate_public_key(pt->data + 1); | 43 | | #else | 44 | 1.14k | bool b = PR_TRUE; | 45 | 1.12k | #endif | 46 | | | 47 | 1.12k | if (!b) { | 48 | 340 | PORT_SetError(SEC_ERROR_BAD_KEY); | 49 | 340 | res = SECFailure; | 50 | 340 | } | 51 | 1.12k | return res; | 52 | 1.14k | } |
|
53 | | |
54 | | /* |
55 | | * Scalar Validation for P-521. |
56 | | */ |
57 | | |
58 | | SECStatus |
59 | | ec_secp521r1_scalar_validate(const SECItem *scalar) |
60 | 872 | { |
61 | 872 | SECStatus res = SECSuccess; |
62 | 872 | if (!scalar || !scalar->data) { |
63 | 0 | PORT_SetError(SEC_ERROR_INVALID_ARGS); |
64 | 0 | res = SECFailure; |
65 | 0 | return res; |
66 | 0 | } |
67 | | |
68 | 872 | if (scalar->len != 66) { |
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 | 436 | bool b = Hacl_P521_validate_private_key(scalar->data); |
76 | | #else |
77 | 436 | bool b = PR_TRUE; |
78 | | #endif |
79 | | |
80 | 872 | if (!b) { |
81 | 0 | PORT_SetError(SEC_ERROR_BAD_KEY); |
82 | 0 | res = SECFailure; |
83 | 0 | } |
84 | 436 | return res; |
85 | 872 | } ec_secp521r1_scalar_validate Line | Count | Source | 60 | 436 | { | 61 | 436 | SECStatus res = SECSuccess; | 62 | 436 | if (!scalar || !scalar->data) { | 63 | 0 | PORT_SetError(SEC_ERROR_INVALID_ARGS); | 64 | 0 | res = SECFailure; | 65 | 0 | return res; | 66 | 0 | } | 67 | | | 68 | 436 | if (scalar->len != 66) { | 69 | 0 | PORT_SetError(SEC_ERROR_BAD_KEY); | 70 | 0 | res = SECFailure; | 71 | 0 | return res; | 72 | 0 | } | 73 | | | 74 | 436 | #ifndef UNSAFE_FUZZER_MODE | 75 | 436 | bool b = Hacl_P521_validate_private_key(scalar->data); | 76 | | #else | 77 | | bool b = PR_TRUE; | 78 | | #endif | 79 | | | 80 | 436 | if (!b) { | 81 | 0 | PORT_SetError(SEC_ERROR_BAD_KEY); | 82 | 0 | res = SECFailure; | 83 | 0 | } | 84 | 436 | return res; | 85 | 436 | } |
ec_secp521r1_scalar_validate Line | Count | Source | 60 | 436 | { | 61 | 436 | SECStatus res = SECSuccess; | 62 | 436 | if (!scalar || !scalar->data) { | 63 | 0 | PORT_SetError(SEC_ERROR_INVALID_ARGS); | 64 | 0 | res = SECFailure; | 65 | 0 | return res; | 66 | 0 | } | 67 | | | 68 | 436 | if (scalar->len != 66) { | 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_P521_validate_private_key(scalar->data); | 76 | | #else | 77 | 436 | bool b = PR_TRUE; | 78 | 436 | #endif | 79 | | | 80 | 436 | if (!b) { | 81 | 0 | PORT_SetError(SEC_ERROR_BAD_KEY); | 82 | 0 | res = SECFailure; | 83 | 0 | } | 84 | 436 | return res; | 85 | 436 | } |
|
86 | | |
87 | | /* |
88 | | * Scalar multiplication for P-521. |
89 | | * If P == NULL, the base point is used. |
90 | | * Returns X = k*P |
91 | | */ |
92 | | |
93 | | SECStatus |
94 | | ec_secp521r1_pt_mul(SECItem *X, SECItem *k, SECItem *P) |
95 | 786 | { |
96 | 786 | SECStatus res = SECSuccess; |
97 | 786 | if (!P) { |
98 | 656 | uint8_t derived[132] = { 0 }; |
99 | | |
100 | 656 | if (!X || !k || !X->data || !k->data || |
101 | 656 | X->len < 133 || k->len != 66) { |
102 | 4 | PORT_SetError(SEC_ERROR_INVALID_ARGS); |
103 | 4 | res = SECFailure; |
104 | 4 | return res; |
105 | 4 | } |
106 | | |
107 | | #ifndef UNSAFE_FUZZER_MODE |
108 | 473 | bool b = Hacl_P521_dh_initiator(derived, k->data); |
109 | | #else |
110 | 179 | bool b = PR_TRUE; |
111 | | #endif |
112 | | |
113 | 652 | if (!b) { |
114 | 21 | PORT_SetError(SEC_ERROR_BAD_KEY); |
115 | 21 | res = SECFailure; |
116 | 21 | return res; |
117 | 21 | } |
118 | | |
119 | 631 | X->len = 133; |
120 | 631 | X->data[0] = EC_POINT_FORM_UNCOMPRESSED; |
121 | 631 | memcpy(X->data + 1, derived, 132); |
122 | | |
123 | 631 | } else { |
124 | 130 | uint8_t full_key[66] = { 0 }; |
125 | 130 | uint8_t *key; |
126 | 130 | uint8_t derived[132] = { 0 }; |
127 | | |
128 | 130 | if (!X || !k || !P || !X->data || !k->data || !P->data || |
129 | 130 | X->len < 66 || P->len != 133 || |
130 | 130 | 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 66, or of size 67 with a single leading 0 */ |
137 | 130 | if (k->len < 66) { |
138 | 0 | memcpy(full_key + 66 - k->len, k->data, k->len); |
139 | 0 | key = full_key; |
140 | 130 | } else if (k->len == 66) { |
141 | 130 | key = k->data; |
142 | 130 | } else if (k->len == 67 && 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 | 17 | bool b = Hacl_P521_dh_responder(derived, P->data + 1, key); |
152 | | #else |
153 | 113 | bool b = key != NULL; /* Avoiding unused variable warnings */ |
154 | 113 | #endif |
155 | | |
156 | 130 | if (!b) { |
157 | 0 | PORT_SetError(SEC_ERROR_BAD_KEY); |
158 | 0 | res = SECFailure; |
159 | 0 | return res; |
160 | 0 | } |
161 | | |
162 | 130 | X->len = 66; |
163 | 130 | memcpy(X->data, derived, 66); |
164 | 130 | } |
165 | | |
166 | 761 | return res; |
167 | 786 | } Line | Count | Source | 95 | 494 | { | 96 | 494 | SECStatus res = SECSuccess; | 97 | 494 | if (!P) { | 98 | 477 | uint8_t derived[132] = { 0 }; | 99 | | | 100 | 477 | if (!X || !k || !X->data || !k->data || | 101 | 477 | X->len < 133 || k->len != 66) { | 102 | 4 | PORT_SetError(SEC_ERROR_INVALID_ARGS); | 103 | 4 | res = SECFailure; | 104 | 4 | return res; | 105 | 4 | } | 106 | | | 107 | 473 | #ifndef UNSAFE_FUZZER_MODE | 108 | 477 | bool b = Hacl_P521_dh_initiator(derived, k->data); | 109 | | #else | 110 | | bool b = PR_TRUE; | 111 | | #endif | 112 | | | 113 | 473 | if (!b) { | 114 | 21 | PORT_SetError(SEC_ERROR_BAD_KEY); | 115 | 21 | res = SECFailure; | 116 | 21 | return res; | 117 | 21 | } | 118 | | | 119 | 452 | X->len = 133; | 120 | 452 | X->data[0] = EC_POINT_FORM_UNCOMPRESSED; | 121 | 452 | memcpy(X->data + 1, derived, 132); | 122 | | | 123 | 452 | } else { | 124 | 17 | uint8_t full_key[66] = { 0 }; | 125 | 17 | uint8_t *key; | 126 | 17 | uint8_t derived[132] = { 0 }; | 127 | | | 128 | 17 | if (!X || !k || !P || !X->data || !k->data || !P->data || | 129 | 17 | X->len < 66 || P->len != 133 || | 130 | 17 | 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 66, or of size 67 with a single leading 0 */ | 137 | 17 | if (k->len < 66) { | 138 | 0 | memcpy(full_key + 66 - k->len, k->data, k->len); | 139 | 0 | key = full_key; | 140 | 17 | } else if (k->len == 66) { | 141 | 17 | key = k->data; | 142 | 17 | } else if (k->len == 67 && 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 | 17 | #ifndef UNSAFE_FUZZER_MODE | 151 | 17 | bool b = Hacl_P521_dh_responder(derived, P->data + 1, key); | 152 | | #else | 153 | | bool b = key != NULL; /* Avoiding unused variable warnings */ | 154 | | #endif | 155 | | | 156 | 17 | if (!b) { | 157 | 0 | PORT_SetError(SEC_ERROR_BAD_KEY); | 158 | 0 | res = SECFailure; | 159 | 0 | return res; | 160 | 0 | } | 161 | | | 162 | 17 | X->len = 66; | 163 | 17 | memcpy(X->data, derived, 66); | 164 | 17 | } | 165 | | | 166 | 469 | return res; | 167 | 494 | } |
Line | Count | Source | 95 | 292 | { | 96 | 292 | SECStatus res = SECSuccess; | 97 | 292 | if (!P) { | 98 | 179 | uint8_t derived[132] = { 0 }; | 99 | | | 100 | 179 | if (!X || !k || !X->data || !k->data || | 101 | 179 | X->len < 133 || k->len != 66) { | 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_P521_dh_initiator(derived, k->data); | 109 | | #else | 110 | 179 | bool b = PR_TRUE; | 111 | 179 | #endif | 112 | | | 113 | 179 | if (!b) { | 114 | 0 | PORT_SetError(SEC_ERROR_BAD_KEY); | 115 | 0 | res = SECFailure; | 116 | 0 | return res; | 117 | 0 | } | 118 | | | 119 | 179 | X->len = 133; | 120 | 179 | X->data[0] = EC_POINT_FORM_UNCOMPRESSED; | 121 | 179 | memcpy(X->data + 1, derived, 132); | 122 | | | 123 | 179 | } else { | 124 | 113 | uint8_t full_key[66] = { 0 }; | 125 | 113 | uint8_t *key; | 126 | 113 | uint8_t derived[132] = { 0 }; | 127 | | | 128 | 113 | if (!X || !k || !P || !X->data || !k->data || !P->data || | 129 | 113 | X->len < 66 || P->len != 133 || | 130 | 113 | 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 66, or of size 67 with a single leading 0 */ | 137 | 113 | if (k->len < 66) { | 138 | 0 | memcpy(full_key + 66 - k->len, k->data, k->len); | 139 | 0 | key = full_key; | 140 | 113 | } else if (k->len == 66) { | 141 | 113 | key = k->data; | 142 | 113 | } else if (k->len == 67 && 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_P521_dh_responder(derived, P->data + 1, key); | 152 | | #else | 153 | 113 | bool b = key != NULL; /* Avoiding unused variable warnings */ | 154 | 113 | #endif | 155 | | | 156 | 113 | if (!b) { | 157 | 0 | PORT_SetError(SEC_ERROR_BAD_KEY); | 158 | 0 | res = SECFailure; | 159 | 0 | return res; | 160 | 0 | } | 161 | | | 162 | 113 | X->len = 66; | 163 | 113 | memcpy(X->data, derived, 66); | 164 | 113 | } | 165 | | | 166 | 292 | return res; | 167 | 292 | } |
|
168 | | |
169 | | /* |
170 | | * ECDSA Signature for P-521 |
171 | | */ |
172 | | |
173 | | SECStatus |
174 | | ec_secp521r1_sign_digest(ECPrivateKey *ecPrivKey, SECItem *signature, |
175 | | const SECItem *digest, const unsigned char *kb, |
176 | | const unsigned int kblen) |
177 | 82 | { |
178 | 82 | SECStatus res = SECSuccess; |
179 | | |
180 | 82 | if (!ecPrivKey || !signature || !digest || !kb || |
181 | 82 | !ecPrivKey->privateValue.data || |
182 | 82 | !signature->data || !digest->data || |
183 | 82 | ecPrivKey->ecParams.name != ECCurve_NIST_P521) { |
184 | 0 | PORT_SetError(SEC_ERROR_INVALID_ARGS); |
185 | 0 | return SECFailure; |
186 | 0 | } |
187 | | |
188 | 82 | if (kblen == 0 || digest->len == 0 || signature->len < 132) { |
189 | 0 | PORT_SetError(SEC_ERROR_INPUT_LEN); |
190 | 0 | return SECFailure; |
191 | 0 | } |
192 | | |
193 | | // Private keys should be 66 bytes, but some software trims leading zeros, |
194 | | // and some software produces 67 byte keys with a leading zero. We'll |
195 | | // accept these variants. |
196 | 82 | uint8_t padded_key_data[66] = { 0 }; |
197 | 82 | uint8_t *key; |
198 | 82 | SECItem *privKey = &ecPrivKey->privateValue; |
199 | 82 | if (privKey->len == 66) { |
200 | 82 | key = privKey->data; |
201 | 82 | } else if (privKey->len == 67 && privKey->data[0] == 0) { |
202 | 0 | key = privKey->data + 1; |
203 | 0 | } else if (privKey->len < 66) { |
204 | 0 | memcpy(padded_key_data + 66 - privKey->len, privKey->data, privKey->len); |
205 | 0 | key = padded_key_data; |
206 | 0 | } else { |
207 | 0 | PORT_SetError(SEC_ERROR_INPUT_LEN); |
208 | 0 | return SECFailure; |
209 | 0 | } |
210 | | |
211 | 82 | uint8_t hash[66] = { 0 }; |
212 | 82 | if (digest->len < 66) { |
213 | 72 | memcpy(hash + 66 - digest->len, digest->data, digest->len); |
214 | 72 | } else { |
215 | | // SEC 1 takes the most significant ceil(log(n)) bits of hash output when the hash output is longer than log(n). |
216 | 10 | hash[0] = digest->data[0] >> 7; |
217 | 660 | for (size_t i = 1; i < 66; i++) { |
218 | 650 | hash[i] = (digest->data[i - 1] << 1) | (digest->data[i] >> 7); |
219 | 650 | } |
220 | 10 | } |
221 | | |
222 | 82 | uint8_t nonce[66] = { 0 }; |
223 | 82 | if (kblen < 66) { |
224 | 39 | memcpy(nonce + 66 - kblen, kb, kblen); |
225 | 43 | } else { |
226 | 43 | memcpy(nonce, kb, 66); |
227 | 43 | } |
228 | | |
229 | 82 | #ifndef UNSAFE_FUZZER_MODE |
230 | 82 | bool b = Hacl_P521_ecdsa_sign_p521_without_hash( |
231 | 82 | signature->data, 66, hash, key, nonce); |
232 | | #else |
233 | | bool b = key != NULL; /* Avoiding unused variable warnings */ |
234 | | #endif |
235 | | |
236 | 82 | if (!b) { |
237 | 11 | PORT_SetError(SEC_ERROR_BAD_KEY); |
238 | 11 | res = SECFailure; |
239 | 11 | return res; |
240 | 11 | } |
241 | | |
242 | 71 | signature->len = 132; |
243 | 71 | return res; |
244 | 82 | } |
245 | | |
246 | | /* |
247 | | * ECDSA Signature Verification for P-521 |
248 | | */ |
249 | | |
250 | | SECStatus |
251 | | ec_secp521r1_verify_digest(ECPublicKey *key, const SECItem *signature, |
252 | | const SECItem *digest) |
253 | 232 | { |
254 | 232 | SECStatus res = SECSuccess; |
255 | | |
256 | 232 | if (!key || !signature || !digest || |
257 | 232 | !key->publicValue.data || |
258 | 232 | !signature->data || !digest->data || |
259 | 232 | key->ecParams.name != ECCurve_NIST_P521) { |
260 | 0 | PORT_SetError(SEC_ERROR_INVALID_ARGS); |
261 | 0 | res = SECFailure; |
262 | 0 | return res; |
263 | 0 | } |
264 | | |
265 | 232 | if (signature->len == 0 || signature->len % 2 != 0 || |
266 | 232 | signature->len > 132 || digest->len == 0 || |
267 | 232 | key->publicValue.len != 133) { |
268 | 0 | PORT_SetError(SEC_ERROR_INPUT_LEN); |
269 | 0 | res = SECFailure; |
270 | 0 | return res; |
271 | 0 | } |
272 | | |
273 | 232 | if (key->publicValue.data[0] != EC_POINT_FORM_UNCOMPRESSED) { |
274 | 0 | PORT_SetError(SEC_ERROR_UNSUPPORTED_EC_POINT_FORM); |
275 | 0 | res = SECFailure; |
276 | 0 | return res; |
277 | 0 | } |
278 | | |
279 | | // Signatures should be 132 bytes, but some software produces short signatures. |
280 | | // Pad components with zeros if necessary. |
281 | 232 | uint8_t paddedSigData[132] = { 0 }; |
282 | 232 | uint8_t *sig; |
283 | 232 | if (signature->len != 132) { |
284 | 0 | size_t split = signature->len / 2; |
285 | |
|
286 | 0 | memcpy(paddedSigData + 66 - split, signature->data, split); |
287 | 0 | memcpy(paddedSigData + 132 - split, signature->data + split, split); |
288 | |
|
289 | 0 | sig = paddedSigData; |
290 | 232 | } else { |
291 | 232 | sig = signature->data; |
292 | 232 | } |
293 | | |
294 | 232 | uint8_t hash[66] = { 0 }; |
295 | 232 | if (digest->len < 66) { |
296 | 221 | memcpy(hash + 66 - digest->len, digest->data, digest->len); |
297 | 221 | } else { |
298 | | // SEC 1 takes the most significant ceil(log(n)) bits of hash output when the hash output is longer than log(n). |
299 | 11 | hash[0] = digest->data[0] >> 7; |
300 | 726 | for (size_t i = 1; i < 66; i++) { |
301 | 715 | hash[i] = (digest->data[i - 1] << 1) | (digest->data[i] >> 7); |
302 | 715 | } |
303 | 11 | } |
304 | | |
305 | 232 | #ifndef UNSAFE_FUZZER_MODE |
306 | 232 | bool b = Hacl_P521_ecdsa_verif_without_hash( |
307 | 232 | 66, hash, key->publicValue.data + 1, sig, sig + 66); |
308 | | #else |
309 | | bool b = sig != NULL; /* Avoiding unused variable warnings */ |
310 | | #endif |
311 | | |
312 | 232 | if (!b) { |
313 | 151 | PORT_SetError(SEC_ERROR_BAD_SIGNATURE); |
314 | 151 | res = SECFailure; |
315 | 151 | return res; |
316 | 151 | } |
317 | | |
318 | 81 | return res; |
319 | 232 | } |
320 | | |
321 | | /* |
322 | | Point decompression for P-521. |
323 | | |
324 | | publicCompressed must be 67 bytes (1 byte for a sign and 66 bytes for the x coordinate. |
325 | | publicUncompressed must be 132 bytes (66 * 2). |
326 | | The function returns SECSuccess if the decompression was success and the decompresse |
327 | | point is a valid P-521 curve point. |
328 | | */ |
329 | | |
330 | | SECStatus |
331 | | ec_secp521r1_decompress(const SECItem *publicCompressed, SECItem *publicUncompressed) |
332 | 33 | { |
333 | 33 | if (!publicCompressed || !publicCompressed->data) { |
334 | 0 | PORT_SetError(SEC_ERROR_INVALID_ARGS); |
335 | 0 | return SECFailure; |
336 | 0 | } |
337 | | |
338 | 33 | if (publicCompressed->len != 67) { |
339 | 33 | PORT_SetError(SEC_ERROR_BAD_KEY); |
340 | 33 | return SECFailure; |
341 | 33 | } |
342 | | |
343 | 0 | if (!publicUncompressed || !publicUncompressed->data) { |
344 | 0 | PORT_SetError(SEC_ERROR_INVALID_ARGS); |
345 | 0 | return SECFailure; |
346 | 0 | } |
347 | | |
348 | 0 | if (publicUncompressed->len != 133) { |
349 | 0 | PORT_SetError(SEC_ERROR_INVALID_ARGS); |
350 | 0 | return SECFailure; |
351 | 0 | } |
352 | | |
353 | 0 | if (publicCompressed->data[0] != EC_POINT_FORM_COMPRESSED_Y0 && |
354 | 0 | publicCompressed->data[0] != EC_POINT_FORM_COMPRESSED_Y1) { |
355 | 0 | PORT_SetError(SEC_ERROR_UNSUPPORTED_EC_POINT_FORM); |
356 | 0 | return SECFailure; |
357 | 0 | } |
358 | | |
359 | 0 | bool b = Hacl_P521_compressed_to_raw(publicCompressed->data, publicUncompressed->data + 1); |
360 | |
|
361 | 0 | if (!b) { |
362 | 0 | PORT_SetError(SEC_ERROR_BAD_KEY); |
363 | 0 | return SECFailure; |
364 | 0 | } |
365 | | |
366 | 0 | publicUncompressed->data[0] = EC_POINT_FORM_UNCOMPRESSED; |
367 | 0 | return SECSuccess; |
368 | 0 | } |