From 7f84e74ace1c0350419b824c8224d20d043bf2a8 Mon Sep 17 00:00:00 2001 From: Michael Richardson Date: Tue, 2 Sep 2025 21:18:13 -0400 Subject: [PATCH] feat: X509.new now takes a keyword arguments, allowing the openssl propq to be set. It uses X509_new_ex() to create the X509 object, allowing a provider to be set. If the provider is not set, then a key residing in a provider (such as a tpm2) can not be used --- ext/openssl/ossl_x509cert.c | 40 +++++++++++++++++++++++++++++++++---- 1 file changed, 36 insertions(+), 4 deletions(-) diff --git a/ext/openssl/ossl_x509cert.c b/ext/openssl/ossl_x509cert.c index 30e3c6175..42ba413d6 100644 --- a/ext/openssl/ossl_x509cert.c +++ b/ext/openssl/ossl_x509cert.c @@ -112,19 +112,51 @@ ossl_x509_initialize(int argc, VALUE *argv, VALUE self) BIO *in; X509 *x509, *x509_orig = RTYPEDDATA_DATA(self); VALUE arg; + VALUE kwargs; + const char *propq = NULL; rb_check_frozen(self); - if (rb_scan_args(argc, argv, "01", &arg) == 0) { + + if (rb_scan_args(argc, argv, "01:", &arg, &kwargs) == 0) { /* create just empty X509Cert */ return self; } + ID table[2]; + table[0] = rb_intern("der"); + table[1] = rb_intern("propq"); + + VALUE values[2]; + rb_get_kwargs(kwargs, table, 0, 2, values); + +#ifdef OSSL_USE_PROVIDER + if(values[1] != Qundef) { + propq = (char *)RSTRING_PTR(values[1]); + } + + x509 = X509_new_ex(/*libctx*/NULL, propq); +#else + x509 = X509_new(); +#endif + if (!x509) ossl_raise(eX509CertError, NULL); + + if(arg == Qundef && values[0] != Qundef) { + arg = values[0]; + } + + if(arg == Qundef) { + return self; + } + + /* something to read in */ arg = ossl_to_der_if_possible(arg); in = ossl_obj2bio(&arg); - x509 = d2i_X509_bio(in, NULL); + x509 = d2i_X509_bio(in, &x509); + if (!x509) { - OSSL_BIO_reset(in); - x509 = PEM_read_bio_X509(in, NULL, NULL, NULL); + OSSL_BIO_reset(in); + x509 = PEM_read_bio_X509(in, &x509, NULL, NULL); } + BIO_free(in); if (!x509) ossl_raise(eX509CertError, "PEM_read_bio_X509");