In OpenSSL documentation it says:
All these functions are implemented as macros. Those containing a 1 increment the reference count of the supplied certificate or chain so it must be freed at some point after the operation. Those containing a 0 do not increment reference counts and the supplied certificate or chain MUST NOT be freed after the operation.
But when I tried to look at examples of cases about which one should be used where I'm confused.
First OpenSSL:
It uses SSL_add0_chain_cert
itself in the SSL_CTX_use_certificate_chain_file
function of ssl_rsa.c
. Here is the source:
static int use_certificate_chain_file(SSL_CTX *ctx, SSL *ssl, const char *file) { if (ctx) ret = SSL_CTX_use_certificate(ctx, x); else ret = SSL_use_certificate(ssl, x); ...... while ((ca = PEM_read_bio_X509(in, NULL, passwd_callback, passwd_callback_userdata)) != NULL) { if (ctx) r = SSL_CTX_add0_chain_cert(ctx, ca); else r = SSL_add0_chain_cert(ssl, ca); ...... }
Second usage I see is OpenResty Lua:
It uses SSL_add0_chain_cert
in one way of setting certificate (ngx_http_lua_ffi_ssl_set_der_certificate
), see here:
int ngx_http_lua_ffi_ssl_set_der_certificate(ngx_http_request_t *r, const char *data, size_t len, char **err) { ...... if (SSL_use_certificate(ssl_conn, x509) == 0) { *err = "SSL_use_certificate() failed"; goto failed; } ...... while (!BIO_eof(bio)) { x509 = d2i_X509_bio(bio, NULL); if (x509 == NULL) { *err = "d2i_X509_bio() failed"; goto failed; } if (SSL_add0_chain_cert(ssl_conn, x509) == 0) { *err = "SSL_add0_chain_cert() failed"; goto failed; } } BIO_free(bio); *err = NULL; return NGX_OK; failed: ....... }
Yet uses SSL_add1_chain_cert
in another way (ngx_http_lua_ffi_set_cert
), see here:
int ngx_http_lua_ffi_set_cert(ngx_http_request_t *r, void *cdata, char **err) { ...... if (SSL_use_certificate(ssl_conn, x509) == 0) { *err = "SSL_use_certificate() failed"; goto failed; } x509 = NULL; /* read rest of the chain */ for (i = 1; i < sk_X509_num(chain); i++) { x509 = sk_X509_value(chain, i); if (x509 == NULL) { *err = "sk_X509_value() failed"; goto failed; } if (SSL_add1_chain_cert(ssl_conn, x509) == 0) { *err = "SSL_add1_chain_cert() failed"; goto failed; } } *err = NULL; return NGX_OK; /* No free of x509 here */ failed: ...... }
Yet I don't see a clear difference of what changes when calling these two in Lua, and it doesn't seem like the cert X509, when set successfully, gets freed in either case. According to my understanding of the OpenSSL doc, I should expect X509_free(x509)
gets called somewhere after SSL_add1_chain_cert
called on that x509. Is that the correct understanding?
Last, the Openssl implementation of ssl_cert_add1_chain_cert
(what boils down from SSL_add1_chain_cert
macro) does indeed show it's just a wrapper of ssl_cert_add0_chain_cert
with reference count incremented on the cert, but how should that be reflected in the calling process?
int ssl_cert_add1_chain_cert(SSL *s, SSL_CTX *ctx, X509 *x) { if (!ssl_cert_add0_chain_cert(s, ctx, x)) return 0; X509_up_ref(x); return 1; }
Now Nginx only deals with another function SSL_CTX_add_extra_chain_cert
which leaves the burden of such choice behind, as it does not deal with switching cert per SSL connection basis. In my case I need to patch Nginx with this capability, switching cert per connection (but without using Lua).
So I'm not sure which one I should be using, SSL_add0_chain_cert
or SSL_add1_chain_cert
? And what's the freeing practice here?
0 comments:
Post a Comment