blob: 4368ae9b795f4c129122a8fcc7df63e420674bf0 [file] [log] [blame]
From 340221b78e7af95b703dcefa9afa4ffe891db920 Mon Sep 17 00:00:00 2001
From: Mattias Nissler <mnissler@chromium.org>
Date: Mon, 20 Jan 2020 14:07:12 +0100
Subject: [PATCH] Add OpenSSL 1.1 support
Add support for OpenSSL 1.1 API while maintaining support for OpenSSL
1.0.2.
Considerations:
* RSA & EVP_PKEY are now opaque and require use of simple accessors
* OpenSSL-1.1 does not define or use the RSA_FLAG_SIGN_VER
* RSA_METHOD has become opaque, requiring a heap allocation
* X509_SIG has become opaque and requires heap allocation and
X509_SIG_getm() to manipulate the algorithm and digest.
Most of the fixes in this patch are copied directly from, or inspired by
the equivalent upstream libp11 fixes, backported onto 0.2.8. See in
particular these upstream commits:
https://github.com/OpenSC/libp11/commit/491c6b150d31d3126059556b757002f9228cc38f
https://github.com/OpenSC/libp11/commit/932e8e036d8f8a0ef74446cf65c2c11129a36c03
https://github.com/OpenSC/libp11/commit/3f248533bbad437a103626ad3c6e5a37726dbf8f
The X509_SIG fix is unique to this patch, since PKCS11_sign has been
significantly re-implemented to avoid direct X509_SIG manipulation.
BUG=chromium:739688
TEST=FEATURES=test emerge-sarien libp11
---
src/p11_key.c | 46 +++++++++++++++----
src/p11_ops.c | 29 ++++++++----
src/p11_rsa.c | 119 +++++++++++++++++++++++++++++++++++++++++++++-----
3 files changed, 165 insertions(+), 29 deletions(-)
--- a/src/p11_key.c
+++ b/src/p11_key.c
@@ -339,6 +339,7 @@ static int pkcs11_store_private_key(PKCS11_TOKEN * token, EVP_PKEY * pk,
CK_ATTRIBUTE attrs[32];
unsigned int n = 0;
int rv;
+ const BIGNUM *rsa_n, *rsa_e, *rsa_d, *rsa_p, *rsa_q;
/* First, make sure we have a session */
if (!PRIVSLOT(slot)->haveSession && PKCS11_open_session(slot, 1))
@@ -346,8 +347,13 @@ static int pkcs11_store_private_key(PKCS11_TOKEN * token, EVP_PKEY * pk,
session = PRIVSLOT(slot)->session;
/* Now build the key attrs */
- if (pk->type == EVP_PKEY_RSA) {
+#if OPENSSL_VERSION_NUMBER >= 0x10100003L
+ if (EVP_PKEY_base_id(pk) == EVP_PKEY_RSA) {
RSA *rsa = EVP_PKEY_get1_RSA(pk);
+#else
+ if (pk->type == EVP_PKEY_RSA) {
+ RSA *rsa = pk->pkey.rsa;
+#endif
pkcs11_addattr_int(attrs + n++, CKA_CLASS, CKO_PRIVATE_KEY);
pkcs11_addattr_int(attrs + n++, CKA_KEY_TYPE, CKK_RSA);
@@ -359,11 +365,21 @@ static int pkcs11_store_private_key(PKCS11_TOKEN * token, EVP_PKEY * pk,
pkcs11_addattr_bool(attrs + n++, CKA_SIGN, TRUE);
pkcs11_addattr_bool(attrs + n++, CKA_UNWRAP, TRUE);
- pkcs11_addattr_bn(attrs + n++, CKA_MODULUS, rsa->n);
- pkcs11_addattr_bn(attrs + n++, CKA_PUBLIC_EXPONENT, rsa->e);
- pkcs11_addattr_bn(attrs + n++, CKA_PRIVATE_EXPONENT, rsa->d);
- pkcs11_addattr_bn(attrs + n++, CKA_PRIME_1, rsa->p);
- pkcs11_addattr_bn(attrs + n++, CKA_PRIME_2, rsa->q);
+#if OPENSSL_VERSION_NUMBER >= 0x10100005L
+ RSA_get0_key(rsa, &rsa_n, &rsa_e, &rsa_d);
+ RSA_get0_factors(rsa, &rsa_p, &rsa_q);
+#else
+ rsa_n=rsa->n;
+ rsa_e=rsa->e;
+ rsa_d=rsa->d;
+ rsa_p=rsa->p;
+ rsa_q=rsa->q;
+#endif
+ pkcs11_addattr_bn(attrs + n++, CKA_MODULUS, rsa_n);
+ pkcs11_addattr_bn(attrs + n++, CKA_PUBLIC_EXPONENT, rsa_e);
+ pkcs11_addattr_bn(attrs + n++, CKA_PRIVATE_EXPONENT, rsa_d);
+ pkcs11_addattr_bn(attrs + n++, CKA_PRIME_1, rsa_p);
+ pkcs11_addattr_bn(attrs + n++, CKA_PRIME_2, rsa_q);
if (label)
pkcs11_addattr_s(attrs + n++, CKA_LABEL, label);
@@ -402,6 +418,7 @@ static int pkcs11_store_public_key(PKCS11_TOKEN * token, EVP_PKEY * pk,
CK_ATTRIBUTE attrs[32];
unsigned int n = 0;
int rv;
+ const BIGNUM *rsa_n, *rsa_e;
/* First, make sure we have a session */
if (!PRIVSLOT(slot)->haveSession && PKCS11_open_session(slot, 1))
@@ -409,8 +426,13 @@ static int pkcs11_store_public_key(PKCS11_TOKEN * token, EVP_PKEY * pk,
session = PRIVSLOT(slot)->session;
/* Now build the key attrs */
- if (pk->type == EVP_PKEY_RSA) {
+#if OPENSSL_VERSION_NUMBER >= 0x10100003L
+ if (EVP_PKEY_base_id(pk) == EVP_PKEY_RSA) {
RSA *rsa = EVP_PKEY_get1_RSA(pk);
+#else
+ if (pk->type == EVP_PKEY_RSA) {
+ RSA *rsa = pk->pkey.rsa;
+#endif
pkcs11_addattr_int(attrs + n++, CKA_CLASS, CKO_PUBLIC_KEY);
pkcs11_addattr_int(attrs + n++, CKA_KEY_TYPE, CKK_RSA);
@@ -420,8 +442,14 @@ static int pkcs11_store_public_key(PKCS11_TOKEN * token, EVP_PKEY * pk,
pkcs11_addattr_bool(attrs + n++, CKA_VERIFY, TRUE);
pkcs11_addattr_bool(attrs + n++, CKA_WRAP, TRUE);
- pkcs11_addattr_bn(attrs + n++, CKA_MODULUS, rsa->n);
- pkcs11_addattr_bn(attrs + n++, CKA_PUBLIC_EXPONENT, rsa->e);
+#if OPENSSL_VERSION_NUMBER >= 0x10100005L
+ RSA_get0_key(rsa, &rsa_n, &rsa_e, NULL);
+#else
+ rsa_n=rsa->n;
+ rsa_e=rsa->e;
+#endif
+ pkcs11_addattr_bn(attrs + n++, CKA_MODULUS, rsa_n);
+ pkcs11_addattr_bn(attrs + n++, CKA_PUBLIC_EXPONENT, rsa_e);
if (label)
pkcs11_addattr_s(attrs + n++, CKA_LABEL, label);
if (id && id_len)
--- a/src/p11_ops.c
+++ b/src/p11_ops.c
@@ -43,25 +43,38 @@ PKCS11_sign(int type, const unsigned char *m, unsigned int m_len,
return(0); /* the size is wrong */
}
} else {
- ASN1_TYPE parameter = { V_ASN1_NULL, { NULL } };
- ASN1_STRING digest = { m_len, V_ASN1_OCTET_STRING, (unsigned char *)m };
- X509_ALGOR algor = { NULL, &parameter };
- X509_SIG digest_info = { &algor, &digest };
+ ASN1_STRING *digest;
+ X509_ALGOR *algor;
+ X509_SIG *digest_info;
int size;
+
+ digest_info = X509_SIG_new();
+ if (digest_info == NULL)
+ return 0;
+
+#if OPENSSL_VERSION_NUMBER >= 0x10100001L
+ X509_SIG_getm(digest_info, &algor, &digest);
+#else
+ digest = digest_info->digest;
+ algor = digest_info->algor;
+#endif
+
/* Fetch the OID of the algorithm used */
- if((algor.algorithm = OBJ_nid2obj(type)) &&
- (algor.algorithm->length) &&
+ if(X509_ALGOR_set0(algor, OBJ_nid2obj(type), V_ASN1_NULL, NULL) &&
+ ASN1_OCTET_STRING_set(digest, m, m_len) &&
/* Get the size of the encoded DigestInfo */
- (size = i2d_X509_SIG(&digest_info, NULL)) &&
+ (size = i2d_X509_SIG(digest_info, NULL)) &&
/* Check that size is compatible with PKCS#11 padding */
(size + RSA_PKCS1_PADDING_SIZE <= sigsize) &&
(encoded = (unsigned char *) malloc(sigsize))) {
unsigned char *tmp = encoded;
/* Actually do the encoding */
- i2d_X509_SIG(&digest_info,&tmp);
+ i2d_X509_SIG(digest_info, &tmp);
m = encoded;
m_len = size;
+ X509_SIG_free(digest_info);
} else {
+ X509_SIG_free(digest_info);
return(0);
}
}
--- a/src/p11_rsa.c
+++ b/src/p11_rsa.c
@@ -38,6 +38,7 @@ static int pkcs11_get_rsa_private(PKCS11_KEY * key, EVP_PKEY * pk)
{
CK_BBOOL sensitive, extractable;
RSA *rsa;
+ BIGNUM *rsa_n = NULL, *rsa_e = NULL;
if (!(rsa = EVP_PKEY_get1_RSA(pk))) {
ERR_clear_error(); /* the above flags an error */
@@ -51,17 +52,30 @@ static int pkcs11_get_rsa_private(PKCS11_KEY * key, EVP_PKEY * pk)
return -1;
}
- if (key_getattr_bn(key, CKA_MODULUS, &rsa->n) ||
- key_getattr_bn(key, CKA_PUBLIC_EXPONENT, &rsa->e)) {
+ if (key_getattr_bn(key, CKA_MODULUS, &rsa_n) ||
+ key_getattr_bn(key, CKA_PUBLIC_EXPONENT, &rsa_e)) {
RSA_free(rsa);
+ BN_clear_free(rsa_n);
+ BN_clear_free(rsa_e);
return -1;
}
+#if OPENSSL_VERSION_NUMBER >= 0x10100005L
+ RSA_set0_key(rsa, rsa_n, rsa_e, NULL);
+#else
+ rsa->n = rsa_n;
+ rsa->e = rsa_e;
+#endif
+
/* If the key is not extractable, create a key object
* that will use the card's functions to sign & decrypt */
if (sensitive || !extractable) {
RSA_set_method(rsa, PKCS11_get_rsa_method());
+
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
+ /* RSA_FLAG_SIGN_VER no longer in OpenSSL 1.1 */
rsa->flags |= RSA_FLAG_SIGN_VER;
+#endif
RSA_set_app_data(rsa, key);
RSA_free(rsa);
@@ -71,7 +85,11 @@ static int pkcs11_get_rsa_private(PKCS11_KEY * key, EVP_PKEY * pk)
/* TBD - extract RSA private key. */
/* In the mean time let's use the card anyway */
RSA_set_method(rsa, PKCS11_get_rsa_method());
+
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
+ /* RSA_FLAG_SIGN_VER no longer in OpenSSL 1.1 */
rsa->flags |= RSA_FLAG_SIGN_VER;
+#endif
RSA_set_app_data(rsa, key);
RSA_free(rsa);
@@ -110,6 +128,8 @@ static int pkcs11_rsa_sign(int type, const unsigned char *m, unsigned int m_len,
return PKCS11_sign(type,m,m_len,sigret,siglen,(PKCS11_KEY *) RSA_get_app_data(rsa));
}
+
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
/* Lousy hack alert. If RSA_verify detects that the key has the
* RSA_FLAG_SIGN_VER flags set, it will assume that verification
* is implemented externally as well.
@@ -118,7 +138,7 @@ static int pkcs11_rsa_sign(int type, const unsigned char *m, unsigned int m_len,
*/
static int
pkcs11_rsa_verify(int type, const unsigned char *m, unsigned int m_len,
- unsigned char *signature, unsigned int siglen, const RSA * rsa)
+ const unsigned char *signature, unsigned int siglen, const RSA * rsa)
{
RSA *r = (RSA *) rsa; /* Ugly hack to get rid of compiler warning */
int res;
@@ -131,24 +151,99 @@ pkcs11_rsa_verify(int type, const unsigned char *m, unsigned int m_len,
PKCS11err(PKCS11_F_PKCS11_RSA_VERIFY, PKCS11_NOT_SUPPORTED);
res = 0;
}
+
return res;
}
+#endif
+
+#if OPENSSL_VERSION_NUMBER < 0x10100005L
+
+static RSA_METHOD *RSA_meth_dup(const RSA_METHOD *meth)
+{
+ RSA_METHOD *ret = OPENSSL_malloc(sizeof(RSA_METHOD));
+ if (ret == NULL)
+ return NULL;
+ memcpy(ret, meth, sizeof(RSA_METHOD));
+ ret->name = OPENSSL_strdup(meth->name);
+ if (ret->name == NULL) {
+ OPENSSL_free(ret);
+ return NULL;
+ }
+ return ret;
+}
+
+static int RSA_meth_set1_name(RSA_METHOD *meth, const char *name)
+{
+ char *tmp = OPENSSL_strdup(name);
+ if (tmp == NULL)
+ return 0;
+ OPENSSL_free((char *)meth->name);
+ meth->name = tmp;
+ return 1;
+}
+
+static int RSA_meth_set_flags(RSA_METHOD *meth, int flags)
+{
+ meth->flags = flags;
+ return 1;
+}
+
+static int RSA_meth_set_priv_enc(RSA_METHOD *meth,
+ int (*priv_enc) (int flen, const unsigned char *from,
+ unsigned char *to, RSA *rsa, int padding))
+{
+ meth->rsa_priv_enc = priv_enc;
+ return 1;
+}
+
+static int RSA_meth_set_priv_dec(RSA_METHOD *meth,
+ int (*priv_dec) (int flen, const unsigned char *from,
+ unsigned char *to, RSA *rsa, int padding))
+{
+ meth->rsa_priv_dec = priv_dec;
+ return 1;
+}
+
+static int RSA_meth_set_sign(RSA_METHOD *meth,
+ int (*sign) (int type, const unsigned char *m,
+ unsigned int m_len, unsigned char *sigret, unsigned int *siglen,
+ const RSA * rsa))
+{
+ meth->rsa_sign = sign;
+ return 1;
+}
+
+static int RSA_meth_set_verify(RSA_METHOD *meth,
+ int (*verify) (int type, const unsigned char *m,
+ unsigned int m_len, const unsigned char *sigbuf,
+ unsigned int siglen, const RSA *rsa))
+{
+ meth->rsa_verify = verify;
+ return 1;
+}
+#endif
/*
* Overload the default OpenSSL methods for RSA
*/
RSA_METHOD *PKCS11_get_rsa_method(void)
{
- static RSA_METHOD ops;
-
- if (!ops.rsa_priv_enc) {
- ops = *RSA_get_default_method();
- ops.rsa_priv_enc = pkcs11_rsa_encrypt;
- ops.rsa_priv_dec = pkcs11_rsa_decrypt;
- ops.rsa_sign = pkcs11_rsa_sign;
- ops.rsa_verify = pkcs11_rsa_verify;
+ static RSA_METHOD *ops = NULL;
+
+ if (ops == NULL) {
+ ops = RSA_meth_dup(RSA_get_default_method());
+ if (ops == NULL)
+ return NULL;
+ RSA_meth_set1_name(ops, "libp11 RSA method");
+ RSA_meth_set_flags(ops, 0);
+ RSA_meth_set_priv_enc(ops, pkcs11_rsa_encrypt);
+ RSA_meth_set_priv_dec(ops, pkcs11_rsa_decrypt);
+ RSA_meth_set_sign(ops, pkcs11_rsa_sign);
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
+ RSA_meth_set_verify(ops, pkcs11_rsa_verify);
+#endif
}
- return &ops;
+ return ops;
}
PKCS11_KEY_ops pkcs11_rsa_ops = {
--
2.24.1