Blame crypto/ec/ec_pmeth.c

Packit c4476c
/*
Packit c4476c
 * Copyright 2006-2019 The OpenSSL Project Authors. All Rights Reserved.
Packit c4476c
 *
Packit c4476c
 * Licensed under the OpenSSL license (the "License").  You may not use
Packit c4476c
 * this file except in compliance with the License.  You can obtain a copy
Packit c4476c
 * in the file LICENSE in the source distribution or at
Packit c4476c
 * https://www.openssl.org/source/license.html
Packit c4476c
 */
Packit c4476c
Packit c4476c
#include <stdio.h>
Packit c4476c
#include "internal/cryptlib.h"
Packit c4476c
#include <openssl/asn1t.h>
Packit c4476c
#include <openssl/x509.h>
Packit c4476c
#include <openssl/ec.h>
Packit c4476c
#include "ec_local.h"
Packit c4476c
#include <openssl/evp.h>
Packit c4476c
#include "crypto/evp.h"
Packit c4476c
Packit c4476c
/* EC pkey context structure */
Packit c4476c
Packit c4476c
typedef struct {
Packit c4476c
    /* Key and paramgen group */
Packit c4476c
    EC_GROUP *gen_group;
Packit c4476c
    /* message digest */
Packit c4476c
    const EVP_MD *md;
Packit c4476c
    /* Duplicate key if custom cofactor needed */
Packit c4476c
    EC_KEY *co_key;
Packit c4476c
    /* Cofactor mode */
Packit c4476c
    signed char cofactor_mode;
Packit c4476c
    /* KDF (if any) to use for ECDH */
Packit c4476c
    char kdf_type;
Packit c4476c
    /* Message digest to use for key derivation */
Packit c4476c
    const EVP_MD *kdf_md;
Packit c4476c
    /* User key material */
Packit c4476c
    unsigned char *kdf_ukm;
Packit c4476c
    size_t kdf_ukmlen;
Packit c4476c
    /* KDF output length */
Packit c4476c
    size_t kdf_outlen;
Packit c4476c
} EC_PKEY_CTX;
Packit c4476c
Packit c4476c
static int pkey_ec_init(EVP_PKEY_CTX *ctx)
Packit c4476c
{
Packit c4476c
    EC_PKEY_CTX *dctx;
Packit c4476c
Packit c4476c
    if ((dctx = OPENSSL_zalloc(sizeof(*dctx))) == NULL) {
Packit c4476c
        ECerr(EC_F_PKEY_EC_INIT, ERR_R_MALLOC_FAILURE);
Packit c4476c
        return 0;
Packit c4476c
    }
Packit c4476c
Packit c4476c
    dctx->cofactor_mode = -1;
Packit c4476c
    dctx->kdf_type = EVP_PKEY_ECDH_KDF_NONE;
Packit c4476c
    ctx->data = dctx;
Packit c4476c
    return 1;
Packit c4476c
}
Packit c4476c
Packit c4476c
static int pkey_ec_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src)
Packit c4476c
{
Packit c4476c
    EC_PKEY_CTX *dctx, *sctx;
Packit c4476c
    if (!pkey_ec_init(dst))
Packit c4476c
        return 0;
Packit c4476c
    sctx = src->data;
Packit c4476c
    dctx = dst->data;
Packit c4476c
    if (sctx->gen_group) {
Packit c4476c
        dctx->gen_group = EC_GROUP_dup(sctx->gen_group);
Packit c4476c
        if (!dctx->gen_group)
Packit c4476c
            return 0;
Packit c4476c
    }
Packit c4476c
    dctx->md = sctx->md;
Packit c4476c
Packit c4476c
    if (sctx->co_key) {
Packit c4476c
        dctx->co_key = EC_KEY_dup(sctx->co_key);
Packit c4476c
        if (!dctx->co_key)
Packit c4476c
            return 0;
Packit c4476c
    }
Packit c4476c
    dctx->kdf_type = sctx->kdf_type;
Packit c4476c
    dctx->kdf_md = sctx->kdf_md;
Packit c4476c
    dctx->kdf_outlen = sctx->kdf_outlen;
Packit c4476c
    if (sctx->kdf_ukm) {
Packit c4476c
        dctx->kdf_ukm = OPENSSL_memdup(sctx->kdf_ukm, sctx->kdf_ukmlen);
Packit c4476c
        if (!dctx->kdf_ukm)
Packit c4476c
            return 0;
Packit c4476c
    } else
Packit c4476c
        dctx->kdf_ukm = NULL;
Packit c4476c
    dctx->kdf_ukmlen = sctx->kdf_ukmlen;
Packit c4476c
    return 1;
Packit c4476c
}
Packit c4476c
Packit c4476c
static void pkey_ec_cleanup(EVP_PKEY_CTX *ctx)
Packit c4476c
{
Packit c4476c
    EC_PKEY_CTX *dctx = ctx->data;
Packit c4476c
    if (dctx != NULL) {
Packit c4476c
        EC_GROUP_free(dctx->gen_group);
Packit c4476c
        EC_KEY_free(dctx->co_key);
Packit c4476c
        OPENSSL_free(dctx->kdf_ukm);
Packit c4476c
        OPENSSL_free(dctx);
Packit c4476c
        ctx->data = NULL;
Packit c4476c
    }
Packit c4476c
}
Packit c4476c
Packit c4476c
static int pkey_ec_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen,
Packit c4476c
                        const unsigned char *tbs, size_t tbslen)
