Commit a08802ce authored by Matt Caswell's avatar Matt Caswell
Browse files

Add functions to create an EVP_PKEY from raw private/public key data



Not all algorithms will support this, since their keys are not a simple
block of data. But many can.

Reviewed-by: default avatarRichard Levitte <levitte@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/5520)
parent 9e381e8a
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -703,6 +703,8 @@ EVP_F_EVP_PKEY_GET0_SIPHASH:172:EVP_PKEY_get0_siphash
EVP_F_EVP_PKEY_KEYGEN:146:EVP_PKEY_keygen
EVP_F_EVP_PKEY_KEYGEN_INIT:147:EVP_PKEY_keygen_init
EVP_F_EVP_PKEY_NEW:106:EVP_PKEY_new
EVP_F_EVP_PKEY_NEW_PRIVATE_KEY:191:EVP_PKEY_new_private_key
EVP_F_EVP_PKEY_NEW_PUBLIC_KEY:192:EVP_PKEY_new_public_key
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
+4 −0
Original line number Diff line number Diff line
@@ -93,6 +93,10 @@ static const ERR_STRING_DATA EVP_str_functs[] = {
    {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_KEYGEN_INIT, 0),
     "EVP_PKEY_keygen_init"},
    {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_NEW, 0), "EVP_PKEY_new"},
    {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_NEW_PRIVATE_KEY, 0),
     "EVP_PKEY_new_private_key"},
    {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_NEW_PUBLIC_KEY, 0),
     "EVP_PKEY_new_public_key"},
    {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"},
+68 −7
Original line number Diff line number Diff line
@@ -174,10 +174,12 @@ int EVP_PKEY_up_ref(EVP_PKEY *pkey)
 * is NULL just return 1 or 0 if the algorithm exists.
 */

static int pkey_set_type(EVP_PKEY *pkey, int type, const char *str, int len)
static int pkey_set_type(EVP_PKEY *pkey, ENGINE *e, int type, const char *str,
                         int len)
{
    const EVP_PKEY_ASN1_METHOD *ameth;
    ENGINE *e = NULL;
    ENGINE **eptr = (e == NULL) ? &e :  NULL;

    if (pkey) {
        if (pkey->pkey.ptr)
            EVP_PKEY_free_it(pkey);
@@ -196,11 +198,11 @@ static int pkey_set_type(EVP_PKEY *pkey, int type, const char *str, int len)
#endif
    }
    if (str)
        ameth = EVP_PKEY_asn1_find_str(&e, str, len);
        ameth = EVP_PKEY_asn1_find_str(eptr, str, len);
    else
        ameth = EVP_PKEY_asn1_find(&e, type);
        ameth = EVP_PKEY_asn1_find(eptr, type);
#ifndef OPENSSL_NO_ENGINE
    if (pkey == NULL)
    if (pkey == NULL && eptr != NULL)
        ENGINE_finish(e);
#endif
    if (ameth == NULL) {
@@ -217,14 +219,73 @@ static int pkey_set_type(EVP_PKEY *pkey, int type, const char *str, int len)
    return 1;
}

EVP_PKEY *EVP_PKEY_new_private_key(int type, ENGINE *e, unsigned char *priv,
                                   size_t len)
{
    EVP_PKEY *ret = EVP_PKEY_new();

    if (ret == NULL
            || !pkey_set_type(ret, e, type, NULL, -1)) {
        /* EVPerr already called */
        goto err;
    }

    if (ret->ameth->set_priv_key == NULL) {
        EVPerr(EVP_F_EVP_PKEY_NEW_PRIVATE_KEY,
               EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
        goto err;
    }

    if (!ret->ameth->set_priv_key(ret, priv, len)) {
        /* We assume the method function calls EVPerr */
        goto err;
    }

    return ret;

 err:
    EVP_PKEY_free(ret);
    return NULL;
}

EVP_PKEY *EVP_PKEY_new_public_key(int type, ENGINE *e, unsigned char *pub,
                                  size_t len)
{
    EVP_PKEY *ret = EVP_PKEY_new();

    if (ret == NULL
            || !pkey_set_type(ret, e, type, NULL, -1)) {
        /* EVPerr already called */
        goto err;
    }

    if (ret->ameth->set_pub_key == NULL) {
        EVPerr(EVP_F_EVP_PKEY_NEW_PUBLIC_KEY,
               EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
        goto err;
    }

    if (!ret->ameth->set_pub_key(ret, pub, len)) {
        /* We assume the method function calls EVPerr */
        goto err;
    }

    return ret;

 err:
    EVP_PKEY_free(ret);
    return NULL;
}


int EVP_PKEY_set_type(EVP_PKEY *pkey, int type)
{
    return pkey_set_type(pkey, type, NULL, -1);
    return pkey_set_type(pkey, NULL, type, NULL, -1);
}

int EVP_PKEY_set_type_str(EVP_PKEY *pkey, const char *str, int len)
{
    return pkey_set_type(pkey, EVP_PKEY_NONE, str, len);
    return pkey_set_type(pkey, NULL, EVP_PKEY_NONE, str, len);
}
#ifndef OPENSSL_NO_ENGINE
int EVP_PKEY_set1_engine(EVP_PKEY *pkey, ENGINE *e)
+3 −0
Original line number Diff line number Diff line
@@ -58,6 +58,9 @@ struct evp_pkey_asn1_method_st {
    int (*pkey_check) (const EVP_PKEY *pk);
    int (*pkey_public_check) (const EVP_PKEY *pk);
    int (*pkey_param_check) (const EVP_PKEY *pk);
    /* Get/set raw private/public key data */
    int (*set_priv_key) (EVP_PKEY *pk, const unsigned char *priv, size_t len);
    int (*set_pub_key) (EVP_PKEY *pk, const unsigned char *pub, size_t len);
} /* EVP_PKEY_ASN1_METHOD */ ;

DEFINE_STACK_OF_CONST(EVP_PKEY_ASN1_METHOD)
+4 −0
Original line number Diff line number Diff line
@@ -1337,6 +1337,10 @@ void EVP_PKEY_CTX_set0_keygen_info(EVP_PKEY_CTX *ctx, int *dat, int datlen);

EVP_PKEY *EVP_PKEY_new_mac_key(int type, ENGINE *e,
                               const unsigned char *key, int keylen);
EVP_PKEY *EVP_PKEY_new_private_key(int type, ENGINE *e, unsigned char *priv,
                                   size_t len);
EVP_PKEY *EVP_PKEY_new_public_key(int type, ENGINE *e, unsigned char *pub,
                                  size_t len);

void EVP_PKEY_CTX_set_data(EVP_PKEY_CTX *ctx, void *data);
void *EVP_PKEY_CTX_get_data(EVP_PKEY_CTX *ctx);
Loading