Commit 2aee35d3 authored by Paul Yang's avatar Paul Yang Committed by Richard Levitte
Browse files

Support key check in EVP interface



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: default avatarRich Salz <rsalz@openssl.org>
Reviewed-by: default avatarRichard Levitte <levitte@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/4337)
parent c061daaa
Loading
Loading
Loading
Loading
+38 −2
Original line number Diff line number Diff line
@@ -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_TEXT, OPT_NOOUT, OPT_MD, OPT_TRADITIONAL, OPT_CHECK
} 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
    {"check", OPT_CHECK, '-', "Check key consistency"},
    {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;
    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) {
@@ -110,6 +111,9 @@ int pkey_main(int argc, char **argv)
        case OPT_TRADITIONAL:
            traditional = 1;
            break;
        case OPT_CHECK:
            check = 1;
            break;
        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 (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) {
+18 −1
Original line number Diff line number Diff line
@@ -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,
@@ -551,7 +564,11 @@ const EVP_PKEY_ASN1_METHOD eckey_asn1_meth = {
    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)
+1 −0
Original line number Diff line number Diff line
@@ -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_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
+1 −0
Original line number Diff line number Diff line
@@ -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_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"},
+24 −0
Original line number Diff line number Diff line
@@ -13,6 +13,7 @@
#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)
@@ -167,3 +168,26 @@ EVP_PKEY *EVP_PKEY_new_mac_key(int type, ENGINE *e,
    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);
}
Loading