Packit c4476c
{
Packit c4476c
    int ret, type;
Packit c4476c
    unsigned int sltmp;
Packit c4476c
    EC_PKEY_CTX *dctx = ctx->data;
Packit c4476c
    EC_KEY *ec = ctx->pkey->pkey.ec;
Packit c4476c
    const int sig_sz = ECDSA_size(ec);
Packit c4476c
Packit c4476c
    /* ensure cast to size_t is safe */
Packit c4476c
    if (!ossl_assert(sig_sz > 0))
Packit c4476c
        return 0;
Packit c4476c
Packit c4476c
    if (sig == NULL) {
Packit c4476c
        *siglen = (size_t)sig_sz;
Packit c4476c
        return 1;
Packit c4476c
    }
Packit c4476c
Packit c4476c
    if (*siglen < (size_t)sig_sz) {
Packit c4476c
        ECerr(EC_F_PKEY_EC_SIGN, EC_R_BUFFER_TOO_SMALL);
Packit c4476c
        return 0;
Packit c4476c
    }
Packit c4476c
Packit c4476c
    type = (dctx->md != NULL) ? EVP_MD_type(dctx->md) : NID_sha1;
Packit c4476c
Packit c4476c
    ret = ECDSA_sign(type, tbs, tbslen, sig, &sltmp, ec);
Packit c4476c
Packit c4476c
    if (ret <= 0)
Packit c4476c
        return ret;
Packit c4476c
    *siglen = (size_t)sltmp;
Packit c4476c
    return 1;
Packit c4476c
}
Packit c4476c
Packit c4476c
static int pkey_ec_verify(EVP_PKEY_CTX *ctx,
Packit c4476c
                          const unsigned char *sig, size_t siglen,
Packit c4476c
                          const unsigned char *tbs, size_t tbslen)
Packit c4476c
{
Packit c4476c
    int ret, type;
Packit c4476c
    EC_PKEY_CTX *dctx = ctx->data;
Packit c4476c
    EC_KEY *ec = ctx->pkey->pkey.ec;
Packit c4476c
Packit c4476c
    if (dctx->md)
Packit c4476c
        type = EVP_MD_type(dctx->md);
Packit c4476c
    else
Packit c4476c
        type = NID_sha1;
Packit c4476c
Packit c4476c
    ret = ECDSA_verify(type, tbs, tbslen, sig, siglen, ec);
Packit c4476c
Packit c4476c
    return ret;
Packit c4476c
}
Packit c4476c
Packit c4476c
#ifndef OPENSSL_NO_EC
Packit c4476c
static int pkey_ec_derive(EVP_PKEY_CTX *ctx, unsigned char *key, size_t *keylen)
Packit c4476c
{
Packit c4476c
    int ret;
Packit c4476c
    size_t outlen;
Packit c4476c
    const EC_POINT *pubkey = NULL;
Packit c4476c
    EC_KEY *eckey;
Packit c4476c
    EC_PKEY_CTX *dctx = ctx->data;
Packit c4476c
    if (!ctx->pkey || !ctx->peerkey) {
Packit c4476c
        ECerr(EC_F_PKEY_EC_DERIVE, EC_R_KEYS_NOT_SET);
Packit c4476c
        return 0;
Packit c4476c
    }
Packit c4476c
Packit c4476c
    eckey = dctx->co_key ? dctx->co_key : ctx->pkey->pkey.ec;
Packit c4476c
Packit c4476c
    if (!key) {
Packit c4476c
        const EC_GROUP *group;
Packit c4476c
        group = EC_KEY_get0_group(eckey);
Packit c4476c
        *keylen = (EC_GROUP_get_degree(group) + 7) / 8;
Packit c4476c
        return 1;
Packit c4476c
    }
Packit c4476c
    pubkey = EC_KEY_get0_public_key(ctx->peerkey->pkey.ec);
Packit c4476c
Packit c4476c
    /*
Packit c4476c
     * NB: unlike PKCS#3 DH, if *outlen is less than maximum size this is not
Packit c4476c
     * an error, the result is truncated.
Packit c4476c
     */
Packit c4476c
Packit c4476c
    outlen = *keylen;
Packit c4476c
Packit c4476c
    ret = ECDH_compute_key(key, outlen, pubkey, eckey, 0);
Packit c4476c
    if (ret <= 0)
Packit c4476c
        return 0;
Packit c4476c
    *keylen = ret;
Packit c4476c
    return 1;
Packit c4476c
}
Packit c4476c
Packit c4476c
static int pkey_ec_kdf_derive(EVP_PKEY_CTX *ctx,
Packit c4476c
                              unsigned char *key, size_t *keylen)
