From 83e73dadd90af52585df1bcce4e5b84da25fe19e Mon Sep 17 00:00:00 2001
From: beck <>
Date: Fri, 11 Nov 2022 11:25:18 +0000
Subject: 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@
---
 src/lib/libcrypto/Makefile                  | 17 +++++++++--
 src/lib/libcrypto/Symbols.namespace         |  9 ++++++
 src/lib/libcrypto/hidden/README             | 40 ++++++++++++++++++++++++++
 src/lib/libcrypto/hidden/crypto_namespace.h | 44 +++++++++++++++++++++++++++++
 src/lib/libcrypto/hidden/openssl/hmac.h     | 36 +++++++++++++++++++++++
 src/lib/libcrypto/hmac/hmac.c               | 11 +++++++-
 src/lib/libssl/Makefile                     |  7 ++++-
 src/lib/libssl/bio_ssl.c                    |  5 +++-
 src/lib/libssl/hidden/openssl/ssl.h         | 31 ++++++++++++++++++++
 src/lib/libssl/hidden/ssl_namespace.h       | 37 ++++++++++++++++++++++++
 10 files changed, 232 insertions(+), 5 deletions(-)
 create mode 100644 src/lib/libcrypto/Symbols.namespace
 create mode 100644 src/lib/libcrypto/hidden/README
 create mode 100644 src/lib/libcrypto/hidden/crypto_namespace.h
 create mode 100644 src/lib/libcrypto/hidden/openssl/hmac.h
 create mode 100644 src/lib/libssl/hidden/openssl/ssl.h
 create mode 100644 src/lib/libssl/hidden/ssl_namespace.h

diff --git a/src/lib/libcrypto/Makefile b/src/lib/libcrypto/Makefile
index ffcdc7dabb..3f5342a72f 100644
--- a/src/lib/libcrypto/Makefile
+++ b/src/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/src/lib/libcrypto/Symbols.namespace b/src/lib/libcrypto/Symbols.namespace
new file mode 100644
index 0000000000..31f7fba4c8
--- /dev/null
+++ b/src/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/src/lib/libcrypto/hidden/README b/src/lib/libcrypto/hidden/README
new file mode 100644
index 0000000000..c41830cf55
--- /dev/null
+++ b/src/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/src/lib/libcrypto/hidden/crypto_namespace.h b/src/lib/libcrypto/hidden/crypto_namespace.h
new file mode 100644
index 0000000000..6ceef26e2d
--- /dev/null
+++ b/src/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 <guenther@openbsd.org>
+ *
+ * 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/src/lib/libcrypto/hidden/openssl/hmac.h b/src/lib/libcrypto/hidden/openssl/hmac.h
new file mode 100644
index 0000000000..d8370945d0
--- /dev/null
+++ b/src/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 <guenther@openbsd.org>
+ *
+ * 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 <openssl/hmac.h>
+#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/src/lib/libcrypto/hmac/hmac.c b/src/lib/libcrypto/hmac/hmac.c
index 3421119b7e..b195ca680b 100644
--- a/src/lib/libcrypto/hmac/hmac.c
+++ b/src/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/src/lib/libssl/Makefile b/src/lib/libssl/Makefile
index 1788cd75a3..a6ee26a667 100644
--- a/src/lib/libssl/Makefile
+++ b/src/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 <bsd.own.mk>
 .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/src/lib/libssl/bio_ssl.c b/src/lib/libssl/bio_ssl.c
index 04dd22f16d..d6974cdb24 100644
--- a/src/lib/libssl/bio_ssl.c
+++ b/src/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/src/lib/libssl/hidden/openssl/ssl.h b/src/lib/libssl/hidden/openssl/ssl.h
new file mode 100644
index 0000000000..540c6e7652
--- /dev/null
+++ b/src/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 <guenther@openbsd.org>
+ *
+ * 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 <openssl/ssl.h>
+#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/src/lib/libssl/hidden/ssl_namespace.h b/src/lib/libssl/hidden/ssl_namespace.h
new file mode 100644
index 0000000000..803f3e66be
--- /dev/null
+++ b/src/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 <guenther@openbsd.org>
+ *
+ * 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_ */
-- 
cgit v1.2.3-55-g6feb