Fix typo in patch formatting.

Richard
diff --git a/include/haproxy/ssl_ckch.h b/include/haproxy/ssl_ckch.h
index 94c53b301..00ba2bf18 100644
--- a/include/haproxy/ssl_ckch.h
+++ b/include/haproxy/ssl_ckch.h
@@ -72,5 +72,14 @@ int __ssl_store_load_locations_file(char *path, int create_if_none, enum cafile_
 extern struct cert_exts cert_exts[];
 extern int (*ssl_commit_crlfile_cb)(const char *path, X509_STORE *ctx, char **err);
 
+struct ckch_data_cache {
+	struct ckch_data_cache *next;
+	struct ckch_data *key;
+	uint8_t *data;
+	int len;
+};
+
+struct ckch_data_cache *ckch_data_get(void *key);
+
 #endif /* USE_OPENSSL */
 #endif /* _HAPROXY_SSL_CRTLIST_H */
diff --git a/src/ssl_ckch.c b/src/ssl_ckch.c
index add42b69e..9c256f193 100644
--- a/src/ssl_ckch.c
+++ b/src/ssl_ckch.c
@@ -516,11 +516,63 @@ int ssl_sock_load_files_into_ckch(const char *path, struct ckch_data *data, char
  *
  *  Return 0 on success or != 0 on failure
  */
+
+struct ckch_data_cache *cache[31] = {0};
+
+/*
+ * This caches the BIO data in case the private key i
+ *
+ * to be instantiated in the child process (used for HSM keys)
+ *
+ * The key ckch_data* and the value is ckch_data_cache*
+ *
+ */
+static void ckch_data_put(void *key, uint8_t *data, int len)
+{
+	int idx = (unsigned long)key % 31;
+	struct ckch_data_cache *prev, *cur, *last = NULL;
+
+	ha_notice("caching ckch_data:%p len:%d\n", key, len);
+
+	for(prev = cache[idx]; prev != NULL;) {
+		last = prev;
+		prev = prev->next;
+	}
+
+	cur = malloc(sizeof(struct ckch_data_cache));
+	memset(cur, 0, sizeof(struct ckch_data_cache));
+	if (last == NULL)
+		cache[idx] = cur;
+	else
+		last->next = cur;
+	cur->key = key;
+	cur->data = malloc(len);
+	memcpy(cur->data, data, len);
+	cur->len = len;
+}
+
+struct ckch_data_cache *ckch_data_get(void *key)
+{
+	int idx = (unsigned long)key % 31;
+	struct ckch_data_cache *prev;
+
+	for(prev = cache[idx]; prev != NULL; prev = prev->next) {
+		if (prev->key == key)
+			return prev;
+	}
+
+	return NULL;
+}
+
 int ssl_sock_load_key_into_ckch(const char *path, char *buf, struct ckch_data *data , char **err)
 {
 	BIO *in = NULL;
 	int ret = 1;
 	EVP_PKEY *key = NULL;
+	static char src[16384];
+	char *src_temp;
+	int len;
+	int filetype = 0;
 
 	if (buf) {
 		/* reading from a buffer */
@@ -538,14 +590,25 @@ int ssl_sock_load_key_into_ckch(const char *path, char *buf, struct ckch_data *d
 
 		if (BIO_read_filename(in, path) <= 0)
 			goto end;
+		filetype = 1;
 	}
 
 	/* Read Private Key */
+	if(filetype) {
+		len = BIO_read(in, src, sizeof(src));
+		BIO_reset(in);
+	} else {
+		len = BIO_get_mem_data(in, &src_temp);
+		memcpy(src, src_temp, len);
+	}
+
 	key = PEM_read_bio_PrivateKey(in, NULL, NULL, NULL);
 	if (key == NULL) {
 		memprintf(err, "%sunable to load private key from file '%s'.\n",
 		          err && *err ? *err : "", path);
 		goto end;
+	} else {
+		ckch_data_put(data, (uint8_t*)src, len);
 	}
 
 	ret = 0;
@@ -581,6 +644,10 @@ int ssl_sock_load_pem_into_ckch(const char *path, char *buf, struct ckch_data *d
 	EVP_PKEY *key = NULL;
 	HASSL_DH *dh = NULL;
 	STACK_OF(X509) *chain = NULL;
+	int filetype = 0;
+	int len;
+	static char src[16384];
+	char *src_temp;
 
 	if (buf) {
 		/* reading from a buffer */
@@ -603,11 +670,23 @@ int ssl_sock_load_pem_into_ckch(const char *path, char *buf, struct ckch_data *d
 			          err && *err ? *err : "", path);
 			goto end;
 		}
+		filetype = 1;
 	}
 
 	/* Read Private Key */
+	if(filetype) {
+		len = BIO_read(in, src, sizeof(src));
+		BIO_reset(in);
+	} else {
+		len = BIO_get_mem_data(in, &src_temp);
+		memcpy(src, src_temp, len);
+	}
+
 	key = PEM_read_bio_PrivateKey(in, NULL, NULL, NULL);
 	/* no need to check for errors here, because the private key could be loaded later */
+	if(key && global.mode&MODE_MWORKER) {
+		ckch_data_put(data, (uint8_t *)src, len);
+	}
 
 #ifndef OPENSSL_NO_DH
 	/* Seek back to beginning of file */
diff --git a/src/ssl_sock.c b/src/ssl_sock.c
index 824bdaa72..64bd7ac04 100644
--- a/src/ssl_sock.c
+++ b/src/ssl_sock.c
@@ -2009,10 +2009,77 @@ struct methodVersions methodVersions[] = {
 	{SSL_OP_NO_TLSv1_3, MC_SSL_O_NO_TLSV13, ctx_set_TLSv13_func, ssl_set_TLSv13_func, "TLSv1.3"}, /* CONF_TLSV13 */
 };
 
+/* cache SSL_CTX* to ckch_data
+ * so we can recreate private key
+ */
+struct ssl_ctx_cache {
+	void *key;
+	struct ckch_data_cache *value;
+	struct ssl_ctx_cache *next;
+	EVP_PKEY *pkey;
+};
+static struct ssl_ctx_cache *ctx_cache[31];
+
+void ssl_ctx_put(void *key, void *data)
+{
+	int idx = (unsigned long)key % 31;
+	struct ssl_ctx_cache *prev, *cur, *last = NULL;
+
+	ha_notice("ssl_ctx_cache key = %p value = %p\n", key, data);
+
+	for(prev = ctx_cache[idx]; prev != NULL;) {
+		last = prev;
+		prev = prev->next;
+	}
+
+	cur = malloc(sizeof(struct ssl_ctx_cache));
+       memset(cur, 0, sizeof(struct ssl_ctx_cache));
+	if (last == NULL)
+		ctx_cache[idx] = cur;
+	else
+		last->next = cur;
+	cur->next = NULL;
+	cur->key = key;
+	cur->value = data;
+}
+
+struct ssl_ctx_cache *ssl_ctx_get(void *key)
+{
+	int idx = (unsigned long)key % 31;
+	struct ssl_ctx_cache *prev;
+
+	for(prev = ctx_cache[idx]; prev != NULL; prev = prev->next) {
+		if (prev->key == key) {
+			ha_notice("ssl_ctx_cache found key = %p value = %p\n", key, prev->value);
+			return prev;
+		}
+	}
+
+	return NULL;
+}
+
 static void ssl_sock_switchctx_set(SSL *ssl, SSL_CTX *ctx)
 {
+	struct ssl_ctx_cache *value = NULL;
+	BIO *in;
+
 	SSL_set_verify(ssl, SSL_CTX_get_verify_mode(ctx), ssl_sock_bind_verifycbk);
 	SSL_set_client_CA_list(ssl, SSL_dup_CA_list(SSL_CTX_get_client_CA_list(ctx)));
+
+	if ((value = ssl_ctx_get(ctx))) {
+		if (value->pkey == NULL) {
+			in = BIO_new_mem_buf(value->value->data, value->value->len);
+			if ((value->pkey = PEM_read_bio_PrivateKey(in, NULL, NULL, NULL))) {
+				SSL_CTX_use_PrivateKey(ctx, value->pkey);
+				ha_notice("loaded private key PID=%d SSL_CTX*=%p\n", getpid(), ctx);
+			}
+			else {
+				value->pkey = (EVP_PKEY*)-1L;
+				ha_notice("unable to realize private key from memory buffer\n");
+			}
+		}
+	}
+
 	SSL_set_SSL_CTX(ssl, ctx);
 }
 
@@ -3323,11 +3390,16 @@ static int ssl_sock_load_cert_chain(const char *path, const struct ckch_data *da
 static int ssl_sock_put_ckch_into_ctx(const char *path, struct ckch_data *data, SSL_CTX *ctx, char **err)
 {
 	int errcode = 0;
+	struct ckch_data_cache *value;
 	STACK_OF(X509) *find_chain = NULL;
 
 	ERR_clear_error();
 
-	if (SSL_CTX_use_PrivateKey(ctx, data->key) <= 0) {
+	if(global.mode&MODE_MWORKER && (value = ckch_data_get(data))) {
+		ssl_ctx_put(ctx, value);
+	}
+
+	if (!(global.mode&MODE_MWORKER) && SSL_CTX_use_PrivateKey(ctx, data->key) <= 0) {
 		int ret;
 
 		ret = ERR_get_error();

Reply via email to