From 04a2b1d9781a7dce2bfdd7eeefebac5b735f3213 Mon Sep 17 00:00:00 2001 From: wildart Date: Fri, 9 Oct 2015 02:54:45 -0400 Subject: [PATCH 01/16] mbedtls cmake config --- CMakeLists.txt | 16 +++++++-- cmake/Modules/FindmbedTLS.cmake | 64 +++++++++++++++++++++++++++++++++ 2 files changed, 78 insertions(+), 2 deletions(-) create mode 100644 cmake/Modules/FindmbedTLS.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index 93a9e47c17d..b868e1d1486 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -88,7 +88,7 @@ IF(MSVC) ENDIF() IF (NOT ${CMAKE_SYSTEM_NAME} MATCHES "Darwin") - OPTION( USE_OPENSSL "Link with and use openssl library" ON ) + OPTION( USE_OPENSSL "Link with and use openssl library" ON ) ENDIF() CHECK_STRUCT_HAS_MEMBER ("struct stat" st_mtim "sys/types.h;sys/stat.h" @@ -109,7 +109,10 @@ ELSE () ENDIF() IF (HAVE_STRUCT_STAT_NSEC OR WIN32) - OPTION( USE_NSEC "Care about sub-second file mtimes and ctimes" ON ) + OPTION( USE_NSEC "Care about sub-second file mtimes and ctimes" ON ) + +IF (NOT USE_OPENSSL) + OPTION( USE_MBEDTLS "Link with and use mbedtls library" ON ) ENDIF() # This variable will contain the libraries we need to put into @@ -283,6 +286,10 @@ ELSE () FIND_PACKAGE(OpenSSL) ENDIF () + IF (NOT AMIGA AND USE_MBEDTLS AND NOT USE_OPENSSL) + FIND_PACKAGE(mbedTLS) + ENDIF () + IF (CURL_FOUND) ADD_DEFINITIONS(-DGIT_CURL) INCLUDE_DIRECTORIES(${CURL_INCLUDE_DIRS}) @@ -542,6 +549,11 @@ IF (OPENSSL_FOUND) SET(SSL_LIBRARIES ${OPENSSL_LIBRARIES}) ENDIF() +IF (MBEDTLS_FOUND) + ADD_DEFINITIONS(-DGIT_MBEDTLS) + INCLUDE_DIRECTORIES(${MBEDTLS_INCLUDE_DIR}) + SET(SSL_LIBRARIES ${MBEDTLS_LIBRARIES}) +ENDIF() IF (THREADSAFE) diff --git a/cmake/Modules/FindmbedTLS.cmake b/cmake/Modules/FindmbedTLS.cmake new file mode 100644 index 00000000000..2f4adbc5198 --- /dev/null +++ b/cmake/Modules/FindmbedTLS.cmake @@ -0,0 +1,64 @@ +# - Try to find mbedTLS +# Once done this will define +# +# Read-Only variables +# MBEDTLS_FOUND - system has mbedTLS +# MBEDTLS_INCLUDE_DIR - the mbedTLS include directory +# MBEDTLS_LIBRARY_DIR - the mbedTLS library directory +# MBEDTLS_LIBRARIES - Link these to use mbedTLS +# MBEDTLS_LIBRARY - path to mbedTLS library +# MBEDX509_LIBRARY - path to mbedTLS X.509 library +# MBEDCRYPTO_LIBRARY - path to mbedTLS Crypto library + +FIND_PATH(MBEDTLS_INCLUDE_DIR mbedtls/version.h) + +IF(MBEDTLS_INCLUDE_DIR AND MBEDTLS_LIBRARIES) + # Already in cache, be silent + SET(MBEDTLS_FIND_QUIETLY TRUE) +ENDIF() + +FIND_LIBRARY(MBEDTLS_LIBRARY NAMES mbedtls libmbedtls libmbedx509) +FIND_LIBRARY(MBEDX509_LIBRARY NAMES mbedx509 libmbedx509) +FIND_LIBRARY(MBEDCRYPTO_LIBRARY NAMES mbedcrypto libmbedcrypto) + +IF(MBEDTLS_INCLUDE_DIR AND MBEDTLS_LIBRARY AND MBEDX509_LIBRARY AND MBEDCRYPTO_LIBRARY) + SET(MBEDTLS_FOUND TRUE) +ENDIF() + +IF(MBEDTLS_FOUND) + # split mbedTLS into -L and -l linker options, so we can set them for pkg-config + GET_FILENAME_COMPONENT(MBEDTLS_LIBRARY_DIR ${MBEDTLS_LIBRARY} PATH) + GET_FILENAME_COMPONENT(MBEDTLS_LIBRARY_FILE ${MBEDTLS_LIBRARY} NAME_WE) + GET_FILENAME_COMPONENT(MBEDX509_LIBRARY_FILE ${MBEDX509_LIBRARY} NAME_WE) + GET_FILENAME_COMPONENT(MBEDCRYPTO_LIBRARY_FILE ${MBEDCRYPTO_LIBRARY} NAME_WE) + STRING(REGEX REPLACE "^lib" "" MBEDTLS_LIBRARY_FILE ${MBEDTLS_LIBRARY_FILE}) + STRING(REGEX REPLACE "^lib" "" MBEDX509_LIBRARY_FILE ${MBEDX509_LIBRARY_FILE}) + STRING(REGEX REPLACE "^lib" "" MBEDCRYPTO_LIBRARY_FILE ${MBEDCRYPTO_LIBRARY_FILE}) + SET(MBEDTLS_LIBRARIES "-L${MBEDTLS_LIBRARY_DIR} -l${MBEDTLS_LIBRARY_FILE} -l${MBEDX509_LIBRARY_FILE} -l${MBEDCRYPTO_LIBRARY_FILE}") + + IF(NOT MBEDTLS_FIND_QUIETLY) + MESSAGE(STATUS "Found mbedTLS:") + FILE(READ ${MBEDTLS_INCLUDE_DIR}/mbedtls/version.h MBEDTLSCONTENT) + STRING(REGEX MATCH "MBEDTLS_VERSION_STRING +\"[0-9|.]+\"" MBEDTLSMATCH ${MBEDTLSCONTENT}) + IF (MBEDTLSMATCH) + STRING(REGEX REPLACE "MBEDTLS_VERSION_STRING +\"([0-9|.]+)\"" "\\1" MBEDTLS_VERSION ${MBEDTLSMATCH}) + MESSAGE(STATUS " version ${MBEDTLS_VERSION}") + ENDIF(MBEDTLSMATCH) + MESSAGE(STATUS " TLS: ${MBEDTLS_LIBRARY}") + MESSAGE(STATUS " X509: ${MBEDX509_LIBRARY}") + MESSAGE(STATUS " Crypto: ${MBEDCRYPTO_LIBRARY}") + ENDIF(NOT MBEDTLS_FIND_QUIETLY) +ELSE(MBEDTLS_FOUND) + IF(MBEDTLS_FIND_REQUIRED) + MESSAGE(FATAL_ERROR "Could not find mbedTLS") + ENDIF(MBEDTLS_FIND_REQUIRED) +ENDIF(MBEDTLS_FOUND) + +MARK_AS_ADVANCED( + MBEDTLS_INCLUDE_DIR + MBEDTLS_LIBRARY_DIR + MBEDTLS_LIBRARIES + MBEDTLS_LIBRARY + MBEDX509_LIBRARY + MBEDCRYPTO_LIBRARY +) From cfc27a3061200f490d8c178b6d8576d1cefe7034 Mon Sep 17 00:00:00 2001 From: wildart Date: Fri, 9 Oct 2015 02:55:23 -0400 Subject: [PATCH 02/16] define mbedtls global configuration --- src/global.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/global.h b/src/global.h index 219951525d7..a7ee1d3f98c 100644 --- a/src/global.h +++ b/src/global.h @@ -23,6 +23,11 @@ typedef struct { extern SSL_CTX *git__ssl_ctx; #endif +#ifdef GIT_MBEDTLS +# include "mbedtls/ssl.h" +extern mbedtls_ssl_config *git__ssl_conf; +#endif + git_global_st *git__global_state(void); extern git_mutex git__mwindow_mutex; From d44d0200a3ed26cdf7f851f36ddd24eb37eeb757 Mon Sep 17 00:00:00 2001 From: wildart Date: Fri, 9 Oct 2015 02:56:04 -0400 Subject: [PATCH 03/16] added certificate location setup --- src/settings.c | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/src/settings.c b/src/settings.c index 4a6e0f353bb..1818d9ad0bb 100644 --- a/src/settings.c +++ b/src/settings.c @@ -9,6 +9,10 @@ # include #endif +#ifdef GIT_MBEDTLS +# include +#endif + #include #include "common.h" #include "sysdir.h" @@ -174,8 +178,25 @@ int git_libgit2_opts(int key, ...) error = -1; } } +#elif GIT_MBEDTLS + { + const char *file = va_arg(ap, const char *); + const char *path = va_arg(ap, const char *); + int ret = 0; + char errbuf[512]; + if (!file) { + ret = mbedtls_x509_crt_parse_file(git__ssl_conf->ca_chain, file); + } else if (!path) { + ret = mbedtls_x509_crt_parse_path(git__ssl_conf->ca_chain, path); + } + if (ret != 0) { + mbedtls_strerror( ret, errbuf, 512 ); + giterr_set(GITERR_NET, "SSL error: %d - %s", ret, errbuf); + error = -1; + } + } #else - giterr_set(GITERR_NET, "cannot set certificate locations: OpenSSL is not enabled"); + giterr_set(GITERR_NET, "Cannot set certificate locations: OpenSSL or mbedTLS is not enabled"); error = -1; #endif break; From a5958d04c614cbd34ce01e085284c592709de85f Mon Sep 17 00:00:00 2001 From: wildart Date: Fri, 9 Oct 2015 02:56:51 -0400 Subject: [PATCH 04/16] introduced GIT_MBEDTLS symbol --- src/tls_stream.c | 3 +++ src/transport.c | 2 +- src/transports/http.c | 2 +- tests/online/badssl.c | 2 +- 4 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/tls_stream.c b/src/tls_stream.c index 83e2d064a15..6fb538f499e 100644 --- a/src/tls_stream.c +++ b/src/tls_stream.c @@ -9,6 +9,7 @@ #include "common.h" #include "openssl_stream.h" +#include "mbedtls_stream.h" #include "stransport_stream.h" static git_stream_cb tls_ctor; @@ -30,6 +31,8 @@ int git_tls_stream_new(git_stream **out, const char *host, const char *port) return git_stransport_stream_new(out, host, port); #elif defined(GIT_OPENSSL) return git_openssl_stream_new(out, host, port); +#elif defined(GIT_MBEDTLS) + return git_mbedtls_stream_new(out, host, port); #else GIT_UNUSED(out); GIT_UNUSED(host); diff --git a/src/transport.c b/src/transport.c index 327052fa393..a4384598481 100644 --- a/src/transport.c +++ b/src/transport.c @@ -29,7 +29,7 @@ static transport_definition local_transport_definition = { "file://", git_transp static transport_definition transports[] = { { "git://", git_transport_smart, &git_subtransport_definition }, { "http://", git_transport_smart, &http_subtransport_definition }, -#if defined(GIT_OPENSSL) || defined(GIT_WINHTTP) || defined(GIT_SECURE_TRANSPORT) +#if defined(GIT_OPENSSL) || defined(GIT_WINHTTP) || defined(GIT_SECURE_TRANSPORT) || defined(GIT_MBEDTLS) { "https://", git_transport_smart, &http_subtransport_definition }, #endif { "file://", git_transport_local, NULL }, diff --git a/src/transports/http.c b/src/transports/http.c index 4fbbfbbad22..19078e434b7 100644 --- a/src/transports/http.c +++ b/src/transports/http.c @@ -620,7 +620,7 @@ static int http_connect(http_subtransport *t) error = git_stream_connect(t->io); -#if defined(GIT_OPENSSL) || defined(GIT_SECURE_TRANSPORT) || defined(GIT_CURL) +#if defined(GIT_OPENSSL) || defined(GIT_SECURE_TRANSPORT) || defined(GIT_CURL) || defined(GIT_MBEDTLS) if ((!error || error == GIT_ECERTIFICATE) && t->owner->certificate_check_cb != NULL && git_stream_is_encrypted(t->io)) { git_cert *cert; diff --git a/tests/online/badssl.c b/tests/online/badssl.c index 66b090df468..bba31cc8eed 100644 --- a/tests/online/badssl.c +++ b/tests/online/badssl.c @@ -4,7 +4,7 @@ static git_repository *g_repo; -#if defined(GIT_OPENSSL) || defined(GIT_WINHTTP) || defined(GIT_SECURE_TRANSPORT) +#if defined(GIT_OPENSSL) || defined(GIT_WINHTTP) || defined(GIT_SECURE_TRANSPORT) || defined(GIT_MBEDTLS) static bool g_has_ssl = true; #else static bool g_has_ssl = false; From ad2b2e2242da65f5f3fa37dbb02c1eb22a97fddb Mon Sep 17 00:00:00 2001 From: wildart Date: Fri, 9 Oct 2015 04:55:30 -0400 Subject: [PATCH 05/16] added git_mbedtls_stream_new --- src/mbedtls_stream.c | 303 +++++++++++++++++++++++++++++++++++++++++++ src/mbedtls_stream.h | 14 ++ 2 files changed, 317 insertions(+) create mode 100644 src/mbedtls_stream.c create mode 100644 src/mbedtls_stream.h diff --git a/src/mbedtls_stream.c b/src/mbedtls_stream.c new file mode 100644 index 00000000000..aeb6cbaf272 --- /dev/null +++ b/src/mbedtls_stream.c @@ -0,0 +1,303 @@ +/* + * 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. + */ + +#ifdef GIT_MBEDTLS + +#include + +#include "global.h" +#include "posix.h" +#include "stream.h" +#include "socket_stream.h" +#include "netops.h" +#include "git2/transport.h" + +#ifdef GIT_CURL +# include "curl_stream.h" +#endif + +#ifndef GIT_WIN32 +# include +# include +# include +#endif + +#include +#include +#include + +static int bio_read(void *b, unsigned char *buf, size_t len) +{ + git_stream *io = (git_stream *) b; + return (int) git_stream_read(io, buf, len); +} + +static int bio_write(void *b, const unsigned char *buf, size_t len) +{ + git_stream *io = (git_stream *) b; + return (int) git_stream_write(io, (const char *)buf, len, 0); +} + +static int ssl_set_error(int error) +{ + char errbuf[512]; + + assert(error != MBEDTLS_ERR_SSL_WANT_READ); + assert(error != MBEDTLS_ERR_SSL_WANT_WRITE); + + if (error == 0) { + giterr_set(GITERR_NET, "SSL error: unknown error"); + } else { + mbedtls_strerror( error, errbuf, 512 ); + giterr_set(GITERR_NET, "SSL error: %d - %s", error, errbuf); + } + + return -1; +} + +static int ssl_teardown(mbedtls_ssl_context *ssl) +{ + int ret = 0; + + ret = mbedtls_ssl_close_notify(ssl); + if (ret < 0) + ret = ssl_set_error(ret); + + mbedtls_ssl_free(ssl); + return ret; +} + +static int verify_server_cert(mbedtls_ssl_context *ssl, const char *host) +{ + const mbedtls_x509_crt *cert; + int flags; + struct in6_addr addr6; + struct in_addr addr4; + void *addr; + + if( ( flags = mbedtls_ssl_get_verify_result(ssl) ) != 0 ) + { + char vrfy_buf[512]; + mbedtls_x509_crt_verify_info( vrfy_buf, sizeof( vrfy_buf ), " ! ", flags ); + giterr_set(GITERR_SSL, "The SSL certificate is invalid: %s", vrfy_buf); + return GIT_ECERTIFICATE; + } + + /* Try to parse the host as an IP address to see if it is */ + if (p_inet_pton(AF_INET, host, &addr4)) { + addr = &addr4; + } else { + if(p_inet_pton(AF_INET6, host, &addr6)) { + addr = &addr6; + } + } + + cert = mbedtls_ssl_get_peer_cert(ssl); + if (!cert) { + giterr_set(GITERR_SSL, "the server did not provide a certificate"); + return -1; + } + + /* Check the alternative names */ + //TODO: cert->subject_alt_names + + /* If no alternative names are available, check the common name */ + /*TODO + mbedtls_x509_name peer_name = cert->subject; + if (peer_name == NULL) + goto on_error; + */ + + return 0; + +on_error: + return ssl_set_error(0); + +cert_fail_name: + giterr_set(GITERR_SSL, "hostname does not match certificate"); + return GIT_ECERTIFICATE; +} + +typedef struct { + git_stream parent; + git_stream *io; + bool connected; + char *host; + mbedtls_ssl_context *ssl; + git_cert_x509 cert_info; +} mbedtls_stream; + + +int mbedtls_connect(git_stream *stream) +{ + int ret; + mbedtls_stream *st = (mbedtls_stream *) stream; + + if ((ret = git_stream_connect(st->io)) < 0) + return ret; + + st->connected = true; + + mbedtls_ssl_set_bio(st->ssl, st->io, bio_write, bio_read, NULL); + + /* specify the host in case SNI is needed */ +#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME + mbedtls_ssl_set_hostname(st->ssl, st->host); +#endif + + if ((ret = mbedtls_ssl_handshake(st->ssl)) != 0) + return ssl_set_error(ret); + + return verify_server_cert(st->ssl, st->host); +} + +int mbedtls_certificate(git_cert **out, git_stream *stream) +{ + unsigned char *encoded_cert; + mbedtls_stream *st = (mbedtls_stream *) stream; + + const mbedtls_x509_crt *cert = mbedtls_ssl_get_peer_cert(st->ssl); + if (!cert) { + giterr_set(GITERR_SSL, "the server did not provide a certificate"); + return -1; + } + + /* Retrieve the length of the certificate first */ + if (cert->raw.len == 0) { + giterr_set(GITERR_NET, "failed to retrieve certificate information"); + return -1; + } + + encoded_cert = git__malloc(cert->raw.len); + GITERR_CHECK_ALLOC(encoded_cert); + memcpy(encoded_cert, cert->raw.p, cert->raw.len); + + st->cert_info.parent.cert_type = GIT_CERT_X509; + st->cert_info.data = encoded_cert; + st->cert_info.len = cert->raw.len; + + *out = &st->cert_info.parent; + + return 0; +} + +static int mbedtls_set_proxy(git_stream *stream, const char *proxy_url) +{ + mbedtls_stream *st = (mbedtls_stream *) stream; + + return git_stream_set_proxy(st->io, proxy_url); +} + +ssize_t mbedtls_write(git_stream *stream, const char *data, size_t len, int flags) +{ + mbedtls_stream *st = (mbedtls_stream *) stream; + int ret; + + GIT_UNUSED(flags); + + if ((ret = mbedtls_ssl_write(st->ssl, (const unsigned char *)data, len)) <= 0) { + return ssl_set_error(ret); + } + + return ret; +} + +ssize_t mbedtls_read(git_stream *stream, void *data, size_t len) +{ + mbedtls_stream *st = (mbedtls_stream *) stream; + int ret; + + if ((ret = mbedtls_ssl_read(st->ssl, (unsigned char *)data, len)) <= 0) + ssl_set_error(ret); + + return ret; +} + +int mbedtls_close(git_stream *stream) +{ + mbedtls_stream *st = (mbedtls_stream *) stream; + int ret = 0; + + if (st->connected && (ret = ssl_teardown(st->ssl)) != 0) + return -1; + + st->connected = false; + + return git_stream_close(st->io); +} + +void mbedtls_free(git_stream *stream) +{ + mbedtls_stream *st = (mbedtls_stream *) stream; + + git__free(st->host); + git__free(st->cert_info.data); + git_stream_free(st->io); + git__free(st->ssl); + git__free(st); +} + +int git_mbedtls_stream_new(git_stream **out, const char *host, const char *port) +{ + int error; + mbedtls_stream *st; + + st = git__calloc(1, sizeof(mbedtls_stream)); + GITERR_CHECK_ALLOC(st); + +#ifdef GIT_CURL + error = git_curl_stream_new(&st->io, host, port); +#else + error = git_socket_stream_new(&st->io, host, port); +#endif + + if (error < 0) + return error; + + st->ssl = git__malloc(sizeof(mbedtls_ssl_context)); + GITERR_CHECK_ALLOC(st->ssl); + mbedtls_ssl_init(st->ssl); + if( (error = mbedtls_ssl_setup(st->ssl, git__ssl_conf)) != 0 ) { + mbedtls_ssl_free(st->ssl); + giterr_set(GITERR_SSL, "failed to create ssl object"); + return -1; + } + + st->host = git__strdup(host); + GITERR_CHECK_ALLOC(st->host); + + st->parent.version = GIT_STREAM_VERSION; + st->parent.encrypted = 1; + st->parent.proxy_support = git_stream_supports_proxy(st->io); + st->parent.connect = mbedtls_connect; + st->parent.certificate = mbedtls_certificate; + st->parent.set_proxy = mbedtls_set_proxy; + st->parent.read = mbedtls_read; + st->parent.write = mbedtls_write; + st->parent.close = mbedtls_close; + st->parent.free = mbedtls_free; + + *out = (git_stream *) st; + return 0; +} + +#else + +#include "stream.h" + +int git_mbedtls_stream_new(git_stream **out, const char *host, const char *port) +{ + GIT_UNUSED(out); + GIT_UNUSED(host); + GIT_UNUSED(port); + + giterr_set(GITERR_SSL, "openssl is not supported in this version"); + return -1; +} + +#endif + diff --git a/src/mbedtls_stream.h b/src/mbedtls_stream.h new file mode 100644 index 00000000000..170b10a2e49 --- /dev/null +++ b/src/mbedtls_stream.h @@ -0,0 +1,14 @@ +/* + * 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_mbedtls_stream_h__ +#define INCLUDE_mbedtls_stream_h__ + +#include "git2/sys/stream.h" + +extern int git_mbedtls_stream_new(git_stream **out, const char *host, const char *port); + +#endif From 101ab46c616d72ac774c1b6e02cf2cececa04024 Mon Sep 17 00:00:00 2001 From: wildart Date: Sat, 10 Oct 2015 07:09:06 -0400 Subject: [PATCH 06/16] proper certificate verification & cleanup of `git_mbedtls_stream_new` --- src/mbedtls_stream.c | 118 ++++++++++++++++++++++++++----------------- 1 file changed, 72 insertions(+), 46 deletions(-) diff --git a/src/mbedtls_stream.c b/src/mbedtls_stream.c index aeb6cbaf272..24b8fda10b6 100644 --- a/src/mbedtls_stream.c +++ b/src/mbedtls_stream.c @@ -10,24 +10,17 @@ #include #include "global.h" -#include "posix.h" #include "stream.h" #include "socket_stream.h" -#include "netops.h" #include "git2/transport.h" #ifdef GIT_CURL # include "curl_stream.h" #endif -#ifndef GIT_WIN32 -# include -# include -# include -#endif - #include #include +#include #include static int bio_read(void *b, unsigned char *buf, size_t len) @@ -42,21 +35,30 @@ static int bio_write(void *b, const unsigned char *buf, size_t len) return (int) git_stream_write(io, (const char *)buf, len, 0); } -static int ssl_set_error(int error) +static int ssl_set_error(mbedtls_ssl_context *ssl, int error) { char errbuf[512]; + int ret = -1; assert(error != MBEDTLS_ERR_SSL_WANT_READ); assert(error != MBEDTLS_ERR_SSL_WANT_WRITE); - if (error == 0) { - giterr_set(GITERR_NET, "SSL error: unknown error"); - } else { + if (error != 0) mbedtls_strerror( error, errbuf, 512 ); - giterr_set(GITERR_NET, "SSL error: %d - %s", error, errbuf); + + switch(error){ + case 0: + giterr_set(GITERR_SSL, "SSL error: unknown error"); + break; + case MBEDTLS_ERR_X509_CERT_VERIFY_FAILED: + giterr_set(GITERR_SSL, "SSL error: %x[%x] - %s", error, ssl->session_negotiate->verify_result, errbuf); + ret = GIT_ECERTIFICATE; + break; + default: + giterr_set(GITERR_SSL, "SSL error: %x - %s", error, errbuf); } - return -1; + return ret; } static int ssl_teardown(mbedtls_ssl_context *ssl) @@ -65,37 +67,39 @@ static int ssl_teardown(mbedtls_ssl_context *ssl) ret = mbedtls_ssl_close_notify(ssl); if (ret < 0) - ret = ssl_set_error(ret); + ret = ssl_set_error(ssl, ret); mbedtls_ssl_free(ssl); return ret; } +static int check_host_name(const char *name, const char *host) +{ + if (!strcasecmp(name, host)) + return 0; + + if (gitno__match_host(name, host) < 0) + return -1; + + return 0; +} + static int verify_server_cert(mbedtls_ssl_context *ssl, const char *host) { const mbedtls_x509_crt *cert; - int flags; - struct in6_addr addr6; - struct in_addr addr4; - void *addr; + const mbedtls_x509_sequence *alts; + int ret, matched = -1; + size_t sn_size = 512; + char subject_name[sn_size], alt_name[sn_size]; + - if( ( flags = mbedtls_ssl_get_verify_result(ssl) ) != 0 ) - { + if (( ret = mbedtls_ssl_get_verify_result(ssl) ) != 0) { char vrfy_buf[512]; - mbedtls_x509_crt_verify_info( vrfy_buf, sizeof( vrfy_buf ), " ! ", flags ); + mbedtls_x509_crt_verify_info( vrfy_buf, sizeof( vrfy_buf ), " ! ", ret ); giterr_set(GITERR_SSL, "The SSL certificate is invalid: %s", vrfy_buf); return GIT_ECERTIFICATE; } - /* Try to parse the host as an IP address to see if it is */ - if (p_inet_pton(AF_INET, host, &addr4)) { - addr = &addr4; - } else { - if(p_inet_pton(AF_INET6, host, &addr6)) { - addr = &addr6; - } - } - cert = mbedtls_ssl_get_peer_cert(ssl); if (!cert) { giterr_set(GITERR_SSL, "the server did not provide a certificate"); @@ -103,19 +107,44 @@ static int verify_server_cert(mbedtls_ssl_context *ssl, const char *host) } /* Check the alternative names */ - //TODO: cert->subject_alt_names + alts = &cert->subject_alt_names; + while (alts != NULL && matched != 1) { + // Buffer is too small + if( alts->buf.len >= sn_size ) + goto on_error; + + memcpy(alt_name, alts->buf.p, alts->buf.len); + alt_name[alts->buf.len] = '\0'; + + if (!memchr(alt_name, '\0', alts->buf.len)) { + if (check_host_name(alt_name, host) < 0) + matched = 0; + else + matched = 1; + } + + alts = alts->next; + } + if (matched == 0) + goto cert_fail_name; + + if (matched == 1) + return 0; /* If no alternative names are available, check the common name */ - /*TODO - mbedtls_x509_name peer_name = cert->subject; - if (peer_name == NULL) + ret = mbedtls_x509_dn_gets(subject_name, sn_size, &cert->subject); + if (ret == 0) goto on_error; - */ + if (memchr(subject_name, '\0', ret)) + goto cert_fail_name; + + if (check_host_name(subject_name, host) < 0) + goto cert_fail_name; return 0; on_error: - return ssl_set_error(0); + return ssl_set_error(ssl, 0); cert_fail_name: giterr_set(GITERR_SSL, "hostname does not match certificate"); @@ -142,15 +171,12 @@ int mbedtls_connect(git_stream *stream) st->connected = true; - mbedtls_ssl_set_bio(st->ssl, st->io, bio_write, bio_read, NULL); - - /* specify the host in case SNI is needed */ -#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME mbedtls_ssl_set_hostname(st->ssl, st->host); -#endif + + mbedtls_ssl_set_bio(st->ssl, st->io, bio_write, bio_read, NULL); if ((ret = mbedtls_ssl_handshake(st->ssl)) != 0) - return ssl_set_error(ret); + return ssl_set_error(st->ssl, ret); return verify_server_cert(st->ssl, st->host); } @@ -200,7 +226,7 @@ ssize_t mbedtls_write(git_stream *stream, const char *data, size_t len, int flag GIT_UNUSED(flags); if ((ret = mbedtls_ssl_write(st->ssl, (const unsigned char *)data, len)) <= 0) { - return ssl_set_error(ret); + return ssl_set_error(st->ssl, ret); } return ret; @@ -212,7 +238,7 @@ ssize_t mbedtls_read(git_stream *stream, void *data, size_t len) int ret; if ((ret = mbedtls_ssl_read(st->ssl, (unsigned char *)data, len)) <= 0) - ssl_set_error(ret); + ssl_set_error(st->ssl, ret); return ret; } @@ -295,7 +321,7 @@ int git_mbedtls_stream_new(git_stream **out, const char *host, const char *port) GIT_UNUSED(host); GIT_UNUSED(port); - giterr_set(GITERR_SSL, "openssl is not supported in this version"); + giterr_set(GITERR_SSL, "mbedtls is not supported in this version"); return -1; } From 46db15f45bb8c3e36ceb4c48da9b2e54016282c0 Mon Sep 17 00:00:00 2001 From: wildart Date: Sun, 11 Oct 2015 08:36:13 -0400 Subject: [PATCH 07/16] use libmbedcrypto for SHA1 --- CMakeLists.txt | 3 +++ src/hash.h | 2 ++ src/hash/hash_mbedtls.c | 38 ++++++++++++++++++++++++++++++++++++++ src/hash/hash_mbedtls.h | 20 ++++++++++++++++++++ 4 files changed, 63 insertions(+) create mode 100644 src/hash/hash_mbedtls.c create mode 100644 src/hash/hash_mbedtls.h diff --git a/CMakeLists.txt b/CMakeLists.txt index b868e1d1486..cd32c957aa3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -322,6 +322,9 @@ ELSEIF (OPENSSL_FOUND AND NOT SHA1_TYPE STREQUAL "builtin") ELSE() SET(LIBGIT2_PC_REQUIRES "${LIBGIT2_PC_REQUIRES} openssl") ENDIF () +ELSEIF (MBEDTLS_FOUND AND NOT SHA1_TYPE STREQUAL "builtin") + ADD_DEFINITIONS(-DMBEDTLS_SHA1) + FILE(GLOB SRC_SHA1 src/hash/hash_mbedtls.c) ELSE() FILE(GLOB SRC_SHA1 src/hash/hash_generic.c) ENDIF() diff --git a/src/hash.h b/src/hash.h index 0bc02a8a995..958d23bacef 100644 --- a/src/hash.h +++ b/src/hash.h @@ -20,6 +20,8 @@ void git_hash_ctx_cleanup(git_hash_ctx *ctx); # include "hash/hash_common_crypto.h" #elif defined(OPENSSL_SHA1) # include "hash/hash_openssl.h" +#elif defined(MBEDTLS_SHA1) +# include "hash/hash_mbedtls.h" #elif defined(WIN32_SHA1) # include "hash/hash_win32.h" #else diff --git a/src/hash/hash_mbedtls.c b/src/hash/hash_mbedtls.c new file mode 100644 index 00000000000..a19d7630827 --- /dev/null +++ b/src/hash/hash_mbedtls.c @@ -0,0 +1,38 @@ +/* + * 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 "common.h" +#include "hash.h" +#include "hash/hash_mbedtls.h" + +void git_hash_ctx_cleanup(git_hash_ctx *ctx) +{ + assert(ctx); + mbedtls_sha1_free(&ctx->c); +} + +int git_hash_init(git_hash_ctx *ctx) +{ + assert(ctx); + mbedtls_sha1_init(&ctx->c); + mbedtls_sha1_starts(&ctx->c); + return 0; +} + +int git_hash_update(git_hash_ctx *ctx, const void *data, size_t len) +{ + assert(ctx); + mbedtls_sha1_update(&ctx->c, data, len); + return 0; +} + +int git_hash_final(git_oid *out, git_hash_ctx *ctx) +{ + assert(ctx); + mbedtls_sha1_finish(&ctx->c, out->id); + return 0; +} diff --git a/src/hash/hash_mbedtls.h b/src/hash/hash_mbedtls.h new file mode 100644 index 00000000000..e50d2953442 --- /dev/null +++ b/src/hash/hash_mbedtls.h @@ -0,0 +1,20 @@ +/* + * 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_hash_mbedtld_h__ +#define INCLUDE_hash_mbedtld_h__ + +#include + +struct git_hash_ctx { + mbedtls_sha1_context c; +}; + +#define git_hash_global_init() 0 +#define git_hash_ctx_init(ctx) git_hash_init(ctx) + +#endif /* INCLUDE_hash_mbedtld_h__ */ \ No newline at end of file From 369d23a8353b287b790bca18dfd90dbb4dc3a0ef Mon Sep 17 00:00:00 2001 From: wildart Date: Sun, 11 Oct 2015 17:52:52 -0400 Subject: [PATCH 08/16] added new CI configuration for mbedtls --- .travis.yml | 10 ++++++++++ CMakeLists.txt | 2 +- script/cibuild.sh | 5 +++++ script/mbedtls.sh | 6 ++++++ 4 files changed, 22 insertions(+), 1 deletion(-) create mode 100755 script/mbedtls.sh diff --git a/.travis.yml b/.travis.yml index bfc0fac4817..0ef35b673b8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -45,6 +45,16 @@ matrix: - VALGRIND=1 OPTIONS="-DBUILD_CLAR=ON -DBUILD_EXAMPLES=OFF -DDEBUG_POOL=ON -DCMAKE_BUILD_TYPE=Debug" os: linux + - compiler: gcc + env: + - MBEDTLS=1 + OPTIONS="-DTHREADSAFE=ON -DCMAKE_BUILD_TYPE=Release -DUSE_OPENSSL=OFF -DMBEDTLS_ROOT_DIR=../mbedtls" + os: linux + - compiler: gcc + env: + - MBEDTLS=1 + OPTIONS="-DTHREADSAFE=OFF -DBUILD_EXAMPLES=ON -DUSE_OPENSSL=OFF -DMBEDTLS_ROOT_DIR=../mbedtls" + os: linux allow_failures: - env: COVERITY=1 - env: diff --git a/CMakeLists.txt b/CMakeLists.txt index cd32c957aa3..0a2e437b846 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -704,7 +704,7 @@ IF (BUILD_CLAR) ENDIF () ENABLE_TESTING() - IF (WINHTTP OR OPENSSL_FOUND OR SECURITY_FOUND) + IF (WINHTTP OR OPENSSL_FOUND OR SECURITY_FOUND OR MBEDTLS_FOUND) ADD_TEST(libgit2_clar libgit2_clar -ionline) ELSE () ADD_TEST(libgit2_clar libgit2_clar -v) diff --git a/script/cibuild.sh b/script/cibuild.sh index 979eb0ce47a..634fc74b536 100755 --- a/script/cibuild.sh +++ b/script/cibuild.sh @@ -15,6 +15,11 @@ curl -L https://github.com/ethomson/poxyproxy/releases/download/v0.1.0/poxyproxy # Run this early so we know it's ready by the time we need it java -jar poxyproxy.jar -d --port 8080 --credentials foo:bar & +if [ -n "$MBEDTLS" ]; +then + ./script/mbedtls.sh; +fi + mkdir _build cd _build # shellcheck disable=SC2086 diff --git a/script/mbedtls.sh b/script/mbedtls.sh new file mode 100755 index 00000000000..fda7abc6fbc --- /dev/null +++ b/script/mbedtls.sh @@ -0,0 +1,6 @@ +#!/bin/sh + +git clone https://github.com/ARMmbed/mbedtls.git mbedtls +cd mbedtls +git checkout mbedtls-2.1.2 +make CFLAGS='-fPIC -fpic' -j2 lib From 4f8968b682d782704aec913e3e97f1a2579c46d1 Mon Sep 17 00:00:00 2001 From: wildart Date: Tue, 24 May 2016 18:57:40 -0400 Subject: [PATCH 09/16] add mbedtls stream initialization --- src/global.c | 8 ++++++++ src/mbedtls_stream.h | 2 ++ 2 files changed, 10 insertions(+) diff --git a/src/global.c b/src/global.c index eee0aea57c4..18038100c98 100644 --- a/src/global.c +++ b/src/global.c @@ -10,7 +10,11 @@ #include "sysdir.h" #include "filter.h" #include "merge_driver.h" +#ifdef GIT_OPENSSL #include "openssl_stream.h" +#elif GIT_MBEDTLS +#include "mbedtls_stream.h" +#endif #include "thread-utils.h" #include "git2/global.h" #include "transports/ssh.h" @@ -62,7 +66,11 @@ static int init_common(void) (ret = git_filter_global_init()) == 0 && (ret = git_merge_driver_global_init()) == 0 && (ret = git_transport_ssh_global_init()) == 0) +#ifdef GIT_OPENSSL ret = git_openssl_stream_global_init(); +#elif GIT_MBEDTLS + ret = git_mbedtls_stream_global_init(); +#endif GIT_MEMORY_BARRIER; diff --git a/src/mbedtls_stream.h b/src/mbedtls_stream.h index 170b10a2e49..5cb1071d252 100644 --- a/src/mbedtls_stream.h +++ b/src/mbedtls_stream.h @@ -9,6 +9,8 @@ #include "git2/sys/stream.h" +extern int git_mbedtls_stream_global_init(void); + extern int git_mbedtls_stream_new(git_stream **out, const char *host, const char *port); #endif From cc156e4a1228882a93fe4d5b4cef35b34c1f39fb Mon Sep 17 00:00:00 2001 From: wildart Date: Wed, 25 May 2016 00:45:30 -0400 Subject: [PATCH 10/16] update to 0.24.1 --- CMakeLists.txt | 5 +- src/global.h | 1 + src/mbedtls_stream.c | 132 +++++++++++++++++++++++++++++++++++++++---- tests/core/stream.c | 2 +- 4 files changed, 127 insertions(+), 13 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 0a2e437b846..b201cff276b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -110,9 +110,10 @@ ENDIF() IF (HAVE_STRUCT_STAT_NSEC OR WIN32) OPTION( USE_NSEC "Care about sub-second file mtimes and ctimes" ON ) +ENDIF() IF (NOT USE_OPENSSL) - OPTION( USE_MBEDTLS "Link with and use mbedtls library" ON ) + OPTION( USE_MBEDTLS "Link with and use mbedTLS library" ON ) ENDIF() # This variable will contain the libraries we need to put into @@ -286,7 +287,7 @@ ELSE () FIND_PACKAGE(OpenSSL) ENDIF () - IF (NOT AMIGA AND USE_MBEDTLS AND NOT USE_OPENSSL) + IF (NOT AMIGA AND USE_MBEDTLS) FIND_PACKAGE(mbedTLS) ENDIF () diff --git a/src/global.h b/src/global.h index a7ee1d3f98c..adadcd9ee38 100644 --- a/src/global.h +++ b/src/global.h @@ -24,6 +24,7 @@ extern SSL_CTX *git__ssl_ctx; #endif #ifdef GIT_MBEDTLS +# include "mbedtls/platform.h" # include "mbedtls/ssl.h" extern mbedtls_ssl_config *git__ssl_conf; #endif diff --git a/src/mbedtls_stream.c b/src/mbedtls_stream.c index 24b8fda10b6..c5bdb80f683 100644 --- a/src/mbedtls_stream.c +++ b/src/mbedtls_stream.c @@ -18,10 +18,116 @@ # include "curl_stream.h" #endif -#include +#include "mbedtls/config.h" #include #include #include +#include "mbedtls/net.h" +#include "mbedtls/debug.h" +#include "mbedtls/entropy.h" +#include "mbedtls/ctr_drbg.h" +#include "mbedtls/error.h" +#include "mbedtls/certs.h" + +#define CRT_LOC "/etc/ssl/certs" + +mbedtls_ssl_config *git__ssl_conf; +mbedtls_entropy_context *mbedtls_entropy; + +#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" + +/** + * This function aims to clean-up the SSL context which + * we allocated. + */ +static void shutdown_ssl(void) +{ + if (git__ssl_conf) { + mbedtls_x509_crt_free(git__ssl_conf->ca_chain); + git__free(git__ssl_conf->ca_chain); + mbedtls_ctr_drbg_free(git__ssl_conf->p_rng); + git__free(git__ssl_conf->p_rng); + mbedtls_ssl_config_free(git__ssl_conf); + git__free(git__ssl_conf); + git__ssl_conf = NULL; + } + if (mbedtls_entropy) { + mbedtls_entropy_free(mbedtls_entropy); + git__free(mbedtls_entropy); + mbedtls_entropy = NULL; + } +} + +int git_mbedtls_stream_global_init(void) +{ + int ret; + // const int *cipherids; + // const char *ciphers = git_libgit2__ssl_ciphers(); + + mbedtls_ctr_drbg_context *ctr_drbg; + mbedtls_x509_crt *cacert; + + mbedtls_entropy = git__malloc(sizeof(mbedtls_entropy_context)); + mbedtls_entropy_init(mbedtls_entropy); + + // Seeding the random number generator + ctr_drbg = git__malloc(sizeof(mbedtls_ctr_drbg_context)); + mbedtls_ctr_drbg_init(ctr_drbg); + if (mbedtls_ctr_drbg_seed(ctr_drbg, + mbedtls_entropy_func, + mbedtls_entropy, NULL, 0) != 0) { + mbedtls_ctr_drbg_free(ctr_drbg); + mbedtls_entropy_free(mbedtls_entropy); + git__free(ctr_drbg); + git__free(mbedtls_entropy); + return -1; + } + + // configure TLSv1 + git__ssl_conf = git__malloc(sizeof(mbedtls_ssl_config)); + mbedtls_ssl_config_init(git__ssl_conf); + if ( mbedtls_ssl_config_defaults(git__ssl_conf, + MBEDTLS_SSL_IS_CLIENT, + MBEDTLS_SSL_TRANSPORT_STREAM, + MBEDTLS_SSL_PRESET_DEFAULT ) != 0) { + mbedtls_ctr_drbg_free(ctr_drbg); + git__free(ctr_drbg); + mbedtls_ssl_config_free(git__ssl_conf); + git__free(git__ssl_conf); + git__ssl_conf = NULL; + return -1; + } + + mbedtls_ssl_conf_authmode(git__ssl_conf, MBEDTLS_SSL_VERIFY_REQUIRED); + mbedtls_ssl_conf_rng(git__ssl_conf, mbedtls_ctr_drbg_random, ctr_drbg); + + // set the list of allowed ciphersuites + // if (!ciphers) { + // cipherids = mbedtls_ssl_list_ciphersuites(); + // } + // mbedtls_ssl_conf_ciphersuites(git__ssl_conf, cipherids); + + // set root certificates + cacert = git__malloc(sizeof(mbedtls_x509_crt)); + mbedtls_x509_crt_init(cacert); + ret = mbedtls_x509_crt_parse_path(cacert, CRT_LOC); + if (ret) { + giterr_set(GITERR_SSL, "failed to load CA certificates: %d", ret); + mbedtls_x509_crt_free(cacert); + git__free(cacert); + mbedtls_ctr_drbg_free(ctr_drbg); + git__free(ctr_drbg); + mbedtls_ssl_config_free(git__ssl_conf); + git__free(git__ssl_conf); + git__ssl_conf = NULL; + } else { + mbedtls_ssl_conf_ca_chain(git__ssl_conf, cacert, NULL); + } + + git__on_shutdown(shutdown_ssl); + + return 0; +} static int bio_read(void *b, unsigned char *buf, size_t len) { @@ -218,7 +324,7 @@ static int mbedtls_set_proxy(git_stream *stream, const char *proxy_url) return git_stream_set_proxy(st->io, proxy_url); } -ssize_t mbedtls_write(git_stream *stream, const char *data, size_t len, int flags) +ssize_t mbedtls_stream_write(git_stream *stream, const char *data, size_t len, int flags) { mbedtls_stream *st = (mbedtls_stream *) stream; int ret; @@ -232,7 +338,7 @@ ssize_t mbedtls_write(git_stream *stream, const char *data, size_t len, int flag return ret; } -ssize_t mbedtls_read(git_stream *stream, void *data, size_t len) +ssize_t mbedtls_stream_read(git_stream *stream, void *data, size_t len) { mbedtls_stream *st = (mbedtls_stream *) stream; int ret; @@ -243,7 +349,7 @@ ssize_t mbedtls_read(git_stream *stream, void *data, size_t len) return ret; } -int mbedtls_close(git_stream *stream) +int mbedtls_stream_close(git_stream *stream) { mbedtls_stream *st = (mbedtls_stream *) stream; int ret = 0; @@ -256,7 +362,7 @@ int mbedtls_close(git_stream *stream) return git_stream_close(st->io); } -void mbedtls_free(git_stream *stream) +void mbedtls_stream_free(git_stream *stream) { mbedtls_stream *st = (mbedtls_stream *) stream; @@ -302,10 +408,10 @@ int git_mbedtls_stream_new(git_stream **out, const char *host, const char *port) st->parent.connect = mbedtls_connect; st->parent.certificate = mbedtls_certificate; st->parent.set_proxy = mbedtls_set_proxy; - st->parent.read = mbedtls_read; - st->parent.write = mbedtls_write; - st->parent.close = mbedtls_close; - st->parent.free = mbedtls_free; + st->parent.read = mbedtls_stream_read; + st->parent.write = mbedtls_stream_write; + st->parent.close = mbedtls_stream_close; + st->parent.free = mbedtls_stream_free; *out = (git_stream *) st; return 0; @@ -314,6 +420,12 @@ int git_mbedtls_stream_new(git_stream **out, const char *host, const char *port) #else #include "stream.h" +#include "git2/sys/openssl.h" + +int git_mbedtls_stream_global_init(void) +{ + return 0; +} int git_mbedtls_stream_new(git_stream **out, const char *host, const char *port) { @@ -321,7 +433,7 @@ int git_mbedtls_stream_new(git_stream **out, const char *host, const char *port) GIT_UNUSED(host); GIT_UNUSED(port); - giterr_set(GITERR_SSL, "mbedtls is not supported in this version"); + giterr_set(GITERR_SSL, "mbedTLS is not supported in this version"); return -1; } diff --git a/tests/core/stream.c b/tests/core/stream.c index 0cbf442304e..a4fa2b447c0 100644 --- a/tests/core/stream.c +++ b/tests/core/stream.c @@ -38,7 +38,7 @@ void test_core_stream__register_tls(void) * with Security framework). */ #if defined(GIT_WIN32) || \ - (!defined(GIT_SECURE_TRANSPORT) && !defined(GIT_OPENSSL)) + (!defined(GIT_SECURE_TRANSPORT) && !(defined(GIT_OPENSSL) || defined(GIT_MBEDTLS))) cl_git_fail_with(-1, error); #else cl_git_pass(error); From f814681ad7aff3c9948dbae6719cb40c96b0eaea Mon Sep 17 00:00:00 2001 From: wildart Date: Wed, 25 May 2016 03:06:21 -0400 Subject: [PATCH 11/16] turned on https feature for mbedtls --- src/settings.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/settings.c b/src/settings.c index 1818d9ad0bb..69b54718d77 100644 --- a/src/settings.c +++ b/src/settings.c @@ -33,7 +33,7 @@ int git_libgit2_features(void) #ifdef GIT_THREADS | GIT_FEATURE_THREADS #endif -#if defined(GIT_OPENSSL) || defined(GIT_WINHTTP) || defined(GIT_SECURE_TRANSPORT) +#if defined(GIT_OPENSSL) || defined(GIT_WINHTTP) || defined(GIT_SECURE_TRANSPORT) || defined(GIT_MBEDTLS) | GIT_FEATURE_HTTPS #endif #if defined(GIT_SSH) From 6b556a62ee102115ebc916612442f4e5948d689f Mon Sep 17 00:00:00 2001 From: wildart Date: Thu, 26 May 2016 23:13:48 -0400 Subject: [PATCH 12/16] better search for CA certificates: using EVs and build-time macros reload properly certificates in libgit2_options --- src/mbedtls_stream.c | 74 ++++++++++++++++++++++++++++++++++---------- src/settings.c | 21 +++++++++---- 2 files changed, 73 insertions(+), 22 deletions(-) diff --git a/src/mbedtls_stream.c b/src/mbedtls_stream.c index c5bdb80f683..98ff808ce08 100644 --- a/src/mbedtls_stream.c +++ b/src/mbedtls_stream.c @@ -29,7 +29,13 @@ #include "mbedtls/error.h" #include "mbedtls/certs.h" -#define CRT_LOC "/etc/ssl/certs" +#ifndef OPENSSLDIR +# define OPENSSLDIR "/usr/lib/ssl" +#endif +#define X509_CERT_DIR OPENSSLDIR "/certs" +#define X509_CERT_FILE OPENSSLDIR "/cert.pem" +#define X509_CERT_DIR_EVP "SSL_CERT_DIR" +#define X509_CERT_FILE_EVP "SSL_CERT_FILE" mbedtls_ssl_config *git__ssl_conf; mbedtls_entropy_context *mbedtls_entropy; @@ -60,12 +66,13 @@ static void shutdown_ssl(void) int git_mbedtls_stream_global_init(void) { - int ret; + int ret, isdir; + char *crtpath; + struct stat statbuf; // const int *cipherids; // const char *ciphers = git_libgit2__ssl_ciphers(); mbedtls_ctr_drbg_context *ctr_drbg; - mbedtls_x509_crt *cacert; mbedtls_entropy = git__malloc(sizeof(mbedtls_entropy_context)); mbedtls_entropy_init(mbedtls_entropy); @@ -101,29 +108,64 @@ int git_mbedtls_stream_global_init(void) mbedtls_ssl_conf_authmode(git__ssl_conf, MBEDTLS_SSL_VERIFY_REQUIRED); mbedtls_ssl_conf_rng(git__ssl_conf, mbedtls_ctr_drbg_random, ctr_drbg); - // set the list of allowed ciphersuites - // if (!ciphers) { - // cipherids = mbedtls_ssl_list_ciphersuites(); - // } - // mbedtls_ssl_conf_ciphersuites(git__ssl_conf, cipherids); + // find locations for which CA certificates + isdir = 0; + crtpath = getenv(X509_CERT_FILE_EVP); + ret = crtpath != NULL && stat(crtpath, &statbuf) == 0 && S_ISREG(statbuf.st_mode) ? 0 : 1; + if (ret) { + isdir = 1; + crtpath = getenv(X509_CERT_DIR_EVP); + ret = crtpath != NULL && stat(crtpath, &statbuf) == 0 && S_ISDIR(statbuf.st_mode) ? 0 : 1; + } + if (ret) { + isdir = 0; + crtpath = X509_CERT_FILE; + ret = crtpath != NULL && stat(crtpath, &statbuf) == 0 && S_ISREG(statbuf.st_mode) ? 0 : 1; + } + if (ret) { + isdir = 1; + crtpath = X509_CERT_DIR; + ret = crtpath != NULL && stat(crtpath, &statbuf) == 0 && S_ISDIR(statbuf.st_mode) ? 0 : 1; + } - // set root certificates - cacert = git__malloc(sizeof(mbedtls_x509_crt)); - mbedtls_x509_crt_init(cacert); - ret = mbedtls_x509_crt_parse_path(cacert, CRT_LOC); + // cannot find CA certificates if (ret) { - giterr_set(GITERR_SSL, "failed to load CA certificates: %d", ret); - mbedtls_x509_crt_free(cacert); - git__free(cacert); mbedtls_ctr_drbg_free(ctr_drbg); git__free(ctr_drbg); mbedtls_ssl_config_free(git__ssl_conf); git__free(git__ssl_conf); git__ssl_conf = NULL; + return -1; } else { - mbedtls_ssl_conf_ca_chain(git__ssl_conf, cacert, NULL); + // set root certificates + mbedtls_x509_crt *cacert = git__malloc(sizeof(mbedtls_x509_crt)); + mbedtls_x509_crt_init(cacert); + if (isdir) + ret = mbedtls_x509_crt_parse_path(cacert, crtpath); + else + ret = mbedtls_x509_crt_parse_file(cacert, crtpath); + + if (ret) { + giterr_set(GITERR_SSL, "failed to load CA certificates: %d", ret); + mbedtls_x509_crt_free(cacert); + git__free(cacert); + mbedtls_ctr_drbg_free(ctr_drbg); + git__free(ctr_drbg); + mbedtls_ssl_config_free(git__ssl_conf); + git__free(git__ssl_conf); + git__ssl_conf = NULL; + return -1; + } else { + mbedtls_ssl_conf_ca_chain(git__ssl_conf, cacert, NULL); + } } + // set the list of allowed ciphersuites + // if (!ciphers) { + // cipherids = mbedtls_ssl_list_ciphersuites(); + // } + // mbedtls_ssl_conf_ciphersuites(git__ssl_conf, cipherids); + git__on_shutdown(shutdown_ssl); return 0; diff --git a/src/settings.c b/src/settings.c index 69b54718d77..9ebcd78d0d5 100644 --- a/src/settings.c +++ b/src/settings.c @@ -184,15 +184,24 @@ int git_libgit2_opts(int key, ...) const char *path = va_arg(ap, const char *); int ret = 0; char errbuf[512]; - if (!file) { - ret = mbedtls_x509_crt_parse_file(git__ssl_conf->ca_chain, file); - } else if (!path) { - ret = mbedtls_x509_crt_parse_path(git__ssl_conf->ca_chain, path); + mbedtls_x509_crt *cacert; + cacert = git__malloc(sizeof(mbedtls_x509_crt)); + mbedtls_x509_crt_init(cacert); + if (file) { + ret = mbedtls_x509_crt_parse_file(cacert, file); + } else if (path) { + ret = mbedtls_x509_crt_parse_path(cacert, path); } - if (ret != 0) { + if (!ret) { + mbedtls_x509_crt_free(cacert); + git__free(cacert); mbedtls_strerror( ret, errbuf, 512 ); - giterr_set(GITERR_NET, "SSL error: %d - %s", ret, errbuf); + giterr_set(GITERR_SSL, "SSL error: failed to load CA certificates : %s (%d)", ret, errbuf); error = -1; + } else { + mbedtls_x509_crt_free(git__ssl_conf->ca_chain); + git__free(git__ssl_conf->ca_chain); + mbedtls_ssl_conf_ca_chain(git__ssl_conf, cacert, NULL); } } #else From 05ca19a268f383c5e003e7ec7ea9936642d06d8e Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Sat, 24 Sep 2016 23:32:02 -0700 Subject: [PATCH 13/16] Update for current libgit2 API with struct git_proxy_options --- src/mbedtls_stream.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mbedtls_stream.c b/src/mbedtls_stream.c index 98ff808ce08..a9ff2ef5a1e 100644 --- a/src/mbedtls_stream.c +++ b/src/mbedtls_stream.c @@ -359,11 +359,11 @@ int mbedtls_certificate(git_cert **out, git_stream *stream) return 0; } -static int mbedtls_set_proxy(git_stream *stream, const char *proxy_url) +static int mbedtls_set_proxy(git_stream *stream, const git_proxy_options *proxy_options) { mbedtls_stream *st = (mbedtls_stream *) stream; - return git_stream_set_proxy(st->io, proxy_url); + return git_stream_set_proxy(st->io, proxy_options); } ssize_t mbedtls_stream_write(git_stream *stream, const char *data, size_t len, int flags) From 77cdc581c2a675bc3162479f5596e57d9c1ca13a Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Sat, 24 Sep 2016 23:56:37 -0700 Subject: [PATCH 14/16] Cleanups for mbedTLS changes Separated for review; squash before merging. - Undo unrelated whitespace changes - Fix indentation - Remove commented-out code - Simplify preprocessor conditionals --- CMakeLists.txt | 4 ++-- src/mbedtls_stream.c | 9 --------- src/tls_stream.c | 2 +- tests/core/stream.c | 2 +- 4 files changed, 4 insertions(+), 13 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4451d093c64..deffc094b87 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -88,7 +88,7 @@ IF(MSVC) ENDIF() IF (NOT ${CMAKE_SYSTEM_NAME} MATCHES "Darwin") - OPTION( USE_OPENSSL "Link with and use openssl library" ON ) + OPTION( USE_OPENSSL "Link with and use openssl library" ON ) ENDIF() CHECK_STRUCT_HAS_MEMBER ("struct stat" st_mtim "sys/types.h;sys/stat.h" @@ -109,7 +109,7 @@ ELSE () ENDIF() IF (HAVE_STRUCT_STAT_NSEC OR WIN32) - OPTION( USE_NSEC "Care about sub-second file mtimes and ctimes" ON ) + OPTION( USE_NSEC "Care about sub-second file mtimes and ctimes" ON ) ENDIF() IF (NOT USE_OPENSSL) diff --git a/src/mbedtls_stream.c b/src/mbedtls_stream.c index a9ff2ef5a1e..5c60c59c2a2 100644 --- a/src/mbedtls_stream.c +++ b/src/mbedtls_stream.c @@ -69,8 +69,6 @@ int git_mbedtls_stream_global_init(void) int ret, isdir; char *crtpath; struct stat statbuf; - // const int *cipherids; - // const char *ciphers = git_libgit2__ssl_ciphers(); mbedtls_ctr_drbg_context *ctr_drbg; @@ -160,12 +158,6 @@ int git_mbedtls_stream_global_init(void) } } - // set the list of allowed ciphersuites - // if (!ciphers) { - // cipherids = mbedtls_ssl_list_ciphersuites(); - // } - // mbedtls_ssl_conf_ciphersuites(git__ssl_conf, cipherids); - git__on_shutdown(shutdown_ssl); return 0; @@ -480,4 +472,3 @@ int git_mbedtls_stream_new(git_stream **out, const char *host, const char *port) } #endif - diff --git a/src/tls_stream.c b/src/tls_stream.c index 6fb538f499e..e129f8fb0fe 100644 --- a/src/tls_stream.c +++ b/src/tls_stream.c @@ -32,7 +32,7 @@ int git_tls_stream_new(git_stream **out, const char *host, const char *port) #elif defined(GIT_OPENSSL) return git_openssl_stream_new(out, host, port); #elif defined(GIT_MBEDTLS) - return git_mbedtls_stream_new(out, host, port); + return git_mbedtls_stream_new(out, host, port); #else GIT_UNUSED(out); GIT_UNUSED(host); diff --git a/tests/core/stream.c b/tests/core/stream.c index a4fa2b447c0..aca0719e0f9 100644 --- a/tests/core/stream.c +++ b/tests/core/stream.c @@ -38,7 +38,7 @@ void test_core_stream__register_tls(void) * with Security framework). */ #if defined(GIT_WIN32) || \ - (!defined(GIT_SECURE_TRANSPORT) && !(defined(GIT_OPENSSL) || defined(GIT_MBEDTLS))) + (!defined(GIT_SECURE_TRANSPORT) && !defined(GIT_OPENSSL) && !defined(GIT_MBEDTLS)) cl_git_fail_with(-1, error); #else cl_git_pass(error); From dab8d43de7edf2b93f573a48c888ab2678a02497 Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Sun, 25 Sep 2016 01:00:44 -0700 Subject: [PATCH 15/16] mbedtls: Fix travis build --- .travis.yml | 4 ++-- script/cibuild.sh | 3 +++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 0ef35b673b8..dcbadf2cc72 100644 --- a/.travis.yml +++ b/.travis.yml @@ -48,12 +48,12 @@ matrix: - compiler: gcc env: - MBEDTLS=1 - OPTIONS="-DTHREADSAFE=ON -DCMAKE_BUILD_TYPE=Release -DUSE_OPENSSL=OFF -DMBEDTLS_ROOT_DIR=../mbedtls" + OPTIONS="-DTHREADSAFE=ON -DCMAKE_BUILD_TYPE=Release -DUSE_OPENSSL=OFF -DUSE_MBEDTLS=ON" os: linux - compiler: gcc env: - MBEDTLS=1 - OPTIONS="-DTHREADSAFE=OFF -DBUILD_EXAMPLES=ON -DUSE_OPENSSL=OFF -DMBEDTLS_ROOT_DIR=../mbedtls" + OPTIONS="-DTHREADSAFE=OFF -DBUILD_EXAMPLES=ON -DUSE_OPENSSL=OFF -DUSE_MBEDTLS=ON" os: linux allow_failures: - env: COVERITY=1 diff --git a/script/cibuild.sh b/script/cibuild.sh index 634fc74b536..ecf854942a2 100755 --- a/script/cibuild.sh +++ b/script/cibuild.sh @@ -18,6 +18,9 @@ java -jar poxyproxy.jar -d --port 8080 --credentials foo:bar & if [ -n "$MBEDTLS" ]; then ./script/mbedtls.sh; + CMAKE_INCLUDE_PATH=../mbedtls/include + CMAKE_LIBRARY_PATH=../mbedtls/library + export CMAKE_INCLUDE_PATH CMAKE_LIBRARY_PATH fi mkdir _build From 81555f5de02d064921018647c4156257a8df748c Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Sun, 25 Sep 2016 11:29:00 -0700 Subject: [PATCH 16/16] Move USE_MBEDTLS option under not-Darwin condition Otherwise, Darwin systems would attempt to build with both their native crypto and mbedTLS. --- CMakeLists.txt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index deffc094b87..2e21099620f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -89,8 +89,12 @@ ENDIF() IF (NOT ${CMAKE_SYSTEM_NAME} MATCHES "Darwin") OPTION( USE_OPENSSL "Link with and use openssl library" ON ) + IF (NOT USE_OPENSSL) + OPTION(USE_MBEDTLS "Link with and use mbedTLS library" ON) + ENDIF() ENDIF() + CHECK_STRUCT_HAS_MEMBER ("struct stat" st_mtim "sys/types.h;sys/stat.h" HAVE_STRUCT_STAT_ST_MTIM LANGUAGE C) CHECK_STRUCT_HAS_MEMBER ("struct stat" st_mtimespec "sys/types.h;sys/stat.h" @@ -112,10 +116,6 @@ IF (HAVE_STRUCT_STAT_NSEC OR WIN32) OPTION( USE_NSEC "Care about sub-second file mtimes and ctimes" ON ) ENDIF() -IF (NOT USE_OPENSSL) - OPTION( USE_MBEDTLS "Link with and use mbedTLS library" ON ) -ENDIF() - # This variable will contain the libraries we need to put into # libgit2.pc's Requires.private. That is, what we're linking to or # what someone who's statically linking us needs to link to.