Support key check in EVP interface
authorPaul Yang <yang.yang@baishancloud.com>
Mon, 4 Sep 2017 14:02:59 +0000 (22:02 +0800)
committerRichard Levitte <levitte@openssl.org>
Wed, 13 Sep 2017 18:38:14 +0000 (20:38 +0200)
A new method is added to EVP_PKEY_METH as:

    int (*check) (EVP_PKEY_CTX *ctx);

and to EVP_PKEY_ASN1_METHOD as:

    int (*pkey_check) (EVP_PKEY_CTX *ctx);

This is used to check the validity of a specific key.

The order of calls is:
EVP_PKEY_check -> pmeth.check -> ameth.pkey_check.

Reviewed-by: Rich Salz <rsalz@openssl.org>
Reviewed-by: Richard Levitte <levitte@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/4337)

17 files changed:
apps/pkey.c
crypto/ec/ec_ameth.c
crypto/err/openssl.txt
crypto/evp/evp_err.c
crypto/evp/pmeth_gn.c
crypto/evp/pmeth_lib.c
crypto/include/internal/asn1_int.h
crypto/include/internal/evp_int.h
crypto/rsa/rsa_ameth.c
doc/man1/pkey.pod
doc/man3/EVP_PKEY_keygen.pod
doc/man3/EVP_PKEY_meth_new.pod
include/openssl/evp.h
include/openssl/evperr.h
test/build.info
test/evp_extra_test.c
util/libcrypto.num

index e8e32ba..06bdaa3 100644 (file)
@@ -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_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_TEXT, OPT_NOOUT, OPT_MD, OPT_TRADITIONAL, OPT_CHECK
 } OPTION_CHOICE;
 
 const OPTIONS pkey_options[] = {
 } OPTION_CHOICE;
 
 const OPTIONS pkey_options[] = {
@@ -41,6 +41,7 @@ const OPTIONS pkey_options[] = {
 #ifndef OPENSSL_NO_ENGINE
     {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
 #endif
 #ifndef OPENSSL_NO_ENGINE
     {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
 #endif
+    {"check", OPT_CHECK, '-', "Check key consistency"},
     {NULL}
 };
 
     {NULL}
 };
 
@@ -55,7 +56,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;
     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;
+    int private = 0, traditional = 0, check = 0;
 
     prog = opt_init(argc, argv, pkey_options);
     while ((o = opt_next()) != OPT_EOF) {
 
     prog = opt_init(argc, argv, pkey_options);
     while ((o = opt_next()) != OPT_EOF) {
@@ -110,6 +111,9 @@ int pkey_main(int argc, char **argv)
         case OPT_TRADITIONAL:
             traditional = 1;
             break;
         case OPT_TRADITIONAL:
             traditional = 1;
             break;
+        case OPT_CHECK:
+            check = 1;
+            break;
         case OPT_MD:
             if (!opt_cipher(opt_unknown(), &cipher))
                 goto opthelp;
         case OPT_MD:
             if (!opt_cipher(opt_unknown(), &cipher))
                 goto opthelp;
@@ -139,6 +143,38 @@ int pkey_main(int argc, char **argv)
     if (pkey == NULL)
         goto end;
 
     if (pkey == NULL)
         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_check(ctx);
+
+        if (r == 1) {
+            BIO_printf(out, "Key is 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, "Key is invalid\n");
+
+            while ((err = ERR_peek_error()) != 0) {
+                BIO_printf(out, "Detailed error: %s\n",
+                           ERR_reason_error_string(err));
+                ERR_get_error(); /* remove e from error stack */
+            }
+        }
+        EVP_PKEY_CTX_free(ctx);
+    }
+
     if (!noout) {
         if (outformat == FORMAT_PEM) {
             if (pubout) {
     if (!noout) {
         if (outformat == FORMAT_PEM) {
             if (pubout) {
index b66adf2..ecf1a02 100644 (file)
@@ -520,6 +520,19 @@ 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_KEY_CHECK_KEY, EC_R_MISSING_PRIVATE_KEY);
+        return 0;
+    }
+
+    return EC_KEY_check_key(eckey);
+}
+
 const EVP_PKEY_ASN1_METHOD eckey_asn1_meth = {
     EVP_PKEY_EC,
     EVP_PKEY_EC,
 const EVP_PKEY_ASN1_METHOD eckey_asn1_meth = {
     EVP_PKEY_EC,
     EVP_PKEY_EC,
@@ -551,7 +564,11 @@ const EVP_PKEY_ASN1_METHOD eckey_asn1_meth = {
     int_ec_free,
     ec_pkey_ctrl,
     old_ec_priv_decode,
     int_ec_free,
     ec_pkey_ctrl,
     old_ec_priv_decode,
-    old_ec_priv_encode
+    old_ec_priv_encode,
+
+    0, 0, 0,
+
+    ec_pkey_check
 };
 
 int EC_KEY_print(BIO *bp, const EC_KEY *x, int off)
 };
 
 int EC_KEY_print(BIO *bp, const EC_KEY *x, int off)
index 253e0ab..b05d459 100644 (file)
@@ -661,6 +661,7 @@ EVP_F_EVP_PBE_CIPHERINIT:116:EVP_PBE_CipherInit
 EVP_F_EVP_PBE_SCRYPT:181:EVP_PBE_scrypt
 EVP_F_EVP_PKCS82PKEY:111:EVP_PKCS82PKEY
 EVP_F_EVP_PKEY2PKCS8:113:EVP_PKEY2PKCS8
 EVP_F_EVP_PBE_SCRYPT:181:EVP_PBE_scrypt
 EVP_F_EVP_PKCS82PKEY:111:EVP_PKCS82PKEY
 EVP_F_EVP_PKEY2PKCS8:113:EVP_PKEY2PKCS8
+EVP_F_EVP_PKEY_CHECK:186:EVP_PKEY_check
 EVP_F_EVP_PKEY_COPY_PARAMETERS:103:EVP_PKEY_copy_parameters
 EVP_F_EVP_PKEY_CTX_CTRL:137:EVP_PKEY_CTX_ctrl
 EVP_F_EVP_PKEY_CTX_CTRL_STR:150:EVP_PKEY_CTX_ctrl_str
 EVP_F_EVP_PKEY_COPY_PARAMETERS:103:EVP_PKEY_copy_parameters
 EVP_F_EVP_PKEY_CTX_CTRL:137:EVP_PKEY_CTX_ctrl
 EVP_F_EVP_PKEY_CTX_CTRL_STR:150:EVP_PKEY_CTX_ctrl_str
index c816196..cc32a3b 100644 (file)
@@ -55,6 +55,7 @@ static const ERR_STRING_DATA EVP_str_functs[] = {
     {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PBE_SCRYPT, 0), "EVP_PBE_scrypt"},
     {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKCS82PKEY, 0), "EVP_PKCS82PKEY"},
     {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY2PKCS8, 0), "EVP_PKEY2PKCS8"},
     {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PBE_SCRYPT, 0), "EVP_PBE_scrypt"},
     {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKCS82PKEY, 0), "EVP_PKCS82PKEY"},
     {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY2PKCS8, 0), "EVP_PKEY2PKCS8"},
+    {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_CHECK, 0), "EVP_PKEY_check"},
     {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_COPY_PARAMETERS, 0),
      "EVP_PKEY_copy_parameters"},
     {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_CTX_CTRL, 0), "EVP_PKEY_CTX_ctrl"},
     {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_COPY_PARAMETERS, 0),
      "EVP_PKEY_copy_parameters"},
     {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_CTX_CTRL, 0), "EVP_PKEY_CTX_ctrl"},
