refactor(security): add OpenSSL 1.x compatibility

When updated to work with OpenSSL 3.0, the host tools lost their
compatibility with previous versions (1.x) of OpenSSL. This is
mainly due to the fact that 1.x APIs became deprecated in 3.0 and
therefore their use cause compiling errors. In addition, updating
for a newer version of OpenSSL meant improving the stability
against security threats. However, although version 1.1.1 is
now deprecated, it still receives security updates, so it would
not imply major security issues to keep compatibility with it too.

This patch adds backwards compatibility with OpenSSL 1.x versions
by adding back 1.x API code. It defines a macro USING_OPENSSL3,
which will select the appropriate OpenSSL API version depending on
the OpenSSL library path chosen (which is determined by the
already-existing OPENSSL_DIR variable).

In addition, cleanup items were packed in functions and moved to
the proper modules in order to make the code more maintainable and
legible.

Signed-off-by: Juan Pablo Conde <juanpablo.conde@arm.com>
Change-Id: I8deceb5e419edc73277792861882404790ccd33c
diff --git a/tools/cert_create/Makefile b/tools/cert_create/Makefile
index d951286..042e844 100644
--- a/tools/cert_create/Makefile
+++ b/tools/cert_create/Makefile
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2015-2022, ARM Limited and Contributors. All rights reserved.
+# Copyright (c) 2015-2022, Arm Limited and Contributors. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -9,12 +9,12 @@
 DEBUG		:= 0
 CRTTOOL		?= cert_create${BIN_EXT}
 BINARY		:= $(notdir ${CRTTOOL})
-OPENSSL_DIR	:= /usr
 COT		:= tbbr
 
 MAKE_HELPERS_DIRECTORY := ../../make_helpers/
 include ${MAKE_HELPERS_DIRECTORY}build_macros.mk
 include ${MAKE_HELPERS_DIRECTORY}build_env.mk
+include ${MAKE_HELPERS_DIRECTORY}defaults.mk
 
 ifneq (${PLAT},none)
 TF_PLATFORM_ROOT	:=	../../plat/
@@ -45,6 +45,10 @@
 include ${PLAT_CERT_CREATE_HELPER_MK}
 endif
 
+# Select OpenSSL version flag according to the OpenSSL build selected
+# from setting the OPENSSL_DIR path.
+$(eval $(call SELECT_OPENSSL_API_VERSION))
+
 HOSTCCFLAGS := -Wall -std=c99
 
 ifeq (${DEBUG},1)
@@ -60,6 +64,9 @@
 endif
 
 HOSTCCFLAGS += ${DEFINES}
+# USING_OPENSSL3 flag will be added to the HOSTCCFLAGS variable with the proper
+# computed value.
+HOSTCCFLAGS += -DUSING_OPENSSL3=$(USING_OPENSSL3)
 
 # Make soft links and include from local directory otherwise wrong headers
 # could get pulled in from firmware tree.
@@ -76,11 +83,11 @@
 
 HOSTCC ?= gcc
 
-.PHONY: all clean realclean
+.PHONY: all clean realclean --openssl
 
 all: ${BINARY}
 
-${BINARY}: ${OBJECTS} Makefile
+${BINARY}: --openssl ${OBJECTS} Makefile
 	@echo "  HOSTLD  $@"
 	@echo 'const char build_msg[] = "Built : "__TIME__", "__DATE__; \
                 const char platform_msg[] = "${PLAT_MSG}";' | \
@@ -91,6 +98,11 @@
 	@echo "  HOSTCC  $<"
 	${Q}${HOSTCC} -c ${HOSTCCFLAGS} ${INC_DIR} $< -o $@
 
+--openssl:
+ifeq ($(DEBUG),1)
+	@echo "Selected OpenSSL version: ${OPENSSL_CURRENT_VER}"
+endif
+
 clean:
 	$(call SHELL_DELETE_ALL, src/build_msg.o ${OBJECTS})
 
diff --git a/tools/cert_create/include/cert.h b/tools/cert_create/include/cert.h
index e63b474..5d39a88 100644
--- a/tools/cert_create/include/cert.h
+++ b/tools/cert_create/include/cert.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2022, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -54,6 +54,7 @@
 	int days,
 	int ca,
 	STACK_OF(X509_EXTENSION) * sk);
+void cert_cleanup(void);
 
 /* Macro to register the certificates used in the CoT */
 #define REGISTER_COT(_certs) \
