[openssl-commits] [openssl] master update

Richard Levitte levitte at openssl.org
Mon Nov 20 06:21:27 UTC 2017


The branch master has been updated
       via  b0004708730f300a2e5c6a11c887caab50b6c42a (commit)
      from  5d99881e6a58a8775b8ca866b794f615a16bb033 (commit)


- Log -----------------------------------------------------------------
commit b0004708730f300a2e5c6a11c887caab50b6c42a
Author: Paul Yang <yang.yang at baishancloud.com>
Date:   Wed Nov 1 00:45:24 2017 +0800

    Support public key and param check in EVP interface
    
    EVP_PKEY_public_check() and EVP_PKEY_param_check()
    
    Doc and test cases are added
    
    Reviewed-by: Tim Hudson <tjh at openssl.org>
    Reviewed-by: Richard Levitte <levitte at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/4647)

-----------------------------------------------------------------------

Summary of changes:
 apps/pkey.c                         | 15 +++++--
 apps/pkeyparam.c                    | 41 ++++++++++++++++-
 crypto/asn1/ameth_lib.c             | 12 +++++
 crypto/dh/dh_ameth.c                | 35 ++++++++++++++-
 crypto/dh/dh_check.c                | 52 +++++++++++++++++++++
 crypto/dh/dh_err.c                  | 24 ++++++++++
 crypto/ec/ec_ameth.c                | 33 +++++++++++++-
 crypto/ec/ec_err.c                  |  1 +
 crypto/err/openssl.txt              | 18 ++++++++
 crypto/evp/evp_err.c                |  4 ++
 crypto/evp/pmeth_gn.c               | 46 +++++++++++++++++++
 crypto/evp/pmeth_lib.c              | 26 +++++++++++
 crypto/include/internal/asn1_int.h  |  2 +
 crypto/include/internal/evp_int.h   |  2 +
 doc/man1/pkey.pod                   |  6 +++
 doc/man1/pkeyparam.pod              |  5 +++
 doc/man3/DH_generate_parameters.pod | 18 +++++++-
 doc/man3/EVP_PKEY_ASN1_METHOD.pod   | 22 +++++++--
 doc/man3/EVP_PKEY_keygen.pod        | 21 +++++++--
 doc/man3/EVP_PKEY_meth_new.pod      | 18 +++++++-
 include/openssl/dh.h                |  3 ++
 include/openssl/dherr.h             | 15 +++++++
 include/openssl/ecerr.h             |  1 +
 include/openssl/evp.h               | 20 +++++++++
 include/openssl/evperr.h            |  2 +
 test/evp_extra_test.c               | 90 +++++++++++++++++++++++++++++++------
 util/libcrypto.num                  | 11 +++++
 27 files changed, 510 insertions(+), 33 deletions(-)

