diff options
author | Patrick Griffis <pgriffis@igalia.com> | 2021-09-01 15:22:34 -0500 |
---|---|---|
committer | Marge Bot <marge-bot@gnome.org> | 2022-08-15 19:12:25 +0000 |
commit | 683b9b3733e92e677c601910ba9593aacaa78341 (patch) | |
tree | 110725be8c50170e3589cae311aed8db1044b454 | |
parent | 28114e7b34e90d1272880b7381079b3fc54c4a13 (diff) | |
download | glib-networking-683b9b3733e92e677c601910ba9593aacaa78341.tar.gz |
Add support for PKCS #12 encrypted files
Part-of: <https://gitlab.gnome.org/GNOME/glib-networking/-/merge_requests/184>
-rw-r--r-- | tls/gnutls/gtlscertificate-gnutls.c | 151 | ||||
-rw-r--r-- | tls/openssl/gtlscertificate-openssl.c | 136 | ||||
-rw-r--r-- | tls/tests/certificate.c | 118 | ||||
-rw-r--r-- | tls/tests/files/client-and-key-fullchain.pem | 77 | ||||
-rw-r--r-- | tls/tests/files/client-and-key-password-enckey.p12 | bin | 0 -> 2794 bytes | |||
-rw-r--r-- | tls/tests/files/client-and-key-password.p12 | bin | 0 -> 2575 bytes | |||
-rw-r--r-- | tls/tests/files/client-and-key.p12 | bin | 0 -> 2455 bytes | |||
-rwxr-xr-x | tls/tests/files/create-files.sh | 16 |
8 files changed, 498 insertions, 0 deletions
diff --git a/tls/gnutls/gtlscertificate-gnutls.c b/tls/gnutls/gtlscertificate-gnutls.c index 11f5c5c..1b2f4a9 100644 --- a/tls/gnutls/gtlscertificate-gnutls.c +++ b/tls/gnutls/gtlscertificate-gnutls.c @@ -25,6 +25,7 @@ #include "config.h" #include <gnutls/gnutls.h> +#include <gnutls/pkcs12.h> #include <gnutls/x509.h> #include <string.h> @@ -48,6 +49,8 @@ enum PROP_ISSUER_NAME, PROP_DNS_NAMES, PROP_IP_ADDRESSES, + PROP_PKCS12_DATA, + PROP_PASSWORD, }; struct _GTlsCertificateGnutls @@ -62,6 +65,9 @@ struct _GTlsCertificateGnutls GTlsCertificateGnutls *issuer; + GByteArray *pkcs12_data; + char *password; + GError *construct_error; guint have_cert : 1; @@ -69,6 +75,7 @@ struct _GTlsCertificateGnutls }; static void g_tls_certificate_gnutls_initable_iface_init (GInitableIface *iface); +static GTlsCertificateGnutls *g_tls_certificate_gnutls_new_take_x509 (gnutls_x509_crt_t cert); G_DEFINE_TYPE_WITH_CODE (GTlsCertificateGnutls, g_tls_certificate_gnutls, G_TYPE_TLS_CERTIFICATE, G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, @@ -85,6 +92,9 @@ g_tls_certificate_gnutls_finalize (GObject *object) g_clear_pointer (&gnutls->pkcs11_uri, g_free); g_clear_pointer (&gnutls->private_key_pkcs11_uri, g_free); + g_clear_pointer (&gnutls->pkcs12_data, g_byte_array_unref); + g_clear_pointer (&gnutls->password, g_free); + g_clear_object (&gnutls->issuer); g_clear_error (&gnutls->construct_error); @@ -192,6 +202,106 @@ err: } static void +maybe_import_pkcs12 (GTlsCertificateGnutls *gnutls) +{ + gnutls_pkcs12_t p12 = NULL; + gnutls_x509_privkey_t x509_key = NULL; + gnutls_x509_crt_t *chain = NULL; + guint chain_len; + int status; + gnutls_datum_t p12_data; + GTlsError error_code = G_TLS_ERROR_BAD_CERTIFICATE; + GTlsCertificateGnutls *previous_cert; + + /* If password is set first. */ + if (!gnutls->pkcs12_data) + return; + + p12_data.data = gnutls->pkcs12_data->data; + p12_data.size = gnutls->pkcs12_data->len; + + status = gnutls_pkcs12_init (&p12); + if (status != GNUTLS_E_SUCCESS) + goto import_failed; + + /* Only support DER, it's the common encoding and what everything including OpenSSL uses. */ + status = gnutls_pkcs12_import (p12, &p12_data, GNUTLS_X509_FMT_DER, 0); + if (status != GNUTLS_E_SUCCESS) + goto import_failed; + + if (gnutls->password) + { + status = gnutls_pkcs12_verify_mac (p12, gnutls->password); + if (status != GNUTLS_E_SUCCESS) + { + error_code = G_TLS_ERROR_BAD_CERTIFICATE_PASSWORD; + goto import_failed; + } + } + + /* Note that this *requires* a cert and key, if we want to make keys optional + * we would have to re-implement this parsing ourselves. */ + status = gnutls_pkcs12_simple_parse (p12, + gnutls->password ? gnutls->password : "", + &x509_key, + &chain, &chain_len, + NULL, NULL, + NULL, + GNUTLS_PKCS12_SP_INCLUDE_SELF_SIGNED); + if (status == GNUTLS_E_DECRYPTION_FAILED) + error_code = G_TLS_ERROR_BAD_CERTIFICATE_PASSWORD; + if (status != GNUTLS_E_SUCCESS) + goto import_failed; + + /* Clear a previous error to load without a password. */ + if (g_error_matches (gnutls->construct_error, G_TLS_ERROR, G_TLS_ERROR_BAD_CERTIFICATE_PASSWORD)) + g_clear_error (&gnutls->construct_error); + + /* Clear existing initialized empty cert. */ + gnutls_x509_crt_deinit (gnutls->cert); + + /* First cert is the main one. */ + gnutls->cert = chain[0]; + gnutls->have_cert = TRUE; + previous_cert = gnutls; + + for (guint i = 1; i < chain_len; i++) + { + /* GnuTLS already built us a valid chain in order by issuer. See pkcs12.c#make_chain(). */ + GTlsCertificateGnutls *new_cert = g_tls_certificate_gnutls_new_take_x509 (chain[i]); + g_tls_certificate_gnutls_set_issuer (previous_cert, new_cert); + previous_cert = new_cert; + g_object_unref (new_cert); + } + + g_clear_pointer (&chain, gnutls_free); + + /* Convert X509 privkey to abstract privkey. */ + status = gnutls_privkey_init (&gnutls->key); + if (status != GNUTLS_E_SUCCESS) + goto import_failed; + + status = gnutls_privkey_import_x509 (gnutls->key, x509_key, GNUTLS_PRIVKEY_IMPORT_COPY); + if (status != GNUTLS_E_SUCCESS) + goto import_failed; + + g_clear_pointer (&x509_key, gnutls_x509_privkey_deinit); + gnutls->have_key = TRUE; + + g_clear_pointer (&p12, gnutls_pkcs12_deinit); + return; + +import_failed: + g_clear_error (&gnutls->construct_error); + g_set_error (&gnutls->construct_error, G_TLS_ERROR, error_code, + _("Failed to import PKCS #12: %s"), gnutls_strerror (status)); + + g_clear_pointer (&p12, gnutls_pkcs12_deinit); + g_clear_pointer (&x509_key, gnutls_x509_privkey_deinit); + g_clear_pointer (&chain, gnutls_free); +} + +static void g_tls_certificate_gnutls_get_property (GObject *object, guint prop_id, GValue *value, @@ -209,6 +319,10 @@ g_tls_certificate_gnutls_get_property (GObject *object, switch (prop_id) { + case PROP_PKCS12_DATA: + g_value_set_boxed (value, gnutls->pkcs12_data); + break; + case PROP_CERTIFICATE: size = 0; status = gnutls_x509_crt_export (gnutls->cert, @@ -343,6 +457,26 @@ g_tls_certificate_gnutls_set_property (GObject *object, switch (prop_id) { + case PROP_PASSWORD: + gnutls->password = g_value_dup_string (value); + if (gnutls->password) + { + g_return_if_fail (gnutls->have_cert == FALSE); + g_return_if_fail (gnutls->have_key == FALSE); + maybe_import_pkcs12 (gnutls); + } + break; + + case PROP_PKCS12_DATA: + gnutls->pkcs12_data = g_value_dup_boxed (value); + if (gnutls->pkcs12_data) + { + g_return_if_fail (gnutls->have_cert == FALSE); + g_return_if_fail (gnutls->have_key == FALSE); + maybe_import_pkcs12 (gnutls); + } + break; + case PROP_CERTIFICATE: bytes = g_value_get_boxed (value); if (!bytes) @@ -485,6 +619,9 @@ g_tls_certificate_gnutls_initable_init (GInitable *initable, { GTlsCertificateGnutls *gnutls = G_TLS_CERTIFICATE_GNUTLS (initable); + /* After init we don't need to keep the password around. */ + g_clear_pointer (&gnutls->password, g_free); + if (gnutls->construct_error) { g_propagate_error (error, gnutls->construct_error); @@ -592,6 +729,8 @@ g_tls_certificate_gnutls_class_init (GTlsCertificateGnutlsClass *klass) g_object_class_override_property (gobject_class, PROP_ISSUER_NAME, "issuer-name"); g_object_class_override_property (gobject_class, PROP_DNS_NAMES, "dns-names"); g_object_class_override_property (gobject_class, PROP_IP_ADDRESSES, "ip-addresses"); + g_object_class_override_property (gobject_class, PROP_PKCS12_DATA, "pkcs12-data"); + g_object_class_override_property (gobject_class, PROP_PASSWORD, "password"); } static void @@ -614,6 +753,18 @@ g_tls_certificate_gnutls_new (const gnutls_datum_t *datum, return G_TLS_CERTIFICATE (gnutls); } +static GTlsCertificateGnutls * +g_tls_certificate_gnutls_new_take_x509 (gnutls_x509_crt_t cert) +{ + GTlsCertificateGnutls *gnutls; + + gnutls = g_object_new (G_TYPE_TLS_CERTIFICATE_GNUTLS, NULL); + gnutls->cert = cert; + gnutls->have_cert = TRUE; + + return gnutls; +} + void g_tls_certificate_gnutls_set_data (GTlsCertificateGnutls *gnutls, const gnutls_datum_t *datum) diff --git a/tls/openssl/gtlscertificate-openssl.c b/tls/openssl/gtlscertificate-openssl.c index 0bc7ea6..d57f5ee 100644 --- a/tls/openssl/gtlscertificate-openssl.c +++ b/tls/openssl/gtlscertificate-openssl.c @@ -27,6 +27,7 @@ #include <string.h> #include "openssl-include.h" +#include <openssl/pkcs12.h> #include "gtlscertificate-openssl.h" #include <glib/gi18n-lib.h> @@ -38,6 +39,9 @@ struct _GTlsCertificateOpenssl X509 *cert; EVP_PKEY *key; + GByteArray *pkcs12_data; + char *password; + GTlsCertificateOpenssl *issuer; GError *construct_error; @@ -61,9 +65,12 @@ enum PROP_ISSUER_NAME, PROP_DNS_NAMES, PROP_IP_ADDRESSES, + PROP_PKCS12_DATA, + PROP_PASSWORD, }; static void g_tls_certificate_openssl_initable_iface_init (GInitableIface *iface); +static gboolean is_issuer (GTlsCertificateOpenssl *cert, GTlsCertificateOpenssl *issuer); G_DEFINE_TYPE_WITH_CODE (GTlsCertificateOpenssl, g_tls_certificate_openssl, G_TYPE_TLS_CERTIFICATE, G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, @@ -79,6 +86,9 @@ g_tls_certificate_openssl_finalize (GObject *object) if (openssl->key) EVP_PKEY_free (openssl->key); + g_clear_pointer (&openssl->pkcs12_data, g_byte_array_unref); + g_clear_pointer (&openssl->password, g_free); + g_clear_object (&openssl->issuer); g_clear_error (&openssl->construct_error); @@ -206,6 +216,103 @@ out: } static void +maybe_import_pkcs12 (GTlsCertificateOpenssl *openssl) +{ + PKCS12 *p12 = NULL; + X509 *cert = NULL; + STACK_OF(X509) *ca = NULL; + EVP_PKEY *key = NULL; + BIO *bio = NULL; + int status; + char error_buffer[256] = { 0 }; + GTlsError error_code = G_TLS_ERROR_BAD_CERTIFICATE; + + /* If password is set first. */ + if (!openssl->pkcs12_data) + return; + + bio = BIO_new (BIO_s_mem ()); + status = BIO_write (bio, openssl->pkcs12_data->data, openssl->pkcs12_data->len); + if (status <= 0) + goto import_failed; + g_assert (status == openssl->pkcs12_data->len); + + p12 = d2i_PKCS12_bio (bio, NULL); + if (p12 == NULL) + goto import_failed; + + status = PKCS12_parse (p12, openssl->password, &key, &cert, &ca); + g_clear_pointer (&bio, BIO_free_all); + + if (status != 1) + { + if (ERR_GET_REASON (ERR_peek_last_error ()) == PKCS12_R_MAC_VERIFY_FAILURE) + error_code = G_TLS_ERROR_BAD_CERTIFICATE_PASSWORD; + goto import_failed; + } + + /* Clear a previous error to load without a password. */ + if (g_error_matches (openssl->construct_error, G_TLS_ERROR, G_TLS_ERROR_BAD_CERTIFICATE_PASSWORD)) + g_clear_error (&openssl->construct_error); + + if (cert) + { + openssl->cert = g_steal_pointer (&cert); + openssl->have_cert = TRUE; + } + + if (ca) + { + GTlsCertificateOpenssl *last_cert = openssl; + + for (guint i = 0; i < sk_X509_num (ca); ) + { + GTlsCertificateOpenssl *new_cert; + new_cert = G_TLS_CERTIFICATE_OPENSSL (g_tls_certificate_openssl_new_from_x509 (sk_X509_value (ca, i), + NULL)); + + if (is_issuer (last_cert, new_cert)) + { + g_tls_certificate_openssl_set_issuer (last_cert, new_cert); + last_cert = new_cert; + + /* Start the list over to find an issuer of the new cert. */ + sk_X509_delete (ca, i); + i = 0; + } + else + i++; + + g_object_unref (new_cert); + } + + sk_X509_pop_free (ca, X509_free); + ca = NULL; + } + + if (key) + { + openssl->key = g_steal_pointer (&key); + openssl->have_key = TRUE; + } + + g_clear_pointer (&p12, PKCS12_free); + return; + +import_failed: + g_clear_error (&openssl->construct_error); + + if (!error_buffer[0]) + ERR_error_string_n (ERR_get_error (), error_buffer, sizeof (error_buffer)); + + g_set_error (&openssl->construct_error, G_TLS_ERROR, error_code, + _("Failed to import PKCS #12: %s"), error_buffer); + + g_clear_pointer (&p12, PKCS12_free); + g_clear_pointer (&bio, BIO_free_all); +} + +static void g_tls_certificate_openssl_get_property (GObject *object, guint prop_id, GValue *value, @@ -228,6 +335,10 @@ g_tls_certificate_openssl_get_property (GObject *object, switch (prop_id) { + case PROP_PKCS12_DATA: + g_value_set_boxed (value, openssl->pkcs12_data); + break; + case PROP_CERTIFICATE: /* NOTE: we do the two calls to avoid openssl allocating the buffer for us */ size = i2d_X509 (openssl->cert, NULL); @@ -345,6 +456,26 @@ g_tls_certificate_openssl_set_property (GObject *object, switch (prop_id) { + case PROP_PASSWORD: + openssl->password = g_value_dup_string (value); + if (openssl->password) + { + g_return_if_fail (openssl->have_cert == FALSE); + g_return_if_fail (openssl->have_key == FALSE); + maybe_import_pkcs12 (openssl); + } + break; + + case PROP_PKCS12_DATA: + openssl->pkcs12_data = g_value_dup_boxed (value); + if (openssl->pkcs12_data) + { + g_return_if_fail (openssl->have_cert == FALSE); + g_return_if_fail (openssl->have_key == FALSE); + maybe_import_pkcs12 (openssl); + } + break; + case PROP_CERTIFICATE: bytes = g_value_get_boxed (value); if (!bytes) @@ -447,6 +578,9 @@ g_tls_certificate_openssl_initable_init (GInitable *initable, { GTlsCertificateOpenssl *openssl = G_TLS_CERTIFICATE_OPENSSL (initable); + /* After init we don't need to keep the password around. */ + g_clear_pointer (&openssl->password, g_free); + if (openssl->construct_error) { g_propagate_error (error, openssl->construct_error); @@ -544,6 +678,8 @@ g_tls_certificate_openssl_class_init (GTlsCertificateOpensslClass *klass) g_object_class_override_property (gobject_class, PROP_ISSUER_NAME, "issuer-name"); g_object_class_override_property (gobject_class, PROP_DNS_NAMES, "dns-names"); g_object_class_override_property (gobject_class, PROP_IP_ADDRESSES, "ip-addresses"); + g_object_class_override_property (gobject_class, PROP_PKCS12_DATA, "pkcs12-data"); + g_object_class_override_property (gobject_class, PROP_PASSWORD, "password"); } static void diff --git a/tls/tests/certificate.c b/tls/tests/certificate.c index 01c3c1a..e820ba1 100644 --- a/tls/tests/certificate.c +++ b/tls/tests/certificate.c @@ -793,6 +793,120 @@ test_certificate_ip_addresses (void) g_object_unref (cert); } +static GByteArray * +load_bytes_for_test_file (const char *filename) +{ + GFile *file = g_file_new_for_path (tls_test_file_path (filename)); + GBytes *bytes = g_file_load_bytes (file, NULL, NULL, NULL); + + g_assert_nonnull (bytes); + g_object_unref (file); + return g_bytes_unref_to_array (bytes); +} + +static void +assert_cert_contains_cert_and_key (GTlsCertificate *certificate) +{ + char *cert_pem, *key_pem; + + g_object_get (certificate, + "certificate-pem", &cert_pem, + "private-key-pem", &key_pem, + NULL); + + g_assert_nonnull (cert_pem); + g_assert_nonnull (key_pem); + + g_free (cert_pem); + g_free (key_pem); +} + +static void +assert_equals_original_cert (GTlsCertificate *cert) +{ + GTlsCertificate *original_cert = g_tls_certificate_new_from_file (tls_test_file_path ("client-and-key.pem"), NULL); + g_assert_nonnull (original_cert); + g_assert_true (g_tls_certificate_is_same (original_cert, cert)); + g_object_unref (original_cert); +} + +static void +test_certificate_pkcs12_basic (void) +{ + GTlsCertificate *cert; + GByteArray *pkcs12_data; + GError *error = NULL; + + pkcs12_data = load_bytes_for_test_file ("client-and-key.p12"); + cert = g_tls_certificate_new_from_pkcs12 (pkcs12_data->data, pkcs12_data->len, NULL, &error); + + g_assert_no_error (error); + g_assert_nonnull (cert); + assert_cert_contains_cert_and_key (cert); + assert_equals_original_cert (cert); + + g_byte_array_unref (pkcs12_data); + g_object_unref (cert); +} + +static void +test_certificate_pkcs12_password (void) +{ + GTlsCertificate *cert; + GByteArray *pkcs12_data; + GError *error = NULL; + + pkcs12_data = load_bytes_for_test_file ("client-and-key-password.p12"); + + /* Without a password it fails. */ + cert = g_tls_certificate_new_from_pkcs12 (pkcs12_data->data, pkcs12_data->len, NULL, &error); + g_assert_error (error, G_TLS_ERROR, G_TLS_ERROR_BAD_CERTIFICATE_PASSWORD); + g_clear_error (&error); + + /* With the wrong password it fails. */ + cert = g_tls_certificate_new_from_pkcs12 (pkcs12_data->data, pkcs12_data->len, "oajfo", &error); + g_assert_error (error, G_TLS_ERROR, G_TLS_ERROR_BAD_CERTIFICATE_PASSWORD); + g_clear_error (&error); + + /* With the correct password it succeeds. */ + cert = g_tls_certificate_new_from_pkcs12 (pkcs12_data->data, pkcs12_data->len, "1234", &error); + g_assert_no_error (error); + g_assert_nonnull (cert); + assert_cert_contains_cert_and_key (cert); + assert_equals_original_cert (cert); + g_object_unref (cert); + g_byte_array_unref (pkcs12_data); +} + +static void +test_certificate_pkcs12_encrypted (void) +{ + GTlsCertificate *cert; + GByteArray *pkcs12_enc_data; + GError *error = NULL; + + pkcs12_enc_data = load_bytes_for_test_file ("client-and-key-password-enckey.p12"); + + /* Without a password it fails. */ + cert = g_tls_certificate_new_from_pkcs12 (pkcs12_enc_data->data, pkcs12_enc_data->len, NULL, &error); + g_assert_error (error, G_TLS_ERROR, G_TLS_ERROR_BAD_CERTIFICATE_PASSWORD); + g_clear_error (&error); + + /* With the wrong password it fails. */ + cert = g_tls_certificate_new_from_pkcs12 (pkcs12_enc_data->data, pkcs12_enc_data->len, "oajfo", &error); + g_assert_error (error, G_TLS_ERROR, G_TLS_ERROR_BAD_CERTIFICATE_PASSWORD); + g_clear_error (&error); + + /* With the correct password it succeeds. */ + cert = g_tls_certificate_new_from_pkcs12 (pkcs12_enc_data->data, pkcs12_enc_data->len, "1234", &error); + g_assert_no_error (error); + g_assert_nonnull (cert); + assert_cert_contains_cert_and_key (cert); + assert_equals_original_cert (cert); + g_object_unref (cert); + g_byte_array_unref (pkcs12_enc_data); +} + int main (int argc, char *argv[]) @@ -862,5 +976,9 @@ main (int argc, g_test_add_func ("/tls/" BACKEND "/certificate/dns-names", test_certificate_dns_names); g_test_add_func ("/tls/" BACKEND "/certificate/ip-addresses", test_certificate_ip_addresses); + g_test_add_func ("/tls/" BACKEND "/certificate/pkcs12/basic", test_certificate_pkcs12_basic); + g_test_add_func ("/tls/" BACKEND "/certificate/pkcs12/password", test_certificate_pkcs12_password); + g_test_add_func ("/tls/" BACKEND "/certificate/pkcs12/encrypted", test_certificate_pkcs12_encrypted); + return g_test_run(); } diff --git a/tls/tests/files/client-and-key-fullchain.pem b/tls/tests/files/client-and-key-fullchain.pem new file mode 100644 index 0000000..591d2c0 --- /dev/null +++ b/tls/tests/files/client-and-key-fullchain.pem @@ -0,0 +1,77 @@ +-----BEGIN CERTIFICATE----- +MIIE4zCCA8ugAwIBAgIUQL/y3nsri2som8J5/D+Hm8ljMwcwDQYJKoZIhvcNAQEL +BQAwgYYxEzARBgoJkiaJk/IsZAEZFgNDT00xFzAVBgoJkiaJk/IsZAEZFgdFWEFN +UExFMR4wHAYDVQQLDBVDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxFzAVBgNVBAMMDmNh +LmV4YW1wbGUuY29tMR0wGwYJKoZIhvcNAQkBFg5jYUBleGFtcGxlLmNvbTAgFw0y +MTA3MzExODEzMTBaGA8yMDUxMDcyNDE4MTMxMFowgYYxEzARBgoJkiaJk/IsZAEZ +FgNDT00xFzAVBgoJkiaJk/IsZAEZFgdFWEFNUExFMR4wHAYDVQQLDBVDZXJ0aWZp +Y2F0ZSBBdXRob3JpdHkxFzAVBgNVBAMMDmNhLmV4YW1wbGUuY29tMR0wGwYJKoZI +hvcNAQkBFg5jYUBleGFtcGxlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC +AQoCggEBALk97CGeG3O95ZKKTbZ25xkZdeKkXm1fQZRwjK1FwC+XMG1ehGtI40zG +rb8ayC/olqoMFqz4yUrkb4qpzau8Uml+jZSOx+E3VsLS41lrgMf4k4lgYqghgXpu ++ErDwL2crJR1IQsKSk/xWeltSZuDkZjUSUqK6SfhC7XZ9PAJmb+Km5YqZ2Bnniox +K1lMC25BFtYyXMje0/+15r/Am0+5ek2HMHmD2nCAaHeXEU4mn30lPGEkq9l7nNpo +vH9Rei8mCuZtXkeuzpcO7icRTusI8VBAPXvYB5d3GRmcECnV6jBwWZ0MAQ6ib+td +T/PkjEkR4oncAsyO8cRw25gltPo+DpECAwEAAaOCAUMwggE/MB0GA1UdDgQWBBR9 +MHdtjvb0Yq9WTAKv4wB756MpeTCBxgYDVR0jBIG+MIG7gBR9MHdtjvb0Yq9WTAKv +4wB756MpeaGBjKSBiTCBhjETMBEGCgmSJomT8ixkARkWA0NPTTEXMBUGCgmSJomT +8ixkARkWB0VYQU1QTEUxHjAcBgNVBAsMFUNlcnRpZmljYXRlIEF1dGhvcml0eTEX +MBUGA1UEAwwOY2EuZXhhbXBsZS5jb20xHTAbBgkqhkiG9w0BCQEWDmNhQGV4YW1w +bGUuY29tghRAv/LeeyuLayibwnn8P4ebyWMzBzAPBgNVHRMBAf8EBTADAQH/MA4G +A1UdDwEB/wQEAwIBBjAZBgNVHREEEjAQgQ5jYUBleGFtcGxlLmNvbTAZBgNVHRIE +EjAQgQ5jYUBleGFtcGxlLmNvbTANBgkqhkiG9w0BAQsFAAOCAQEAVn5Zp/2oUFAO +Ork8QU7IJo9a/NEfBMOJfFQBXyN8l7AKux/wDICDqd+Hmeb3yoPx/Yy+5Z/BoEdY +H+sG5gAGK8Kd5KsQxfcPW6uQMQ8K+WEmtdeT2OjDkKzkLhMfAXbaSOrGf/95rMk8 +Tq/Cx7csH+M21m8ZvrvJCHFr673d4GvWKN7nfa7xcd2ErvKWLEIiyp607AfD5wHg +cKm0LtC9RCVABGrS7tvW6DfR2V0QNKk/+OlWAqPXzElJwZPwI4CdGjAVfYkEfE86 +uTWT08HDZM5gD1ohhUPEnNxma1HkMOnBhhxmnA3HfFB7l6BPPAj4xmv/tQv5BtfT +QSNhrzqDvA== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDXTCCAkUCAQQwDQYJKoZIhvcNAQELBQAwgYYxEzARBgoJkiaJk/IsZAEZFgND +T00xFzAVBgoJkiaJk/IsZAEZFgdFWEFNUExFMR4wHAYDVQQLDBVDZXJ0aWZpY2F0 +ZSBBdXRob3JpdHkxFzAVBgNVBAMMDmNhLmV4YW1wbGUuY29tMR0wGwYJKoZIhvcN +AQkBFg5jYUBleGFtcGxlLmNvbTAeFw0yMTA3MzExODEzMTBaFw00NjA3MjUxODEz +MTBaMGIxEzARBgoJkiaJk/IsZAEZFgNDT00xFzAVBgoJkiaJk/IsZAEZFgdFWEFN +UExFMQ8wDQYDVQQDDAZDbGllbnQxITAfBgkqhkiG9w0BCQEWEmNsaWVudEBleGFt +cGxlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOPbuZMMuAYN +HHfO9oXuDJG2vNcphC4nEoldJrS4Wr7X5RUXlVUHyHiwY2S7qXstZP25m6H9Obl4 +2AysGDYccKSm0/Ne97CGkTuMSoJFfm8EP1W5hn2FyiAmcJJDEA4s9AG7ZNuZtbi7 +LMp5M0J7Qyj/7AKruaKYXfB1CWHAR5B9mAqE11hGZJcUAN4gxV7IVNPYk6bnhUgj +EH8eiCfs6yUB3CqZ1S7LICvC9jwg2J/+Qkfm0tfHbvtoyAEb7tFVWbZ3GcgUfntN +ixe+1Um3s8pyB+wVznv65cEjCPvgqMMJVfS9oMV7Lg7TuNqjirzaSSGSVWGuR3Iy +VmjtfpGk9R8CAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAZs33954DJg4+NJzt8QKI +5+aDeBb5FcnwvIbx7QpsSPuJJOuamLX8fo4x7VZut3y5VqyK1QFIE8dWNCotVP5r +I4xFFYG6CEKkzc/fZ8FTMCYFoGVxUce2PMX/XcZuYWaO+F7Gz8LzW1CbYzbFmAyZ +ZUl0WOeFbWl/yQmwym5ZFKLogZXL0ZHtwNKHH0LiKOyUssiWbN1cD7BQaiuXcsKS +JjWsl2j5pi+07WaGZGk+MB8mFl56I9u/43qdaxf1lWicyj6QiwvZf/WVxi5dT3zA +8IEOS5j2Ahg2xP/ot24R/7+d4eV5m27qfqzB4HT7y1bl0Hi5lXl1O6qzmqJo7Z49 +zg== +-----END CERTIFICATE----- +-----BEGIN RSA PRIVATE KEY----- +MIIEowIBAAKCAQEA49u5kwy4Bg0cd872he4Mkba81ymELicSiV0mtLhavtflFReV +VQfIeLBjZLupey1k/bmbof05uXjYDKwYNhxwpKbT8173sIaRO4xKgkV+bwQ/VbmG +fYXKICZwkkMQDiz0Abtk25m1uLssynkzQntDKP/sAqu5ophd8HUJYcBHkH2YCoTX +WEZklxQA3iDFXshU09iTpueFSCMQfx6IJ+zrJQHcKpnVLssgK8L2PCDYn/5CR+bS +18du+2jIARvu0VVZtncZyBR+e02LF77VSbezynIH7BXOe/rlwSMI++CowwlV9L2g +xXsuDtO42qOKvNpJIZJVYa5HcjJWaO1+kaT1HwIDAQABAoIBAFr6JStQfb10yLQR +f57UAFLByr6CBhPDaAROnCC2Jw1h+EampupPdDyz+MuEnlPfOR6RWFGiYMTsOh89 +K2GXk2Y6chAPEAh8gkprZmiDRMsgwAUDUW6W17BkiLftbOCsFDUI1GlWAxeiLG0f +XVcjDhq1rE8Yr8L64S8cG8Xa1vgaXI6YpPch8YaBXQrBtZZsKiqmD8OUcE/sj1rc +jrSuwTYmR9wqNymJH1b21cDhCKcU2UAUAhbLWm6k9rhKGEvbcrFcBVe6cRjY10h3 +RahLV8geyNKtundqg4Fajw5i74SxRHqnGrrK99EAYOyehxI0hjAPlrUmUsx5juwX +DuThPrECgYEA9jTMikAY7TIZOb2R1Dmy4ob3jGV23YoetSb/RyDuIYI1FhOxk8M7 +Lh61zdcnih4q4AZU4f+tSrLM0faVO+Qm/aPsXcJZSw6voOLX7crWA6RoffrNXpcr +I8QfBqXoDosUEZhu+ZWTOHU3jaUEZojT3HVii3dnDe8lcg2fURZ8CxcCgYEA7OwV +Jis3geW4JeqimmKYCcb2eCYX/XhK5s0fIY1TUQc2BcjG5qmsfBK5WM4Y/9kgiqRy +kGb0KSLcf4EGA2UMfARPXMjGBd7O7ZGw97h52OQ9KntwAlk+M88IkGtgiBB8B8/6 +vOM1NlYm9KNdz7yYJyWKhX5CpYWNKDybBBanizkCgYAfFk2ZSzyafo/m1YPbSynG +JoqNRKZ8lJsJ/pGPFp5axskTL4tlf+oyCZilE/yfGO4K+WGwY4sq+maYQE1ZkZZG +wnLu58JEkuckJmBjWxAox5KWDZvuzKGa04GjYkFpzK/NBPVGOFetckeAcAydMbum +g3/c4ke137NXslaic3dYIwKBgQCEJk7JonNsngCwDYczC+l4EqVpcP4SoKVOxX0m +zth5KseERHBFOsD918fQc+zX0HlpO763MuXfiBVrfUEoZZWoGxNVUpu5rITJWGlY +U2qLgwtnBcD9Xl/msAU74NjQLDmyddyKvUTyEO3bqL/r3msT8smoGjv8bVjF58Aj +cKt1aQKBgF8WJ/5JbhEUvhv9+2tkSGXsoGVRZkHVeMr++NCJH4Ee6U2eKeq2DOYA +e8ex5fKJPcjoaXeguKYaP3lsFVdT+F9bj7+L1RpJea06ovYbTs7wAyzxURLOjbfy +0SUZG8hhBhdcqz+RVvqnQeYFe8k/c4RVZQeEgtBGChevJtT4ymY3 +-----END RSA PRIVATE KEY----- diff --git a/tls/tests/files/client-and-key-password-enckey.p12 b/tls/tests/files/client-and-key-password-enckey.p12 Binary files differnew file mode 100644 index 0000000..5100a15 --- /dev/null +++ b/tls/tests/files/client-and-key-password-enckey.p12 diff --git a/tls/tests/files/client-and-key-password.p12 b/tls/tests/files/client-and-key-password.p12 Binary files differnew file mode 100644 index 0000000..7d863b3 --- /dev/null +++ b/tls/tests/files/client-and-key-password.p12 diff --git a/tls/tests/files/client-and-key.p12 b/tls/tests/files/client-and-key.p12 Binary files differnew file mode 100644 index 0000000..9bccfcf --- /dev/null +++ b/tls/tests/files/client-and-key.p12 diff --git a/tls/tests/files/create-files.sh b/tls/tests/files/create-files.sh index ca1b842..d350e69 100755 --- a/tls/tests/files/create-files.sh +++ b/tls/tests/files/create-files.sh @@ -133,6 +133,10 @@ msg "Concatenating client certificate and private key into a single file" cat client.pem > client-and-key.pem cat client-key.pem >> client-and-key.pem +msg "Concatenating the full client chain into a single file" +cat ca.pem > client-and-key-fullchain.pem +cat client-and-key.pem >> client-and-key-fullchain.pem + # It is not possible to specify the start and end date using the "x509" tool. # It would be better to use the "ca" tool. Sorry! msg "Creating client certificate (past)" @@ -221,6 +225,18 @@ msg "Updating test expectations" ./update-certificate-test.py server.pem ../certificate.h ####################################################################### +### Generate PKCS #12 format copies for testing +####################################################################### + +msg "Generating PKCS #12 files" +# Not encrypted p12 file +openssl pkcs12 -in client-and-key.pem -export -keypbe NONE -certpbe NONE -nomaciter -out client-and-key.p12 -passout 'pass:' -name "No password" +# Encrypted key only +openssl pkcs12 -in client-and-key.pem -export -certpbe NONE -nomaciter -out client-and-key-password.p12 -passout 'pass:1234' -name "With Password" +# Encrypted p12 file +openssl pkcs12 -in client-and-key.pem -export -out client-and-key-password-enckey.p12 -passout 'pass:1234' -name "With Password and encrypted privkey" + +####################################################################### ### Cleanup ####################################################################### |