Packit c4476c
{
Packit c4476c
    EC_PKEY_CTX *dctx = ctx->data;
Packit c4476c
    unsigned char *ktmp = NULL;
Packit c4476c
    size_t ktmplen;
Packit c4476c
    int rv = 0;
Packit c4476c
    if (dctx->kdf_type == EVP_PKEY_ECDH_KDF_NONE)
Packit c4476c
        return pkey_ec_derive(ctx, key, keylen);
Packit c4476c
    if (!key) {
Packit c4476c
        *keylen = dctx->kdf_outlen;
Packit c4476c
        return 1;
Packit c4476c
    }
Packit c4476c
    if (*keylen != dctx->kdf_outlen)
Packit c4476c
        return 0;
Packit c4476c
    if (!pkey_ec_derive(ctx, NULL, &ktmplen))
Packit c4476c
        return 0;
Packit c4476c
    if ((ktmp = OPENSSL_malloc(ktmplen)) == NULL) {
Packit c4476c
        ECerr(EC_F_PKEY_EC_KDF_DERIVE, ERR_R_MALLOC_FAILURE);
Packit c4476c
        return 0;
Packit c4476c
    }
Packit c4476c
    if (!pkey_ec_derive(ctx, ktmp, &ktmplen))
Packit c4476c
        goto err;
Packit c4476c
    /* Do KDF stuff */
Packit c4476c
    if (!ecdh_KDF_X9_63(key, *keylen, ktmp, ktmplen,
Packit c4476c
                        dctx->kdf_ukm, dctx->kdf_ukmlen, dctx->kdf_md))
Packit c4476c
        goto err;
Packit c4476c
    rv = 1;
Packit c4476c
Packit c4476c
 err:
Packit c4476c
    OPENSSL_clear_free(ktmp, ktmplen);
Packit c4476c
    return rv;
Packit c4476c
}
Packit c4476c
#endif
Packit c4476c
Packit c4476c
static int pkey_ec_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
Packit c4476c
{
Packit c4476c
    EC_PKEY_CTX *dctx = ctx->data;
Packit c4476c
    EC_GROUP *group;
Packit c4476c
    switch (type) {
Packit c4476c
    case EVP_PKEY_CTRL_EC_PARAMGEN_CURVE_NID:
Packit c4476c
        group = EC_GROUP_new_by_curve_name(p1);
Packit c4476c
        if (group == NULL) {
Packit c4476c
            ECerr(EC_F_PKEY_EC_CTRL, EC_R_INVALID_CURVE);
Packit c4476c
            return 0;
Packit c4476c
        }
Packit c4476c
        EC_GROUP_free(dctx->gen_group);
Packit c4476c
        dctx->gen_group = group;
Packit c4476c
        return 1;
Packit c4476c
Packit c4476c
    case EVP_PKEY_CTRL_EC_PARAM_ENC:
Packit c4476c
        if (!dctx->gen_group) {
Packit c4476c
            ECerr(EC_F_PKEY_EC_CTRL, EC_R_NO_PARAMETERS_SET);
Packit c4476c
            return 0;
Packit c4476c
        }
Packit c4476c
        EC_GROUP_set_asn1_flag(dctx->gen_group, p1);
Packit c4476c
        return 1;
Packit c4476c
Packit c4476c
#ifndef OPENSSL_NO_EC
Packit c4476c
    case EVP_PKEY_CTRL_EC_ECDH_COFACTOR:
Packit c4476c
        if (p1 == -2) {
Packit c4476c
            if (dctx->cofactor_mode != -1)
Packit c4476c
                return dctx->cofactor_mode;
Packit c4476c
            else {
Packit c4476c
                EC_KEY *ec_key = ctx->pkey->pkey.ec;
Packit c4476c
                return EC_KEY_get_flags(ec_key) & EC_FLAG_COFACTOR_ECDH ? 1 : 0;
Packit c4476c
            }
Packit c4476c
        } else if (p1 < -1 || p1 > 1)
Packit c4476c
            return -2;
Packit c4476c
        dctx->cofactor_mode = p1;
Packit c4476c
        if (p1 != -1) {
Packit c4476c
            EC_KEY *ec_key = ctx->pkey->pkey.ec;
Packit c4476c
            if (!ec_key->group)
Packit c4476c
                return -2;
Packit c4476c
            /* If cofactor is 1 cofactor mode does nothing */
Packit c4476c
            if (BN_is_one(ec_key->group->cofactor))
Packit c4476c
                return 1;
Packit c4476c
            if (!dctx->co_key) {
Packit c4476c
                dctx->co_key = EC_KEY_dup(ec_key);
Packit c4476c
                if (!dctx->co_key)
Packit c4476c
                    return 0;
Packit c4476c
            }
Packit c4476c
            if (p1)
Packit c4476c
                EC_KEY_set_flags(dctx->co_key, EC_FLAG_COFACTOR_ECDH);
Packit c4476c
            else
Packit c4476c
                EC_KEY_clear_flags(dctx->co_key, EC_FLAG_COFACTOR_ECDH);
Packit c4476c
        } else {
Packit c4476c
            EC_KEY_free(dctx->co_key);
Packit c4476c
            dctx->co_key = NULL;
Packit c4476c
        }
Packit c4476c
        return 1;
Packit c4476c
#endif
Packit c4476c
Packit c4476c
    case EVP_PKEY_CTRL_EC_KDF_TYPE:
Packit c4476c
        if (p1 == -2)
Packit c4476c
            return dctx->kdf_type;
Packit c4476c
        if (p1 != EVP_PKEY_ECDH_KDF_NONE && p1 != EVP_PKEY_ECDH_KDF_X9_63)
Packit c4476c
            return -2;
Packit c4476c
        dctx->kdf_type = p1;
Packit c4476c
        return 1;
Packit c4476c
Packit c4476c
    case EVP_PKEY_CTRL_EC_KDF_MD:
Packit c4476c
        dctx->kdf_md = p2;
Packit c4476c
        return 1;
Packit c4476c
Packit c4476c
    case EVP_PKEY_CTRL_GET_EC_KDF_MD:
Packit c4476c
        *(const EVP_MD **)p2 = dctx->kdf_md;
Packit c4476c
        return 1;
Packit c4476c
Packit c4476c
    case EVP_PKEY_CTRL_EC_KDF_OUTLEN:
Packit c4476c
        if (p1 <= 0)
Packit c4476c
            return -2;
Packit c4476c
        dctx->kdf_outlen = (size_t)p1;
Packit c4476c
        return 1;
Packit c4476c
Packit c4476c
    case EVP_PKEY_CTRL_GET_EC_KDF_OUTLEN:
Packit c4476c
        *(int *)p2 = dctx->kdf_outlen;
Packit c4476c
        return 1;
Packit c4476c
Packit c4476c
    case EVP_PKEY_CTRL_EC_KDF_UKM:
Packit c4476c
        OPENSSL_free(dctx->kdf_ukm);
Packit c4476c
        dctx->kdf_ukm = p2;
Packit c4476c
        if (p2)
Packit c4476c
            dctx->kdf_ukmlen = p1;
Packit c4476c
        else
Packit c4476c
            dctx->kdf_ukmlen = 0;
Packit c4476c
        return 1;
Packit c4476c
Packit c4476c
    case EVP_PKEY_CTRL_GET_EC_KDF_UKM:
Packit c4476c
        *(unsigned char **)p2 = dctx->kdf_ukm;
Packit c4476c
        return dctx->kdf_ukmlen;
Packit c4476c
Packit c4476c
    case EVP_PKEY_CTRL_MD:
Packit c4476c
        if (EVP_MD_type((const EVP_MD *)p2) != NID_sha1 &&
Packit c4476c
            EVP_MD_type((const EVP_MD *)p2) != NID_ecdsa_with_SHA1 &&
Packit c4476c
            EVP_MD_type((const EVP_MD *)p2) != NID_sha224 &&
Packit c4476c
            EVP_MD_type((const EVP_MD *)p2) != NID_sha256 &&
Packit c4476c
            EVP_MD_type((const EVP_MD *)p2) != NID_sha384 &&
Packit c4476c
            EVP_MD_type((const EVP_MD *)p2) != NID_sha512 &&
Packit c4476c
            EVP_MD_type((const EVP_MD *)p2) != NID_sha3_224 &&
Packit c4476c
            EVP_MD_type((const EVP_MD *)p2) != NID_sha3_256 &&
Packit c4476c
            EVP_MD_type((const EVP_MD *)p2) != NID_sha3_384 &&
Packit c4476c
            EVP_MD_type((const EVP_MD *)p2) != NID_sha3_512) {
Packit c4476c
            ECerr(EC_F_PKEY_EC_CTRL, EC_R_INVALID_DIGEST_TYPE);
Packit c4476c
            return 0;
Packit c4476c
        }
Packit c4476c
        dctx->md = p2;
Packit c4476c
        return 1;
Packit c4476c
Packit c4476c
    case EVP_PKEY_CTRL_GET_MD:
Packit c4476c
        *(const EVP_MD **)p2 = dctx->md;
Packit c4476c
        return 1;
Packit c4476c
Packit c4476c
    case EVP_PKEY_CTRL_PEER_KEY:
Packit c4476c
        /* Default behaviour is OK */
Packit c4476c
    case EVP_PKEY_CTRL_DIGESTINIT:
Packit c4476c
    case EVP_PKEY_CTRL_PKCS7_SIGN:
Packit c4476c
    case EVP_PKEY_CTRL_CMS_SIGN:
Packit c4476c
        return 1;
Packit c4476c
Packit c4476c
    default:
Packit c4476c
        return -2;
Packit c4476c
Packit c4476c
    }
Packit c4476c
}
Packit c4476c
Packit c4476c
static int pkey_ec_ctrl_str(EVP_PKEY_CTX *ctx,
Packit c4476c
                            const char *type, const char *value)
