/src/openssl30/crypto/ec/ec_ameth.c
| Line | Count | Source (jump to first uncovered line) | 
| 1 |  | /* | 
| 2 |  |  * Copyright 2006-2022 The OpenSSL Project Authors. All Rights Reserved. | 
| 3 |  |  * | 
| 4 |  |  * Licensed under the Apache License 2.0 (the "License").  You may not use | 
| 5 |  |  * this file except in compliance with the License.  You can obtain a copy | 
| 6 |  |  * in the file LICENSE in the source distribution or at | 
| 7 |  |  * https://www.openssl.org/source/license.html | 
| 8 |  |  */ | 
| 9 |  |  | 
| 10 |  | /* | 
| 11 |  |  * ECDH and ECDSA low level APIs are deprecated for public use, but still ok | 
| 12 |  |  * for internal use. | 
| 13 |  |  */ | 
| 14 |  | #include "internal/deprecated.h" | 
| 15 |  |  | 
| 16 |  | #include <stdio.h> | 
| 17 |  | #include "internal/cryptlib.h" | 
| 18 |  | #include <openssl/x509.h> | 
| 19 |  | #include <openssl/ec.h> | 
| 20 |  | #include <openssl/bn.h> | 
| 21 |  | #include <openssl/asn1t.h> | 
| 22 |  | #include "crypto/asn1.h" | 
| 23 |  | #include "crypto/evp.h" | 
| 24 |  | #include "crypto/x509.h" | 
| 25 |  | #include <openssl/core_names.h> | 
| 26 |  | #include <openssl/param_build.h> | 
| 27 |  | #include "ec_local.h" | 
| 28 |  |  | 
| 29 |  | static int eckey_param2type(int *pptype, void **ppval, const EC_KEY *ec_key) | 
| 30 | 0 | { | 
| 31 | 0 |     const EC_GROUP *group; | 
| 32 | 0 |     int nid; | 
| 33 |  | 
 | 
| 34 | 0 |     if (ec_key == NULL || (group = EC_KEY_get0_group(ec_key)) == NULL) { | 
| 35 | 0 |         ERR_raise(ERR_LIB_EC, EC_R_MISSING_PARAMETERS); | 
| 36 | 0 |         return 0; | 
| 37 | 0 |     } | 
| 38 | 0 |     if (EC_GROUP_get_asn1_flag(group) | 
| 39 | 0 |         && (nid = EC_GROUP_get_curve_name(group))) | 
| 40 |  |         /* we have a 'named curve' => just set the OID */ | 
| 41 | 0 |     { | 
| 42 | 0 |         ASN1_OBJECT *asn1obj = OBJ_nid2obj(nid); | 
| 43 |  | 
 | 
| 44 | 0 |         if (asn1obj == NULL || OBJ_length(asn1obj) == 0) { | 
| 45 | 0 |             ERR_raise(ERR_LIB_EC, EC_R_MISSING_OID); | 
| 46 | 0 |             return 0; | 
| 47 | 0 |         } | 
| 48 | 0 |         *ppval = asn1obj; | 
| 49 | 0 |         *pptype = V_ASN1_OBJECT; | 
| 50 | 0 |     } else {                    /* explicit parameters */ | 
| 51 |  | 
 | 
| 52 | 0 |         ASN1_STRING *pstr = NULL; | 
| 53 | 0 |         pstr = ASN1_STRING_new(); | 
| 54 | 0 |         if (pstr == NULL) | 
| 55 | 0 |             return 0; | 
| 56 | 0 |         pstr->length = i2d_ECParameters(ec_key, &pstr->data); | 
| 57 | 0 |         if (pstr->length <= 0) { | 
| 58 | 0 |             ASN1_STRING_free(pstr); | 
| 59 | 0 |             ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB); | 
| 60 | 0 |             return 0; | 
| 61 | 0 |         } | 
| 62 | 0 |         *ppval = pstr; | 
| 63 | 0 |         *pptype = V_ASN1_SEQUENCE; | 
| 64 | 0 |     } | 
| 65 | 0 |     return 1; | 
| 66 | 0 | } | 
| 67 |  |  | 
| 68 |  | static int eckey_pub_encode(X509_PUBKEY *pk, const EVP_PKEY *pkey) | 
| 69 | 0 | { | 
| 70 | 0 |     const EC_KEY *ec_key = pkey->pkey.ec; | 
| 71 | 0 |     void *pval = NULL; | 
| 72 | 0 |     int ptype; | 
| 73 | 0 |     unsigned char *penc = NULL, *p; | 
| 74 | 0 |     int penclen; | 
| 75 |  | 
 | 
| 76 | 0 |     if (!eckey_param2type(&ptype, &pval, ec_key)) { | 
| 77 | 0 |         ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB); | 
| 78 | 0 |         return 0; | 
| 79 | 0 |     } | 
| 80 | 0 |     penclen = i2o_ECPublicKey(ec_key, NULL); | 
| 81 | 0 |     if (penclen <= 0) | 
| 82 | 0 |         goto err; | 
| 83 | 0 |     penc = OPENSSL_malloc(penclen); | 
| 84 | 0 |     if (penc == NULL) | 
| 85 | 0 |         goto err; | 
| 86 | 0 |     p = penc; | 
| 87 | 0 |     penclen = i2o_ECPublicKey(ec_key, &p); | 
| 88 | 0 |     if (penclen <= 0) | 
| 89 | 0 |         goto err; | 
| 90 | 0 |     if (X509_PUBKEY_set0_param(pk, OBJ_nid2obj(EVP_PKEY_EC), | 
| 91 | 0 |                                ptype, pval, penc, penclen)) | 
| 92 | 0 |         return 1; | 
| 93 | 0 |  err: | 
| 94 | 0 |     if (ptype == V_ASN1_SEQUENCE) | 
| 95 | 0 |         ASN1_STRING_free(pval); | 
| 96 | 0 |     OPENSSL_free(penc); | 
| 97 | 0 |     return 0; | 
| 98 | 0 | } | 
| 99 |  |  | 
| 100 |  | static int eckey_pub_decode(EVP_PKEY *pkey, const X509_PUBKEY *pubkey) | 
| 101 | 186k | { | 
| 102 | 186k |     const unsigned char *p = NULL; | 
| 103 | 186k |     int pklen; | 
| 104 | 186k |     EC_KEY *eckey = NULL; | 
| 105 | 186k |     X509_ALGOR *palg; | 
| 106 | 186k |     OSSL_LIB_CTX *libctx = NULL; | 
| 107 | 186k |     const char *propq = NULL; | 
| 108 |  |  | 
| 109 | 186k |     if (!ossl_x509_PUBKEY_get0_libctx(&libctx, &propq, pubkey) | 
| 110 | 186k |         || !X509_PUBKEY_get0_param(NULL, &p, &pklen, &palg, pubkey)) | 
| 111 | 0 |         return 0; | 
| 112 | 186k |     eckey = ossl_ec_key_param_from_x509_algor(palg, libctx, propq); | 
| 113 |  |  | 
| 114 | 186k |     if (!eckey) | 
| 115 | 27.6k |         return 0; | 
| 116 |  |  | 
| 117 |  |     /* We have parameters now set public key */ | 
| 118 | 158k |     if (!o2i_ECPublicKey(&eckey, &p, pklen)) { | 
| 119 | 58.7k |         ERR_raise(ERR_LIB_EC, EC_R_DECODE_ERROR); | 
| 120 | 58.7k |         goto ecerr; | 
| 121 | 58.7k |     } | 
| 122 |  |  | 
| 123 | 99.9k |     EVP_PKEY_assign_EC_KEY(pkey, eckey); | 
| 124 | 99.9k |     return 1; | 
| 125 |  |  | 
| 126 | 58.7k |  ecerr: | 
| 127 | 58.7k |     EC_KEY_free(eckey); | 
| 128 | 58.7k |     return 0; | 
| 129 | 158k | } | 
| 130 |  |  | 
| 131 |  | static int eckey_pub_cmp(const EVP_PKEY *a, const EVP_PKEY *b) | 
| 132 | 6.11k | { | 
| 133 | 6.11k |     int r; | 
| 134 | 6.11k |     const EC_GROUP *group = EC_KEY_get0_group(b->pkey.ec); | 
| 135 | 6.11k |     const EC_POINT *pa = EC_KEY_get0_public_key(a->pkey.ec), | 
| 136 | 6.11k |         *pb = EC_KEY_get0_public_key(b->pkey.ec); | 
| 137 |  |  | 
| 138 | 6.11k |     if (group == NULL || pa == NULL || pb == NULL) | 
| 139 | 0 |         return -2; | 
| 140 | 6.11k |     r = EC_POINT_cmp(group, pa, pb, NULL); | 
| 141 | 6.11k |     if (r == 0) | 
| 142 | 6.11k |         return 1; | 
| 143 | 0 |     if (r == 1) | 
| 144 | 0 |         return 0; | 
| 145 | 0 |     return -2; | 
| 146 | 0 | } | 
| 147 |  |  | 
| 148 |  | static int eckey_priv_decode_ex(EVP_PKEY *pkey, const PKCS8_PRIV_KEY_INFO *p8, | 
| 149 |  |                                 OSSL_LIB_CTX *libctx, const char *propq) | 
| 150 | 31 | { | 
| 151 | 31 |     int ret = 0; | 
| 152 | 31 |     EC_KEY *eckey = ossl_ec_key_from_pkcs8(p8, libctx, propq); | 
| 153 |  |  | 
| 154 | 31 |     if (eckey != NULL) { | 
| 155 | 2 |         ret = 1; | 
| 156 | 2 |         EVP_PKEY_assign_EC_KEY(pkey, eckey); | 
| 157 | 2 |     } | 
| 158 |  |  | 
| 159 | 31 |     return ret; | 
| 160 | 31 | } | 
| 161 |  |  | 
| 162 |  | static int eckey_priv_encode(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pkey) | 
| 163 | 0 | { | 
| 164 | 0 |     EC_KEY ec_key = *(pkey->pkey.ec); | 
| 165 | 0 |     unsigned char *ep = NULL; | 
| 166 | 0 |     int eplen, ptype; | 
| 167 | 0 |     void *pval; | 
| 168 | 0 |     unsigned int old_flags; | 
| 169 |  | 
 | 
| 170 | 0 |     if (!eckey_param2type(&ptype, &pval, &ec_key)) { | 
| 171 | 0 |         ERR_raise(ERR_LIB_EC, EC_R_DECODE_ERROR); | 
| 172 | 0 |         return 0; | 
| 173 | 0 |     } | 
| 174 |  |  | 
| 175 |  |     /* set the private key */ | 
| 176 |  |  | 
| 177 |  |     /* | 
| 178 |  |      * do not include the parameters in the SEC1 private key see PKCS#11 | 
| 179 |  |      * 12.11 | 
| 180 |  |      */ | 
| 181 | 0 |     old_flags = EC_KEY_get_enc_flags(&ec_key); | 
| 182 | 0 |     EC_KEY_set_enc_flags(&ec_key, old_flags | EC_PKEY_NO_PARAMETERS); | 
| 183 |  | 
 | 
| 184 | 0 |     eplen = i2d_ECPrivateKey(&ec_key, &ep); | 
| 185 | 0 |     if (eplen <= 0) { | 
| 186 | 0 |         ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB); | 
| 187 | 0 |         goto err; | 
| 188 | 0 |     } | 
| 189 |  |  | 
| 190 | 0 |     if (!PKCS8_pkey_set0(p8, OBJ_nid2obj(NID_X9_62_id_ecPublicKey), 0, | 
| 191 | 0 |                          ptype, pval, ep, eplen)) { | 
| 192 | 0 |         ERR_raise(ERR_LIB_EC, ERR_R_ASN1_LIB); | 
| 193 | 0 |         OPENSSL_clear_free(ep, eplen); | 
| 194 | 0 |         goto err; | 
| 195 | 0 |     } | 
| 196 |  |  | 
| 197 | 0 |     return 1; | 
| 198 |  |  | 
| 199 | 0 |  err: | 
| 200 | 0 |     if (ptype == V_ASN1_SEQUENCE) | 
| 201 | 0 |         ASN1_STRING_free(pval); | 
| 202 | 0 |     return 0; | 
| 203 | 0 | } | 
| 204 |  |  | 
| 205 |  | static int int_ec_size(const EVP_PKEY *pkey) | 
| 206 | 963 | { | 
| 207 | 963 |     return ECDSA_size(pkey->pkey.ec); | 
| 208 | 963 | } | 
| 209 |  |  | 
| 210 |  | static int ec_bits(const EVP_PKEY *pkey) | 
| 211 | 6.89k | { | 
| 212 | 6.89k |     return EC_GROUP_order_bits(EC_KEY_get0_group(pkey->pkey.ec)); | 
| 213 | 6.89k | } | 
| 214 |  |  | 
| 215 |  | static int ec_security_bits(const EVP_PKEY *pkey) | 
| 216 | 6.89k | { | 
| 217 | 6.89k |     int ecbits = ec_bits(pkey); | 
| 218 |  |  | 
| 219 | 6.89k |     if (ecbits >= 512) | 
| 220 | 0 |         return 256; | 
| 221 | 6.89k |     if (ecbits >= 384) | 
| 222 | 0 |         return 192; | 
| 223 | 6.89k |     if (ecbits >= 256) | 
| 224 | 6.89k |         return 128; | 
| 225 | 0 |     if (ecbits >= 224) | 
| 226 | 0 |         return 112; | 
| 227 | 0 |     if (ecbits >= 160) | 
| 228 | 0 |         return 80; | 
| 229 | 0 |     return ecbits / 2; | 
| 230 | 0 | } | 
| 231 |  |  | 
| 232 |  | static int ec_missing_parameters(const EVP_PKEY *pkey) | 
| 233 | 25.3k | { | 
| 234 | 25.3k |     if (pkey->pkey.ec == NULL || EC_KEY_get0_group(pkey->pkey.ec) == NULL) | 
| 235 | 628 |         return 1; | 
| 236 | 24.7k |     return 0; | 
| 237 | 25.3k | } | 
| 238 |  |  | 
| 239 |  | static int ec_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from) | 
| 240 | 628 | { | 
| 241 | 628 |     EC_GROUP *group = EC_GROUP_dup(EC_KEY_get0_group(from->pkey.ec)); | 
| 242 |  |  | 
| 243 | 628 |     if (group == NULL) | 
| 244 | 0 |         return 0; | 
| 245 | 628 |     if (to->pkey.ec == NULL) { | 
| 246 | 385 |         to->pkey.ec = EC_KEY_new(); | 
| 247 | 385 |         if (to->pkey.ec == NULL) | 
| 248 | 0 |             goto err; | 
| 249 | 385 |     } | 
| 250 | 628 |     if (EC_KEY_set_group(to->pkey.ec, group) == 0) | 
| 251 | 0 |         goto err; | 
| 252 | 628 |     EC_GROUP_free(group); | 
| 253 | 628 |     return 1; | 
| 254 | 0 |  err: | 
| 255 | 0 |     EC_GROUP_free(group); | 
| 256 | 0 |     return 0; | 
| 257 | 628 | } | 
| 258 |  |  | 
| 259 |  | static int ec_cmp_parameters(const EVP_PKEY *a, const EVP_PKEY *b) | 
| 260 | 12.6k | { | 
| 261 | 12.6k |     const EC_GROUP *group_a = EC_KEY_get0_group(a->pkey.ec), | 
| 262 | 12.6k |         *group_b = EC_KEY_get0_group(b->pkey.ec); | 
| 263 |  |  | 
| 264 | 12.6k |     if (group_a == NULL || group_b == NULL) | 
| 265 | 0 |         return -2; | 
| 266 | 12.6k |     if (EC_GROUP_cmp(group_a, group_b, NULL)) | 
| 267 | 0 |         return 0; | 
| 268 | 12.6k |     else | 
| 269 | 12.6k |         return 1; | 
| 270 | 12.6k | } | 
| 271 |  |  | 
| 272 |  | static void int_ec_free(EVP_PKEY *pkey) | 
| 273 | 291k | { | 
| 274 | 291k |     EC_KEY_free(pkey->pkey.ec); | 
| 275 | 291k | } | 
| 276 |  |  | 
| 277 |  | typedef enum { | 
| 278 |  |     EC_KEY_PRINT_PRIVATE, | 
| 279 |  |     EC_KEY_PRINT_PUBLIC, | 
| 280 |  |     EC_KEY_PRINT_PARAM | 
| 281 |  | } ec_print_t; | 
| 282 |  |  | 
| 283 |  | static int do_EC_KEY_print(BIO *bp, const EC_KEY *x, int off, ec_print_t ktype) | 
| 284 | 1.96k | { | 
| 285 | 1.96k |     const char *ecstr; | 
| 286 | 1.96k |     unsigned char *priv = NULL, *pub = NULL; | 
| 287 | 1.96k |     size_t privlen = 0, publen = 0; | 
| 288 | 1.96k |     int ret = 0; | 
| 289 | 1.96k |     const EC_GROUP *group; | 
| 290 |  |  | 
| 291 | 1.96k |     if (x == NULL || (group = EC_KEY_get0_group(x)) == NULL) { | 
| 292 | 0 |         ERR_raise(ERR_LIB_EC, ERR_R_PASSED_NULL_PARAMETER); | 
| 293 | 0 |         return 0; | 
| 294 | 0 |     } | 
| 295 |  |  | 
| 296 | 1.96k |     if (ktype != EC_KEY_PRINT_PARAM && EC_KEY_get0_public_key(x) != NULL) { | 
| 297 | 1.75k |         publen = EC_KEY_key2buf(x, EC_KEY_get_conv_form(x), &pub, NULL); | 
| 298 | 1.75k |         if (publen == 0) | 
| 299 | 13 |             goto err; | 
| 300 | 1.75k |     } | 
| 301 |  |  | 
| 302 | 1.95k |     if (ktype == EC_KEY_PRINT_PRIVATE && EC_KEY_get0_private_key(x) != NULL) { | 
| 303 | 1.67k |         privlen = EC_KEY_priv2buf(x, &priv); | 
| 304 | 1.67k |         if (privlen == 0) | 
| 305 | 516 |             goto err; | 
| 306 | 1.67k |     } | 
| 307 |  |  | 
| 308 | 1.43k |     if (ktype == EC_KEY_PRINT_PRIVATE) | 
| 309 | 1.16k |         ecstr = "Private-Key"; | 
| 310 | 276 |     else if (ktype == EC_KEY_PRINT_PUBLIC) | 
| 311 | 61 |         ecstr = "Public-Key"; | 
| 312 | 215 |     else | 
| 313 | 215 |         ecstr = "ECDSA-Parameters"; | 
| 314 |  |  | 
| 315 | 1.43k |     if (!BIO_indent(bp, off, 128)) | 
| 316 | 0 |         goto err; | 
| 317 | 1.43k |     if (BIO_printf(bp, "%s: (%d bit)\n", ecstr, | 
| 318 | 1.43k |                    EC_GROUP_order_bits(group)) <= 0) | 
| 319 | 0 |         goto err; | 
| 320 |  |  | 
| 321 | 1.43k |     if (privlen != 0) { | 
| 322 | 1.16k |         if (BIO_printf(bp, "%*spriv:\n", off, "") <= 0) | 
| 323 | 0 |             goto err; | 
| 324 | 1.16k |         if (ASN1_buf_print(bp, priv, privlen, off + 4) == 0) | 
| 325 | 0 |             goto err; | 
| 326 | 1.16k |     } | 
| 327 |  |  | 
| 328 | 1.43k |     if (publen != 0) { | 
| 329 | 1.22k |         if (BIO_printf(bp, "%*spub:\n", off, "") <= 0) | 
| 330 | 0 |             goto err; | 
| 331 | 1.22k |         if (ASN1_buf_print(bp, pub, publen, off + 4) == 0) | 
| 332 | 0 |             goto err; | 
| 333 | 1.22k |     } | 
| 334 |  |  | 
| 335 | 1.43k |     if (!ECPKParameters_print(bp, group, off)) | 
| 336 | 0 |         goto err; | 
| 337 | 1.43k |     ret = 1; | 
| 338 | 1.96k |  err: | 
| 339 | 1.96k |     if (!ret) | 
| 340 | 1.96k |         ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB); | 
| 341 | 1.96k |     OPENSSL_clear_free(priv, privlen); | 
| 342 | 1.96k |     OPENSSL_free(pub); | 
| 343 | 1.96k |     return ret; | 
| 344 | 1.43k | } | 
| 345 |  |  | 
| 346 |  | static int eckey_param_decode(EVP_PKEY *pkey, | 
| 347 |  |                               const unsigned char **pder, int derlen) | 
| 348 | 0 | { | 
| 349 | 0 |     EC_KEY *eckey; | 
| 350 |  | 
 | 
| 351 | 0 |     if ((eckey = d2i_ECParameters(NULL, pder, derlen)) == NULL) | 
| 352 | 0 |         return 0; | 
| 353 | 0 |     EVP_PKEY_assign_EC_KEY(pkey, eckey); | 
| 354 | 0 |     return 1; | 
| 355 | 0 | } | 
| 356 |  |  | 
| 357 |  | static int eckey_param_encode(const EVP_PKEY *pkey, unsigned char **pder) | 
| 358 | 0 | { | 
| 359 | 0 |     return i2d_ECParameters(pkey->pkey.ec, pder); | 
| 360 | 0 | } | 
| 361 |  |  | 
| 362 |  | static int eckey_param_print(BIO *bp, const EVP_PKEY *pkey, int indent, | 
| 363 |  |                              ASN1_PCTX *ctx) | 
| 364 | 0 | { | 
| 365 | 0 |     return do_EC_KEY_print(bp, pkey->pkey.ec, indent, EC_KEY_PRINT_PARAM); | 
| 366 | 0 | } | 
| 367 |  |  | 
| 368 |  | static int eckey_pub_print(BIO *bp, const EVP_PKEY *pkey, int indent, | 
| 369 |  |                            ASN1_PCTX *ctx) | 
| 370 | 67 | { | 
| 371 | 67 |     return do_EC_KEY_print(bp, pkey->pkey.ec, indent, EC_KEY_PRINT_PUBLIC); | 
| 372 | 67 | } | 
| 373 |  |  | 
| 374 |  | static int eckey_priv_print(BIO *bp, const EVP_PKEY *pkey, int indent, | 
| 375 |  |                             ASN1_PCTX *ctx) | 
| 376 | 58 | { | 
| 377 | 58 |     return do_EC_KEY_print(bp, pkey->pkey.ec, indent, EC_KEY_PRINT_PRIVATE); | 
| 378 | 58 | } | 
| 379 |  |  | 
| 380 |  | static int old_ec_priv_decode(EVP_PKEY *pkey, | 
| 381 |  |                               const unsigned char **pder, int derlen) | 
| 382 | 7.27k | { | 
| 383 | 7.27k |     EC_KEY *ec; | 
| 384 |  |  | 
| 385 | 7.27k |     if ((ec = d2i_ECPrivateKey(NULL, pder, derlen)) == NULL) | 
| 386 | 1.10k |         return 0; | 
| 387 | 6.16k |     EVP_PKEY_assign_EC_KEY(pkey, ec); | 
| 388 | 6.16k |     return 1; | 
| 389 | 7.27k | } | 
| 390 |  |  | 
| 391 |  | static int old_ec_priv_encode(const EVP_PKEY *pkey, unsigned char **pder) | 
| 392 | 58 | { | 
| 393 | 58 |     return i2d_ECPrivateKey(pkey->pkey.ec, pder); | 
| 394 | 58 | } | 
| 395 |  |  | 
| 396 |  | static int ec_pkey_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2) | 
| 397 |  | { | 
| 398 |  |     switch (op) { | 
| 399 |  |     case ASN1_PKEY_CTRL_DEFAULT_MD_NID: | 
| 400 |  |         if (EVP_PKEY_get_id(pkey) == EVP_PKEY_SM2) { | 
| 401 |  |             /* For SM2, the only valid digest-alg is SM3 */ | 
| 402 |  |             *(int *)arg2 = NID_sm3; | 
| 403 |  |             return 2;            /* Make it mandatory */ | 
| 404 |  |         } | 
| 405 |  |         *(int *)arg2 = NID_sha256; | 
| 406 |  |         return 1; | 
| 407 |  |  | 
| 408 |  |     case ASN1_PKEY_CTRL_SET1_TLS_ENCPT: | 
| 409 |  |         /* We should only be here if we have a legacy key */ | 
| 410 |  |         if (!ossl_assert(evp_pkey_is_legacy(pkey))) | 
| 411 |  |             return 0; | 
| 412 |  |         return EC_KEY_oct2key(evp_pkey_get0_EC_KEY_int(pkey), arg2, arg1, NULL); | 
| 413 |  |  | 
| 414 |  |     case ASN1_PKEY_CTRL_GET1_TLS_ENCPT: | 
| 415 |  |         return EC_KEY_key2buf(EVP_PKEY_get0_EC_KEY(pkey), | 
| 416 |  |                               POINT_CONVERSION_UNCOMPRESSED, arg2, NULL); | 
| 417 |  |  | 
| 418 |  |     default: | 
| 419 |  |         return -2; | 
| 420 |  |     } | 
| 421 |  | } | 
| 422 |  |  | 
| 423 |  | static int ec_pkey_check(const EVP_PKEY *pkey) | 
| 424 | 0 | { | 
| 425 | 0 |     EC_KEY *eckey = pkey->pkey.ec; | 
| 426 |  |  | 
| 427 |  |     /* stay consistent to what EVP_PKEY_check demands */ | 
| 428 | 0 |     if (eckey->priv_key == NULL) { | 
| 429 | 0 |         ERR_raise(ERR_LIB_EC, EC_R_MISSING_PRIVATE_KEY); | 
| 430 | 0 |         return 0; | 
| 431 | 0 |     } | 
| 432 |  |  | 
| 433 | 0 |     return EC_KEY_check_key(eckey); | 
| 434 | 0 | } | 
| 435 |  |  | 
| 436 |  | static int ec_pkey_public_check(const EVP_PKEY *pkey) | 
| 437 | 0 | { | 
| 438 | 0 |     EC_KEY *eckey = pkey->pkey.ec; | 
| 439 |  |  | 
| 440 |  |     /* | 
| 441 |  |      * Note: it unnecessary to check eckey->pub_key here since | 
| 442 |  |      * it will be checked in EC_KEY_check_key(). In fact, the | 
| 443 |  |      * EC_KEY_check_key() mainly checks the public key, and checks | 
| 444 |  |      * the private key optionally (only if there is one). So if | 
| 445 |  |      * someone passes a whole EC key (public + private), this | 
| 446 |  |      * will also work... | 
| 447 |  |      */ | 
| 448 |  | 
 | 
| 449 | 0 |     return EC_KEY_check_key(eckey); | 
| 450 | 0 | } | 
| 451 |  |  | 
| 452 |  | static int ec_pkey_param_check(const EVP_PKEY *pkey) | 
| 453 | 0 | { | 
| 454 | 0 |     EC_KEY *eckey = pkey->pkey.ec; | 
| 455 |  |  | 
| 456 |  |     /* stay consistent to what EVP_PKEY_check demands */ | 
| 457 | 0 |     if (eckey->group == NULL) { | 
| 458 | 0 |         ERR_raise(ERR_LIB_EC, EC_R_MISSING_PARAMETERS); | 
| 459 | 0 |         return 0; | 
| 460 | 0 |     } | 
| 461 |  |  | 
| 462 | 0 |     return EC_GROUP_check(eckey->group, NULL); | 
| 463 | 0 | } | 
| 464 |  |  | 
| 465 |  | static | 
| 466 |  | size_t ec_pkey_dirty_cnt(const EVP_PKEY *pkey) | 
| 467 | 54.9k | { | 
| 468 | 54.9k |     return pkey->pkey.ec->dirty_cnt; | 
| 469 | 54.9k | } | 
| 470 |  |  | 
| 471 |  | static | 
| 472 |  | int ec_pkey_export_to(const EVP_PKEY *from, void *to_keydata, | 
| 473 |  |                       OSSL_FUNC_keymgmt_import_fn *importer, | 
| 474 |  |                       OSSL_LIB_CTX *libctx, const char *propq) | 
| 475 | 10.1k | { | 
| 476 | 10.1k |     const EC_KEY *eckey = NULL; | 
| 477 | 10.1k |     const EC_GROUP *ecg = NULL; | 
| 478 | 10.1k |     unsigned char *pub_key_buf = NULL, *gen_buf = NULL; | 
| 479 | 10.1k |     size_t pub_key_buflen; | 
| 480 | 10.1k |     OSSL_PARAM_BLD *tmpl; | 
| 481 | 10.1k |     OSSL_PARAM *params = NULL; | 
| 482 | 10.1k |     const BIGNUM *priv_key = NULL; | 
| 483 | 10.1k |     const EC_POINT *pub_point = NULL; | 
| 484 | 10.1k |     int selection = 0; | 
| 485 | 10.1k |     int rv = 0; | 
| 486 | 10.1k |     BN_CTX *bnctx = NULL; | 
| 487 |  |  | 
| 488 | 10.1k |     if (from == NULL | 
| 489 | 10.1k |             || (eckey = from->pkey.ec) == NULL | 
| 490 | 10.1k |             || (ecg = EC_KEY_get0_group(eckey)) == NULL) | 
| 491 | 0 |         return 0; | 
| 492 |  |  | 
| 493 | 10.1k |     tmpl = OSSL_PARAM_BLD_new(); | 
| 494 | 10.1k |     if (tmpl == NULL) | 
| 495 | 0 |         return 0; | 
| 496 |  |  | 
| 497 |  |     /* | 
| 498 |  |      * EC_POINT_point2buf() can generate random numbers in some | 
| 499 |  |      * implementations so we need to ensure we use the correct libctx. | 
| 500 |  |      */ | 
| 501 | 10.1k |     bnctx = BN_CTX_new_ex(libctx); | 
| 502 | 10.1k |     if (bnctx == NULL) | 
| 503 | 0 |         goto err; | 
| 504 | 10.1k |     BN_CTX_start(bnctx); | 
| 505 |  |  | 
| 506 |  |     /* export the domain parameters */ | 
| 507 | 10.1k |     if (!ossl_ec_group_todata(ecg, tmpl, NULL, libctx, propq, bnctx, &gen_buf)) | 
| 508 | 0 |         goto err; | 
| 509 | 10.1k |     selection |= OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS; | 
| 510 |  |  | 
| 511 | 10.1k |     priv_key = EC_KEY_get0_private_key(eckey); | 
| 512 | 10.1k |     pub_point = EC_KEY_get0_public_key(eckey); | 
| 513 |  |  | 
| 514 | 10.1k |     if (pub_point != NULL) { | 
| 515 |  |         /* convert pub_point to a octet string according to the SECG standard */ | 
| 516 | 10.1k |         point_conversion_form_t format = EC_KEY_get_conv_form(eckey); | 
| 517 |  |  | 
| 518 | 10.1k |         if ((pub_key_buflen = EC_POINT_point2buf(ecg, pub_point, | 
| 519 | 10.1k |                                                  format, | 
| 520 | 10.1k |                                                  &pub_key_buf, bnctx)) == 0 | 
| 521 | 10.1k |             || !OSSL_PARAM_BLD_push_octet_string(tmpl, | 
| 522 | 10.1k |                                                  OSSL_PKEY_PARAM_PUB_KEY, | 
| 523 | 10.1k |                                                  pub_key_buf, | 
| 524 | 10.1k |                                                  pub_key_buflen)) | 
| 525 | 0 |             goto err; | 
| 526 | 10.1k |         selection |= OSSL_KEYMGMT_SELECT_PUBLIC_KEY; | 
| 527 | 10.1k |     } | 
| 528 |  |  | 
| 529 | 10.1k |     if (priv_key != NULL) { | 
| 530 | 10.1k |         size_t sz; | 
| 531 | 10.1k |         int ecbits; | 
| 532 | 10.1k |         int ecdh_cofactor_mode; | 
| 533 |  |  | 
| 534 |  |         /* | 
| 535 |  |          * Key import/export should never leak the bit length of the secret | 
| 536 |  |          * scalar in the key. | 
| 537 |  |          * | 
| 538 |  |          * For this reason, on export we use padded BIGNUMs with fixed length. | 
| 539 |  |          * | 
| 540 |  |          * When importing we also should make sure that, even if short lived, | 
| 541 |  |          * the newly created BIGNUM is marked with the BN_FLG_CONSTTIME flag as | 
| 542 |  |          * soon as possible, so that any processing of this BIGNUM might opt for | 
| 543 |  |          * constant time implementations in the backend. | 
| 544 |  |          * | 
| 545 |  |          * Setting the BN_FLG_CONSTTIME flag alone is never enough, we also have | 
| 546 |  |          * to preallocate the BIGNUM internal buffer to a fixed public size big | 
| 547 |  |          * enough that operations performed during the processing never trigger | 
| 548 |  |          * a realloc which would leak the size of the scalar through memory | 
| 549 |  |          * accesses. | 
| 550 |  |          * | 
| 551 |  |          * Fixed Length | 
| 552 |  |          * ------------ | 
| 553 |  |          * | 
| 554 |  |          * The order of the large prime subgroup of the curve is our choice for | 
| 555 |  |          * a fixed public size, as that is generally the upper bound for | 
| 556 |  |          * generating a private key in EC cryptosystems and should fit all valid | 
| 557 |  |          * secret scalars. | 
| 558 |  |          * | 
| 559 |  |          * For padding on export we just use the bit length of the order | 
| 560 |  |          * converted to bytes (rounding up). | 
| 561 |  |          * | 
| 562 |  |          * For preallocating the BIGNUM storage we look at the number of "words" | 
| 563 |  |          * required for the internal representation of the order, and we | 
| 564 |  |          * preallocate 2 extra "words" in case any of the subsequent processing | 
| 565 |  |          * might temporarily overflow the order length. | 
| 566 |  |          */ | 
| 567 | 10.1k |         ecbits = EC_GROUP_order_bits(ecg); | 
| 568 | 10.1k |         if (ecbits <= 0) | 
| 569 | 0 |             goto err; | 
| 570 |  |  | 
| 571 | 10.1k |         sz = (ecbits + 7 ) / 8; | 
| 572 | 10.1k |         if (!OSSL_PARAM_BLD_push_BN_pad(tmpl, | 
| 573 | 10.1k |                                         OSSL_PKEY_PARAM_PRIV_KEY, | 
| 574 | 10.1k |                                         priv_key, sz)) | 
| 575 | 0 |             goto err; | 
| 576 | 10.1k |         selection |= OSSL_KEYMGMT_SELECT_PRIVATE_KEY; | 
| 577 |  |  | 
| 578 |  |         /* | 
| 579 |  |          * The ECDH Cofactor Mode is defined only if the EC_KEY actually | 
| 580 |  |          * contains a private key, so we check for the flag and export it only | 
| 581 |  |          * in this case. | 
| 582 |  |          */ | 
| 583 | 10.1k |         ecdh_cofactor_mode = | 
| 584 | 10.1k |             (EC_KEY_get_flags(eckey) & EC_FLAG_COFACTOR_ECDH) ? 1 : 0; | 
| 585 |  |  | 
| 586 |  |         /* Export the ECDH_COFACTOR_MODE parameter */ | 
| 587 | 10.1k |         if (!OSSL_PARAM_BLD_push_int(tmpl, | 
| 588 | 10.1k |                                      OSSL_PKEY_PARAM_USE_COFACTOR_ECDH, | 
| 589 | 10.1k |                                      ecdh_cofactor_mode)) | 
| 590 | 0 |             goto err; | 
| 591 | 10.1k |         selection |= OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS; | 
| 592 | 10.1k |     } | 
| 593 |  |  | 
| 594 | 10.1k |     params = OSSL_PARAM_BLD_to_param(tmpl); | 
| 595 |  |  | 
| 596 |  |     /* We export, the provider imports */ | 
| 597 | 10.1k |     rv = importer(to_keydata, selection, params); | 
| 598 |  |  | 
| 599 | 10.1k |  err: | 
| 600 | 10.1k |     OSSL_PARAM_BLD_free(tmpl); | 
| 601 | 10.1k |     OSSL_PARAM_free(params); | 
| 602 | 10.1k |     OPENSSL_free(pub_key_buf); | 
| 603 | 10.1k |     OPENSSL_free(gen_buf); | 
| 604 | 10.1k |     BN_CTX_end(bnctx); | 
| 605 | 10.1k |     BN_CTX_free(bnctx); | 
| 606 | 10.1k |     return rv; | 
| 607 | 10.1k | } | 
| 608 |  |  | 
| 609 |  | static int ec_pkey_import_from(const OSSL_PARAM params[], void *vpctx) | 
| 610 | 10.1k | { | 
| 611 | 10.1k |     EVP_PKEY_CTX *pctx = vpctx; | 
| 612 | 10.1k |     EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(pctx); | 
| 613 | 10.1k |     EC_KEY *ec = EC_KEY_new_ex(pctx->libctx, pctx->propquery); | 
| 614 |  |  | 
| 615 | 10.1k |     if (ec == NULL) { | 
| 616 | 0 |         ERR_raise(ERR_LIB_DH, ERR_R_MALLOC_FAILURE); | 
| 617 | 0 |         return 0; | 
| 618 | 0 |     } | 
| 619 |  |  | 
| 620 | 10.1k |     if (!ossl_ec_group_fromdata(ec, params) | 
| 621 | 10.1k |         || !ossl_ec_key_otherparams_fromdata(ec, params) | 
| 622 | 10.1k |         || !ossl_ec_key_fromdata(ec, params, 1) | 
| 623 | 10.1k |         || !EVP_PKEY_assign_EC_KEY(pkey, ec)) { | 
| 624 | 0 |         EC_KEY_free(ec); | 
| 625 | 0 |         return 0; | 
| 626 | 0 |     } | 
| 627 | 10.1k |     return 1; | 
| 628 | 10.1k | } | 
| 629 |  |  | 
| 630 |  | static int ec_pkey_copy(EVP_PKEY *to, EVP_PKEY *from) | 
| 631 | 0 | { | 
| 632 | 0 |     EC_KEY *eckey = from->pkey.ec; | 
| 633 | 0 |     EC_KEY *dupkey = NULL; | 
| 634 | 0 |     int ret; | 
| 635 |  | 
 | 
| 636 | 0 |     if (eckey != NULL) { | 
| 637 | 0 |         dupkey = EC_KEY_dup(eckey); | 
| 638 | 0 |         if (dupkey == NULL) | 
| 639 | 0 |             return 0; | 
| 640 | 0 |     } else { | 
| 641 |  |         /* necessary to properly copy empty SM2 keys */ | 
| 642 | 0 |         return EVP_PKEY_set_type(to, from->type); | 
| 643 | 0 |     } | 
| 644 |  |  | 
| 645 | 0 |     ret = EVP_PKEY_assign_EC_KEY(to, dupkey); | 
| 646 | 0 |     if (!ret) | 
| 647 | 0 |         EC_KEY_free(dupkey); | 
| 648 | 0 |     return ret; | 
| 649 | 0 | } | 
| 650 |  |  | 
| 651 |  | const EVP_PKEY_ASN1_METHOD ossl_eckey_asn1_meth = { | 
| 652 |  |     EVP_PKEY_EC, | 
| 653 |  |     EVP_PKEY_EC, | 
| 654 |  |     0, | 
| 655 |  |     "EC", | 
| 656 |  |     "OpenSSL EC algorithm", | 
| 657 |  |  | 
| 658 |  |     eckey_pub_decode, | 
| 659 |  |     eckey_pub_encode, | 
| 660 |  |     eckey_pub_cmp, | 
| 661 |  |     eckey_pub_print, | 
| 662 |  |  | 
| 663 |  |     NULL, | 
| 664 |  |     eckey_priv_encode, | 
| 665 |  |     eckey_priv_print, | 
| 666 |  |  | 
| 667 |  |     int_ec_size, | 
| 668 |  |     ec_bits, | 
| 669 |  |     ec_security_bits, | 
| 670 |  |  | 
| 671 |  |     eckey_param_decode, | 
| 672 |  |     eckey_param_encode, | 
| 673 |  |     ec_missing_parameters, | 
| 674 |  |     ec_copy_parameters, | 
| 675 |  |     ec_cmp_parameters, | 
| 676 |  |     eckey_param_print, | 
| 677 |  |     0, | 
| 678 |  |  | 
| 679 |  |     int_ec_free, | 
| 680 |  |     ec_pkey_ctrl, | 
| 681 |  |     old_ec_priv_decode, | 
| 682 |  |     old_ec_priv_encode, | 
| 683 |  |  | 
| 684 |  |     0, 0, 0, | 
| 685 |  |  | 
| 686 |  |     ec_pkey_check, | 
| 687 |  |     ec_pkey_public_check, | 
| 688 |  |     ec_pkey_param_check, | 
| 689 |  |  | 
| 690 |  |     0, /* set_priv_key */ | 
| 691 |  |     0, /* set_pub_key */ | 
| 692 |  |     0, /* get_priv_key */ | 
| 693 |  |     0, /* get_pub_key */ | 
| 694 |  |  | 
| 695 |  |     ec_pkey_dirty_cnt, | 
| 696 |  |     ec_pkey_export_to, | 
| 697 |  |     ec_pkey_import_from, | 
| 698 |  |     ec_pkey_copy, | 
| 699 |  |     eckey_priv_decode_ex | 
| 700 |  | }; | 
| 701 |  |  | 
| 702 |  | #if !defined(OPENSSL_NO_SM2) | 
| 703 |  | const EVP_PKEY_ASN1_METHOD ossl_sm2_asn1_meth = { | 
| 704 |  |    EVP_PKEY_SM2, | 
| 705 |  |    EVP_PKEY_EC, | 
| 706 |  |    ASN1_PKEY_ALIAS | 
| 707 |  | }; | 
| 708 |  | #endif | 
| 709 |  |  | 
| 710 |  | int EC_KEY_print(BIO *bp, const EC_KEY *x, int off) | 
| 711 | 1.62k | { | 
| 712 | 1.62k |     int private = EC_KEY_get0_private_key(x) != NULL; | 
| 713 |  |  | 
| 714 | 1.62k |     return do_EC_KEY_print(bp, x, off, | 
| 715 | 1.62k |                 private ? EC_KEY_PRINT_PRIVATE : EC_KEY_PRINT_PUBLIC); | 
| 716 | 1.62k | } | 
| 717 |  |  | 
| 718 |  | int ECParameters_print(BIO *bp, const EC_KEY *x) | 
| 719 | 215 | { | 
| 720 | 215 |     return do_EC_KEY_print(bp, x, 4, EC_KEY_PRINT_PARAM); | 
| 721 | 215 | } |