Commit 150eddd9 by Edward Thomson

openssl: separate legacy api

Refactor the OpenSSL stream implementation so that the legacy code is better
abstracted.  This will enable future development.
parent a09d4367
......@@ -6,6 +6,7 @@
*/
#include "streams/openssl.h"
#include "streams/openssl_legacy.h"
#ifdef GIT_OPENSSL
......@@ -35,147 +36,6 @@ SSL_CTX *git__ssl_ctx;
#define GIT_SSL_DEFAULT_CIPHERS "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-DSS-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA:DHE-DSS-AES128-SHA256:DHE-DSS-AES256-SHA256:DHE-DSS-AES128-SHA:DHE-DSS-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA"
#if (defined(OPENSSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER < 0x10100000L) || \
(defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x20700000L)
# define OPENSSL_LEGACY_API
#endif
/*
* OpenSSL 1.1 made BIO opaque so we have to use functions to interact with it
* which do not exist in previous versions. We define these inline functions so
* we can program against the interface instead of littering the implementation
* with ifdefs. We do the same for OPENSSL_init_ssl.
*/
#if defined(OPENSSL_LEGACY_API)
static int OPENSSL_init_ssl(int opts, void *settings)
{
GIT_UNUSED(opts);
GIT_UNUSED(settings);
SSL_load_error_strings();
OpenSSL_add_ssl_algorithms();
return 0;
}
static BIO_METHOD* BIO_meth_new(int type, const char *name)
{
BIO_METHOD *meth = git__calloc(1, sizeof(BIO_METHOD));
if (!meth) {
return NULL;
}
meth->type = type;
meth->name = name;
return meth;
}
static void BIO_meth_free(BIO_METHOD *biom)
{
git__free(biom);
}
static int BIO_meth_set_write(BIO_METHOD *biom, int (*write) (BIO *, const char *, int))
{
biom->bwrite = write;
return 1;
}
static int BIO_meth_set_read(BIO_METHOD *biom, int (*read) (BIO *, char *, int))
{
biom->bread = read;
return 1;
}
static int BIO_meth_set_puts(BIO_METHOD *biom, int (*puts) (BIO *, const char *))
{
biom->bputs = puts;
return 1;
}
static int BIO_meth_set_gets(BIO_METHOD *biom, int (*gets) (BIO *, char *, int))
{
biom->bgets = gets;
return 1;
}
static int BIO_meth_set_ctrl(BIO_METHOD *biom, long (*ctrl) (BIO *, int, long, void *))
{
biom->ctrl = ctrl;
return 1;
}
static int BIO_meth_set_create(BIO_METHOD *biom, int (*create) (BIO *))
{
biom->create = create;
return 1;
}
static int BIO_meth_set_destroy(BIO_METHOD *biom, int (*destroy) (BIO *))
{
biom->destroy = destroy;
return 1;
}
static int BIO_get_new_index(void)
{
/* This exists as of 1.1 so before we'd just have 0 */
return 0;
}
static void BIO_set_init(BIO *b, int init)
{
b->init = init;
}
static void BIO_set_data(BIO *a, void *ptr)
{
a->ptr = ptr;
}
static void *BIO_get_data(BIO *a)
{
return a->ptr;
}
static const unsigned char *ASN1_STRING_get0_data(const ASN1_STRING *x)
{
return ASN1_STRING_data((ASN1_STRING *)x);
}
# if defined(GIT_THREADS)
static git_mutex *openssl_locks;
static void openssl_locking_function(
int mode, int n, const char *file, int line)
{
int lock;
GIT_UNUSED(file);
GIT_UNUSED(line);
lock = mode & CRYPTO_LOCK;
if (lock) {
(void)git_mutex_lock(&openssl_locks[n]);
} else {
git_mutex_unlock(&openssl_locks[n]);
}
}
static void shutdown_ssl_locking(void)
{
int num_locks, i;
num_locks = CRYPTO_num_locks();
CRYPTO_set_locking_callback(NULL);
for (i = 0; i < num_locks; ++i)
git_mutex_free(&openssl_locks[i]);
git__free(openssl_locks);
}
# endif /* GIT_THREADS */
#endif /* OPENSSL_LEGACY_API */
static BIO_METHOD *git_stream_bio_method;
static int init_bio_method(void);
......@@ -198,22 +58,6 @@ static void shutdown_ssl(void)
}
#ifdef VALGRIND
#ifdef OPENSSL_LEGACY_API
static void *git_openssl_malloc(size_t bytes)
{
return git__calloc(1, bytes);
}
static void *git_openssl_realloc(void *mem, size_t size)
{
return git__realloc(mem, size);
}
static void git_openssl_free(void *mem)
{
return git__free(mem);
}
#else
static void *git_openssl_malloc(size_t bytes, const char *file, int line)
{
GIT_UNUSED(file);
......@@ -235,7 +79,6 @@ static void git_openssl_free(void *mem, const char *file, int line)
return git__free(mem);
}
#endif
#endif
int git_openssl_stream_global_init(void)
{
......@@ -301,42 +144,17 @@ error:
return -1;
}
#if defined(GIT_THREADS) && defined(OPENSSL_LEGACY_API)
static void threadid_cb(CRYPTO_THREADID *threadid)
{
GIT_UNUSED(threadid);
CRYPTO_THREADID_set_numeric(threadid, git_thread_currentid());
}
#endif
#ifndef GIT_OPENSSL_LEGACY
int git_openssl_set_locking(void)
{
#if defined(GIT_THREADS) && defined(OPENSSL_LEGACY_API)
int num_locks, i;
CRYPTO_THREADID_set_callback(threadid_cb);
num_locks = CRYPTO_num_locks();
openssl_locks = git__calloc(num_locks, sizeof(git_mutex));
GIT_ERROR_CHECK_ALLOC(openssl_locks);
for (i = 0; i < num_locks; i++) {
if (git_mutex_init(&openssl_locks[i]) != 0) {
git_error_set(GIT_ERROR_SSL, "failed to initialize openssl locks");
return -1;
}
}
CRYPTO_set_locking_callback(openssl_locking_function);
return git_runtime_shutdown_register(shutdown_ssl_locking);
#elif !defined(OPENSSL_LEGACY_API)
# ifdef GIT_THREADS
return 0;
#else
# else
git_error_set(GIT_ERROR_THREAD, "libgit2 was not built with threads");
return -1;
#endif
# endif
}
#endif
static int bio_create(BIO *b)
......
/*
* Copyright (C) the libgit2 contributors. All rights reserved.
*
* This file is part of libgit2, distributed under the GNU GPL v2 with
* a Linking Exception. For full terms see the included COPYING file.
*/
#include "streams/openssl.h"
#include "streams/openssl_legacy.h"
#if defined(GIT_OPENSSL) && defined(GIT_OPENSSL_LEGACY)
#include <openssl/ssl.h>
#include <openssl/err.h>
#include <openssl/x509v3.h>
#include <openssl/bio.h>
#include "runtime.h"
#include "git2/sys/openssl.h"
/*
* OpenSSL 1.1 made BIO opaque so we have to use functions to interact with it
* which do not exist in previous versions. We define these inline functions so
* we can program against the interface instead of littering the implementation
* with ifdefs. We do the same for OPENSSL_init_ssl.
*/
int OPENSSL_init_ssl(int opts, void *settings)
{
GIT_UNUSED(opts);
GIT_UNUSED(settings);
SSL_load_error_strings();
OpenSSL_add_ssl_algorithms();
return 0;
}
BIO_METHOD* BIO_meth_new(int type, const char *name)
{
BIO_METHOD *meth = git__calloc(1, sizeof(BIO_METHOD));
if (!meth) {
return NULL;
}
meth->type = type;
meth->name = name;
return meth;
}
void BIO_meth_free(BIO_METHOD *biom)
{
git__free(biom);
}
int BIO_meth_set_write(BIO_METHOD *biom, int (*write) (BIO *, const char *, int))
{
biom->bwrite = write;
return 1;
}
int BIO_meth_set_read(BIO_METHOD *biom, int (*read) (BIO *, char *, int))
{
biom->bread = read;
return 1;
}
int BIO_meth_set_puts(BIO_METHOD *biom, int (*puts) (BIO *, const char *))
{
biom->bputs = puts;
return 1;
}
int BIO_meth_set_gets(BIO_METHOD *biom, int (*gets) (BIO *, char *, int))
{
biom->bgets = gets;
return 1;
}
int BIO_meth_set_ctrl(BIO_METHOD *biom, long (*ctrl) (BIO *, int, long, void *))
{
biom->ctrl = ctrl;
return 1;
}
int BIO_meth_set_create(BIO_METHOD *biom, int (*create) (BIO *))
{
biom->create = create;
return 1;
}
int BIO_meth_set_destroy(BIO_METHOD *biom, int (*destroy) (BIO *))
{
biom->destroy = destroy;
return 1;
}
int BIO_get_new_index(void)
{
/* This exists as of 1.1 so before we'd just have 0 */
return 0;
}
void BIO_set_init(BIO *b, int init)
{
b->init = init;
}
void BIO_set_data(BIO *a, void *ptr)
{
a->ptr = ptr;
}
void *BIO_get_data(BIO *a)
{
return a->ptr;
}
const unsigned char *ASN1_STRING_get0_data(const ASN1_STRING *x)
{
return ASN1_STRING_data((ASN1_STRING *)x);
}
# if defined(GIT_THREADS)
static git_mutex *openssl_locks;
static void openssl_locking_function(
int mode, int n, const char *file, int line)
{
int lock;
GIT_UNUSED(file);
GIT_UNUSED(line);
lock = mode & CRYPTO_LOCK;
if (lock) {
(void)git_mutex_lock(&openssl_locks[n]);
} else {
git_mutex_unlock(&openssl_locks[n]);
}
}
static void shutdown_ssl_locking(void)
{
int num_locks, i;
num_locks = CRYPTO_num_locks();
CRYPTO_set_locking_callback(NULL);
for (i = 0; i < num_locks; ++i)
git_mutex_free(&openssl_locks[i]);
git__free(openssl_locks);
}
static void threadid_cb(CRYPTO_THREADID *threadid)
{
GIT_UNUSED(threadid);
CRYPTO_THREADID_set_numeric(threadid, git_thread_currentid());
}
int git_openssl_set_locking(void)
{
int num_locks, i;
CRYPTO_THREADID_set_callback(threadid_cb);
num_locks = CRYPTO_num_locks();
openssl_locks = git__calloc(num_locks, sizeof(git_mutex));
GIT_ERROR_CHECK_ALLOC(openssl_locks);
for (i = 0; i < num_locks; i++) {
if (git_mutex_init(&openssl_locks[i]) != 0) {
git_error_set(GIT_ERROR_SSL, "failed to initialize openssl locks");
return -1;
}
}
CRYPTO_set_locking_callback(openssl_locking_function);
return git_runtime_shutdown_register(shutdown_ssl_locking);
}
#endif /* GIT_THREADS */
#ifdef VALGRIND
void *git_openssl_malloc(size_t bytes)
{
return git__calloc(1, bytes);
}
void *git_openssl_realloc(void *mem, size_t size)
{
return git__realloc(mem, size);
}
void git_openssl_free(void *mem)
{
return git__free(mem);
}
#endif
#endif /* GIT_OPENSSL && GIT_OPENSSL_LEGACY */
/*
* Copyright (C) the libgit2 contributors. All rights reserved.
*
* This file is part of libgit2, distributed under the GNU GPL v2 with
* a Linking Exception. For full terms see the included COPYING file.
*/
#ifndef INCLUDE_streams_openssl_legacy_h__
#define INCLUDE_streams_openssl_legacy_h__
#ifdef GIT_OPENSSL
# include <openssl/ssl.h>
# include <openssl/err.h>
# include <openssl/x509v3.h>
# include <openssl/bio.h>
# if (defined(OPENSSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER < 0x10100000L) || \
(defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x20700000L)
# define GIT_OPENSSL_LEGACY
# endif
#endif
#ifdef GIT_OPENSSL_LEGACY
extern int OPENSSL_init_ssl(int opts, void *settings);
extern BIO_METHOD* BIO_meth_new(int type, const char *name);
extern void BIO_meth_free(BIO_METHOD *biom);
extern int BIO_meth_set_write(BIO_METHOD *biom, int (*write) (BIO *, const char *, int));
extern int BIO_meth_set_read(BIO_METHOD *biom, int (*read) (BIO *, char *, int));
extern int BIO_meth_set_puts(BIO_METHOD *biom, int (*puts) (BIO *, const char *));
extern int BIO_meth_set_gets(BIO_METHOD *biom, int (*gets) (BIO *, char *, int));
extern int BIO_meth_set_ctrl(BIO_METHOD *biom, long (*ctrl) (BIO *, int, long, void *));
extern int BIO_meth_set_create(BIO_METHOD *biom, int (*create) (BIO *));
extern int BIO_meth_set_destroy(BIO_METHOD *biom, int (*destroy) (BIO *));
extern int BIO_get_new_index(void);
extern void BIO_set_data(BIO *a, void *ptr);
extern void BIO_set_init(BIO *b, int init);
extern void *BIO_get_data(BIO *a);
extern const unsigned char *ASN1_STRING_get0_data(const ASN1_STRING *x);
#endif
#endif
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment