ecp_secp384r1.c (9364B)
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 { 22 SECStatus res = SECSuccess; 23 if (!pt || !pt->data) { 24 PORT_SetError(SEC_ERROR_INVALID_ARGS); 25 res = SECFailure; 26 return res; 27 } 28 29 if (pt->len != 97) { 30 PORT_SetError(SEC_ERROR_BAD_KEY); 31 res = SECFailure; 32 return res; 33 } 34 35 if (pt->data[0] != EC_POINT_FORM_UNCOMPRESSED) { 36 PORT_SetError(SEC_ERROR_UNSUPPORTED_EC_POINT_FORM); 37 res = SECFailure; 38 return res; 39 } 40 41 #ifndef UNSAFE_FUZZER_MODE 42 bool b = Hacl_P384_validate_public_key(pt->data + 1); 43 #else 44 bool b = PR_TRUE; 45 #endif 46 47 if (!b) { 48 PORT_SetError(SEC_ERROR_BAD_KEY); 49 res = SECFailure; 50 } 51 return res; 52 } 53 54 /* 55 * Scalar Validation for P-384. 56 */ 57 58 SECStatus 59 ec_secp384r1_scalar_validate(const SECItem *scalar) 60 { 61 SECStatus res = SECSuccess; 62 if (!scalar || !scalar->data) { 63 PORT_SetError(SEC_ERROR_INVALID_ARGS); 64 res = SECFailure; 65 return res; 66 } 67 68 if (scalar->len != 48) { 69 PORT_SetError(SEC_ERROR_BAD_KEY); 70 res = SECFailure; 71 return res; 72 } 73 74 #ifndef UNSAFE_FUZZER_MODE 75 bool b = Hacl_P384_validate_private_key(scalar->data); 76 #else 77 bool b = PR_TRUE; 78 #endif 79 80 if (!b) { 81 PORT_SetError(SEC_ERROR_BAD_KEY); 82 res = SECFailure; 83 } 84 return res; 85 } 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 { 96 SECStatus res = SECSuccess; 97 if (!P) { 98 uint8_t derived[96] = { 0 }; 99 100 if (!X || !k || !X->data || !k->data || 101 X->len < 97 || k->len != 48) { 102 PORT_SetError(SEC_ERROR_INVALID_ARGS); 103 res = SECFailure; 104 return res; 105 } 106 107 #ifndef UNSAFE_FUZZER_MODE 108 bool b = Hacl_P384_dh_initiator(derived, k->data); 109 #else 110 bool b = PR_TRUE; 111 #endif 112 113 if (!b) { 114 PORT_SetError(SEC_ERROR_BAD_KEY); 115 res = SECFailure; 116 return res; 117 } 118 119 X->len = 97; 120 X->data[0] = EC_POINT_FORM_UNCOMPRESSED; 121 memcpy(X->data + 1, derived, 96); 122 123 } else { 124 uint8_t full_key[48] = { 0 }; 125 uint8_t *key; 126 uint8_t derived[96] = { 0 }; 127 128 if (!X || !k || !P || !X->data || !k->data || !P->data || 129 X->len < 48 || P->len != 97 || 130 P->data[0] != EC_POINT_FORM_UNCOMPRESSED) { 131 PORT_SetError(SEC_ERROR_INVALID_ARGS); 132 res = SECFailure; 133 return res; 134 } 135 136 /* We consider keys of up to size 48, or of size 49 with a single leading 0 */ 137 if (k->len < 48) { 138 memcpy(full_key + 48 - k->len, k->data, k->len); 139 key = full_key; 140 } else if (k->len == 48) { 141 key = k->data; 142 } else if (k->len == 49 && k->data[0] == 0) { 143 key = k->data + 1; 144 } else { 145 PORT_SetError(SEC_ERROR_INVALID_ARGS); 146 res = SECFailure; 147 return res; 148 } 149 150 #ifndef UNSAFE_FUZZER_MODE 151 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 if (!b) { 157 PORT_SetError(SEC_ERROR_BAD_KEY); 158 res = SECFailure; 159 return res; 160 } 161 162 X->len = 48; 163 memcpy(X->data, derived, 48); 164 } 165 166 return res; 167 } 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 { 178 SECStatus res = SECSuccess; 179 180 if (!ecPrivKey || !signature || !digest || !kb || 181 !ecPrivKey->privateValue.data || 182 !signature->data || !digest->data || 183 ecPrivKey->ecParams.name != ECCurve_NIST_P384) { 184 PORT_SetError(SEC_ERROR_INVALID_ARGS); 185 res = SECFailure; 186 return res; 187 } 188 189 if (kblen == 0 || digest->len == 0 || signature->len < 96) { 190 PORT_SetError(SEC_ERROR_INPUT_LEN); 191 res = SECFailure; 192 return res; 193 } 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 uint8_t padded_key_data[48] = { 0 }; 199 uint8_t *key; 200 SECItem *privKey = &ecPrivKey->privateValue; 201 if (privKey->len == 48) { 202 key = privKey->data; 203 } else if (privKey->len == 49 && privKey->data[0] == 0) { 204 key = privKey->data + 1; 205 } else if (privKey->len < 48) { 206 memcpy(padded_key_data + 48 - privKey->len, privKey->data, privKey->len); 207 key = padded_key_data; 208 } else { 209 PORT_SetError(SEC_ERROR_INPUT_LEN); 210 return SECFailure; 211 } 212 213 uint8_t hash[48] = { 0 }; 214 if (digest->len < 48) { 215 memcpy(hash + 48 - digest->len, digest->data, digest->len); 216 } else { 217 memcpy(hash, digest->data, 48); 218 } 219 220 uint8_t nonce[48] = { 0 }; 221 if (kblen < 48) { 222 memcpy(nonce + 48 - kblen, kb, kblen); 223 } else { 224 memcpy(nonce, kb, 48); 225 } 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 bool b = key != NULL; /* Avoiding unused variable warnings */ 232 #endif 233 234 if (!b) { 235 PORT_SetError(SEC_ERROR_BAD_KEY); 236 res = SECFailure; 237 return res; 238 } 239 240 signature->len = 96; 241 return res; 242 } 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 { 252 SECStatus res = SECSuccess; 253 254 if (!key || !signature || !digest || 255 !key->publicValue.data || 256 !signature->data || !digest->data || 257 key->ecParams.name != ECCurve_NIST_P384) { 258 PORT_SetError(SEC_ERROR_INVALID_ARGS); 259 res = SECFailure; 260 return res; 261 } 262 263 if (signature->len == 0 || signature->len % 2 != 0 || 264 signature->len > 96 || digest->len == 0 || 265 key->publicValue.len != 97) { 266 PORT_SetError(SEC_ERROR_INPUT_LEN); 267 res = SECFailure; 268 return res; 269 } 270 271 if (key->publicValue.data[0] != EC_POINT_FORM_UNCOMPRESSED) { 272 PORT_SetError(SEC_ERROR_UNSUPPORTED_EC_POINT_FORM); 273 res = SECFailure; 274 return res; 275 } 276 277 // Signatures should be 96 bytes, but some software produces short signatures. 278 // Pad components with zeros if necessary. 279 uint8_t paddedSigData[96] = { 0 }; 280 uint8_t *sig; 281 if (signature->len != 96) { 282 size_t split = signature->len / 2; 283 284 memcpy(paddedSigData + 48 - split, signature->data, split); 285 memcpy(paddedSigData + 96 - split, signature->data + split, split); 286 287 sig = paddedSigData; 288 } else { 289 sig = signature->data; 290 } 291 292 uint8_t hash[48] = { 0 }; 293 if (digest->len < 48) { 294 memcpy(hash + 48 - digest->len, digest->data, digest->len); 295 } else { 296 memcpy(hash, digest->data, 48); 297 } 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 bool b = sig != NULL; /* Avoiding unused variable warnings */ 304 #endif 305 306 if (!b) { 307 PORT_SetError(SEC_ERROR_BAD_SIGNATURE); 308 res = SECFailure; 309 return res; 310 } 311 312 return res; 313 } 314 315 /* 316 Point decompression for P-384. 317 318 publicCompressed must be 49 bytes (1 byte for a sign and 48 bytes for the x coordinate. 319 publicUncompressed must be 96 bytes (48 * 2). 320 The function returns SECSuccess if the decompression was success and the decompresse 321 point is a valid P-384 curve point. 322 */ 323 324 SECStatus 325 ec_secp384r1_decompress(const SECItem *publicCompressed, SECItem *publicUncompressed) 326 { 327 if (!publicCompressed || !publicCompressed->data) { 328 PORT_SetError(SEC_ERROR_INVALID_ARGS); 329 return SECFailure; 330 } 331 332 if (publicCompressed->len != 49) { 333 PORT_SetError(SEC_ERROR_BAD_KEY); 334 return SECFailure; 335 } 336 337 if (!publicUncompressed || !publicUncompressed->data) { 338 PORT_SetError(SEC_ERROR_INVALID_ARGS); 339 return SECFailure; 340 } 341 342 if (publicUncompressed->len != 97) { 343 PORT_SetError(SEC_ERROR_INVALID_ARGS); 344 return SECFailure; 345 } 346 347 if (publicCompressed->data[0] != EC_POINT_FORM_COMPRESSED_Y0 && 348 publicCompressed->data[0] != EC_POINT_FORM_COMPRESSED_Y1) { 349 PORT_SetError(SEC_ERROR_UNSUPPORTED_EC_POINT_FORM); 350 return SECFailure; 351 } 352 353 bool b = Hacl_P384_compressed_to_raw(publicCompressed->data, publicUncompressed->data + 1); 354 355 if (!b) { 356 PORT_SetError(SEC_ERROR_BAD_KEY); 357 return SECFailure; 358 } 359 360 publicUncompressed->data[0] = EC_POINT_FORM_UNCOMPRESSED; 361 return SECSuccess; 362 }