From ec6848bc68497924e9fc9ce8881742eba4e842d5 Mon Sep 17 00:00:00 2001 From: beck Date: Fri, 11 Nov 2022 11:25:18 +0000 Subject: [PATCH] Add support for symbol hiding disabled by default. Fully explained in libcrypto/README. TL;DR make sure libcrypto and libssl's function calls internally and to each other are via symbol names that won't get overridden by linking other libraries. Mostly work by guenther@, which will currently be gated behind a build setting NAMESPACE=yes. once we convert all the symbols to this method we will do a major bump and pick up the changes. ok tb@ jsing@ --- lib/libcrypto/Makefile | 17 ++++++++-- lib/libcrypto/Symbols.namespace | 9 +++++ lib/libcrypto/hidden/README | 40 ++++++++++++++++++++++ lib/libcrypto/hidden/crypto_namespace.h | 44 +++++++++++++++++++++++++ lib/libcrypto/hidden/openssl/hmac.h | 36 ++++++++++++++++++++ lib/libcrypto/hmac/hmac.c | 11 ++++++- lib/libssl/Makefile | 7 +++- lib/libssl/bio_ssl.c | 5 ++- lib/libssl/hidden/openssl/ssl.h | 31 +++++++++++++++++ lib/libssl/hidden/ssl_namespace.h | 37 +++++++++++++++++++++ 10 files changed, 232 insertions(+), 5 deletions(-) create mode 100644 lib/libcrypto/Symbols.namespace create mode 100644 lib/libcrypto/hidden/README create mode 100644 lib/libcrypto/hidden/crypto_namespace.h create mode 100644 lib/libcrypto/hidden/openssl/hmac.h create mode 100644 lib/libssl/hidden/openssl/ssl.h create mode 100644 lib/libssl/hidden/ssl_namespace.h diff --git a/lib/libcrypto/Makefile b/lib/libcrypto/Makefile index ffcdc7dabb9..3f5342a72fe 100644 --- a/lib/libcrypto/Makefile +++ b/lib/libcrypto/Makefile @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile,v 1.87 2022/11/10 17:53:45 joshua Exp $ +# $OpenBSD: Makefile,v 1.88 2022/11/11 11:25:18 beck Exp $ LIB= crypto LIBREBUILD=y @@ -19,6 +19,10 @@ CFLAGS+= -Wall -Wundef CFLAGS+= -Werror .endif CFLAGS+= -DLIBRESSL_INTERNAL -DLIBRESSL_CRYPTO_INTERNAL +.ifdef NAMESPACE +CFLAGS+= -DLIBRESSL_NAMESPACE -DLIBRESSL_CRYPTO_NAMESPACE +.endif + .if !defined(NOPIC) CFLAGS+= -DDSO_DLFCN -DHAVE_DLFCN_H -DHAVE_FUNOPEN @@ -40,6 +44,7 @@ CFLAGS+= -I${LCRYPTO_SRC}/ec CFLAGS+= -I${LCRYPTO_SRC}/ecdh CFLAGS+= -I${LCRYPTO_SRC}/ecdsa CFLAGS+= -I${LCRYPTO_SRC}/evp +CFLAGS+= -I${LCRYPTO_SRC}/hidden CFLAGS+= -I${LCRYPTO_SRC}/hmac CFLAGS+= -I${LCRYPTO_SRC}/kdf CFLAGS+= -I${LCRYPTO_SRC}/modes @@ -51,6 +56,7 @@ CFLAGS+= -I${LCRYPTO_SRC}/x509 VERSION_SCRIPT= Symbols.map SYMBOL_LIST= ${.CURDIR}/Symbols.list +SYMBOL_NAMESPACE= ${.CURDIR}/Symbols.namespace # crypto/ SRCS+= cpt_err.c @@ -875,11 +881,18 @@ includes: prereq echo $$j; \ eval "$$j"; \ done; - +.ifdef NAMESPACE +${VERSION_SCRIPT}: ${SYMBOL_LIST} ${SYMBOL_NAMESPACE} + { printf '{\n\tglobal:\n'; \ + sed '/^[._a-zA-Z]/s/$$/;/; s/^/ /' ${SYMBOL_NAMESPACE}; \ + sed '/^[._a-zA-Z]/s/$$/;/; s/^/ /' ${SYMBOL_LIST}; \ + printf '\n\tlocal:\n\t\t*;\n};\n'; } >$@.tmp && mv $@.tmp $@ +.else ${VERSION_SCRIPT}: ${SYMBOL_LIST} { printf '{\n\tglobal:\n'; \ sed '/^[._a-zA-Z]/s/$$/;/; s/^/ /' ${SYMBOL_LIST}; \ printf '\n\tlocal:\n\t\t*;\n};\n'; } >$@.tmp && mv $@.tmp $@ +.endif # generated CFLAGS+= -I${.OBJDIR} diff --git a/lib/libcrypto/Symbols.namespace b/lib/libcrypto/Symbols.namespace new file mode 100644 index 00000000000..31f7fba4c81 --- /dev/null +++ b/lib/libcrypto/Symbols.namespace @@ -0,0 +1,9 @@ +_libre_HMAC +_libre_HMAC_CTX_copy +_libre_HMAC_CTX_free +_libre_HMAC_CTX_get_md +_libre_HMAC_CTX_new +_libre_HMAC_CTX_set_flags +_libre_HMAC_Final +_libre_HMAC_Init_ex +_libre_HMAC_Update diff --git a/lib/libcrypto/hidden/README b/lib/libcrypto/hidden/README new file mode 100644 index 00000000000..c41830cf55f --- /dev/null +++ b/lib/libcrypto/hidden/README @@ -0,0 +1,40 @@ +The goals: +1) calls from inside libcrypto to other libcrypto functions should + be via identifiers that are of hidden visibility and -- to avoid + confusion or conflicts -- are in the reserved namespace. By + doing this these calls are protected from being overridden by + applications and on many platforms can avoid creation or use of + GOT or PLT entries. I've chosen a prefix of "_lcry_" for this. + Note that these symbols aren't in the dynamic symbol table of the + libcrypto.so shared library...but they are visible in the static + library. + +2) calls from libssl to symbols in libcrypto should be via identifiers + which won't be accidentally overridden by the application, libc, + other random crypto libraries that are pulled in, etc. I've + chosen a prefix of "_libre_" for this. + +These will not be declared directly; instead, the gcc "asm labels" +extension will be used rename the function. In order to actually +set up the desired asm labels, we use these in the internal .h +files: + + LCRYPTO_USED(x) Symbols used both internally and externally + In builds of libcrypto, this makes gcc convert use of x to + use _libre_x instead. In other builds that use these headers, + it makes gcc convert use of x to use _libre_x instead. Use + LCRYPTO_ALIAS(x) to create the external aliases. + ex: LCRYPTO_USED(SSL_get_verify_mode) + + LCRYPTO_UNUSED(x) Symbols that are not used internally or by libssl + No renaming is done. In builds of libcrypto, the symbol + is marked as deprecated to detect unintentional use of such + a synbol, so that it can be marked as used going forward. + ex: LCRYPTO_UNUSED(SSL_CIPHER_get_name) + +Finally, to create the expected aliases, we use these in the .c files +where the definitions are: + LCRYPTO_ALIAS(x) + This defines both x and _libre_x as strong aliases for _lcry_x. + Match uses of this with uses of LCRYPTO_USED() + ex: LCRYPTO_ALIAS(SSL_get_verify_mode) diff --git a/lib/libcrypto/hidden/crypto_namespace.h b/lib/libcrypto/hidden/crypto_namespace.h new file mode 100644 index 00000000000..6ceef26e2d8 --- /dev/null +++ b/lib/libcrypto/hidden/crypto_namespace.h @@ -0,0 +1,44 @@ +/* $OpenBSD: crypto_namespace.h,v 1.1 2022/11/11 11:25:18 beck Exp $ */ +/* + * Copyright (c) 2016 Philip Guenther + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _LIBCRYPTO_CRYPTO_NAMESPACE_H_ +#define _LIBCRYPTO_CRYPTO_NAMESPACE_H_ + +/* + * If marked as 'used', then internal calls use the name with prefix "_lcry_" + * and we alias that to the normal name *and* the name with prefix "_libre_"; + * external calls use the latter name. + */ + +#ifdef LIBRESSL_NAMESPACE +# define LCRYPTO_UNUSED(x) typeof(x) x __attribute__((deprecated)) +#ifdef LIBRESSL_CRYPTO_NAMESPACE +# define LCRYPTO_USED(x) __attribute__((visibility("hidden"))) \ + typeof(x) x asm("_lcry_"#x) +# define LCRYPTO_ALIAS1(pre,x) asm(".global "#pre#x"; "#pre#x" = _lcry_"#x) +# define LCRYPTO_ALIAS(x) LCRYPTO_ALIAS1(,x); LCRYPTO_ALIAS1(_libre_,x); +#else +# define LCRYPTO_USED(x) typeof(x) x asm("_libre_"#x) +#endif +#else +# define LCRYPTO_UNUSED(x) +# define LCRYPTO_USED(x) +# define LCRYPTO_ALIAS1(pre,x) +# define LCRYPTO_ALIAS(x) +#endif + +#endif /* _LIBCRYPTO_CRYPTO_NAMESPACE_H_ */ diff --git a/lib/libcrypto/hidden/openssl/hmac.h b/lib/libcrypto/hidden/openssl/hmac.h new file mode 100644 index 00000000000..d8370945d05 --- /dev/null +++ b/lib/libcrypto/hidden/openssl/hmac.h @@ -0,0 +1,36 @@ +/* $OpenBSD: hmac.h,v 1.1 2022/11/11 11:25:18 beck Exp $ */ +/* + * Copyright (c) 2016 Philip Guenther + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _LIBCRYPTO_HMAC_H_ +#define _LIBCRYPTO_HMAC_H_ + +#include_next +#include "crypto_namespace.h" + +LCRYPTO_USED(HMAC_CTX_new); +LCRYPTO_USED(HMAC_CTX_free); +LCRYPTO_UNUSED(HMAC_CTX_reset); +LCRYPTO_UNUSED(HMAC_Init); +LCRYPTO_USED(HMAC_Init_ex); +LCRYPTO_USED(HMAC_Update); +LCRYPTO_USED(HMAC_Final); +LCRYPTO_USED(HMAC); +LCRYPTO_USED(HMAC_CTX_copy); +LCRYPTO_USED(HMAC_CTX_set_flags); +LCRYPTO_USED(HMAC_CTX_get_md); + +#endif /* _LIBCRYPTO_HMAC_H_ */ diff --git a/lib/libcrypto/hmac/hmac.c b/lib/libcrypto/hmac/hmac.c index 3421119b7e6..b195ca680b2 100644 --- a/lib/libcrypto/hmac/hmac.c +++ b/lib/libcrypto/hmac/hmac.c @@ -1,4 +1,4 @@ -/* $OpenBSD: hmac.c,v 1.28 2022/05/05 18:29:34 tb Exp $ */ +/* $OpenBSD: hmac.c,v 1.29 2022/11/11 11:25:18 beck Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -134,6 +134,7 @@ HMAC_Init_ex(HMAC_CTX *ctx, const void *key, int len, const EVP_MD *md, err: return 0; } +LCRYPTO_ALIAS(HMAC_Init_ex) int HMAC_Init(HMAC_CTX *ctx, const void *key, int len, const EVP_MD *md) @@ -151,6 +152,7 @@ HMAC_Update(HMAC_CTX *ctx, const unsigned char *data, size_t len) return EVP_DigestUpdate(&ctx->md_ctx, data, len); } +LCRYPTO_ALIAS(HMAC_Update) int HMAC_Final(HMAC_CTX *ctx, unsigned char *md, unsigned int *len) @@ -173,6 +175,7 @@ HMAC_Final(HMAC_CTX *ctx, unsigned char *md, unsigned int *len) err: return 0; } +LCRYPTO_ALIAS(HMAC_Final) HMAC_CTX * HMAC_CTX_new(void) @@ -186,6 +189,7 @@ HMAC_CTX_new(void) return ctx; } +LCRYPTO_ALIAS(HMAC_CTX_new) void HMAC_CTX_free(HMAC_CTX *ctx) @@ -197,6 +201,7 @@ HMAC_CTX_free(HMAC_CTX *ctx) free(ctx); } +LCRYPTO_ALIAS(HMAC_CTX_free) int HMAC_CTX_reset(HMAC_CTX *ctx) @@ -231,6 +236,7 @@ HMAC_CTX_copy(HMAC_CTX *dctx, HMAC_CTX *sctx) err: return 0; } +LCRYPTO_ALIAS(HMAC_CTX_copy) void HMAC_CTX_cleanup(HMAC_CTX *ctx) @@ -248,12 +254,14 @@ HMAC_CTX_set_flags(HMAC_CTX *ctx, unsigned long flags) EVP_MD_CTX_set_flags(&ctx->o_ctx, flags); EVP_MD_CTX_set_flags(&ctx->md_ctx, flags); } +LCRYPTO_ALIAS(HMAC_CTX_set_flags) const EVP_MD * HMAC_CTX_get_md(const HMAC_CTX *ctx) { return ctx->md; } +LCRYPTO_ALIAS(HMAC_CTX_get_md) unsigned char * HMAC(const EVP_MD *evp_md, const void *key, int key_len, const unsigned char *d, @@ -282,3 +290,4 @@ err: HMAC_CTX_cleanup(&c); return NULL; } +LCRYPTO_ALIAS(HMAC) diff --git a/lib/libssl/Makefile b/lib/libssl/Makefile index 1788cd75a3a..a6ee26a6676 100644 --- a/lib/libssl/Makefile +++ b/lib/libssl/Makefile @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile,v 1.77 2022/08/17 07:39:19 jsing Exp $ +# $OpenBSD: Makefile,v 1.78 2022/11/11 11:25:18 beck Exp $ .include .ifndef NOMAN @@ -16,6 +16,9 @@ CFLAGS+= -Wall -Wundef CFLAGS+= -Werror .endif CFLAGS+= -DLIBRESSL_INTERNAL +.ifdef NAMESPACE +CFLAGS+= -DLIBRESSL_NAMESPACE +.endif .ifdef TLS1_3 CFLAGS+= -DLIBRESSL_HAS_TLS1_3_CLIENT CFLAGS+= -DLIBRESSL_HAS_TLS1_3_SERVER @@ -24,7 +27,9 @@ CFLAGS+= -DLIBRESSL_HAS_TLS1_3_SERVER CFLAGS+= -DTLS13_DEBUG .endif CFLAGS+= -I${.CURDIR} +CFLAGS+= -I${.CURDIR}/../libcrypto/hidden CFLAGS+= -I${.CURDIR}/../libcrypto/bio +CFLAGS+= -I${.CURDIR}/hidden LDADD+= -L${BSDOBJDIR}/lib/libcrypto -lcrypto diff --git a/lib/libssl/bio_ssl.c b/lib/libssl/bio_ssl.c index 04dd22f16de..d6974cdb24a 100644 --- a/lib/libssl/bio_ssl.c +++ b/lib/libssl/bio_ssl.c @@ -1,4 +1,4 @@ -/* $OpenBSD: bio_ssl.c,v 1.35 2022/10/05 21:16:14 tb Exp $ */ +/* $OpenBSD: bio_ssl.c,v 1.36 2022/11/11 11:25:18 beck Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -103,6 +103,7 @@ BIO_f_ssl(void) { return (&methods_sslp); } +LSSL_ALIAS(BIO_f_ssl) static int ssl_new(BIO *bi) @@ -532,6 +533,7 @@ BIO_new_ssl_connect(SSL_CTX *ctx) BIO_free(ssl); return (NULL); } +LSSL_ALIAS(BIO_new_ssl_connect) BIO * BIO_new_ssl(SSL_CTX *ctx, int client) @@ -556,6 +558,7 @@ BIO_new_ssl(SSL_CTX *ctx, int client) BIO_free(ret); return (NULL); } +LSSL_ALIAS(BIO_new_ssl) int BIO_ssl_copy_session_id(BIO *t, BIO *f) diff --git a/lib/libssl/hidden/openssl/ssl.h b/lib/libssl/hidden/openssl/ssl.h new file mode 100644 index 00000000000..540c6e76527 --- /dev/null +++ b/lib/libssl/hidden/openssl/ssl.h @@ -0,0 +1,31 @@ +/* $OpenBSD: ssl.h,v 1.1 2022/11/11 11:25:18 beck Exp $ */ +/* + * Copyright (c) 2022 Philip Guenther + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _LIBSSL_SSL_H_ +#define _LIBSSL_SSL_H_ + +#include_next +#include "ssl_namespace.h" + +LSSL_USED(BIO_f_ssl); +LSSL_USED(BIO_new_ssl); +LSSL_USED(BIO_new_ssl_connect); +LSSL_UNUSED(BIO_new_buffer_ssl_connect); +LSSL_UNUSED(BIO_ssl_copy_session_id); +LSSL_UNUSED(BIO_ssl_shutdown); + +#endif /* _LIBSSL_SSL_H_ */ diff --git a/lib/libssl/hidden/ssl_namespace.h b/lib/libssl/hidden/ssl_namespace.h new file mode 100644 index 00000000000..803f3e66bed --- /dev/null +++ b/lib/libssl/hidden/ssl_namespace.h @@ -0,0 +1,37 @@ +/* $OpenBSD: ssl_namespace.h,v 1.1 2022/11/11 11:25:18 beck Exp $ */ +/* + * Copyright (c) 2016 Philip Guenther + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _LIBSSL_SSL_NAMESPACE_H_ +#define _LIBSSL_SSL_NAMESPACE_H_ + +/* + * If marked as 'used', then internal calls use the name with prefix "_lssl_" + * and we alias that to the normal name. + */ + +#ifdef LIBRESSL_NAMESPACE +#define LSSL_UNUSED(x) typeof(x) x __attribute__((deprecated)) +#define LSSL_USED(x) __attribute__((visibility("hidden"))) \ + typeof(x) x asm("_lssl_"#x) +#define LSSL_ALIAS(x) asm(".global "#x"; "#x" = _lssl_"#x); +#else +#define LSSL_UNUSED(x) +#define LSSL_USED(x) +#define LSSL_ALIAS(x) +#endif + +#endif /* _LIBSSL_SSL_NAMESPACE_H_ */ -- 2.20.1