diff --git a/apps/pkey.c b/apps/pkey.c
index 0a3a36a..6160e5a 100644
--- a/apps/pkey.c
+++ b/apps/pkey.c
@@ -18,7 +18,7 @@ typedef enum OPTION_choice {
     OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
     OPT_INFORM, OPT_OUTFORM, OPT_PASSIN, OPT_PASSOUT, OPT_ENGINE,
     OPT_IN, OPT_OUT, OPT_PUBIN, OPT_PUBOUT, OPT_TEXT_PUB,
-    OPT_TEXT, OPT_NOOUT, OPT_MD, OPT_TRADITIONAL, OPT_CHECK
+    OPT_TEXT, OPT_NOOUT, OPT_MD, OPT_TRADITIONAL, OPT_CHECK, OPT_PUB_CHECK
 } OPTION_CHOICE;
 
 const OPTIONS pkey_options[] = {
@@ -42,6 +42,7 @@ const OPTIONS pkey_options[] = {
     {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
 #endif
     {"check", OPT_CHECK, '-', "Check key consistency"},
+    {"pubcheck", OPT_PUB_CHECK, '-', "Check public key consistency"},
     {NULL}
 };
 
@@ -56,7 +57,7 @@ int pkey_main(int argc, char **argv)
     OPTION_CHOICE o;
     int informat = FORMAT_PEM, outformat = FORMAT_PEM;
     int pubin = 0, pubout = 0, pubtext = 0, text = 0, noout = 0, ret = 1;
-    int private = 0, traditional = 0, check = 0;
+    int private = 0, traditional = 0, check = 0, pub_check = 0;
 
     prog = opt_init(argc, argv, pkey_options);
     while ((o = opt_next()) != OPT_EOF) {
@@ -114,6 +115,9 @@ int pkey_main(int argc, char **argv)
         case OPT_CHECK:
             check = 1;
             break;
+        case OPT_PUB_CHECK:
+            pub_check = 1;
+            break;
         case OPT_MD:
             if (!opt_cipher(opt_unknown(), &cipher))
                 goto opthelp;
@@ -143,7 +147,7 @@ int pkey_main(int argc, char **argv)
     if (pkey == NULL)
         goto end;
 
-    if (check) {
+    if (check || pub_check) {
         int r;
         EVP_PKEY_CTX *ctx;
 
@@ -153,7 +157,10 @@ int pkey_main(int argc, char **argv)
             goto end;
         }
 
-        r = EVP_PKEY_check(ctx);
+        if (check)
+            r = EVP_PKEY_check(ctx);
+        else
+            r = EVP_PKEY_public_check(ctx);
 
         if (r == 1) {
             BIO_printf(out, "Key is valid\n");
diff --git a/apps/pkeyparam.c b/apps/pkeyparam.c
index 9ac2475..35cdd8d 100644
--- a/apps/pkeyparam.c
+++ b/apps/pkeyparam.c
@@ -16,7 +16,8 @@
 
 typedef enum OPTION_choice {
     OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
-    OPT_IN, OPT_OUT, OPT_TEXT, OPT_NOOUT, OPT_ENGINE
+    OPT_IN, OPT_OUT, OPT_TEXT, OPT_NOOUT,
+    OPT_ENGINE, OPT_CHECK
 } OPTION_CHOICE;
 
 const OPTIONS pkeyparam_options[] = {
@@ -28,6 +29,7 @@ const OPTIONS pkeyparam_options[] = {
 #ifndef OPENSSL_NO_ENGINE
     {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
 #endif
+    {"check", OPT_CHECK, '-', "Check key param consistency"},
     {NULL}
 };
 
@@ -36,7 +38,7 @@ int pkeyparam_main(int argc, char **argv)
     ENGINE *e = NULL;
     BIO *in = NULL, *out = NULL;
     EVP_PKEY *pkey = NULL;
-    int text = 0, noout = 0, ret = 1;
+    int text = 0, noout = 0, ret = 1, check = 0;
     OPTION_CHOICE o;
     char *infile = NULL, *outfile = NULL, *prog;
 
@@ -67,6 +69,9 @@ int pkeyparam_main(int argc, char **argv)
         case OPT_NOOUT:
             noout = 1;
             break;
+        case OPT_CHECK:
+            check = 1;
+            break;
         }
     }
     argc = opt_num_rest();
@@ -86,6 +91,38 @@ int pkeyparam_main(int argc, char **argv)
         goto end;
     }
 
+    if (check) {
+        int r;
+        EVP_PKEY_CTX *ctx;
+
+        ctx = EVP_PKEY_CTX_new(pkey, e);
+        if (ctx == NULL) {
+            ERR_print_errors(bio_err);
+            goto end;
+        }
+
+        r = EVP_PKEY_param_check(ctx);
+
+        if (r == 1) {
+            BIO_printf(out, "Parameters are valid\n");
+        } else {
+            /*
+             * Note: at least for RSA keys if this function returns
+             * -1, there will be no error reasons.
+             */
+            unsigned long err;
+
+            BIO_printf(out, "Parameters are invalid\n");
+
+            while ((err = ERR_peek_error()) != 0) {
+                BIO_printf(out, "Detailed error: %s\n",
+                           ERR_reason_error_string(err));
+                ERR_get_error(); /* remove err from error stack */
+            }
+        }
+        EVP_PKEY_CTX_free(ctx);
+    }
+
     if (!noout)
         PEM_write_bio_Parameters(out, pkey);
 
diff --git a/crypto/asn1/ameth_lib.c b/crypto/asn1/ameth_lib.c
index 87a3eba..5662e17 100644
--- a/crypto/asn1/ameth_lib.c
+++ b/crypto/asn1/ameth_lib.c
@@ -382,3 +382,15 @@ void EVP_PKEY_asn1_set_check(EVP_PKEY_ASN1_METHOD *ameth,
 {
     ameth->pkey_check = pkey_check;
 }
+
+void EVP_PKEY_asn1_set_public_check(EVP_PKEY_ASN1_METHOD *ameth,
+                                    int (*pkey_pub_check) (const EVP_PKEY *pk))
+{
+    ameth->pkey_public_check = pkey_pub_check;
+}
+
+void EVP_PKEY_asn1_set_param_check(EVP_PKEY_ASN1_METHOD *ameth,
+                                   int (*pkey_param_check) (const EVP_PKEY *pk))
+{
+    ameth->pkey_param_check = pkey_param_check;
+}
diff --git a/crypto/dh/dh_ameth.c b/crypto/dh/dh_ameth.c
index e504690..05a1d42 100644
--- a/crypto/dh/dh_ameth.c
+++ b/crypto/dh/dh_ameth.c
@@ -509,6 +509,25 @@ static int dh_pkey_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2)
 
 }
 
+static int dh_pkey_public_check(const EVP_PKEY *pkey)
+{
+    DH *dh = pkey->pkey.dh;
+
+    if (dh->pub_key == NULL) {
+        DHerr(DH_F_DH_PKEY_PUBLIC_CHECK, DH_R_MISSING_PUBKEY);
+        return 0;
+    }
+
+    return DH_check_pub_key_ex(dh, dh->pub_key);
+}
+
+static int dh_pkey_param_check(const EVP_PKEY *pkey)
+{
+    DH *dh = pkey->pkey.dh;
+
+    return DH_check_ex(dh);
+}
+
 const EVP_PKEY_ASN1_METHOD dh_asn1_meth = {
     EVP_PKEY_DH,
     EVP_PKEY_DH,
@@ -539,7 +558,13 @@ const EVP_PKEY_ASN1_METHOD dh_asn1_meth = {
     0,
 
     int_dh_free,
-    0
+    0,
+
+    0, 0, 0, 0, 0,
+
+    0,
+    dh_pkey_public_check,
+    dh_pkey_param_check
 };
 
 const EVP_PKEY_ASN1_METHOD dhx_asn1_meth = {
@@ -572,7 +597,13 @@ const EVP_PKEY_ASN1_METHOD dhx_asn1_meth = {
     0,
 
     int_dh_free,
-    dh_pkey_ctrl
+    dh_pkey_ctrl,
+
+    0, 0, 0, 0, 0,
+
+    0,
+    dh_pkey_public_check,
+    dh_pkey_param_check
 };
 
 #ifndef OPENSSL_NO_CMS
diff --git a/crypto/dh/dh_check.c b/crypto/dh/dh_check.c
index 066bf83..fc45577 100644
--- a/crypto/dh/dh_check.c
+++ b/crypto/dh/dh_check.c
@@ -18,6 +18,19 @@
  * p is odd
  * 1 < g < p - 1
  */
+int DH_check_params_ex(const DH *dh)
+{
+    int errflags = 0;
+
+    (void)DH_check_params(dh, &errflags);
+
+    if ((errflags & DH_CHECK_P_NOT_PRIME) != 0)
+        DHerr(DH_F_DH_CHECK_PARAMS_EX, DH_R_CHECK_P_NOT_PRIME);
+    if ((errflags & DH_NOT_SUITABLE_GENERATOR) != 0)
+        DHerr(DH_F_DH_CHECK_PARAMS_EX, DH_R_NOT_SUITABLE_GENERATOR);
+
+    return errflags == 0;
+}
 
 int DH_check_params(const DH *dh, int *ret)
 {
@@ -61,6 +74,29 @@ int DH_check_params(const DH *dh, int *ret)
  * for 5, p mod 10 == 3 or 7
  * should hold.
  */
+int DH_check_ex(const DH *dh)
+{
+    int errflags = 0;
+
+    (void)DH_check(dh, &errflags);
+
+    if ((errflags & DH_NOT_SUITABLE_GENERATOR) != 0)
+        DHerr(DH_F_DH_CHECK_EX, DH_R_NOT_SUITABLE_GENERATOR);
+    if ((errflags & DH_CHECK_Q_NOT_PRIME) != 0)
+        DHerr(DH_F_DH_CHECK_EX, DH_R_CHECK_Q_NOT_PRIME);
+    if ((errflags & DH_CHECK_INVALID_Q_VALUE) != 0)
+        DHerr(DH_F_DH_CHECK_EX, DH_R_CHECK_INVALID_Q_VALUE);
+    if ((errflags & DH_CHECK_INVALID_J_VALUE) != 0)
+        DHerr(DH_F_DH_CHECK_EX, DH_R_CHECK_INVALID_J_VALUE);
+    if ((errflags & DH_UNABLE_TO_CHECK_GENERATOR) != 0)
+        DHerr(DH_F_DH_CHECK_EX, DH_R_UNABLE_TO_CHECK_GENERATOR);
+    if ((errflags & DH_CHECK_P_NOT_PRIME) != 0)
+        DHerr(DH_F_DH_CHECK_EX, DH_R_CHECK_P_NOT_PRIME);
+    if ((errflags & DH_CHECK_P_NOT_SAFE_PRIME) != 0)
+        DHerr(DH_F_DH_CHECK_EX, DH_R_CHECK_P_NOT_SAFE_PRIME);
+
+    return errflags == 0;
+}
 
 int DH_check(const DH *dh, int *ret)
 {
@@ -142,6 +178,22 @@ int DH_check(const DH *dh, int *ret)
     return ok;
 }
 
+int DH_check_pub_key_ex(const DH *dh, const BIGNUM *pub_key)
+{
+    int errflags = 0;
+
+    (void)DH_check(dh, &errflags);
+
+    if ((errflags & DH_CHECK_PUBKEY_TOO_SMALL) != 0)
+        DHerr(DH_F_DH_CHECK_PUB_KEY_EX, DH_R_CHECK_PUBKEY_TOO_SMALL);
+    if ((errflags & DH_CHECK_PUBKEY_TOO_LARGE) != 0)
+        DHerr(DH_F_DH_CHECK_PUB_KEY_EX, DH_R_CHECK_PUBKEY_TOO_LARGE);
+    if ((errflags & DH_CHECK_PUBKEY_INVALID) != 0)
+        DHerr(DH_F_DH_CHECK_PUB_KEY_EX, DH_R_CHECK_PUBKEY_INVALID);
+
+    return errflags == 0;
+}
+
 int DH_check_pub_key(const DH *dh, const BIGNUM *pub_key, int *ret)
 {
     int ok = 0;
diff --git a/crypto/dh/dh_err.c b/crypto/dh/dh_err.c
index aae66fa..bbedab5 100644
--- a/crypto/dh/dh_err.c
+++ b/crypto/dh/dh_err.c
@@ -18,6 +18,9 @@ static const ERR_STRING_DATA DH_str_functs[] = {
     {ERR_PACK(ERR_LIB_DH, DH_F_DHPARAMS_PRINT_FP, 0), "DHparams_print_fp"},
     {ERR_PACK(ERR_LIB_DH, DH_F_DH_BUILTIN_GENPARAMS, 0),
      "dh_builtin_genparams"},
+    {ERR_PACK(ERR_LIB_DH, DH_F_DH_CHECK_EX, 0), "DH_check_ex"},
+    {ERR_PACK(ERR_LIB_DH, DH_F_DH_CHECK_PARAMS_EX, 0), "DH_check_params_ex"},
+    {ERR_PACK(ERR_LIB_DH, DH_F_DH_CHECK_PUB_KEY_EX, 0), "DH_check_pub_key_ex"},
     {ERR_PACK(ERR_LIB_DH, DH_F_DH_CMS_DECRYPT, 0), "dh_cms_decrypt"},
     {ERR_PACK(ERR_LIB_DH, DH_F_DH_CMS_SET_PEERKEY, 0), "dh_cms_set_peerkey"},
     {ERR_PACK(ERR_LIB_DH, DH_F_DH_CMS_SET_SHARED_INFO, 0),
@@ -28,6 +31,8 @@ static const ERR_STRING_DATA DH_str_functs[] = {
     {ERR_PACK(ERR_LIB_DH, DH_F_DH_NEW_BY_NID, 0), "DH_new_by_nid"},
     {ERR_PACK(ERR_LIB_DH, DH_F_DH_NEW_METHOD, 0), "DH_new_method"},
     {ERR_PACK(ERR_LIB_DH, DH_F_DH_PARAM_DECODE, 0), "dh_param_decode"},
+    {ERR_PACK(ERR_LIB_DH, DH_F_DH_PKEY_PUBLIC_CHECK, 0),
+     "dh_pkey_public_check"},
     {ERR_PACK(ERR_LIB_DH, DH_F_DH_PRIV_DECODE, 0), "dh_priv_decode"},
     {ERR_PACK(ERR_LIB_DH, DH_F_DH_PRIV_ENCODE, 0), "dh_priv_encode"},
     {ERR_PACK(ERR_LIB_DH, DH_F_DH_PUB_DECODE, 0), "dh_pub_decode"},
@@ -44,6 +49,20 @@ static const ERR_STRING_DATA DH_str_reasons[] = {
     {ERR_PACK(ERR_LIB_DH, 0, DH_R_BAD_GENERATOR), "bad generator"},
     {ERR_PACK(ERR_LIB_DH, 0, DH_R_BN_DECODE_ERROR), "bn decode error"},
     {ERR_PACK(ERR_LIB_DH, 0, DH_R_BN_ERROR), "bn error"},
+    {ERR_PACK(ERR_LIB_DH, 0, DH_R_CHECK_INVALID_J_VALUE),
+    "check invalid j value"},
+    {ERR_PACK(ERR_LIB_DH, 0, DH_R_CHECK_INVALID_Q_VALUE),
+    "check invalid q value"},
+    {ERR_PACK(ERR_LIB_DH, 0, DH_R_CHECK_PUBKEY_INVALID),
+    "check pubkey invalid"},
+    {ERR_PACK(ERR_LIB_DH, 0, DH_R_CHECK_PUBKEY_TOO_LARGE),
+    "check pubkey too large"},
+    {ERR_PACK(ERR_LIB_DH, 0, DH_R_CHECK_PUBKEY_TOO_SMALL),
+    "check pubkey too small"},
+    {ERR_PACK(ERR_LIB_DH, 0, DH_R_CHECK_P_NOT_PRIME), "check p not prime"},
+    {ERR_PACK(ERR_LIB_DH, 0, DH_R_CHECK_P_NOT_SAFE_PRIME),
+    "check p not safe prime"},
+    {ERR_PACK(ERR_LIB_DH, 0, DH_R_CHECK_Q_NOT_PRIME), "check q not prime"},
     {ERR_PACK(ERR_LIB_DH, 0, DH_R_DECODE_ERROR), "decode error"},
     {ERR_PACK(ERR_LIB_DH, 0, DH_R_INVALID_PARAMETER_NAME),
     "invalid parameter name"},
@@ -52,13 +71,18 @@ static const ERR_STRING_DATA DH_str_reasons[] = {
     {ERR_PACK(ERR_LIB_DH, 0, DH_R_INVALID_PUBKEY), "invalid public key"},
     {ERR_PACK(ERR_LIB_DH, 0, DH_R_KDF_PARAMETER_ERROR), "kdf parameter error"},
     {ERR_PACK(ERR_LIB_DH, 0, DH_R_KEYS_NOT_SET), "keys not set"},
+    {ERR_PACK(ERR_LIB_DH, 0, DH_R_MISSING_PUBKEY), "missing pubkey"},
     {ERR_PACK(ERR_LIB_DH, 0, DH_R_MODULUS_TOO_LARGE), "modulus too large"},
+    {ERR_PACK(ERR_LIB_DH, 0, DH_R_NOT_SUITABLE_GENERATOR),
+    "not suitable generator"},
     {ERR_PACK(ERR_LIB_DH, 0, DH_R_NO_PARAMETERS_SET), "no parameters set"},
     {ERR_PACK(ERR_LIB_DH, 0, DH_R_NO_PRIVATE_VALUE), "no private value"},
     {ERR_PACK(ERR_LIB_DH, 0, DH_R_PARAMETER_ENCODING_ERROR),
     "parameter encoding error"},
     {ERR_PACK(ERR_LIB_DH, 0, DH_R_PEER_KEY_ERROR), "peer key error"},
     {ERR_PACK(ERR_LIB_DH, 0, DH_R_SHARED_INFO_ERROR), "shared info error"},
+    {ERR_PACK(ERR_LIB_DH, 0, DH_R_UNABLE_TO_CHECK_GENERATOR),
+    "unable to check generator"},
     {0, NULL}
 };
 
diff --git a/crypto/ec/ec_ameth.c b/crypto/ec/ec_ameth.c
index 22ad6b0..0682bc3 100644
--- a/crypto/ec/ec_ameth.c
+++ b/crypto/ec/ec_ameth.c
@@ -533,6 +533,35 @@ static int ec_pkey_check(const EVP_PKEY *pkey)
     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,
@@ -568,7 +597,9 @@ const EVP_PKEY_ASN1_METHOD eckey_asn1_meth = {
 
     0, 0, 0,
 
-    ec_pkey_check
+    ec_pkey_check,
+    ec_pkey_public_check,
+    ec_pkey_param_check
 };
 
 int EC_KEY_print(BIO *bp, const EC_KEY *x, int off)
diff --git a/crypto/ec/ec_err.c b/crypto/ec/ec_err.c
index 19a7a9d..9f82b4e 100644
--- a/crypto/ec/ec_err.c
+++ b/crypto/ec/ec_err.c
@@ -182,6 +182,7 @@ static const ERR_STRING_DATA EC_str_functs[] = {
     {ERR_PACK(ERR_LIB_EC, EC_F_EC_KEY_SIMPLE_PRIV2OCT, 0),
      "ec_key_simple_priv2oct"},
     {ERR_PACK(ERR_LIB_EC, EC_F_EC_PKEY_CHECK, 0), "ec_pkey_check"},
+    {ERR_PACK(ERR_LIB_EC, EC_F_EC_PKEY_PARAM_CHECK, 0), "ec_pkey_param_check"},
     {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINTS_MAKE_AFFINE, 0),
      "EC_POINTs_make_affine"},
     {ERR_PACK(ERR_LIB_EC, EC_F_EC_POINT_ADD, 0), "EC_POINT_add"},
diff --git a/crypto/err/openssl.txt b/crypto/err/openssl.txt
index d3e4a62..8547d07 100644
--- a/crypto/err/openssl.txt
+++ b/crypto/err/openssl.txt
@@ -351,6 +351,9 @@ CT_F_SCT_SET_VERSION:104:SCT_set_version
 DH_F_COMPUTE_KEY:102:compute_key
 DH_F_DHPARAMS_PRINT_FP:101:DHparams_print_fp
 DH_F_DH_BUILTIN_GENPARAMS:106:dh_builtin_genparams
+DH_F_DH_CHECK_EX:121:DH_check_ex
+DH_F_DH_CHECK_PARAMS_EX:122:DH_check_params_ex
+DH_F_DH_CHECK_PUB_KEY_EX:123:DH_check_pub_key_ex
 DH_F_DH_CMS_DECRYPT:114:dh_cms_decrypt
 DH_F_DH_CMS_SET_PEERKEY:115:dh_cms_set_peerkey
 DH_F_DH_CMS_SET_SHARED_INFO:116:dh_cms_set_shared_info
@@ -360,6 +363,7 @@ DH_F_DH_METH_SET1_NAME:119:DH_meth_set1_name
 DH_F_DH_NEW_BY_NID:104:DH_new_by_nid
 DH_F_DH_NEW_METHOD:105:DH_new_method
 DH_F_DH_PARAM_DECODE:107:dh_param_decode
+DH_F_DH_PKEY_PUBLIC_CHECK:124:dh_pkey_public_check
 DH_F_DH_PRIV_DECODE:110:dh_priv_decode
 DH_F_DH_PRIV_ENCODE:111:dh_priv_encode
 DH_F_DH_PUB_DECODE:108:dh_pub_decode
@@ -542,6 +546,7 @@ EC_F_EC_KEY_SIMPLE_CHECK_KEY:258:ec_key_simple_check_key
 EC_F_EC_KEY_SIMPLE_OCT2PRIV:259:ec_key_simple_oct2priv
 EC_F_EC_KEY_SIMPLE_PRIV2OCT:260:ec_key_simple_priv2oct
 EC_F_EC_PKEY_CHECK:273:ec_pkey_check
+EC_F_EC_PKEY_PARAM_CHECK:274:ec_pkey_param_check
 EC_F_EC_POINTS_MAKE_AFFINE:136:EC_POINTs_make_affine
 EC_F_EC_POINT_ADD:112:EC_POINT_add
 EC_F_EC_POINT_CMP:113:EC_POINT_cmp
@@ -692,6 +697,8 @@ EVP_F_EVP_PKEY_KEYGEN_INIT:147:EVP_PKEY_keygen_init
 EVP_F_EVP_PKEY_NEW:106:EVP_PKEY_new
 EVP_F_EVP_PKEY_PARAMGEN:148:EVP_PKEY_paramgen
 EVP_F_EVP_PKEY_PARAMGEN_INIT:149:EVP_PKEY_paramgen_init
+EVP_F_EVP_PKEY_PARAM_CHECK:189:EVP_PKEY_param_check
+EVP_F_EVP_PKEY_PUBLIC_CHECK:190:EVP_PKEY_public_check
 EVP_F_EVP_PKEY_SET1_ENGINE:187:EVP_PKEY_set1_engine
 EVP_F_EVP_PKEY_SIGN:140:EVP_PKEY_sign
 EVP_F_EVP_PKEY_SIGN_INIT:141:EVP_PKEY_sign_init
@@ -1794,18 +1801,29 @@ CT_R_UNSUPPORTED_VERSION:103:unsupported version
 DH_R_BAD_GENERATOR:101:bad generator
 DH_R_BN_DECODE_ERROR:109:bn decode error
 DH_R_BN_ERROR:106:bn error
+DH_R_CHECK_INVALID_J_VALUE:115:check invalid j value
+DH_R_CHECK_INVALID_Q_VALUE:116:check invalid q value
+DH_R_CHECK_PUBKEY_INVALID:122:check pubkey invalid
+DH_R_CHECK_PUBKEY_TOO_LARGE:123:check pubkey too large
+DH_R_CHECK_PUBKEY_TOO_SMALL:124:check pubkey too small
+DH_R_CHECK_P_NOT_PRIME:117:check p not prime
+DH_R_CHECK_P_NOT_SAFE_PRIME:118:check p not safe prime
+DH_R_CHECK_Q_NOT_PRIME:119:check q not prime
 DH_R_DECODE_ERROR:104:decode error
 DH_R_INVALID_PARAMETER_NAME:110:invalid parameter name
 DH_R_INVALID_PARAMETER_NID:114:invalid parameter nid
 DH_R_INVALID_PUBKEY:102:invalid public key
 DH_R_KDF_PARAMETER_ERROR:112:kdf parameter error
 DH_R_KEYS_NOT_SET:108:keys not set
+DH_R_MISSING_PUBKEY:125:missing pubkey
 DH_R_MODULUS_TOO_LARGE:103:modulus too large
+DH_R_NOT_SUITABLE_GENERATOR:120:not suitable generator
 DH_R_NO_PARAMETERS_SET:107:no parameters set
 DH_R_NO_PRIVATE_VALUE:100:no private value
 DH_R_PARAMETER_ENCODING_ERROR:105:parameter encoding error
 DH_R_PEER_KEY_ERROR:111:peer key error
 DH_R_SHARED_INFO_ERROR:113:shared info error
+DH_R_UNABLE_TO_CHECK_GENERATOR:121:unable to check generator
 DSA_R_BAD_Q_VALUE:102:bad q value
 DSA_R_BN_DECODE_ERROR:108:bn decode error
 DSA_R_BN_ERROR:109:bn error
diff --git a/crypto/evp/evp_err.c b/crypto/evp/evp_err.c
index 9bb37e0..6c1dc83 100644
--- a/crypto/evp/evp_err.c
+++ b/crypto/evp/evp_err.c
@@ -96,6 +96,10 @@ static const ERR_STRING_DATA EVP_str_functs[] = {
     {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_PARAMGEN, 0), "EVP_PKEY_paramgen"},
     {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_PARAMGEN_INIT, 0),
      "EVP_PKEY_paramgen_init"},
+    {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_PARAM_CHECK, 0),
+     "EVP_PKEY_param_check"},
+    {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_PUBLIC_CHECK, 0),
+     "EVP_PKEY_public_check"},
     {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_SET1_ENGINE, 0),
      "EVP_PKEY_set1_engine"},
     {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_SIGN, 0), "EVP_PKEY_sign"},
diff --git a/crypto/evp/pmeth_gn.c b/crypto/evp/pmeth_gn.c
index 1a927a8..e14965f 100644
--- a/crypto/evp/pmeth_gn.c
+++ b/crypto/evp/pmeth_gn.c
@@ -191,3 +191,49 @@ int EVP_PKEY_check(EVP_PKEY_CTX *ctx)
 
     return pkey->ameth->pkey_check(pkey);
 }
+
+int EVP_PKEY_public_check(EVP_PKEY_CTX *ctx)
+{
+    EVP_PKEY *pkey = ctx->pkey;
+
+    if (pkey == NULL) {
+        EVPerr(EVP_F_EVP_PKEY_PUBLIC_CHECK, EVP_R_NO_KEY_SET);
+        return 0;
+    }
+
+    /* call customized public key check function first */
+    if (ctx->pmeth->public_check != NULL)
+        return ctx->pmeth->public_check(pkey);
+
+    /* use default public key check function in ameth */
+    if (pkey->ameth == NULL || pkey->ameth->pkey_public_check == NULL) {
+        EVPerr(EVP_F_EVP_PKEY_PUBLIC_CHECK,
+               EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+        return -2;
+    }
+
+    return pkey->ameth->pkey_public_check(pkey);
+}
+
+int EVP_PKEY_param_check(EVP_PKEY_CTX *ctx)
+{
+    EVP_PKEY *pkey = ctx->pkey;
+
+    if (pkey == NULL) {
+        EVPerr(EVP_F_EVP_PKEY_PARAM_CHECK, EVP_R_NO_KEY_SET);
+        return 0;
+    }
+
+    /* call customized param check function first */
+    if (ctx->pmeth->param_check != NULL)
+        return ctx->pmeth->param_check(pkey);
+
+    /* use default param check function in ameth */
+    if (pkey->ameth == NULL || pkey->ameth->pkey_param_check == NULL) {
+        EVPerr(EVP_F_EVP_PKEY_PARAM_CHECK,
+               EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+        return -2;
+    }
+
+    return pkey->ameth->pkey_param_check(pkey);
+}
diff --git a/crypto/evp/pmeth_lib.c b/crypto/evp/pmeth_lib.c
index 37c5e85..2d9f4fc 100644
--- a/crypto/evp/pmeth_lib.c
+++ b/crypto/evp/pmeth_lib.c
@@ -630,6 +630,18 @@ void EVP_PKEY_meth_set_check(EVP_PKEY_METHOD *pmeth,
     pmeth->check = check;
 }
 
+void EVP_PKEY_meth_set_public_check(EVP_PKEY_METHOD *pmeth,
+                                    int (*check) (EVP_PKEY *pkey))
+{
+    pmeth->public_check = check;
+}
+
+void EVP_PKEY_meth_set_param_check(EVP_PKEY_METHOD *pmeth,
+                                   int (*check) (EVP_PKEY *pkey))
+{
+    pmeth->param_check = check;
+}
+
 void EVP_PKEY_meth_get_init(EVP_PKEY_METHOD *pmeth,
                             int (**pinit) (EVP_PKEY_CTX *ctx))
 {
@@ -803,3 +815,17 @@ void EVP_PKEY_meth_get_check(EVP_PKEY_METHOD *pmeth,
     if (*pcheck)
         *pcheck = pmeth->check;
 }
+
+void EVP_PKEY_meth_get_public_check(EVP_PKEY_METHOD *pmeth,
+                                    int (**pcheck) (EVP_PKEY *pkey))
+{
+    if (*pcheck)
+        *pcheck = pmeth->public_check;
+}
+
+void EVP_PKEY_meth_get_param_check(EVP_PKEY_METHOD *pmeth,
+                                   int (**pcheck) (EVP_PKEY *pkey))
+{
+    if (*pcheck)
+        *pcheck = pmeth->param_check;
+}
diff --git a/crypto/include/internal/asn1_int.h b/crypto/include/internal/asn1_int.h
index d8b6f45..90d525a 100644
--- a/crypto/include/internal/asn1_int.h
+++ b/crypto/include/internal/asn1_int.h
@@ -56,6 +56,8 @@ struct evp_pkey_asn1_method_st {
                        const ASN1_STRING *sig);
     /* Check */
     int (*pkey_check) (const EVP_PKEY *pk);
+    int (*pkey_public_check) (const EVP_PKEY *pk);
+    int (*pkey_param_check) (const EVP_PKEY *pk);
 } /* EVP_PKEY_ASN1_METHOD */ ;
 
 DEFINE_STACK_OF_CONST(EVP_PKEY_ASN1_METHOD)
diff --git a/crypto/include/internal/evp_int.h b/crypto/include/internal/evp_int.h
index 562ac42..917245c 100644
--- a/crypto/include/internal/evp_int.h
+++ b/crypto/include/internal/evp_int.h
@@ -76,6 +76,8 @@ struct evp_pkey_method_st {
                          size_t siglen, const unsigned char *tbs,
                          size_t tbslen);
     int (*check) (EVP_PKEY *pkey);
+    int (*public_check) (EVP_PKEY *pkey);
+    int (*param_check) (EVP_PKEY *pkey);
 } /* EVP_PKEY_METHOD */ ;
 
 DEFINE_STACK_OF_CONST(EVP_PKEY_METHOD)
diff --git a/doc/man1/pkey.pod b/doc/man1/pkey.pod
index 47ffb66..9569fe0 100644
--- a/doc/man1/pkey.pod
+++ b/doc/man1/pkey.pod
@@ -24,6 +24,7 @@ B<openssl> B<pkey>
 [B<-pubout>]
 [B<-engine id>]
 [B<-check>]
+[B<-pubcheck>]
 
 =head1 DESCRIPTION
 
@@ -117,6 +118,11 @@ for all available algorithms.
 This option checks the consistency of a key pair for both public and private
 components.
 
+=item B<-pubcheck>
+
+This option checks the correctness of either a public key or the public component
+of a key pair.
+
 =back
 
 =head1 EXAMPLES
diff --git a/doc/man1/pkeyparam.pod b/doc/man1/pkeyparam.pod
index 45c053c..1179705 100644
--- a/doc/man1/pkeyparam.pod
+++ b/doc/man1/pkeyparam.pod
@@ -14,6 +14,7 @@ B<openssl> B<pkeyparam>
 [B<-text>]
 [B<-noout>]
 [B<-engine id>]
+[B<-check>]
 
 =head1 DESCRIPTION
 
@@ -53,6 +54,10 @@ to attempt to obtain a functional reference to the specified engine,
 thus initialising it if needed. The engine will then be set as the default
 for all available algorithms.
 
+=item B<-check>
+
+This option checks the correctness of parameters.
+
 =back
 
 =head1 EXAMPLE
diff --git a/doc/man3/DH_generate_parameters.pod b/doc/man3/DH_generate_parameters.pod
index 2e8c3b7..56ad4b1 100644
--- a/doc/man3/DH_generate_parameters.pod
+++ b/doc/man3/DH_generate_parameters.pod
@@ -3,7 +3,9 @@
 =head1 NAME
 
 DH_generate_parameters_ex, DH_generate_parameters,
-DH_check, DH_check_params - generate and check Diffie-Hellman
+DH_check, DH_check_params,
+DH_check_ex, DH_check_params_ex, DH_check_pub_key_ex
+- generate and check Diffie-Hellman
 parameters
 
 =head1 SYNOPSIS
@@ -15,6 +17,10 @@ parameters
  int DH_check(DH *dh, int *codes);
  int DH_check_params(DH *dh, int *codes);
 
+ int DH_check_ex(const DH *dh);
+ int DH_check_params_ex(const DH *dh);
+ int DH_check_pub_key_ex(const DH *dh, const BIGNUM *pub_key);
+
 Deprecated:
 
  #if OPENSSL_API_COMPAT < 0x00908000L
@@ -105,6 +111,11 @@ The parameter B<j> is invalid.
 
 =back
 
+DH_check_ex(), DH_check_params() and DH_check_pub_key_ex() are similiar with
+DH_check() and DH_check_params() respectively, but the error reasons are set
+to the OpenSSL error handling framework instead of returning by the function
+parameters.
+
 =head1 RETURN VALUES
 
 DH_generate_parameters_ex(), DH_check() and DH_check_params() return 1
@@ -113,6 +124,9 @@ if the check could be performed, 0 otherwise.
 DH_generate_parameters() returns a pointer to the DH structure or NULL if
 the parameter generation fails.
 
+DH_check_ex(), DH_check_params() and DH_check_pub_key_ex() return 1 if the
+check is successful, 0 for failed.
+
 The error codes can be obtained by L<ERR_get_error(3)>.
 
 =head1 SEE ALSO
@@ -127,7 +141,7 @@ DH_generate_parameters_ex() instead.
 
 =head1 COPYRIGHT
 
-Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2000-2017 The OpenSSL Project Authors. All Rights Reserved.
 
 Licensed under the OpenSSL license (the "License").  You may not use
 this file except in compliance with the License.  You can obtain a copy
diff --git a/doc/man3/EVP_PKEY_ASN1_METHOD.pod b/doc/man3/EVP_PKEY_ASN1_METHOD.pod
index 2ebabd1..cb03b47 100644
--- a/doc/man3/EVP_PKEY_ASN1_METHOD.pod
+++ b/doc/man3/EVP_PKEY_ASN1_METHOD.pod
@@ -16,6 +16,8 @@ EVP_PKEY_asn1_set_ctrl,
 EVP_PKEY_asn1_set_item,
 EVP_PKEY_asn1_set_siginf,
 EVP_PKEY_asn1_set_check,
+EVP_PKEY_asn1_set_public_check,
+EVP_PKEY_asn1_set_param_check,
 EVP_PKEY_asn1_set_security_bits,
 EVP_PKEY_get0_asn1
 - manipulating and registering EVP_PKEY_ASN1_METHOD structure
@@ -100,6 +102,12 @@ EVP_PKEY_get0_asn1
  void EVP_PKEY_asn1_set_check(EVP_PKEY_ASN1_METHOD *ameth,
                               int (*pkey_check) (const EVP_PKEY *pk));
 
+ void EVP_PKEY_asn1_set_public_check(EVP_PKEY_ASN1_METHOD *ameth,
+                                     int (*pkey_pub_check) (const EVP_PKEY *pk));
+
+ void EVP_PKEY_asn1_set_param_check(EVP_PKEY_ASN1_METHOD *ameth,
+                                    int (*pkey_param_check) (const EVP_PKEY *pk));
+
  void EVP_PKEY_asn1_set_security_bits(EVP_PKEY_ASN1_METHOD *ameth,
                                       int (*pkey_security_bits) (const EVP_PKEY
                                                                  *pk));
@@ -309,10 +317,15 @@ It's called as part of L<X509_check_purpose(3)>, L<X509_check_ca(3)>
 and L<X509_check_issued(3)>.
 
  int (*pkey_check) (const EVP_PKEY *pk);
+ int (*pkey_public_check) (const EVP_PKEY *pk);
+ int (*pkey_param_check) (const EVP_PKEY *pk);
 
-The pkey_check() method is used to check the validity of B<pk>.
-It MUST return 0 for an invalid key, or 1 for a valid key.
-It's called by L<EVP_PKEY_check(3)>.
+The pkey_check(), pkey_public_check() and pkey_param_check() methods are used
+to check the validity of B<pk> for key-pair, public component and parameters,
+respectively.
+They MUST return 0 for an invalid key, or 1 for a valid key.
+They are called by L<EVP_PKEY_check(3)>, L<EVP_PKEY_public_check(3)> and
+L<EVP_PKEY_param_check(3)> respectively.
 
 =head2 Functions
 
@@ -354,7 +367,8 @@ when initializing the application.
 EVP_PKEY_asn1_set_public(), EVP_PKEY_asn1_set_private(),
 EVP_PKEY_asn1_set_param(), EVP_PKEY_asn1_set_free(),
 EVP_PKEY_asn1_set_ctrl(), EVP_PKEY_asn1_set_item(),
-EVP_PKEY_asn1_set_siginf(), EVP_PKEY_asn1_set_check(), and
+EVP_PKEY_asn1_set_siginf(), EVP_PKEY_asn1_set_check(),
+EVP_PKEY_asn1_set_public_check(), EVP_PKEY_asn1_set_param_check() and
 EVP_PKEY_asn1_set_security_bits() set the diverse methods of the given
 B<EVP_PKEY_ASN1_METHOD> object.
 
diff --git a/doc/man3/EVP_PKEY_keygen.pod b/doc/man3/EVP_PKEY_keygen.pod
index 099cd0c..a18579c 100644
--- a/doc/man3/EVP_PKEY_keygen.pod
+++ b/doc/man3/EVP_PKEY_keygen.pod
@@ -6,7 +6,8 @@ EVP_PKEY_keygen_init, EVP_PKEY_keygen, EVP_PKEY_paramgen_init,
 EVP_PKEY_paramgen, EVP_PKEY_CTX_set_cb, EVP_PKEY_CTX_get_cb,
 EVP_PKEY_CTX_get_keygen_info, EVP_PKEY_CTX_set_app_data,
 EVP_PKEY_CTX_get_app_data,
-EVP_PKEY_gen_cb, EVP_PKEY_check
+EVP_PKEY_gen_cb, EVP_PKEY_check, EVP_PKEY_public_check,
+EVP_PKEY_param_check
 - key and parameter generation and check functions
 
 =head1 SYNOPSIS
@@ -29,6 +30,8 @@ EVP_PKEY_gen_cb, EVP_PKEY_check
  void *EVP_PKEY_CTX_get_app_data(EVP_PKEY_CTX *ctx);
 
  int EVP_PKEY_check(EVP_PKEY_CTX *ctx);
+ int EVP_PKEY_public_check(EVP_PKEY_CTX *ctx);
+ int EVP_PKEY_param_check(EVP_PKEY_CTX *ctx);
 
 =head1 DESCRIPTION
 
@@ -64,6 +67,14 @@ EVP_PKEY_check() validates the key-pair given by B<ctx>. This function first tri
 to use customized key check method in B<EVP_PKEY_METHOD> if it's present; otherwise
 it calls a default one defined in B<EVP_PKEY_ASN1_METHOD>.
 
+EVP_PKEY_public_check() validates the public component of the key-pair given by B<ctx>.
+This function first tries to use customized key check method in B<EVP_PKEY_METHOD>
+if it's present; otherwise it calls a default one defined in B<EVP_PKEY_ASN1_METHOD>.
+
+EVP_PKEY_param_check() validates the algorithm parameters of the key-pair given by B<ctx>.
+This function first tries to use customized key check method in B<EVP_PKEY_METHOD>
+if it's present; otherwise it calls a default one defined in B<EVP_PKEY_ASN1_METHOD>.
+
 =head1 NOTES
 
 After the call to EVP_PKEY_keygen_init() or EVP_PKEY_paramgen_init() algorithm
@@ -95,8 +106,9 @@ EVP_PKEY_paramgen() return 1 for success and 0 or a negative value for failure.
 In particular a return value of -2 indicates the operation is not supported by
 the public key algorithm.
 
-EVP_PKEY_check() returns 1 for success or others for failure. It
-returns -2 if the operation is not supported for the specific algorithm.
+EVP_PKEY_check(), EVP_PKEY_public_check() and EVP_PKEY_param_check() return 1
+for success or others for failure. They return -2 if the operation is not supported
+for the specific algorithm.
 
 =head1 EXAMPLES
 
@@ -178,6 +190,9 @@ L<EVP_PKEY_derive(3)>
 
 These functions were first added to OpenSSL 1.0.0.
 
+EVP_PKEY_check(), EVP_PKEY_public_check() and EVP_PKEY_param_check() were added
+in OpenSSL 1.1.1.
+
 =head1 COPYRIGHT
 
 Copyright 2006-2017 The OpenSSL Project Authors. All Rights Reserved.
diff --git a/doc/man3/EVP_PKEY_meth_new.pod b/doc/man3/EVP_PKEY_meth_new.pod
index 672ac29..918e4fa 100644
--- a/doc/man3/EVP_PKEY_meth_new.pod
+++ b/doc/man3/EVP_PKEY_meth_new.pod
@@ -9,11 +9,13 @@ EVP_PKEY_meth_set_paramgen, EVP_PKEY_meth_set_keygen, EVP_PKEY_meth_set_sign,
 EVP_PKEY_meth_set_verify, EVP_PKEY_meth_set_verify_recover, EVP_PKEY_meth_set_signctx,
 EVP_PKEY_meth_set_verifyctx, EVP_PKEY_meth_set_encrypt, EVP_PKEY_meth_set_decrypt,
 EVP_PKEY_meth_set_derive, EVP_PKEY_meth_set_ctrl, EVP_PKEY_meth_set_check,
+EVP_PKEY_meth_set_public_check, EVP_PKEY_meth_set_param_check,
 EVP_PKEY_meth_get_init, EVP_PKEY_meth_get_copy, EVP_PKEY_meth_get_cleanup,
 EVP_PKEY_meth_get_paramgen, EVP_PKEY_meth_get_keygen, EVP_PKEY_meth_get_sign,
 EVP_PKEY_meth_get_verify, EVP_PKEY_meth_get_verify_recover, EVP_PKEY_meth_get_signctx,
 EVP_PKEY_meth_get_verifyctx, EVP_PKEY_meth_get_encrypt, EVP_PKEY_meth_get_decrypt,
 EVP_PKEY_meth_get_derive, EVP_PKEY_meth_get_ctrl, EVP_PKEY_meth_get_check,
+EVP_PKEY_meth_get_public_check, EVP_PKEY_meth_get_param_check,
 EVP_PKEY_meth_remove
 - manipulating EVP_PKEY_METHOD structure
 
@@ -110,6 +112,10 @@ EVP_PKEY_meth_remove
                                               const char *value));
  void EVP_PKEY_meth_set_check(EVP_PKEY_METHOD *pmeth,
                               int (*check) (EVP_PKEY *pkey));
+ void EVP_PKEY_meth_set_public_check(EVP_PKEY_METHOD *pmeth,
+                                     int (*check) (EVP_PKEY *pkey));
+ void EVP_PKEY_meth_set_param_check(EVP_PKEY_METHOD *pmeth,
+                                    int (*check) (EVP_PKEY *pkey));
 
  void EVP_PKEY_meth_get_init(EVP_PKEY_METHOD *pmeth,
                              int (**pinit) (EVP_PKEY_CTX *ctx));
@@ -191,6 +197,10 @@ EVP_PKEY_meth_remove
                                                 const char *value));
  void EVP_PKEY_meth_get_check(EVP_PKEY_METHOD *pmeth,
                               int (**pcheck) (EVP_PKEY *pkey));
+ void EVP_PKEY_meth_get_public_check(EVP_PKEY_METHOD *pmeth,
+                                     int (**pcheck) (EVP_PKEY *pkey));
+ void EVP_PKEY_meth_get_param_check(EVP_PKEY_METHOD *pmeth,
+                                    int (**pcheck) (EVP_PKEY *pkey));
 
 =head1 DESCRIPTION
 
@@ -316,9 +326,13 @@ a signature in a one-shot mode. They could be called by L<EVP_DigetSign(3)>
 and L<EVP_DigestVerify(3)>.
 
  int (*check) (EVP_PKEY *pkey);
+ int (*public_check) (EVP_PKEY *pkey);
+ int (*param_check) (EVP_PKEY *pkey);
 
-The check() method is used to validate a key-pair for a given B<pkey>. It
-could be called by L<EVP_PKEY_check(3)>.
+The check(), public_check() and param_check() methods are used to validate a
+key-pair, the public component and parameters respectively for a given B<pkey>.
+They could be called by L<EVP_PKEY_check(3)>, L<EVP_PKEY_public_check(3)> and
+L<EVP_PKEY_param_check(3)> respectively.
 
 =head2 Functions
 
diff --git a/include/openssl/dh.h b/include/openssl/dh.h
index 753df4e..0085824 100644
--- a/include/openssl/dh.h
+++ b/include/openssl/dh.h
@@ -142,6 +142,9 @@ DEPRECATEDIN_0_9_8(DH *DH_generate_parameters(int prime_len, int generator,
 int DH_generate_parameters_ex(DH *dh, int prime_len, int generator,
                               BN_GENCB *cb);
 
+int DH_check_params_ex(const DH *dh);
+int DH_check_ex(const DH *dh);
+int DH_check_pub_key_ex(const DH *dh, const BIGNUM *pub_key);
 int DH_check_params(const DH *dh, int *ret);
 int DH_check(const DH *dh, int *codes);
 int DH_check_pub_key(const DH *dh, const BIGNUM *pub_key, int *codes);
diff --git a/include/openssl/dherr.h b/include/openssl/dherr.h
index 0203907..ddec341 100644
--- a/include/openssl/dherr.h
+++ b/include/openssl/dherr.h
@@ -25,6 +25,9 @@ int ERR_load_DH_strings(void);
 # define DH_F_COMPUTE_KEY                                 102
 # define DH_F_DHPARAMS_PRINT_FP                           101
 # define DH_F_DH_BUILTIN_GENPARAMS                        106
+# define DH_F_DH_CHECK_EX                                 121
+# define DH_F_DH_CHECK_PARAMS_EX                          122
+# define DH_F_DH_CHECK_PUB_KEY_EX                         123
 # define DH_F_DH_CMS_DECRYPT                              114
 # define DH_F_DH_CMS_SET_PEERKEY                          115
 # define DH_F_DH_CMS_SET_SHARED_INFO                      116
@@ -34,6 +37,7 @@ int ERR_load_DH_strings(void);
 # define DH_F_DH_NEW_BY_NID                               104
 # define DH_F_DH_NEW_METHOD                               105
 # define DH_F_DH_PARAM_DECODE                             107
+# define DH_F_DH_PKEY_PUBLIC_CHECK                        124
 # define DH_F_DH_PRIV_DECODE                              110
 # define DH_F_DH_PRIV_ENCODE                              111
 # define DH_F_DH_PUB_DECODE                               108
@@ -50,17 +54,28 @@ int ERR_load_DH_strings(void);
 # define DH_R_BAD_GENERATOR                               101
 # define DH_R_BN_DECODE_ERROR                             109
 # define DH_R_BN_ERROR                                    106
+# define DH_R_CHECK_INVALID_J_VALUE                       115
+# define DH_R_CHECK_INVALID_Q_VALUE                       116
+# define DH_R_CHECK_PUBKEY_INVALID                        122
+# define DH_R_CHECK_PUBKEY_TOO_LARGE                      123
+# define DH_R_CHECK_PUBKEY_TOO_SMALL                      124
+# define DH_R_CHECK_P_NOT_PRIME                           117
+# define DH_R_CHECK_P_NOT_SAFE_PRIME                      118
+# define DH_R_CHECK_Q_NOT_PRIME                           119
 # define DH_R_DECODE_ERROR                                104
 # define DH_R_INVALID_PARAMETER_NAME                      110
 # define DH_R_INVALID_PARAMETER_NID                       114
 # define DH_R_INVALID_PUBKEY                              102
 # define DH_R_KDF_PARAMETER_ERROR                         112
 # define DH_R_KEYS_NOT_SET                                108
+# define DH_R_MISSING_PUBKEY                              125
 # define DH_R_MODULUS_TOO_LARGE                           103
+# define DH_R_NOT_SUITABLE_GENERATOR                      120
 # define DH_R_NO_PARAMETERS_SET                           107
 # define DH_R_NO_PRIVATE_VALUE                            100
 # define DH_R_PARAMETER_ENCODING_ERROR                    105
 # define DH_R_PEER_KEY_ERROR                              111
 # define DH_R_SHARED_INFO_ERROR                           113
+# define DH_R_UNABLE_TO_CHECK_GENERATOR                   121
 
 #endif
diff --git a/include/openssl/ecerr.h b/include/openssl/ecerr.h
index b04599a..bd09cb7 100644
--- a/include/openssl/ecerr.h
+++ b/include/openssl/ecerr.h
@@ -126,6 +126,7 @@ int ERR_load_EC_strings(void);
 # define EC_F_EC_KEY_SIMPLE_OCT2PRIV                      259
 # define EC_F_EC_KEY_SIMPLE_PRIV2OCT                      260
 # define EC_F_EC_PKEY_CHECK                               273
+# define EC_F_EC_PKEY_PARAM_CHECK                         274
 # define EC_F_EC_POINTS_MAKE_AFFINE                       136
 # define EC_F_EC_POINT_ADD                                112
 # define EC_F_EC_POINT_CMP                                113
diff --git a/include/openssl/evp.h b/include/openssl/evp.h
index e002d63..aaecc1b 100644
--- a/include/openssl/evp.h
+++ b/include/openssl/evp.h
@@ -1218,6 +1218,12 @@ void EVP_PKEY_asn1_set_siginf(EVP_PKEY_ASN1_METHOD *ameth,
 void EVP_PKEY_asn1_set_check(EVP_PKEY_ASN1_METHOD *ameth,
                              int (*pkey_check) (const EVP_PKEY *pk));
 
+void EVP_PKEY_asn1_set_public_check(EVP_PKEY_ASN1_METHOD *ameth,
+                                    int (*pkey_pub_check) (const EVP_PKEY *pk));
+
+void EVP_PKEY_asn1_set_param_check(EVP_PKEY_ASN1_METHOD *ameth,
+                                   int (*pkey_param_check) (const EVP_PKEY *pk));
+
 void EVP_PKEY_asn1_set_security_bits(EVP_PKEY_ASN1_METHOD *ameth,
                                      int (*pkey_security_bits) (const EVP_PKEY
                                                                 *pk));
@@ -1367,6 +1373,8 @@ int EVP_PKEY_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey);
 int EVP_PKEY_keygen_init(EVP_PKEY_CTX *ctx);
 int EVP_PKEY_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey);
 int EVP_PKEY_check(EVP_PKEY_CTX *ctx);
+int EVP_PKEY_public_check(EVP_PKEY_CTX *ctx);
+int EVP_PKEY_param_check(EVP_PKEY_CTX *ctx);
 
 void EVP_PKEY_CTX_set_cb(EVP_PKEY_CTX *ctx, EVP_PKEY_gen_cb *cb);
 EVP_PKEY_gen_cb *EVP_PKEY_CTX_get_cb(EVP_PKEY_CTX *ctx);
@@ -1468,6 +1476,12 @@ void EVP_PKEY_meth_set_ctrl(EVP_PKEY_METHOD *pmeth,
 void EVP_PKEY_meth_set_check(EVP_PKEY_METHOD *pmeth,
                              int (*check) (EVP_PKEY *pkey));
 
+void EVP_PKEY_meth_set_public_check(EVP_PKEY_METHOD *pmeth,
+                                    int (*check) (EVP_PKEY *pkey));
+
+void EVP_PKEY_meth_set_param_check(EVP_PKEY_METHOD *pmeth,
+                                   int (*check) (EVP_PKEY *pkey));
+
 void EVP_PKEY_meth_get_init(EVP_PKEY_METHOD *pmeth,
                             int (**pinit) (EVP_PKEY_CTX *ctx));
 
@@ -1563,6 +1577,12 @@ void EVP_PKEY_meth_get_ctrl(EVP_PKEY_METHOD *pmeth,
 void EVP_PKEY_meth_get_check(EVP_PKEY_METHOD *pmeth,
                              int (**pcheck) (EVP_PKEY *pkey));
 
+void EVP_PKEY_meth_get_public_check(EVP_PKEY_METHOD *pmeth,
+                                    int (**pcheck) (EVP_PKEY *pkey));
+
+void EVP_PKEY_meth_get_param_check(EVP_PKEY_METHOD *pmeth,
+                                   int (**pcheck) (EVP_PKEY *pkey));
+
 void EVP_add_alg_module(void);
 
 int ERR_load_EVP_strings(void);
diff --git a/include/openssl/evperr.h b/include/openssl/evperr.h
index a7a46ae..a870e43 100644
--- a/include/openssl/evperr.h
+++ b/include/openssl/evperr.h
@@ -83,6 +83,8 @@ int ERR_load_EVP_strings(void);
 # define EVP_F_EVP_PKEY_NEW                               106
 # define EVP_F_EVP_PKEY_PARAMGEN                          148
 # define EVP_F_EVP_PKEY_PARAMGEN_INIT                     149
+# define EVP_F_EVP_PKEY_PARAM_CHECK                       189
+# define EVP_F_EVP_PKEY_PUBLIC_CHECK                      190
 # define EVP_F_EVP_PKEY_SET1_ENGINE                       187
 # define EVP_F_EVP_PKEY_SIGN                              140
 # define EVP_F_EVP_PKEY_SIGN_INIT                         141
diff --git a/test/evp_extra_test.c b/test/evp_extra_test.c
index f49ca80..1e1fa17 100644
--- a/test/evp_extra_test.c
+++ b/test/evp_extra_test.c
@@ -283,6 +283,22 @@ static const unsigned char kExampleBadECKeyDER[] = {
     0xFF, 0xFF, 0xFF, 0xFF, 0xBC, 0xE6, 0xFA, 0xAD, 0xA7, 0x17, 0x9E, 0x84,
     0xF3, 0xB9, 0xCA, 0xC2, 0xFC, 0x63, 0x25, 0x51
 };
+
+/* prime256v1 */
+static const unsigned char kExampleECPubKeyDER[] = {
+    0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02,
+    0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03,
+    0x42, 0x00, 0x04, 0xba, 0xeb, 0x83, 0xfb, 0x3b, 0xb2, 0xff, 0x30, 0x53,
+    0xdb, 0xce, 0x32, 0xf2, 0xac, 0xae, 0x44, 0x0d, 0x3d, 0x13, 0x53, 0xb8,
+    0xd1, 0x68, 0x55, 0xde, 0x44, 0x46, 0x05, 0xa6, 0xc9, 0xd2, 0x04, 0xb7,
+    0xe3, 0xa2, 0x96, 0xc8, 0xb2, 0x5e, 0x22, 0x03, 0xd7, 0x03, 0x7a, 0x8b,
+    0x13, 0x5c, 0x42, 0x49, 0xc2, 0xab, 0x86, 0xd6, 0xac, 0x6b, 0x93, 0x20,
+    0x56, 0x6a, 0xc6, 0xc8, 0xa5, 0x0b, 0xe5
+};
+
+static const unsigned char pExampleECParamDER[] = {
+    0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07
+};
 #endif
 
 typedef struct APK_DATA_st {
@@ -290,6 +306,9 @@ typedef struct APK_DATA_st {
     size_t size;
     int evptype;
     int check;
+    int pub_check;
+    int param_check;
+    int type; /* 0 for private, 1 for public, 2 for params */
 } APK_DATA;
 
 static APK_DATA keydata[] = {
@@ -301,10 +320,14 @@ static APK_DATA keydata[] = {
 };
 
 static APK_DATA keycheckdata[] = {
-    {kExampleRSAKeyDER, sizeof(kExampleRSAKeyDER), EVP_PKEY_RSA, 1},
-    {kExampleBadRSAKeyDER, sizeof(kExampleBadRSAKeyDER), EVP_PKEY_RSA, 0},
+    {kExampleRSAKeyDER, sizeof(kExampleRSAKeyDER), EVP_PKEY_RSA, 1, -2, -2, 0},
+    {kExampleBadRSAKeyDER, sizeof(kExampleBadRSAKeyDER), EVP_PKEY_RSA,
+     0, -2, -2, 0},
 #ifndef OPENSSL_NO_EC
-    {kExampleECKeyDER, sizeof(kExampleECKeyDER), EVP_PKEY_EC, 1}
+    {kExampleECKeyDER, sizeof(kExampleECKeyDER), EVP_PKEY_EC, 1, 1, 1, 0},
+    /* group is also associated in our pub key */
+    {kExampleECPubKeyDER, sizeof(kExampleECPubKeyDER), EVP_PKEY_EC, 0, 1, 1, 1},
+    {pExampleECParamDER, sizeof(pExampleECParamDER), EVP_PKEY_EC, 0, 0, 1, 2}
 #endif
 };
 
@@ -458,6 +481,16 @@ static int pkey_custom_check(EVP_PKEY *pkey)
     return 0xbeef;
 }
 
+static int pkey_custom_pub_check(EVP_PKEY *pkey)
+{
+    return 0xbeef;
+}
+
+static int pkey_custom_param_check(EVP_PKEY *pkey)
+{
+    return 0xbeef;
+}
+
 static EVP_PKEY_METHOD *custom_pmeth;
 
 static int test_EVP_PKEY_check(int i)
@@ -465,6 +498,7 @@ static int test_EVP_PKEY_check(int i)
     int ret = 0;
     const unsigned char *p;
     EVP_PKEY *pkey = NULL;
+    EC_KEY *eckey = NULL;
     EVP_PKEY_CTX *ctx = NULL;
     EVP_PKEY_CTX *ctx2 = NULL;
     const APK_DATA *ak = &keycheckdata[i];
@@ -472,23 +506,44 @@ static int test_EVP_PKEY_check(int i)
     size_t input_len = ak->size;
     int expected_id = ak->evptype;
     int expected_check = ak->check;
+    int expected_pub_check = ak->pub_check;
+    int expected_param_check = ak->param_check;
+    int type = ak->type;
+    BIO *pubkey = NULL;
 
     p = input;
-    if (!TEST_ptr(pkey = d2i_AutoPrivateKey(NULL, &p, input_len))
-            || !TEST_ptr_eq(p, input + input_len)
-            || !TEST_int_eq(EVP_PKEY_id(pkey), expected_id))
+
+    if (type == 0 &&
+            (!TEST_ptr(pkey = d2i_AutoPrivateKey(NULL, &p, input_len))
+             || !TEST_ptr_eq(p, input + input_len)
+             || !TEST_int_eq(EVP_PKEY_id(pkey), expected_id)))
+        goto done;
+
+    if (type == 1 &&
+            (!TEST_ptr(pubkey = BIO_new_mem_buf(input, input_len))
+             || !TEST_ptr(eckey = d2i_EC_PUBKEY_bio(pubkey, NULL))
+             || !TEST_ptr(pkey = EVP_PKEY_new())
+             || !TEST_true(EVP_PKEY_assign_EC_KEY(pkey, eckey))))
+        goto done;
+
+    if (type == 2 &&
+            (!TEST_ptr(eckey = d2i_ECParameters(NULL, &p, input_len))
+             || !TEST_ptr_eq(p, input + input_len)
+             || !TEST_ptr(pkey = EVP_PKEY_new())
+             || !TEST_true(EVP_PKEY_assign_EC_KEY(pkey, eckey))))
         goto done;
 
     if (!TEST_ptr(ctx = EVP_PKEY_CTX_new(pkey, NULL)))
         goto done;
 
-    if (expected_check == 1) {
-        if (!TEST_int_eq(EVP_PKEY_check(ctx), 1))
-            goto done;
-    } else {
-        if (!TEST_int_ne(EVP_PKEY_check(ctx), 1))
-            goto done;
-    }
+    if (!TEST_int_eq(EVP_PKEY_check(ctx), expected_check))
+        goto done;
+
+    if (!TEST_int_eq(EVP_PKEY_public_check(ctx), expected_pub_check))
+        goto done;
+
+    if (!TEST_int_eq(EVP_PKEY_param_check(ctx), expected_param_check))
+        goto done;
 
     ctx2 = EVP_PKEY_CTX_new_id(0xdefaced, NULL);
     /* assign the pkey directly, as an internal test */
@@ -498,12 +553,19 @@ static int test_EVP_PKEY_check(int i)
     if (!TEST_int_eq(EVP_PKEY_check(ctx2), 0xbeef))
         goto done;
 
+    if (!TEST_int_eq(EVP_PKEY_public_check(ctx2), 0xbeef))
+        goto done;
+
+    if (!TEST_int_eq(EVP_PKEY_param_check(ctx2), 0xbeef))
+        goto done;
+
     ret = 1;
 
  done:
     EVP_PKEY_CTX_free(ctx);
     EVP_PKEY_CTX_free(ctx2);
     EVP_PKEY_free(pkey);
+    BIO_free(pubkey);
     return ret;
 }
 
@@ -519,6 +581,8 @@ int setup_tests(void)
     if (!TEST_ptr(custom_pmeth))
         return 0;
     EVP_PKEY_meth_set_check(custom_pmeth, pkey_custom_check);
+    EVP_PKEY_meth_set_public_check(custom_pmeth, pkey_custom_pub_check);
+    EVP_PKEY_meth_set_param_check(custom_pmeth, pkey_custom_param_check);
     if (!TEST_int_eq(EVP_PKEY_meth_add0(custom_pmeth), 1))
         return 0;
     ADD_ALL_TESTS(test_EVP_PKEY_check, OSSL_NELEM(keycheckdata));
diff --git a/util/libcrypto.num b/util/libcrypto.num
index 100e71f..8d9db31 100644
--- a/util/libcrypto.num
+++ b/util/libcrypto.num
@@ -4427,3 +4427,14 @@ EVP_sm4_ecb                             4371	1_1_1	EXIST::FUNCTION:SM4
 EVP_sm4_cfb128                          4372	1_1_1	EXIST::FUNCTION:SM4
 EVP_sm3                                 4373	1_1_1	EXIST::FUNCTION:SM3
 OCSP_resp_get0_signer                   4374	1_1_0h	EXIST::FUNCTION:OCSP
+EVP_PKEY_public_check                   4375	1_1_1	EXIST::FUNCTION:
+EVP_PKEY_param_check                    4376	1_1_1	EXIST::FUNCTION:
+EVP_PKEY_meth_set_public_check          4377	1_1_1	EXIST::FUNCTION:
+EVP_PKEY_meth_set_param_check           4378	1_1_1	EXIST::FUNCTION:
+EVP_PKEY_meth_get_public_check          4379	1_1_1	EXIST::FUNCTION:
+EVP_PKEY_meth_get_param_check           4380	1_1_1	EXIST::FUNCTION:
+EVP_PKEY_asn1_set_public_check          4381	1_1_1	EXIST::FUNCTION:
+EVP_PKEY_asn1_set_param_check           4382	1_1_1	EXIST::FUNCTION:
+DH_check_ex                             4383	1_1_1	EXIST::FUNCTION:DH
+DH_check_pub_key_ex                     4384	1_1_1	EXIST::FUNCTION:DH
+DH_check_params_ex                      4385	1_1_1	EXIST::FUNCTION:DH


More information about the openssl-commits mailing list