Packit c4476c
{
Packit c4476c
    if (strcmp(type, "ec_paramgen_curve") == 0) {
Packit c4476c
        int nid;
Packit c4476c
        nid = EC_curve_nist2nid(value);
Packit c4476c
        if (nid == NID_undef)
Packit c4476c
            nid = OBJ_sn2nid(value);
Packit c4476c
        if (nid == NID_undef)
Packit c4476c
            nid = OBJ_ln2nid(value);
Packit c4476c
        if (nid == NID_undef) {
Packit c4476c
            ECerr(EC_F_PKEY_EC_CTRL_STR, EC_R_INVALID_CURVE);
Packit c4476c
            return 0;
Packit c4476c
        }
Packit c4476c
        return EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx, nid);
Packit c4476c
    } else if (strcmp(type, "ec_param_enc") == 0) {
Packit c4476c
        int param_enc;
Packit c4476c
        if (strcmp(value, "explicit") == 0)
Packit c4476c
            param_enc = 0;
Packit c4476c
        else if (strcmp(value, "named_curve") == 0)
Packit c4476c
            param_enc = OPENSSL_EC_NAMED_CURVE;
Packit c4476c
        else
Packit c4476c
            return -2;
Packit c4476c
        return EVP_PKEY_CTX_set_ec_param_enc(ctx, param_enc);
Packit c4476c
    } else if (strcmp(type, "ecdh_kdf_md") == 0) {
Packit c4476c
        const EVP_MD *md;
Packit c4476c
        if ((md = EVP_get_digestbyname(value)) == NULL) {
Packit c4476c
            ECerr(EC_F_PKEY_EC_CTRL_STR, EC_R_INVALID_DIGEST);
Packit c4476c
            return 0;
Packit c4476c
        }
Packit c4476c
        return EVP_PKEY_CTX_set_ecdh_kdf_md(ctx, md);
Packit c4476c
    } else if (strcmp(type, "ecdh_cofactor_mode") == 0) {
Packit c4476c
        int co_mode;
Packit c4476c
        co_mode = atoi(value);
Packit c4476c
        return EVP_PKEY_CTX_set_ecdh_cofactor_mode(ctx, co_mode);
Packit c4476c
    }
