diff options
author | Paul Yang <yang.yang@baishancloud.com> | 2017-11-01 00:45:24 +0800 |
---|---|---|
committer | Richard Levitte <levitte@openssl.org> | 2017-11-20 07:20:30 +0100 |
commit | b0004708730f300a2e5c6a11c887caab50b6c42a (patch) | |
tree | cdfb52867403b6dee0f8c1c9860111076dd37144 | |
parent | 5d99881e6a58a8775b8ca866b794f615a16bb033 (diff) |
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.c | 15 | ||||
-rw-r--r-- | apps/pkeyparam.c | 41 | ||||
-rw-r--r-- | crypto/asn1/ameth_lib.c | 12 | ||||
-rw-r--r-- | crypto/dh/dh_ameth.c | 35 | ||||
-rw-r--r-- | crypto/dh/dh_check.c | 52 | ||||
-rw-r--r-- | crypto/dh/dh_err.c | 24 | ||||
-rw-r--r-- | crypto/ec/ec_ameth.c | 33 | ||||
-rw-r--r-- | crypto/ec/ec_err.c | 1 | ||||
-rw-r--r-- | crypto/err/openssl.txt | 18 | ||||
-rw-r--r-- | crypto/evp/evp_err.c | 4 | ||||
-rw-r--r-- | crypto/evp/pmeth_gn.c | 46 | ||||
-rw-r--r-- | crypto/evp/pmeth_lib.c | 26 | ||||
-rw-r--r-- | crypto/include/internal/asn1_int.h | 2 | ||||
-rw-r--r-- | crypto/include/internal/evp_int.h | 2 | ||||
-rw-r--r-- | doc/man1/pkey.pod | 6 | ||||
-rw-r--r-- | doc/man1/pkeyparam.pod | 5 | ||||
-rw-r--r-- | doc/man3/DH_generate_parameters.pod | 18 | ||||
-rw-r--r-- | doc/man3/EVP_PKEY_ASN1_METHOD.pod | 22 | ||||
-rw-r--r-- | doc/man3/EVP_PKEY_keygen.pod | 21 | ||||
-rw-r--r-- | doc/man3/EVP_PKEY_meth_new.pod | 18 | ||||
-rw-r--r-- | include/openssl/dh.h | 3 | ||||
-rw-r--r-- | include/openssl/dherr.h | 15 | ||||
-rw-r--r-- | include/openssl/ecerr.h | 1 | ||||
-rw-r--r-- | include/openssl/evp.h | 20 | ||||
-rw-r--r-- | include/openssl/evperr.h | 2 | ||||
-rw-r--r-- | test/evp_extra_test.c | 90 | ||||
-rw-r--r-- | util/libcrypto.num | 11 |
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_par |