diff --git a/tools/cert_create/include/ext.h b/tools/cert_create/include/ext.h
index e900a6d..0e7f3be 100644
--- a/tools/cert_create/include/ext.h
+++ b/tools/cert_create/include/ext.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2022, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -72,6 +72,7 @@
 		unsigned char *buf, size_t len);
 X509_EXTENSION *ext_new_nvcounter(int nid, int crit, int value);
 X509_EXTENSION *ext_new_key(int nid, int crit, EVP_PKEY *k);
+void ext_cleanup(void);
 
 /* Macro to register the extensions used in the CoT */
 #define REGISTER_EXTENSIONS(_ext) \
diff --git a/tools/cert_create/include/key.h b/tools/cert_create/include/key.h
index 128e7f7..0ef046b 100644
--- a/tools/cert_create/include/key.h
+++ b/tools/cert_create/include/key.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2022, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -66,10 +66,13 @@
 /* Exported API */
 int key_init(void);
 key_t *key_get_by_opt(const char *opt);
+#if !USING_OPENSSL3
 int key_new(key_t *key);
+#endif
 int key_create(key_t *key, int type, int key_bits);
 int key_load(key_t *key, unsigned int *err_code);
 int key_store(key_t *key);
+void key_cleanup(void);
 
 /* Macro to register the keys used in the CoT */
 #define REGISTER_KEYS(_keys) \
diff --git a/tools/cert_create/src/cert.c b/tools/cert_create/src/cert.c
index 67ae1d6..2513213 100644
--- a/tools/cert_create/src/cert.c
+++ b/tools/cert_create/src/cert.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2022, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2022, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -39,7 +39,11 @@
 	if (!btmp)
 		return 0;
 
+#if USING_OPENSSL3
 	if (!BN_rand(btmp, SERIAL_RAND_BITS, 0, 0))
+#else
+	if (!BN_pseudo_rand(btmp, SERIAL_RAND_BITS, 0, 0))
+#endif
 		goto error;
 	if (ai && !BN_to_ASN1_INTEGER(btmp, ai))
 		goto error;
@@ -272,3 +276,19 @@
 
 	return NULL;
 }
+
+void cert_cleanup(void)
+{
+	unsigned int i;
+
+	for (i = 0; i < num_certs; i++) {
+		if (certs[i].fn != NULL) {
+			void *ptr = (void *)certs[i].fn;
+
+			certs[i].fn = NULL;
+			free(ptr);
+		}
+	}
+	free(certs);
+}
+
diff --git a/tools/cert_create/src/ext.c b/tools/cert_create/src/ext.c
index 2882123..acf57a4 100644
--- a/tools/cert_create/src/ext.c
+++ b/tools/cert_create/src/ext.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2022, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -315,3 +315,20 @@
 
 	return NULL;
 }
+
+void ext_cleanup(void)
+{
+	unsigned int i;
+
+	for (i = 0; i < num_extensions; i++) {
+		if (extensions[i].arg != NULL) {
+			void *ptr = (void *)extensions[i].arg;
+
+			extensions[i].arg = NULL;
+			free(ptr);
+		}
+	}
+	free(extensions);
+	X509V3_EXT_cleanup();
+}
+
diff --git a/tools/cert_create/src/key.c b/tools/cert_create/src/key.c
index 2857a3b..0061b8a 100644
--- a/tools/cert_create/src/key.c
+++ b/tools/cert_create/src/key.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2022, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2022, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -24,6 +24,7 @@
 key_t *keys;
 unsigned int num_keys;
 
+#if !USING_OPENSSL3
 /*
  * Create a new key container
  */
@@ -37,9 +38,11 @@
 
 	return 1;
 }
