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

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: default avatarTim Hudson <tjh@openssl.org>
Reviewed-by: default avatarRichard Levitte <levitte@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/4647)
parent 5d99881e
Loading
Loading
Loading
Loading
+11 −4
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_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;
        }

        if (check)
            r = EVP_PKEY_check(ctx);
        else
            r = EVP_PKEY_public_check(ctx);

        if (r == 1) {
            BIO_printf(out, "Key is valid\n");
+39 −2
Original line number Diff line number Diff line
@@ -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);

+12 −0
Original line number Diff line number Diff line
@@ -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;
}
+33 −2
Original line number Diff line number Diff line
@@ -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
+52 −0
Original line number Diff line number Diff line
@@ -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;
Loading