diff --git a/src/rdkafka.c b/src/rdkafka.c index c6f89ad469..9444bbf55c 100644 --- a/src/rdkafka.c +++ b/src/rdkafka.c @@ -2337,6 +2337,23 @@ rd_kafka_t *rd_kafka_new(rd_kafka_type_t type, else conf = app_conf; + /* Set default FIPS and debug configuration */ + if (rd_kafka_conf_set(conf, "ssl.providers", "fips,base", errstr, + errstr_size) != RD_KAFKA_CONF_OK) { + if (!app_conf) + rd_kafka_conf_destroy(conf); + rd_kafka_set_last_error(RD_KAFKA_RESP_ERR__INVALID_ARG, EINVAL); + return NULL; + } + if (rd_kafka_conf_set(conf, "debug", "security", errstr, + errstr_size) != RD_KAFKA_CONF_OK) { + if (!app_conf) + rd_kafka_conf_destroy(conf); + rd_kafka_set_last_error(RD_KAFKA_RESP_ERR__INVALID_ARG, EINVAL); + return NULL; + } + + /* Verify and finalize configuration */ if ((conf_err = rd_kafka_conf_finalize(type, conf))) { /* Incompatible configuration settings */ diff --git a/tests/0154-ssl_keys_3des_fips.c b/tests/0154-ssl_keys_3des_fips.c new file mode 100644 index 0000000000..b5feebc8fd --- /dev/null +++ b/tests/0154-ssl_keys_3des_fips.c @@ -0,0 +1,126 @@ +/* + * librdkafka - Apache Kafka C library + * + * Copyright (c) 2025, Magnus Edenhill + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "test.h" +#include "rdstring.h" + +/** + * @brief Tests that 3DES encrypted SSL keys/keystores are rejected when + * FIPS mode is enabled. + * + * Uses keys from fixtures/ssl/fips_testing that are encrypted with 3DES, + * which is not FIPS 140-3 compliant and should fail to load. + */ +static void do_test_3des_keys_fail(const char *type) { +#define TEST_FIPS_FIXTURES_FOLDER "./fixtures/ssl/fips_testing/" +#define TEST_FIPS_KEYSTORE_PASSWORD "use_strong_password_keystore_client" +#define TEST_FIPS_KEY_PASSWORD "use_strong_password_keystore_client2" +#define TEST_FIPS_KEYSTORE_LOCATION TEST_FIPS_FIXTURES_FOLDER "client.keystore.p12" +#define TEST_FIPS_CERTIFICATE_LOCATION \ + TEST_FIPS_FIXTURES_FOLDER "client2.certificate.pem" +#define TEST_FIPS_KEY_LOCATION TEST_FIPS_FIXTURES_FOLDER "client2.key" + + rd_kafka_conf_t *conf; + rd_kafka_t *rk; + char errstr[512]; + + SUB_TEST_QUICK("3DES keystore type = %s, expect failure in FIPS mode", + type); + + /* Don't use test_conf_init otherwise + * key file configuration value conflicts + * with PEM string configuration, + * when running in --ssl mode. */ + conf = rd_kafka_conf_new(); + test_conf_set(conf, "security.protocol", "SSL"); + + if (!strcmp(type, "PKCS12")) { + test_conf_set(conf, "ssl.keystore.location", + TEST_FIPS_KEYSTORE_LOCATION); + test_conf_set(conf, "ssl.keystore.password", + TEST_FIPS_KEYSTORE_PASSWORD); + } else if (!strcmp(type, "PEM")) { + test_conf_set(conf, "ssl.certificate.location", + TEST_FIPS_CERTIFICATE_LOCATION); + test_conf_set(conf, "ssl.key.location", + TEST_FIPS_KEY_LOCATION); + test_conf_set(conf, "ssl.key.password", + TEST_FIPS_KEY_PASSWORD); + } else if (!strcmp(type, "PEM_STRING")) { + char buf[1024 * 50]; + if (!test_read_file(TEST_FIPS_CERTIFICATE_LOCATION, buf, + sizeof(buf))) + TEST_FAIL("Failed to read certificate file\n"); + test_conf_set(conf, "ssl.certificate.pem", buf); + + if (!test_read_file(TEST_FIPS_KEY_LOCATION, buf, sizeof(buf))) + TEST_FAIL("Failed to read key file\n"); + test_conf_set(conf, "ssl.key.pem", buf); + + test_conf_set(conf, "ssl.key.password", + TEST_FIPS_KEY_PASSWORD); + } else { + TEST_FAIL("Unexpected key type\n"); + } + + /* Attempt to create Kafka client - should FAIL due to 3DES in FIPS + * mode */ + rk = rd_kafka_new(RD_KAFKA_PRODUCER, conf, errstr, sizeof(errstr)); + if (rk != NULL) { + TEST_FAIL( + "Expected rd_kafka creation to fail with 3DES encrypted " + "keys in FIPS mode, but it succeeded\n"); + rd_kafka_destroy(rk); + } else { + TEST_SAY( + "rd_kafka_new() correctly failed with 3DES keys in FIPS " + "mode: %s\n", + errstr); + /* Configuration is destroyed by rd_kafka_new on failure */ + } + + SUB_TEST_PASS(); + +#undef TEST_FIPS_KEYSTORE_PASSWORD +#undef TEST_FIPS_KEY_PASSWORD +#undef TEST_FIPS_KEYSTORE_LOCATION +#undef TEST_FIPS_CERTIFICATE_LOCATION +#undef TEST_FIPS_KEY_LOCATION +#undef TEST_FIPS_FIXTURES_FOLDER +} + + +int main_0154_ssl_keys_3des_fips(int argc, char **argv) { + /* Test all three key format types with 3DES encryption + * All should fail when FIPS mode is enabled */ + do_test_3des_keys_fail("PKCS12"); + do_test_3des_keys_fail("PEM"); + do_test_3des_keys_fail("PEM_STRING"); + + return 0; +} \ No newline at end of file diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 324281bd99..592949e36c 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -144,6 +144,7 @@ set( 0151-purge-brokers.c 0152-rebootstrap.c 0153-memberid.c + 0154-ssl_keys_3des_fips.c 8000-idle.cpp 8001-fetch_from_follower_mock_manual.c test.c diff --git a/tests/fixtures/ssl/fips_testing/Makefile b/tests/fixtures/ssl/fips_testing/Makefile new file mode 100644 index 0000000000..d12bbda9f2 --- /dev/null +++ b/tests/fixtures/ssl/fips_testing/Makefile @@ -0,0 +1,8 @@ +ssl_keys: clear_keys + @./create_keys.sh client client2 + +clear_keys: + @rm -f *.key *.crt *.jks \ + *.csr *.pem *.p12 *.srl extfile + +.PHONY: ssl_keys diff --git a/tests/fixtures/ssl/fips_testing/client.keystore.intermediate.p12 b/tests/fixtures/ssl/fips_testing/client.keystore.intermediate.p12 new file mode 100644 index 0000000000..2e9411e2fa Binary files /dev/null and b/tests/fixtures/ssl/fips_testing/client.keystore.intermediate.p12 differ diff --git a/tests/fixtures/ssl/fips_testing/client.keystore.p12 b/tests/fixtures/ssl/fips_testing/client.keystore.p12 new file mode 100644 index 0000000000..b69707a52d Binary files /dev/null and b/tests/fixtures/ssl/fips_testing/client.keystore.p12 differ diff --git a/tests/fixtures/ssl/fips_testing/client2.certificate.intermediate.pem b/tests/fixtures/ssl/fips_testing/client2.certificate.intermediate.pem new file mode 100644 index 0000000000..f900d05705 --- /dev/null +++ b/tests/fixtures/ssl/fips_testing/client2.certificate.intermediate.pem @@ -0,0 +1,67 @@ +Bag Attributes + friendlyName: client2 + localKeyID: 26 88 82 5A 6E 8F 23 CB 4A 44 A6 28 DB BD 9C B8 9F 0C 8E EF +subject=C=, ST=, L=, O=, OU=, CN=client2 +issuer=CN=caintermediate +-----BEGIN CERTIFICATE----- +MIIDUzCCAjugAwIBAgIUZS7m395fM40loForE9ZxHEQMkq0wDQYJKoZIhvcNAQEL +BQAwGTEXMBUGA1UEAwwOY2FpbnRlcm1lZGlhdGUwIBcNMjUxMTI1MTc1NTAyWhgP +MjA1MzA0MTExNzU1MDJaMEkxCTAHBgNVBAYTADEJMAcGA1UECBMAMQkwBwYDVQQH +EwAxCTAHBgNVBAoTADEJMAcGA1UECxMAMRAwDgYDVQQDEwdjbGllbnQyMIIBIjAN +BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAgm01byBcria/QdtRfbpbR0ST3A+/ +4QygJhNOERYKCVQ/fNq2BdEzdF5+cqylnV1UYd5ODBynCVdIRUcwb8ISqai9fl03 +IAsM8zizl2FMTfRqaMjcCsJyzVqy/U73Ed2rm+2ZRA2jSJ2meajXnQhyC/0J7rhQ +rW4ZH/rGSJYshIPiYQNVXWVjnXseojgnaiuN+tw6EvqQayz7EFgIyXlARq6cIlSA +YNRwLbNFQ5wMCMVGG0THw8G6DyAtiVp4l/DINaFV0A6gTd/2U5w1AUynrIdFfZcj +o6lD0VFQpnhJJX1hl2eGsO4bkdl2WnUoZI3c5irvfzR1XZxOTCP3w/BgtwIDAQAB +o2EwXzAdBgNVHREEFjAUggdjbGllbnQygglsb2NhbGhvc3QwHQYDVR0OBBYEFMfW +ZJkGeAPK3l8ETi6StqDEMlzrMB8GA1UdIwQYMBaAFC8GeBMyq3WJhjVcygXYg5R2 +UwiaMA0GCSqGSIb3DQEBCwUAA4IBAQCYqz1qn2bcPdgxrcyzyuQtqOcsVoMyEODO +XBcXKftKvyrjrBxSJes0hfPuH+F48zEVWJExqA90JFOMw8hslgZlj9HYQt0fQw/2 +P5+QkajBCJgxrTP7tnoVeX5FNoY1zBxoiH07AshbBYAyRZ8rQVTj5rV0LtmBfhb2 ++0hmuxE6GVM7ftEbwoTI1op6AiV32xORnsR08ELZbe3+o9WzUypAuYVv9T2mJJ+u +g/+ZXKs4FtxVTIa6dcB0z5gR2zipI0oi8jzoC6MqwZc8Z433L2JSqj4+xB7/GSAZ +jUJZzcq20YkEMjEmABVxXRN8sRMdgKCKZCm4JXieGrnV1ll4UCTC +-----END CERTIFICATE----- +Bag Attributes: +subject=CN=caintermediate +issuer=CN=caroot +-----BEGIN CERTIFICATE----- +MIIC+jCCAeKgAwIBAgIUEb7JmmOH1eAXu8q/HZBQe1kwA/QwDQYJKoZIhvcNAQEL +BQAwETEPMA0GA1UEAwwGY2Fyb290MB4XDTI1MTEyNTE3NTQ1OFoXDTM1MTEyMzE3 +NTQ1OFowGTEXMBUGA1UEAwwOY2FpbnRlcm1lZGlhdGUwggEiMA0GCSqGSIb3DQEB +AQUAA4IBDwAwggEKAoIBAQC0KdfACN5Y3b88l50Vu+3MXT/vVnZBv2CWgxXWFZtD +oPklE5g71zAdFf+grNDDIRyWO2oU93VVK/cNtxKE+PMr4D3gvBZnYDSiBwvuVNIo ++WnEEsIWVoewAlFSv3NAMynrmJ+ign6pDTCBanvYSu8/e7ZwLD6YiqNghlRfGGia +/g2K7kzlEsVb34ABJqKbxuTzImHIzqy98TVqnJj5+4OohWSMV8MIBbdkOJOxtLm0 +GLZ6puUAVHrpZZ/ie2l2w3y3CSjYEmfxZ4nwIvnkimXxBKqS5WG7NLNa8zlNsZFr +W6ADH60DNSBAjq/lARD8y8eJUS/PtuTPJucM/QNXMcoRAgMBAAGjQjBAMB0GA1Ud +DgQWBBQvBngTMqt1iYY1XMoF2IOUdlMImjAfBgNVHSMEGDAWgBRT0wgXL6D9sWYZ +tI4TrEv1V1sQ6jANBgkqhkiG9w0BAQsFAAOCAQEAiMbK67NhimMdCJVeQt9Ucwkd +UODxn6KH2WRCNA3Zp4hsofYcnqT/kHU4QFGs+JQyUzv8hlEz7YKA5qaSG+V85urQ +vORTmlY5R2AmPp23hB+cXyMIZh2pbcMhL4hWAAmjKAkLhvSCWxdkhwr3aid61qN1 +4aDt2xgaRmtaNfqglTeEbgz6oWfpWL7JtiyZbf4CRXCIn0h8WtrrpKtniAcPnwA7 +FMnho5q6gLrAHmESMaJR1fkBw0hIMjT3/S/CBQkPqZAe/ZDBK0SsjHuk3HVuv7WU +uh8BLXePCNi2EoJLT6tEJe0bfRxLjAzUBuv1aPXSGKziXf420nHQWhwLnnldlQ== +-----END CERTIFICATE----- +Bag Attributes: +subject=CN=caroot +issuer=CN=caroot +-----BEGIN CERTIFICATE----- +MIIC0TCCAbmgAwIBAgIUIZuT3ZRi/rg5tp/nJdJfMX7LqFswDQYJKoZIhvcNAQEL +BQAwETEPMA0GA1UEAwwGY2Fyb290MB4XDTI1MTEyNTE3NTQ1OFoXDTI1MTIyNTE3 +NTQ1OFowETEPMA0GA1UEAwwGY2Fyb290MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A +MIIBCgKCAQEArvN1tXJiIvX6EOcOdHsKbsec3vg1u18JrvWkLV5ApF6I230x+vp3 +HP/4C4yxCjhR/1QrZVaYeaMPpm2T1Q21XxZBacl4SStQRbfho0vhZTNrQPN1SQKD +ICU8xjRe3+Nwtt1CEdbOP3NaEAZt7nUf4qViX/xUJzTj0POZ+dwImWf3WaDkmzL9 +94G7beei2OjWsLPZgXaVglNRAT8cyY5zXgY1gltSrjD1M/qJ7qGCufpCo3WbGIgN +nfROpDMqNUrjTJxWSpEE/xvFOwWa4yOwP8hy+7ZooTUy3UFds4HG7PVjgPF9Hg3N +4cDKFhg79ddyx/so6b80QiptxWoaPvcQ4QIDAQABoyEwHzAdBgNVHQ4EFgQUU9MI +Fy+g/bFmGbSOE6xL9VdbEOowDQYJKoZIhvcNAQELBQADggEBAJk4i0pcLTxBrInr +NVdDMwYK0ssIJ4TTicMosdsKYzT77UluJ23MklSMmv7Spl1rbC3zw252oH/hf0hS +FHN1z4Xfpi1DMPGLhWfMGQsPkYj+hIiXJoygfsUWjEpu1oR/kbycpjQDUaWMYvbs +mQYK6mBWa29qseXu5fvc9Q3PAJU3ZQrFjdk4QoJrJ3kw4Qskt+zGIx70iN7RyTQZ +WjAtEvLZlB+ZSNt54v3udcIsVm2yVEcHRB+1rnpufqVAZqIOmLmRQEUdPMFmmbTC +G/P/LmYrmWNUBblFpDNbgwAst1cpUQl+OrL11jOMCJvN94xaO/7p+nGgcNUswXU3 +ACnLv1g= +-----END CERTIFICATE----- diff --git a/tests/fixtures/ssl/fips_testing/client2.certificate.pem b/tests/fixtures/ssl/fips_testing/client2.certificate.pem new file mode 100644 index 0000000000..538ffdc32d --- /dev/null +++ b/tests/fixtures/ssl/fips_testing/client2.certificate.pem @@ -0,0 +1,46 @@ +Bag Attributes + friendlyName: client2 + localKeyID: 03 D1 53 C3 1C C5 9C 05 C8 62 44 FF F8 CA A4 20 00 95 DE B5 +subject=C=, ST=, L=, O=, OU=, CN=client2 +issuer=CN=caroot +-----BEGIN CERTIFICATE----- +MIIDSzCCAjOgAwIBAgIUVhvehT8q1VP+m37T/qOQiTEYDukwDQYJKoZIhvcNAQEL +BQAwETEPMA0GA1UEAwwGY2Fyb290MCAXDTI1MTEyNTE3NTUwNFoYDzIwNTMwNDEx +MTc1NTA0WjBJMQkwBwYDVQQGEwAxCTAHBgNVBAgTADEJMAcGA1UEBxMAMQkwBwYD +VQQKEwAxCTAHBgNVBAsTADEQMA4GA1UEAxMHY2xpZW50MjCCASIwDQYJKoZIhvcN +AQEBBQADggEPADCCAQoCggEBAKf9BTW43p3ii/W4mNEfSGq1inIyxgnCom99NrW0 +3QW1tWdzOmbXlxYPV/fKCPuNlponJyPekaD0nk8lHHd0XTaf+22HZoIlhM3bj/fR +Nv3ltJdxARHeBMXbT2y5sHV9xE5xvzoLjefOG6BZ+r/hf5+lLYsc5b+2yTY3tlkf +QgqXOO3zvMxMN5QyHKqjgtE4GvCQwcIZBZ09rNRxTdZ+CtCtrJF34ZwH0y/KytB+ +1HBxh6Y5pmSGS2tlT4zhpwjALTbo4/iZ39zl+phxOdNHDmSs0RE3PbqPXTk8DHAS +faWOqNsi5Oh/bliN5mMyHq+m5v2dAAfO+PF1wYmWBoxcZlUCAwEAAaNhMF8wHQYD +VR0RBBYwFIIHY2xpZW50MoIJbG9jYWxob3N0MB0GA1UdDgQWBBQK4ppiu5jPt14n +pXwjnt5Nbp/x4zAfBgNVHSMEGDAWgBRT0wgXL6D9sWYZtI4TrEv1V1sQ6jANBgkq +hkiG9w0BAQsFAAOCAQEAibGMDw1MP0plC4d3B7S5Auj7T1vx3pCX46v/R1mCzg1X +0aC/LuWIcxxLegBYhqF4m/4onBkeGt1tZuuVqWBEAJ/RUTaTuVjvPR3dYeOAteE6 +jVPfWNh2smNJ2CKTsM3/sIzt7jqujVZt1rCZs5M88qvHzorKv+BCzXb8onbcj/P3 +qVibud9Bl5t3aKQKviA7sepVdIdLIFnqcm80uhvhJau7fLhL4r+wvRo1wBRHz5IY +4KL4fKpPetUyLJexDXuK60NGBByWtO9WxKOZOgDK+qtvmwqK7C467dSBHT3QOKLc +hb0mhiATcDiQ+d9+OIbJvQ2bJHEAIMfXPWIAEdgEfA== +-----END CERTIFICATE----- +Bag Attributes: +subject=CN=caroot +issuer=CN=caroot +-----BEGIN CERTIFICATE----- +MIIC0TCCAbmgAwIBAgIUIZuT3ZRi/rg5tp/nJdJfMX7LqFswDQYJKoZIhvcNAQEL +BQAwETEPMA0GA1UEAwwGY2Fyb290MB4XDTI1MTEyNTE3NTQ1OFoXDTI1MTIyNTE3 +NTQ1OFowETEPMA0GA1UEAwwGY2Fyb290MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A +MIIBCgKCAQEArvN1tXJiIvX6EOcOdHsKbsec3vg1u18JrvWkLV5ApF6I230x+vp3 +HP/4C4yxCjhR/1QrZVaYeaMPpm2T1Q21XxZBacl4SStQRbfho0vhZTNrQPN1SQKD +ICU8xjRe3+Nwtt1CEdbOP3NaEAZt7nUf4qViX/xUJzTj0POZ+dwImWf3WaDkmzL9 +94G7beei2OjWsLPZgXaVglNRAT8cyY5zXgY1gltSrjD1M/qJ7qGCufpCo3WbGIgN +nfROpDMqNUrjTJxWSpEE/xvFOwWa4yOwP8hy+7ZooTUy3UFds4HG7PVjgPF9Hg3N +4cDKFhg79ddyx/so6b80QiptxWoaPvcQ4QIDAQABoyEwHzAdBgNVHQ4EFgQUU9MI +Fy+g/bFmGbSOE6xL9VdbEOowDQYJKoZIhvcNAQELBQADggEBAJk4i0pcLTxBrInr +NVdDMwYK0ssIJ4TTicMosdsKYzT77UluJ23MklSMmv7Spl1rbC3zw252oH/hf0hS +FHN1z4Xfpi1DMPGLhWfMGQsPkYj+hIiXJoygfsUWjEpu1oR/kbycpjQDUaWMYvbs +mQYK6mBWa29qseXu5fvc9Q3PAJU3ZQrFjdk4QoJrJ3kw4Qskt+zGIx70iN7RyTQZ +WjAtEvLZlB+ZSNt54v3udcIsVm2yVEcHRB+1rnpufqVAZqIOmLmRQEUdPMFmmbTC +G/P/LmYrmWNUBblFpDNbgwAst1cpUQl+OrL11jOMCJvN94xaO/7p+nGgcNUswXU3 +ACnLv1g= +-----END CERTIFICATE----- diff --git a/tests/fixtures/ssl/fips_testing/client2.intermediate.key b/tests/fixtures/ssl/fips_testing/client2.intermediate.key new file mode 100644 index 0000000000..c5a9b830c0 --- /dev/null +++ b/tests/fixtures/ssl/fips_testing/client2.intermediate.key @@ -0,0 +1,34 @@ +Bag Attributes + friendlyName: client2 + localKeyID: 26 88 82 5A 6E 8F 23 CB 4A 44 A6 28 DB BD 9C B8 9F 0C 8E EF +Key Attributes: +-----BEGIN ENCRYPTED PRIVATE KEY----- +MIIFJDBWBgkqhkiG9w0BBQ0wSTAxBgkqhkiG9w0BBQwwJAQQKX8XhLoOOxCA7lYK +JdbxUQICCAAwDAYIKoZIhvcNAgkFADAUBggqhkiG9w0DBwQI2UYkSOMbRasEggTI +8lqX14Issa6pl4VetvSYUeL4a8KnyXHSV6g12qlw/ojL4yh9lKF6qmMlpHO4Glrz +mYGUIaLAqChmxbwuQpUY77y32dN1/rcNmY1bG0qggsWwOgCale1SG59aCUbvX9BJ +fbm/OrrGj6pusI/1umryQckhheiB65aiLngFLYf+1oEKOgGMNf17Qei2QDErBoq+ +Opt6yXnp2oavlo7SPRX0uYishfoQSqpnLYpzcWlfGZAVY81lsEKSQjRECp42Cpah +A4IhhdteaeMNhqiz0rW5dK8LCwZZmaGBKxYUroOjbEnRslWA2F480DibLCl7V4Dn +B9+AAkkJjpTCuMQTeoxwWcQMxzHHktGmb6/YGoOr90SRLnt5Hnl4LjGVdLTFhsF9 +vSC481SFSjS3QaoLxnv9dRSyzhDDhO78w+4+TGAMfIUI10HnE0XCsp3twV35XdFR +l7pIuKLJ7oCQ/BUaoHJHFuw6vVlrEbgu/DAQZ66fAMo8u/oHDd4mBSv0Zh+2mjH6 +/sOo+lPVCKYKBj7JHhFW0AnuCRTrF7WF4foEZwZ3xabR55gD4hcHwuBpY1S5mrg2 +Cu8okYv33fPoOktAkM9IHkD4vUnZnfi1rm8pGVHCI3mcbzSpSBQHOaK9PLCfXKZq +Of5ajglJyWtk4+1gBhUX6anLepcCmGdnbdfKtROCBvcm4g87IdP9tQLLx2zHfQSf ++Z5feBrvrV/mB3DFUCkMIKxe6gKyXsCIA1bFKJsBitY2Zk9Wwe54bXmPGE5SviJh +tPRrOAia6wMe1hiYp80islvkL08Gml5Wqu52IgtMn5NjCNk6S/eWRqpYMKBZ02rA +3vIK/JsgUhZsZZV9YGZlrZ6fgwSnYFZjA8yH0yc9d8TlqmRqtEb2fJdg4sANLxCo +abJo6FfNX+kPO/6fp5MORjNhzpClmK8WXeJ133w/UFZquZkS8kemaQvHfw/z9eeS +kbJYPdKLijEtLIT0UTdmCwjli54GF398t7qpGud84bYAQe/naDifyuRYutC/R5wr +JKBoXJwQIJZg39xTDby/ObIXCibYUqzxFVt0nZLhKBouAEk362J7IOxmWIacXTaD +qAm4V/cU4R1hg5oXYn5x8Hxdk3pIW58PqBQZO7wxg1zGw4pSTzIkqKgU1eH6sPdM +Zu7T9zS5cNRntLy+A8NplR2tvft16MXArQQAyvVLvBQ/U/sHcO9BjsgV5BopYl7B +powXSKSvb+NsGSjHNUgj+Frr5DB7ifapJUNMhQI5AZadEx6cL5jHnhiHb2qP+4rH +eOxNFlM/EbeOtCsy6uSojuRbSycTwWvJ6Y0uhmSSj19i3Lp3KLaG0PkWoSK7IKlr +Mhr31vA4jl71hFKdPQQHrNQa4hOhk+otPj1+1t8tUU6gSDuK8imsSGoJESajTf1Q +Cf6gVJMCyZFW298O8zNrof8/2mGW8wG1Gm+xUAyNkktR/HZeu4Lhrx8sfxIUl5D1 +iT88onoND57MB+/fHBgnwpuqvmFZy6hlJfFc+nNnII6eV+hRJdz6ddJJ0h1fc/+c +lbJewG/EyhdGD+Kom6nAnaP0JTgKHr092iZFNx9UsuPnBK5mZiiD/pCZ0hmkq1kF +tdl5UUXLa0PDpBhn6WnopdRnQch8osJC +-----END ENCRYPTED PRIVATE KEY----- diff --git a/tests/fixtures/ssl/fips_testing/client2.key b/tests/fixtures/ssl/fips_testing/client2.key new file mode 100644 index 0000000000..ff025ae7d2 --- /dev/null +++ b/tests/fixtures/ssl/fips_testing/client2.key @@ -0,0 +1,34 @@ +Bag Attributes + friendlyName: client2 + localKeyID: 03 D1 53 C3 1C C5 9C 05 C8 62 44 FF F8 CA A4 20 00 95 DE B5 +Key Attributes: +-----BEGIN ENCRYPTED PRIVATE KEY----- +MIIFJDBWBgkqhkiG9w0BBQ0wSTAxBgkqhkiG9w0BBQwwJAQQGESZU3kCj6hqn0uu +v66y2QICCAAwDAYIKoZIhvcNAgkFADAUBggqhkiG9w0DBwQId+Jfp7qDjWEEggTI +QohK5ooTxQv2mO2IHbnJhGkuQqkObhAwAwXZCLgd74exzm9SJ6lN8LbdPutFxTnu +CCbxyfYRc8VzNBP41Ey+Zt/G8AAf8+eL5NXWS7+6kMatpnann489Je43N3DB3U6g +CBdOwU/lUwH9g7pDqyQbX3lSrqJLv62izv1zo9om1i9cYnK8hxgrl55gkQxuWnwk +yEkUkTIcpLZ9uqbmRKdu6xgTqqESODbImDaoFA8OYHIzdEk7Y3Yr0YUGB0zOgRn3 +99cxbsXFLJk+vsbhcF9SEDUUPR2I6YtfI5AQ7oq97x53rdVplaCk6g+4qTAjpAT5 +S+PFSgVvxTQRUkm7DtU4SC5mnCqAqPMX4zAObQe9CUBddkAo5CRPo0CH+xxRo051 +ZuIFn1mqsHRYy3pVFopgq46yCOkhO24X/TFtUiHcb4apgQE4hTrKQe75A/tJLcGv +VoZ5QnLK10eOcFoA5MS3ycX0bEsDPO3hNlgrnBUMwdftAcv8qdz8NJ8ZeFAYyy34 +F7ethL8Wuqrf/AWaM4gtZGHXt+KU56j7YFnF86VClytRQktzL5f3EkU2H3F3Vg3L +KP4f1Xp+fr+Tt4xzdTgk9JnbZWr5OeXoFK9GoNt6kTtUqwb32012RWVr7c04JUCt ++DcyADFr/jaQLsOQAnr0P7pIwOTNwHOewi8O5+KHgpvGRmL8+AuYlSpHNe4/UTPo +2JbX5Md298kfTG8XIQcPgwabiuAI0M5fB19r9tEeIpq7hFFA/lmnE8VbfnvUR99r +xD2PDtEPOzt79iWJzFFxRdYNyIo8qwjQNFEhwNoPBUt3+N0PCFuFBnz5BxGAI7V8 +Rlr6aXuMqj/i4jvgUYjb48kwCvWSfoz6Wq96Uq0S3fKzUXhft+6BwU8MH7zGSMxx +aqr/ddLTtJTOQR0AedPE9NcVC3FM+US/7fpH4KHg4+XbIIliIT6QPnKkhLq1vTyj +0fmeF68qsjGHiKHQdK58mFngM0DgNjh36MONfHrhxsXW1BYj6IPixjQgQKaHCqLL +0rMyZAxiG64wCaX3yeSvK/5L9JzW+fR2ikVipMDgWMho8sIEsey+nFQuggUYW+fk +L8XAS+t/HyyC7/iFdDRIbJ/G8PjM7ML0EGnTxxTXpXaglHRYI0xIL3he8j4ZolRz +gI1v0/EHdNcZr3A5TTvalHBGCVhtLoA4Jj64uCe8ti6wIUDdb6dd7p+2GfROmsb7 +6djzGdkqg2ittkinF4lCF95APMNdfNpEi2UzjL3jtplxyxC5ZD3+A4QEn1jKz6bQ +X3pHWChpaPH5UsxJouLUvQI4X7SO0Vp7Siejjlqe7jlSZIswGGzqSz3YBmI6r8O0 +3t6/ZjzeweGWsSd6lECmCrN7b26vdtFRBLoSm5QJCk+bbb/+DLiYnGu0DG272oE+ +Ay6Ewsnn988TDwqjHI65jfaxlBkNjJV+luQnwPR/Q3Yejun3ZboH5Gjf3BRM0/mT +iJcp2xF/lYWHrM1OneV1amz0vkpoFb907CCSr+/mWnTjmjWSp6nFrkY06nhq2o/X +/jDqDZ+IECj4xmlD3u7JmTLaGwLbIGU9BE5w5q7MOHziXcZwmiCbdEyqiCfNhMn5 +2QGkrZV1fnql08m87vCHYNjkDnGT5h// +-----END ENCRYPTED PRIVATE KEY----- diff --git a/tests/fixtures/ssl/fips_testing/create_keys.sh b/tests/fixtures/ssl/fips_testing/create_keys.sh new file mode 100755 index 0000000000..e8d8ac7528 --- /dev/null +++ b/tests/fixtures/ssl/fips_testing/create_keys.sh @@ -0,0 +1,189 @@ +#!/bin/sh +set -e +CA_PASSWORD="${CA_PASSWORD:-use_strong_password_ca}" +CA_INTERMEDIATE_PASSWORD="${CA_INTERMEDIATE_PASSWORD:-use_strong_password_intermediate_ca}" +KEYSTORE_PASSWORD="${KEYSTORE_PASSWORD:-use_strong_password_keystore}" +TRUSTSTORE_PASSWORD="${TRUSTSTORE_PASSWORD:-use_strong_password_truststore}" +OUTPUT_FOLDER=${OUTPUT_FOLDER:-$( dirname "$0" )} +CNS=${@:-client} + +cd ${OUTPUT_FOLDER} +CA_ROOT_KEY=${CA_ROOT_KEY:-caroot.key} +CA_ROOT_CRT=${CA_ROOT_CRT:-caroot.crt} +CA_INTERMEDIATE_KEY=intermediate.key +CA_INTERMEDIATE_CSR=intermediate.csr +CA_INTERMEDIATE_CRT=intermediate.crt + +generate_ca_extfile() { +echo "# $1: Generate extfile" +cat << EOF > extfile +[req] +distinguished_name=dn +[ dn ] +CN=$1 +[ ext ] +basicConstraints=CA:TRUE,pathlen:0 +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid:always, issuer:always +keyUsage = critical, cRLSign, digitalSignature, keyCertSign +extendedKeyUsage = clientAuth +EOF +} + +generate_client_certificate_extfile() { +local CN=$1 +echo "# $CN: Generate extfile" +cat << EOF > extfile +[req] +distinguished_name = req_distinguished_name +x509_extensions = v3_req +prompt = no +[req_distinguished_name] +CN = $CN +[v3_req] +subjectAltName = @alt_names +[alt_names] +DNS.1 = $CN +DNS.2 = localhost +EOF +} + +if [ ! -f $CA_ROOT_KEY -o ! -f $CA_ROOT_CRT ]; then + echo "# Generate CA" + generate_ca_extfile caroot + openssl req -new -x509 -config extfile -keyout $CA_ROOT_KEY \ + -out $CA_ROOT_CRT -subj \ + '/CN=caroot/OU=/O=/L=/ST=/C=' -passin "pass:${CA_PASSWORD}" \ + -passout "pass:${CA_PASSWORD}" +fi + +echo "# caintermediate: Generate CSR" +openssl req -new -keyout $CA_INTERMEDIATE_KEY \ + -out $CA_INTERMEDIATE_CSR -subj \ + '/CN=caintermediate/OU=/O=/L=/ST=/C=' \ + -passin "pass:${CA_INTERMEDIATE_PASSWORD}" \ + -passout "pass:${CA_INTERMEDIATE_PASSWORD}" + +generate_ca_extfile caintermediate + +echo "# caintermediate: Sign request" +openssl x509 -req -extfile extfile \ +-passin "pass:${CA_PASSWORD}" \ +-in "${CA_INTERMEDIATE_CSR}" \ +-CA "${CA_ROOT_CRT}" \ +-CAkey "${CA_ROOT_KEY}" \ +-days 3650 \ +-out "${CA_INTERMEDIATE_CRT}" + +for CN in $CNS; do +for INTERMEDIATE in true false; do + INTERMEDIATE_PREFIX="" + if [ $INTERMEDIATE = "true" ]; then + INTERMEDIATE_PREFIX=".intermediate" + fi + + KEYSTORE=${CN}.keystore${INTERMEDIATE_PREFIX}.p12 + TRUSTSTORE=${CN}.truststore${INTERMEDIATE_PREFIX}.p12 + CSR=${CN}${INTERMEDIATE_PREFIX}.csr + SIGNED_CRT=${CN}-ca-signed${INTERMEDIATE_PREFIX}.crt + CERTIFICATE=${CN}.certificate${INTERMEDIATE_PREFIX}.pem + KEY=${CN}${INTERMEDIATE_PREFIX}.key + # Get specific password for this CN + CN_KEYSTORE_PASSWORD="$(eval echo \$${CN}_KEYSTORE_PASSWORD)" + if [ -z "$CN_KEYSTORE_PASSWORD" ]; then + CN_KEYSTORE_PASSWORD=${KEYSTORE_PASSWORD}_$CN + fi + + echo "# $CN: Generate Keystore" + keytool -genkey -noprompt \ + -alias $CN \ + -dname "CN=$CN,OU=,O=,L=,S=,C=" \ + -ext "SAN=dns:$CN,dns:localhost" \ + -keystore $KEYSTORE \ + -keyalg RSA \ + -storepass "${CN_KEYSTORE_PASSWORD}" \ + -storetype pkcs12 + + echo "# $CN: Generate Truststore" + keytool -noprompt -keystore \ + $TRUSTSTORE -alias caroot -import \ + -file $CA_ROOT_CRT -storepass "${TRUSTSTORE_PASSWORD}" + + echo "# $CN: Generate CSR" + keytool -keystore $KEYSTORE -alias $CN \ + -certreq -file $CSR -storepass "${CN_KEYSTORE_PASSWORD}" \ + -keypass "${CN_KEYSTORE_PASSWORD}" \ + -ext "SAN=dns:$CN,dns:localhost" + + generate_client_certificate_extfile $CN + + echo "# $CN: Import root certificate" + keytool -noprompt -keystore $KEYSTORE \ + -alias caroot -import -file $CA_ROOT_CRT -storepass "${CN_KEYSTORE_PASSWORD}" + + if [ $INTERMEDIATE = "true" ]; then + echo "# $CN: Sign the certificate with the intermediate CA" + openssl x509 -req -CA $CA_INTERMEDIATE_CRT -CAkey $CA_INTERMEDIATE_KEY \ + -in $CSR \ + -out $SIGNED_CRT -days 9999 \ + -CAcreateserial -passin "pass:${CA_INTERMEDIATE_PASSWORD}" \ + -extensions v3_req -extfile extfile + + echo "# $CN: Import intermediate CA certificate" + keytool -noprompt -keystore $KEYSTORE \ + -alias caintermediate -import -file $CA_INTERMEDIATE_CRT \ + -storepass "${CN_KEYSTORE_PASSWORD}" + else + echo "# $CN: Sign the certificate with the CA" + openssl x509 -req -CA $CA_ROOT_CRT -CAkey $CA_ROOT_KEY \ + -in $CSR \ + -out $SIGNED_CRT -days 9999 \ + -CAcreateserial -passin "pass:${CA_PASSWORD}" \ + -extensions v3_req -extfile extfile + fi + + echo "# $CN: Import signed certificate" + keytool -noprompt -keystore $KEYSTORE -alias $CN \ + -import -file $SIGNED_CRT -storepass "${CN_KEYSTORE_PASSWORD}" \ + -ext "SAN=dns:$CN,dns:localhost" + + # Delete imported certificates as they were only used to import the + # signed certificate. + keytool -delete -alias caroot -keystore $KEYSTORE \ + -storepass "${CN_KEYSTORE_PASSWORD}" + if [ $INTERMEDIATE = "true" ]; then + keytool -delete -alias caintermediate -keystore $KEYSTORE \ + -storepass "${CN_KEYSTORE_PASSWORD}" + fi + + # Re-export keystore with 3DES encryption + echo "# $CN: Re-export keystore with 3DES encryption" + TEMP_KEYSTORE="${KEYSTORE}.tmp" + TEMP_PEM="${KEYSTORE}.pem" + mv "$KEYSTORE" "$TEMP_KEYSTORE" + + # Extract certificate and key to PEM format + openssl pkcs12 -in "$TEMP_KEYSTORE" -out "$TEMP_PEM" \ + -passin "pass:${CN_KEYSTORE_PASSWORD}" \ + -passout "pass:${CN_KEYSTORE_PASSWORD}" + + # Re-export to PKCS12 with 3DES encryption + openssl pkcs12 -export -in "$TEMP_PEM" -out "$KEYSTORE" \ + -passin "pass:${CN_KEYSTORE_PASSWORD}" \ + -passout "pass:${CN_KEYSTORE_PASSWORD}" \ + -name "$CN" \ + -keypbe PBE-SHA1-3DES -certpbe PBE-SHA1-3DES -macalg sha1 + + rm "$TEMP_KEYSTORE" "$TEMP_PEM" + + echo "# $CN: Export PEM certificate" + openssl pkcs12 -in "$KEYSTORE" -out "$CERTIFICATE" \ + -nokeys -passin "pass:${CN_KEYSTORE_PASSWORD}" + + echo "# $CN: Export PEM key with 3DES encryption" + openssl pkcs12 -in "$KEYSTORE" -out "$KEY" \ + -nocerts -passin "pass:${CN_KEYSTORE_PASSWORD}" \ + -passout "pass:${CN_KEYSTORE_PASSWORD}" \ + -des3 +done +done diff --git a/tests/test.c b/tests/test.c index 42e525a9cc..bbd669351c 100644 --- a/tests/test.c +++ b/tests/test.c @@ -272,6 +272,7 @@ _TEST_DECL(0150_telemetry_mock); _TEST_DECL(0151_purge_brokers_mock); _TEST_DECL(0152_rebootstrap_local); _TEST_DECL(0153_memberid); +_TEST_DECL(0154_ssl_keys_3des_fips); /* Manual tests */ _TEST_DECL(8000_idle); @@ -540,6 +541,7 @@ struct test tests[] = { _TEST(0151_purge_brokers_mock, TEST_F_LOCAL), _TEST(0152_rebootstrap_local, TEST_F_LOCAL), _TEST(0153_memberid, 0, TEST_BRKVER(0, 4, 0, 0)), + _TEST(0154_ssl_keys_3des_fips, TEST_F_LOCAL), /* Manual tests */ _TEST(8000_idle, TEST_F_MANUAL),