index 6adc3a9..1a927a8 100644 (file)
@@ -13,6 +13,7 @@
 #include <openssl/objects.h>
 #include <openssl/evp.h>
 #include "internal/bn_int.h"
 #include <openssl/objects.h>
 #include <openssl/evp.h>
 #include "internal/bn_int.h"
+#include "internal/asn1_int.h"
 #include "internal/evp_int.h"
 
 int EVP_PKEY_paramgen_init(EVP_PKEY_CTX *ctx)
 #include "internal/evp_int.h"
 
 int EVP_PKEY_paramgen_init(EVP_PKEY_CTX *ctx)
@@ -167,3 +168,26 @@ EVP_PKEY *EVP_PKEY_new_mac_key(int type, ENGINE *e,
     EVP_PKEY_CTX_free(mac_ctx);
     return mac_key;
 }
     EVP_PKEY_CTX_free(mac_ctx);
     return mac_key;
 }
+
+int EVP_PKEY_check(EVP_PKEY_CTX *ctx)
+{
+    EVP_PKEY *pkey = ctx->pkey;
+
+    if (pkey == NULL) {
+        EVPerr(EVP_F_EVP_PKEY_CHECK, EVP_R_NO_KEY_SET);
+        return 0;
+    }
+
+    /* call customized check function first */
+    if (ctx->pmeth->check != NULL)
+        return ctx->pmeth->check(pkey);
+
+    /* use default check function in ameth */
+    if (pkey->ameth == NULL || pkey->ameth->pkey_check == NULL) {
+        EVPerr(EVP_F_EVP_PKEY_CHECK,
+               EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+        return -2;
+    }
+
+    return pkey->ameth->pkey_check(pkey);
+}
index 71ec099..c62bd81 100644 (file)
@@ -219,6 +219,8 @@ void EVP_PKEY_meth_copy(EVP_PKEY_METHOD *dst, const EVP_PKEY_METHOD *src)
 
     dst->ctrl = src->ctrl;
     dst->ctrl_str = src->ctrl_str;
 
     dst->ctrl = src->ctrl;
     dst->ctrl_str = src->ctrl_str;
+
+    dst->check = src->check;
 }
 
 void EVP_PKEY_meth_free(EVP_PKEY_METHOD *pmeth)
 }
 
 void EVP_PKEY_meth_free(EVP_PKEY_METHOD *pmeth)
@@ -603,6 +605,12 @@ void EVP_PKEY_meth_set_ctrl(EVP_PKEY_METHOD *pmeth,
     pmeth->ctrl_str = ctrl_str;
 }
 
     pmeth->ctrl_str = ctrl_str;
 }
 
