|
Packit |
6b81fa |
/* libp11, a simple layer on to of PKCS#11 API
|
|
Packit |
6b81fa |
* Copyright (C) 2005 Olaf Kirch <okir@lst.de>
|
|
Packit |
6b81fa |
* Copyright (C) 2016-2017 MichaĆ Trojnara <Michal.Trojnara@stunnel.org>
|
|
Packit |
6b81fa |
*
|
|
Packit |
6b81fa |
* This library is free software; you can redistribute it and/or
|
|
Packit |
6b81fa |
* modify it under the terms of the GNU Lesser General Public
|
|
Packit |
6b81fa |
* License as published by the Free Software Foundation; either
|
|
Packit |
6b81fa |
* version 2.1 of the License, or (at your option) any later version.
|
|
Packit |
6b81fa |
*
|
|
Packit |
6b81fa |
* This library is distributed in the hope that it will be useful,
|
|
Packit |
6b81fa |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
6b81fa |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit |
6b81fa |
* Lesser General Public License for more details.
|
|
Packit |
6b81fa |
*
|
|
Packit |
6b81fa |
* You should have received a copy of the GNU Lesser General Public
|
|
Packit |
6b81fa |
* License along with this library; if not, write to the Free Software
|
|
Packit |
6b81fa |
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
Packit |
6b81fa |
*/
|
|
Packit |
6b81fa |
|
|
Packit |
6b81fa |
/*
|
|
Packit |
6b81fa |
* This file implements the handling of RSA keys stored on a
|
|
Packit |
6b81fa |
* PKCS11 token
|
|
Packit |
6b81fa |
*/
|
|
Packit |
6b81fa |
|
|
Packit |
6b81fa |
#include "libp11-int.h"
|
|
Packit |
6b81fa |
#include <string.h>
|
|
Packit |
6b81fa |
#include <openssl/evp.h>
|
|
Packit |
6b81fa |
#include <openssl/rsa.h>
|
|
Packit |
6b81fa |
|
|
Packit |
6b81fa |
static int rsa_ex_index = 0;
|
|
Packit |
6b81fa |
|
|
Packit |
6b81fa |
static RSA *pkcs11_rsa(PKCS11_KEY *key)
|
|
Packit |
6b81fa |
{
|
|
Packit |
6b81fa |
EVP_PKEY *evp_key = pkcs11_get_key(key, key->isPrivate);
|
|
Packit |
6b81fa |
RSA *rsa;
|
|
Packit |
6b81fa |
if (evp_key == NULL)
|
|
Packit |
6b81fa |
return NULL;
|
|
Packit |
6b81fa |
rsa = EVP_PKEY_get0_RSA(evp_key);
|
|
Packit |
6b81fa |
EVP_PKEY_free(evp_key);
|
|
Packit |
6b81fa |
return rsa;
|
|
Packit |
6b81fa |
}
|
|
Packit |
6b81fa |
|
|
Packit |
6b81fa |
/* PKCS#1 v1.5 RSA signature */
|
|
Packit |
6b81fa |
/* TODO: remove this function in libp11 0.5.0 */
|
|
Packit |
6b81fa |
int pkcs11_sign(int type, const unsigned char *m, unsigned int m_len,
|
|
Packit |
6b81fa |
unsigned char *sigret, unsigned int *siglen, PKCS11_KEY *key)
|
|
Packit |
6b81fa |
{
|
|
Packit |
6b81fa |
RSA *rsa = pkcs11_rsa(key);
|
|
Packit |
6b81fa |
if (rsa == NULL)
|
|
Packit |
6b81fa |
return -1;
|
|
Packit |
6b81fa |
return RSA_sign(type, m, m_len, sigret, siglen, rsa);
|
|
Packit |
6b81fa |
}
|
|
Packit |
6b81fa |
|
|
Packit |
6b81fa |
/* Setup PKCS#11 mechanisms for encryption/decryption */
|
|
Packit |
6b81fa |
static int pkcs11_mechanism(CK_MECHANISM *mechanism, const int padding)
|
|
Packit |
6b81fa |
{
|
|
Packit |
6b81fa |
memset(mechanism, 0, sizeof(CK_MECHANISM));
|
|
Packit |
6b81fa |
switch (padding) {
|
|
Packit |
6b81fa |
case RSA_PKCS1_PADDING:
|
|
Packit |
6b81fa |
mechanism->mechanism = CKM_RSA_PKCS;
|
|
Packit |
6b81fa |
break;
|
|
Packit |
6b81fa |
case RSA_NO_PADDING:
|
|
Packit |
6b81fa |
mechanism->mechanism = CKM_RSA_X_509;
|
|
Packit |
6b81fa |
break;
|
|
Packit |
6b81fa |
case RSA_X931_PADDING:
|
|
Packit |
6b81fa |
mechanism->mechanism = CKM_RSA_X9_31;
|
|
Packit |
6b81fa |
break;
|
|
Packit |
6b81fa |
default:
|
|
Packit |
6b81fa |
P11err(P11_F_PKCS11_MECHANISM, P11_R_UNSUPPORTED_PADDING_TYPE);
|
|
Packit |
6b81fa |
return -1;
|
|
Packit |
6b81fa |
}
|
|
Packit |
6b81fa |
return 0;
|
|
Packit |
6b81fa |
}
|
|
Packit |
6b81fa |
|
|
Packit |
6b81fa |
/* RSA private key encryption (also invoked by OpenSSL for signing) */
|
|
Packit |
6b81fa |
/* OpenSSL assumes that the output buffer is always big enough */
|
|
Packit |
6b81fa |
int pkcs11_private_encrypt(int flen,
|
|
Packit |
6b81fa |
const unsigned char *from, unsigned char *to,
|
|
Packit |
6b81fa |
PKCS11_KEY *key, int padding)
|
|
Packit |
6b81fa |
{
|
|
Packit |
6b81fa |
PKCS11_SLOT *slot = KEY2SLOT(key);
|
|
Packit |
6b81fa |
PKCS11_CTX *ctx = KEY2CTX(key);
|
|
Packit |
6b81fa |
PKCS11_KEY_private *kpriv = PRIVKEY(key);
|
|
Packit |
6b81fa |
PKCS11_SLOT_private *spriv = PRIVSLOT(slot);
|
|
Packit |
6b81fa |
CK_MECHANISM mechanism;
|
|
Packit |
6b81fa |
CK_ULONG size;
|
|
Packit |
6b81fa |
int rv;
|
|
Packit |
6b81fa |
|
|
Packit |
6b81fa |
size = pkcs11_get_key_size(key);
|
|
Packit |
6b81fa |
|
|
Packit |
6b81fa |
if (pkcs11_mechanism(&mechanism, padding) < 0)
|
|
Packit |
6b81fa |
return -1;
|
|
Packit |
6b81fa |
|
|
Packit |
6b81fa |
CRYPTO_THREAD_write_lock(PRIVCTX(ctx)->rwlock);
|
|
Packit |
6b81fa |
/* Try signing first, as applications are more likely to use it */
|
|
Packit |
6b81fa |
rv = CRYPTOKI_call(ctx,
|
|
Packit |
6b81fa |
C_SignInit(spriv->session, &mechanism, kpriv->object));
|
|
Packit |
6b81fa |
if (!rv && kpriv->always_authenticate == CK_TRUE)
|
|
Packit |
6b81fa |
rv = pkcs11_authenticate(key);
|
|
Packit |
6b81fa |
if (!rv)
|
|
Packit |
6b81fa |
rv = CRYPTOKI_call(ctx,
|
|
Packit |
6b81fa |
C_Sign(spriv->session, (CK_BYTE *)from, flen, to, &size));
|
|
Packit |
6b81fa |
if (rv == CKR_KEY_FUNCTION_NOT_PERMITTED) {
|
|
Packit |
6b81fa |
/* OpenSSL may use it for encryption rather than signing */
|
|
Packit |
6b81fa |
rv = CRYPTOKI_call(ctx,
|
|
Packit |
6b81fa |
C_EncryptInit(spriv->session, &mechanism, kpriv->object));
|
|
Packit |
6b81fa |
if (!rv && kpriv->always_authenticate == CK_TRUE)
|
|
Packit |
6b81fa |
rv = pkcs11_authenticate(key);
|
|
Packit |
6b81fa |
if (!rv)
|
|
Packit |
6b81fa |
rv = CRYPTOKI_call(ctx,
|
|
Packit |
6b81fa |
C_Encrypt(spriv->session, (CK_BYTE *)from, flen, to, &size));
|
|
Packit |
6b81fa |
}
|
|
Packit |
6b81fa |
CRYPTO_THREAD_unlock(PRIVCTX(ctx)->rwlock);
|
|
Packit |
6b81fa |
|
|
Packit |
6b81fa |
if (rv) {
|
|
Packit |
6b81fa |
CKRerr(CKR_F_PKCS11_PRIVATE_ENCRYPT, rv);
|
|
Packit |
6b81fa |
return -1;
|
|
Packit |
6b81fa |
}
|
|
Packit |
6b81fa |
|
|
Packit |
6b81fa |
return size;
|
|
Packit |
6b81fa |
}
|
|
Packit |
6b81fa |
|
|
Packit |
6b81fa |
/* RSA private key decryption */
|
|
Packit |
6b81fa |
int pkcs11_private_decrypt(int flen, const unsigned char *from, unsigned char *to,
|
|
Packit |
6b81fa |
PKCS11_KEY *key, int padding)
|
|
Packit |
6b81fa |
{
|
|
Packit |
6b81fa |
PKCS11_SLOT *slot = KEY2SLOT(key);
|
|
Packit |
6b81fa |
PKCS11_CTX *ctx = KEY2CTX(key);
|
|
Packit |
6b81fa |
PKCS11_KEY_private *kpriv = PRIVKEY(key);
|
|
Packit |
6b81fa |
PKCS11_SLOT_private *spriv = PRIVSLOT(slot);
|
|
Packit |
6b81fa |
CK_MECHANISM mechanism;
|
|
Packit |
6b81fa |
CK_ULONG size = flen;
|
|
Packit |
6b81fa |
CK_RV rv;
|
|
Packit |
6b81fa |
|
|
Packit |
6b81fa |
if (pkcs11_mechanism(&mechanism, padding) < 0)
|
|
Packit |
6b81fa |
return -1;
|
|
Packit |
6b81fa |
|
|
Packit |
6b81fa |
CRYPTO_THREAD_write_lock(PRIVCTX(ctx)->rwlock);
|
|
Packit |
6b81fa |
rv = CRYPTOKI_call(ctx,
|
|
Packit |
6b81fa |
C_DecryptInit(spriv->session, &mechanism, kpriv->object));
|
|
Packit |
6b81fa |
if (!rv && kpriv->always_authenticate == CK_TRUE)
|
|
Packit |
6b81fa |
rv = pkcs11_authenticate(key);
|
|
Packit |
6b81fa |
if (!rv)
|
|
Packit |
6b81fa |
rv = CRYPTOKI_call(ctx,
|
|
Packit |
6b81fa |
C_Decrypt(spriv->session, (CK_BYTE *)from, size,
|
|
Packit |
6b81fa |
(CK_BYTE_PTR)to, &size));
|
|
Packit |
6b81fa |
CRYPTO_THREAD_unlock(PRIVCTX(ctx)->rwlock);
|
|
Packit |
6b81fa |
|
|
Packit |
6b81fa |
if (rv) {
|
|
Packit |
6b81fa |
CKRerr(CKR_F_PKCS11_PRIVATE_DECRYPT, rv);
|
|
Packit |
6b81fa |
return -1;
|
|
Packit |
6b81fa |
}
|
|
Packit |
6b81fa |
|
|
Packit |
6b81fa |
return size;
|
|
Packit |
6b81fa |
}
|
|
Packit |
6b81fa |
|
|
Packit |
6b81fa |
/* TODO: remove this function in libp11 0.5.0 */
|
|
Packit |
6b81fa |
int pkcs11_verify(int type, const unsigned char *m, unsigned int m_len,
|
|
Packit |
6b81fa |
unsigned char *signature, unsigned int siglen, PKCS11_KEY *key)
|
|
Packit |
6b81fa |
{
|
|
Packit |
6b81fa |
(void)type;
|
|
Packit |
6b81fa |
(void)m;
|
|
Packit |
6b81fa |
(void)m_len;
|
|
Packit |
6b81fa |
(void)signature;
|
|
Packit |
6b81fa |
(void)siglen;
|
|
Packit |
6b81fa |
(void)key;
|
|
Packit |
6b81fa |
|
|
Packit |
6b81fa |
/* PKCS11 calls go here */
|
|
Packit |
6b81fa |
P11err(P11_F_PKCS11_VERIFY, P11_R_NOT_SUPPORTED);
|
|
Packit |
6b81fa |
return -1;
|
|
Packit |
6b81fa |
}
|
|
Packit |
6b81fa |
|
|
Packit |
6b81fa |
/*
|
|
Packit |
6b81fa |
* Get RSA key material
|
|
Packit |
6b81fa |
*/
|
|
Packit |
6b81fa |
static RSA *pkcs11_get_rsa(PKCS11_KEY *key)
|
|
Packit |
6b81fa |
{
|
|
Packit |
6b81fa |
RSA *rsa;
|
|
Packit |
6b81fa |
PKCS11_KEY *keys;
|
|
Packit |
6b81fa |
unsigned int i, count;
|
|
Packit |
6b81fa |
BIGNUM *rsa_n = NULL, *rsa_e = NULL;
|
|
Packit |
6b81fa |
|
|
Packit |
6b81fa |
/* Retrieve the modulus */
|
|
Packit |
6b81fa |
if (key_getattr_bn(key, CKA_MODULUS, &rsa_n))
|
|
Packit |
6b81fa |
return NULL;
|
|
Packit |
6b81fa |
|
|
Packit |
6b81fa |
/* Retrieve the public exponent */
|
|
Packit |
6b81fa |
if (!key_getattr_bn(key, CKA_PUBLIC_EXPONENT, &rsa_e)) {
|
|
Packit |
6b81fa |
if (!BN_is_zero(rsa_e)) /* A valid public exponent */
|
|
Packit |
6b81fa |
goto success;
|
|
Packit |
6b81fa |
BN_clear_free(rsa_e);
|
|
Packit |
6b81fa |
rsa_e = NULL;
|
|
Packit |
6b81fa |
}
|
|
Packit |
6b81fa |
|
|
Packit |
6b81fa |
/* The public exponent was not found in the private key:
|
|
Packit |
6b81fa |
* retrieve it from the corresponding public key */
|
|
Packit |
6b81fa |
if (!PKCS11_enumerate_public_keys(KEY2TOKEN(key), &keys, &count)) {
|
|
Packit |
6b81fa |
for (i = 0; i < count; i++) {
|
|
Packit |
6b81fa |
BIGNUM *pubmod = NULL;
|
|
Packit |
6b81fa |
if (!key_getattr_bn(&keys[i], CKA_MODULUS, &pubmod)) {
|
|
Packit |
6b81fa |
int found = BN_cmp(rsa_n, pubmod) == 0;
|
|
Packit |
6b81fa |
BN_clear_free(pubmod);
|
|
Packit |
6b81fa |
if (found && !key_getattr_bn(&keys[i],
|
|
Packit |
6b81fa |
CKA_PUBLIC_EXPONENT, &rsa_e))
|
|
Packit |
6b81fa |
goto success;
|
|
Packit |
6b81fa |
}
|
|
Packit |
6b81fa |
}
|
|
Packit |
6b81fa |
}
|
|
Packit |
6b81fa |
|
|
Packit |
6b81fa |
/* Last resort: use the most common default */
|
|
Packit |
6b81fa |
rsa_e = BN_new();
|
|
Packit |
6b81fa |
if (rsa_e && BN_set_word(rsa_e, RSA_F4))
|
|
Packit |
6b81fa |
goto success;
|
|
Packit |
6b81fa |
|
|
Packit |
6b81fa |
failure:
|
|
Packit |
6b81fa |
if (rsa_n)
|
|
Packit |
6b81fa |
BN_clear_free(rsa_n);
|
|
Packit |
6b81fa |
if (rsa_e)
|
|
Packit |
6b81fa |
BN_clear_free(rsa_e);
|
|
Packit |
6b81fa |
return NULL;
|
|
Packit |
6b81fa |
|
|
Packit |
6b81fa |
success:
|
|
Packit |
6b81fa |
rsa = RSA_new();
|
|
Packit |
6b81fa |
if (rsa == NULL)
|
|
Packit |
6b81fa |
goto failure;
|
|
Packit |
6b81fa |
#if OPENSSL_VERSION_NUMBER >= 0x10100005L && !defined(LIBRESSL_VERSION_NUMBER)
|
|
Packit |
6b81fa |
RSA_set0_key(rsa, rsa_n, rsa_e, NULL);
|
|
Packit |
6b81fa |
#else
|
|
Packit |
6b81fa |
rsa->n = rsa_n;
|
|
Packit |
6b81fa |
rsa->e = rsa_e;
|
|
Packit |
6b81fa |
#endif
|
|
Packit |
6b81fa |
return rsa;
|
|
Packit |
6b81fa |
}
|
|
Packit |
6b81fa |
|
|
Packit |
6b81fa |
PKCS11_KEY *pkcs11_get_ex_data_rsa(const RSA *rsa)
|
|
Packit |
6b81fa |
{
|
|
Packit |
6b81fa |
return RSA_get_ex_data(rsa, rsa_ex_index);
|
|
Packit |
6b81fa |
}
|
|
Packit |
6b81fa |
|
|
Packit |
6b81fa |
static void pkcs11_set_ex_data_rsa(RSA *rsa, PKCS11_KEY *key)
|
|
Packit |
6b81fa |
{
|
|
Packit |
6b81fa |
RSA_set_ex_data(rsa, rsa_ex_index, key);
|
|
Packit |
6b81fa |
}
|
|
Packit |
6b81fa |
|
|
Packit |
6b81fa |
static void pkcs11_update_ex_data_rsa(PKCS11_KEY *key)
|
|
Packit |
6b81fa |
{
|
|
Packit |
6b81fa |
EVP_PKEY *evp = key->evp_key;
|
|
Packit |
6b81fa |
RSA *rsa;
|
|
Packit |
6b81fa |
if (evp == NULL)
|
|
Packit |
6b81fa |
return;
|
|
Packit |
6b81fa |
if (EVP_PKEY_base_id(evp) != EVP_PKEY_RSA)
|
|
Packit |
6b81fa |
return;
|
|
Packit |
6b81fa |
|
|
Packit |
6b81fa |
rsa = EVP_PKEY_get1_RSA(evp);
|
|
Packit |
6b81fa |
pkcs11_set_ex_data_rsa(rsa, key);
|
|
Packit |
6b81fa |
RSA_free(rsa);
|
|
Packit |
6b81fa |
}
|
|
Packit |
6b81fa |
/*
|
|
Packit |
6b81fa |
* Build an EVP_PKEY object
|
|
Packit |
6b81fa |
*/
|
|
Packit |
6b81fa |
static EVP_PKEY *pkcs11_get_evp_key_rsa(PKCS11_KEY *key)
|
|
Packit |
6b81fa |
{
|
|
Packit |
6b81fa |
EVP_PKEY *pk;
|
|
Packit |
6b81fa |
RSA *rsa;
|
|
Packit |
6b81fa |
|
|
Packit |
6b81fa |
rsa = pkcs11_get_rsa(key);
|
|
Packit |
6b81fa |
if (rsa == NULL)
|
|
Packit |
6b81fa |
return NULL;
|
|
Packit |
6b81fa |
pk = EVP_PKEY_new();
|
|
Packit |
6b81fa |
if (pk == NULL) {
|
|
Packit |
6b81fa |
RSA_free(rsa);
|
|
Packit |
6b81fa |
return NULL;
|
|
Packit |
6b81fa |
}
|
|
Packit |
6b81fa |
EVP_PKEY_set1_RSA(pk, rsa); /* Also increments the rsa ref count */
|
|
Packit |
6b81fa |
|
|
Packit |
6b81fa |
if (key->isPrivate)
|
|
Packit |
6b81fa |
RSA_set_method(rsa, PKCS11_get_rsa_method());
|
|
Packit |
6b81fa |
/* TODO: Retrieve the RSA private key object attributes instead,
|
|
Packit |
6b81fa |
* unless the key has the "sensitive" attribute set */
|
|
Packit |
6b81fa |
|
|
Packit |
6b81fa |
#if OPENSSL_VERSION_NUMBER < 0x01010000L
|
|
Packit |
6b81fa |
/* RSA_FLAG_SIGN_VER is no longer needed since OpenSSL 1.1 */
|
|
Packit |
6b81fa |
rsa->flags |= RSA_FLAG_SIGN_VER;
|
|
Packit |
6b81fa |
#endif
|
|
Packit |
6b81fa |
pkcs11_set_ex_data_rsa(rsa, key);
|
|
Packit |
6b81fa |
RSA_free(rsa); /* Drops our reference to it */
|
|
Packit |
6b81fa |
return pk;
|
|
Packit |
6b81fa |
}
|
|
Packit |
6b81fa |
|
|
Packit |
6b81fa |
/* TODO: remove this function in libp11 0.5.0 */
|
|
Packit |
6b81fa |
int pkcs11_get_key_modulus(PKCS11_KEY *key, BIGNUM **bn)
|
|
Packit |
6b81fa |
{
|
|
Packit |
6b81fa |
RSA *rsa = pkcs11_rsa(key);
|
|
Packit |
6b81fa |
const BIGNUM *rsa_n;
|
|
Packit |
6b81fa |
|
|
Packit |
6b81fa |
if (rsa == NULL)
|
|
Packit |
6b81fa |
return 0;
|
|
Packit |
6b81fa |
#if OPENSSL_VERSION_NUMBER >= 0x10100005L && !defined(LIBRESSL_VERSION_NUMBER)
|
|
Packit |
6b81fa |
RSA_get0_key(rsa, &rsa_n, NULL, NULL);
|
|
Packit |
6b81fa |
#else
|
|
Packit |
6b81fa |
rsa_n=rsa->n;
|
|
Packit |
6b81fa |
#endif
|
|
Packit |
6b81fa |
*bn = BN_dup(rsa_n);
|
|
Packit |
6b81fa |
return *bn == NULL ? 0 : 1;
|
|
Packit |
6b81fa |
}
|
|
Packit |
6b81fa |
|
|
Packit |
6b81fa |
/* TODO: remove this function in libp11 0.5.0 */
|
|
Packit |
6b81fa |
int pkcs11_get_key_exponent(PKCS11_KEY *key, BIGNUM **bn)
|
|
Packit |
6b81fa |
{
|
|
Packit |
6b81fa |
RSA *rsa = pkcs11_rsa(key);
|
|
Packit |
6b81fa |
const BIGNUM *rsa_e;
|
|
Packit |
6b81fa |
|
|
Packit |
6b81fa |
if (rsa == NULL)
|
|
Packit |
6b81fa |
return 0;
|
|
Packit |
6b81fa |
#if OPENSSL_VERSION_NUMBER >= 0x10100005L && !defined(LIBRESSL_VERSION_NUMBER)
|
|
Packit |
6b81fa |
RSA_get0_key(rsa, NULL, &rsa_e, NULL);
|
|
Packit |
6b81fa |
#else
|
|
Packit |
6b81fa |
rsa_e=rsa->e;
|
|
Packit |
6b81fa |
#endif
|
|
Packit |
6b81fa |
*bn = BN_dup(rsa_e);
|
|
Packit |
6b81fa |
return *bn == NULL ? 0 : 1;
|
|
Packit |
6b81fa |
}
|
|
Packit |
6b81fa |
|
|
Packit |
6b81fa |
/* TODO: make this function static in libp11 0.5.0 */
|
|
Packit |
6b81fa |
int pkcs11_get_key_size(PKCS11_KEY *key)
|
|
Packit |
6b81fa |
{
|
|
Packit |
6b81fa |
RSA *rsa = pkcs11_rsa(key);
|
|
Packit |
6b81fa |
if (rsa == NULL)
|
|
Packit |
6b81fa |
return 0;
|
|
Packit |
6b81fa |
return RSA_size(rsa);
|
|
Packit |
6b81fa |
}
|
|
Packit |
6b81fa |
|
|
Packit |
6b81fa |
#if OPENSSL_VERSION_NUMBER < 0x10100005L || defined(LIBRESSL_VERSION_NUMBER)
|
|
Packit |
6b81fa |
|
|
Packit |
6b81fa |
int (*RSA_meth_get_priv_enc(const RSA_METHOD *meth))
|
|
Packit |
6b81fa |
(int flen, const unsigned char *from,
|
|
Packit |
6b81fa |
unsigned char *to, RSA *rsa, int padding)
|
|
Packit |
6b81fa |
{
|
|
Packit |
6b81fa |
return meth->rsa_priv_enc;
|
|
Packit |
6b81fa |
}
|
|
Packit |
6b81fa |
|
|
Packit |
6b81fa |
int (*RSA_meth_get_priv_dec(const RSA_METHOD *meth))
|
|
Packit |
6b81fa |
(int flen, const unsigned char *from,
|
|
Packit |
6b81fa |
unsigned char *to, RSA *rsa, int padding)
|
|
Packit |
6b81fa |
{
|
|
Packit |
6b81fa |
return meth->rsa_priv_dec;
|
|
Packit |
6b81fa |
}
|
|
Packit |
6b81fa |
|
|
Packit |
6b81fa |
#endif
|
|
Packit |
6b81fa |
|
|
Packit |
6b81fa |
static int pkcs11_rsa_priv_dec_method(int flen, const unsigned char *from,
|
|
Packit |
6b81fa |
unsigned char *to, RSA *rsa, int padding)
|
|
Packit |
6b81fa |
{
|
|
Packit |
6b81fa |
PKCS11_KEY *key = pkcs11_get_ex_data_rsa(rsa);
|
|
Packit |
6b81fa |
int (*priv_dec) (int flen, const unsigned char *from,
|
|
Packit |
6b81fa |
unsigned char *to, RSA *rsa, int padding);
|
|
Packit |
6b81fa |
if (check_key_fork(key) < 0) {
|
|
Packit |
6b81fa |
priv_dec = RSA_meth_get_priv_dec(RSA_get_default_method());
|
|
Packit |
6b81fa |
return priv_dec(flen, from, to, rsa, padding);
|
|
Packit |
6b81fa |
}
|
|
Packit |
6b81fa |
return PKCS11_private_decrypt(flen, from, to, key, padding);
|
|
Packit |
6b81fa |
}
|
|
Packit |
6b81fa |
|
|
Packit |
6b81fa |
static int pkcs11_rsa_priv_enc_method(int flen, const unsigned char *from,
|
|
Packit |
6b81fa |
unsigned char *to, RSA *rsa, int padding)
|
|
Packit |
6b81fa |
{
|
|
Packit |
6b81fa |
PKCS11_KEY *key = pkcs11_get_ex_data_rsa(rsa);
|
|
Packit |
6b81fa |
int (*priv_enc) (int flen, const unsigned char *from,
|
|
Packit |
6b81fa |
unsigned char *to, RSA *rsa, int padding);
|
|
Packit |
6b81fa |
if (check_key_fork(key) < 0) {
|
|
Packit |
6b81fa |
priv_enc = RSA_meth_get_priv_enc(RSA_get_default_method());
|
|
Packit |
6b81fa |
return priv_enc(flen, from, to, rsa, padding);
|
|
Packit |
6b81fa |
}
|
|
Packit |
6b81fa |
return PKCS11_private_encrypt(flen, from, to, key, padding);
|
|
Packit |
6b81fa |
}
|
|
Packit |
6b81fa |
|
|
Packit |
6b81fa |
static int pkcs11_rsa_free_method(RSA *rsa)
|
|
Packit |
6b81fa |
{
|
|
Packit |
6b81fa |
RSA_set_ex_data(rsa, rsa_ex_index, NULL);
|
|
Packit |
6b81fa |
return 1;
|
|
Packit |
6b81fa |
}
|
|
Packit |
6b81fa |
|
|
Packit |
6b81fa |
static void alloc_rsa_ex_index()
|
|
Packit |
6b81fa |
{
|
|
Packit |
6b81fa |
if (rsa_ex_index == 0) {
|
|
Packit |
6b81fa |
while (rsa_ex_index == 0) /* Workaround for OpenSSL RT3710 */
|
|
Packit |
6b81fa |
rsa_ex_index = RSA_get_ex_new_index(0, "libp11 rsa",
|
|
Packit |
6b81fa |
NULL, NULL, NULL);
|
|
Packit |
6b81fa |
if (rsa_ex_index < 0)
|
|
Packit |
6b81fa |
rsa_ex_index = 0; /* Fallback to app_data */
|
|
Packit |
6b81fa |
}
|
|
Packit |
6b81fa |
}
|
|
Packit |
6b81fa |
|
|
Packit |
6b81fa |
static void free_rsa_ex_index()
|
|
Packit |
6b81fa |
{
|
|
Packit |
6b81fa |
/* CRYPTO_free_ex_index requires OpenSSL version >= 1.1.0-pre1 */
|
|
Packit |
6b81fa |
#if OPENSSL_VERSION_NUMBER >= 0x10100001L && !defined(LIBRESSL_VERSION_NUMBER)
|
|
Packit |
6b81fa |
if (rsa_ex_index > 0) {
|
|
Packit |
6b81fa |
CRYPTO_free_ex_index(CRYPTO_EX_INDEX_RSA, rsa_ex_index);
|
|
Packit |
6b81fa |
rsa_ex_index = 0;
|
|
Packit |
6b81fa |
}
|
|
Packit |
6b81fa |
#endif
|
|
Packit |
6b81fa |
}
|
|
Packit |
6b81fa |
|
|
Packit |
6b81fa |
#if OPENSSL_VERSION_NUMBER < 0x10100005L || ( defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x2080000L )
|
|
Packit |
6b81fa |
|
|
Packit |
6b81fa |
static RSA_METHOD *RSA_meth_dup(const RSA_METHOD *meth)
|
|
Packit |
6b81fa |
{
|
|
Packit |
6b81fa |
RSA_METHOD *ret = OPENSSL_malloc(sizeof(RSA_METHOD));
|
|
Packit |
6b81fa |
if (ret == NULL)
|
|
Packit |
6b81fa |
return NULL;
|
|
Packit |
6b81fa |
memcpy(ret, meth, sizeof(RSA_METHOD));
|
|
Packit |
6b81fa |
ret->name = OPENSSL_strdup(meth->name);
|
|
Packit |
6b81fa |
if (ret->name == NULL) {
|
|
Packit |
6b81fa |
OPENSSL_free(ret);
|
|
Packit |
6b81fa |
return NULL;
|
|
Packit |
6b81fa |
}
|
|
Packit |
6b81fa |
return ret;
|
|
Packit |
6b81fa |
}
|
|
Packit |
6b81fa |
|
|
Packit |
6b81fa |
static int RSA_meth_set1_name(RSA_METHOD *meth, const char *name)
|
|
Packit |
6b81fa |
{
|
|
Packit |
6b81fa |
char *tmp = OPENSSL_strdup(name);
|
|
Packit |
6b81fa |
if (tmp == NULL)
|
|
Packit |
6b81fa |
return 0;
|
|
Packit |
6b81fa |
OPENSSL_free((char *)meth->name);
|
|
Packit |
6b81fa |
meth->name = tmp;
|
|
Packit |
6b81fa |
return 1;
|
|
Packit |
6b81fa |
}
|
|
Packit |
6b81fa |
|
|
Packit |
6b81fa |
#endif
|
|
Packit |
6b81fa |
|
|
Packit |
6b81fa |
#if OPENSSL_VERSION_NUMBER < 0x10100005L || defined(LIBRESSL_VERSION_NUMBER)
|
|
Packit |
6b81fa |
|
|
Packit |
6b81fa |
static int RSA_meth_set_flags(RSA_METHOD *meth, int flags)
|
|
Packit |
6b81fa |
{
|
|
Packit |
6b81fa |
meth->flags = flags;
|
|
Packit |
6b81fa |
return 1;
|
|
Packit |
6b81fa |
}
|
|
Packit |
6b81fa |
#endif
|
|
Packit |
6b81fa |
|
|
Packit |
6b81fa |
#if OPENSSL_VERSION_NUMBER < 0x10100005L || ( defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x2080000L )
|
|
Packit |
6b81fa |
|
|
Packit |
6b81fa |
static int RSA_meth_set_priv_enc(RSA_METHOD *meth,
|
|
Packit |
6b81fa |
int (*priv_enc) (int flen, const unsigned char *from,
|
|
Packit |
6b81fa |
unsigned char *to, RSA *rsa, int padding))
|
|
Packit |
6b81fa |
{
|
|
Packit |
6b81fa |
meth->rsa_priv_enc = priv_enc;
|
|
Packit |
6b81fa |
return 1;
|
|
Packit |
6b81fa |
}
|
|
Packit |
6b81fa |
|
|
Packit |
6b81fa |
static int RSA_meth_set_priv_dec(RSA_METHOD *meth,
|
|
Packit |
6b81fa |
int (*priv_dec) (int flen, const unsigned char *from,
|
|
Packit |
6b81fa |
unsigned char *to, RSA *rsa, int padding))
|
|
Packit |
6b81fa |
{
|
|
Packit |
6b81fa |
meth->rsa_priv_dec = priv_dec;
|
|
Packit |
6b81fa |
return 1;
|
|
Packit |
6b81fa |
}
|
|
Packit |
6b81fa |
|
|
Packit |
6b81fa |
static int RSA_meth_set_finish(RSA_METHOD *meth, int (*finish)(RSA *rsa))
|
|
Packit |
6b81fa |
{
|
|
Packit |
6b81fa |
meth->finish = finish;
|
|
Packit |
6b81fa |
return 1;
|
|
Packit |
6b81fa |
}
|
|
Packit |
6b81fa |
|
|
Packit |
6b81fa |
#endif
|
|
Packit |
6b81fa |
|
|
Packit |
6b81fa |
/*
|
|
Packit |
6b81fa |
* Overload the default OpenSSL methods for RSA
|
|
Packit |
6b81fa |
*/
|
|
Packit |
6b81fa |
RSA_METHOD *PKCS11_get_rsa_method(void)
|
|
Packit |
6b81fa |
{
|
|
Packit |
6b81fa |
static RSA_METHOD *ops = NULL;
|
|
Packit |
6b81fa |
|
|
Packit |
6b81fa |
if (ops == NULL) {
|
|
Packit |
6b81fa |
alloc_rsa_ex_index();
|
|
Packit |
6b81fa |
ops = RSA_meth_dup(RSA_get_default_method());
|
|
Packit |
6b81fa |
if (ops == NULL)
|
|
Packit |
6b81fa |
return NULL;
|
|
Packit |
6b81fa |
RSA_meth_set1_name(ops, "libp11 RSA method");
|
|
Packit Service |
975729 |
RSA_meth_set_flags(ops, 0);
|
|
Packit |
6b81fa |
RSA_meth_set_priv_enc(ops, pkcs11_rsa_priv_enc_method);
|
|
Packit |
6b81fa |
RSA_meth_set_priv_dec(ops, pkcs11_rsa_priv_dec_method);
|
|
Packit |
6b81fa |
RSA_meth_set_finish(ops, pkcs11_rsa_free_method);
|
|
Packit |
6b81fa |
}
|
|
Packit |
6b81fa |
return ops;
|
|
Packit |
6b81fa |
}
|
|
Packit |
6b81fa |
|
|
Packit |
6b81fa |
/* This function is *not* currently exported */
|
|
Packit |
6b81fa |
void PKCS11_rsa_method_free(void)
|
|
Packit |
6b81fa |
{
|
|
Packit |
6b81fa |
free_rsa_ex_index();
|
|
Packit |
6b81fa |
}
|
|
Packit |
6b81fa |
|
|
Packit |
6b81fa |
PKCS11_KEY_ops pkcs11_rsa_ops = {
|
|
Packit |
6b81fa |
EVP_PKEY_RSA,
|
|
Packit |
6b81fa |
pkcs11_get_evp_key_rsa,
|
|
Packit |
6b81fa |
pkcs11_update_ex_data_rsa
|
|
Packit |
6b81fa |
};
|
|
Packit |
6b81fa |
|
|
Packit |
6b81fa |
/* vim: set noexpandtab: */
|