Hi, I ported libressl to my custom hobby OS and it has been a pleasant experience. Nonetheless, I did run into some minor portability problems that I wish to share:
* apps/Makefile.am.tpl links libcrypto and libssl in the wrong order. The libssl library depends on libcrypto and libcrypto doesn't depend on libssl. Linking the openssl program as -lcrypto -lssl breaks on static linking if the main program didn't pull in parts of libcrypto that libssl needs. * The POSIX <sys/select.h> header is not used to get the select function. While <sys/time.h> is required to also provide it (though that seems transitional to me), there is no requirement <sys/time.h> also provide the FD_* macros needed to actually use select. This inclusion needs to be added in apps/ocsp.c, apps/s_client.c, apps/s_server.c and apps/s_time.c. * ioctl(FIONBIO) is used in a few files to make sockets non-blocking rather than using fcntl to set the the standard O_NONBLOCK bit. The files apps/s_client.c and apps/s_server.c should use BIO_socket_nbio() instead of directly using BIO_socket_ioctl(). The bio/b_sock.c file should implement BIO_shock_nbio() using fcntl, F_GETFL/F_SETFL and O_NONBLOCK. * include/machine/endian.h wraps the <endian.h> header if Linux and the <machine/endian.h> header if non-Linux. However, it may be the case that a non-Linux system (such as mine) has <endian.h> and not <machine/endian.h>. The POSIX committee has accepted <endian.h> into the next revision of POSIX. guenther recently implemented this draft in OpenBSD and the header is already present on many modern Unix systems. It would be better if the compatibility layer instead implement <endian.h> rather than <machine/endian.h>. * The build system defaults --program-transform-name to the host triplet when cross-compiling. It shouldn't do that as the library doesn't have a target and is not a cross-compiler (as far as I know). It certainly doesn't make sense to do when the library itself is being cross-compiled. This also caused unexpected trouble during the man page installation as the real man pages got installed under the transformed name, but the hard links to the man pages wasn't transformed and broke the build. * The non-standard err(3) family is used a few places. In the main library it is only used in the apps/openssl.c file, while it is used a few times in the regression tests. The convenience of using these functions is not worth the portability concerns when the calling code can easily use fprintf and exit instead. * The configure.ac file doesn't check if explicit_bzero is provided by the operating system but unconditionally uses the internal one. I also have a list of minor portability issues I don't mind patching locally and other stray suggestions: * crypto/compat/issetugid_linux.c is used on non-Linux platforms. This fail on including glibc internal headers which is hardly elegant. Perhaps another file should be used for unknown operating systems that assumes the worst and throws a #warning? It could also be handled like getentropy where it fails with linker errors. * ssl/d1_lib.c includes the non-standard header <sys/param.h>. It worked when I removed the inclusion, so it seems redundant. * The non-standard u_char and u_int types are used a few places in the random compatibility code. It would work just as well if those were replaced with explicit unsigned char and unsigned int types. * Consider using _DEFAULT_SOURCE or _ALL_SOURCE as feature macros on unknown platforms. * My strerror() (when certain feature macros are defined) return a const char* as it would be an error to modify the storage. This triggered on a strerror() invocation in crypto/err/err.c where it stores the result in a char * rather than a safe const char *. * There should be an explicit counterpart of memset called explicit_memset. My libc has such a function, but no explicit_bzero as I have no regular bzero. If an explicit_memset is added (or detected in the host system), it could be used in the compatibility implementation of explicit_bzero (which is currently implemented by calling memset). I would much prefer if the library uses a safe zeroing function from the standard library (rather than its own) as that would give the standard library a chance to be better: I'm quite interested in using new compiler extensions to robustly ensure memory is cleared even in the face of link-time optimization and sufficiently advanced compilers. I don't have absolute confidence that the weak symbol trick used in explicit_bzero.c is good enough. * The timingsafe_bcmp function could be implemented using timingsafe_memcmp for the same reasons. * The compatibility wrapper headers doesn't check whether the standard library already provides prototypes. The #include_next mechanism is a good solution, but duplicate function prototypes would happen if the standard library happens to provide the extensions. Though, I think that should be harmless, I don't know how that interacts with __attribute__'s used in the system headers, if they are implemented as macros, or any other imaginable situation. * The <sys/stat.h> and <sys/time.h> inclusions in include/stdlib.h seems redundant. * The <sys/types.h> inclusion in string.h seems redundant, size_t is always provided by <string.h>. * The header inclusion guard macro in include/machine/endian.h is _COMPAT_BYTE_ORDER_H_ (in the reserved namespace) while the other headers use the macro LIBCRYPTOCOMPAT_FOO_H. * The <stdint.h> inclusion in include/sys/types.h seems like a non-standard extension. Files relying on <sys/types.h> pulling in <stdint.h> should be rewritten to include <stdint.h> explicitly. Below you'll find the reasonably-finished parts of my local patch that solves some of the above issues. Thanks, Jonas 'Sortie' Termansen diff -Nur libressl-2.0.2/apps/Makefile.am libssl/apps/Makefile.am --- libressl-2.0.2/apps/Makefile.am 2014-07-16 05:25:52.000000000 +0200 +++ libssl/apps/Makefile.am 2014-07-16 13:26:55.425448073 +0200 @@ -4,8 +4,8 @@ openssl_CFLAGS = $(USER_CFLAGS) openssl_LDADD = $(PLATFORM_LDADD) -openssl_LDADD += $(top_builddir)/crypto/libcrypto.la openssl_LDADD += $(top_builddir)/ssl/libssl.la +openssl_LDADD += $(top_builddir)/crypto/libcrypto.la openssl_SOURCES = noinst_HEADERS = diff -Nur libressl-2.0.2/apps/ocsp.c libssl/apps/ocsp.c --- libressl-2.0.2/apps/ocsp.c 2014-07-16 05:25:50.000000000 +0200 +++ libssl/apps/ocsp.c 2014-07-16 13:26:55.429448073 +0200 @@ -57,6 +57,8 @@ */ #ifndef OPENSSL_NO_OCSP +#include <sys/select.h> + #include <stdio.h> #include <stdlib.h> #include <limits.h> diff -Nur libressl-2.0.2/apps/openssl.c libssl/apps/openssl.c --- libressl-2.0.2/apps/openssl.c 2014-07-16 05:25:50.000000000 +0200 +++ libssl/apps/openssl.c 2014-07-16 13:26:55.429448073 +0200 @@ -109,7 +109,6 @@ * */ -#include <err.h> #include <signal.h> #include <stdio.h> #include <string.h> @@ -256,8 +255,10 @@ arg.count = 0; bio_err = BIO_new_fp(stderr, BIO_NOCLOSE); - if (bio_err == NULL) - errx(1, "failed to initialise bio_err"); + if (bio_err == NULL) { + fprintf(stderr, "%s: failed to initialize bio_err\n", argv[0]); + exit(1); + } CRYPTO_set_locking_callback(lock_dbg_cb); diff -Nur libressl-2.0.2/apps/s_client.c libssl/apps/s_client.c --- libressl-2.0.2/apps/s_client.c 2014-07-16 05:25:50.000000000 +0200 +++ libssl/apps/s_client.c 2014-07-16 13:26:55.429448073 +0200 @@ -137,6 +137,7 @@ #include <sys/types.h> #include <sys/ioctl.h> +#include <sys/select.h> #include <sys/socket.h> #include <netinet/in.h> @@ -830,9 +831,8 @@ BIO_printf(bio_c_out, "CONNECTED(%08X)\n", s); if (c_nbio) { - unsigned long l = 1; BIO_printf(bio_c_out, "turning on non blocking io\n"); - if (BIO_socket_ioctl(s, FIONBIO, &l) < 0) { + if (BIO_socket_nbio(s, 1) < 0) { ERR_print_errors(bio_err); goto end; } diff -Nur libressl-2.0.2/apps/s_server.c libssl/apps/s_server.c --- libressl-2.0.2/apps/s_server.c 2014-07-16 05:25:50.000000000 +0200 +++ libssl/apps/s_server.c 2014-07-16 13:26:55.429448073 +0200 @@ -148,6 +148,7 @@ #include <sys/types.h> #include <sys/ioctl.h> +#include <sys/select.h> #include <sys/socket.h> #include <assert.h> @@ -1363,11 +1364,9 @@ goto err; } if (s_nbio) { - unsigned long sl = 1; - if (!s_quiet) BIO_printf(bio_err, "turning on non blocking io\n"); - if (BIO_socket_ioctl(s, FIONBIO, &sl) < 0) + if (!BIO_socket_nbio(s, 1)) ERR_print_errors(bio_err); } @@ -1798,11 +1797,9 @@ goto err; if (s_nbio) { - unsigned long sl = 1; - if (!s_quiet) BIO_printf(bio_err, "turning on non blocking io\n"); - if (BIO_socket_ioctl(s, FIONBIO, &sl) < 0) + if (!BIO_socket_nbio(s, 1)) ERR_print_errors(bio_err); } diff -Nur libressl-2.0.2/apps/s_time.c libssl/apps/s_time.c --- libressl-2.0.2/apps/s_time.c 2014-07-16 05:25:50.000000000 +0200 +++ libssl/apps/s_time.c 2014-07-16 13:26:55.433448073 +0200 @@ -64,6 +64,7 @@ -----------------------------------------*/ #include <sys/socket.h> +#include <sys/select.h> #include <stdio.h> #include <stdlib.h> diff -Nur libressl-2.0.2/configure.ac libssl/configure.ac --- libressl-2.0.2/configure.ac 2014-07-16 05:25:48.000000000 +0200 +++ libssl/configure.ac 2014-07-16 05:25:48.000000000 +0200 @@ -25,7 +25,9 @@ *openbsd*) AC_DEFINE([HAVE_ATTRIBUTE__BOUNDED__], [1], [OpenBSD gcc has bounded]) ;; - *) ;; + *) + CFLAGS="$CFLAGS -D_ALL_SOURCE" + ;; esac AM_CONDITIONAL(TARGET_DARWIN, test x$TARGET_OS = xdarwin) diff -Nur libressl-2.0.2/crypto/bio/b_sock.c libssl/crypto/bio/b_sock.c --- libressl-2.0.2/crypto/bio/b_sock.c 2014-07-16 05:25:49.000000000 +0200 +++ libssl/crypto/bio/b_sock.c 2014-07-16 13:26:55.437448072 +0200 @@ -65,6 +65,7 @@ #include <netinet/tcp.h> #include <errno.h> +#include <fcntl.h> #include <limits.h> #include <netdb.h> #include <stdio.h> @@ -462,5 +463,10 @@ int BIO_socket_nbio(int s, int mode) { - return (BIO_socket_ioctl(s, FIONBIO, &mode) == 0); + int flags = fcntl(s, F_GETFD); + if ( mode && !(flags & O_NONBLOCK) ) + return (fcntl(s, F_SETFL, flags | O_NONBLOCK) == 0); + else if ( !mode && (flags & O_NONBLOCK) ) + return (fcntl(s, F_SETFL, flags & ~O_NONBLOCK) == 0); + return 1; } diff -Nur libressl-2.0.2/crypto/err/err.c libssl/crypto/err/err.c --- libressl-2.0.2/crypto/err/err.c 2014-07-16 05:25:49.000000000 +0200 +++ libssl/crypto/err/err.c 2014-07-16 13:26:55.437448072 +0200 @@ -596,7 +596,7 @@ if (str->string == NULL) { char (*dest)[LEN_SYS_STR_REASON] = &(strerror_tab[i - 1]); - char *src = strerror(i); + const char *src = strerror(i); if (src != NULL) { strlcpy(*dest, src, sizeof *dest); str->string = *dest; diff -Nur libressl-2.0.2/ssl/d1_lib.c libssl/ssl/d1_lib.c --- libressl-2.0.2/ssl/d1_lib.c 2014-07-16 05:25:48.000000000 +0200 +++ libssl/ssl/d1_lib.c 2014-07-16 13:26:55.441448071 +0200 @@ -57,7 +57,6 @@ * */ -#include <sys/param.h> #include <sys/socket.h> #include <netinet/in.h>