+void EVP_PKEY_meth_set_check(EVP_PKEY_METHOD *pmeth,
+                             int (*check) (EVP_PKEY *pkey))
+{
+    pmeth->check = check;
+}
+
 void EVP_PKEY_meth_get_init(EVP_PKEY_METHOD *pmeth,
                             int (**pinit) (EVP_PKEY_CTX *ctx))
 {
 void EVP_PKEY_meth_get_init(EVP_PKEY_METHOD *pmeth,
                             int (**pinit) (EVP_PKEY_CTX *ctx))
 {
@@ -769,3 +777,10 @@ void EVP_PKEY_meth_get_ctrl(EVP_PKEY_METHOD *pmeth,
     if (pctrl_str)
         *pctrl_str = pmeth->ctrl_str;
 }
     if (pctrl_str)
         *pctrl_str = pmeth->ctrl_str;
 }
+
+void EVP_PKEY_meth_get_check(EVP_PKEY_METHOD *pmeth,
+                             int (**pcheck) (EVP_PKEY *pkey))
+{
+    if (*pcheck)
+        *pcheck = pmeth->check;
+}
index 8ff919c..d8b6f45 100644 (file)
@@ -54,6 +54,8 @@ struct evp_pkey_asn1_method_st {
                       ASN1_BIT_STRING *sig);
     int (*siginf_set) (X509_SIG_INFO *siginf, const X509_ALGOR *alg,
                        const ASN1_STRING *sig);
                       ASN1_BIT_STRING *sig);
     int (*siginf_set) (X509_SIG_INFO *siginf, const X509_ALGOR *alg,
                        const ASN1_STRING *sig);
+    /* Check */
+    int (*pkey_check) (const EVP_PKEY *pk);
 } /* EVP_PKEY_ASN1_METHOD */ ;
 
 DEFINE_STACK_OF_CONST(EVP_PKEY_ASN1_METHOD)
 } /* EVP_PKEY_ASN1_METHOD */ ;
 
 DEFINE_STACK_OF_CONST(EVP_PKEY_ASN1_METHOD)
index be1b9be..b9558a6 100644 (file)
@@ -75,6 +75,7 @@ struct evp_pkey_method_st {
     int (*digestverify) (EVP_MD_CTX *ctx, const unsigned char *sig,
                          size_t siglen, const unsigned char *tbs,
                          size_t tbslen);
     int (*digestverify) (EVP_MD_CTX *ctx, const unsigned char *sig,
                          size_t siglen, const unsigned char *tbs,
                          size_t tbslen);
+    int (*check) (EVP_PKEY *pkey);
 } /* EVP_PKEY_METHOD */ ;
 
 DEFINE_STACK_OF_CONST(EVP_PKEY_METHOD)
 } /* EVP_PKEY_METHOD */ ;
 
 DEFINE_STACK_OF_CONST(EVP_PKEY_METHOD)
index 42138ce..97a37ba 100644 (file)
@@ -984,6 +984,11 @@ static int rsa_cms_encrypt(CMS_RecipientInfo *ri)
 }
 #endif
 
 }
 #endif
 
+static int rsa_pkey_check(const EVP_PKEY *pkey)
+{
+    return RSA_check_key_ex(pkey->pkey.rsa, NULL);
+}
+
 const EVP_PKEY_ASN1_METHOD rsa_asn1_meths[2] = {
     {
      EVP_PKEY_RSA,
 const EVP_PKEY_ASN1_METHOD rsa_asn1_meths[2] = {
     {
      EVP_PKEY_RSA,
@@ -1015,7 +1020,8 @@ const EVP_PKEY_ASN1_METHOD rsa_asn1_meths[2] = {
      old_rsa_priv_encode,
      rsa_item_verify,
      rsa_item_sign,
      old_rsa_priv_encode,
      rsa_item_verify,
      rsa_item_sign,
-     rsa_sig_info_set
+     rsa_sig_info_set,
+     rsa_pkey_check
     },
 
     {
     },
 
     {
@@ -1053,4 +1059,6 @@ const EVP_PKEY_ASN1_METHOD rsa_pss_asn1_meth = {
      0, 0,
      rsa_item_verify,
      rsa_item_sign,
      0, 0,
      rsa_item_verify,
      rsa_item_sign,
+     0,
+     rsa_pkey_check
 };
 };
index 3c277a5..d6b0db4 100644 (file)
@@ -22,6 +22,7 @@ B<openssl> B<pkey>
 [B<-pubin>]
 [B<-pubout>]
 [B<-engine id>]
 [B<-pubin>]
 [B<-pubout>]
 [B<-engine id>]
+[B<-check>]
 
 =head1 DESCRIPTION
 
 
 =head1 DESCRIPTION
 
@@ -110,6 +111,11 @@ 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.
 
 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 consistency of a key pair for both public and private
+components.
+
 =back
 
 =head1 EXAMPLES
 =back
 
 =head1 EXAMPLES
index b7f2128..3687f9b 100644 (file)
@@ -6,8 +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_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
-- key and parameter generation functions
+EVP_PKEY_gen_cb, EVP_PKEY_check
+- key and parameter generation and check functions
 
 =head1 SYNOPSIS
 
 
 =head1 SYNOPSIS
 
@@ -28,6 +28,8 @@ EVP_PKEY_gen_cb
  void EVP_PKEY_CTX_set_app_data(EVP_PKEY_CTX *ctx, void *data);
  void *EVP_PKEY_CTX_get_app_data(EVP_PKEY_CTX *ctx);
 
  void EVP_PKEY_CTX_set_app_data(EVP_PKEY_CTX *ctx, void *data);
  void *EVP_PKEY_CTX_get_app_data(EVP_PKEY_CTX *ctx);
 
+ int EVP_PKEY_check(EVP_PKEY_CTX *ctx);
+
 =head1 DESCRIPTION
 
 The EVP_PKEY_keygen_init() function initializes a public key algorithm
 =head1 DESCRIPTION
 
 The EVP_PKEY_keygen_init() function initializes a public key algorithm
@@ -58,6 +60,10 @@ and retrieve an opaque pointer. This can be used to set some application
 defined value which can be retrieved in the callback: for example a handle
 which is used to update a "progress dialog".
 
 defined value which can be retrieved in the callback: for example a handle
 which is used to update a "progress dialog".
 
+EVP_PKEY_check() validates 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
 =head1 NOTES
 
 After the call to EVP_PKEY_keygen_init() or EVP_PKEY_paramgen_init() algorithm
@@ -89,6 +95,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.
 
 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.
+
 =head1 EXAMPLES
 
 Generate a 2048 bit RSA key:
 =head1 EXAMPLES
 
 Generate a 2048 bit RSA key:
@@ -171,7 +180,7 @@ These functions were first added to OpenSSL 1.0.0.
 
 =head1 COPYRIGHT
 
 
 =head1 COPYRIGHT
 
-Copyright 2006-2016 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2006-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
 
 Licensed under the OpenSSL license (the "License").  You may not use
 this file except in compliance with the License.  You can obtain a copy
index 041492a..acff78a 100644 (file)
@@ -8,12 +8,12 @@ EVP_PKEY_meth_set_init, EVP_PKEY_meth_set_copy, EVP_PKEY_meth_set_cleanup,
 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_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_derive, EVP_PKEY_meth_set_ctrl, EVP_PKEY_meth_set_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_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_derive, EVP_PKEY_meth_get_ctrl, EVP_PKEY_meth_get_check
 - manipulating EVP_PKEY_METHOD structure
 
 =head1 SYNOPSIS
 - manipulating EVP_PKEY_METHOD structure
 
 =head1 SYNOPSIS
@@ -106,6 +106,8 @@ EVP_PKEY_meth_get_derive, EVP_PKEY_meth_get_ctrl
                              int (*ctrl_str) (EVP_PKEY_CTX *ctx,
                                               const char *type,
                                               const char *value));
                              int (*ctrl_str) (EVP_PKEY_CTX *ctx,
                                               const char *type,
                                               const char *value));
+ void EVP_PKEY_meth_set_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));
 
  void EVP_PKEY_meth_get_init(EVP_PKEY_METHOD *pmeth,
                              int (**pinit) (EVP_PKEY_CTX *ctx));
