diff options
| -rw-r--r-- | meta-networking/recipes-support/strongswan/files/CVE-2022-40617.patch | 210 | ||||
| -rw-r--r-- | meta-networking/recipes-support/strongswan/strongswan_5.8.4.bb | 1 |
2 files changed, 211 insertions, 0 deletions
diff --git a/meta-networking/recipes-support/strongswan/files/CVE-2022-40617.patch b/meta-networking/recipes-support/strongswan/files/CVE-2022-40617.patch new file mode 100644 index 0000000000..66e5047125 --- /dev/null +++ b/meta-networking/recipes-support/strongswan/files/CVE-2022-40617.patch | |||
| @@ -0,0 +1,210 @@ | |||
| 1 | From 66d3b2e0e596a6eac1ebcd15c83a8d9368fe7b34 Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Tobias Brunner <tobias@strongswan.org> | ||
| 3 | Date: Fri, 22 Jul 2022 15:37:43 +0200 | ||
| 4 | Subject: [PATCH] credential-manager: Do online revocation checks only after | ||
| 5 | basic trust chain validation | ||
| 6 | |||
| 7 | This avoids querying URLs of potentially untrusted certificates, e.g. if | ||
| 8 | an attacker sends a specially crafted end-entity and intermediate CA | ||
| 9 | certificate with a CDP that points to a server that completes the | ||
| 10 | TCP handshake but then does not send any further data, which will block | ||
| 11 | the fetcher thread (depending on the plugin) for as long as the default | ||
| 12 | timeout for TCP. Doing that multiple times will block all worker threads, | ||
| 13 | leading to a DoS attack. | ||
| 14 | |||
| 15 | The logging during the certificate verification obviously changes. The | ||
| 16 | following example shows the output of `pki --verify` for the current | ||
| 17 | strongswan.org certificate: | ||
| 18 | |||
| 19 | new: | ||
| 20 | |||
| 21 | using certificate "CN=www.strongswan.org" | ||
| 22 | using trusted intermediate ca certificate "C=US, O=Let's Encrypt, CN=R3" | ||
| 23 | using trusted ca certificate "C=US, O=Internet Security Research Group, CN=ISRG Root X1" | ||
| 24 | reached self-signed root ca with a path length of 1 | ||
| 25 | checking certificate status of "CN=www.strongswan.org" | ||
| 26 | requesting ocsp status from 'http://r3.o.lencr.org' ... | ||
| 27 | ocsp response correctly signed by "C=US, O=Let's Encrypt, CN=R3" | ||
| 28 | ocsp response is valid: until Jul 27 12:59:58 2022 | ||
| 29 | certificate status is good | ||
| 30 | checking certificate status of "C=US, O=Let's Encrypt, CN=R3" | ||
| 31 | ocsp response verification failed, no signer certificate 'C=US, O=Let's Encrypt, CN=R3' found | ||
| 32 | fetching crl from 'http://x1.c.lencr.org/' ... | ||
| 33 | using trusted certificate "C=US, O=Internet Security Research Group, CN=ISRG Root X1" | ||
| 34 | crl correctly signed by "C=US, O=Internet Security Research Group, CN=ISRG Root X1" | ||
| 35 | crl is valid: until Apr 18 01:59:59 2023 | ||
| 36 | certificate status is good | ||
| 37 | certificate trusted, lifetimes valid, certificate not revoked | ||
| 38 | |||
| 39 | old: | ||
| 40 | |||
| 41 | using certificate "CN=www.strongswan.org" | ||
| 42 | using trusted intermediate ca certificate "C=US, O=Let's Encrypt, CN=R3" | ||
| 43 | checking certificate status of "CN=www.strongswan.org" | ||
| 44 | requesting ocsp status from 'http://r3.o.lencr.org' ... | ||
| 45 | ocsp response correctly signed by "C=US, O=Let's Encrypt, CN=R3" | ||
| 46 | ocsp response is valid: until Jul 27 12:59:58 2022 | ||
| 47 | certificate status is good | ||
| 48 | using trusted ca certificate "C=US, O=Internet Security Research Group, CN=ISRG Root X1" | ||
| 49 | checking certificate status of "C=US, O=Let's Encrypt, CN=R3" | ||
| 50 | ocsp response verification failed, no signer certificate 'C=US, O=Let's Encrypt, CN=R3' found | ||
| 51 | fetching crl from 'http://x1.c.lencr.org/' ... | ||
| 52 | using trusted certificate "C=US, O=Internet Security Research Group, CN=ISRG Root X1" | ||
| 53 | crl correctly signed by "C=US, O=Internet Security Research Group, CN=ISRG Root X1" | ||
| 54 | crl is valid: until Apr 18 01:59:59 2023 | ||
| 55 | certificate status is good | ||
| 56 | reached self-signed root ca with a path length of 1 | ||
| 57 | certificate trusted, lifetimes valid, certificate not revoked | ||
| 58 | |||
| 59 | Note that this also fixes an issue with the previous dual-use of the | ||
| 60 | `trusted` flag. It not only indicated whether the chain is trusted but | ||
| 61 | also whether the current issuer is the root anchor (the corresponding | ||
| 62 | flag in the `cert_validator_t` interface is called `anchor`). This was | ||
| 63 | a problem when building multi-level trust chains for pre-trusted | ||
| 64 | end-entity certificates (i.e. where `trusted` is TRUE from the start). | ||
| 65 | This caused the main loop to get aborted after the first intermediate CA | ||
| 66 | certificate and the mentioned `anchor` flag wasn't correct in any calls | ||
| 67 | to `cert_validator_t` implementations. | ||
| 68 | |||
| 69 | Fixes: CVE-2022-40617 | ||
| 70 | |||
| 71 | CVE: CVE-2022-40617 | ||
| 72 | Upstream-Status: Backport [https://download.strongswan.org/security/CVE-2022-40617/strongswan-5.1.0-5.9.7_cert_online_validate.patch] | ||
| 73 | Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com> | ||
| 74 | |||
| 75 | --- | ||
| 76 | .../credentials/credential_manager.c | 54 +++++++++++++++---- | ||
| 77 | 1 file changed, 45 insertions(+), 9 deletions(-) | ||
| 78 | |||
| 79 | diff --git a/src/libstrongswan/credentials/credential_manager.c b/src/libstrongswan/credentials/credential_manager.c | ||
| 80 | index e93b5943a3a7..798785544e41 100644 | ||
| 81 | --- a/src/libstrongswan/credentials/credential_manager.c | ||
| 82 | +++ b/src/libstrongswan/credentials/credential_manager.c | ||
| 83 | @@ -556,7 +556,7 @@ static void cache_queue(private_credential_manager_t *this) | ||
| 84 | */ | ||
| 85 | static bool check_lifetime(private_credential_manager_t *this, | ||
| 86 | certificate_t *cert, char *label, | ||
| 87 | - int pathlen, bool trusted, auth_cfg_t *auth) | ||
| 88 | + int pathlen, bool anchor, auth_cfg_t *auth) | ||
| 89 | { | ||
| 90 | time_t not_before, not_after; | ||
| 91 | cert_validator_t *validator; | ||
| 92 | @@ -571,7 +571,7 @@ static bool check_lifetime(private_credential_manager_t *this, | ||
| 93 | continue; | ||
| 94 | } | ||
| 95 | status = validator->check_lifetime(validator, cert, | ||
| 96 | - pathlen, trusted, auth); | ||
| 97 | + pathlen, anchor, auth); | ||
| 98 | if (status != NEED_MORE) | ||
| 99 | { | ||
| 100 | break; | ||
| 101 | @@ -604,13 +604,13 @@ static bool check_lifetime(private_credential_manager_t *this, | ||
| 102 | */ | ||
| 103 | static bool check_certificate(private_credential_manager_t *this, | ||
| 104 | certificate_t *subject, certificate_t *issuer, bool online, | ||
| 105 | - int pathlen, bool trusted, auth_cfg_t *auth) | ||
| 106 | + int pathlen, bool anchor, auth_cfg_t *auth) | ||
| 107 | { | ||
| 108 | cert_validator_t *validator; | ||
| 109 | enumerator_t *enumerator; | ||
| 110 | |||
| 111 | if (!check_lifetime(this, subject, "subject", pathlen, FALSE, auth) || | ||
| 112 | - !check_lifetime(this, issuer, "issuer", pathlen + 1, trusted, auth)) | ||
| 113 | + !check_lifetime(this, issuer, "issuer", pathlen + 1, anchor, auth)) | ||
| 114 | { | ||
| 115 | return FALSE; | ||
| 116 | } | ||
| 117 | @@ -623,7 +623,7 @@ static bool check_certificate(private_credential_manager_t *this, | ||
| 118 | continue; | ||
| 119 | } | ||
| 120 | if (!validator->validate(validator, subject, issuer, | ||
| 121 | - online, pathlen, trusted, auth)) | ||
| 122 | + online, pathlen, anchor, auth)) | ||
| 123 | { | ||
| 124 | enumerator->destroy(enumerator); | ||
| 125 | return FALSE; | ||
| 126 | @@ -726,6 +726,7 @@ static bool verify_trust_chain(private_credential_manager_t *this, | ||
| 127 | auth_cfg_t *auth; | ||
| 128 | signature_params_t *scheme; | ||
| 129 | int pathlen; | ||
| 130 | + bool is_anchor = FALSE; | ||
| 131 | |||
| 132 | auth = auth_cfg_create(); | ||
| 133 | get_key_strength(subject, auth); | ||
| 134 | @@ -743,7 +744,7 @@ static bool verify_trust_chain(private_credential_manager_t *this, | ||
| 135 | auth->add(auth, AUTH_RULE_CA_CERT, issuer->get_ref(issuer)); | ||
| 136 | DBG1(DBG_CFG, " using trusted ca certificate \"%Y\"", | ||
| 137 | issuer->get_subject(issuer)); | ||
| 138 | - trusted = TRUE; | ||
| 139 | + trusted = is_anchor = TRUE; | ||
| 140 | } | ||
| 141 | else | ||
| 142 | { | ||
| 143 | @@ -778,11 +779,18 @@ static bool verify_trust_chain(private_credential_manager_t *this, | ||
| 144 | DBG1(DBG_CFG, " issuer is \"%Y\"", | ||
| 145 | current->get_issuer(current)); | ||
| 146 | call_hook(this, CRED_HOOK_NO_ISSUER, current); | ||
| 147 | + if (trusted) | ||
| 148 | + { | ||
| 149 | + DBG1(DBG_CFG, " reached end of incomplete trust chain for " | ||
| 150 | + "trusted certificate \"%Y\"", | ||
| 151 | + subject->get_subject(subject)); | ||
| 152 | + } | ||
| 153 | break; | ||
| 154 | } | ||
| 155 | } | ||
| 156 | - if (!check_certificate(this, current, issuer, online, | ||
| 157 | - pathlen, trusted, auth)) | ||
| 158 | + /* don't do online verification here */ | ||
| 159 | + if (!check_certificate(this, current, issuer, FALSE, | ||
| 160 | + pathlen, is_anchor, auth)) | ||
| 161 | { | ||
| 162 | trusted = FALSE; | ||
| 163 | issuer->destroy(issuer); | ||
| 164 | @@ -794,7 +802,7 @@ static bool verify_trust_chain(private_credential_manager_t *this, | ||
| 165 | } | ||
| 166 | current->destroy(current); | ||
| 167 | current = issuer; | ||
| 168 | - if (trusted) | ||
| 169 | + if (is_anchor) | ||
| 170 | { | ||
| 171 | DBG1(DBG_CFG, " reached self-signed root ca with a " | ||
| 172 | "path length of %d", pathlen); | ||
| 173 | @@ -807,6 +815,34 @@ static bool verify_trust_chain(private_credential_manager_t *this, | ||
| 174 | DBG1(DBG_CFG, "maximum path length of %d exceeded", MAX_TRUST_PATH_LEN); | ||
| 175 | call_hook(this, CRED_HOOK_EXCEEDED_PATH_LEN, subject); | ||
| 176 | } | ||
| 177 | + else if (trusted && online) | ||
| 178 | + { | ||
| 179 | + enumerator_t *enumerator; | ||
| 180 | + auth_rule_t rule; | ||
| 181 | + | ||
| 182 | + /* do online revocation checks after basic validation of the chain */ | ||
| 183 | + pathlen = 0; | ||
| 184 | + current = subject; | ||
| 185 | + enumerator = auth->create_enumerator(auth); | ||
| 186 | + while (enumerator->enumerate(enumerator, &rule, &issuer)) | ||
| 187 | + { | ||
| 188 | + if (rule == AUTH_RULE_CA_CERT || rule == AUTH_RULE_IM_CERT) | ||
| 189 | + { | ||
| 190 | + if (!check_certificate(this, current, issuer, TRUE, pathlen++, | ||
| 191 | + rule == AUTH_RULE_CA_CERT, auth)) | ||
| 192 | + { | ||
| 193 | + trusted = FALSE; | ||
| 194 | + break; | ||
| 195 | + } | ||
| 196 | + else if (rule == AUTH_RULE_CA_CERT) | ||
| 197 | + { | ||
| 198 | + break; | ||
| 199 | + } | ||
| 200 | + current = issuer; | ||
| 201 | + } | ||
| 202 | + } | ||
| 203 | + enumerator->destroy(enumerator); | ||
| 204 | + } | ||
| 205 | if (trusted) | ||
| 206 | { | ||
| 207 | result->merge(result, auth, FALSE); | ||
| 208 | -- | ||
| 209 | 2.25.1 | ||
| 210 | |||
diff --git a/meta-networking/recipes-support/strongswan/strongswan_5.8.4.bb b/meta-networking/recipes-support/strongswan/strongswan_5.8.4.bb index 8a5855fb87..c11748645c 100644 --- a/meta-networking/recipes-support/strongswan/strongswan_5.8.4.bb +++ b/meta-networking/recipes-support/strongswan/strongswan_5.8.4.bb | |||
| @@ -14,6 +14,7 @@ SRC_URI = "http://download.strongswan.org/strongswan-${PV}.tar.bz2 \ | |||
| 14 | file://CVE-2021-41990.patch \ | 14 | file://CVE-2021-41990.patch \ |
| 15 | file://CVE-2021-41991.patch \ | 15 | file://CVE-2021-41991.patch \ |
| 16 | file://CVE-2021-45079.patch \ | 16 | file://CVE-2021-45079.patch \ |
| 17 | file://CVE-2022-40617.patch \ | ||
| 17 | " | 18 | " |
| 18 | 19 | ||
| 19 | SRC_URI[md5sum] = "0634e7f40591bd3f6770e583c3f27d29" | 20 | SRC_URI[md5sum] = "0634e7f40591bd3f6770e583c3f27d29" |
