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 e8e32bacda5ba74b9b69c00e1003b4dcb290c14a..06bdaa3a897fa3934e3493d374d650e54b99bd07 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 b66adf2bbc246dc6f556e8ceeef45aa2a6ba0923..ecf1a0207d42d513b51f8984b3b39eaef75920af 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 253e0ab29c4eecfd5ec7ddc446fa0c005e571314..b05d4599af324222f5495a6fd86a4817d541b132 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 c8161965d88b88b7420af9ed366b14473270ce47..cc32a3bfde9a79d60734672146e7772fa3e2c57f 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 6adc3a9c19867e84e0fce6ec8bae0f2549cea563..1a927a832029fd9ec8864a23f26c02feb372a985 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 71ec09944041252be8698196c177eed544298e80..c62bd81da41b31d0438f9b12bc664184b3b48944 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 8ff919c8fa97b3826025f53e7f9804cf9e6fb4e7..d8b6f45bd8ab9f462818baac219634cfaf647265 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 be1b9be926f732694f7852102a53e34080c93b4f..b9558a60d4b9148f130e90fc038c90eaaef6c02d 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 42138ce9eb6ffcf7cbbcde898bc546801a095d1d..97a37ba47d3e853805143d93787c5c836e957701 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 3c277a55a353d4e229f67472f251397cf23ebc19..d6b0db4d808685720dfcf404972dfa41b07237da 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 b7f2128baa61c04bbfb28b0446178b58bd23ce31..3687f9bffff4111f23a307911abcc8196995edb7 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 041492a8f0fbf1b3450d7df0a14266e862617097..acff78a16c777377b9b6c938ba63c3e41f53960f 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 a1e2318621c3ce09a5a05745c3e812ed356aafc3..2c01bdf4fdafa7020c59e4b55f44b848351d2583 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 cbb18bd6301f615807922e281eafc36b0681b3a1..9bb2bca323538766e32046c74cad73769123a5c5 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 f1f26afef279ab8da7e319014a2cec22d91381dd..06e77f7b1b87525befe7c8aec1d1d2f51fd4ef0b 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 e3fab29a82f638894730e48c7d91b204c3eb7373..221f9a6d101c749f10205fb95771207e3872765d 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 30cea8c15fea3dbfaf7d371a4f9806bca6e5a88e..35c05dae88f1779152c137ab2c5441a9d412ea7d 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: