diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..82ad896 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +SOURCES/libp11-0.4.8.tar.gz diff --git a/.openssl-pkcs11.metadata b/.openssl-pkcs11.metadata new file mode 100644 index 0000000..1917f75 --- /dev/null +++ b/.openssl-pkcs11.metadata @@ -0,0 +1 @@ +c39ae70fda467b8096ed419fc6a1687421696717 SOURCES/libp11-0.4.8.tar.gz diff --git a/SOURCES/openssl-pkcs11-0.4.8-allow-use-privkey-without-pin.patch b/SOURCES/openssl-pkcs11-0.4.8-allow-use-privkey-without-pin.patch new file mode 100644 index 0000000..280428a --- /dev/null +++ b/SOURCES/openssl-pkcs11-0.4.8-allow-use-privkey-without-pin.patch @@ -0,0 +1,18 @@ +diff --git a/src/eng_back.c b/src/eng_back.c +index 464c47b..fb94934 100644 +--- a/src/eng_back.c ++++ b/src/eng_back.c +@@ -750,10 +750,6 @@ static EVP_PKEY *ctx_load_key(ENGINE_CTX *ctx, const char *s_slot_key_id, + * with some other (which ones?) PKCS#11 libraries */ + if (!tok->initialized) + ctx_log(ctx, 0, "Found uninitialized token\n"); +- if (isPrivate && !tok->userPinSet && !tok->readOnly) { +- ctx_log(ctx, 0, "Found slot without user PIN\n"); +- goto error; +- } + + ctx_log(ctx, 1, "Found slot: %s\n", slot->description); + ctx_log(ctx, 1, "Found token: %s\n", slot->token->label); +-- +2.17.1 + diff --git a/SOURCES/openssl-pkcs11-0.4.8-atfork-checks-rsa-and-ec-keys.patch b/SOURCES/openssl-pkcs11-0.4.8-atfork-checks-rsa-and-ec-keys.patch new file mode 100644 index 0000000..7731d13 --- /dev/null +++ b/SOURCES/openssl-pkcs11-0.4.8-atfork-checks-rsa-and-ec-keys.patch @@ -0,0 +1,107 @@ +From efce4defdf31ce74d905ae4dd47c6a36df532854 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Micha=C5=82=20Trojnara?= +Date: Wed, 29 Aug 2018 23:05:05 +0200 +Subject: [PATCH 09/23] Atfork checks for RSA and EC_KEY methods + +--- + src/p11_ec.c | 9 +++------ + src/p11_pkey.c | 9 ++++----- + src/p11_rsa.c | 4 ++-- + 3 files changed, 9 insertions(+), 13 deletions(-) + +diff --git a/src/p11_ec.c b/src/p11_ec.c +index eb0cbb2..1b58c01 100644 +--- a/src/p11_ec.c ++++ b/src/p11_ec.c +@@ -394,7 +394,7 @@ static ECDSA_SIG *pkcs11_ecdsa_sign_sig(const unsigned char *dgst, int dlen, + (void)rp; /* Precomputed values are not used for PKCS#11 */ + + key = pkcs11_get_ex_data_ec(ec); +- if (key == NULL) { ++ if (check_key_fork(key) < 0) { + sign_sig_fn orig_sign_sig; + #if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER) + const EC_KEY_METHOD *meth = EC_KEY_OpenSSL(); +@@ -406,7 +406,6 @@ static ECDSA_SIG *pkcs11_ecdsa_sign_sig(const unsigned char *dgst, int dlen, + #endif + return orig_sign_sig(dgst, dlen, kinv, rp, ec); + } +- /* TODO: Add an atfork check */ + + /* Truncate digest if its byte size is longer than needed */ + order = BN_new(); +@@ -580,9 +579,8 @@ static int pkcs11_ec_ckey(unsigned char **out, size_t *outlen, + int rv; + + key = pkcs11_get_ex_data_ec(ecdh); +- if (key == NULL) /* The private key is not handled by PKCS#11 */ ++ if (check_key_fork(key) < 0) + return ossl_ecdh_compute_key(out, outlen, peer_point, ecdh); +- /* TODO: Add an atfork check */ + + /* both peer and ecdh use same group parameters */ + parms = pkcs11_ecdh_params_alloc(EC_KEY_get0_group(ecdh), peer_point); +@@ -622,9 +620,8 @@ static int pkcs11_ec_ckey(void *out, size_t outlen, + int rv; + + key = pkcs11_get_ex_data_ec(ecdh); +- if (key == NULL) /* The private key is not handled by PKCS#11 */ ++ if (check_key_fork(key) < 0) + return ossl_ecdh_compute_key(out, outlen, peer_point, ecdh, KDF); +- /* TODO: Add an atfork check */ + + /* both peer and ecdh use same group parameters */ + parms = pkcs11_ecdh_params_alloc(EC_KEY_get0_group(ecdh), peer_point); +diff --git a/src/p11_pkey.c b/src/p11_pkey.c +index 0efcaa4..2ba23d9 100644 +--- a/src/p11_pkey.c ++++ b/src/p11_pkey.c +@@ -309,7 +309,7 @@ static int pkcs11_try_pkey_rsa_sign(EVP_PKEY_CTX *evp_pkey_ctx, + if (rsa == NULL) + return -1; + key = pkcs11_get_ex_data_rsa(rsa); +- if (key == NULL) ++ if (check_key_fork(key) < 0) + return -1; + slot = KEY2SLOT(key); + ctx = KEY2CTX(key); +@@ -413,11 +413,10 @@ static int pkcs11_try_pkey_rsa_decrypt(EVP_PKEY_CTX *evp_pkey_ctx, + if (rsa == NULL) + return -1; + key = pkcs11_get_ex_data_rsa(rsa); +- if (key == NULL) ++ if (check_key_fork(key) < 0) + return -1; +- +- slot = KEY2SLOT(key); +- ctx = KEY2CTX(key); ++ slot = KEY2SLOT(key); ++ ctx = KEY2CTX(key); + kpriv = PRIVKEY(key); + spriv = PRIVSLOT(slot); + cpriv = PRIVCTX(ctx); +diff --git a/src/p11_rsa.c b/src/p11_rsa.c +index f69a8a6..6a519f9 100644 +--- a/src/p11_rsa.c ++++ b/src/p11_rsa.c +@@ -355,7 +355,7 @@ static int pkcs11_rsa_priv_dec_method(int flen, const unsigned char *from, + PKCS11_KEY *key = pkcs11_get_ex_data_rsa(rsa); + int (*priv_dec) (int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding); +- if (key == NULL) { ++ if (check_key_fork(key) < 0) { + priv_dec = RSA_meth_get_priv_dec(RSA_get_default_method()); + return priv_dec(flen, from, to, rsa, padding); + } +@@ -368,7 +368,7 @@ static int pkcs11_rsa_priv_enc_method(int flen, const unsigned char *from, + PKCS11_KEY *key = pkcs11_get_ex_data_rsa(rsa); + int (*priv_enc) (int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding); +- if (key == NULL) { ++ if (check_key_fork(key) < 0) { + priv_enc = RSA_meth_get_priv_enc(RSA_get_default_method()); + return priv_enc(flen, from, to, rsa, padding); + } +-- +2.17.1 + diff --git a/SOURCES/openssl-pkcs11-0.4.8-ec-sign-test.patch b/SOURCES/openssl-pkcs11-0.4.8-ec-sign-test.patch new file mode 100644 index 0000000..103b07d --- /dev/null +++ b/SOURCES/openssl-pkcs11-0.4.8-ec-sign-test.patch @@ -0,0 +1,167 @@ +From 10ed7e56f159dba8980644494532898c9063438d Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Micha=C5=82=20Trojnara?= +Date: Thu, 23 Aug 2018 22:19:04 +0200 +Subject: [PATCH 03/23] ec-evp-sign test + +--- + tests/Makefile.am | 1 + + tests/ec-common.sh | 18 +++++----- + tests/ec-evp-sign.softhsm | 71 +++++++++++++++++++++++++++++++++++++++ + tests/ec-testfork.softhsm | 2 +- + 4 files changed, 82 insertions(+), 10 deletions(-) + create mode 100755 tests/ec-evp-sign.softhsm + +diff --git a/tests/Makefile.am b/tests/Makefile.am +index 8864709..cd17051 100644 +--- a/tests/Makefile.am ++++ b/tests/Makefile.am +@@ -21,6 +21,7 @@ dist_check_SCRIPTS = \ + rsa-testfork.softhsm \ + rsa-testlistkeys.softhsm \ + rsa-evp-sign.softhsm \ ++ ec-evp-sign.softhsm \ + ec-testfork.softhsm \ + fork-change-slot.softhsm \ + rsa-pss-sign.softhsm \ +diff --git a/tests/ec-common.sh b/tests/ec-common.sh +index a709c0d..a53a4ee 100755 +--- a/tests/ec-common.sh ++++ b/tests/ec-common.sh +@@ -35,11 +35,11 @@ mkdir -p $outdir + + for i in /usr/lib64/pkcs11 /usr/lib64/softhsm /usr/lib/x86_64-linux-gnu/softhsm /usr/local/lib/softhsm /opt/local/lib/softhsm /usr/lib/softhsm /usr/lib ;do + if test -f "$i/libsofthsm2.so"; then +- ADDITIONAL_PARAM="$i/libsofthsm2.so" ++ MODULE="$i/libsofthsm2.so" + break + else + if test -f "$i/libsofthsm.so";then +- ADDITIONAL_PARAM="$i/libsofthsm.so" ++ MODULE="$i/libsofthsm.so" + break + fi + fi +@@ -104,18 +104,18 @@ PUK=1234 + init_card $PIN $PUK + + # generate key in token +-pkcs11-tool -p $PIN --module $ADDITIONAL_PARAM -d 01020304 -a server-key -l -w ${srcdir}/ec-prvkey.der -y privkey >/dev/null ++pkcs11-tool -p $PIN --module $MODULE -d 01020304 -a server-key -l -w ${srcdir}/ec-prvkey.der -y privkey >/dev/null + if test $? != 0;then + exit 1; + fi + + # pkcs11-tool currently only supports RSA public keys +-#pkcs11-tool -p $PIN --module $ADDITIONAL_PARAM -d 01020304 -a server-key -l -w ${srcdir}/ec-pubkey.der -y pubkey >/dev/null +-#if test $? != 0;then +-# exit 1; +-#fi ++pkcs11-tool -p $PIN --module $MODULE -d 01020304 -a server-key -l -w ${srcdir}/ec-pubkey.der -y pubkey >/dev/null ++if test $? != 0;then ++ exit 1; ++fi + +-pkcs11-tool -p $PIN --module $ADDITIONAL_PARAM -d 01020304 -a server-key -l -w ${srcdir}/ec-cert.der -y cert >/dev/null ++pkcs11-tool -p $PIN --module $MODULE -d 01020304 -a server-key -l -w ${srcdir}/ec-cert.der -y cert >/dev/null + if test $? != 0;then + exit 1; + fi +@@ -123,4 +123,4 @@ fi + echo "***************" + echo "Listing objects" + echo "***************" +-pkcs11-tool -p $PIN --module $ADDITIONAL_PARAM -l -O ++pkcs11-tool -p $PIN --module $MODULE -l -O +diff --git a/tests/ec-evp-sign.softhsm b/tests/ec-evp-sign.softhsm +new file mode 100755 +index 0000000..edecd4a +--- /dev/null ++++ b/tests/ec-evp-sign.softhsm +@@ -0,0 +1,71 @@ ++#!/bin/sh ++ ++# Copyright (C) 2015 Nikos Mavrogiannopoulos ++# ++# GnuTLS is free software; you can redistribute it and/or modify it ++# under the terms of the GNU General Public License as published by the ++# Free Software Foundation; either version 3 of the License, or (at ++# your option) any later version. ++# ++# GnuTLS 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 ++# General Public License for more details. ++# ++# You should have received a copy of the GNU General Public License ++# along with GnuTLS; if not, write to the Free Software Foundation, ++# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ++ ++outdir="output.$$" ++ ++# Load common test functions ++. ${srcdir}/ec-common.sh ++ ++# Do the common test initialization ++# common_init ++ ++sed -e "s|@MODULE_PATH@|${MODULE}|g" -e "s|@ENGINE_PATH@|../src/.libs/pkcs11.so|g" <"${srcdir}/engines.cnf.in" >"${outdir}/engines.cnf" ++ ++export OPENSSL_ENGINES="../src/.libs/" ++PRIVATE_KEY="pkcs11:token=libp11-test;id=%01%02%03%04;object=server-key;type=private;pin-value=1234" ++PUBLIC_KEY="pkcs11:token=libp11-test;id=%01%02%03%04;object=server-key;type=public;pin-value=1234" ++ ++./evp-sign ctrl false "${outdir}/engines.cnf" ${PRIVATE_KEY} ${PUBLIC_KEY} ${MODULE} ++if test $? != 0;then ++ echo "Basic PKCS #11 test, using ctrl failed" ++ exit 1; ++fi ++ ++./evp-sign default false "${outdir}/engines.cnf" ${PRIVATE_KEY} ${PUBLIC_KEY} ${MODULE} ++if test $? != 0;then ++ echo "Basic PKCS #11 test, using default failed" ++ exit 1; ++fi ++ ++./evp-sign ctrl 1234 "${outdir}/engines.cnf" ${PRIVATE_KEY} ${PUBLIC_KEY} ${MODULE} ++if test $? != 0;then ++ echo "Basic PKCS #11 test without pin-value, using ctrl failed" ++ exit 1; ++fi ++ ++./evp-sign default 1234 "${outdir}/engines.cnf" ${PRIVATE_KEY} ${PUBLIC_KEY} ${MODULE} ++if test $? != 0;then ++ echo "Basic PKCS #11 test without pin-value, using default failed" ++ exit 1; ++fi ++ ++./evp-sign ctrl 1234 "${outdir}/engines.cnf" "label_server-key" "label_server-key" ${MODULE} ++if test $? != 0;then ++ echo "Basic PKCS #11 test with legacy name #1 failed" ++ exit 1; ++fi ++ ++./evp-sign default 1234 "${outdir}/engines.cnf" "id_01020304" "id_01020304" ${MODULE} ++if test $? != 0;then ++ echo "Basic PKCS #11 test with legacy name #2 failed" ++ exit 1; ++fi ++ ++rm -rf "$outdir" ++ ++exit 0 +diff --git a/tests/ec-testfork.softhsm b/tests/ec-testfork.softhsm +index 961424a..55b6516 100755 +--- a/tests/ec-testfork.softhsm ++++ b/tests/ec-testfork.softhsm +@@ -21,7 +21,7 @@ outdir="output.$$" + + . ${srcdir}/ec-common.sh + +-./fork-test $ADDITIONAL_PARAM $PIN ++./fork-test $MODULE $PIN + if test $? != 0;then + exit 1; + fi +-- +2.17.1 + diff --git a/SOURCES/openssl-pkcs11-0.4.8-error-handling-evp-pkey-set1-engine-fixed.patch b/SOURCES/openssl-pkcs11-0.4.8-error-handling-evp-pkey-set1-engine-fixed.patch new file mode 100644 index 0000000..1f16235 --- /dev/null +++ b/SOURCES/openssl-pkcs11-0.4.8-error-handling-evp-pkey-set1-engine-fixed.patch @@ -0,0 +1,19 @@ +diff --git a/src/eng_front.c b/src/eng_front.c +index 5fe8f55..286aaa9 100644 +--- a/src/eng_front.c ++++ b/src/eng_front.c +@@ -233,11 +233,9 @@ static EVP_PKEY *load_privkey(ENGINE *engine, const char *s_key_id, + #ifdef EVP_F_EVP_PKEY_SET1_ENGINE + /* EVP_PKEY_set1_engine() is required for OpenSSL 1.1.x, + * but otherwise setting pkey->engine breaks OpenSSL 1.0.2 */ +- if (pkey) { +- if (!EVP_PKEY_set1_engine(pkey, engine)) { +- EVP_PKEY_free(pkey); +- return NULL; +- } ++ if (pkey && !EVP_PKEY_set1_engine(pkey, engine)) { ++ EVP_PKEY_free(pkey); ++ pkey = NULL; + } + #endif /* EVP_F_EVP_PKEY_SET1_ENGINE */ + return pkey; diff --git a/SOURCES/openssl-pkcs11-0.4.8-error-handling-evp-pkey-set1-engine.patch b/SOURCES/openssl-pkcs11-0.4.8-error-handling-evp-pkey-set1-engine.patch new file mode 100644 index 0000000..a0644c4 --- /dev/null +++ b/SOURCES/openssl-pkcs11-0.4.8-error-handling-evp-pkey-set1-engine.patch @@ -0,0 +1,31 @@ +From f41dba3102f4257fe366adf4cd8f0a0088c9b3f1 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Micha=C5=82=20Trojnara?= +Date: Thu, 23 Aug 2018 22:27:55 +0200 +Subject: [PATCH 04/23] Error handling for EVP_PKEY_set1_engine() + +--- + src/eng_front.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git a/src/eng_front.c b/src/eng_front.c +index 853fa5a..5fe8f55 100644 +--- a/src/eng_front.c ++++ b/src/eng_front.c +@@ -233,8 +233,12 @@ static EVP_PKEY *load_privkey(ENGINE *engine, const char *s_key_id, + #ifdef EVP_F_EVP_PKEY_SET1_ENGINE + /* EVP_PKEY_set1_engine() is required for OpenSSL 1.1.x, + * but otherwise setting pkey->engine breaks OpenSSL 1.0.2 */ +- if (pkey) +- EVP_PKEY_set1_engine(pkey, engine); ++ if (pkey) { ++ if (!EVP_PKEY_set1_engine(pkey, engine)) { ++ EVP_PKEY_free(pkey); ++ return NULL; ++ } ++ } + #endif /* EVP_F_EVP_PKEY_SET1_ENGINE */ + return pkey; + } +-- +2.17.1 + diff --git a/SOURCES/openssl-pkcs11-0.4.8-evp-pkey-ec-framework.patch b/SOURCES/openssl-pkcs11-0.4.8-evp-pkey-ec-framework.patch new file mode 100644 index 0000000..787f44a --- /dev/null +++ b/SOURCES/openssl-pkcs11-0.4.8-evp-pkey-ec-framework.patch @@ -0,0 +1,157 @@ +From 0a2df89ba517bfbeaeadb81e42fe7bc3288b1985 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Micha=C5=82=20Trojnara?= +Date: Thu, 23 Aug 2018 22:35:53 +0200 +Subject: [PATCH 05/23] Initial EVP_PKEY_EC framework + +Fixes #243 +--- + src/p11_pkey.c | 94 +++++++++++++++++++++++++++++++++++++++++--------- + 1 file changed, 78 insertions(+), 16 deletions(-) + +diff --git a/src/p11_pkey.c b/src/p11_pkey.c +index 45d5ad3..0efcaa4 100644 +--- a/src/p11_pkey.c ++++ b/src/p11_pkey.c +@@ -29,6 +29,13 @@ 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; +@@ -490,54 +497,109 @@ static int pkcs11_pkey_rsa_decrypt(EVP_PKEY_CTX *evp_pkey_ctx, + + static EVP_PKEY_METHOD *pkcs11_pkey_method_rsa() + { +- EVP_PKEY_METHOD *orig_evp_pkey_meth_rsa, *new_evp_pkey_meth_rsa; ++ EVP_PKEY_METHOD *orig_meth, *new_meth; + +- orig_evp_pkey_meth_rsa = (EVP_PKEY_METHOD *)EVP_PKEY_meth_find(EVP_PKEY_RSA); +- EVP_PKEY_meth_get_sign(orig_evp_pkey_meth_rsa, ++ 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_evp_pkey_meth_rsa, ++ EVP_PKEY_meth_get_decrypt(orig_meth, + &orig_pkey_rsa_decrypt_init, + &orig_pkey_rsa_decrypt); + +- new_evp_pkey_meth_rsa = EVP_PKEY_meth_new(EVP_PKEY_RSA, ++ new_meth = EVP_PKEY_meth_new(EVP_PKEY_RSA, + EVP_PKEY_FLAG_AUTOARGLEN); + +- EVP_PKEY_meth_copy(new_evp_pkey_meth_rsa, orig_evp_pkey_meth_rsa); ++ EVP_PKEY_meth_copy(new_meth, orig_meth); + +- EVP_PKEY_meth_set_sign(new_evp_pkey_meth_rsa, ++ EVP_PKEY_meth_set_sign(new_meth, + orig_pkey_rsa_sign_init, pkcs11_pkey_rsa_sign); +- EVP_PKEY_meth_set_decrypt(new_evp_pkey_meth_rsa, ++ EVP_PKEY_meth_set_decrypt(new_meth, + orig_pkey_rsa_decrypt_init, pkcs11_pkey_rsa_decrypt); + +- return new_evp_pkey_meth_rsa; ++ 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) ++{ ++ fprintf(stderr, "%s:%d pkcs11_try_pkey_ec_sign() not implemented\n", ++ __FILE__, __LINE__); ++ 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 + }; + static EVP_PKEY_METHOD *pkey_method_rsa = NULL; ++ static 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 (pkey_method_rsa == NULL) +- pkey_method_rsa = pkcs11_pkey_method_rsa(); +- if (pkey_method_rsa == NULL) +- return 0; +- + if (!pmeth) { /* get the list of supported nids */ + *nids = pkey_nids; +- return 1; /* the number of returned nids */ ++ return sizeof(pkey_nids) / sizeof(int) - 1; + } + + /* get the EVP_PKEY_METHOD */ +- if (nid == EVP_PKEY_RSA) { ++ switch (nid) { ++ case EVP_PKEY_RSA: ++ if (pkey_method_rsa == NULL) ++ 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: ++ if (pkey_method_ec == NULL) ++ 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; +-- +2.17.1 + diff --git a/SOURCES/openssl-pkcs11-0.4.8-ex-data-coding-style.patch b/SOURCES/openssl-pkcs11-0.4.8-ex-data-coding-style.patch new file mode 100644 index 0000000..6e7cf15 --- /dev/null +++ b/SOURCES/openssl-pkcs11-0.4.8-ex-data-coding-style.patch @@ -0,0 +1,129 @@ +From cd6316777395bef8997324cd7152f383534779d3 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Micha=C5=82=20Trojnara?= +Date: Wed, 29 Aug 2018 22:38:54 +0200 +Subject: [PATCH 08/23] ex_data coding style unification + +--- + src/libp11-int.h | 2 +- + src/p11_ec.c | 31 ++++++++++++++++--------------- + src/p11_rsa.c | 6 +++--- + 3 files changed, 20 insertions(+), 19 deletions(-) + +diff --git a/src/libp11-int.h b/src/libp11-int.h +index 411f2b0..3c4792b 100644 +--- a/src/libp11-int.h ++++ b/src/libp11-int.h +@@ -367,7 +367,7 @@ extern int pkcs11_private_decrypt( + unsigned char *to, PKCS11_KEY * key, int padding); + + /* Retrieve PKCS11_KEY from an RSA key */ +-extern PKCS11_KEY *pkcs11_get_ex_data_rsa(RSA *rsa); ++extern PKCS11_KEY *pkcs11_get_ex_data_rsa(const RSA *rsa); + + #endif + +diff --git a/src/p11_ec.c b/src/p11_ec.c +index 8d458dc..eb0cbb2 100644 +--- a/src/p11_ec.c ++++ b/src/p11_ec.c +@@ -260,7 +260,16 @@ static EC_KEY *pkcs11_get_ec(PKCS11_KEY *key) + return ec; + } + +-static void pkcs11_set_ex_data_ec(EC_KEY* ec, PKCS11_KEY* key) ++static PKCS11_KEY *pkcs11_get_ex_data_ec(const EC_KEY *ec) ++{ ++#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER) ++ return EC_KEY_get_ex_data(ec, ec_ex_index); ++#else ++ return ECDSA_get_ex_data((EC_KEY *)ec, ec_ex_index); ++#endif ++} ++ ++static void pkcs11_set_ex_data_ec(EC_KEY *ec, PKCS11_KEY *key) + { + #if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER) + EC_KEY_set_ex_data(ec, ec_ex_index, key); +@@ -269,10 +278,10 @@ static void pkcs11_set_ex_data_ec(EC_KEY* ec, PKCS11_KEY* key) + #endif + } + +-static void pkcs11_update_ex_data_ec(PKCS11_KEY* key) ++static void pkcs11_update_ex_data_ec(PKCS11_KEY *key) + { +- EVP_PKEY* evp = key->evp_key; +- EC_KEY* ec; ++ EVP_PKEY *evp = key->evp_key; ++ EC_KEY *ec; + if (evp == NULL) + return; + if (EVP_PKEY_base_id(evp) != EVP_PKEY_EC) +@@ -384,11 +393,7 @@ static ECDSA_SIG *pkcs11_ecdsa_sign_sig(const unsigned char *dgst, int dlen, + (void)kinv; /* Precomputed values are not used for PKCS#11 */ + (void)rp; /* Precomputed values are not used for PKCS#11 */ + +-#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER) +- key = (PKCS11_KEY *)EC_KEY_get_ex_data(ec, ec_ex_index); +-#else +- key = (PKCS11_KEY *)ECDSA_get_ex_data(ec, ec_ex_index); +-#endif ++ key = pkcs11_get_ex_data_ec(ec); + if (key == NULL) { + sign_sig_fn orig_sign_sig; + #if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER) +@@ -574,7 +579,7 @@ static int pkcs11_ec_ckey(unsigned char **out, size_t *outlen, + size_t buflen; + int rv; + +- key = (PKCS11_KEY *)EC_KEY_get_ex_data(ecdh, ec_ex_index); ++ key = pkcs11_get_ex_data_ec(ecdh); + if (key == NULL) /* The private key is not handled by PKCS#11 */ + return ossl_ecdh_compute_key(out, outlen, peer_point, ecdh); + /* TODO: Add an atfork check */ +@@ -616,11 +621,7 @@ static int pkcs11_ec_ckey(void *out, size_t outlen, + size_t buflen; + int rv; + +-#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER) +- key = (PKCS11_KEY *)EC_KEY_get_ex_data(ecdh, ec_ex_index); +-#else +- key = (PKCS11_KEY *)ECDSA_get_ex_data((EC_KEY *)ecdh, ec_ex_index); +-#endif ++ key = pkcs11_get_ex_data_ec(ecdh); + if (key == NULL) /* The private key is not handled by PKCS#11 */ + return ossl_ecdh_compute_key(out, outlen, peer_point, ecdh, KDF); + /* TODO: Add an atfork check */ +diff --git a/src/p11_rsa.c b/src/p11_rsa.c +index 97cd5a2..f69a8a6 100644 +--- a/src/p11_rsa.c ++++ b/src/p11_rsa.c +@@ -233,7 +233,7 @@ success: + } + + +-PKCS11_KEY *pkcs11_get_ex_data_rsa(RSA *rsa) ++PKCS11_KEY *pkcs11_get_ex_data_rsa(const RSA *rsa) + { + return RSA_get_ex_data(rsa, rsa_ex_index); + } +@@ -352,7 +352,7 @@ int (*RSA_meth_get_priv_dec(const RSA_METHOD *meth)) + static int pkcs11_rsa_priv_dec_method(int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding) + { +- PKCS11_KEY *key = RSA_get_ex_data(rsa, rsa_ex_index); ++ PKCS11_KEY *key = pkcs11_get_ex_data_rsa(rsa); + int (*priv_dec) (int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding); + if (key == NULL) { +@@ -365,7 +365,7 @@ static int pkcs11_rsa_priv_dec_method(int flen, const unsigned char *from, + static int pkcs11_rsa_priv_enc_method(int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding) + { +- PKCS11_KEY *key = RSA_get_ex_data(rsa, rsa_ex_index); ++ PKCS11_KEY *key = pkcs11_get_ex_data_rsa(rsa); + int (*priv_enc) (int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding); + if (key == NULL) { +-- +2.17.1 + diff --git a/SOURCES/openssl-pkcs11-0.4.8-expose-check-fork.patch b/SOURCES/openssl-pkcs11-0.4.8-expose-check-fork.patch new file mode 100644 index 0000000..2ca80bb --- /dev/null +++ b/SOURCES/openssl-pkcs11-0.4.8-expose-check-fork.patch @@ -0,0 +1,534 @@ +From 45d6529dbe1b69f3a838d01a83f0688e91696377 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Micha=C5=82=20Trojnara?= +Date: Wed, 29 Aug 2018 21:35:48 +0200 +Subject: [PATCH 07/23] Expose check_fork internal API + +--- + src/Makefile.am | 2 +- + src/atfork.c | 93 ------------------- + src/libp11-int.h | 7 ++ + src/p11_atfork.c | 231 +++++++++++++++++++++++++++++++++++++++++++++++ + src/p11_front.c | 138 ---------------------------- + 5 files changed, 239 insertions(+), 232 deletions(-) + delete mode 100644 src/atfork.c + create mode 100644 src/p11_atfork.c + +diff --git a/src/Makefile.am b/src/Makefile.am +index 3cdbce1..2ca250e 100644 +--- a/src/Makefile.am ++++ b/src/Makefile.am +@@ -14,7 +14,7 @@ SHARED_EXT=@SHARED_EXT@ + + libp11_la_SOURCES = libpkcs11.c p11_attr.c p11_cert.c p11_err.c p11_ckr.c \ + p11_key.c p11_load.c p11_misc.c p11_rsa.c p11_ec.c p11_pkey.c \ +- p11_slot.c p11_front.c atfork.c libp11.exports ++ p11_slot.c p11_front.c p11_atfork.c libp11.exports + if WIN32 + libp11_la_SOURCES += libp11.rc + else +diff --git a/src/atfork.c b/src/atfork.c +deleted file mode 100644 +index 04691fb..0000000 +--- a/src/atfork.c ++++ /dev/null +@@ -1,93 +0,0 @@ +-/* +- * Copyright (C) 2010-2012 Free Software Foundation, Inc. +- * Copyright (C) 2014 Red Hat +- * +- * Author: Nikos Mavrogiannopoulos +- * +- * This 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 program. If not, see +- * +- */ +- +-#include "libp11-int.h" +-#if defined(_WIN32) && !defined(__CYGWIN__) +-#include +-#else +-#include +-#endif +-#include +-#include +-#include +-#include +-#include +- +-#ifdef __sun +-# pragma fini(lib_deinit) +-# pragma init(lib_init) +-# define _CONSTRUCTOR +-# define _DESTRUCTOR +-#else +-# define _CONSTRUCTOR __attribute__((constructor)) +-# define _DESTRUCTOR __attribute__((destructor)) +-#endif +- +-unsigned int P11_forkid = 0; +- +-#ifndef _WIN32 +- +-# ifdef HAVE_ATFORK +-static void fork_handler(void) +-{ +- P11_forkid++; +-} +-# endif +- +-# if defined(HAVE___REGISTER_ATFORK) +-extern int __register_atfork(void (*)(void), void(*)(void), void (*)(void), void *); +-extern void *__dso_handle; +- +-_CONSTRUCTOR +-int _P11_register_fork_handler(void) +-{ +- if (__register_atfork(0, 0, fork_handler, __dso_handle) != 0) +- return -1; +- return 0; +-} +- +-# else +- +-unsigned int _P11_get_forkid(void) +-{ +- return getpid(); +-} +- +-int _P11_detect_fork(unsigned int forkid) +-{ +- if (getpid() == forkid) +- return 0; +- return 1; +-} +- +-/* we have to detect fork manually */ +-_CONSTRUCTOR +-int _P11_register_fork_handler(void) +-{ +- P11_forkid = getpid(); +- return 0; +-} +- +-# endif +- +-#endif /* !_WIN32 */ +- +-/* vim: set noexpandtab: */ +diff --git a/src/libp11-int.h b/src/libp11-int.h +index b62a13e..411f2b0 100644 +--- a/src/libp11-int.h ++++ b/src/libp11-int.h +@@ -323,6 +323,13 @@ extern int pkcs11_store_certificate(PKCS11_TOKEN * token, X509 * x509, + extern int pkcs11_seed_random(PKCS11_SLOT *, const unsigned char *s, unsigned int s_len); + extern int pkcs11_generate_random(PKCS11_SLOT *, unsigned char *r, unsigned int r_len); + ++/* Reinitialize the module afer fork if needed */ ++extern int check_fork(PKCS11_CTX *ctx); ++extern int check_slot_fork(PKCS11_SLOT *slot); ++extern int check_token_fork(PKCS11_TOKEN *token); ++extern int check_key_fork(PKCS11_KEY *key); ++extern int check_cert_fork(PKCS11_CERT *cert); ++ + /* Internal implementation of deprecated features */ + + /* Generate and store a private key on the token */ +diff --git a/src/p11_atfork.c b/src/p11_atfork.c +new file mode 100644 +index 0000000..fce87c6 +--- /dev/null ++++ b/src/p11_atfork.c +@@ -0,0 +1,231 @@ ++/* ++ * Copyright (C) 2010-2012 Free Software Foundation, Inc. ++ * Copyright (C) 2014 Red Hat ++ * ++ * Author: Nikos Mavrogiannopoulos ++ * ++ * This 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 program. If not, see ++ * ++ */ ++ ++#include "libp11-int.h" ++#if defined(_WIN32) && !defined(__CYGWIN__) ++#include ++#else ++#include ++#endif ++#include ++#include ++#include ++#include ++#include ++ ++#ifdef __sun ++# pragma fini(lib_deinit) ++# pragma init(lib_init) ++# define _CONSTRUCTOR ++# define _DESTRUCTOR ++#else ++# define _CONSTRUCTOR __attribute__((constructor)) ++# define _DESTRUCTOR __attribute__((destructor)) ++#endif ++ ++unsigned int P11_forkid = 0; ++ ++#ifndef _WIN32 ++ ++# ifdef HAVE_ATFORK ++static void fork_handler(void) ++{ ++ P11_forkid++; ++} ++# endif ++ ++# if defined(HAVE___REGISTER_ATFORK) ++extern int __register_atfork(void (*)(void), void(*)(void), void (*)(void), void *); ++extern void *__dso_handle; ++ ++_CONSTRUCTOR ++int _P11_register_fork_handler(void) ++{ ++ if (__register_atfork(0, 0, fork_handler, __dso_handle) != 0) ++ return -1; ++ return 0; ++} ++ ++# else ++ ++unsigned int _P11_get_forkid(void) ++{ ++ return getpid(); ++} ++ ++int _P11_detect_fork(unsigned int forkid) ++{ ++ if (getpid() == forkid) ++ return 0; ++ return 1; ++} ++ ++/* we have to detect fork manually */ ++_CONSTRUCTOR ++int _P11_register_fork_handler(void) ++{ ++ P11_forkid = getpid(); ++ return 0; ++} ++ ++# endif ++ ++#endif /* !_WIN32 */ ++ ++/* ++ * PKCS#11 reinitialization after fork ++ * It wipes out the internal state of the PKCS#11 library ++ * Any libp11 references to this state are no longer valid ++ */ ++static int check_fork_int(PKCS11_CTX *ctx) ++{ ++ PKCS11_CTX_private *cpriv = PRIVCTX(ctx); ++ ++ if (_P11_detect_fork(cpriv->forkid)) { ++ if (pkcs11_CTX_reload(ctx) < 0) ++ return -1; ++ cpriv->forkid = _P11_get_forkid(); ++ } ++ return 0; ++} ++ ++/* ++ * PKCS#11 reinitialization after fork ++ * Also relogins and reopens the session if needed ++ */ ++static int check_slot_fork_int(PKCS11_SLOT *slot) ++{ ++ PKCS11_SLOT_private *spriv = PRIVSLOT(slot); ++ PKCS11_CTX *ctx = SLOT2CTX(slot); ++ PKCS11_CTX_private *cpriv = PRIVCTX(ctx); ++ ++ if (check_fork_int(SLOT2CTX(slot)) < 0) ++ return -1; ++ if (spriv->forkid != cpriv->forkid) { ++ if (spriv->loggedIn) { ++ int saved = spriv->haveSession; ++ spriv->haveSession = 0; ++ spriv->loggedIn = 0; ++ if (pkcs11_relogin(slot) < 0) ++ return -1; ++ spriv->haveSession = saved; ++ } ++ if (spriv->haveSession) { ++ spriv->haveSession = 0; ++ if (pkcs11_reopen_session(slot) < 0) ++ return -1; ++ } ++ spriv->forkid = cpriv->forkid; ++ } ++ return 0; ++} ++ ++/* ++ * PKCS#11 reinitialization after fork ++ * Also reloads the key ++ */ ++static int check_key_fork_int(PKCS11_KEY *key) ++{ ++ PKCS11_SLOT *slot = KEY2SLOT(key); ++ PKCS11_KEY_private *kpriv = PRIVKEY(key); ++ PKCS11_SLOT_private *spriv = PRIVSLOT(slot); ++ ++ if (check_slot_fork_int(slot) < 0) ++ return -1; ++ if (spriv->forkid != kpriv->forkid) { ++ pkcs11_reload_key(key); ++ kpriv->forkid = spriv->forkid; ++ } ++ return 0; ++} ++ ++/* ++ * Locking interface to check_fork_int() ++ */ ++int check_fork(PKCS11_CTX *ctx) ++{ ++ PKCS11_CTX_private *cpriv; ++ int rv; ++ ++ if (ctx == NULL) ++ return -1; ++ cpriv = PRIVCTX(ctx); ++ CRYPTO_THREAD_write_lock(cpriv->rwlock); ++ rv = check_fork_int(ctx); ++ CRYPTO_THREAD_unlock(cpriv->rwlock); ++ return rv; ++} ++ ++/* ++ * Locking interface to check_slot_fork_int() ++ */ ++int check_slot_fork(PKCS11_SLOT *slot) ++{ ++ PKCS11_CTX_private *cpriv; ++ int rv; ++ ++ if (slot == NULL) ++ return -1; ++ cpriv = PRIVCTX(SLOT2CTX(slot)); ++ CRYPTO_THREAD_write_lock(cpriv->rwlock); ++ rv = check_slot_fork_int(slot); ++ CRYPTO_THREAD_unlock(cpriv->rwlock); ++ return rv; ++} ++ ++/* ++ * Reinitialize token (just its slot) ++ */ ++int check_token_fork(PKCS11_TOKEN *token) ++{ ++ if (token == NULL) ++ return -1; ++ return check_slot_fork(TOKEN2SLOT(token)); ++} ++ ++/* ++ * Locking interface to check_key_fork_int() ++ */ ++int check_key_fork(PKCS11_KEY *key) ++{ ++ PKCS11_CTX_private *cpriv; ++ int rv; ++ ++ if (key == NULL) ++ return -1; ++ cpriv = PRIVCTX(KEY2CTX(key)); ++ CRYPTO_THREAD_write_lock(cpriv->rwlock); ++ rv = check_key_fork_int(key); ++ CRYPTO_THREAD_unlock(cpriv->rwlock); ++ return rv; ++} ++ ++/* ++ * Reinitialize cert (just its token) ++ */ ++int check_cert_fork(PKCS11_CERT *cert) ++{ ++ if (cert == NULL) ++ return -1; ++ return check_token_fork(CERT2TOKEN(cert)); ++} ++ ++/* vim: set noexpandtab: */ +diff --git a/src/p11_front.c b/src/p11_front.c +index 167a778..efdd4c0 100644 +--- a/src/p11_front.c ++++ b/src/p11_front.c +@@ -25,144 +25,6 @@ + * PKCS11_get_ec_key_method + */ + +-/* +- * PKCS#11 reinitialization after fork +- * It wipes out the internal state of the PKCS#11 library +- * Any libp11 references to this state are no longer valid +- */ +-static int check_fork_int(PKCS11_CTX *ctx) +-{ +- PKCS11_CTX_private *cpriv = PRIVCTX(ctx); +- +- if (_P11_detect_fork(cpriv->forkid)) { +- if (pkcs11_CTX_reload(ctx) < 0) +- return -1; +- cpriv->forkid = _P11_get_forkid(); +- } +- return 0; +-} +- +-/* +- * PKCS#11 reinitialization after fork +- * Also relogins and reopens the session if needed +- */ +-static int check_slot_fork_int(PKCS11_SLOT *slot) +-{ +- PKCS11_SLOT_private *spriv = PRIVSLOT(slot); +- PKCS11_CTX *ctx = SLOT2CTX(slot); +- PKCS11_CTX_private *cpriv = PRIVCTX(ctx); +- +- if (check_fork_int(SLOT2CTX(slot)) < 0) +- return -1; +- if (spriv->forkid != cpriv->forkid) { +- if (spriv->loggedIn) { +- int saved = spriv->haveSession; +- spriv->haveSession = 0; +- spriv->loggedIn = 0; +- if (pkcs11_relogin(slot) < 0) +- return -1; +- spriv->haveSession = saved; +- } +- if (spriv->haveSession) { +- spriv->haveSession = 0; +- if (pkcs11_reopen_session(slot) < 0) +- return -1; +- } +- spriv->forkid = cpriv->forkid; +- } +- return 0; +-} +- +-/* +- * PKCS#11 reinitialization after fork +- * Also reloads the key +- */ +-static int check_key_fork_int(PKCS11_KEY *key) +-{ +- PKCS11_SLOT *slot = KEY2SLOT(key); +- PKCS11_KEY_private *kpriv = PRIVKEY(key); +- PKCS11_SLOT_private *spriv = PRIVSLOT(slot); +- +- if (check_slot_fork_int(slot) < 0) +- return -1; +- if (spriv->forkid != kpriv->forkid) { +- pkcs11_reload_key(key); +- kpriv->forkid = spriv->forkid; +- } +- return 0; +-} +- +-/* +- * Locking interface to check_fork_int() +- */ +-static int check_fork(PKCS11_CTX *ctx) +-{ +- PKCS11_CTX_private *cpriv; +- int rv; +- +- if (ctx == NULL) +- return -1; +- cpriv = PRIVCTX(ctx); +- CRYPTO_THREAD_write_lock(cpriv->rwlock); +- rv = check_fork_int(ctx); +- CRYPTO_THREAD_unlock(cpriv->rwlock); +- return rv; +-} +- +-/* +- * Locking interface to check_slot_fork_int() +- */ +-static int check_slot_fork(PKCS11_SLOT *slot) +-{ +- PKCS11_CTX_private *cpriv; +- int rv; +- +- if (slot == NULL) +- return -1; +- cpriv = PRIVCTX(SLOT2CTX(slot)); +- CRYPTO_THREAD_write_lock(cpriv->rwlock); +- rv = check_slot_fork_int(slot); +- CRYPTO_THREAD_unlock(cpriv->rwlock); +- return rv; +-} +- +-/* +- * Reinitialize token (just its slot) +- */ +-static int check_token_fork(PKCS11_TOKEN *token) +-{ +- if (token == NULL) +- return -1; +- return check_slot_fork(TOKEN2SLOT(token)); +-} +- +-/* +- * Locking interface to check_key_fork_int() +- */ +-static int check_key_fork(PKCS11_KEY *key) +-{ +- PKCS11_CTX_private *cpriv; +- int rv; +- +- if (key == NULL) +- return -1; +- cpriv = PRIVCTX(KEY2CTX(key)); +- CRYPTO_THREAD_write_lock(cpriv->rwlock); +- rv = check_key_fork_int(key); +- CRYPTO_THREAD_unlock(cpriv->rwlock); +- return rv; +-} +- +-/* +- * Reinitialize cert (just its token) +- */ +-static int check_cert_fork(PKCS11_CERT *cert) +-{ +- if (cert == NULL) +- return -1; +- return check_token_fork(CERT2TOKEN(cert)); +-} +- + /* External interface to the libp11 features */ + + PKCS11_CTX *PKCS11_CTX_new(void) +-- +2.17.1 + diff --git a/SOURCES/openssl-pkcs11-0.4.8-fix-build-old-c-dialects.patch b/SOURCES/openssl-pkcs11-0.4.8-fix-build-old-c-dialects.patch new file mode 100644 index 0000000..35384bb --- /dev/null +++ b/SOURCES/openssl-pkcs11-0.4.8-fix-build-old-c-dialects.patch @@ -0,0 +1,55 @@ +From c2512ee261efb6fdd81226549f48421bd57a8230 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Micha=C5=82=20Trojnara?= +Date: Mon, 3 Sep 2018 20:54:59 +0200 +Subject: [PATCH 20/23] Build fixes for old C dialects + +--- + src/p11_cert.c | 3 ++- + src/p11_key.c | 3 ++- + 2 files changed, 4 insertions(+), 2 deletions(-) + +diff --git a/src/p11_cert.c b/src/p11_cert.c +index 811db85..bc78447 100644 +--- a/src/p11_cert.c ++++ b/src/p11_cert.c +@@ -74,6 +74,7 @@ int pkcs11_remove_certificate(PKCS11_CERT *cert){ + CK_ULONG count; + CK_ATTRIBUTE search_parameters[32]; + unsigned int n = 0; ++ int rv; + + /* First, make sure we have a session */ + if (!spriv->haveSession && PKCS11_open_session(slot, 1)){ +@@ -88,7 +89,7 @@ int pkcs11_remove_certificate(PKCS11_CERT *cert){ + pkcs11_addattr_s(search_parameters + n++, CKA_LABEL, cert->label); + } + +- int rv = CRYPTOKI_call(ctx, ++ rv = CRYPTOKI_call(ctx, + C_FindObjectsInit(spriv->session, search_parameters, n)); + CRYPTOKI_checkerr(CKR_F_PKCS11_REMOVE_CERTIFICATE, rv); + +diff --git a/src/p11_key.c b/src/p11_key.c +index 1681c7d..f73029b 100644 +--- a/src/p11_key.c ++++ b/src/p11_key.c +@@ -457,6 +457,7 @@ int pkcs11_remove_key(PKCS11_KEY *key) { + CK_ULONG count; + CK_ATTRIBUTE search_parameters[32]; + unsigned int n = 0; ++ int rv; + + /* First, make sure we have a session */ + if (!spriv->haveSession && PKCS11_open_session(slot, 1)) +@@ -470,7 +471,7 @@ int pkcs11_remove_key(PKCS11_KEY *key) { + if (key->label) + pkcs11_addattr_s(search_parameters + n++, CKA_LABEL, key->label); + +- int rv = CRYPTOKI_call(ctx, ++ rv = CRYPTOKI_call(ctx, + C_FindObjectsInit(spriv->session, search_parameters, n)); + CRYPTOKI_checkerr(CKR_F_PKCS11_REMOVE_KEY, rv); + +-- +2.17.1 + diff --git a/SOURCES/openssl-pkcs11-0.4.8-fix-leak-rsa-object-pkcs11-store-key.patch b/SOURCES/openssl-pkcs11-0.4.8-fix-leak-rsa-object-pkcs11-store-key.patch new file mode 100644 index 0000000..df1166c --- /dev/null +++ b/SOURCES/openssl-pkcs11-0.4.8-fix-leak-rsa-object-pkcs11-store-key.patch @@ -0,0 +1,25 @@ +From e420b22fab9b81d7f4ec8c82bd836269c9d2dc51 Mon Sep 17 00:00:00 2001 +From: lbonn +Date: Thu, 30 Aug 2018 14:48:24 +0200 +Subject: [PATCH 11/23] Fix leak of RSA object in pkcs11_store_key() + +EVP_PKEY_get1_RSA() increments the reference count +--- + src/p11_key.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/src/p11_key.c b/src/p11_key.c +index 1e99e0d..6fb844f 100644 +--- a/src/p11_key.c ++++ b/src/p11_key.c +@@ -265,6 +265,7 @@ static int pkcs11_store_key(PKCS11_TOKEN *token, EVP_PKEY *pk, + RSA_get0_key(rsa, &rsa_n, &rsa_e, &rsa_d); + RSA_get0_factors(rsa, &rsa_p, &rsa_q); + RSA_get0_crt_params(rsa, &rsa_dmp1, &rsa_dmq1, &rsa_iqmp); ++ RSA_free(rsa); + #else + rsa_n=rsa->n; + rsa_e=rsa->e; +-- +2.17.1 + diff --git a/SOURCES/openssl-pkcs11-0.4.8-improve-code-readability.patch b/SOURCES/openssl-pkcs11-0.4.8-improve-code-readability.patch new file mode 100644 index 0000000..29c16c2 --- /dev/null +++ b/SOURCES/openssl-pkcs11-0.4.8-improve-code-readability.patch @@ -0,0 +1,43 @@ +From 1462a0a25286d36cf85acb4bab189ae6cc8eabd0 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Micha=C5=82=20Trojnara?= +Date: Fri, 31 Aug 2018 08:45:16 +0200 +Subject: [PATCH 14/23] Improved code readability + +--- + src/p11_slot.c | 13 +++++++------ + 1 file changed, 7 insertions(+), 6 deletions(-) + +diff --git a/src/p11_slot.c b/src/p11_slot.c +index 94ec378..c5140c1 100644 +--- a/src/p11_slot.c ++++ b/src/p11_slot.c +@@ -119,19 +119,20 @@ PKCS11_SLOT *pkcs11_find_token(PKCS11_CTX *ctx, PKCS11_SLOT *slots, unsigned int + */ + PKCS11_SLOT *pkcs11_find_next_token(PKCS11_CTX *ctx, PKCS11_SLOT *slots, unsigned int nslots, PKCS11_SLOT *current) + { ++ int offset; ++ + if (slots == NULL) + return NULL; + + if (current) { +- if (slots > current || (current - slots) > nslots) ++ offset = current + 1 - slots; ++ if (offset < 1 || (unsigned int)offset >= nslots) + return NULL; +- +- current++; +- nslots -= (current - slots); +- slots = current; ++ } else { ++ offset = 0; + } + +- return pkcs11_find_token(ctx, slots, nslots); ++ return pkcs11_find_token(ctx, slots+offset, nslots-offset); + } + + /* +-- +2.17.1 + diff --git a/SOURCES/openssl-pkcs11-0.4.8-missing-function-declaration.patch b/SOURCES/openssl-pkcs11-0.4.8-missing-function-declaration.patch new file mode 100644 index 0000000..ba8cdf7 --- /dev/null +++ b/SOURCES/openssl-pkcs11-0.4.8-missing-function-declaration.patch @@ -0,0 +1,24 @@ +From 63e2039edb888bfa190b8dd6cfa646ccab7de5b7 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Micha=C5=82=20Trojnara?= +Date: Thu, 9 Aug 2018 07:19:54 +0200 +Subject: [PATCH 02/23] Missing function declaration + +--- + src/libp11.h | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/src/libp11.h b/src/libp11.h +index 844bab9..2a8aa64 100644 +--- a/src/libp11.h ++++ b/src/libp11.h +@@ -40,6 +40,7 @@ int ERR_load_CKR_strings(void); + void ERR_unload_CKR_strings(void); + void ERR_CKR_error(int function, int reason, char *file, int line); + # define CKRerr(f,r) ERR_CKR_error((f),(r),__FILE__,__LINE__) ++int ERR_get_CKR_code(void); + + /* + * The purpose of this library is to provide a simple PKCS11 +-- +2.17.1 + diff --git a/SOURCES/openssl-pkcs11-0.4.8-openssl-license-update.patch b/SOURCES/openssl-pkcs11-0.4.8-openssl-license-update.patch new file mode 100644 index 0000000..e9a92b1 --- /dev/null +++ b/SOURCES/openssl-pkcs11-0.4.8-openssl-license-update.patch @@ -0,0 +1,91 @@ +From 218edd6df9f9546eb0b6f55fbcff07a1aa4763c6 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Micha=C5=82=20Trojnara?= +Date: Sat, 1 Sep 2018 06:26:43 +0200 +Subject: [PATCH 15/23] Updated OpenSSL license in the engine front-end + +The OpenSSL team has decided to re-license their library. +This commit propagates the license change to our derived code. +--- + src/eng_front.c | 65 +++++++------------------------------------------ + 1 file changed, 9 insertions(+), 56 deletions(-) + +diff --git a/src/eng_front.c b/src/eng_front.c +index 286aaa9..95c2b03 100644 +--- a/src/eng_front.c ++++ b/src/eng_front.c +@@ -1,63 +1,16 @@ +-/* crypto/engine/hw_pkcs11.c */ +-/* Written by Geoff Thorpe (geoff@geoffthorpe.net) for the OpenSSL ++/* ++ * Copyright 1999-2001 The OpenSSL Project Authors. All Rights Reserved. ++ * Written by Geoff Thorpe (geoff@geoffthorpe.net) for the OpenSSL + * project 2000. ++ * Portions Copyright (c) 2003 Kevin Stefanik (kstef@mtppi.org) + * Copied/modified by Kevin Stefanik (kstef@mtppi.org) for the OpenSC + * project 2003. +- * Copyright (c) 2017 Michał Trojnara +- */ +-/* ==================================================================== +- * Copyright (c) 1999-2001 The OpenSSL Project. All rights reserved. +- * Portions Copyright (c) 2003 Kevin Stefanik (kstef@mtppi.org) +- * +- * Redistribution and use in source and binary forms, with or without +- * modification, are permitted provided that the following conditions +- * are met: +- * +- * 1. Redistributions of source code must retain the above copyright +- * notice, this list of conditions and the following disclaimer. +- * +- * 2. Redistributions in binary form must reproduce the above copyright +- * notice, this list of conditions and the following disclaimer in +- * the documentation and/or other materials provided with the +- * distribution. +- * +- * 3. All advertising materials mentioning features or use of this +- * software must display the following acknowledgment: +- * "This product includes software developed by the OpenSSL Project +- * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" +- * +- * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to +- * endorse or promote products derived from this software without +- * prior written permission. For written permission, please contact +- * licensing@OpenSSL.org. +- * +- * 5. Products derived from this software may not be called "OpenSSL" +- * nor may "OpenSSL" appear in their names without prior written +- * permission of the OpenSSL Project. +- * +- * 6. Redistributions of any form whatsoever must retain the following +- * acknowledgment: +- * "This product includes software developed by the OpenSSL Project +- * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" +- * +- * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY +- * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR +- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED +- * OF THE POSSIBILITY OF SUCH DAMAGE. +- * ==================================================================== +- * +- * This product includes cryptographic software written by Eric Young +- * (eay@cryptsoft.com). This product includes software written by Tim +- * Hudson (tjh@cryptsoft.com). ++ * Copyright (c) 2016-2018 Michał Trojnara + * ++ * Licensed under the OpenSSL license (the "License"). You may not use ++ * this file except in compliance with the License. You can obtain a copy ++ * in the file LICENSE in the source distribution or at ++ * https://www.openssl.org/source/license.html + */ + + #include "engine.h" +-- +2.17.1 + diff --git a/SOURCES/openssl-pkcs11-0.4.8-require-debug-to-print.patch b/SOURCES/openssl-pkcs11-0.4.8-require-debug-to-print.patch new file mode 100644 index 0000000..ebf2029 --- /dev/null +++ b/SOURCES/openssl-pkcs11-0.4.8-require-debug-to-print.patch @@ -0,0 +1,49 @@ +From 58230eb4869fad540fab450b79f325ca76d2320e Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Micha=C5=82=20Trojnara?= +Date: Wed, 12 Sep 2018 22:42:06 +0200 +Subject: [PATCH 22/23] Require DEBUG to print libp11 debugging messages + +Printing unneeded warnings was mentioned in #242 +--- + src/p11_key.c | 9 +++++---- + src/p11_pkey.c | 2 ++ + 2 files changed, 7 insertions(+), 4 deletions(-) + +diff --git a/src/p11_key.c b/src/p11_key.c +index f73029b..d226b86 100644 +--- a/src/p11_key.c ++++ b/src/p11_key.c +@@ -331,10 +331,11 @@ EVP_PKEY *pkcs11_get_key(PKCS11_KEY *key, int isPrivate) + if (key->evp_key == NULL) + return NULL; + kpriv->always_authenticate = CK_FALSE; +- if(isPrivate) { +- if(key_getattr_val(key, CKA_ALWAYS_AUTHENTICATE, +- &kpriv->always_authenticate, sizeof(CK_BBOOL))) +- fprintf(stderr, "Missing CKA_ALWAYS_AUTHENTICATE attribute\n"); ++ if (isPrivate && key_getattr_val(key, CKA_ALWAYS_AUTHENTICATE, ++ &kpriv->always_authenticate, sizeof(CK_BBOOL))) { ++#ifdef DEBUG ++ fprintf(stderr, "Missing CKA_ALWAYS_AUTHENTICATE attribute\n"); ++#endif + } + } + #if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER) +diff --git a/src/p11_pkey.c b/src/p11_pkey.c +index 95c6458..88cbc79 100644 +--- a/src/p11_pkey.c ++++ b/src/p11_pkey.c +@@ -524,8 +524,10 @@ 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) + { ++#ifdef DEBUG + fprintf(stderr, "%s:%d pkcs11_try_pkey_ec_sign() not implemented\n", + __FILE__, __LINE__); ++#endif + return -1; + } + +-- +2.17.1 + diff --git a/SPECS/openssl-pkcs11.spec b/SPECS/openssl-pkcs11.spec new file mode 100644 index 0000000..c90a801 --- /dev/null +++ b/SPECS/openssl-pkcs11.spec @@ -0,0 +1,162 @@ +Version: 0.4.8 +Release: 2%{?dist} + +# Define the directory where the OpenSSL engines are installed +%global enginesdir %{_libdir}/engines-1.1 + +Name: openssl-pkcs11 +Summary: A PKCS#11 engine for use with OpenSSL +# The source code is LGPLv2+ except eng_back.c and eng_parse.c which are BSD +License: LGPLv2+ and BSD +URL: https://github.com/OpenSC/libp11 +Source0: https://github.com/OpenSC/libp11/releases/download/libp11-%{version}/libp11-%{version}.tar.gz + +Patch0: openssl-pkcs11-0.4.8-missing-function-declaration.patch +Patch1: openssl-pkcs11-0.4.8-ec-sign-test.patch +Patch2: openssl-pkcs11-0.4.8-error-handling-evp-pkey-set1-engine.patch +Patch3: openssl-pkcs11-0.4.8-evp-pkey-ec-framework.patch +Patch4: openssl-pkcs11-0.4.8-error-handling-evp-pkey-set1-engine-fixed.patch +Patch5: openssl-pkcs11-0.4.8-expose-check-fork.patch +Patch6: openssl-pkcs11-0.4.8-ex-data-coding-style.patch +Patch7: openssl-pkcs11-0.4.8-atfork-checks-rsa-and-ec-keys.patch +Patch8: openssl-pkcs11-0.4.8-fix-leak-rsa-object-pkcs11-store-key.patch +Patch9: openssl-pkcs11-0.4.8-improve-code-readability.patch +Patch10: openssl-pkcs11-0.4.8-openssl-license-update.patch +Patch11: openssl-pkcs11-0.4.8-fix-build-old-c-dialects.patch +Patch12: openssl-pkcs11-0.4.8-allow-use-privkey-without-pin.patch +Patch13: openssl-pkcs11-0.4.8-require-debug-to-print.patch + +BuildRequires: autoconf automake libtool +BuildRequires: openssl-devel +BuildRequires: pkgconfig +BuildRequires: pkgconfig(p11-kit-1) +# Needed for testsuite +BuildRequires: softhsm opensc procps-ng + +%if 0%{?fedora} +BuildRequires: doxygen +%endif + +Requires: p11-kit-trust +Requires: openssl >= 1.0.2 + +# Package renamed from libp11 to openssl-pkcs11 in release 0.4.7-4 +Provides: libp11%{?_isa} = %{version}-%{release} +Obsoletes: libp11 < 0.4.7-4 +# The engine_pkcs11 subpackage is also provided +Provides: engine_pkcs11%{?_isa} = %{version}-%{release} +Obsoletes: engine_pkcs11 < 0.4.7-4 + +%if 0%{?fedora} +# The libp11-devel subpackage was removed in libp11-0.4.7-1, but not obsoleted +# This Obsoletes prevents the conflict in updates by removing old libp11-devel +Obsoletes: libp11-devel < 0.4.7-4 +%endif + +%description -n openssl-pkcs11 +openssl-pkcs11 enables hardware security module (HSM), and smart card support in +OpenSSL applications. More precisely, it is an OpenSSL engine which makes +registered PKCS#11 modules available for OpenSSL applications. The engine is +optional and can be loaded by configuration file, command line or through the +OpenSSL ENGINE API. + +# The libp11-devel subpackage was reintroduced in libp11-0.4.7-7 for Fedora +%if 0%{?fedora} +%package -n libp11-devel +Summary: Files for developing with libp11 +Requires: %{name} = %{version}-%{release} + +%description -n libp11-devel +The libp11-devel package contains libraries and header files for +developing applications that use libp11. + +%endif + +%prep +%autosetup -p 1 -n libp11-%{version} + +%build +autoreconf -fvi +export CFLAGS="%{optflags}" +%if 0%{?fedora} +%configure --disable-static --enable-api-doc --with-enginesdir=%{enginesdir} +%else +%configure --disable-static --with-enginesdir=%{enginesdir} +%endif +make V=1 %{?_smp_mflags} + +%install +mkdir -p %{buildroot}%{enginesdir} +make install DESTDIR=%{buildroot} + +# Remove libtool .la files +rm -f %{buildroot}%{_libdir}/*.la +rm -f %{buildroot}%{enginesdir}/*.la + +%if ! 0%{?fedora} +## Remove development files +rm -f %{buildroot}%{_libdir}/libp11.so +rm -f %{buildroot}%{_libdir}/pkgconfig/libp11.pc +rm -f %{buildroot}%{_includedir}/*.h +%endif + +# Remove documentation automatically installed by make install +rm -rf %{buildroot}%{_docdir}/libp11/ + +%check +make check %{?_smp_mflags} + +%post -p /sbin/ldconfig + +%postun -p /sbin/ldconfig + +%files +%license COPYING +%doc NEWS +%{_libdir}/libp11.so.* +%{enginesdir}/*.so + +%if 0%{?fedora} +%files -n libp11-devel +%doc examples/ doc/api.out/html/ +%{_libdir}/libp11.so +%{_libdir}/pkgconfig/libp11.pc +%{_includedir}/*.h +%endif + +%changelog +* Tue Sep 18 2018 Anderson Sasaki - 0.4.8-2 +- Require OpenSSL >= 1.0.2 +- Fixed missing declaration of ERR_get_CKR_code() +- Add support to use EC keys and tests (#1625338) +- Exposed check_fork() API +- Fixed memory leak of RSA objects in pkcs11_store_key() +- Updated OpenSSL license in eng_front.c +- Fixed build for old C dialects +- Allow engine to use private key without PIN +- Require DEBUG to be defined to print debug messages +- Changed package description + +* Mon Aug 06 2018 Anderson Sasaki - 0.4.8-1 +- Update to 0.4.8-1 +- RSA key generation on the token +- RSA-OAEP and RSA-PKCS encryption support +- RSA-PSS signature support +- Support for OpenSSL 1.1.1 beta +- Removed support for OpenSSL 0.9.8 +- Various bug fixes and enhancements + +* Fri Jul 13 2018 Fedora Release Engineering - 0.4.7-8 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_29_Mass_Rebuild + +* Wed Jun 06 2018 Anderson Sasaki - 0.4.7-7 +- Reintroduce libp11-devel subpackage to Fedora (#1583719) + +* Tue Mar 13 2018 Anderson Sasaki - 0.4.7-6 +- Obsolete libp11-devel to fix update + +* Tue Mar 06 2018 Anderson Sasaki - 0.4.7-5 +- Fixed broken Obsoletes + +* Thu Mar 01 2018 Anderson Sasaki - 0.4.7-4 +- Package renamed from libp11 to openssl-pkcs11