aboutsummaryrefslogtreecommitdiffstats
path: root/src/libcharon/encoding
diff options
context:
space:
mode:
authorMartin Willi <martin@revosec.ch>2015-02-03 16:40:14 +0100
committerMartin Willi <martin@revosec.ch>2015-03-18 13:33:25 +0100
commit84738b1aed955662106b272169915928e1232086 (patch)
treeaed513e7bba38359ed9a7033660827875b058da5 /src/libcharon/encoding
parentb8ecdfd8952d4c9021db565f22adb87a9adaa8b0 (diff)
downloadstrongswan-84738b1aed955662106b272169915928e1232086.tar.bz2
strongswan-84738b1aed955662106b272169915928e1232086.tar.xz
encoding: Verify the length of KE payload data for known groups
IKE is very strict in the length of KE payloads, and it should be safe to strictly verify their length. Not doing so is no direct threat, but allows DDoS amplification by sending short KE payloads for large groups using the target as the source address.
Diffstat (limited to 'src/libcharon/encoding')
-rw-r--r--src/libcharon/encoding/payloads/ke_payload.c67
1 files changed, 67 insertions, 0 deletions
diff --git a/src/libcharon/encoding/payloads/ke_payload.c b/src/libcharon/encoding/payloads/ke_payload.c
index 4f552d6ac..644b5b6f9 100644
--- a/src/libcharon/encoding/payloads/ke_payload.c
+++ b/src/libcharon/encoding/payloads/ke_payload.c
@@ -142,6 +142,73 @@ static encoding_rule_t encodings_v1[] = {
METHOD(payload_t, verify, status_t,
private_ke_payload_t *this)
{
+ diffie_hellman_params_t *params;
+ diffie_hellman_group_t g = this->dh_group_number;
+ bool valid = TRUE;
+
+ switch (g)
+ {
+ case MODP_NONE:
+ valid = FALSE;
+ break;
+ case MODP_768_BIT:
+ case MODP_1024_BIT:
+ case MODP_1536_BIT:
+ case MODP_2048_BIT:
+ case MODP_3072_BIT:
+ case MODP_4096_BIT:
+ case MODP_6144_BIT:
+ case MODP_8192_BIT:
+ case MODP_1024_160:
+ case MODP_2048_224:
+ case MODP_2048_256:
+ params = diffie_hellman_get_params(g);
+ if (params)
+ {
+ valid = this->key_exchange_data.len == params->prime.len;
+ }
+ break;
+ case ECP_192_BIT:
+ valid = this->key_exchange_data.len == 48;
+ break;
+ case ECP_224_BIT:
+ case ECP_224_BP:
+ valid = this->key_exchange_data.len == 56;
+ break;
+ case ECP_256_BIT:
+ case ECP_256_BP:
+ valid = this->key_exchange_data.len == 64;
+ break;
+ case ECP_384_BIT:
+ case ECP_384_BP:
+ valid = this->key_exchange_data.len == 96;
+ break;
+ case ECP_512_BP:
+ valid = this->key_exchange_data.len == 128;
+ break;
+ case ECP_521_BIT:
+ valid = this->key_exchange_data.len == 132;
+ break;
+ case NTRU_112_BIT:
+ case NTRU_128_BIT:
+ case NTRU_192_BIT:
+ case NTRU_256_BIT:
+ /* NTRU public key size depends on the parameter set, but is
+ * at least 512 bytes */
+ valid = this->key_exchange_data.len > 512;
+ break;
+ case MODP_NULL:
+ case MODP_CUSTOM:
+ break;
+ /* compile-warn unhandled groups, but accept them so we can negotiate
+ * a different group that we support. */
+ }
+ if (!valid)
+ {
+ DBG1(DBG_ENC, "invalid KE data size (%zu bytes) for %N",
+ this->key_exchange_data.len, diffie_hellman_group_names, g);
+ return FAILED;
+ }
return SUCCESS;
}