Packit c4476c
Packit c4476c
    return -2;
Packit c4476c
}
Packit c4476c
Packit c4476c
static int pkey_ec_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
Packit c4476c
{
Packit c4476c
    EC_KEY *ec = NULL;
Packit c4476c
    EC_PKEY_CTX *dctx = ctx->data;
Packit c4476c
    int ret;
Packit c4476c
Packit c4476c
    if (dctx->gen_group == NULL) {
Packit c4476c
        ECerr(EC_F_PKEY_EC_PARAMGEN, EC_R_NO_PARAMETERS_SET);
Packit c4476c
        return 0;
Packit c4476c
    }
Packit c4476c
    ec = EC_KEY_new();
Packit c4476c
    if (ec == NULL)
Packit c4476c
        return 0;
Packit c4476c
    if (!(ret = EC_KEY_set_group(ec, dctx->gen_group))
Packit c4476c
        || !ossl_assert(ret = EVP_PKEY_assign_EC_KEY(pkey, ec)))
Packit c4476c
        EC_KEY_free(ec);
Packit c4476c
    return ret;
Packit c4476c
}
Packit c4476c
Packit c4476c
static int pkey_ec_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
Packit c4476c
{
Packit c4476c
    EC_KEY *ec = NULL;
Packit c4476c
    EC_PKEY_CTX *dctx = ctx->data;
Packit c4476c
    int ret;
Packit c4476c
Packit c4476c
    if (ctx->pkey == NULL && dctx->gen_group == NULL) {
Packit c4476c
        ECerr(EC_F_PKEY_EC_KEYGEN, EC_R_NO_PARAMETERS_SET);
Packit c4476c
        return 0;
Packit c4476c
    }
Packit c4476c
    ec = EC_KEY_new();
Packit c4476c
    if (ec == NULL)
Packit c4476c
        return 0;
Packit c4476c
    if (!ossl_assert(EVP_PKEY_assign_EC_KEY(pkey, ec))) {
Packit c4476c
        EC_KEY_free(ec);
Packit c4476c
        return 0;
Packit c4476c
    }
Packit c4476c
    /* Note: if error is returned, we count on caller to free pkey->pkey.ec */
Packit c4476c
    if (ctx->pkey != NULL)
Packit c4476c
        ret = EVP_PKEY_copy_parameters(pkey, ctx->pkey);
Packit c4476c
    else
Packit c4476c
        ret = EC_KEY_set_group(ec, dctx->gen_group);
Packit c4476c
Packit c4476c
    return ret ? EC_KEY_generate_key(ec) : 0;
Packit c4476c
}
Packit c4476c
Packit c4476c
const EVP_PKEY_METHOD ec_pkey_meth = {
Packit c4476c
    EVP_PKEY_EC,
Packit c4476c
    EVP_PKEY_FLAG_FIPS,
Packit c4476c
    pkey_ec_init,
Packit c4476c
    pkey_ec_copy,
Packit c4476c
    pkey_ec_cleanup,
Packit c4476c
Packit c4476c
    0,
Packit c4476c
    pkey_ec_paramgen,
Packit c4476c
Packit c4476c
    0,
Packit c4476c
    pkey_ec_keygen,
Packit c4476c
Packit c4476c
    0,
Packit c4476c
    pkey_ec_sign,
Packit c4476c
Packit c4476c
    0,
Packit c4476c
    pkey_ec_verify,
Packit c4476c
Packit c4476c
    0, 0,
Packit c4476c
Packit c4476c
    0, 0, 0, 0,
Packit c4476c
Packit c4476c
    0,
Packit c4476c
    0,
Packit c4476c
Packit c4476c
    0,
Packit c4476c
    0,
Packit c4476c
Packit c4476c
    0,
Packit c4476c
#ifndef OPENSSL_NO_EC
Packit c4476c
    pkey_ec_kdf_derive,
Packit c4476c
#else
Packit c4476c
    0,
Packit c4476c
#endif
Packit c4476c
    pkey_ec_ctrl,
Packit c4476c
    pkey_ec_ctrl_str
Packit c4476c
};
Packit c4476c
Packit c4476c
const EVP_PKEY_METHOD *ec_pkey_method(void)
Packit c4476c
{
Packit c4476c
    return &ec_pkey_meth;
Packit c4476c
}