From e4cf0e7b39093de24e832a6d04b8d62d209c3901 Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Tue, 4 May 2021 13:46:20 +0200 Subject: [PATCH 01/12] Basic unit test for secure messaging functions --- src/tests/unittests/Makefile.am | 8 ++++ src/tests/unittests/sm.c | 69 +++++++++++++++++++++++++++++++++ 2 files changed, 77 insertions(+) create mode 100644 src/tests/unittests/sm.c diff --git a/src/tests/unittests/Makefile.am b/src/tests/unittests/Makefile.am index b6bef298..8708e464 100644 --- a/src/tests/unittests/Makefile.am +++ b/src/tests/unittests/Makefile.am @@ -32,6 +32,14 @@ compression_SOURCES = compression.c compression_LDADD = $(LDADD) $(OPTIONAL_ZLIB_LIBS) endif +if ENABLE_OPENSSL +noinst_PROGRAMS += sm +TESTS += sm + +sm_SOURCES = sm.c +sm_LDADD = $(top_builddir)/src/sm/libsm.la $(LDADD) +endif + endif diff --git a/src/tests/unittests/sm.c b/src/tests/unittests/sm.c new file mode 100644 index 00000000..75cce97d --- /dev/null +++ b/src/tests/unittests/sm.c @@ -0,0 +1,69 @@ +/* + * sm.c: Unit tests for Secure Messaging + * + * Copyright (C) 2021 Red Hat, Inc. + * + * Author: Jakub Jelen + * + * 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 General Public License + * along with this program. If not, see . + */ + +#include "torture.h" +#include "libopensc/log.c" +#include "sm/sm-common.h" + +static void torture_sm_incr_ssc(void **state) +{ + unsigned char in[] = {0x00, 0x00}; + + (void)state; + + /* just make sure it does not crash */ + sm_incr_ssc(NULL, 0); + + /* zero-length input should not underflow the buffer */ + sm_incr_ssc(in, 0); + + /* shortest possible input */ + in[0] = 0x42; + sm_incr_ssc(in, 1); + assert_int_equal(in[0], 0x43); + + /* overflow to the second byte */ + in[0] = 0x00; + in[1] = 0xff; + sm_incr_ssc(in, 2); + assert_int_equal(in[0], 0x01); + assert_int_equal(in[1], 0x00); + + /* overflow */ + in[0] = 0xff; + in[1] = 0xff; + sm_incr_ssc(in, 2); + assert_int_equal(in[0], 0x00); + assert_int_equal(in[1], 0x00); +} + + +int main(void) +{ + int rc; + struct CMUnitTest tests[] = { + /* sm_incr_ssc */ + cmocka_unit_test(torture_sm_incr_ssc), + }; + + rc = cmocka_run_group_tests(tests, NULL, NULL); + return rc; +} From 12be677cb869bd1ae11180224fded86dd3686f1d Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Wed, 5 May 2021 14:27:05 +0200 Subject: [PATCH 02/12] Drop duplicate -Werror build flag (already used unless --disable-strict) --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 62afc6e2..d88d7181 100644 --- a/configure.ac +++ b/configure.ac @@ -133,7 +133,7 @@ esac AX_CODE_COVERAGE() -AX_CHECK_COMPILE_FLAG([-Wunknown-warning-option], [have_unknown_warning_option="yes"], [have_unknown_warning_option="no"], [-Werror]) +AX_CHECK_COMPILE_FLAG([-Wunknown-warning-option], [have_unknown_warning_option="yes"], [have_unknown_warning_option="no"]) AM_CONDITIONAL([HAVE_UNKNOWN_WARNING_OPTION], [test "${have_unknown_warning_option}" = "yes"]) AC_ARG_ENABLE( From 07f5e63abf1c9e446f9df6c86830cbdefcc7ae3f Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Thu, 6 May 2021 10:53:14 +0200 Subject: [PATCH 03/12] tests: verify secure messaging functions work as expected --- src/tests/unittests/Makefile.am | 1 - src/tests/unittests/sm.c | 189 ++++++++++++++++++++++++++++++++ 2 files changed, 189 insertions(+), 1 deletion(-) diff --git a/src/tests/unittests/Makefile.am b/src/tests/unittests/Makefile.am index 8708e464..03019c32 100644 --- a/src/tests/unittests/Makefile.am +++ b/src/tests/unittests/Makefile.am @@ -41,5 +41,4 @@ sm_LDADD = $(top_builddir)/src/sm/libsm.la $(LDADD) endif - endif diff --git a/src/tests/unittests/sm.c b/src/tests/unittests/sm.c index 75cce97d..d39d13c9 100644 --- a/src/tests/unittests/sm.c +++ b/src/tests/unittests/sm.c @@ -23,6 +23,33 @@ #include "libopensc/log.c" #include "sm/sm-common.h" +/* Setup context */ +static int setup_sc_context(void **state) +{ + sc_context_t *ctx = NULL; + int rv; + + rv = sc_establish_context(&ctx, "sm"); + assert_non_null(ctx); + assert_int_equal(rv, SC_SUCCESS); + + *state = ctx; + + return 0; +} + +/* Cleanup context */ +static int teardown_sc_context(void **state) +{ + sc_context_t *ctx = *state; + int rv; + + rv = sc_release_context(ctx); + assert_int_equal(rv, SC_SUCCESS); + + return 0; +} + static void torture_sm_incr_ssc(void **state) { unsigned char in[] = {0x00, 0x00}; @@ -55,6 +82,158 @@ static void torture_sm_incr_ssc(void **state) assert_int_equal(in[1], 0x00); } +static void torture_sm_crypt_des_cbc3(void **state) +{ + sc_context_t *ctx = *state; + /* Test vector from + * https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-20.pdf + * 5.2.1.1 The Variable Plaintext Known Answer Test -TCBC Mode + */ + unsigned char key[] = { + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, /* KEY1 */ + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, /* KEY2 */}; + unsigned char plain[] = {0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + unsigned char ciphertext[] = {0x95, 0xF8, 0xA5, 0xE5, 0xDD, 0x31, 0xD9, 0x00}; + unsigned char *out = NULL; /* allocates */ + size_t out_len = 0; + int rv; + + rv = sm_encrypt_des_cbc3(ctx, key, plain, sizeof(plain), &out, &out_len, 1); + assert_int_equal(rv, SC_SUCCESS); + assert_int_equal(out_len, sizeof(ciphertext)); + assert_memory_equal(out, ciphertext, sizeof(ciphertext)); + free(out); + out = NULL; + out_len = 0; + + rv = sm_decrypt_des_cbc3(ctx, key, ciphertext, sizeof(ciphertext), &out, &out_len); + assert_int_equal(rv, SC_SUCCESS); + assert_memory_equal(out, plain, sizeof(plain)); + free(out); +} + +static void torture_sm_crypt_des_cbc3_multiblock(void **state) +{ + /* not a test vector -- generated by openssl 1.1.1 */ + sc_context_t *ctx = *state; + unsigned char key[] = { + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, /* KEY1 */ + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, /* KEY2 */}; + unsigned char plain[] = { + 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00}; + unsigned char ciphertext[] = { + 0x95, 0xF8, 0xA5, 0xE5, 0xDD, 0x31, 0xD9, 0x00, + 0xAF, 0xA0, 0x77, 0x1d, 0x35, 0xE1, 0xCC, 0x26}; + unsigned char *out = NULL; /* allocates */ + size_t out_len = 0; + int rv; + + rv = sm_encrypt_des_cbc3(ctx, key, plain, sizeof(plain), &out, &out_len, 1); + assert_int_equal(rv, SC_SUCCESS); + assert_int_equal(out_len, sizeof(ciphertext)); + assert_memory_equal(out, ciphertext, sizeof(ciphertext)); + free(out); + out = NULL; + out_len = 0; + + rv = sm_decrypt_des_cbc3(ctx, key, ciphertext, sizeof(ciphertext), &out, &out_len); + assert_int_equal(rv, SC_SUCCESS); + assert_memory_equal(out, plain, sizeof(plain)); + free(out); +} + +static void torture_sm_crypt_des_cbc3_force_pad(void **state) +{ + /* not a test vector -- generated by openssl 1.1.1 */ + sc_context_t *ctx = *state; + unsigned char key[] = { + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, /* KEY1 */ + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, /* KEY2 */}; + unsigned char plain[] = {0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + unsigned char ciphertext[] = { + 0x95, 0xF8, 0xA5, 0xE5, 0xDD, 0x31, 0xD9, 0x00, + 0xC6, 0xD3, 0xE1, 0x4F, 0xFB, 0xDE, 0xDF, 0xF9}; + unsigned char *out = NULL; /* allocates */ + size_t out_len = 0; + int rv; + + rv = sm_encrypt_des_cbc3(ctx, key, plain, sizeof(plain), &out, &out_len, 0); + assert_int_equal(rv, SC_SUCCESS); + assert_int_equal(out_len, sizeof(ciphertext)); + assert_memory_equal(out, ciphertext, sizeof(ciphertext)); + free(out); + out = NULL; + out_len = 0; + + rv = sm_decrypt_des_cbc3(ctx, key, ciphertext, sizeof(ciphertext), &out, &out_len); + assert_int_equal(rv, SC_SUCCESS); + assert_memory_equal(out, plain, sizeof(plain)); + free(out); +} + +static void torture_sm_encrypt_des_ecb3(void **state) +{ + /* Test vector from + * https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-20.pdf + * 5.2.1.1 The Variable Plaintext Known Answer Test -TCBC Mode + */ + unsigned char key[] = { + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, /* KEY1 */ + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, /* KEY2 */}; + unsigned char plain[] = {0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + unsigned char ciphertext[] = {0x95, 0xF8, 0xA5, 0xE5, 0xDD, 0x31, 0xD9, 0x00}; + unsigned char *out = NULL; /* allocates */ + int out_len = 0; + int rv; + + (void)state; + + rv = sm_encrypt_des_ecb3(key, plain, sizeof(plain), &out, &out_len); + assert_int_equal(rv, SC_SUCCESS); + assert_int_equal(out_len, sizeof(ciphertext)); + assert_memory_equal(out, ciphertext, sizeof(ciphertext)); + free(out); + out = NULL; + out_len = 0; + + rv = sm_encrypt_des_ecb3(key, ciphertext, sizeof(ciphertext), &out, &out_len); + assert_int_equal(rv, SC_SUCCESS); + assert_memory_equal(out, plain, sizeof(plain)); + free(out); +} + +static void torture_sm_encrypt_des_ecb3_multiblock(void **state) +{ + /* not a test vector -- generated by openssl 1.1.1 */ + unsigned char key[] = { + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, /* KEY1 */ + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, /* KEY2 */}; + unsigned char plain[] = { + 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00}; + unsigned char ciphertext[] = { + 0x95, 0xF8, 0xA5, 0xE5, 0xDD, 0x31, 0xD9, 0x00, + 0x18, 0x0d, 0x91, 0xdf, 0xa1, 0x25, 0x2f, 0x81}; + unsigned char *out = NULL; /* allocates */ + int out_len = 0; + int rv; + + (void)state; + + rv = sm_encrypt_des_ecb3(key, plain, sizeof(plain), &out, &out_len); + assert_int_equal(rv, SC_SUCCESS); + assert_int_equal(out_len, sizeof(ciphertext)); + assert_memory_equal(out, ciphertext, sizeof(ciphertext)); + free(out); + out = NULL; + out_len = 0; + + rv = sm_encrypt_des_ecb3(key, ciphertext, sizeof(ciphertext), &out, &out_len); + assert_int_equal(rv, SC_SUCCESS); + assert_memory_equal(out, plain, sizeof(plain)); + free(out); +} int main(void) { @@ -62,6 +241,16 @@ int main(void) struct CMUnitTest tests[] = { /* sm_incr_ssc */ cmocka_unit_test(torture_sm_incr_ssc), + /* sm_encrypt_des_cbc3 and sm_decrypt_des_cbc3 */ + cmocka_unit_test_setup_teardown(torture_sm_crypt_des_cbc3, + setup_sc_context, teardown_sc_context), + cmocka_unit_test_setup_teardown(torture_sm_crypt_des_cbc3_multiblock, + setup_sc_context, teardown_sc_context), + cmocka_unit_test_setup_teardown(torture_sm_crypt_des_cbc3_force_pad, + setup_sc_context, teardown_sc_context), + /* sm_encrypt_des_ecb3 */ + cmocka_unit_test(torture_sm_encrypt_des_ecb3), + cmocka_unit_test(torture_sm_encrypt_des_ecb3_multiblock), }; rc = cmocka_run_group_tests(tests, NULL, NULL); From 1b92501ef98f5bb785aa090163945e7a090bebf0 Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Thu, 6 May 2021 10:53:56 +0200 Subject: [PATCH 04/12] sm: Rewrite to use non-deprecated OpenSSL 3.0 API --- src/sm/sm-common.c | 227 ++++++++++++++++++++++++++++++++--- src/sm/sm-common.h | 4 +- src/smm/sm-cwa14890.c | 8 +- src/smm/sm-global-platform.c | 17 +-- src/tests/unittests/sm.c | 122 ++++++++++++++++++- 5 files changed, 338 insertions(+), 40 deletions(-) diff --git a/src/sm/sm-common.c b/src/sm/sm-common.c index ecd6ef12..d47228d8 100644 --- a/src/sm/sm-common.c +++ b/src/sm/sm-common.c @@ -40,6 +40,7 @@ #error "Need OpenSSL" #endif +#include #include #include @@ -49,6 +50,7 @@ #include "sm-common.h" +#if OPENSSL_VERSION_NUMBER < 0x30000000L /* * From crypto/des/des_locl.h of OpenSSL . */ @@ -120,18 +122,34 @@ DES_3cbc_encrypt(DES_cblock *input, DES_cblock *output, long length, } memcpy(*iv,icv_out,sizeof(DES_cblock)); } +#else +#include + +/* The single-DES algorithm is not available in the default provider anymore + * so we need to load the legacy provider. This is not done on the application + * start, but only as needed */ +OSSL_PROVIDER *legacy_provider = NULL; +#endif DES_LONG DES_cbc_cksum_3des_emv96(const unsigned char *in, DES_cblock *output, - long length, DES_key_schedule *schedule, DES_key_schedule *schedule2, + long length, unsigned char *key, const_DES_cblock *ivec) { - register DES_LONG tout0,tout1,tin0,tin1; register long l=length; - DES_LONG tin[2]; unsigned char *out = &(*output)[0]; const unsigned char *iv = &(*ivec)[0]; +#if OPENSSL_VERSION_NUMBER < 0x30000000L + register DES_LONG tout0,tout1,tin0,tin1; + DES_LONG tin[2]; + DES_cblock kk, k2; + DES_key_schedule ks,ks2; + + memcpy(&kk, key, 8); + memcpy(&k2, key + 8, 8); + DES_set_key_unchecked(&kk,&ks); + DES_set_key_unchecked(&k2,&ks2); c2l(iv,tout0); c2l(iv,tout1); @@ -147,7 +165,7 @@ DES_cbc_cksum_3des_emv96(const unsigned char *in, DES_cblock *output, tin0^=tout0; tin[0]=tin0; tin1^=tout1; tin[1]=tin1; - DES_encrypt1((DES_LONG *)tin,schedule, DES_ENCRYPT); + DES_encrypt1((DES_LONG *)tin, &ks, DES_ENCRYPT); tout0=tin[0]; tout1=tin[1]; } @@ -161,9 +179,8 @@ DES_cbc_cksum_3des_emv96(const unsigned char *in, DES_cblock *output, tin0^=tout0; tin[0]=tin0; tin1^=tout1; tin[1]=tin1; - DES_encrypt3((DES_LONG *)tin,schedule,schedule2,schedule); + DES_encrypt3((DES_LONG *)tin, &ks, &ks2, &ks); tout1=tin[1]; - if (out != NULL) { l2c(tout0,out); @@ -179,22 +196,87 @@ DES_cbc_cksum_3des_emv96(const unsigned char *in, DES_cblock *output, | ((tout1 << 8L) & 0x00FF0000) | ((tout1 << 24L) & 0xFF000000); return(tout1); +#else + EVP_CIPHER_CTX *cctx = NULL; + unsigned char outv[8], tmpout[4]; + int tmplen; + + /* Prepare IV */ + memcpy(outv, iv, sizeof outv); + + cctx = EVP_CIPHER_CTX_new(); + if (l > 8) { + if (legacy_provider == NULL) { + legacy_provider = OSSL_PROVIDER_load(NULL, "legacy"); + } + if (!EVP_EncryptInit_ex2(cctx, EVP_des_cbc(), key, iv, NULL)) { + EVP_CIPHER_CTX_free(cctx); + return SC_ERROR_INTERNAL; + } + /* Disable padding, otherwise it will fail to decrypt non-padded inputs */ + EVP_CIPHER_CTX_set_padding(cctx, 0); + for (; l > 8; l -= 8, in += 8) { + if (!EVP_EncryptUpdate(cctx, outv, &tmplen, in, 8)) { + EVP_CIPHER_CTX_free(cctx); + return SC_ERROR_INTERNAL; + } + } + if (!EVP_EncryptFinal_ex(cctx, outv + tmplen, &tmplen)) { + EVP_CIPHER_CTX_free(cctx); + return SC_ERROR_INTERNAL; + } + } + + /* We need to return first 4 bytes from here */ + memcpy(tmpout, outv, 4); + if (!EVP_EncryptInit_ex2(cctx, EVP_des_ede_cbc(), key, outv, NULL)) { + EVP_CIPHER_CTX_free(cctx); + return SC_ERROR_INTERNAL; + } + /* Disable padding, otherwise it will fail to decrypt non-padded inputs */ + EVP_CIPHER_CTX_set_padding(cctx, 0); + if (!EVP_EncryptUpdate(cctx, outv, &tmplen, in, l)) { + EVP_CIPHER_CTX_free(cctx); + return SC_ERROR_INTERNAL; + } + if (!EVP_EncryptFinal_ex(cctx, outv + tmplen, &tmplen)) { + EVP_CIPHER_CTX_free(cctx); + return SC_ERROR_INTERNAL; + } + if (out != NULL) { + memcpy(out, tmpout, 4); + memcpy(out+4, outv+4, 4); + } + EVP_CIPHER_CTX_free(cctx); + return ((outv[7] << 0L) & 0x000000FF) | + ((outv[6] << 8L) & 0x0000FF00) | + ((outv[5] << 16L) & 0x00FF0000) | + ((outv[4] << 24L) & 0xFF000000); +#endif } DES_LONG DES_cbc_cksum_3des(const unsigned char *in, DES_cblock *output, - long length, DES_key_schedule *schedule, DES_key_schedule *schedule2, + long length, unsigned char *key, const_DES_cblock *ivec) { - register DES_LONG tout0,tout1,tin0,tin1; register long l=length; - DES_LONG tin[2]; unsigned char *out = &(*output)[0]; const unsigned char *iv = &(*ivec)[0]; +#if OPENSSL_VERSION_NUMBER < 0x30000000L + register DES_LONG tout0,tout1,tin0,tin1; + DES_LONG tin[2]; + DES_cblock kk, k2; + DES_key_schedule ks,ks2; - c2l(iv,tout0); - c2l(iv,tout1); + memcpy(&kk, key, 8); + memcpy(&k2, key + 8, 8); + DES_set_key_unchecked(&kk,&ks); + DES_set_key_unchecked(&k2,&ks2); + + c2l(iv, tout0); + c2l(iv, tout1); for (; l>0; l-=8) { @@ -208,7 +290,7 @@ DES_cbc_cksum_3des(const unsigned char *in, DES_cblock *output, tin0^=tout0; tin[0]=tin0; tin1^=tout1; tin[1]=tin1; - DES_encrypt3((DES_LONG *)tin,schedule,schedule2,schedule); + DES_encrypt3((DES_LONG *)tin, &ks, &ks2, &ks); /* fix 15/10/91 eay - thanks to keithr@sco.COM */ tout0=tin[0]; tout1=tin[1]; @@ -228,6 +310,40 @@ DES_cbc_cksum_3des(const unsigned char *in, DES_cblock *output, | ((tout1 << 8L) & 0x00FF0000) | ((tout1 << 24L) & 0xFF000000); return(tout1); +#else + EVP_CIPHER_CTX *cctx = NULL; + unsigned char outv[8]; + int tmplen; + + /* Prepare IV */ + memcpy(outv, iv, sizeof outv); + + cctx = EVP_CIPHER_CTX_new(); + if (!EVP_EncryptInit_ex2(cctx, EVP_des_ede_cbc(), key, iv, NULL)) { + EVP_CIPHER_CTX_free(cctx); + return SC_ERROR_INTERNAL; + } + /* Disable padding, otherwise it will fail to decrypt non-padded inputs */ + EVP_CIPHER_CTX_set_padding(cctx, 0); + for (; l > 0; l -= 8, in += 8) { + if (!EVP_EncryptUpdate(cctx, outv, &tmplen, in, 8)) { + EVP_CIPHER_CTX_free(cctx); + return SC_ERROR_INTERNAL; + } + } + if (!EVP_EncryptFinal_ex(cctx, outv + tmplen, &tmplen)) { + EVP_CIPHER_CTX_free(cctx); + return SC_ERROR_INTERNAL; + } + if (out != NULL) { + memcpy(out, outv, sizeof outv); + } + EVP_CIPHER_CTX_free(cctx); + return ((outv[7] << 0L) & 0x000000FF) | + ((outv[6] << 8L) & 0x0000FF00) | + ((outv[5] << 16L) & 0x00FF0000) | + ((outv[4] << 24L) & 0xFF000000); +#endif } @@ -235,9 +351,14 @@ int sm_encrypt_des_ecb3(unsigned char *key, unsigned char *data, int data_len, unsigned char **out, int *out_len) { +#if OPENSSL_VERSION_NUMBER < 0x30000000L int ii; DES_cblock kk,k2; DES_key_schedule ks,ks2; +#else + EVP_CIPHER_CTX *cctx = NULL; + int tmplen; +#endif if (!out || !out_len) @@ -251,6 +372,7 @@ sm_encrypt_des_ecb3(unsigned char *key, unsigned char *data, int data_len, if (!(*out)) return -1; +#if OPENSSL_VERSION_NUMBER < 0x30000000L memcpy(&kk, key, 8); memcpy(&k2, key + 8, 8); @@ -260,6 +382,27 @@ sm_encrypt_des_ecb3(unsigned char *key, unsigned char *data, int data_len, for (ii=0; ii Date: Thu, 6 May 2021 10:56:04 +0200 Subject: [PATCH 05/12] Do not use deprecated ERR_load_ERR_strings() with OpenSSL 3.0 --- src/libopensc/pkcs15-prkey.c | 2 ++ src/pkcs15init/pkcs15-oberthur-awp.c | 6 ++++++ 2 files changed, 8 insertions(+) diff --git a/src/libopensc/pkcs15-prkey.c b/src/libopensc/pkcs15-prkey.c index 772179cd..c7d2d011 100644 --- a/src/libopensc/pkcs15-prkey.c +++ b/src/libopensc/pkcs15-prkey.c @@ -527,7 +527,9 @@ sc_pkcs15_prkey_attrs_from_cert(struct sc_pkcs15_card *p15card, struct sc_pkcs15 key_info = (struct sc_pkcs15_prkey_info *) key_object->data; +#if OPENSSL_VERSION_NUMBER < 0x30000000L ERR_load_ERR_strings(); +#endif ERR_load_crypto_strings(); sc_log(ctx, "CertValue(%"SC_FORMAT_LEN_SIZE_T"u) %p", diff --git a/src/pkcs15init/pkcs15-oberthur-awp.c b/src/pkcs15init/pkcs15-oberthur-awp.c index b9991e78..70ff580d 100644 --- a/src/pkcs15init/pkcs15-oberthur-awp.c +++ b/src/pkcs15init/pkcs15-oberthur-awp.c @@ -769,7 +769,9 @@ awp_encode_key_info(struct sc_pkcs15_card *p15card, struct sc_pkcs15_object *obj int r = 0; LOG_FUNC_CALLED(ctx); +#if OPENSSL_VERSION_NUMBER < 0x30000000L ERR_load_ERR_strings(); +#endif ERR_load_crypto_strings(); key_info = (struct sc_pkcs15_prkey_info *)obj->data; @@ -827,7 +829,9 @@ awp_encode_key_info(struct sc_pkcs15_card *p15card, struct sc_pkcs15_object *obj sc_log(ctx, "cosm_encode_key_info() label:%s",ki->label.value); done: +#if OPENSSL_VERSION_NUMBER < 0x30000000L ERR_load_ERR_strings(); +#endif ERR_load_crypto_strings(); LOG_FUNC_RETURN(ctx, r); } @@ -933,7 +937,9 @@ awp_encode_cert_info(struct sc_pkcs15_card *p15card, struct sc_pkcs15_object *ob LOG_FUNC_CALLED(ctx); +#if OPENSSL_VERSION_NUMBER < 0x30000000L ERR_load_ERR_strings(); +#endif ERR_load_crypto_strings(); if (!obj || !ci) From a69ab7c70c2cf753d0a3c609eb1b0288effcf72f Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Thu, 6 May 2021 10:56:45 +0200 Subject: [PATCH 06/12] tests: Fix context for the asn1 test --- src/tests/unittests/asn1.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tests/unittests/asn1.c b/src/tests/unittests/asn1.c index 5f5d4ea3..799722cc 100644 --- a/src/tests/unittests/asn1.c +++ b/src/tests/unittests/asn1.c @@ -241,7 +241,7 @@ static int setup_sc_context(void **state) sc_context_t *ctx = NULL; int rv; - rv = sc_establish_context(&ctx, "fuzz"); + rv = sc_establish_context(&ctx, "asn1"); assert_non_null(ctx); assert_int_equal(rv, SC_SUCCESS); From a8a4bddfada6d8253046a2912f224a25f61ef7df Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Wed, 12 May 2021 16:58:11 +0200 Subject: [PATCH 07/12] p11test: Debug level from commandline This replaces the debug level defined at build time with -NDEBUG, which turned out to be quite confusing. Fixes #2304 --- src/tests/p11test/Makefile.am | 2 +- src/tests/p11test/p11test.c | 6 +++++- src/tests/p11test/p11test_case_readonly.c | 6 ------ src/tests/p11test/p11test_common.h | 13 +++++++------ 4 files changed, 13 insertions(+), 14 deletions(-) diff --git a/src/tests/p11test/Makefile.am b/src/tests/p11test/Makefile.am index f7cc67e3..abc2d5a1 100644 --- a/src/tests/p11test/Makefile.am +++ b/src/tests/p11test/Makefile.am @@ -31,7 +31,7 @@ p11test_SOURCES = p11test.c p11test_loader.c \ p11test_case_pss_oaep.c \ p11test_case_interface.c \ p11test_helpers.c -p11test_CFLAGS = -DNDEBUG $(CMOCKA_CFLAGS) +p11test_CFLAGS = $(CMOCKA_CFLAGS) p11test_LDADD = $(OPTIONAL_OPENSSL_LIBS) $(CMOCKA_LIBS) if WIN32 diff --git a/src/tests/p11test/p11test.c b/src/tests/p11test/p11test.c index 457a7b63..dbac167d 100644 --- a/src/tests/p11test/p11test.c +++ b/src/tests/p11test/p11test.c @@ -37,6 +37,7 @@ /* Global variable keeping information about token we are using */ token_info_t token; +int debug_flag = 0; void display_usage() { fprintf(stdout, @@ -98,7 +99,7 @@ int main(int argc, char** argv) { token.slot_id = (unsigned long) -1; token.log.outfile = NULL; - while ((command = getopt(argc, argv, "?hm:s:p:io:")) != -1) { + while ((command = getopt(argc, argv, "?hm:s:p:io:v")) != -1) { switch (command) { case 'o': token.log.outfile = strdup(optarg); @@ -120,6 +121,9 @@ int main(int argc, char** argv) { case '?': display_usage(); return 0; + case 'v': + debug_flag = 1; + break; default: break; } diff --git a/src/tests/p11test/p11test_case_readonly.c b/src/tests/p11test/p11test_case_readonly.c index df39ecb4..60ad0407 100644 --- a/src/tests/p11test/p11test_case_readonly.c +++ b/src/tests/p11test/p11test_case_readonly.c @@ -498,9 +498,7 @@ int verify_message(test_cert_t *o, token_info_t *info, CK_BYTE *message, CK_FUNCTION_LIST_PTR fp = info->function_pointer; CK_MECHANISM sign_mechanism = { mech->mech, NULL_PTR, 0 }; static int verify_support = 1; -#ifndef NDEBUG char *name; -#endif if (!verify_support) goto openssl_verify; @@ -531,15 +529,11 @@ int verify_message(test_cert_t *o, token_info_t *info, CK_BYTE *message, /* Final */ rv = fp->C_VerifyFinal(info->session_handle, sign, sign_length); -#ifndef NDEBUG name = "C_VerifyFinal"; -#endif } else { rv = fp->C_Verify(info->session_handle, message, message_length, sign, sign_length); -#ifndef NDEBUG name = "C_Verify"; -#endif } if (rv == CKR_OK) { mech->result_flags |= FLAGS_SIGN; diff --git a/src/tests/p11test/p11test_common.h b/src/tests/p11test/p11test_common.h index 1122e8e3..d3eb1040 100644 --- a/src/tests/p11test/p11test_common.h +++ b/src/tests/p11test/p11test_common.h @@ -33,12 +33,12 @@ #define MAX_MECHS 200 -#ifndef NDEBUG - #define debug_print(fmt, ...) \ - { fprintf(stderr, fmt "\n", ##__VA_ARGS__); } while (0) -#else - #define debug_print(fmt, ...) -#endif +#define debug_print(fmt, ...) \ + do { \ + if (debug_flag) { \ + fprintf(stderr, fmt "\n", ##__VA_ARGS__); \ + } \ + } while (0) #define FLAGS_SIGN 0x01 #define FLAGS_SIGN_OPENSSL 0x02 @@ -89,6 +89,7 @@ typedef struct { } token_info_t; extern token_info_t token; +extern int debug_flag; #endif /* P11TEST_COMMON_H */ From 8e4134841da57b1d49b796c36a21c519f5e3ac11 Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Wed, 12 May 2021 17:16:46 +0200 Subject: [PATCH 08/12] p11test: Add new mechanisms from softhsm --- src/tests/p11test/p11test_case_common.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/tests/p11test/p11test_case_common.c b/src/tests/p11test/p11test_case_common.c index 639e07e5..4da0382c 100644 --- a/src/tests/p11test/p11test_case_common.c +++ b/src/tests/p11test/p11test_case_common.c @@ -780,8 +780,12 @@ const char *get_mechanism_name(int mech_id) return "ECDH1_COFACTOR_DERIVE"; case CKM_EC_KEY_PAIR_GEN: return "EC_KEY_PAIR_GEN"; + case CKM_EC_EDWARDS_KEY_PAIR_GEN: + return "EC_EDWARDS_KEY_PAIR_GEN"; case CKM_RSA_PKCS_KEY_PAIR_GEN: return "RSA_PKCS_KEY_PAIR_GEN"; + case CKM_GENERIC_SECRET_KEY_GEN: + return "GENERIC_SECRET_KEY_GEN"; case CKM_MD5_RSA_PKCS: return "MD5_RSA_PKCS"; case CKM_RIPEMD160_RSA_PKCS: @@ -802,6 +806,8 @@ const char *get_mechanism_name(int mech_id) return "MD5_HMAC"; case CKM_SHA_1_HMAC: return "SHA_1_HMAC"; + case CKM_SHA224_HMAC: + return "SHA224_HMAC"; case CKM_SHA256_HMAC: return "SHA256_HMAC"; case CKM_SHA384_HMAC: From 33426df3ff28f6944ebedf6ac7ae5aaa2feb396a Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Fri, 21 May 2021 14:50:00 +0200 Subject: [PATCH 09/12] p11test: Do not return on warnings for (X)EDDSA keys --- src/tests/p11test/p11test_case_common.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/tests/p11test/p11test_case_common.c b/src/tests/p11test/p11test_case_common.c index 4da0382c..695ae2ea 100644 --- a/src/tests/p11test/p11test_case_common.c +++ b/src/tests/p11test/p11test_case_common.c @@ -447,7 +447,6 @@ int callback_public_keys(test_certs_t *objects, if (strcmp((char *)curve->data, "edwards25519")) { debug_print(" [WARN %s ] Unknown curve name. " " expected edwards25519, got %s", o->id_str, curve->data); - return -1; } evp_type = EVP_PKEY_ED25519; break; @@ -455,7 +454,6 @@ int callback_public_keys(test_certs_t *objects, if (strcmp((char *)curve->data, "curve25519")) { debug_print(" [WARN %s ] Unknown curve name. " " expected curve25519, got %s", o->id_str, curve->data); - return -1; } evp_type = EVP_PKEY_X25519; break; @@ -466,12 +464,13 @@ int callback_public_keys(test_certs_t *objects, ASN1_PRINTABLESTRING_free(curve); } else if (d2i_ASN1_OBJECT(&obj, &a, (long)template[6].ulValueLen) != NULL) { int nid = OBJ_obj2nid(obj); + ASN1_OBJECT_free(obj); + switch (o->key_type) { case CKK_EC_EDWARDS: if (nid != NID_ED25519) { debug_print(" [WARN %s ] Unknown OID. " " expected NID_ED25519 (%d), got %d", o->id_str, NID_ED25519, nid); - return -1; } evp_type = EVP_PKEY_ED25519; break; @@ -479,7 +478,6 @@ int callback_public_keys(test_certs_t *objects, if (nid != NID_X25519) { debug_print(" [WARN %s ] Unknown OID. " " expected NID_X25519 (%d), got %d", o->id_str, NID_X25519, nid); - return -1; } evp_type = EVP_PKEY_X25519; break; @@ -487,7 +485,6 @@ int callback_public_keys(test_certs_t *objects, debug_print(" [WARN %s ] Unknown key type %lu", o->id_str, o->key_type); return -1; } - ASN1_OBJECT_free(obj); } else { debug_print(" [WARN %s ] Failed to convert EC_PARAMS" " to curve name or object id", o->id_str); From fc2fecc80e845329fabc43044a1596c404cfe747 Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Mon, 24 May 2021 11:24:51 +0200 Subject: [PATCH 10/12] Use const types for RSA and EC_KEY These are anyway not supposed to be modified even in older versions of openssl. Visible when building with -Wno-deprecated-declarations --- src/libopensc/cwa14890.c | 18 +++++++++--------- src/libopensc/p15card-helper.c | 2 +- src/libopensc/sc-ossl-compat.h | 1 + src/pkcs11/openssl.c | 2 +- src/tests/p11test/p11test_case_common.c | 7 ++++--- 5 files changed, 16 insertions(+), 14 deletions(-) diff --git a/src/libopensc/cwa14890.c b/src/libopensc/cwa14890.c index da471abf..88f68b85 100644 --- a/src/libopensc/cwa14890.c +++ b/src/libopensc/cwa14890.c @@ -519,8 +519,8 @@ static int cwa_internal_auth(sc_card_t * card, u8 * sig, size_t sig_len, u8 * da * @return SC_SUCCESS if ok; else errorcode */ static int cwa_prepare_external_auth(sc_card_t * card, - RSA * icc_pubkey, - RSA * ifd_privkey, + const RSA * icc_pubkey, + const RSA * ifd_privkey, u8 * sig, size_t sig_len) { @@ -594,7 +594,7 @@ static int cwa_prepare_external_auth(sc_card_t * card, buf3[127] = 0xBC; /* iso padding */ /* encrypt with ifd private key */ - len2 = RSA_private_decrypt(128, buf3, buf2, ifd_privkey, RSA_NO_PADDING); + len2 = RSA_private_decrypt(128, buf3, buf2, (RSA *)ifd_privkey, RSA_NO_PADDING); if (len2 < 0) { msg = "Prepare external auth: ifd_privk encrypt failed"; res = SC_ERROR_SM_ENCRYPT_FAILED; @@ -630,7 +630,7 @@ static int cwa_prepare_external_auth(sc_card_t * card, } /* re-encrypt result with icc public key */ - len1 = RSA_public_encrypt(len3, buf3, buf1, icc_pubkey, RSA_NO_PADDING); + len1 = RSA_public_encrypt(len3, buf3, buf1, (RSA *)icc_pubkey, RSA_NO_PADDING); if (len1 <= 0 || (size_t) len1 != sig_len) { msg = "Prepare external auth: icc_pubk encrypt failed"; res = SC_ERROR_SM_ENCRYPT_FAILED; @@ -842,8 +842,8 @@ static int cwa_compare_signature(u8 * data, size_t dlen, u8 * ifd_data) * @return SC_SUCCESS if ok; else error code */ static int cwa_verify_internal_auth(sc_card_t * card, - RSA * icc_pubkey, - RSA * ifd_privkey, + const RSA * icc_pubkey, + const RSA * ifd_privkey, u8 * ifdbuf, size_t ifdlen, u8 * sig, @@ -901,7 +901,7 @@ static int cwa_verify_internal_auth(sc_card_t * card, */ /* decrypt data with our ifd priv key */ - len1 = RSA_private_decrypt(sig_len, sig, buf1, ifd_privkey, RSA_NO_PADDING); + len1 = RSA_private_decrypt(sig_len, sig, buf1, (RSA *)ifd_privkey, RSA_NO_PADDING); if (len1 <= 0) { msg = "Verify Signature: decrypt with ifd privk failed"; res = SC_ERROR_SM_ENCRYPT_FAILED; @@ -911,7 +911,7 @@ static int cwa_verify_internal_auth(sc_card_t * card, /* OK: now we have SIGMIN in buf1 */ /* check if SIGMIN data matches SIG or N.ICC-SIG */ /* evaluate DS[SK.ICC.AUTH](SIG) trying to decrypt with icc pubk */ - len3 = RSA_public_encrypt(len1, buf1, buf3, icc_pubkey, RSA_NO_PADDING); + len3 = RSA_public_encrypt(len1, buf1, buf3, (RSA *) icc_pubkey, RSA_NO_PADDING); if (len3 <= 0) goto verify_nicc_sig; /* evaluate N.ICC-SIG and retry */ res = cwa_compare_signature(buf3, len3, ifdbuf); @@ -945,7 +945,7 @@ static int cwa_verify_internal_auth(sc_card_t * card, } /* ok: check again with new data */ /* evaluate DS[SK.ICC.AUTH](I.ICC-SIG) trying to decrypt with icc pubk */ - len3 = RSA_public_encrypt(len2, buf2, buf3, icc_pubkey, RSA_NO_PADDING); + len3 = RSA_public_encrypt(len2, buf2, buf3, (RSA *)icc_pubkey, RSA_NO_PADDING); if (len3 <= 0) { msg = "Verify Signature: cannot get valid SIG data"; res = SC_ERROR_INVALID_DATA; diff --git a/src/libopensc/p15card-helper.c b/src/libopensc/p15card-helper.c index e641858d..bf0ff901 100644 --- a/src/libopensc/p15card-helper.c +++ b/src/libopensc/p15card-helper.c @@ -143,7 +143,7 @@ CERT_HANDLE_FUNCTION(default_cert_handle) { int r; X509 *cert_data = NULL; EVP_PKEY *pkey = NULL; - RSA * rsa = NULL; + const RSA * rsa = NULL; int certtype = 0; int modulus_len = 0; const prdata* key = get_prkey_by_cert(items, cert); diff --git a/src/libopensc/sc-ossl-compat.h b/src/libopensc/sc-ossl-compat.h index 339ad96c..ba4a0c51 100644 --- a/src/libopensc/sc-ossl-compat.h +++ b/src/libopensc/sc-ossl-compat.h @@ -273,6 +273,7 @@ static sc_ossl_inline void CRYPTO_secure_malloc_done() #endif /* OPENSSL_VERSION_NUMBER < 0x10100000L */ + #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/src/pkcs11/openssl.c b/src/pkcs11/openssl.c index 92fed189..4c521e08 100644 --- a/src/pkcs11/openssl.c +++ b/src/pkcs11/openssl.c @@ -522,7 +522,7 @@ CK_RV sc_pkcs11_verify_data(const unsigned char *pubkey, unsigned int pubkey_len size_t signat_len_tmp; unsigned char *signat_tmp = NULL; EVP_PKEY_CTX *ctx; - EC_KEY *eckey; + const EC_KEY *eckey; int r; sc_log(context, "Trying to verify using EVP"); diff --git a/src/tests/p11test/p11test_case_common.c b/src/tests/p11test/p11test_case_common.c index 695ae2ea..295a8e23 100644 --- a/src/tests/p11test/p11test_case_common.c +++ b/src/tests/p11test/p11test_case_common.c @@ -20,6 +20,7 @@ */ #include "p11test_case_common.h" +#include "../../libopensc/sc-ossl-compat.h" char name_buffer[11]; char flag_buffer[11]; @@ -208,8 +209,8 @@ int callback_certificates(test_certs_t *objects, if (EVP_PKEY_base_id(evp) == EVP_PKEY_RSA) { /* Extract public RSA key */ - RSA *rsa = EVP_PKEY_get0_RSA(evp); - if ((o->key.rsa = RSAPublicKey_dup(rsa)) == NULL) { + const RSA *rsa = EVP_PKEY_get0_RSA(evp); + if ((o->key.rsa = RSAPublicKey_dup((RSA *)rsa)) == NULL) { fail_msg("RSAPublicKey_dup failed"); return -1; } @@ -218,7 +219,7 @@ int callback_certificates(test_certs_t *objects, } else if (EVP_PKEY_base_id(evp) == EVP_PKEY_EC) { /* Extract public EC key */ - EC_KEY *ec = EVP_PKEY_get0_EC_KEY(evp); + const EC_KEY *ec = EVP_PKEY_get0_EC_KEY(evp); if ((o->key.ec = EC_KEY_dup(ec)) == NULL) { fail_msg("EC_KEY_dup failed"); return -1; From 9d1a2143405eeb5f55da7090f97f3b48ad328e45 Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Wed, 2 Jun 2021 14:55:11 +0200 Subject: [PATCH 11/12] pkcs11: Undefine internal typedef and remove its usage --- src/pkcs11/pkcs11-global.c | 2 +- src/pkcs11/pkcs11-spy.c | 2 +- src/pkcs11/pkcs11.h | 2 ++ 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/pkcs11/pkcs11-global.c b/src/pkcs11/pkcs11-global.c index 98b61a20..3b42070f 100644 --- a/src/pkcs11/pkcs11-global.c +++ b/src/pkcs11/pkcs11-global.c @@ -810,7 +810,7 @@ out: */ #define NUM_INTERFACES 2 #define DEFAULT_INTERFACE 0 -ck_interface interfaces[NUM_INTERFACES] = { +CK_INTERFACE interfaces[NUM_INTERFACES] = { {"PKCS 11", (void *)&pkcs11_function_list_3_0, 0}, {"PKCS 11", (void *)&pkcs11_function_list, 0} }; diff --git a/src/pkcs11/pkcs11-spy.c b/src/pkcs11/pkcs11-spy.c index c03418b3..b924bd74 100644 --- a/src/pkcs11/pkcs11-spy.c +++ b/src/pkcs11/pkcs11-spy.c @@ -176,7 +176,7 @@ allocate_function_list(int v3) /* The compatibility interfaces that can be returned from Interface functions * if the V3 API is used, but the proxied module does not support V3 API */ #define NUM_INTERFACES 1 -ck_interface compat_interfaces[NUM_INTERFACES] = { +CK_INTERFACE compat_interfaces[NUM_INTERFACES] = { {"PKCS 11", NULL, 0} }; diff --git a/src/pkcs11/pkcs11.h b/src/pkcs11/pkcs11.h index c400ac74..68cac91c 100644 --- a/src/pkcs11/pkcs11.h +++ b/src/pkcs11/pkcs11.h @@ -1786,6 +1786,8 @@ typedef struct ck_c_initialize_args *CK_C_INITIALIZE_ARGS_PTR; #undef ck_rv_t #undef ck_notify_t +#undef ck_interface + #undef ck_function_list #undef ck_function_list_3_0 From 9be6dc66067cfa5c1ed4e74d32c70af52d8bea29 Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Wed, 2 Jun 2021 14:55:49 +0200 Subject: [PATCH 12/12] pkcs11: Update the version to 3.0 (unused anywhere though) --- src/pkcs11/pkcs11.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/pkcs11/pkcs11.h b/src/pkcs11/pkcs11.h index 68cac91c..85aa98e0 100644 --- a/src/pkcs11/pkcs11.h +++ b/src/pkcs11/pkcs11.h @@ -63,9 +63,9 @@ extern "C" { version of this file, please consider deleting the revision macro (you may use a macro with a different name to keep track of your versions). */ -#define CRYPTOKI_VERSION_MAJOR 2 -#define CRYPTOKI_VERSION_MINOR 20 -#define CRYPTOKI_VERSION_REVISION 6 +#define CRYPTOKI_VERSION_MAJOR 3 +#define CRYPTOKI_VERSION_MINOR 0 +#define CRYPTOKI_VERSION_REVISION 0 /* Compatibility interface is default, unless CRYPTOKI_GNU is