+#endif
 
 static int key_create_rsa(key_t *key, int key_bits)
 {
+#if USING_OPENSSL3
 	EVP_PKEY *rsa = EVP_RSA_gen(key_bits);
 	if (rsa == NULL) {
 		printf("Cannot generate RSA key\n");
@@ -47,11 +50,52 @@
 	}
 	key->key = rsa;
 	return 1;
+#else
+	BIGNUM *e;
+	RSA *rsa = NULL;
+
+	e = BN_new();
+	if (e == NULL) {
+		printf("Cannot create RSA exponent\n");
+		return 0;
+	}
+
+	if (!BN_set_word(e, RSA_F4)) {
+		printf("Cannot assign RSA exponent\n");
+		goto err2;
+	}
+
+	rsa = RSA_new();
+	if (rsa == NULL) {
+		printf("Cannot create RSA key\n");
+		goto err2;
+	}
+
+	if (!RSA_generate_key_ex(rsa, key_bits, e, NULL)) {
+		printf("Cannot generate RSA key\n");
+		goto err;
+	}
+
+	if (!EVP_PKEY_assign_RSA(key->key, rsa)) {
+		printf("Cannot assign RSA key\n");
+		goto err;
+	}
+
+	BN_free(e);
+	return 1;
+
+err:
+	RSA_free(rsa);
+err2:
+	BN_free(e);
+	return 0;
+#endif
 }
 
 #ifndef OPENSSL_NO_EC
 static int key_create_ecdsa(key_t *key, int key_bits)
 {
+#if USING_OPENSSL3
 	EVP_PKEY *ec = EVP_EC_gen("prime256v1");
 	if (ec == NULL) {
 		printf("Cannot generate EC key\n");
@@ -59,6 +103,31 @@
 	}
 	key->key = ec;
 	return 1;
+#else
+	EC_KEY *ec;
+
+	ec = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
+	if (ec == NULL) {
+		printf("Cannot create EC key\n");
+		return 0;
+	}
+	if (!EC_KEY_generate_key(ec)) {
+		printf("Cannot generate EC key\n");
+		goto err;
+	}
+	EC_KEY_set_flags(ec, EC_PKEY_NO_PARAMETERS);
+	EC_KEY_set_asn1_flag(ec, OPENSSL_EC_NAMED_CURVE);
+	if (!EVP_PKEY_assign_EC_KEY(key->key, ec)) {
+		printf("Cannot assign EC key\n");
+		goto err;
+	}
+
+	return 1;
+
+err:
+	EC_KEY_free(ec);
+	return 0;
+#endif
 }
 #endif /* OPENSSL_NO_EC */
 
@@ -194,3 +263,20 @@
 
 	return NULL;
 }
+
+void key_cleanup(void)
+{
+	unsigned int i;
+
+	for (i = 0; i < num_keys; i++) {
+		EVP_PKEY_free(keys[i].key);
+		if (keys[i].fn != NULL) {
+			void *ptr = keys[i].fn;
+
+			free(ptr);
+			keys[i].fn = NULL;
+		}
+	}
+	free(keys);
+}
+
diff --git a/tools/cert_create/src/main.c b/tools/cert_create/src/main.c
index b39378c..fe386b7 100644
--- a/tools/cert_create/src/main.c
+++ b/tools/cert_create/src/main.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2022, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -430,10 +430,12 @@
 
 	/* Load private keys from files (or generate new ones) */
 	for (i = 0 ; i < num_keys ; i++) {
+#if !USING_OPENSSL3
 		if (!key_new(&keys[i])) {
 			ERROR("Failed to allocate key container\n");
 			exit(1);
 		}
+#endif
 
 		/* First try to load the key from disk */
 		if (key_load(&keys[i], &err_code)) {
@@ -594,9 +596,7 @@
 	/* If we got here, then we must have filled the key array completely.
 	 * We can then safely call free on all of the keys in the array
 	 */
-	for (i = 0; i < num_keys; i++) {
-		EVP_PKEY_free(keys[i].key);
-	}
+	key_cleanup();
 
 #ifndef OPENSSL_NO_ENGINE
 	ENGINE_cleanup();
@@ -605,30 +605,10 @@
 
 
 	/* We allocated strings through strdup, so now we have to free them */
-	for (i = 0; i < num_keys; i++) {
-		if (keys[i].fn != NULL) {
-			void *ptr = keys[i].fn;
-
-			keys[i].fn = NULL;
-			free(ptr);
-		}
-	}
-	for (i = 0; i < num_extensions; i++) {
-		if (extensions[i].arg != NULL) {
-			void *ptr = (void *)extensions[i].arg;
 
-			extensions[i].arg = NULL;
-			free(ptr);
-		}
-	}
-	for (i = 0; i < num_certs; i++) {
-		if (certs[i].fn != NULL) {
-			void *ptr = (void *)certs[i].fn;
+	ext_cleanup();
 
-			certs[i].fn = NULL;
-			free(ptr);
-		}
-	}
+	cert_cleanup();
 
 	return 0;
 }
diff --git a/tools/cert_create/src/sha.c b/tools/cert_create/src/sha.c
index 06ef360..bb750d4 100644
--- a/tools/cert_create/src/sha.c
+++ b/tools/cert_create/src/sha.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2022, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2022, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -7,11 +7,16 @@
 #include <stdio.h>
 #include "debug.h"
 #include "key.h"
+#if USING_OPENSSL3
 #include <openssl/evp.h>
 #include <openssl/obj_mac.h>
+#else
+#include <openssl/sha.h>
+#endif
 
 #define BUFFER_SIZE	256
 
+#if USING_OPENSSL3
 static int get_algorithm_nid(int hash_alg)
 {
 	int nids[] = {NID_sha256, NID_sha384, NID_sha512};
@@ -20,16 +25,22 @@
 	}
 	return nids[hash_alg];
 }