@@ -185,6 +187,8 @@ EVP_PKEY_meth_get_derive, EVP_PKEY_meth_get_ctrl
                              int (**pctrl_str) (EVP_PKEY_CTX *ctx,
                                                 const char *type,
                                                 const char *value));
                              int (**pctrl_str) (EVP_PKEY_CTX *ctx,
                                                 const char *type,
                                                 const char *value));
+ void EVP_PKEY_meth_get_check(EVP_PKEY_METHOD *pmeth,
+                              int (**pcheck) (EVP_PKEY *pkey));
 
 =head1 DESCRIPTION
 
 
 =head1 DESCRIPTION
 
@@ -309,6 +313,11 @@ The digestsign() and digestverify() methods are used to generate or verify
 a signature in a one-shot mode. They could be called by L<EVP_DigetSign(3)>
 and L<EVP_DigestVerify(3)>.
 
 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);
+
+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)>.
+
 =head2 Functions
 
 EVP_PKEY_meth_new() creates and returns a new B<EVP_PKEY_METHOD> object,
 =head2 Functions
 
 EVP_PKEY_meth_new() creates and returns a new B<EVP_PKEY_METHOD> object,
index a1e2318..2c01bdf 100644 (file)
@@ -1342,6 +1342,7 @@ int EVP_PKEY_paramgen_init(EVP_PKEY_CTX *ctx);
 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_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);
 
 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);
 
 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);
@@ -1440,6 +1441,9 @@ void EVP_PKEY_meth_set_ctrl(EVP_PKEY_METHOD *pmeth,
                                              const char *type,
                                              const char *value));
 
                                              const char *type,
                                              const char *value));
 
+void EVP_PKEY_meth_set_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));
 
 void EVP_PKEY_meth_get_init(EVP_PKEY_METHOD *pmeth,
                             int (**pinit) (EVP_PKEY_CTX *ctx));
 
@@ -1532,6 +1536,9 @@ void EVP_PKEY_meth_get_ctrl(EVP_PKEY_METHOD *pmeth,
                                                const char *type,
                                                const char *value));
 
                                                const char *type,
                                                const char *value));
 
+void EVP_PKEY_meth_get_check(EVP_PKEY_METHOD *pmeth,
+                             int (**pcheck) (EVP_PKEY *pkey));
+
 void EVP_add_alg_module(void);
 
 int ERR_load_EVP_strings(void);
 void EVP_add_alg_module(void);
 
 int ERR_load_EVP_strings(void);
index cbb18bd..9bb2bca 100644 (file)
@@ -55,6 +55,7 @@ int ERR_load_EVP_strings(void);
 # define EVP_F_EVP_PBE_SCRYPT                             181
 # define EVP_F_EVP_PKCS82PKEY                             111
 # define EVP_F_EVP_PKEY2PKCS8                             113
 # define EVP_F_EVP_PBE_SCRYPT                             181
 # define EVP_F_EVP_PKCS82PKEY                             111
 # define EVP_F_EVP_PKEY2PKCS8                             113
+# define EVP_F_EVP_PKEY_CHECK                             186
 # define EVP_F_EVP_PKEY_COPY_PARAMETERS                   103
 # define EVP_F_EVP_PKEY_CTX_CTRL                          137
 # define EVP_F_EVP_PKEY_CTX_CTRL_STR                      150
 # define EVP_F_EVP_PKEY_COPY_PARAMETERS                   103
 # define EVP_F_EVP_PKEY_CTX_CTRL                          137
 # define EVP_F_EVP_PKEY_CTX_CTRL_STR                      150
