From 2eb853d7299b0b0fa4162ab4a03c1de890b97e53 Mon Sep 17 00:00:00 2001 From: Lukasz Pawelczyk Date: Mon, 5 Sep 2016 18:50:36 +0200 Subject: [PATCH] Adapt YACA to work with OpenSSL 1.1 preserving 1.0 compatibility Change-Id: I27e199659666d2d87b17fcb9882b0e70f751c628 --- src/crypto.c | 46 +++++++++++++++++++++++++++++++++++++++------- src/debug.c | 8 +++++++- src/encrypt.c | 14 +++++++------- src/internal.h | 29 +++++++++++++++++++++++++++++ src/key.c | 8 ++++---- src/rsa.c | 2 +- src/sign.c | 26 ++++++++++++++++---------- 7 files changed, 103 insertions(+), 30 deletions(-) diff --git a/src/crypto.c b/src/crypto.c index aeb6220..a13a594 100644 --- a/src/crypto.c +++ b/src/crypto.c @@ -44,7 +44,9 @@ #include "internal.h" +#if OPENSSL_VERSION_NUMBER < 0x10100000L static pthread_mutex_t *mutexes = NULL; +#endif /* OPENSSL_VERSION_NUMBER < 0x10100000L */ static __thread bool current_thread_initialized = false; static size_t threads_cnt = 0; @@ -85,16 +87,21 @@ static int getrandom_wrapper(unsigned char *buf, int num) return 1; } -static void RAND_METHOD_seed(UNUSED const void *buf, UNUSED int num) +#if OPENSSL_VERSION_NUMBER >= 0x10100000L + +static int RAND_METHOD_seed(UNUSED const void *buf, UNUSED int num) { + return 1; } -static int RAND_METHOD_bytes(unsigned char *buf, int num) +static int RAND_METHOD_add(UNUSED const void *buf, UNUSED int num, UNUSED double entropy) { - return getrandom_wrapper(buf, num); + return 1; } -static void RAND_METHOD_cleanup(void) +#else /* OPENSSL_VERSION_NUMBER >= 0x10100000L */ + +static void RAND_METHOD_seed(UNUSED const void *buf, UNUSED int num) { } @@ -102,6 +109,17 @@ static void RAND_METHOD_add(UNUSED const void *buf, UNUSED int num, UNUSED doubl { } +#endif /* OPENSSL_VERSION_NUMBER >= 0x10100000L */ + +static int RAND_METHOD_bytes(unsigned char *buf, int num) +{ + return getrandom_wrapper(buf, num); +} + +static void RAND_METHOD_cleanup(void) +{ +} + static int RAND_METHOD_pseudorand(UNUSED unsigned char *buf, UNUSED int num) { return getrandom_wrapper(buf, num); @@ -128,6 +146,8 @@ static const RAND_METHOD new_rand_method = { RAND_METHOD_status, }; +#if OPENSSL_VERSION_NUMBER < 0x10100000L + static void locking_callback(int mode, int type, UNUSED const char *file, UNUSED int line) { /* Ignore NULL mutexes and lock/unlock error codes as we can't do anything @@ -159,6 +179,8 @@ static void destroy_mutexes(int count) } } +#endif /* OPENSSL_VERSION_NUMBER < 0x10100000L */ + API int yaca_initialize(void) { int ret = YACA_ERROR_NONE; @@ -170,7 +192,6 @@ API int yaca_initialize(void) pthread_mutex_lock(&init_mutex); { if (threads_cnt == 0) { - assert(mutexes == NULL); #ifndef SYS_getrandom if (urandom_fd == -2) { @@ -209,7 +230,10 @@ API int yaca_initialize(void) OpenSSL_add_all_digests(); OpenSSL_add_all_ciphers(); +#if OPENSSL_VERSION_NUMBER < 0x10100000L /* enable threads support */ + assert(mutexes == NULL); + if (CRYPTO_num_locks() > 0) { ret = yaca_malloc(CRYPTO_num_locks() * sizeof(pthread_mutex_t), (void**)&mutexes); @@ -240,6 +264,7 @@ API int yaca_initialize(void) CRYPTO_set_id_callback(thread_id_callback); CRYPTO_set_locking_callback(locking_callback); } +#endif /* OPENSSL_VERSION_NUMBER < 0x10100000L */ /* * TODO: @@ -251,7 +276,11 @@ API int yaca_initialize(void) threads_cnt++; current_thread_initialized = true; } + +#if OPENSSL_VERSION_NUMBER < 0x10100000L || !defined SYS_getrandom exit: +#endif /* OPENSSL_VERSION_NUMBER < 0x10100000L || !defined SYS_getrandom */ + pthread_mutex_unlock(&init_mutex); return ret; @@ -264,7 +293,9 @@ API void yaca_cleanup(void) return; /* per thread cleanup */ +#if OPENSSL_VERSION_NUMBER < 0x10100000L ERR_remove_thread_state(NULL); +#endif /* OPENSSL_VERSION_NUMBER < 0x10100000L */ CRYPTO_cleanup_all_ex_data(); pthread_mutex_lock(&init_mutex); @@ -272,21 +303,22 @@ API void yaca_cleanup(void) /* last one turns off the light */ if (threads_cnt == 1) { ERR_free_strings(); - ERR_remove_thread_state(NULL); EVP_cleanup(); RAND_cleanup(); - CRYPTO_cleanup_all_ex_data(); RAND_set_rand_method(saved_rand_method); + #ifndef SYS_getrandom close(urandom_fd); urandom_fd = -2; #endif /* SYS_getrandom */ +#if OPENSSL_VERSION_NUMBER < 0x10100000L /* threads support cleanup */ CRYPTO_set_id_callback(NULL); CRYPTO_set_locking_callback(NULL); destroy_mutexes(CRYPTO_num_locks()); +#endif /* OPENSSL_VERSION_NUMBER < 0x10100000L */ } assert(threads_cnt > 0); diff --git a/src/debug.c b/src/debug.c index a229ab8..b6a113d 100644 --- a/src/debug.c +++ b/src/debug.c @@ -123,9 +123,15 @@ int error_handle(const char *file, int line, const char *function) /* known errors */ switch (err) { +#if OPENSSL_VERSION_NUMBER > 0x10100000L + case ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_OSSL_PRIVATE_DECRYPT, RSA_R_DATA_GREATER_THAN_MOD_LEN): + case ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_OSSL_PUBLIC_DECRYPT, RSA_R_DATA_GREATER_THAN_MOD_LEN): +#else /* OPENSSL_VERSION_NUMBER > 0x10100000L */ case ERR_PACK(ERR_LIB_RSA, RSA_F_PKEY_RSA_CTRL, RSA_R_INVALID_KEYBITS): case ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_EAY_PRIVATE_DECRYPT, RSA_R_DATA_GREATER_THAN_MOD_LEN): case ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_EAY_PUBLIC_DECRYPT, RSA_R_DATA_GREATER_THAN_MOD_LEN): +#endif /* OPENSSL_VERSION_NUMBER > 0x10100000L */ + case ERR_PACK(ERR_LIB_RSA, RSA_F_PKEY_RSA_CTRL, RSA_R_KEY_SIZE_TOO_SMALL): case ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_CTX_CTRL, EVP_R_COMMAND_NOT_SUPPORTED): case ERR_PACK(ERR_LIB_PEM, PEM_F_PEM_READ_BIO, PEM_R_NO_START_LINE): case ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_D2I_READ_BIO, ASN1_R_NOT_ENOUGH_DATA): @@ -191,7 +197,7 @@ int error_handle(const char *file, int line, const char *function) /* fatal errors */ int reason = ERR_GET_REASON(err); - if (ret == YACA_ERROR_NONE && reason <= GENERIC_REASON_MAX && ERR_FATAL_ERROR(err) > 0) { + if (ret == YACA_ERROR_NONE && reason <= GENERIC_REASON_MAX && (err & ERR_R_FATAL) > 0) { switch (reason) { case ERR_R_MALLOC_FAILURE: ret = YACA_ERROR_OUT_OF_MEMORY; diff --git a/src/encrypt.c b/src/encrypt.c index 56b316f..6ce25cc 100644 --- a/src/encrypt.c +++ b/src/encrypt.c @@ -277,7 +277,7 @@ int get_wrap_output_length(const yaca_context_h ctx, size_t input_len, size_t *o assert(c->cipher_ctx != NULL); bool encryption = is_encryption_op(c->op_type); - int type = EVP_CIPHER_type(c->cipher_ctx->cipher); + int type = EVP_CIPHER_CTX_type(c->cipher_ctx); if (input_len > 0) { if (type == NID_id_aes128_wrap || type == NID_id_aes192_wrap || type == NID_id_aes256_wrap) { @@ -644,7 +644,7 @@ int set_encrypt_property(yaca_context_h ctx, assert(c->cipher_ctx != NULL); mode = EVP_CIPHER_CTX_mode(c->cipher_ctx); - nid = EVP_CIPHER_nid(c->cipher_ctx->cipher); + nid = EVP_CIPHER_CTX_nid(c->cipher_ctx); switch (property) { case YACA_PROPERTY_GCM_AAD: @@ -942,7 +942,7 @@ int encrypt_initialize(yaca_context_h *ctx, goto exit; mode = EVP_CIPHER_CTX_mode(nc->cipher_ctx); - nid = EVP_CIPHER_nid(nc->cipher_ctx->cipher); + nid = EVP_CIPHER_CTX_nid(nc->cipher_ctx); if (mode == EVP_CIPH_CCM_MODE || nid == NID_rc2_cbc || nid == NID_rc2_ecb || nid == NID_rc2_cfb64 || nid == NID_rc2_ofb64) { ret = encrypt_ctx_backup(nc, cipher, sym_key, iv); @@ -977,7 +977,7 @@ int encrypt_update(yaca_context_h ctx, return YACA_ERROR_INVALID_PARAMETER; mode = EVP_CIPHER_CTX_mode(c->cipher_ctx); - type = EVP_CIPHER_type(c->cipher_ctx->cipher); + type = EVP_CIPHER_CTX_type(c->cipher_ctx); enum encrypt_context_state_e target_state; if (output == NULL && input == NULL) @@ -1024,7 +1024,7 @@ int encrypt_update(yaca_context_h ctx, } /* Fix for OpenSSL error in 3DES CFB1 */ - if ((c->cipher_ctx->flags & EVP_CIPH_FLAG_LENGTH_BITS) != 0) { + if ((EVP_CIPHER_CTX_flags(c->cipher_ctx) & EVP_CIPH_FLAG_LENGTH_BITS) != 0) { if (input_len > INT_MAX / 8) return YACA_ERROR_INVALID_PARAMETER; input_len *= 8; @@ -1042,7 +1042,7 @@ int encrypt_update(yaca_context_h ctx, c->state = target_state; /* Fix for OpenSSL error in 3DES CFB1 */ - if ((c->cipher_ctx->flags & EVP_CIPH_FLAG_LENGTH_BITS) != 0) + if ((EVP_CIPHER_CTX_flags(c->cipher_ctx) & EVP_CIPH_FLAG_LENGTH_BITS) != 0) *output_len /= 8; return YACA_ERROR_NONE; @@ -1071,7 +1071,7 @@ int encrypt_finalize(yaca_context_h ctx, *output_len = loutput_len; /* Fix for OpenSSL error in 3DES CFB1 */ - if ((c->cipher_ctx->flags & EVP_CIPH_FLAG_LENGTH_BITS) != 0) + if ((EVP_CIPHER_CTX_flags(c->cipher_ctx) & EVP_CIPH_FLAG_LENGTH_BITS) != 0) *output_len /= 8; c->state = STATE_FINALIZED; diff --git a/src/internal.h b/src/internal.h index 97e86c3..20da604 100644 --- a/src/internal.h +++ b/src/internal.h @@ -29,12 +29,41 @@ #include #include +#include +#include +#include #include #define API __attribute__ ((visibility("default"))) #define UNUSED __attribute__((unused)) +/* Functions that handle the hidden nature of internal + * OpenSSL structures that don't exist in OpenSSL < 1.1.0 + */ +#if OPENSSL_VERSION_NUMBER < 0x10100000L + +static inline EVP_PKEY_CTX *EVP_MD_CTX_pkey_ctx(const EVP_MD_CTX *ctx) +{ + return ctx->pctx; +} + +static inline int EVP_PKEY_up_ref(EVP_PKEY *pkey) +{ + if (CRYPTO_add(&pkey->references, 1, CRYPTO_LOCK_EVP_PKEY) <= 0) + return 0; + return 1; +} + +static inline RSA *EVP_PKEY_get0_RSA(EVP_PKEY *pkey) +{ + if (pkey->type != EVP_PKEY_RSA) + return NULL; + return pkey->pkey.rsa; +} + +#endif /* OPENSSL_VERSION_NUMBER < 0x10100000L */ + enum yaca_context_type_e { YACA_CONTEXT_INVALID = 0, YACA_CONTEXT_DIGEST, diff --git a/src/key.c b/src/key.c index de55295..264d5ae 100644 --- a/src/key.c +++ b/src/key.c @@ -568,7 +568,7 @@ static int import_evp(yaca_key_h *key, goto exit; } - imported_evp_id = EVP_PKEY_type(pkey->type); + imported_evp_id = EVP_PKEY_type(EVP_PKEY_id(pkey)); switch (imported_key_category) { case IMPORTED_KEY_CATEGORY_PRIVATE: @@ -1161,7 +1161,7 @@ static int generate_evp_pkey_key(int evp_id, size_t key_bit_len, EVP_PKEY *param if (ret != YACA_ERROR_NONE) return ret; } else { - CRYPTO_add(¶ms->references, 1, CRYPTO_LOCK_EVP_PKEY); + EVP_PKEY_up_ref(params); } kctx = EVP_PKEY_CTX_new(params, NULL); @@ -1359,7 +1359,7 @@ static yaca_key_h key_copy_evp(const struct yaca_key_evp_s *key) return YACA_KEY_NULL; /* raise the refcount */ - CRYPTO_add(&key->evp->references, 1, CRYPTO_LOCK_EVP_PKEY); + EVP_PKEY_up_ref(key->evp); copy->key.type = key->key.type; copy->evp = key->evp; @@ -1427,7 +1427,7 @@ API int yaca_key_get_bit_length(const yaca_key_h key, size_t *key_bit_len) case YACA_KEY_TYPE_EC_PRIV: case YACA_KEY_TYPE_EC_PUB: case YACA_KEY_TYPE_EC_PARAMS: { - assert(EVP_PKEY_type(evp_key->evp->type) == EVP_PKEY_EC); + assert(EVP_PKEY_type(EVP_PKEY_id(evp_key->evp)) == EVP_PKEY_EC); const EC_KEY *eck = EVP_PKEY_get0(evp_key->evp); const EC_GROUP *ecg = EC_KEY_get0_group(eck); diff --git a/src/rsa.c b/src/rsa.c index 277af34..334a383 100644 --- a/src/rsa.c +++ b/src/rsa.c @@ -97,7 +97,7 @@ static int encrypt_decrypt(yaca_padding_e padding, ret = fn(input_len, (const unsigned char*)input, (unsigned char*)loutput, - lasym_key->evp->pkey.rsa, + EVP_PKEY_get0_RSA(lasym_key->evp), lpadding); if (ret < 0) { diff --git a/src/sign.c b/src/sign.c index 79d7759..ea9ce6f 100644 --- a/src/sign.c +++ b/src/sign.c @@ -70,16 +70,18 @@ static int get_sign_output_length(const yaca_context_h ctx, assert(output_len != NULL); struct yaca_sign_context_s *c = get_sign_context(ctx); + EVP_PKEY_CTX *pctx; if (c == NULL || input_len != 0) return YACA_ERROR_INVALID_PARAMETER; assert(c->md_ctx != NULL); - if (c->md_ctx->pctx == NULL) + pctx = EVP_MD_CTX_pkey_ctx(c->md_ctx); + if (pctx == NULL) return YACA_ERROR_INTERNAL; - EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(c->md_ctx->pctx); + EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(pctx); if (pkey == NULL) { ERROR_DUMP(YACA_ERROR_INTERNAL); return YACA_ERROR_INTERNAL; @@ -116,13 +118,15 @@ int set_sign_property(yaca_context_h ctx, yaca_padding_e padding; int pad; EVP_PKEY *pkey; + EVP_PKEY_CTX *pctx; if (c == NULL || value == NULL) return YACA_ERROR_INVALID_PARAMETER; assert(c->md_ctx != NULL); - if (c->md_ctx->pctx == NULL) + pctx = EVP_MD_CTX_pkey_ctx(c->md_ctx); + if (pctx == NULL) return YACA_ERROR_INTERNAL; /* this function only supports padding */ @@ -143,7 +147,7 @@ int set_sign_property(yaca_context_h ctx, pad = rsa_padding2openssl(padding); assert(pad != -1); - pkey = EVP_PKEY_CTX_get0_pkey(c->md_ctx->pctx); + pkey = EVP_PKEY_CTX_get0_pkey(pctx); if (pkey == NULL) { ret = YACA_ERROR_INTERNAL; ERROR_DUMP(ret); @@ -151,10 +155,10 @@ int set_sign_property(yaca_context_h ctx, } /* padding only works for RSA */ - if (pkey->type != EVP_PKEY_RSA) + if (EVP_PKEY_id(pkey) != EVP_PKEY_RSA) return YACA_ERROR_INVALID_PARAMETER; - ret = EVP_PKEY_CTX_set_rsa_padding(c->md_ctx->pctx, pad); + ret = EVP_PKEY_CTX_set_rsa_padding(pctx, pad); if (ret <= 0) { ret = YACA_ERROR_INTERNAL; ERROR_DUMP(ret); @@ -172,6 +176,7 @@ int get_sign_property(const yaca_context_h ctx, int ret; struct yaca_sign_context_s *c = get_sign_context(ctx); EVP_PKEY *pkey; + EVP_PKEY_CTX *pctx; int pad; yaca_padding_e padding; @@ -180,14 +185,15 @@ int get_sign_property(const yaca_context_h ctx, assert(c->md_ctx != NULL); - if (c->md_ctx->pctx == NULL) + pctx = EVP_MD_CTX_pkey_ctx(c->md_ctx); + if (pctx == NULL) return YACA_ERROR_INTERNAL; /* this function only supports padding */ if (property != YACA_PROPERTY_PADDING) return YACA_ERROR_INVALID_PARAMETER; - pkey = EVP_PKEY_CTX_get0_pkey(c->md_ctx->pctx); + pkey = EVP_PKEY_CTX_get0_pkey(pctx); if (pkey == NULL) { ret = YACA_ERROR_INTERNAL; ERROR_DUMP(ret); @@ -195,10 +201,10 @@ int get_sign_property(const yaca_context_h ctx, } /* padding only works for RSA */ - if (pkey->type != EVP_PKEY_RSA) + if (EVP_PKEY_id(pkey) != EVP_PKEY_RSA) return YACA_ERROR_INVALID_PARAMETER; - ret = EVP_PKEY_CTX_get_rsa_padding(c->md_ctx->pctx, &pad); + ret = EVP_PKEY_CTX_get_rsa_padding(pctx, &pad); if (ret <= 0) { ret = YACA_ERROR_INTERNAL; ERROR_DUMP(ret); -- 2.7.4