Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
SUSE:SLE-15-SP6:GA
openssl_tpm_engine
0003-OpenSSL-1.1-compatibility.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File 0003-OpenSSL-1.1-compatibility.patch of Package openssl_tpm_engine
From ade88cc6abb7b389f8d73efd7700f284953e8d81 Mon Sep 17 00:00:00 2001 From: Matthias Gerstner <mgerstner@suse.de> Date: Thu, 30 Nov 2017 18:29:44 +0100 Subject: [PATCH] OpenSSL 1.1 compatibility support compiling against both OpenSSL 1.0 and OpenSSL 1.1 by means of suitable wrapper functions. --- create_tpm_key.c | 11 ++- e_tpm.c | 113 ++++++++++++--------- e_tpm_err.c | 1 - ssl_compat.h | 243 ++++++++++++++++++++++++++++++++++++++++++++++ test/Makefile.am | 1 + test/engine_key_loading.c | 22 +++-- 6 files changed, 336 insertions(+), 55 deletions(-) create mode 100644 ssl_compat.h diff --git a/create_tpm_key.c b/create_tpm_key.c index fee917f..a73d549 100644 --- a/create_tpm_key.c +++ b/create_tpm_key.c @@ -46,6 +46,8 @@ #include <trousers/tss.h> #include <trousers/trousers.h> +#include "ssl_compat.h" + #define print_error(a,b) \ fprintf(stderr, "%s:%d %s result: 0x%x (%s)\n", __FILE__, __LINE__, \ a, b, Trspi_Error_String(b)) @@ -115,14 +117,19 @@ int openssl_get_modulus_and_prime(RSA *rsa, unsigned int *size_n, unsigned char *n, unsigned int *size_p, unsigned char *p) { + const BIGNUM *bn_n = NULL, *bn_p = NULL; + + RSA_get0_key(rsa, &bn_n, NULL, NULL); + RSA_get0_factors(rsa, &bn_p, NULL); + /* get the modulus from the RSA object */ - if ((*size_n = BN_bn2bin(rsa->n, n)) <= 0) { + if ((*size_n = BN_bn2bin(bn_n, n)) <= 0) { openssl_print_errors(); return -1; } /* get one of the primes from the RSA object */ - if ((*size_p = BN_bn2bin(rsa->p, p)) <= 0) { + if ((*size_p = BN_bn2bin(bn_p, p)) <= 0) { openssl_print_errors(); return -1; } diff --git a/e_tpm.c b/e_tpm.c index 0ebf636..f671771 100644 --- a/e_tpm.c +++ b/e_tpm.c @@ -19,7 +19,6 @@ #include <string.h> #include <openssl/crypto.h> -#include <openssl/dso.h> #include <openssl/engine.h> #include <openssl/evp.h> #include <openssl/objects.h> @@ -37,6 +36,7 @@ #include <trousers/trousers.h> // XXX DEBUG #include "e_tpm.h" +#include "ssl_compat.h" //#define DLOPEN_TSPI @@ -66,7 +66,7 @@ static int tpm_rsa_keygen(RSA *, int, BIGNUM *, BN_GENCB *); /* random functions */ static int tpm_rand_bytes(unsigned char *, int); static int tpm_rand_status(void); -static void tpm_rand_seed(const void *, int); +static RAND_SEED_RET_TYPE tpm_rand_seed(const void *, int); /* The definitions for control commands specific to this engine */ #define TPM_CMD_SO_PATH ENGINE_CMD_BASE @@ -88,24 +88,8 @@ static const ENGINE_CMD_DEFN tpm_cmd_defns[] = { {0, NULL, NULL, 0} }; -#ifndef OPENSSL_NO_RSA -static RSA_METHOD tpm_rsa = { - "TPM RSA method", - tpm_rsa_pub_enc, - tpm_rsa_pub_dec, - tpm_rsa_priv_enc, - tpm_rsa_priv_dec, - NULL, /* set in tpm_engine_init */ - BN_mod_exp_mont, - tpm_rsa_init, - tpm_rsa_finish, - (RSA_FLAG_SIGN_VER | RSA_FLAG_NO_BLINDING), - NULL, - NULL, /* sign */ - NULL, /* verify */ - tpm_rsa_keygen -}; -#endif +static RSA_METHOD *tpm_rsa; +static const RSA_METHOD *ssl_rsa; static RAND_METHOD tpm_rand = { /* "TPM RAND method", */ @@ -195,14 +179,44 @@ static unsigned int (*p_tspi_Policy_AssignToObject)(); #define Tspi_Policy_AssignToObject p_tspi_Policy_AssignToObject #endif /* DLOPEN_TSPI */ +static int setup_rsa_method() +{ + tpm_rsa = RSA_meth_new("TPM RSA method", 0); + if (tpm_rsa == NULL) + return 0; + + if (!RSA_meth_set_flags(tpm_rsa, + RSA_FLAG_SIGN_VER | RSA_FLAG_NO_BLINDING) || + !RSA_meth_set_pub_enc(tpm_rsa, tpm_rsa_pub_enc) || + !RSA_meth_set_pub_dec(tpm_rsa, tpm_rsa_pub_dec) || + !RSA_meth_set_priv_enc(tpm_rsa, tpm_rsa_priv_enc) || + !RSA_meth_set_priv_dec(tpm_rsa, tpm_rsa_priv_dec) || + !RSA_meth_set_bn_mod_exp(tpm_rsa, BN_mod_exp_mont) || + !RSA_meth_set_init(tpm_rsa, tpm_rsa_init) || + !RSA_meth_set_finish(tpm_rsa, tpm_rsa_finish) || + !RSA_meth_set_keygen(tpm_rsa, tpm_rsa_keygen)) + { + RSA_meth_free(tpm_rsa); + tpm_rsa = NULL; + return 0; + } + + return 1; +} + /* This internal function is used by ENGINE_tpm() and possibly by the * "dynamic" ENGINE support too */ static int bind_helper(ENGINE * e) { + if (!setup_rsa_method()) + return 0; + + ssl_rsa = RSA_PKCS1_OpenSSL(); + if (!ENGINE_set_id(e, engine_tpm_id) || !ENGINE_set_name(e, engine_tpm_name) || #ifndef OPENSSL_NO_RSA - !ENGINE_set_RSA(e, &tpm_rsa) || + !ENGINE_set_RSA(e, tpm_rsa) || #endif !ENGINE_set_RAND(e, &tpm_rand) || !ENGINE_set_destroy_function(e, tpm_engine_destroy) || @@ -399,7 +413,7 @@ static int tpm_engine_init(ENGINE * e) goto err; } - tpm_rsa.rsa_mod_exp = RSA_PKCS1_SSLeay()->rsa_mod_exp; + RSA_meth_set_mod_exp(tpm_rsa, RSA_meth_get_mod_exp(ssl_rsa)); return 1; err: @@ -491,6 +505,8 @@ static int tpm_engine_finish(ENGINE * e) } tpm_dso = NULL; #endif + RSA_meth_free(tpm_rsa); + tpm_rsa = NULL; return 1; } @@ -500,6 +516,7 @@ int fill_out_rsa_object(RSA *rsa, TSS_HKEY hKey) UINT32 pubkey_len, encScheme, sigScheme; BYTE *pubkey; struct rsa_app_data *app_data; + BIGNUM *e = NULL, *n = NULL; DBG("%s", __FUNCTION__); @@ -525,7 +542,7 @@ int fill_out_rsa_object(RSA *rsa, TSS_HKEY hKey) return 0; } - if ((rsa->n = BN_bin2bn(pubkey, pubkey_len, rsa->n)) == NULL) { + if ((n = BN_bin2bn(pubkey, pubkey_len, n)) == NULL) { Tspi_Context_FreeMemory(hContext, pubkey); TSSerr(TPM_F_TPM_FILL_RSA_OBJECT, TPM_R_BN_CONVERSION_FAILED); return 0; @@ -534,23 +551,24 @@ int fill_out_rsa_object(RSA *rsa, TSS_HKEY hKey) Tspi_Context_FreeMemory(hContext, pubkey); /* set e in the RSA object */ - if (!rsa->e && ((rsa->e = BN_new()) == NULL)) { + if (((e = BN_new()) == NULL)) { TSSerr(TPM_F_TPM_FILL_RSA_OBJECT, ERR_R_MALLOC_FAILURE); - return 0; + goto err; } - if (!BN_set_word(rsa->e, 65537)) { + if (!BN_set_word(e, 65537)) { TSSerr(TPM_F_TPM_FILL_RSA_OBJECT, TPM_R_REQUEST_FAILED); - BN_free(rsa->e); - rsa->e = NULL; - return 0; + goto err; } if ((app_data = OPENSSL_malloc(sizeof(struct rsa_app_data))) == NULL) { TSSerr(TPM_F_TPM_FILL_RSA_OBJECT, ERR_R_MALLOC_FAILURE); - BN_free(rsa->e); - rsa->e = NULL; - return 0; + goto err; + } + + if (RSA_set0_key(rsa, n, e, NULL) == 0) { + TSSerr(TPM_F_TPM_FILL_RSA_OBJECT, TPM_R_REQUEST_FAILED); + goto err; } DBG("Setting hKey(0x%x) in RSA object", hKey); @@ -564,6 +582,12 @@ int fill_out_rsa_object(RSA *rsa, TSS_HKEY hKey) RSA_set_ex_data(rsa, ex_app_data, app_data); return 1; +err: + if (e) + BN_free(e); + if (n) + BN_free(n); + return 0; } static EVP_PKEY *tpm_engine_load_key(ENGINE *e, const char *key_id, @@ -681,7 +705,6 @@ static EVP_PKEY *tpm_engine_load_key(ENGINE *e, const char *key_id, TSSerr(TPM_F_TPM_ENGINE_LOAD_KEY, ERR_R_MALLOC_FAILURE); return NULL; } - pkey->type = EVP_PKEY_RSA; if ((rsa = RSA_new()) == NULL) { EVP_PKEY_free(pkey); @@ -689,10 +712,8 @@ static EVP_PKEY *tpm_engine_load_key(ENGINE *e, const char *key_id, TSSerr(TPM_F_TPM_ENGINE_LOAD_KEY, ERR_R_MALLOC_FAILURE); return NULL; } - rsa->meth = &tpm_rsa; - /* call our local init function here */ - rsa->meth->init(rsa); - pkey->pkey.rsa = rsa; + + RSA_set_method(rsa, tpm_rsa); if (!fill_out_rsa_object(rsa, hKey)) { EVP_PKEY_free(pkey); @@ -841,8 +862,8 @@ static int tpm_rsa_pub_dec(int flen, DBG("%s", __FUNCTION__); - if ((rv = RSA_PKCS1_SSLeay()->rsa_pub_dec(flen, from, to, rsa, - padding)) < 0) { + if ((rv = RSA_meth_get_pub_dec(ssl_rsa)( + flen, from, to, rsa, padding)) < 0) { TSSerr(TPM_F_TPM_RSA_PUB_DEC, TPM_R_REQUEST_FAILED); return 0; } @@ -867,7 +888,7 @@ static int tpm_rsa_priv_dec(int flen, if (!app_data) { DBG("No app data found for RSA object %p. Calling software.", rsa); - if ((rv = RSA_PKCS1_SSLeay()->rsa_priv_dec(flen, from, to, rsa, + if ((rv = RSA_meth_get_priv_dec(ssl_rsa)(flen, from, to, rsa, padding)) < 0) { TSSerr(TPM_F_TPM_RSA_PRIV_DEC, TPM_R_REQUEST_FAILED); } @@ -944,7 +965,7 @@ static int tpm_rsa_pub_enc(int flen, if (!app_data) { DBG("No app data found for RSA object %p. Calling software.", rsa); - if ((rv = RSA_PKCS1_SSLeay()->rsa_pub_enc(flen, from, to, rsa, + if ((rv = RSA_meth_get_pub_enc(ssl_rsa)(flen, from, to, rsa, padding)) < 0) { TSSerr(TPM_F_TPM_RSA_PUB_ENC, TPM_R_REQUEST_FAILED); } @@ -1051,8 +1072,8 @@ static int tpm_rsa_priv_enc(int flen, if (!app_data) { DBG("No app data found for RSA object %p. Calling software.", rsa); - if ((rv = RSA_PKCS1_SSLeay()->rsa_priv_enc(flen, from, to, rsa, - padding)) < 0) { + if ((rv = RSA_meth_get_priv_enc(ssl_rsa)(flen, from, to, rsa, + padding)) < 0) { TSSerr(TPM_F_TPM_RSA_PRIV_ENC, TPM_R_REQUEST_FAILED); } @@ -1254,7 +1275,7 @@ static int tpm_rand_status(void) return 1; } -static void tpm_rand_seed(const void *buf, int num) +static RAND_SEED_RET_TYPE tpm_rand_seed(const void *buf, int num) { TSS_RESULT result; UINT32 total_stirred = 0; @@ -1267,7 +1288,7 @@ static void tpm_rand_seed(const void *buf, int num) if ((result = Tspi_TPM_StirRandom(hTPM, 255, ((BYTE*)buf) + total_stirred))) { TSSerr(TPM_F_TPM_RAND_SEED, TPM_R_REQUEST_FAILED); - return; + return RAND_SEED_BAD_RETURN; } total_stirred += 255; @@ -1278,7 +1299,7 @@ static void tpm_rand_seed(const void *buf, int num) TSSerr(TPM_F_TPM_RAND_SEED, TPM_R_REQUEST_FAILED); } - return; + return RAND_SEED_GOOD_RETURN; } /* This stuff is needed if this ENGINE is being compiled into a self-contained diff --git a/e_tpm_err.c b/e_tpm_err.c index 25a5d0f..c913dff 100644 --- a/e_tpm_err.c +++ b/e_tpm_err.c @@ -18,7 +18,6 @@ #include <stdio.h> #include <openssl/err.h> -#include <openssl/dso.h> #include <openssl/engine.h> #include <tss/platform.h> diff --git a/ssl_compat.h b/ssl_compat.h new file mode 100644 index 0000000..b332a85 --- /dev/null +++ b/ssl_compat.h @@ -0,0 +1,243 @@ +#ifndef _SSL_COMPAT_H +#define _SSL_COMPAT_H + +// C std. headers +#include <stdlib.h> + +// OpenSSL +#include <openssl/rsa.h> +#include <openssl/opensslv.h> + +/* + * Matthias Gerstner + * Copyright (C) SUSE Linux GmbH 2017 + * mgerstner@suse.de + * + * This header provides a compatibility layer for being able to compile + * against OpenSSL 1.0 as well as OpenSSL 1.1 versions. In OpenSSL 1.1 various + * data structures have been made opaque and can no longer be accessed + * directly. + * + * This header provides wrapper functions that do the right thing + */ + +#if OPENSSL_VERSION_NUMBER >= 0x1010000fL +# define USE_OPENSSL_OPAQUE_API +# define HAVE_OPENSSL_110 +// this flag was removed in 1.1.0, no longer needed, see commit OpenSSL +// 19c6d3ea2d3b4e0ad3e978e42cc7cbdf0c09891f +# define RSA_FLAG_SIGN_VER 0 +#endif + +/* + * the RAND_METHOD seed function has got an error return type in OpenSSL + * 1.1.0. + * + * these defines help dealing with it. + */ +#ifdef HAVE_OPENSSL_110 +# define RAND_SEED_RET_TYPE int +# define RAND_SEED_GOOD_RETURN 1 +# define RAND_SEED_BAD_RETURN 0 +#else +# define RAND_SEED_RET_TYPE void +# define RAND_SEED_GOOD_RETURN +# define RAND_SEED_BAD_RETURN +#endif + +/* + * callback function pointer typedefs + */ + +typedef int (*func_rsa_pub_enc)(int, const unsigned char *, unsigned char *, + RSA *, int); +typedef int (*func_rsa_pub_dec)(int, const unsigned char *, unsigned char *, + RSA *, int); +typedef int (*func_rsa_priv_enc)(int, const unsigned char *, unsigned char *, + RSA *, int); +typedef int (*func_rsa_priv_dec)(int, const unsigned char *, unsigned char *, + RSA *, int); +typedef int (*func_rsa_mod_exp)(BIGNUM *r0, const BIGNUM *I, RSA *rsa, + BN_CTX *ctx); +typedef int (*func_rsa_bn_mod_exp)(BIGNUM *, const BIGNUM *, const BIGNUM *, + const BIGNUM *, BN_CTX *, BN_MONT_CTX *); +typedef int (*func_rsa_init)(RSA *rsa); +typedef int (*func_rsa_finish)(RSA *rsa); +typedef int (*func_rsa_keygen)(RSA *, int, BIGNUM *, BN_GENCB *); + +/* + * wrapper functions which provide the OpenSSL 1.1 accessor functions to + * OpenSSL 1.0. + */ + +#ifndef USE_OPENSSL_OPAQUE_API +RSA_METHOD* RSA_meth_new(const char *name, int flags) +{ + RSA_METHOD *ret = malloc(sizeof(RSA_METHOD)); + if (ret) { + ret->name = name; + ret->flags = flags; + } + + return ret; +} + +void RSA_meth_free(RSA_METHOD *meth) +{ + free(meth); +} + +int RSA_meth_set_flags(RSA_METHOD *method, int flags) +{ + method->flags = flags; + return 1; +} + +int RSA_meth_set_pub_enc(RSA_METHOD *method, func_rsa_pub_enc pub_enc) +{ + method->rsa_pub_enc = pub_enc; + return 1; +} + +func_rsa_pub_enc RSA_meth_get_pub_enc(const RSA_METHOD *method) +{ + return method->rsa_pub_enc; +} + +int RSA_meth_set_pub_dec(RSA_METHOD *method, func_rsa_pub_dec pub_dec) +{ + method->rsa_pub_dec = pub_dec; + return 1; +} + +func_rsa_pub_dec RSA_meth_get_pub_dec(const RSA_METHOD *method) +{ + return method->rsa_pub_dec; +} + +int RSA_meth_set_priv_enc(RSA_METHOD *method, func_rsa_priv_enc priv_enc) +{ + method->rsa_priv_enc = priv_enc; + return 1; +} + +func_rsa_priv_enc RSA_meth_get_priv_enc(const RSA_METHOD *method) +{ + return method->rsa_priv_enc; +} + +int RSA_meth_set_priv_dec(RSA_METHOD *method, func_rsa_priv_dec priv_dec) +{ + method->rsa_priv_dec = priv_dec; + return 1; +} + +func_rsa_priv_dec RSA_meth_get_priv_dec(const RSA_METHOD *method) +{ + return method->rsa_priv_dec; +} + +int RSA_meth_set_mod_exp(RSA_METHOD *method, func_rsa_mod_exp mod_exp) +{ + method->rsa_mod_exp = mod_exp; + return 1; +} + +func_rsa_mod_exp RSA_meth_get_mod_exp(const RSA_METHOD *method) +{ + return method->rsa_mod_exp; +} + +int RSA_meth_set_bn_mod_exp(RSA_METHOD *method, + func_rsa_bn_mod_exp bn_mod_exp) +{ + method->bn_mod_exp = bn_mod_exp; + return 1; +} + +int RSA_meth_set_init(RSA_METHOD *method, func_rsa_init init) +{ + method->init = init; + return 1; +} + +int RSA_meth_set_finish(RSA_METHOD *method, func_rsa_finish finish) +{ + method->finish = finish; + return 1; +} + +int RSA_meth_set_keygen(RSA_METHOD *method, func_rsa_keygen keygen) +{ + method->rsa_keygen = keygen; + return 1; +} + +int RSA_set0_key(RSA *key, BIGNUM *n, BIGNUM *e, BIGNUM *d) +{ + if (key->n == NULL && n == NULL) + return 0; + if (key->e == NULL && e == NULL) + return 0; + + if (n != NULL) { + BN_free(key->n); + key->n = n; + } + if (e != NULL) { + BN_free(key->e); + key->e = e; + } + if (d != NULL) { + BN_free(key->d); + key->d = d; + } + + return 1; +} + +void RSA_get0_key(RSA *key, const BIGNUM **n, const BIGNUM **e, const BIGNUM **d) +{ + if (n) + *n = key->n; + if (e) + *e = key->e; + if (d) + *d = key->d; +} + +void RSA_get0_factors(RSA *key, const BIGNUM **p, const BIGNUM **q) +{ + if (p) + *p = key->p; + if (q) + *q = key->q; +} + +int RSA_set_method(RSA *key, const RSA_METHOD *method) +{ + key->meth = method; + /* call our local init function here, the original RSA_set_method() + * does this internally */ + key->meth->init(key); + return 1; +} + +RSA* EVP_PKEY_get0_RSA(EVP_PKEY *key) +{ + return key->pkey.rsa; +} + +#endif // ! USE_OPENSSL_OPAQUE_API + +#ifndef HAVE_OPENSSL_110 + +const RSA_METHOD* RSA_PKCS1_OpenSSL() +{ + // was renamed in 1.1.0 + return RSA_PKCS1_SSLeay(); +} + +#endif // ! HAVE_OPENSSL_110 + +#endif // include guard diff --git a/test/Makefile.am b/test/Makefile.am index 2e0de61..a0e2a1d 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -1,4 +1,5 @@ noinst_PROGRAMS=engine_key_loading +engine_key_loading_CFLAGS=-I../ engine_key_loading_SOURCES=engine_key_loading.c engine_key_loading_LDADD=-ltspi -lcrypto diff --git a/test/engine_key_loading.c b/test/engine_key_loading.c index 4bc2ef8..c425f36 100644 --- a/test/engine_key_loading.c +++ b/test/engine_key_loading.c @@ -32,6 +32,7 @@ #include <tss/tss_error.h> #include <tss/tspi.h> +#include "ssl_compat.h" #define ERR(x, ...) fprintf(stderr, "%s:%d " x "\n", __FILE__, __LINE__, ##__VA_ARGS__) @@ -71,8 +72,8 @@ int test_num[] = { 1, 1, 2, 2 }; int run_test(EVP_PKEY *key) { - RSA *rsa; - char signature[256], data_to_sign[DATA_SIZE], data_recovered[DATA_SIZE]; + RSA *rsa = NULL; + unsigned char signature[256], data_to_sign[DATA_SIZE], data_recovered[DATA_SIZE]; int sig_size; if (RAND_bytes(data_to_sign, sizeof(data_to_sign)) != 1) { @@ -80,10 +81,19 @@ run_test(EVP_PKEY *key) return 1; } - if (key) - rsa = key->pkey.rsa; - else - rsa = RSA_generate_key(KEY_SIZE_BITS, 65537, NULL, NULL); + if (key) { + rsa = EVP_PKEY_get0_RSA(key); + } + else { + BIGNUM *e = BN_new(); + rsa = RSA_new(); + if( !e || !rsa || !BN_set_word(e, 65537) ) + return 1; + if( RSA_generate_key_ex(rsa, KEY_SIZE_BITS, e, NULL) != 1 ) + { + return 1; + } + } if (!rsa) return 1; -- 2.13.6
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor