/* libp11, a simple layer on to of PKCS#11 API * Copyright (C) 2017 Douglas E. Engert * Copyright (C) 2017-2018 MichaƂ Trojnara * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "libp11-int.h" #include static int (*orig_pkey_rsa_sign_init) (EVP_PKEY_CTX *ctx); static int (*orig_pkey_rsa_sign) (EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen, const unsigned char *tbs, size_t tbslen); static int (*orig_pkey_rsa_decrypt_init) (EVP_PKEY_CTX *ctx); static int (*orig_pkey_rsa_decrypt) (EVP_PKEY_CTX *ctx, unsigned char *out, size_t *outlen, const unsigned char *in, size_t inlen); #ifndef OPENSSL_NO_EC static int (*orig_pkey_ec_sign_init) (EVP_PKEY_CTX *ctx); static int (*orig_pkey_ec_sign) (EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen, const unsigned char *tbs, size_t tbslen); #endif /* OPENSSL_NO_EC */ #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) struct evp_pkey_method_st { int pkey_id; int flags; int (*init) (EVP_PKEY_CTX *ctx); int (*copy) (EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src); void (*cleanup) (EVP_PKEY_CTX *ctx); int (*paramgen_init) (EVP_PKEY_CTX *ctx); int (*paramgen) (EVP_PKEY_CTX *ctx, EVP_PKEY *pkey); int (*keygen_init) (EVP_PKEY_CTX *ctx); int (*keygen) (EVP_PKEY_CTX *ctx, EVP_PKEY *pkey); int (*sign_init) (EVP_PKEY_CTX *ctx); int (*sign) (EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen, const unsigned char *tbs, size_t tbslen); int (*verify_init) (EVP_PKEY_CTX *ctx); int (*verify) (EVP_PKEY_CTX *ctx, const unsigned char *sig, size_t siglen, const unsigned char *tbs, size_t tbslen); int (*verify_recover_init) (EVP_PKEY_CTX *ctx); int (*verify_recover) (EVP_PKEY_CTX *ctx, unsigned char *rout, size_t *routlen, const unsigned char *sig, size_t siglen); int (*signctx_init) (EVP_PKEY_CTX *ctx, EVP_MD_CTX *mctx); int (*signctx) (EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen, EVP_MD_CTX *mctx); int (*verifyctx_init) (EVP_PKEY_CTX *ctx, EVP_MD_CTX *mctx); int (*verifyctx) (EVP_PKEY_CTX *ctx, const unsigned char *sig, int siglen, EVP_MD_CTX *mctx); int (*encrypt_init) (EVP_PKEY_CTX *ctx); int (*encrypt) (EVP_PKEY_CTX *ctx, unsigned char *out, size_t *outlen, const unsigned char *in, size_t inlen); int (*decrypt_init) (EVP_PKEY_CTX *ctx); int (*decrypt) (EVP_PKEY_CTX *ctx, unsigned char *out, size_t *outlen, const unsigned char *in, size_t inlen); int (*derive_init) (EVP_PKEY_CTX *ctx); int (*derive) (EVP_PKEY_CTX *ctx, unsigned char *key, size_t *keylen); int (*ctrl) (EVP_PKEY_CTX *ctx, int type, int p1, void *p2); int (*ctrl_str) (EVP_PKEY_CTX *ctx, const char *type, const char *value); } /* EVP_PKEY_METHOD */ ; #endif #if OPENSSL_VERSION_NUMBER < 0x10002000L || defined(LIBRESSL_VERSION_NUMBER) typedef struct { int nbits; BIGNUM *pub_exp; int gentmp[2]; int pad_mode; const EVP_MD *md; const EVP_MD *mgf1md; int saltlen; unsigned char *tbuf; } RSA_PKEY_CTX; static int EVP_PKEY_CTX_get_signature_md(EVP_PKEY_CTX *ctx, const EVP_MD **pmd) { RSA_PKEY_CTX *rctx = EVP_PKEY_CTX_get_data(ctx); if (rctx == NULL) return -1; *pmd = rctx->md; return 1; } static int EVP_PKEY_CTX_get_rsa_oaep_md(EVP_PKEY_CTX *ctx, const EVP_MD **pmd) { RSA_PKEY_CTX *rctx = EVP_PKEY_CTX_get_data(ctx); if (rctx == NULL) return -1; *pmd = rctx->md; return 1; } #endif #if OPENSSL_VERSION_NUMBER < 0x10001000L static int EVP_PKEY_CTX_get_rsa_mgf1_md(EVP_PKEY_CTX *ctx, const EVP_MD **pmd) { RSA_PKEY_CTX *rctx = EVP_PKEY_CTX_get_data(ctx); if (rctx == NULL) return -1; *pmd = rctx->mgf1md; return 1; } static int EVP_PKEY_CTX_get_rsa_padding(EVP_PKEY_CTX *ctx, int *padding) { RSA_PKEY_CTX *rctx = EVP_PKEY_CTX_get_data(ctx); if (rctx == NULL) return -1; *padding = rctx->pad_mode; return 1; } static int EVP_PKEY_CTX_get_rsa_pss_saltlen(EVP_PKEY_CTX *ctx, int *saltlen) { RSA_PKEY_CTX *rctx = EVP_PKEY_CTX_get_data(ctx); if (rctx == NULL) return -1; *saltlen = rctx->saltlen; return 1; } static void EVP_PKEY_meth_copy(EVP_PKEY_METHOD *dst, const EVP_PKEY_METHOD *src) { memcpy((int *)dst + 2, (int *)src + 2, 25 * sizeof(void (*)())); } #endif #if OPENSSL_VERSION_NUMBER < 0x100020d0L || defined(LIBRESSL_VERSION_NUMBER) static void EVP_PKEY_meth_get_sign(EVP_PKEY_METHOD *pmeth, int (**psign_init) (EVP_PKEY_CTX *ctx), int (**psign) (EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen, const unsigned char *tbs, size_t tbslen)) { if (psign_init) *psign_init = pmeth->sign_init; if (psign) *psign = pmeth->sign; } static void EVP_PKEY_meth_get_decrypt(EVP_PKEY_METHOD *pmeth, int (**pdecrypt_init) (EVP_PKEY_CTX *ctx), int (**pdecrypt) (EVP_PKEY_CTX *ctx, unsigned char *out, size_t *outlen, const unsigned char *in, size_t inlen)) { if (pdecrypt_init) *pdecrypt_init = pmeth->decrypt_init; if (pdecrypt) *pdecrypt = pmeth->decrypt; } #endif static CK_MECHANISM_TYPE pkcs11_md2ckm(const EVP_MD *md) { switch (EVP_MD_type(md)) { case NID_sha1: return CKM_SHA_1; case NID_sha224: return CKM_SHA224; case NID_sha256: return CKM_SHA256; case NID_sha512: return CKM_SHA512; case NID_sha384: return CKM_SHA384; default: return 0; } } static CK_RSA_PKCS_MGF_TYPE pkcs11_md2ckg(const EVP_MD *md) { switch (EVP_MD_type(md)) { case NID_sha1: return CKG_MGF1_SHA1; case NID_sha224: return CKG_MGF1_SHA224; case NID_sha256: return CKG_MGF1_SHA256; case NID_sha512: return CKG_MGF1_SHA512; case NID_sha384: return CKG_MGF1_SHA384; default: return 0; } } static int pkcs11_params_pss(CK_RSA_PKCS_PSS_PARAMS *pss, EVP_PKEY_CTX *ctx) { const EVP_MD *sig_md, *mgf1_md; EVP_PKEY *evp_pkey; int salt_len; /* retrieve PSS parameters */ if (EVP_PKEY_CTX_get_signature_md(ctx, &sig_md) <= 0) return -1; if (EVP_PKEY_CTX_get_rsa_mgf1_md(ctx, &mgf1_md) <= 0) return -1; if (!EVP_PKEY_CTX_get_rsa_pss_saltlen(ctx, &salt_len)) return -1; switch (salt_len) { case -1: salt_len = EVP_MD_size(sig_md); break; case -2: evp_pkey = EVP_PKEY_CTX_get0_pkey(ctx); if (evp_pkey == NULL) return -1; salt_len = EVP_PKEY_size(evp_pkey) - EVP_MD_size(sig_md) - 2; if (((EVP_PKEY_bits(evp_pkey) - 1) & 0x7) == 0) salt_len--; if (salt_len < 0) /* integer underflow detected */ return -1; } #ifdef DEBUG fprintf(stderr, "salt_len=%d sig_md=%s mdf1_md=%s\n", salt_len, EVP_MD_name(sig_md), EVP_MD_name(mgf1_md)); #endif /* fill the CK_RSA_PKCS_PSS_PARAMS structure */ memset(pss, 0, sizeof(CK_RSA_PKCS_PSS_PARAMS)); pss->hashAlg = pkcs11_md2ckm(sig_md); pss->mgf = pkcs11_md2ckg(mgf1_md); if (!pss->hashAlg || !pss->mgf) return -1; pss->sLen = salt_len; return 0; } static int pkcs11_params_oaep(CK_RSA_PKCS_OAEP_PARAMS *oaep, EVP_PKEY_CTX *ctx) { const EVP_MD *oaep_md, *mgf1_md; /* retrieve OAEP parameters */ if (EVP_PKEY_CTX_get_rsa_oaep_md(ctx, &oaep_md) <= 0) return -1; if (EVP_PKEY_CTX_get_rsa_mgf1_md(ctx, &mgf1_md) <= 0) return -1; #ifdef DEBUG fprintf(stderr, "oaep_md=%s mdf1_md=%s\n", EVP_MD_name(oaep_md), EVP_MD_name(mgf1_md)); #endif /* fill the CK_RSA_PKCS_OAEP_PARAMS structure */ memset(oaep, 0, sizeof(CK_RSA_PKCS_OAEP_PARAMS)); oaep->hashAlg = pkcs11_md2ckm(oaep_md); oaep->mgf = pkcs11_md2ckg(mgf1_md); if (!oaep->hashAlg || !oaep->mgf) return -1; /* we do not support the OAEP "label" parameter yet... */ oaep->source = 0UL; /* empty parameter (label) */ oaep->pSourceData = NULL; oaep->ulSourceDataLen = 0; return 0; } static int pkcs11_try_pkey_rsa_sign(EVP_PKEY_CTX *evp_pkey_ctx, unsigned char *sig, size_t *siglen, const unsigned char *tbs, size_t tbslen) { EVP_PKEY *pkey; RSA *rsa; PKCS11_KEY *key; int rv = 0; CK_ULONG size = *siglen; PKCS11_SLOT *slot; PKCS11_CTX *ctx; PKCS11_KEY_private *kpriv; PKCS11_SLOT_private *spriv; PKCS11_CTX_private *cpriv; const EVP_MD *sig_md; #ifdef DEBUG fprintf(stderr, "%s:%d pkcs11_try_pkey_rsa_sign() " "sig=%p *siglen=%lu tbs=%p tbslen=%lu\n", __FILE__, __LINE__, sig, *siglen, tbs, tbslen); #endif pkey = EVP_PKEY_CTX_get0_pkey(evp_pkey_ctx); if (pkey == NULL) return -1; rsa = EVP_PKEY_get0_RSA(pkey); if (rsa == NULL) return -1; key = pkcs11_get_ex_data_rsa(rsa); if (check_key_fork(key) < 0) return -1; slot = KEY2SLOT(key); ctx = KEY2CTX(key); kpriv = PRIVKEY(key); spriv = PRIVSLOT(slot); cpriv = PRIVCTX(ctx); if (evp_pkey_ctx == NULL) return -1; if (EVP_PKEY_CTX_get_signature_md(evp_pkey_ctx, &sig_md) <= 0) return -1; if (tbslen != (size_t)EVP_MD_size(sig_md)) return -1; if (!cpriv->sign_initialized) { int padding; CK_MECHANISM mechanism; CK_RSA_PKCS_PSS_PARAMS pss_params; memset(&mechanism, 0, sizeof mechanism); EVP_PKEY_CTX_get_rsa_padding(evp_pkey_ctx, &padding); switch (padding) { case RSA_PKCS1_PSS_PADDING: #ifdef DEBUG fprintf(stderr, "%s:%d padding=RSA_PKCS1_PSS_PADDING\n", __FILE__, __LINE__); #endif if (pkcs11_params_pss(&pss_params, evp_pkey_ctx) < 0) return -1; mechanism.mechanism = CKM_RSA_PKCS_PSS; mechanism.pParameter = &pss_params; mechanism.ulParameterLen = sizeof pss_params; break; default: #ifdef DEBUG fprintf(stderr, "%s:%d unsupported padding: %d\n", __FILE__, __LINE__, padding); #endif return -1; } /* end switch(padding) */ CRYPTO_THREAD_write_lock(cpriv->rwlock); rv = CRYPTOKI_call(ctx, C_SignInit(spriv->session, &mechanism, kpriv->object)); if (!rv && kpriv->always_authenticate == CK_TRUE) rv = pkcs11_authenticate(key); } if (!rv) rv = CRYPTOKI_call(ctx, C_Sign(spriv->session, (CK_BYTE_PTR)tbs, tbslen, sig, &size)); cpriv->sign_initialized = !rv && sig == NULL; if (!cpriv->sign_initialized) CRYPTO_THREAD_unlock(cpriv->rwlock); #ifdef DEBUG fprintf(stderr, "%s:%d C_SignInit or C_Sign rv=%d\n", __FILE__, __LINE__, rv); #endif if (rv != CKR_OK) return -1; *siglen = size; return 1; } static int pkcs11_pkey_rsa_sign(EVP_PKEY_CTX *evp_pkey_ctx, unsigned char *sig, size_t *siglen, const unsigned char *tbs, size_t tbslen) { int ret; ret = pkcs11_try_pkey_rsa_sign(evp_pkey_ctx, sig, siglen, tbs, tbslen); if (ret < 0) ret = (*orig_pkey_rsa_sign)(evp_pkey_ctx, sig, siglen, tbs, tbslen); return ret; } static int pkcs11_try_pkey_rsa_decrypt(EVP_PKEY_CTX *evp_pkey_ctx, unsigned char *out, size_t *outlen, const unsigned char *in, size_t inlen) { EVP_PKEY *pkey; RSA *rsa; PKCS11_KEY *key; int rv = 0; CK_ULONG size = *outlen; PKCS11_SLOT *slot; PKCS11_CTX *ctx; PKCS11_KEY_private *kpriv; PKCS11_SLOT_private *spriv; PKCS11_CTX_private *cpriv; #ifdef DEBUG fprintf(stderr, "%s:%d pkcs11_try_pkey_rsa_decrypt() " "out=%p *outlen=%lu in=%p inlen=%lu\n", __FILE__, __LINE__, out, *outlen, in, inlen); #endif pkey = EVP_PKEY_CTX_get0_pkey(evp_pkey_ctx); if (pkey == NULL) return -1; rsa = EVP_PKEY_get0_RSA(pkey); if (rsa == NULL) return -1; key = pkcs11_get_ex_data_rsa(rsa); if (check_key_fork(key) < 0) return -1; slot = KEY2SLOT(key); ctx = KEY2CTX(key); kpriv = PRIVKEY(key); spriv = PRIVSLOT(slot); cpriv = PRIVCTX(ctx); if (evp_pkey_ctx == NULL) return -1; if (!cpriv->decrypt_initialized) { int padding; CK_MECHANISM mechanism; CK_RSA_PKCS_OAEP_PARAMS oaep_params; memset(&mechanism, 0, sizeof mechanism); EVP_PKEY_CTX_get_rsa_padding(evp_pkey_ctx, &padding); switch (padding) { case RSA_PKCS1_OAEP_PADDING: #ifdef DEBUG fprintf(stderr, "%s:%d padding=RSA_PKCS1_OAEP_PADDING\n", __FILE__, __LINE__); #endif if (pkcs11_params_oaep(&oaep_params, evp_pkey_ctx) < 0) return -1; mechanism.mechanism = CKM_RSA_PKCS_OAEP; mechanism.pParameter = &oaep_params; mechanism.ulParameterLen = sizeof oaep_params; break; case CKM_RSA_PKCS: #ifdef DEBUG fprintf(stderr, "%s:%d padding=CKM_RSA_PKCS\n", __FILE__, __LINE__); #endif mechanism.pParameter = NULL; mechanism.ulParameterLen = 0; break; default: #ifdef DEBUG fprintf(stderr, "%s:%d unsupported padding: %d\n", __FILE__, __LINE__, padding); #endif return -1; } /* end switch(padding) */ CRYPTO_THREAD_write_lock(cpriv->rwlock); rv = CRYPTOKI_call(ctx, C_DecryptInit(spriv->session, &mechanism, kpriv->object)); if (!rv && kpriv->always_authenticate == CK_TRUE) rv = pkcs11_authenticate(key); } if (!rv) rv = CRYPTOKI_call(ctx, C_Decrypt(spriv->session, (CK_BYTE_PTR)in, inlen, out, &size)); cpriv->decrypt_initialized = !rv && out == NULL; if (!cpriv->decrypt_initialized) CRYPTO_THREAD_unlock(cpriv->rwlock); #ifdef DEBUG fprintf(stderr, "%s:%d C_DecryptInit or C_Decrypt rv=%d\n", __FILE__, __LINE__, rv); #endif if (rv != CKR_OK) return -1; *outlen = size; return 1; } static int pkcs11_pkey_rsa_decrypt(EVP_PKEY_CTX *evp_pkey_ctx, unsigned char *out, size_t *outlen, const unsigned char *in, size_t inlen) { int ret; ret = pkcs11_try_pkey_rsa_decrypt(evp_pkey_ctx, out, outlen, in, inlen); if (ret < 0) ret = (*orig_pkey_rsa_decrypt)(evp_pkey_ctx, out, outlen, in, inlen); return ret; } static EVP_PKEY_METHOD *pkcs11_pkey_method_rsa() { EVP_PKEY_METHOD *orig_meth, *new_meth; orig_meth = (EVP_PKEY_METHOD *)EVP_PKEY_meth_find(EVP_PKEY_RSA); EVP_PKEY_meth_get_sign(orig_meth, &orig_pkey_rsa_sign_init, &orig_pkey_rsa_sign); EVP_PKEY_meth_get_decrypt(orig_meth, &orig_pkey_rsa_decrypt_init, &orig_pkey_rsa_decrypt); new_meth = EVP_PKEY_meth_new(EVP_PKEY_RSA, EVP_PKEY_FLAG_AUTOARGLEN); EVP_PKEY_meth_copy(new_meth, orig_meth); EVP_PKEY_meth_set_sign(new_meth, orig_pkey_rsa_sign_init, pkcs11_pkey_rsa_sign); EVP_PKEY_meth_set_decrypt(new_meth, orig_pkey_rsa_decrypt_init, pkcs11_pkey_rsa_decrypt); return new_meth; } #ifndef OPENSSL_NO_EC static int pkcs11_try_pkey_ec_sign(EVP_PKEY_CTX *evp_pkey_ctx, unsigned char *sig, size_t *siglen, const unsigned char *tbs, size_t tbslen) { EVP_PKEY *pkey; EC_KEY *eckey; PKCS11_KEY *key; int rv = 0; CK_ULONG size = *siglen; PKCS11_SLOT *slot; PKCS11_CTX *ctx; PKCS11_KEY_private *kpriv; PKCS11_SLOT_private *spriv; PKCS11_CTX_private *cpriv; const EVP_MD *sig_md; ECDSA_SIG *ossl_sig; #ifdef DEBUG fprintf(stderr, "%s:%d pkcs11_try_pkey_ec_sign() " "sig=%p *siglen=%lu tbs=%p tbslen=%lu\n", __FILE__, __LINE__, sig, *siglen, tbs, tbslen); #endif ossl_sig = ECDSA_SIG_new(); if (ossl_sig == NULL) return -1; pkey = EVP_PKEY_CTX_get0_pkey(evp_pkey_ctx); if (pkey == NULL) return -1; eckey = (EC_KEY *)EVP_PKEY_get0_EC_KEY(pkey); if (eckey == NULL) return -1; if (*siglen < (size_t)ECDSA_size(eckey)) return -1; key = pkcs11_get_ex_data_ec(eckey); if (check_key_fork(key) < 0) return -1; slot = KEY2SLOT(key); ctx = KEY2CTX(key); kpriv = PRIVKEY(key); spriv = PRIVSLOT(slot); cpriv = PRIVCTX(ctx); if (evp_pkey_ctx == NULL) return -1; if (EVP_PKEY_CTX_get_signature_md(evp_pkey_ctx, &sig_md) <= 0) return -1; if (tbslen < (size_t)EVP_MD_size(sig_md)) return -1; if (!cpriv->sign_initialized) { CK_MECHANISM mechanism; memset(&mechanism, 0, sizeof mechanism); mechanism.mechanism = CKM_ECDSA; CRYPTO_THREAD_write_lock(cpriv->rwlock); rv = CRYPTOKI_call(ctx, C_SignInit(spriv->session, &mechanism, kpriv->object)); if (!rv && kpriv->always_authenticate == CK_TRUE) rv = pkcs11_authenticate(key); } if (!rv) rv = CRYPTOKI_call(ctx, C_Sign(spriv->session, (CK_BYTE_PTR)tbs, tbslen, sig, &size)); cpriv->sign_initialized = !rv && sig == NULL; if (!cpriv->sign_initialized) CRYPTO_THREAD_unlock(cpriv->rwlock); #ifdef DEBUG fprintf(stderr, "%s:%d C_SignInit or C_Sign rv=%d\n", __FILE__, __LINE__, rv); #endif if (rv == CKR_OK) { BIGNUM *r = BN_bin2bn(sig, size/2, NULL); BIGNUM *s = BN_bin2bn(sig + size/2, size/2, NULL); #if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER) ECDSA_SIG_set0(ossl_sig, r, s); #else BN_free(ossl_sig->r); ossl_sig->r = r; BN_free(ossl_sig->s); ossl_sig->s = s; #endif *siglen = i2d_ECDSA_SIG(ossl_sig, &sig); } ECDSA_SIG_free(ossl_sig); if (rv != CKR_OK) return -1; return 1; } static int pkcs11_pkey_ec_sign(EVP_PKEY_CTX *evp_pkey_ctx, unsigned char *sig, size_t *siglen, const unsigned char *tbs, size_t tbslen) { int ret; ret = pkcs11_try_pkey_ec_sign(evp_pkey_ctx, sig, siglen, tbs, tbslen); if (ret < 0) ret = (*orig_pkey_ec_sign)(evp_pkey_ctx, sig, siglen, tbs, tbslen); return ret; } static EVP_PKEY_METHOD *pkcs11_pkey_method_ec() { EVP_PKEY_METHOD *orig_meth, *new_meth; orig_meth = (EVP_PKEY_METHOD *)EVP_PKEY_meth_find(EVP_PKEY_EC); EVP_PKEY_meth_get_sign(orig_meth, &orig_pkey_ec_sign_init, &orig_pkey_ec_sign); new_meth = EVP_PKEY_meth_new(EVP_PKEY_EC, EVP_PKEY_FLAG_AUTOARGLEN); EVP_PKEY_meth_copy(new_meth, orig_meth); EVP_PKEY_meth_set_sign(new_meth, orig_pkey_ec_sign_init, pkcs11_pkey_ec_sign); return new_meth; } #endif /* OPENSSL_NO_EC */ int PKCS11_pkey_meths(ENGINE *e, EVP_PKEY_METHOD **pmeth, const int **nids, int nid) { static int pkey_nids[] = { EVP_PKEY_RSA, EVP_PKEY_EC, 0 }; EVP_PKEY_METHOD *pkey_method_rsa = NULL; EVP_PKEY_METHOD *pkey_method_ec = NULL; (void)e; /* squash the unused parameter warning */ /* all PKCS#11 engines currently share the same pkey_meths */ if (!pmeth) { /* get the list of supported nids */ *nids = pkey_nids; return sizeof(pkey_nids) / sizeof(int) - 1; } /* get the EVP_PKEY_METHOD */ switch (nid) { case EVP_PKEY_RSA: pkey_method_rsa = pkcs11_pkey_method_rsa(); if (pkey_method_rsa == NULL) return 0; *pmeth = pkey_method_rsa; return 1; /* success */ #ifndef OPENSSL_NO_EC case EVP_PKEY_EC: pkey_method_ec = pkcs11_pkey_method_ec(); if (pkey_method_ec == NULL) return 0; *pmeth = pkey_method_ec; return 1; /* success */ #endif /* OPENSSL_NO_EC */ } *pmeth = NULL; return 0; } /* vim: set noexpandtab: */