[PATCH 1/4] SSL: Add support for loading X.509 certificate from openssl engine

Vesa Jääskeläinen vesa.jaaskelainen at vaisala.com
Wed Jul 12 14:07:04 UTC 2023


# HG changeset patch
# User Vesa Jääskeläinen <vesa.jaaskelainen at vaisala.com>
# Date 1689169151 -10800
#      Wed Jul 12 16:39:11 2023 +0300
# Node ID 57f9cc8ef8ce24385ebb7bb4cf3150299bc8ed91
# Parent  f91dc350be9f4a6bf1379a32a210afece7b0d75e
SSL: Add support for loading X.509 certificate from openssl engine

It is convenient to keep X.509 certificates related to key pairs stored in
openssl engine within the engine.

Implementation uses 'LOAD_CERT_CTRL' extension to fetch certificate from
the engine. This extension is not supported by all engines and in those
cases it should report with an error.

Configuration is similar to what it is for 'ssl_certificate_key'.

Example configuration with libp11's pkcs11 engine:

  ssl_certificate      "engine:pkcs11:pkcs11:token=mytoken;object=mykey";
  ssl_certificate_key  "engine:pkcs11:pkcs11:token=mytoken;object=mykey?pin-value=mypin";

diff -r f91dc350be9f -r 57f9cc8ef8ce src/event/ngx_event_openssl.c
--- a/src/event/ngx_event_openssl.c	Wed Jul 12 15:27:35 2023 +0400
+++ b/src/event/ngx_event_openssl.c	Wed Jul 12 16:39:11 2023 +0300
@@ -607,6 +607,24 @@
     return NGX_OK;
 }
 
+static X509 *
+ngx_ssl_engine_load_certificate(ENGINE *engine, const char * cert_id)
+{
+    struct {
+        const char * cert_id;
+        X509 * cert;
+    } load_cert;
+
+    load_cert.cert_id = cert_id;
+    load_cert.cert = NULL;
+
+    /* Note: if certificate is found -- X509 object's ownership is transferred. */
+    if (!ENGINE_ctrl_cmd(engine, "LOAD_CERT_CTRL", 0, &load_cert, NULL, 0)) {
+        return NULL;
+    }
+
+    return load_cert.cert;
+}
 
 static X509 *
 ngx_ssl_load_certificate(ngx_pool_t *pool, char **err, ngx_str_t *cert,
@@ -616,6 +634,50 @@
     X509    *x509, *temp;
     u_long   n;
 
+    if (ngx_strncmp(cert->data, "engine:", sizeof("engine:") - 1) == 0) {
+
+#ifndef OPENSSL_NO_ENGINE
+
+        u_char  *p, *last;
+        ENGINE  *engine;
+
+        p = cert->data + sizeof("engine:") - 1;
+        last = (u_char *) ngx_strchr(p, ':');
+
+        if (last == NULL) {
+            *err = "invalid syntax";
+            return NULL;
+        }
+
+        *last = '\0';
+
+        engine = ENGINE_by_id((char *) p);
+
+        if (engine == NULL) {
+            *err = "ENGINE_by_id() failed";
+            return NULL;
+        }
+
+        *last++ = ':';
+
+        x509 = ngx_ssl_engine_load_certificate(engine, (char *) last);
+
+        if (x509 == NULL) {
+            *err = "ngx_ssl_engine_load_certificate() failed";
+            return NULL;
+        }
+
+        ENGINE_free(engine);
+        return x509;
+
+#else
+
+        *err = "loading \"engine:...\" certificate is not supported";
+        return NULL;
+
+#endif
+    }
+
     if (ngx_strncmp(cert->data, "data:", sizeof("data:") - 1) == 0) {
 
         bio = BIO_new_mem_buf(cert->data + sizeof("data:") - 1,


More information about the nginx-devel mailing list