Adapt YACA to work with OpenSSL 1.1 preserving 1.0 compatibility 65/86965/9
authorLukasz Pawelczyk <l.pawelczyk@samsung.com>
Mon, 5 Sep 2016 16:50:36 +0000 (18:50 +0200)
committerLukasz Pawelczyk <l.pawelczyk@samsung.com>
Fri, 9 Sep 2016 10:55:40 +0000 (12:55 +0200)
Change-Id: I27e199659666d2d87b17fcb9882b0e70f751c628

src/crypto.c
src/debug.c
src/encrypt.c
src/internal.h
src/key.c
src/rsa.c
src/sign.c

index aeb6220..a13a594 100644 (file)
@@ -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);
index a229ab8..b6a113d 100644 (file)
@@ -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;
index 56b316f..6ce25cc 100644 (file)
@@ -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;
index 97e86c3..20da604 100644 (file)
 
 #include <openssl/ossl_typ.h>
 #include <openssl/err.h>
+#include <openssl/evp.h>
+#include <openssl/opensslv.h>
+#include <openssl/rand.h>
 
 #include <yaca_types.h>
 
 #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,
index de55295..264d5ae 100644 (file)
--- 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(&params->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);
index 277af34..334a383 100644 (file)
--- 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) {
index 79d7759..ea9ce6f 100644 (file)
@@ -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);