From: Adrian-Ken Rueegsegger Date: Thu, 22 Oct 2020 17:11:32 +0000 (+0200) Subject: charon-tkm: Reverse cert chain processing order X-Git-Tag: 5.9.2dr2~33 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a0a0571bd1a6eff9d42c668b26372bb45fb63dc0;p=thirdparty%2Fstrongswan.git charon-tkm: Reverse cert chain processing order Verify certificate chains starting from the root CA certificate and moving towards the leaf/user certificate. Also update TKM-RPC and TKM in testing scripts to version supporting the reworked CC handling. --- diff --git a/src/charon-tkm/src/tkm/tkm_listener.c b/src/charon-tkm/src/tkm/tkm_listener.c index 9e39308f82..18e3a54d8f 100644 --- a/src/charon-tkm/src/tkm/tkm_listener.c +++ b/src/charon-tkm/src/tkm/tkm_listener.c @@ -18,6 +18,7 @@ #include #include +#include #include #include #include @@ -94,125 +95,132 @@ static bool build_cert_chain(const ike_sa_t * const ike_sa, cc_id_type cc_id) rounds = ike_sa->create_auth_cfg_enumerator((ike_sa_t *)ike_sa, FALSE); while (rounds->enumerate(rounds, &auth)) { - cert = auth->get(auth, AUTH_RULE_SUBJECT_CERT); + cert = auth->get(auth, AUTH_RULE_CA_CERT); if (cert) { - chunk_t enc_user_cert; - ri_id_type ri_id; - certificate_type user_cert; auth_rule_t rule; enumerator_t *enumerator; + ca_id_type ca_id; + public_key_t *pubkey; + certificate_type ca_cert; + chunk_t enc_ca_cert, fp; + array_t *im_certs = NULL; + uint64_t *raw_id; + + pubkey = cert->get_public_key(cert); + if (!pubkey) + { + DBG1(DBG_IKE, "unable to get CA certificate pubkey"); + rounds->destroy(rounds); + return FALSE; + } + if (!pubkey->get_fingerprint(pubkey, KEYID_PUBKEY_SHA1, &fp)) + { + DBG1(DBG_IKE, "unable to extract CA certificate fingerprint"); + rounds->destroy(rounds); + pubkey->destroy(pubkey); + return FALSE; + } + pubkey->destroy(pubkey); + + raw_id = ca_map->get(ca_map, &fp); + if (!raw_id || *raw_id == 0) + { + DBG1(DBG_IKE, "error mapping CA certificate (fp: %#B) to " + "ID", &fp); + rounds->destroy(rounds); + return FALSE; + } + ca_id = *raw_id; - /* set user certificate */ - if (!cert->get_encoding(cert, CERT_ASN1_DER, &enc_user_cert)) + if (!cert->get_encoding(cert, CERT_ASN1_DER, &enc_ca_cert)) { - DBG1(DBG_IKE, "unable to extract encoded user certificate"); + DBG1(DBG_IKE, "unable to extract encoded CA certificate"); rounds->destroy(rounds); return FALSE; } - ri_id = get_remote_identity_id(ike_sa->get_peer_cfg((ike_sa_t *)ike_sa)); - chunk_to_sequence(&enc_user_cert, &user_cert, sizeof(certificate_type)); - chunk_free(&enc_user_cert); - if (ike_cc_set_user_certificate(cc_id, ri_id, 1, user_cert) != TKM_OK) + chunk_to_sequence(&enc_ca_cert, &ca_cert, + sizeof(certificate_type)); + chunk_free(&enc_ca_cert); + + if (ike_cc_check_ca(cc_id, ca_id, ca_cert) != TKM_OK) { - DBG1(DBG_IKE, "error setting user certificate of cert chain" - " (cc_id: %llu)", cc_id); + DBG1(DBG_IKE, "CA certificate (fp: %#B, cc_id: %llu) does not" + " match trusted CA (ca_id: %llu)", &fp, cc_id, ca_id); rounds->destroy(rounds); return FALSE; } - /* process intermediate CA certificates */ + /* process intermediate CA certificates in reverse order */ enumerator = auth->create_enumerator(auth); while (enumerator->enumerate(enumerator, &rule, &cert)) { if (rule == AUTH_RULE_IM_CERT) { - chunk_t enc_im_cert; - certificate_type im_cert; - - if (!cert->get_encoding(cert, CERT_ASN1_DER, &enc_im_cert)) - { - DBG1(DBG_IKE, "unable to extract encoded intermediate CA" - " certificate"); - rounds->destroy(rounds); - enumerator->destroy(enumerator); - return FALSE; - } - - chunk_to_sequence(&enc_im_cert, &im_cert, - sizeof(certificate_type)); - chunk_free(&enc_im_cert); - if (ike_cc_add_certificate(cc_id, 1, im_cert) != TKM_OK) - { - DBG1(DBG_IKE, "error adding intermediate certificate to" - " cert chain (cc_id: %llu)", cc_id); - rounds->destroy(rounds); - enumerator->destroy(enumerator); - return FALSE; - } + array_insert_create(&im_certs, ARRAY_TAIL, cert); } } enumerator->destroy(enumerator); - /* finally add CA certificate */ - cert = auth->get(auth, AUTH_RULE_CA_CERT); - if (cert) + while (array_remove(im_certs, ARRAY_TAIL, &cert)) { - ca_id_type ca_id; - public_key_t *pubkey; - certificate_type ca_cert; - chunk_t enc_ca_cert, fp; - uint64_t *raw_id; - - pubkey = cert->get_public_key(cert); - if (!pubkey) - { - DBG1(DBG_IKE, "unable to get CA certificate pubkey"); - rounds->destroy(rounds); - return FALSE; - } - if (!pubkey->get_fingerprint(pubkey, KEYID_PUBKEY_SHA1, &fp)) + chunk_t enc_im_cert; + certificate_type im_cert; + + if (!cert->get_encoding(cert, CERT_ASN1_DER, &enc_im_cert)) { - DBG1(DBG_IKE, "unable to extract CA certificate fingerprint"); + DBG1(DBG_IKE, "unable to extract encoded intermediate CA" + " certificate"); rounds->destroy(rounds); - pubkey->destroy(pubkey); + array_destroy(im_certs); return FALSE; } - pubkey->destroy(pubkey); - raw_id = ca_map->get(ca_map, &fp); - if (!raw_id || *raw_id == 0) + chunk_to_sequence(&enc_im_cert, &im_cert, + sizeof(certificate_type)); + chunk_free(&enc_im_cert); + if (ike_cc_add_certificate(cc_id, 1, im_cert) != TKM_OK) { - DBG1(DBG_IKE, "error mapping CA certificate (fp: %#B) to " - "ID", &fp); + DBG1(DBG_IKE, "error adding intermediate certificate to" + " cert chain (cc_id: %llu)", cc_id); rounds->destroy(rounds); + array_destroy(im_certs); return FALSE; } - ca_id = *raw_id; + } + array_destroy(im_certs); - if (!cert->get_encoding(cert, CERT_ASN1_DER, &enc_ca_cert)) + /* finally add user certificate and check chain */ + cert = auth->get(auth, AUTH_RULE_SUBJECT_CERT); + if (cert) + { + chunk_t enc_user_cert; + ri_id_type ri_id; + certificate_type user_cert; + + /* set user certificate */ + if (!cert->get_encoding(cert, CERT_ASN1_DER, &enc_user_cert)) { - DBG1(DBG_IKE, "unable to extract encoded CA certificate"); + DBG1(DBG_IKE, "unable to extract encoded user certificate"); rounds->destroy(rounds); return FALSE; } - chunk_to_sequence(&enc_ca_cert, &ca_cert, - sizeof(certificate_type)); - chunk_free(&enc_ca_cert); - if (ike_cc_add_certificate(cc_id, 1, ca_cert) != TKM_OK) + chunk_to_sequence(&enc_user_cert, &user_cert, sizeof(certificate_type)); + chunk_free(&enc_user_cert); + if (ike_cc_add_certificate(cc_id, 1, user_cert) != TKM_OK) { - DBG1(DBG_IKE, "error adding CA certificate to cert chain " - "(cc_id: %llu)", cc_id); + DBG1(DBG_IKE, "error adding user certificate to cert chain" + " (cc_id: %llu)", cc_id); rounds->destroy(rounds); return FALSE; } - if (ike_cc_check_ca(cc_id, ca_id) != TKM_OK) + ri_id = get_remote_identity_id(ike_sa->get_peer_cfg((ike_sa_t *)ike_sa)); + if (ike_cc_check_chain(cc_id, ri_id) != TKM_OK) { - DBG1(DBG_IKE, "certificate chain (cc_id: %llu) not based on" - " trusted CA (ca_id: %llu)", cc_id, ca_id); + DBG1(DBG_IKE, "error checking cert chain (cc_id: %llu)", cc_id); rounds->destroy(rounds); return FALSE; } @@ -222,12 +230,12 @@ static bool build_cert_chain(const ike_sa_t * const ike_sa, cc_id_type cc_id) } else { - DBG1(DBG_IKE, "no CA certificate"); + DBG1(DBG_IKE, "no subject certificate for remote peer"); } } else { - DBG1(DBG_IKE, "no subject certificate for remote peer"); + DBG1(DBG_IKE, "no CA certificate"); } } diff --git a/testing/scripts/recipes/006_tkm-rpc.mk b/testing/scripts/recipes/006_tkm-rpc.mk index 428ac2d142..a5db052e90 100644 --- a/testing/scripts/recipes/006_tkm-rpc.mk +++ b/testing/scripts/recipes/006_tkm-rpc.mk @@ -2,7 +2,7 @@ PKG = tkm-rpc SRC = https://git.codelabs.ch/git/$(PKG).git -REV = 4d6cd3f5e6a8f0d33f56289ad3a07645f10edc91 +REV = 1f4e1c9c6ec473cdb391b5416f38d48b09cb6004 PREFIX = /usr/local/ada diff --git a/testing/scripts/recipes/010_tkm.mk b/testing/scripts/recipes/010_tkm.mk index 4d8af638a0..7918485d46 100644 --- a/testing/scripts/recipes/010_tkm.mk +++ b/testing/scripts/recipes/010_tkm.mk @@ -2,7 +2,7 @@ PKG = tkm SRC = https://git.codelabs.ch/git/$(PKG).git -REV = 5320ec82f2221d9c4d5be106f6b90287bfb4acce +REV = 8184cc0976a5b00c9d042bef2032223ae261f948 export ADA_PROJECT_PATH=/usr/local/ada/lib/gnat diff --git a/testing/tests/tkm/host2host-initiator/evaltest.dat b/testing/tests/tkm/host2host-initiator/evaltest.dat index 65b47c3c51..4158625a13 100644 --- a/testing/tests/tkm/host2host-initiator/evaltest.dat +++ b/testing/tests/tkm/host2host-initiator/evaltest.dat @@ -7,7 +7,8 @@ sun::tcpdump::IP moon.strongswan.org > sun.strongswan.org: ESP::YES sun::tcpdump::IP sun.strongswan.org > moon.strongswan.org: ESP::YES moon::cat /tmp/tkm.log::RSA private key '/etc/tkm/moonKey.der' loaded::YES moon::cat /tmp/tkm.log::Adding policy \[ 1, 192.168.0.1 <-> 192.168.0.2 \]::YES -moon::cat /tmp/tkm.log::Checked CA certificate of CC context 1::YES +moon::cat /tmp/tkm.log::Linked CC context 1 with CA certificate 1::YES +moon::cat /tmp/tkm.log::Certificate chain of CC context 1 is valid::YES moon::cat /tmp/tkm.log::Authentication of ISA context 1 successful::YES moon::cat /tmp/tkm.log::Adding ESA \[ 1, 192.168.0.1 <-> 192.168.0.2, SPI_in.*, SPI_out.*, soft 30, hard 60 \]::YES moon::DAEMON_NAME=charon-tkm ipsec down conn1 && sleep 1::no output expected::NO diff --git a/testing/tests/tkm/host2host-responder/evaltest.dat b/testing/tests/tkm/host2host-responder/evaltest.dat index 9921960e00..2db775799d 100644 --- a/testing/tests/tkm/host2host-responder/evaltest.dat +++ b/testing/tests/tkm/host2host-responder/evaltest.dat @@ -7,6 +7,7 @@ sun::tcpdump::IP moon.strongswan.org > sun.strongswan.org: ESP::YES sun::tcpdump::IP sun.strongswan.org > moon.strongswan.org: ESP::YES moon::cat /tmp/tkm.log::RSA private key '/etc/tkm/moonKey.der' loaded::YES moon::cat /tmp/tkm.log::Adding policy \[ 1, 192.168.0.1 <-> 192.168.0.2 \]::YES -moon::cat /tmp/tkm.log::Checked CA certificate of CC context 1::YES +moon::cat /tmp/tkm.log::Linked CC context 1 with CA certificate 1::YES +moon::cat /tmp/tkm.log::Certificate chain of CC context 1 is valid::YES moon::cat /tmp/tkm.log::Authentication of ISA context 1 successful::YES moon::cat /tmp/tkm.log::Adding ESA \[ 1, 192.168.0.1 <-> 192.168.0.2, SPI_in.*, SPI_out.*, soft 30, hard 60 \]::YES diff --git a/testing/tests/tkm/host2host-xfrmproxy/evaltest.dat b/testing/tests/tkm/host2host-xfrmproxy/evaltest.dat index eb954bdf84..74203f82d9 100644 --- a/testing/tests/tkm/host2host-xfrmproxy/evaltest.dat +++ b/testing/tests/tkm/host2host-xfrmproxy/evaltest.dat @@ -8,7 +8,8 @@ sun::tcpdump::IP sun.strongswan.org > moon.strongswan.org: ESP::YES moon::cat /var/log/daemon.log::ees: acquire received for reqid 1::YES moon::cat /tmp/tkm.log::RSA private key '/etc/tkm/moonKey.der' loaded::YES moon::cat /tmp/tkm.log::Adding policy \[ 1, 192.168.0.1 <-> 192.168.0.2 \]::YES -moon::cat /tmp/tkm.log::Checked CA certificate of CC context 1::YES +moon::cat /tmp/tkm.log::Linked CC context 1 with CA certificate 1::YES +moon::cat /tmp/tkm.log::Certificate chain of CC context 1 is valid::YES moon::cat /tmp/tkm.log::Authentication of ISA context 1 successful::YES moon::cat /tmp/tkm.log::Adding ESA \[ 1, 192.168.0.1 <-> 192.168.0.2, SPI_in.*, SPI_out.*, soft 30, hard 60 \]::YES moon::cat /tmp/xfrm_proxy.log::Initiating ESA acquire for reqid 1::YES diff --git a/testing/tests/tkm/multiple-clients/evaltest.dat b/testing/tests/tkm/multiple-clients/evaltest.dat index 045e583520..23f6151fc3 100644 --- a/testing/tests/tkm/multiple-clients/evaltest.dat +++ b/testing/tests/tkm/multiple-clients/evaltest.dat @@ -15,7 +15,7 @@ dave::tcpdump::IP sun.strongswan.org > dave.strongswan.org: ESP::YES sun::cat /tmp/tkm.log::RSA private key '/etc/tkm/sunKey.der' loaded::YES sun::cat /tmp/tkm.log::Adding policy \[ 1, 192.168.0.2 <-> 192.168.0.100 \]::YES sun::cat /tmp/tkm.log::Adding policy \[ 2, 192.168.0.2 <-> 192.168.0.200 \]::YES -sun::cat /tmp/tkm.log | grep "Checked CA certificate of CC context 1" | wc -l::2::YES +sun::cat /tmp/tkm.log | grep "Certificate chain of CC context 1 is valid" | wc -l::2::YES sun::cat /tmp/tkm.log::Authentication of ISA context 1 successful::YES sun::cat /tmp/tkm.log::Authentication of ISA context 2 successful::YES sun::cat /tmp/tkm.log::Adding ESA \[ 1, 192.168.0.2 <-> 192.168.0.100, SPI_in.*, SPI_out.*, soft 30, hard 60 \]::YES diff --git a/testing/tests/tkm/net2net-initiator/evaltest.dat b/testing/tests/tkm/net2net-initiator/evaltest.dat index 54b7ca4fae..f3a06c66b7 100644 --- a/testing/tests/tkm/net2net-initiator/evaltest.dat +++ b/testing/tests/tkm/net2net-initiator/evaltest.dat @@ -7,6 +7,7 @@ sun::tcpdump::IP moon.strongswan.org > sun.strongswan.org: ESP::YES sun::tcpdump::IP sun.strongswan.org > moon.strongswan.org: ESP::YES moon::cat /tmp/tkm.log::RSA private key '/etc/tkm/moonKey.der' loaded::YES moon::cat /tmp/tkm.log::Adding policy \[ 1, 10.1.0.0/16 > 192.168.0.1 <=> 192.168.0.2 < 10.2.0.0/16 \]::YES -moon::cat /tmp/tkm.log::Checked CA certificate of CC context 1::YES +moon::cat /tmp/tkm.log::Linked CC context 1 with CA certificate 1::YES +moon::cat /tmp/tkm.log::Certificate chain of CC context 1 is valid::YES moon::cat /tmp/tkm.log::Authentication of ISA context 1 successful::YES moon::cat /tmp/tkm.log::Adding ESA \[ 1, 10.1.0.0/16 > 192.168.0.1 <=> 192.168.0.2 < 10.2.0.0/16, SPI_in.*, SPI_out.*, soft 30, hard 60 \]::YES diff --git a/testing/tests/tkm/net2net-xfrmproxy/evaltest.dat b/testing/tests/tkm/net2net-xfrmproxy/evaltest.dat index 3e61ea614a..d4befada5f 100644 --- a/testing/tests/tkm/net2net-xfrmproxy/evaltest.dat +++ b/testing/tests/tkm/net2net-xfrmproxy/evaltest.dat @@ -8,7 +8,8 @@ sun::tcpdump::IP sun.strongswan.org > moon.strongswan.org: ESP::YES moon::cat /var/log/daemon.log::ees: acquire received for reqid 1::YES moon::cat /tmp/tkm.log::RSA private key '/etc/tkm/moonKey.der' loaded::YES moon::cat /tmp/tkm.log::Adding policy \[ 1, 10.1.0.0/16 > 192.168.0.1 <=> 192.168.0.2 < 10.2.0.0/16 \]::YES -moon::cat /tmp/tkm.log::Checked CA certificate of CC context 1::YES +moon::cat /tmp/tkm.log::Linked CC context 1 with CA certificate 1::YES +moon::cat /tmp/tkm.log::Certificate chain of CC context 1 is valid::YES moon::cat /tmp/tkm.log::Authentication of ISA context 1 successful::YES moon::cat /tmp/tkm.log::Adding ESA \[ 1, 10.1.0.0/16 > 192.168.0.1 <=> 192.168.0.2 < 10.2.0.0/16, SPI_in.*, SPI_out.*, soft 30, hard 60 \]::YES moon::cat /tmp/xfrm_proxy.log::Initiating ESA acquire for reqid 1::YES diff --git a/testing/tests/tkm/xfrmproxy-expire/evaltest.dat b/testing/tests/tkm/xfrmproxy-expire/evaltest.dat index a3f45871ca..421924c7cc 100644 --- a/testing/tests/tkm/xfrmproxy-expire/evaltest.dat +++ b/testing/tests/tkm/xfrmproxy-expire/evaltest.dat @@ -15,7 +15,8 @@ moon::cat /var/log/daemon.log::deleting child SA (esa: 1, spi:.*)::YES moon::ping -c 1 PH_IP_SUN::64 bytes from PH_IP_SUN: icmp_.eq=1::YES moon::cat /tmp/tkm.log::RSA private key '/etc/tkm/moonKey.der' loaded::YES moon::cat /tmp/tkm.log::Adding policy \[ 1, 192.168.0.1 <-> 192.168.0.2 \]::YES -moon::cat /tmp/tkm.log::Checked CA certificate of CC context 1::YES +moon::cat /tmp/tkm.log::Linked CC context 1 with CA certificate 1::YES +moon::cat /tmp/tkm.log::Certificate chain of CC context 1 is valid::YES moon::cat /tmp/tkm.log::Authentication of ISA context 1 successful::YES moon::cat /tmp/tkm.log::Creating first new ESA context with ID 1 (Isa 1, Sp 1, Ea 1, Initiator TRUE, spi_loc.*, spi_rem.*)::YES moon::cat /tmp/tkm.log::Creating ESA context with ID 2 (Isa 1, Sp 1, Ea 1, Dh_Id 1, Nc_Loc_Id 1, Initiator TRUE, spi_loc.*, spi_rem.*)::YES diff --git a/testing/tests/tkm/xfrmproxy-rekey/evaltest.dat b/testing/tests/tkm/xfrmproxy-rekey/evaltest.dat index 15bdf3b39a..fbda21e0b4 100644 --- a/testing/tests/tkm/xfrmproxy-rekey/evaltest.dat +++ b/testing/tests/tkm/xfrmproxy-rekey/evaltest.dat @@ -13,7 +13,8 @@ moon::cat /var/log/daemon.log::deleting child SA (esa: 1, spi:.*)::YES moon::ping -c 1 PH_IP_SUN::64 bytes from PH_IP_SUN: icmp_.eq=1::YES moon::cat /tmp/tkm.log::RSA private key '/etc/tkm/moonKey.der' loaded::YES moon::cat /tmp/tkm.log::Adding policy \[ 1, 192.168.0.1 <-> 192.168.0.2 \]::YES -moon::cat /tmp/tkm.log::Checked CA certificate of CC context 1::YES +moon::cat /tmp/tkm.log::Linked CC context 1 with CA certificate 1::YES +moon::cat /tmp/tkm.log::Certificate chain of CC context 1 is valid::YES moon::cat /tmp/tkm.log::Authentication of ISA context 1 successful::YES moon::cat /tmp/tkm.log::Creating first new ESA context with ID 1 (Isa 1, Sp 1, Ea 1, Initiator TRUE, spi_loc.*, spi_rem.*)::YES moon::cat /tmp/tkm.log::Creating ESA context with ID 2 (Isa 1, Sp 1, Ea 1, Dh_Id 1, Nc_Loc_Id 1, Initiator FALSE, spi_loc.*, spi_rem.*)::YES