ecp_secp256r1.c (9306B)
1 /* P-256 from HACL* */ 2 3 #ifdef FREEBL_NO_DEPEND 4 #include "../stubs.h" 5 #endif 6 7 #include "ecl-priv.h" 8 #include "secitem.h" 9 #include "secerr.h" 10 #include "secmpi.h" 11 #include "../verified/Hacl_P256.h" 12 13 /* 14 * Point Validation for P-256. 15 */ 16 17 SECStatus 18 ec_secp256r1_pt_validate(const SECItem *pt) 19 { 20 SECStatus res = SECSuccess; 21 if (!pt || !pt->data) { 22 PORT_SetError(SEC_ERROR_INVALID_ARGS); 23 res = SECFailure; 24 return res; 25 } 26 27 if (pt->len != 65) { 28 PORT_SetError(SEC_ERROR_BAD_KEY); 29 res = SECFailure; 30 return res; 31 } 32 33 if (pt->data[0] != EC_POINT_FORM_UNCOMPRESSED) { 34 PORT_SetError(SEC_ERROR_UNSUPPORTED_EC_POINT_FORM); 35 res = SECFailure; 36 return res; 37 } 38 39 #ifndef UNSAFE_FUZZER_MODE 40 bool b = Hacl_P256_validate_public_key(pt->data + 1); 41 #else 42 bool b = PR_TRUE; 43 #endif 44 45 if (!b) { 46 PORT_SetError(SEC_ERROR_BAD_KEY); 47 res = SECFailure; 48 } 49 return res; 50 } 51 52 /* 53 * Scalar Validation for P-256. 54 */ 55 56 SECStatus 57 ec_secp256r1_scalar_validate(const SECItem *scalar) 58 { 59 SECStatus res = SECSuccess; 60 if (!scalar || !scalar->data) { 61 PORT_SetError(SEC_ERROR_INVALID_ARGS); 62 res = SECFailure; 63 return res; 64 } 65 66 if (scalar->len != 32) { 67 PORT_SetError(SEC_ERROR_BAD_KEY); 68 res = SECFailure; 69 return res; 70 } 71 72 #ifndef UNSAFE_FUZZER_MODE 73 bool b = Hacl_P256_validate_private_key(scalar->data); 74 #else 75 bool b = PR_TRUE; 76 #endif 77 78 if (!b) { 79 PORT_SetError(SEC_ERROR_BAD_KEY); 80 res = SECFailure; 81 } 82 return res; 83 } 84 85 /* 86 * Scalar multiplication for P-256. 87 * If P == NULL, the base point is used. 88 * Returns X = k*P 89 */ 90 91 SECStatus 92 ec_secp256r1_pt_mul(SECItem *X, SECItem *k, SECItem *P) 93 { 94 SECStatus res = SECSuccess; 95 if (!P) { 96 uint8_t derived[64] = { 0 }; 97 98 if (!X || !k || !X->data || !k->data || 99 X->len < 65 || k->len != 32) { 100 PORT_SetError(SEC_ERROR_INVALID_ARGS); 101 res = SECFailure; 102 return res; 103 } 104 105 #ifndef UNSAFE_FUZZER_MODE 106 bool b = Hacl_P256_dh_initiator(derived, k->data); 107 #else 108 bool b = PR_TRUE; 109 #endif 110 111 if (!b) { 112 PORT_SetError(SEC_ERROR_BAD_KEY); 113 res = SECFailure; 114 return res; 115 } 116 117 X->len = 65; 118 X->data[0] = EC_POINT_FORM_UNCOMPRESSED; 119 memcpy(X->data + 1, derived, 64); 120 121 } else { 122 uint8_t full_key[32] = { 0 }; 123 uint8_t *key; 124 uint8_t derived[64] = { 0 }; 125 126 if (!X || !k || !P || !X->data || !k->data || !P->data || 127 X->len < 32 || P->len != 65 || 128 P->data[0] != EC_POINT_FORM_UNCOMPRESSED) { 129 PORT_SetError(SEC_ERROR_INVALID_ARGS); 130 res = SECFailure; 131 return res; 132 } 133 134 /* We consider keys of up to size 32, or of size 33 with a single leading 0 */ 135 if (k->len < 32) { 136 memcpy(full_key + 32 - k->len, k->data, k->len); 137 key = full_key; 138 } else if (k->len == 32) { 139 key = k->data; 140 } else if (k->len == 33 && k->data[0] == 0) { 141 key = k->data + 1; 142 } else { 143 PORT_SetError(SEC_ERROR_INVALID_ARGS); 144 res = SECFailure; 145 return res; 146 } 147 148 bool b = Hacl_P256_dh_responder(derived, P->data + 1, key); 149 150 if (!b) { 151 PORT_SetError(SEC_ERROR_BAD_KEY); 152 res = SECFailure; 153 return res; 154 } 155 156 X->len = 32; 157 memcpy(X->data, derived, 32); 158 } 159 160 return res; 161 } 162 163 /* 164 * ECDSA Signature for P-256 165 */ 166 167 SECStatus 168 ec_secp256r1_sign_digest(ECPrivateKey *ecPrivKey, SECItem *signature, 169 const SECItem *digest, const unsigned char *kb, 170 const unsigned int kblen) 171 { 172 SECStatus res = SECSuccess; 173 174 if (!ecPrivKey || !signature || !digest || !kb || 175 !ecPrivKey->privateValue.data || 176 !signature->data || !digest->data || 177 ecPrivKey->ecParams.name != ECCurve_NIST_P256) { 178 PORT_SetError(SEC_ERROR_INVALID_ARGS); 179 res = SECFailure; 180 return res; 181 } 182 183 if (kblen == 0 || digest->len == 0 || signature->len < 64) { 184 PORT_SetError(SEC_ERROR_INPUT_LEN); 185 res = SECFailure; 186 return res; 187 } 188 189 // Private keys should be 32 bytes, but some software trims leading zeros, 190 // and some software produces 33 byte keys with a leading zero. We'll 191 // accept these variants. 192 uint8_t padded_key_data[32] = { 0 }; 193 uint8_t *key; 194 SECItem *privKey = &ecPrivKey->privateValue; 195 if (privKey->len == 32) { 196 key = privKey->data; 197 } else if (privKey->len == 33 && privKey->data[0] == 0) { 198 key = privKey->data + 1; 199 } else if (privKey->len < 32) { 200 memcpy(padded_key_data + 32 - privKey->len, privKey->data, privKey->len); 201 key = padded_key_data; 202 } else { 203 PORT_SetError(SEC_ERROR_INPUT_LEN); 204 return SECFailure; 205 } 206 207 uint8_t hash[32] = { 0 }; 208 if (digest->len < 32) { 209 memcpy(hash + 32 - digest->len, digest->data, digest->len); 210 } else { 211 memcpy(hash, digest->data, 32); 212 } 213 214 uint8_t nonce[32] = { 0 }; 215 if (kblen < 32) { 216 memcpy(nonce + 32 - kblen, kb, kblen); 217 } else { 218 memcpy(nonce, kb, 32); 219 } 220 221 #ifndef UNSAFE_FUZZER_MODE 222 bool b = Hacl_P256_ecdsa_sign_p256_without_hash( 223 signature->data, 32, hash, key, nonce); 224 #else 225 bool b = key != NULL; /* Avoiding unused variable warnings */ 226 #endif 227 228 if (!b) { 229 PORT_SetError(SEC_ERROR_BAD_KEY); 230 res = SECFailure; 231 return res; 232 } 233 234 signature->len = 64; 235 return res; 236 } 237 238 /* 239 * ECDSA Signature Verification for P-256 240 */ 241 242 SECStatus 243 ec_secp256r1_verify_digest(ECPublicKey *key, const SECItem *signature, 244 const SECItem *digest) 245 { 246 SECStatus res = SECSuccess; 247 248 unsigned char _padded_sig_data[64] = { 0 }; 249 unsigned char *sig_r, *sig_s; 250 251 if (!key || !signature || !digest || 252 !key->publicValue.data || 253 !signature->data || !digest->data || 254 key->ecParams.name != ECCurve_NIST_P256) { 255 PORT_SetError(SEC_ERROR_INVALID_ARGS); 256 res = SECFailure; 257 return res; 258 } 259 260 unsigned int olen = key->ecParams.order.len; 261 if (signature->len == 0 || signature->len % 2 != 0 || 262 signature->len > 2 * olen || 263 digest->len == 0 || key->publicValue.len != 65) { 264 PORT_SetError(SEC_ERROR_INPUT_LEN); 265 res = SECFailure; 266 return res; 267 } 268 269 if (key->publicValue.data[0] != EC_POINT_FORM_UNCOMPRESSED) { 270 PORT_SetError(SEC_ERROR_UNSUPPORTED_EC_POINT_FORM); 271 res = SECFailure; 272 return res; 273 } 274 275 /* P-256 signature has to be 64 bytes long, pad it with 0s if it isn't */ 276 if (signature->len != 64) { 277 unsigned split = signature->len / 2; 278 unsigned pad = 32 - split; 279 280 unsigned char *o_sig = signature->data; 281 unsigned char *p_sig = _padded_sig_data; 282 283 memcpy(p_sig + pad, o_sig, split); 284 memcpy(p_sig + 32 + pad, o_sig + split, split); 285 286 sig_r = p_sig; 287 sig_s = p_sig + 32; 288 } else { 289 sig_r = signature->data; 290 sig_s = signature->data + 32; 291 } 292 293 uint8_t hash[32] = { 0 }; 294 if (digest->len < 32) { 295 memcpy(hash + 32 - digest->len, digest->data, digest->len); 296 } else { 297 memcpy(hash, digest->data, 32); 298 } 299 300 #ifndef UNSAFE_FUZZER_MODE 301 bool b = Hacl_P256_ecdsa_verif_without_hash( 302 32, hash, 303 key->publicValue.data + 1, 304 sig_r, sig_s); 305 #else 306 bool b = (sig_r != NULL) && (sig_s != NULL); /* Avoiding unused variable warnings */ 307 #endif 308 309 if (!b) { 310 PORT_SetError(SEC_ERROR_BAD_SIGNATURE); 311 res = SECFailure; 312 return res; 313 } 314 315 return res; 316 } 317 318 /* 319 Point decompression for P-256. 320 321 publicCompressed must be 33 bytes (1 byte for a sign and 32 bytes for the x coordinate. 322 publicUncompressed must be 64 bytes (32 * 2). 323 The function returns SECSuccess if the decompression was success and the decompresse 324 point is a valid P-256 curve point. 325 */ 326 327 SECStatus 328 ec_secp256r1_decompress(const SECItem *publicCompressed, SECItem *publicUncompressed) 329 { 330 if (!publicCompressed || !publicCompressed->data) { 331 PORT_SetError(SEC_ERROR_INVALID_ARGS); 332 return SECFailure; 333 } 334 335 if (publicCompressed->len != 33) { 336 PORT_SetError(SEC_ERROR_BAD_KEY); 337 return SECFailure; 338 } 339 340 if (!publicUncompressed || !publicUncompressed->data) { 341 PORT_SetError(SEC_ERROR_INVALID_ARGS); 342 return SECFailure; 343 } 344 345 if (publicUncompressed->len != 65) { 346 PORT_SetError(SEC_ERROR_INVALID_ARGS); 347 return SECFailure; 348 } 349 350 if (publicCompressed->data[0] != EC_POINT_FORM_COMPRESSED_Y0 && 351 publicCompressed->data[0] != EC_POINT_FORM_COMPRESSED_Y1) { 352 PORT_SetError(SEC_ERROR_UNSUPPORTED_EC_POINT_FORM); 353 return SECFailure; 354 } 355 356 bool b = Hacl_P256_compressed_to_raw(publicCompressed->data, publicUncompressed->data + 1); 357 358 if (!b) { 359 PORT_SetError(SEC_ERROR_BAD_KEY); 360 return SECFailure; 361 } 362 363 publicUncompressed->data[0] = EC_POINT_FORM_UNCOMPRESSED; 364 return SECSuccess; 365 }