X-Git-Url: https://git.openssl.org/?p=openssl.git;a=blobdiff_plain;f=crypto%2Fec%2Fec_ameth.c;h=2beeb82707bbb5f4da8c52f33574b84095665841;hp=684da95ab208f50119e279c451fa8ccaacad5225;hb=a941920514995b520e7666897347fdcdcb5bf358;hpb=aa6bb1352b1026b20a23b49da4efdcf171926eb0 diff --git a/crypto/ec/ec_ameth.c b/crypto/ec/ec_ameth.c index 684da95ab2..2beeb82707 100644 --- a/crypto/ec/ec_ameth.c +++ b/crypto/ec/ec_ameth.c @@ -1,7 +1,7 @@ /* - * Copyright 2006-2016 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2006-2018 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy * in the file LICENSE in the source distribution or at * https://www.openssl.org/source/license.html @@ -16,6 +16,7 @@ #include #include "internal/asn1_int.h" #include "internal/evp_int.h" +#include "ec_lcl.h" #ifndef OPENSSL_NO_CMS static int ecdh_cms_decrypt(CMS_RecipientInfo *ri); @@ -88,22 +89,22 @@ static int eckey_pub_encode(X509_PUBKEY *pk, const EVP_PKEY *pkey) return 0; } -static EC_KEY *eckey_type2param(int ptype, void *pval) +static EC_KEY *eckey_type2param(int ptype, const void *pval) { EC_KEY *eckey = NULL; + EC_GROUP *group = NULL; + if (ptype == V_ASN1_SEQUENCE) { - ASN1_STRING *pstr = pval; - const unsigned char *pm = NULL; - int pmlen; - pm = pstr->data; - pmlen = pstr->length; + const ASN1_STRING *pstr = pval; + const unsigned char *pm = pstr->data; + int pmlen = pstr->length; + if ((eckey = d2i_ECParameters(NULL, &pm, pmlen)) == NULL) { ECerr(EC_F_ECKEY_TYPE2PARAM, EC_R_DECODE_ERROR); goto ecerr; } } else if (ptype == V_ASN1_OBJECT) { - ASN1_OBJECT *poid = pval; - EC_GROUP *group; + const ASN1_OBJECT *poid = pval; /* * type == V_ASN1_OBJECT => the parameters are given by an asn1 OID @@ -128,13 +129,14 @@ static EC_KEY *eckey_type2param(int ptype, void *pval) ecerr: EC_KEY_free(eckey); + EC_GROUP_free(group); return NULL; } static int eckey_pub_decode(EVP_PKEY *pkey, X509_PUBKEY *pubkey) { const unsigned char *p = NULL; - void *pval; + const void *pval; int ptype, pklen; EC_KEY *eckey = NULL; X509_ALGOR *palg; @@ -170,6 +172,8 @@ static int eckey_pub_cmp(const EVP_PKEY *a, const EVP_PKEY *b) const EC_GROUP *group = EC_KEY_get0_group(b->pkey.ec); const EC_POINT *pa = EC_KEY_get0_public_key(a->pkey.ec), *pb = EC_KEY_get0_public_key(b->pkey.ec); + if (group == NULL || pa == NULL || pb == NULL) + return -2; r = EC_POINT_cmp(group, pa, pb, NULL); if (r == 0) return 1; @@ -178,13 +182,13 @@ static int eckey_pub_cmp(const EVP_PKEY *a, const EVP_PKEY *b) return -2; } -static int eckey_priv_decode(EVP_PKEY *pkey, PKCS8_PRIV_KEY_INFO *p8) +static int eckey_priv_decode(EVP_PKEY *pkey, const PKCS8_PRIV_KEY_INFO *p8) { const unsigned char *p = NULL; - void *pval; + const void *pval; int ptype, pklen; EC_KEY *eckey = NULL; - X509_ALGOR *palg; + const X509_ALGOR *palg; if (!PKCS8_pkey_get0(NULL, &p, &pklen, &palg, p8)) return 0; @@ -213,15 +217,13 @@ static int eckey_priv_decode(EVP_PKEY *pkey, PKCS8_PRIV_KEY_INFO *p8) static int eckey_priv_encode(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pkey) { - EC_KEY *ec_key; + EC_KEY ec_key = *(pkey->pkey.ec); unsigned char *ep, *p; int eplen, ptype; void *pval; - unsigned int tmp_flags, old_flags; - - ec_key = pkey->pkey.ec; + unsigned int old_flags; - if (!eckey_param2type(&ptype, &pval, ec_key)) { + if (!eckey_param2type(&ptype, &pval, &ec_key)) { ECerr(EC_F_ECKEY_PRIV_ENCODE, EC_R_DECODE_ERROR); return 0; } @@ -232,34 +234,31 @@ static int eckey_priv_encode(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pkey) * do not include the parameters in the SEC1 private key see PKCS#11 * 12.11 */ - old_flags = EC_KEY_get_enc_flags(ec_key); - tmp_flags = old_flags | EC_PKEY_NO_PARAMETERS; - EC_KEY_set_enc_flags(ec_key, tmp_flags); - eplen = i2d_ECPrivateKey(ec_key, NULL); + old_flags = EC_KEY_get_enc_flags(&ec_key); + EC_KEY_set_enc_flags(&ec_key, old_flags | EC_PKEY_NO_PARAMETERS); + + eplen = i2d_ECPrivateKey(&ec_key, NULL); if (!eplen) { - EC_KEY_set_enc_flags(ec_key, old_flags); ECerr(EC_F_ECKEY_PRIV_ENCODE, ERR_R_EC_LIB); return 0; } ep = OPENSSL_malloc(eplen); if (ep == NULL) { - EC_KEY_set_enc_flags(ec_key, old_flags); ECerr(EC_F_ECKEY_PRIV_ENCODE, ERR_R_MALLOC_FAILURE); return 0; } p = ep; - if (!i2d_ECPrivateKey(ec_key, &p)) { - EC_KEY_set_enc_flags(ec_key, old_flags); + if (!i2d_ECPrivateKey(&ec_key, &p)) { OPENSSL_free(ep); ECerr(EC_F_ECKEY_PRIV_ENCODE, ERR_R_EC_LIB); return 0; } - /* restore old encoding flags */ - EC_KEY_set_enc_flags(ec_key, old_flags); if (!PKCS8_pkey_set0(p8, OBJ_nid2obj(NID_X9_62_id_ecPublicKey), 0, - ptype, pval, ep, eplen)) + ptype, pval, ep, eplen)) { + OPENSSL_free(ep); return 0; + } return 1; } @@ -292,7 +291,7 @@ static int ec_security_bits(const EVP_PKEY *pkey) static int ec_missing_parameters(const EVP_PKEY *pkey) { - if (EC_KEY_get0_group(pkey->pkey.ec) == NULL) + if (pkey->pkey.ec == NULL || EC_KEY_get0_group(pkey->pkey.ec) == NULL) return 1; return 0; } @@ -300,23 +299,29 @@ static int ec_missing_parameters(const EVP_PKEY *pkey) static int ec_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from) { EC_GROUP *group = EC_GROUP_dup(EC_KEY_get0_group(from->pkey.ec)); + if (group == NULL) return 0; if (to->pkey.ec == NULL) { to->pkey.ec = EC_KEY_new(); if (to->pkey.ec == NULL) - return 0; + goto err; } if (EC_KEY_set_group(to->pkey.ec, group) == 0) - return 0; + goto err; EC_GROUP_free(group); return 1; + err: + EC_GROUP_free(group); + return 0; } static int ec_cmp_parameters(const EVP_PKEY *a, const EVP_PKEY *b) { const EC_GROUP *group_a = EC_KEY_get0_group(a->pkey.ec), *group_b = EC_KEY_get0_group(b->pkey.ec); + if (group_a == NULL || group_b == NULL) + return -2; if (EC_GROUP_cmp(group_a, group_b, NULL)) return 0; else @@ -347,7 +352,7 @@ static int do_EC_KEY_print(BIO *bp, const EC_KEY *x, int off, ec_print_t ktype) return 0; } - if (ktype != EC_KEY_PRINT_PARAM) { + if (ktype != EC_KEY_PRINT_PARAM && EC_KEY_get0_public_key(x) != NULL) { publen = EC_KEY_key2buf(x, EC_KEY_get_conv_form(x), &pub, NULL); if (publen == 0) goto err; @@ -499,8 +504,20 @@ static int ec_pkey_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2) #endif case ASN1_PKEY_CTRL_DEFAULT_MD_NID: - *(int *)arg2 = NID_sha256; - return 2; + if (EVP_PKEY_id(pkey) == EVP_PKEY_SM2) { + /* For SM2, the only valid digest-alg is SM3 */ + *(int *)arg2 = NID_sm3; + } else { + *(int *)arg2 = NID_sha256; + } + return 1; + + case ASN1_PKEY_CTRL_SET1_TLS_ENCPT: + return EC_KEY_oct2key(EVP_PKEY_get0_EC_KEY(pkey), arg2, arg1, NULL); + + case ASN1_PKEY_CTRL_GET1_TLS_ENCPT: + return EC_KEY_key2buf(EVP_PKEY_get0_EC_KEY(pkey), + POINT_CONVERSION_UNCOMPRESSED, arg2, NULL); default: return -2; @@ -509,6 +526,48 @@ static int ec_pkey_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2) } +static int ec_pkey_check(const EVP_PKEY *pkey) +{ + EC_KEY *eckey = pkey->pkey.ec; + + /* stay consistent to what EVP_PKEY_check demands */ + if (eckey->priv_key == NULL) { + ECerr(EC_F_EC_PKEY_CHECK, EC_R_MISSING_PRIVATE_KEY); + return 0; + } + + return EC_KEY_check_key(eckey); +} + +static int ec_pkey_public_check(const EVP_PKEY *pkey) +{ + EC_KEY *eckey = pkey->pkey.ec; + + /* + * Note: it unnecessary to check eckey->pub_key here since + * it will be checked in EC_KEY_check_key(). In fact, the + * EC_KEY_check_key() mainly checks the public key, and checks + * the private key optionally (only if there is one). So if + * someone passes a whole EC key (public + private), this + * will also work... + */ + + return EC_KEY_check_key(eckey); +} + +static int ec_pkey_param_check(const EVP_PKEY *pkey) +{ + EC_KEY *eckey = pkey->pkey.ec; + + /* stay consistent to what EVP_PKEY_check demands */ + if (eckey->group == NULL) { + ECerr(EC_F_EC_PKEY_PARAM_CHECK, EC_R_MISSING_PARAMETERS); + return 0; + } + + return EC_GROUP_check(eckey->group, NULL); +} + const EVP_PKEY_ASN1_METHOD eckey_asn1_meth = { EVP_PKEY_EC, EVP_PKEY_EC, @@ -540,17 +599,44 @@ const EVP_PKEY_ASN1_METHOD eckey_asn1_meth = { int_ec_free, ec_pkey_ctrl, old_ec_priv_decode, - old_ec_priv_encode + old_ec_priv_encode, + + 0, 0, 0, + + ec_pkey_check, + ec_pkey_public_check, + ec_pkey_param_check }; +#if !defined(OPENSSL_NO_SM2) +const EVP_PKEY_ASN1_METHOD sm2_asn1_meth = { + EVP_PKEY_SM2, + EVP_PKEY_EC, + ASN1_PKEY_ALIAS +}; +#endif + +int EC_KEY_print(BIO *bp, const EC_KEY *x, int off) +{ + int private = EC_KEY_get0_private_key(x) != NULL; + + return do_EC_KEY_print(bp, x, off, + private ? EC_KEY_PRINT_PRIVATE : EC_KEY_PRINT_PUBLIC); +} + +int ECParameters_print(BIO *bp, const EC_KEY *x) +{ + return do_EC_KEY_print(bp, x, 4, EC_KEY_PRINT_PARAM); +} + #ifndef OPENSSL_NO_CMS static int ecdh_cms_set_peerkey(EVP_PKEY_CTX *pctx, X509_ALGOR *alg, ASN1_BIT_STRING *pubkey) { - ASN1_OBJECT *aoid; + const ASN1_OBJECT *aoid; int atype; - void *aval; + const void *aval; int rv = 0; EVP_PKEY *pkpeer = NULL; EC_KEY *ecpeer = NULL; @@ -579,7 +665,7 @@ static int ecdh_cms_set_peerkey(EVP_PKEY_CTX *pctx, } /* We have parameters now set public key */ plen = ASN1_STRING_length(pubkey); - p = ASN1_STRING_data(pubkey); + p = ASN1_STRING_get0_data(pubkey); if (!p || !plen) goto err; if (!o2i_ECPublicKey(&ecpeer, &p, plen)) @@ -618,7 +704,7 @@ static int ecdh_cms_set_kdf_param(EVP_PKEY_CTX *pctx, int eckdf_nid) if (EVP_PKEY_CTX_set_ecdh_cofactor_mode(pctx, cofactor) <= 0) return 0; - if (EVP_PKEY_CTX_set_ecdh_kdf_type(pctx, EVP_PKEY_ECDH_KDF_X9_62) <= 0) + if (EVP_PKEY_CTX_set_ecdh_kdf_type(pctx, EVP_PKEY_ECDH_KDF_X9_63) <= 0) return 0; kdf_md = EVP_get_digestbynid(kdfmd_nid); @@ -724,7 +810,7 @@ static int ecdh_cms_encrypt(CMS_RecipientInfo *ri) EVP_CIPHER_CTX *ctx; int keylen; X509_ALGOR *talg, *wrap_alg = NULL; - ASN1_OBJECT *aoid; + const ASN1_OBJECT *aoid; ASN1_BIT_STRING *pubkey; ASN1_STRING *wrap_str; ASN1_OCTET_STRING *ukm; @@ -783,7 +869,7 @@ static int ecdh_cms_encrypt(CMS_RecipientInfo *ri) ecdh_nid = NID_dh_cofactor_kdf; if (kdf_type == EVP_PKEY_ECDH_KDF_NONE) { - kdf_type = EVP_PKEY_ECDH_KDF_X9_62; + kdf_type = EVP_PKEY_ECDH_KDF_X9_63; if (EVP_PKEY_CTX_set_ecdh_kdf_type(pctx, kdf_type) <= 0) goto err; } else