+#endif
 
 int sha_file(int md_alg, const char *filename, unsigned char *md)
 {
 	FILE *inFile;
+	int bytes;
+	unsigned char data[BUFFER_SIZE];
+#if USING_OPENSSL3
 	EVP_MD_CTX *mdctx;
 	const EVP_MD *md_type;
-	int bytes;
 	int alg_nid;
 	unsigned int total_bytes;
-	unsigned char data[BUFFER_SIZE];
+#else
+	SHA256_CTX shaContext;
+	SHA512_CTX sha512Context;
+#endif
 
 	if ((filename == NULL) || (md == NULL)) {
 		ERROR("%s(): NULL argument\n", __func__);
@@ -42,6 +53,8 @@
 		return 0;
 	}
 
+#if USING_OPENSSL3
+
 	mdctx = EVP_MD_CTX_new();
 	if (mdctx == NULL) {
 		fclose(inFile);
@@ -74,5 +87,32 @@
 	fclose(inFile);
 	EVP_MD_CTX_free(mdctx);
 	return 0;
+
+#else
+
+	if (md_alg == HASH_ALG_SHA384) {
+		SHA384_Init(&sha512Context);
+		while ((bytes = fread(data, 1, BUFFER_SIZE, inFile)) != 0) {
+			SHA384_Update(&sha512Context, data, bytes);
+		}
+		SHA384_Final(md, &sha512Context);
+	} else if (md_alg == HASH_ALG_SHA512) {
+		SHA512_Init(&sha512Context);
+		while ((bytes = fread(data, 1, BUFFER_SIZE, inFile)) != 0) {
+			SHA512_Update(&sha512Context, data, bytes);
+		}
+		SHA512_Final(md, &sha512Context);
+	} else {
+		SHA256_Init(&shaContext);
+		while ((bytes = fread(data, 1, BUFFER_SIZE, inFile)) != 0) {
+			SHA256_Update(&shaContext, data, bytes);
+		}
+		SHA256_Final(md, &shaContext);
+	}
+
+	fclose(inFile);
+	return 1;
+
+#endif
 }
 
diff --git a/tools/encrypt_fw/Makefile b/tools/encrypt_fw/Makefile
index 60bd8ea..2939b14 100644
--- a/tools/encrypt_fw/Makefile
+++ b/tools/encrypt_fw/Makefile
@@ -11,15 +11,21 @@
 BINARY		:= $(notdir ${ENCTOOL})
 OPENSSL_DIR	:= /usr
 
+
+MAKE_HELPERS_DIRECTORY := ../../make_helpers/
+include ${MAKE_HELPERS_DIRECTORY}build_macros.mk
+include ${MAKE_HELPERS_DIRECTORY}build_env.mk
+include ${MAKE_HELPERS_DIRECTORY}defaults.mk
+
 OBJECTS := src/encrypt.o \
            src/cmd_opt.o \
            src/main.o
 
 HOSTCCFLAGS := -Wall -std=c99
 
-MAKE_HELPERS_DIRECTORY := ../../make_helpers/
-include ${MAKE_HELPERS_DIRECTORY}build_macros.mk
-include ${MAKE_HELPERS_DIRECTORY}build_env.mk
+# Select OpenSSL version flag according to the OpenSSL build selected
+# from setting the OPENSSL_DIR path.
+$(eval $(call SELECT_OPENSSL_API_VERSION))
 
 ifeq (${DEBUG},1)
   HOSTCCFLAGS += -g -O0 -DDEBUG -DLOG_LEVEL=40
@@ -36,6 +42,12 @@
   Q :=
 endif
 
+HOSTCCFLAGS += ${DEFINES}
+# USING_OPENSSL3 flag will be added to the HOSTCCFLAGS variable with the proper
+# computed value.
+HOSTCCFLAGS += -DUSING_OPENSSL3=$(USING_OPENSSL3)
+
+
 # Make soft links and include from local directory otherwise wrong headers
 # could get pulled in from firmware tree.
 INC_DIR := -I ./include -I ../../include/tools_share -I ${OPENSSL_DIR}/include
@@ -51,11 +63,11 @@
 
 HOSTCC ?= gcc
 
-.PHONY: all clean realclean
+.PHONY: all clean realclean --openssl
 
 all: ${BINARY}
 
-${BINARY}: ${OBJECTS} Makefile
+${BINARY}: --openssl ${OBJECTS} Makefile
 	@echo "  HOSTLD  $@"
 	@echo 'const char build_msg[] = "Built : "__TIME__", "__DATE__;' | \
                 ${HOSTCC} -c ${HOSTCCFLAGS} -xc - -o src/build_msg.o
@@ -65,6 +77,11 @@
 	@echo "  HOSTCC  $<"
 	${Q}${HOSTCC} -c ${HOSTCCFLAGS} ${INC_DIR} $< -o $@
 
+--openssl:
+ifeq ($(DEBUG),1)
+	@echo "Selected OpenSSL version: ${OPENSSL_CURRENT_VER}"
+endif
+
 clean:
 	$(call SHELL_DELETE_ALL, src/build_msg.o ${OBJECTS})
 
diff --git a/tools/fiptool/Makefile b/tools/fiptool/Makefile
index e6aeba9..d7e0fe5 100644
--- a/tools/fiptool/Makefile
+++ b/tools/fiptool/Makefile
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2014-2022, ARM Limited and Contributors. All rights reserved.
+# Copyright (c) 2014-2022, Arm Limited and Contributors. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -7,6 +7,7 @@
 MAKE_HELPERS_DIRECTORY := ../../make_helpers/
 include ${MAKE_HELPERS_DIRECTORY}build_macros.mk
 include ${MAKE_HELPERS_DIRECTORY}build_env.mk
+include ${MAKE_HELPERS_DIRECTORY}defaults.mk
 
 FIPTOOL ?= fiptool${BIN_EXT}
 PROJECT := $(notdir ${FIPTOOL})
@@ -23,6 +24,15 @@
   HOSTCCFLAGS += -O2
 endif
 
+# Select OpenSSL version flag according to the OpenSSL build selected
+# from setting the OPENSSL_DIR path.
+$(eval $(call SELECT_OPENSSL_API_VERSION))
+
+HOSTCCFLAGS += ${DEFINES}
+# USING_OPENSSL3 flag will be added to the HOSTCCFLAGS variable with the proper
+# computed value.
+HOSTCCFLAGS += -DUSING_OPENSSL3=$(USING_OPENSSL3)
+
 # Include library directories where OpenSSL library files are located.
 # For a normal installation (i.e.: when ${OPENSSL_DIR} = /usr or
 # /usr/local), binaries are located under the ${OPENSSL_DIR}/lib/
@@ -51,11 +61,11 @@
 include ${PLAT_FIPTOOL_HELPER_MK}
 endif
 
-.PHONY: all clean distclean
+.PHONY: all clean distclean --openssl
 
 all: ${PROJECT}
 
-${PROJECT}: ${OBJECTS} Makefile
+${PROJECT}: --openssl ${OBJECTS} Makefile
 	@echo "  HOSTLD  $@"
 	${Q}${HOSTCC} ${OBJECTS} -o $@ ${LDLIBS}
 	@${ECHO_BLANK_LINE}
@@ -66,5 +76,11 @@
 	@echo "  HOSTCC  $<"
 	${Q}${HOSTCC} -c ${CPPFLAGS} ${HOSTCCFLAGS} ${INCLUDE_PATHS} $< -o $@
 
+--openssl:
+ifeq ($(DEBUG),1)
+	@echo "Selected OpenSSL version: ${OPENSSL_CURRENT_VER}"
+endif
+
+
 clean:
 	$(call SHELL_DELETE_ALL, ${PROJECT} ${OBJECTS})