index f1f26af..06e77f7 100644 (file)
@@ -157,7 +157,7 @@ INCLUDE_MAIN___test_libtestutil_OLB = /INCLUDE=MAIN
   DEPEND[evp_test]=../libcrypto libtestutil.a
 
   SOURCE[evp_extra_test]=evp_extra_test.c
   DEPEND[evp_test]=../libcrypto libtestutil.a
 
   SOURCE[evp_extra_test]=evp_extra_test.c
-  INCLUDE[evp_extra_test]=.. ../include
+  INCLUDE[evp_extra_test]=.. ../include ../crypto/include
   DEPEND[evp_extra_test]=../libcrypto libtestutil.a
 
   SOURCE[igetest]=igetest.c
   DEPEND[evp_extra_test]=../libcrypto libtestutil.a
 
   SOURCE[igetest]=igetest.c
index e3fab29..221f9a6 100644 (file)
@@ -17,6 +17,7 @@
 #include <openssl/x509.h>
 #include "testutil.h"
 #include "internal/nelem.h"
 #include <openssl/x509.h>
 #include "testutil.h"
 #include "internal/nelem.h"
+#include "internal/evp_int.h"
 
 /*
  * kExampleRSAKeyDER is an RSA private key in ASN.1, DER format. Of course, you
 
 /*
  * kExampleRSAKeyDER is an RSA private key in ASN.1, DER format. Of course, you
@@ -76,6 +77,102 @@ static const unsigned char kExampleRSAKeyDER[] = {
     0x2d, 0x86, 0x9d, 0xa5, 0x20, 0x1b, 0xe5, 0xdf,
 };
 
     0x2d, 0x86, 0x9d, 0xa5, 0x20, 0x1b, 0xe5, 0xdf,
 };
 
+/*
+ * kExampleBadRSAKeyDER is an RSA private key in ASN.1, DER format. The private
+ * components are not correct.
+ */
+static const unsigned char kExampleBadRSAKeyDER[] = {
+    0x30, 0x82, 0x04, 0x27, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01, 0x01, 0x00,
+    0xa6, 0x1a, 0x1e, 0x6e, 0x7b, 0xee, 0xc6, 0x89, 0x66, 0xe7, 0x93, 0xef,
+    0x54, 0x12, 0x68, 0xea, 0xbf, 0x86, 0x2f, 0xdd, 0xd2, 0x79, 0xb8, 0xa9,
+    0x6e, 0x03, 0xc2, 0xa3, 0xb9, 0xa3, 0xe1, 0x4b, 0x2a, 0xb3, 0xf8, 0xb4,
+    0xcd, 0xea, 0xbe, 0x24, 0xa6, 0x57, 0x5b, 0x83, 0x1f, 0x0f, 0xf2, 0xd3,
+    0xb7, 0xac, 0x7e, 0xd6, 0x8e, 0x6e, 0x1e, 0xbf, 0xb8, 0x73, 0x8c, 0x05,
+    0x56, 0xe6, 0x35, 0x1f, 0xe9, 0x04, 0x0b, 0x09, 0x86, 0x7d, 0xf1, 0x26,
+    0x08, 0x99, 0xad, 0x7b, 0xc8, 0x4d, 0x94, 0xb0, 0x0b, 0x8b, 0x38, 0xa0,
+    0x5c, 0x62, 0xa0, 0xab, 0xd3, 0x8f, 0xd4, 0x09, 0x60, 0x72, 0x1e, 0x33,
+    0x50, 0x80, 0x6e, 0x22, 0xa6, 0x77, 0x57, 0x6b, 0x9a, 0x33, 0x21, 0x66,
+    0x87, 0x6e, 0x21, 0x7b, 0xc7, 0x24, 0x0e, 0xd8, 0x13, 0xdf, 0x83, 0xde,
+    0xcd, 0x40, 0x58, 0x1d, 0x84, 0x86, 0xeb, 0xb8, 0x12, 0x4e, 0xd2, 0xfa,
+    0x80, 0x1f, 0xe4, 0xe7, 0x96, 0x29, 0xb8, 0xcc, 0xce, 0x66, 0x6d, 0x53,
+    0xca, 0xb9, 0x5a, 0xd7, 0xf6, 0x84, 0x6c, 0x2d, 0x9a, 0x1a, 0x14, 0x1c,
+    0x4e, 0x93, 0x39, 0xba, 0x74, 0xed, 0xed, 0x87, 0x87, 0x5e, 0x48, 0x75,
+    0x36, 0xf0, 0xbc, 0x34, 0xfb, 0x29, 0xf9, 0x9f, 0x96, 0x5b, 0x0b, 0xa7,
+    0x54, 0x30, 0x51, 0x29, 0x18, 0x5b, 0x7d, 0xac, 0x0f, 0xd6, 0x5f, 0x7c,
+    0xf8, 0x98, 0x8c, 0xd8, 0x86, 0x62, 0xb3, 0xdc, 0xff, 0x0f, 0xff, 0x7a,
+    0xaf, 0x5c, 0x4c, 0x61, 0x49, 0x2e, 0xc8, 0x95, 0x86, 0xc4, 0x0e, 0x87,
+    0xfc, 0x1d, 0xcf, 0x8b, 0x7c, 0x61, 0xf6, 0xd8, 0xd0, 0x69, 0xf6, 0xcd,
+    0x8a, 0x8c, 0xf6, 0x62, 0xa2, 0x56, 0xa9, 0xe3, 0xd1, 0xcf, 0x4d, 0xa0,
+    0xf6, 0x2d, 0x20, 0x0a, 0x04, 0xb7, 0xa2, 0xf7, 0xb5, 0x99, 0x47, 0x18,
+    0x56, 0x85, 0x87, 0xc7, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02, 0x82, 0x01,
+    0x01, 0x00, 0x99, 0x41, 0x38, 0x1a, 0xd0, 0x96, 0x7a, 0xf0, 0x83, 0xd5,
+    0xdf, 0x94, 0xce, 0x89, 0x3d, 0xec, 0x7a, 0x52, 0x21, 0x10, 0x16, 0x06,
+    0xe0, 0xee, 0xd2, 0xe6, 0xfd, 0x4b, 0x7b, 0x19, 0x4d, 0xe1, 0xc0, 0xc0,
+    0xd5, 0x14, 0x5d, 0x79, 0xdd, 0x7e, 0x8b, 0x4b, 0xc6, 0xcf, 0xb0, 0x75,
+    0x52, 0xa3, 0x2d, 0xb1, 0x26, 0x46, 0x68, 0x9c, 0x0a, 0x1a, 0xf2, 0xe1,
+    0x09, 0xac, 0x53, 0x85, 0x8c, 0x36, 0xa9, 0x14, 0x65, 0xea, 0xa0, 0x00,
+    0xcb, 0xe3, 0x3f, 0xc4, 0x2b, 0x61, 0x2e, 0x6b, 0x06, 0x69, 0x77, 0xfd,
+    0x38, 0x7e, 0x1d, 0x3f, 0x92, 0xe7, 0x77, 0x08, 0x19, 0xa7, 0x9d, 0x29,
+    0x2d, 0xdc, 0x42, 0xc6, 0x7c, 0xd7, 0xd3, 0xa8, 0x01, 0x2c, 0xf2, 0xd5,
+    0x82, 0x57, 0xcb, 0x55, 0x3d, 0xe7, 0xaa, 0xd2, 0x06, 0x30, 0x30, 0x05,
+    0xe6, 0xf2, 0x47, 0x86, 0xba, 0xc6, 0x61, 0x64, 0xeb, 0x4f, 0x2a, 0x5e,
+    0x07, 0x29, 0xe0, 0x96, 0xb2, 0x43, 0xff, 0x5f, 0x1a, 0x54, 0x16, 0xcf,
+    0xb5, 0x56, 0x5c, 0xa0, 0x9b, 0x0c, 0xfd, 0xb3, 0xd2, 0xe3, 0x79, 0x1d,
+    0x21, 0xe2, 0xd6, 0x13, 0xc4, 0x74, 0xa6, 0xf5, 0x8e, 0x8e, 0x81, 0xbb,
+    0xb4, 0xad, 0x8a, 0xf0, 0x93, 0x0a, 0xd8, 0x0a, 0x42, 0x36, 0xbc, 0xe5,
+    0x26, 0x2a, 0x0d, 0x5d, 0x57, 0x13, 0xc5, 0x4e, 0x2f, 0x12, 0x0e, 0xef,
+    0xa7, 0x81, 0x1e, 0xc3, 0xa5, 0xdb, 0xc9, 0x24, 0xeb, 0x1a, 0xa1, 0xf9,
+    0xf6, 0xa1, 0x78, 0x98, 0x93, 0x77, 0x42, 0x45, 0x03, 0xe2, 0xc9, 0xa2,
+    0xfe, 0x2d, 0x77, 0xc8, 0xc6, 0xac, 0x9b, 0x98, 0x89, 0x6d, 0x9a, 0xe7,
+    0x61, 0x63, 0xb7, 0xf2, 0xec, 0xd6, 0xb1, 0xa1, 0x6e, 0x0a, 0x1a, 0xff,
+    0xfd, 0x43, 0x28, 0xc3, 0x0c, 0xdc, 0xf2, 0x47, 0x4f, 0x27, 0xaa, 0x99,
+    0x04, 0x8e, 0xac, 0xe8, 0x7c, 0x01, 0x02, 0x04, 0x12, 0x34, 0x56, 0x78,
+    0x02, 0x81, 0x81, 0x00, 0xca, 0x69, 0xe5, 0xbb, 0x3a, 0x90, 0x82, 0xcb,
+    0x82, 0x50, 0x2f, 0x29, 0xe2, 0x76, 0x6a, 0x57, 0x55, 0x45, 0x4e, 0x35,
+    0x18, 0x61, 0xe0, 0x12, 0x70, 0xc0, 0xab, 0xc7, 0x80, 0xa2, 0xd4, 0x46,
+    0x34, 0x03, 0xa0, 0x19, 0x26, 0x23, 0x9e, 0xef, 0x1a, 0xcb, 0x75, 0xd6,
+    0xba, 0x81, 0xf4, 0x7e, 0x52, 0xe5, 0x2a, 0xe8, 0xf1, 0x49, 0x6c, 0x0f,
+    0x1a, 0xa0, 0xf9, 0xc6, 0xe7, 0xec, 0x60, 0xe4, 0xcb, 0x2a, 0xb5, 0x56,
+    0xe9, 0x9c, 0xcd, 0x19, 0x75, 0x92, 0xb1, 0x66, 0xce, 0xc3, 0xd9, 0x3d,
+    0x11, 0xcb, 0xc4, 0x09, 0xce, 0x1e, 0x30, 0xba, 0x2f, 0x60, 0x60, 0x55,
+    0x8d, 0x02, 0xdc, 0x5d, 0xaf, 0xf7, 0x52, 0x31, 0x17, 0x07, 0x53, 0x20,
+    0x33, 0xad, 0x8c, 0xd5, 0x2f, 0x5a, 0xd0, 0x57, 0xd7, 0xd1, 0x80, 0xd6,
+    0x3a, 0x9b, 0x04, 0x4f, 0x35, 0xbf, 0xe7, 0xd5, 0xbc, 0x8f, 0xd4, 0x81,
+    0x02, 0x81, 0x81, 0x00, 0xc0, 0x9f, 0xf8, 0xcd, 0xf7, 0x3f, 0x26, 0x8a,
+    0x3d, 0x4d, 0x2b, 0x0c, 0x01, 0xd0, 0xa2, 0xb4, 0x18, 0xfe, 0xf7, 0x5e,
+    0x2f, 0x06, 0x13, 0xcd, 0x63, 0xaa, 0x12, 0xa9, 0x24, 0x86, 0xe3, 0xf3,
+    0x7b, 0xda, 0x1a, 0x3c, 0xb1, 0x38, 0x80, 0x80, 0xef, 0x64, 0x64, 0xa1,
+    0x9b, 0xfe, 0x76, 0x63, 0x8e, 0x83, 0xd2, 0xd9, 0xb9, 0x86, 0xb0, 0xe6,
+    0xa6, 0x0c, 0x7e, 0xa8, 0x84, 0x90, 0x98, 0x0c, 0x1e, 0xf3, 0x14, 0x77,
+    0xe0, 0x5f, 0x81, 0x08, 0x11, 0x8f, 0xa6, 0x23, 0xc4, 0xba, 0xc0, 0x8a,
+    0xe4, 0xc6, 0xe3, 0x5c, 0xbe, 0xc5, 0xec, 0x2c, 0xb9, 0xd8, 0x8c, 0x4d,
+    0x1a, 0x9d, 0xe7, 0x7c, 0x85, 0x4c, 0x0d, 0x71, 0x4e, 0x72, 0x33, 0x1b,
+    0xfe, 0xa9, 0x17, 0x72, 0x76, 0x56, 0x9d, 0x74, 0x7e, 0x52, 0x67, 0x9a,
+    0x87, 0x9a, 0xdb, 0x30, 0xde, 0xe4, 0x49, 0x28, 0x3b, 0xd2, 0x67, 0xaf,
+    0x02, 0x81, 0x81, 0x00, 0x89, 0x74, 0x9a, 0x8e, 0xa7, 0xb9, 0xa5, 0x28,
+    0xc0, 0x68, 0xe5, 0x6e, 0x63, 0x1c, 0x99, 0x20, 0x8f, 0x86, 0x8e, 0x12,
+    0x9e, 0x69, 0x30, 0xfa, 0x34, 0xd9, 0x92, 0x8d, 0xdb, 0x7c, 0x37, 0xfd,
+    0x28, 0xab, 0x61, 0x98, 0x52, 0x7f, 0x14, 0x1a, 0x39, 0xae, 0xfb, 0x6a,
+    0x03, 0xa3, 0xe6, 0xbd, 0xb6, 0x5b, 0x6b, 0xe5, 0x5e, 0x9d, 0xc6, 0xa5,
+    0x07, 0x27, 0x54, 0x17, 0xd0, 0x3d, 0x84, 0x9b, 0x3a, 0xa0, 0xd9, 0x1e,
+    0x99, 0x6c, 0x63, 0x17, 0xab, 0xf1, 0x1f, 0x49, 0xba, 0x95, 0xe3, 0x3b,
+    0x86, 0x8f, 0x42, 0xa4, 0x89, 0xf5, 0x94, 0x8f, 0x8b, 0x46, 0xbe, 0x84,
+    0xba, 0x4a, 0xbc, 0x0d, 0x5f, 0x46, 0xeb, 0xe8, 0xec, 0x43, 0x8c, 0x1e,
+    0xad, 0x19, 0x69, 0x2f, 0x08, 0x86, 0x7a, 0x3f, 0x7d, 0x0f, 0x07, 0x97,
+    0xf3, 0x9a, 0x7b, 0xb5, 0xb2, 0xc1, 0x8c, 0x95, 0x68, 0x04, 0xa0, 0x81,
+    0x02, 0x81, 0x80, 0x4e, 0xbf, 0x7e, 0x1b, 0xcb, 0x13, 0x61, 0x75, 0x3b,
+    0xdb, 0x59, 0x5f, 0xb1, 0xd4, 0xb8, 0xeb, 0x9e, 0x73, 0xb5, 0xe7, 0xf6,
+    0x89, 0x3d, 0x1c, 0xda, 0xf0, 0x36, 0xff, 0x35, 0xbd, 0x1e, 0x0b, 0x74,
+    0xe3, 0x9e, 0xf0, 0xf2, 0xf7, 0xd7, 0x82, 0xb7, 0x7b, 0x6a, 0x1b, 0x0e,
+    0x30, 0x4a, 0x98, 0x0e, 0xb4, 0xf9, 0x81, 0x07, 0xe4, 0x75, 0x39, 0xe9,
+    0x53, 0xca, 0xbb, 0x5c, 0xaa, 0x93, 0x07, 0x0e, 0xa8, 0x2f, 0xba, 0x98,
+    0x49, 0x30, 0xa7, 0xcc, 0x1a, 0x3c, 0x68, 0x0c, 0xe1, 0xa4, 0xb1, 0x05,
+    0xe6, 0xe0, 0x25, 0x78, 0x58, 0x14, 0x37, 0xf5, 0x1f, 0xe3, 0x22, 0xef,
+    0xa8, 0x0e, 0x22, 0xa0, 0x94, 0x3a, 0xf6, 0xc9, 0x13, 0xe6, 0x06, 0xbf,
+    0x7f, 0x99, 0xc6, 0xcc, 0xd8, 0xc6, 0xbe, 0xd9, 0x2e, 0x24, 0xc7, 0x69,
+    0x8c, 0x95, 0xba, 0xf6, 0x04, 0xb3, 0x0a, 0xf4, 0xcb, 0xf0, 0xce,
+};
+
 static const unsigned char kMsg[] = { 1, 2, 3, 4 };
 
 static const unsigned char kSignature[] = {
 static const unsigned char kMsg[] = { 1, 2, 3, 4 };
 
 static const unsigned char kSignature[] = {
@@ -192,6 +289,7 @@ typedef struct APK_DATA_st {
     const unsigned char *kder;
     size_t size;
     int evptype;
     const unsigned char *kder;
     size_t size;
     int evptype;
+    int check;
 } APK_DATA;
 
 static APK_DATA keydata[] = {
 } APK_DATA;
 
 static APK_DATA keydata[] = {
@@ -202,6 +300,14 @@ static APK_DATA keydata[] = {
 #endif
 };
 
 #endif
 };
 
+static APK_DATA keycheckdata[] = {
+    {kExampleRSAKeyDER, sizeof(kExampleRSAKeyDER), EVP_PKEY_RSA, 1},
+    {kExampleBadRSAKeyDER, sizeof(kExampleBadRSAKeyDER), EVP_PKEY_RSA, 0},
+#ifndef OPENSSL_NO_EC
+    {kExampleECKeyDER, sizeof(kExampleECKeyDER), EVP_PKEY_EC, 1}
+#endif
+};
+
 static EVP_PKEY *load_example_rsa_key(void)
 {
     EVP_PKEY *ret = NULL;
 static EVP_PKEY *load_example_rsa_key(void)
 {
     EVP_PKEY *ret = NULL;
@@ -347,6 +453,60 @@ static int test_EVP_PKCS82PKEY(void)
 }
 #endif
 
 }
 #endif
 
+static int pkey_custom_check(EVP_PKEY *pkey)
+{
+    return 0xbeef;
+}
+
+static EVP_PKEY_METHOD *custom_pmeth;
+
+static int test_EVP_PKEY_check(int i)
+{
+    int ret = 0;
+    const unsigned char *p;
+    EVP_PKEY *pkey = NULL;
+    EVP_PKEY_CTX *ctx = NULL;
+    EVP_PKEY_CTX *ctx2 = NULL;
+    const APK_DATA *ak = &keycheckdata[i];
+    const unsigned char *input = ak->kder;
+    size_t input_len = ak->size;
+    int expected_id = ak->evptype;
+    int expected_check = ak->check;
+
+    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))
+        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;
+    }
+
+    ctx2 = EVP_PKEY_CTX_new_id(0xdefaced, NULL);
+    /* assign the pkey directly, as an internal test */
+    EVP_PKEY_up_ref(pkey);
+    ctx2->pkey = pkey;
+
+    if (!TEST_int_eq(EVP_PKEY_check(ctx2), 0xbeef))
+        goto done;
+
+    ret = 1;
+
+ done:
+    EVP_PKEY_CTX_free(ctx);
+    EVP_PKEY_CTX_free(ctx2);
+    EVP_PKEY_free(pkey);
+    return ret;
+}
+
 int setup_tests(void)
 {
     ADD_TEST(test_EVP_DigestSignInit);
 int setup_tests(void)
 {
     ADD_TEST(test_EVP_DigestSignInit);
@@ -355,5 +515,17 @@ int setup_tests(void)
 #ifndef OPENSSL_NO_EC
     ADD_TEST(test_EVP_PKCS82PKEY);
 #endif
 #ifndef OPENSSL_NO_EC
     ADD_TEST(test_EVP_PKCS82PKEY);
 #endif
+    custom_pmeth = EVP_PKEY_meth_new(0xdefaced, 0);
+    if (!TEST_ptr(custom_pmeth))
+        return 0;
+    EVP_PKEY_meth_set_check(custom_pmeth, pkey_custom_check);
+    if (!TEST_int_eq(EVP_PKEY_meth_add0(custom_pmeth), 1))
+        return 0;
+    ADD_ALL_TESTS(test_EVP_PKEY_check, OSSL_NELEM(keycheckdata));
     return 1;
 }
     return 1;
 }
+
+void cleanup_tests(void)
+{
+    EVP_PKEY_meth_free(custom_pmeth);
+}
index 30cea8c..35c05da 100644 (file)
@@ -4393,3 +4393,6 @@ CRYPTO_THREAD_glock_new                 4336      1_1_1   EXIST::FUNCTION:
 UI_get_result_length                    4337   1_1_1   EXIST::FUNCTION:
 UI_set_result_ex                        4338   1_1_1   EXIST::FUNCTION:
 UI_get_result_string_length             4339   1_1_1   EXIST::FUNCTION:
 UI_get_result_length                    4337   1_1_1   EXIST::FUNCTION:
 UI_set_result_ex                        4338   1_1_1   EXIST::FUNCTION:
 UI_get_result_string_length             4339   1_1_1   EXIST::FUNCTION:
+EVP_PKEY_check                          4340   1_1_1   EXIST::FUNCTION:
+EVP_PKEY_meth_set_check                 4341   1_1_1   EXIST::FUNCTION:
+EVP_PKEY_meth_get_check                 4342   1_1_1   EXIST::FUNCTION: