summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Yang <yang.yang@baishancloud.com>2017-11-01 00:45:24 +0800
committerRichard Levitte <levitte@openssl.org>2017-11-20 07:20:30 +0100
commitb0004708730f300a2e5c6a11c887caab50b6c42a (patch)
treecdfb52867403b6dee0f8c1c9860111076dd37144
parent5d99881e6a58a8775b8ca866b794f615a16bb033 (diff)
downloadopenssl-new-b0004708730f300a2e5c6a11c887caab50b6c42a.tar.gz
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@openssl.org> Reviewed-by: Richard Levitte <levitte@openssl.org> (Merged from https://github.com/openssl/openssl/pull/4647)
-rw-r--r--apps/pkey.c15
-rw-r--r--apps/pkeyparam.c41
-rw-r--r--crypto/asn1/ameth_lib.c12
-rw-r--r--crypto/dh/dh_ameth.c35
-rw-r--r--crypto/dh/dh_check.c52
-rw-r--r--crypto/dh/dh_err.c24
-rw-r--r--crypto/ec/ec_ameth.c33
-rw-r--r--crypto/ec/ec_err.c1
-rw-r--r--crypto/err/openssl.txt18
-rw-r--r--crypto/evp/evp_err.c4
-rw-r--r--crypto/evp/pmeth_gn.c46
-rw-r--r--crypto/evp/pmeth_lib.c26
-rw-r--r--crypto/include/internal/asn1_int.h2
-rw-r--r--crypto/include/internal/evp_int.h2
-rw-r--r--doc/man1/pkey.pod6
-rw-r--r--doc/man1/pkeyparam.pod5
-rw-r--r--doc/man3/DH_generate_parameters.pod18
-rw-r--r--doc/man3/EVP_PKEY_ASN1_METHOD.pod22
-rw-r--r--doc/man3/EVP_PKEY_keygen.pod21
-rw-r--r--doc/man3/EVP_PKEY_meth_new.pod18
-rw-r--r--include/openssl/dh.h3
-rw-r--r--include/openssl/dherr.h15
-rw-r--r--include/openssl/ecerr.h1
-rw-r--r--include/openssl/evp.h20
-rw-r--r--include/openssl/evperr.h2
-rw-r--r--test/evp_extra_test.c90
-rw-r--r--util/libcrypto.num11
27 files changed, 510 insertions, 33 deletions
diff --git a/apps/pkey.c b/apps/pkey.c
index 0a3a36a716..6160e5a381 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 9ac247509a..35cdd8dc92 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 87a3eba14a..5662e17688 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 e504690fa3..05a1d4227e 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 066bf83336..fc45577101 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 aae66fa0b9..bbedab593e 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 22ad6b0f2d..0682bc3d1d 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 19a7a9d7bd..9f82b4ef7e 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 d3e4a62e71..8547d07882 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 9bb37e0db8..6c1dc83c19 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 1a927a8320..e14965f333 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 37c5e85257..2d9f4fc6dc 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 d8b6f45bd8..90d525aa8d 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 562ac42ab5..917245c7d4 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 47ffb6649f..9569fe0e41 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 45c053cf43..117970582d 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 2e8c3b7172..56ad4b12fe 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 2ebabd10af..cb03b473aa 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 099cd0cf8f..a18579c09a 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 672ac29cb3..918e4fa141 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 753df4e7ae..00858244b8 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 02039071e8..ddec341d12 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 b04599a8b3..bd09cb7f1b 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 e002d63d24..aaecc1b80a 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 a7a46ae9d9..a870e438dd 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 f49ca80bf7..1e1fa171d3 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 100e71f965..8d9db312a6 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