From e2fc0c80b3432d69fcda7e9e52b091584a91430b Mon Sep 17 00:00:00 2001
From: Tobias Brunner <tobias@strongswan.org>
Date: Thu, 4 Dec 2014 11:56:09 +0100
Subject: [PATCH] crypto: Define MODP_CUSTOM outside of IKE DH range

Before this fix it was possible to crash charon with an IKE_SA_INIT
message containing a KE payload with DH group MODP_CUSTOM(1025).
Defining MODP_CUSTOM outside of the two byte IKE DH identifier range
prevents it from getting negotiated.

Fixes CVE-2014-9221 in version 5.1.1.
---
 src/charon-tkm/src/tkm/tkm_diffie_hellman.c                   | 2 +-
 src/libstrongswan/crypto/diffie_hellman.c                     | 5 +++--
 src/libstrongswan/crypto/diffie_hellman.h                     | 5 +++--
 src/libstrongswan/plugins/gcrypt/gcrypt_dh.c                  | 2 +-
 src/libstrongswan/plugins/gmp/gmp_diffie_hellman.c            | 2 +-
 src/libstrongswan/plugins/openssl/openssl_diffie_hellman.c    | 2 +-
 src/libstrongswan/plugins/openssl/openssl_ec_diffie_hellman.c | 2 +-
 src/libstrongswan/plugins/pkcs11/pkcs11_dh.c                  | 2 +-
 8 files changed, 12 insertions(+), 10 deletions(-)

diff --git a/src/charon-tkm/src/tkm/tkm_diffie_hellman.c b/src/charon-tkm/src/tkm/tkm_diffie_hellman.c
index 19f57de01666..4ee748247c27 100644
--- a/src/charon-tkm/src/tkm/tkm_diffie_hellman.c
+++ b/src/charon-tkm/src/tkm/tkm_diffie_hellman.c
@@ -38,7 +38,7 @@ struct private_tkm_diffie_hellman_t {
 	/**
 	 * Diffie Hellman group number.
 	 */
-	u_int16_t group;
+	diffie_hellman_group_t group;
 
 	/**
 	 * Diffie Hellman public value.
diff --git a/src/libstrongswan/crypto/diffie_hellman.c b/src/libstrongswan/crypto/diffie_hellman.c
index 3d319d2d4b0b..873a31c135b5 100644
--- a/src/libstrongswan/crypto/diffie_hellman.c
+++ b/src/libstrongswan/crypto/diffie_hellman.c
@@ -42,8 +42,9 @@ ENUM_NEXT(diffie_hellman_group_names, MODP_1024_160, ECP_512_BP, ECP_521_BIT,
 	"ECP_256_BP",
 	"ECP_384_BP",
 	"ECP_512_BP");
-ENUM_NEXT(diffie_hellman_group_names, MODP_NULL, MODP_CUSTOM, ECP_512_BP,
-	"MODP_NULL",
+ENUM_NEXT(diffie_hellman_group_names, MODP_NULL, MODP_NULL, ECP_512_BP,
+	"MODP_NULL");
+ENUM_NEXT(diffie_hellman_group_names, MODP_CUSTOM, MODP_CUSTOM, MODP_NULL,
 	"MODP_CUSTOM");
 ENUM_END(diffie_hellman_group_names, MODP_CUSTOM);
 
diff --git a/src/libstrongswan/crypto/diffie_hellman.h b/src/libstrongswan/crypto/diffie_hellman.h
index edf6bbd6da74..d864da35967c 100644
--- a/src/libstrongswan/crypto/diffie_hellman.h
+++ b/src/libstrongswan/crypto/diffie_hellman.h
@@ -62,8 +62,9 @@ enum diffie_hellman_group_t {
 	ECP_512_BP    = 30,
 	/** insecure NULL diffie hellman group for testing, in PRIVATE USE */
 	MODP_NULL = 1024,
-	/** MODP group with custom generator/prime */
-	MODP_CUSTOM = 1025,
+	/** internally used DH group with additional parameters g and p, outside
+	 * of PRIVATE USE (i.e. IKEv2 DH group range) so it can't be negotiated */
+	MODP_CUSTOM = 65536,
 };
 
 /**
diff --git a/src/libstrongswan/plugins/gcrypt/gcrypt_dh.c b/src/libstrongswan/plugins/gcrypt/gcrypt_dh.c
index f418b941db86..299865da2e09 100644
--- a/src/libstrongswan/plugins/gcrypt/gcrypt_dh.c
+++ b/src/libstrongswan/plugins/gcrypt/gcrypt_dh.c
@@ -35,7 +35,7 @@ struct private_gcrypt_dh_t {
 	/**
 	 * Diffie Hellman group number
 	 */
-	u_int16_t group;
+	diffie_hellman_group_t group;
 
 	/*
 	 * Generator value
diff --git a/src/libstrongswan/plugins/gmp/gmp_diffie_hellman.c b/src/libstrongswan/plugins/gmp/gmp_diffie_hellman.c
index b74d35169f44..9936f7e4518f 100644
--- a/src/libstrongswan/plugins/gmp/gmp_diffie_hellman.c
+++ b/src/libstrongswan/plugins/gmp/gmp_diffie_hellman.c
@@ -42,7 +42,7 @@ struct private_gmp_diffie_hellman_t {
 	/**
 	 * Diffie Hellman group number.
 	 */
-	u_int16_t group;
+	diffie_hellman_group_t group;
 
 	/*
 	 * Generator value.
diff --git a/src/libstrongswan/plugins/openssl/openssl_diffie_hellman.c b/src/libstrongswan/plugins/openssl/openssl_diffie_hellman.c
index ff3382473666..1e68ac59b838 100644
--- a/src/libstrongswan/plugins/openssl/openssl_diffie_hellman.c
+++ b/src/libstrongswan/plugins/openssl/openssl_diffie_hellman.c
@@ -38,7 +38,7 @@ struct private_openssl_diffie_hellman_t {
 	/**
 	 * Diffie Hellman group number.
 	 */
-	u_int16_t group;
+	diffie_hellman_group_t group;
 
 	/**
 	 * Diffie Hellman object
diff --git a/src/libstrongswan/plugins/openssl/openssl_ec_diffie_hellman.c b/src/libstrongswan/plugins/openssl/openssl_ec_diffie_hellman.c
index c43fe455a804..c382b704abda 100644
--- a/src/libstrongswan/plugins/openssl/openssl_ec_diffie_hellman.c
+++ b/src/libstrongswan/plugins/openssl/openssl_ec_diffie_hellman.c
@@ -40,7 +40,7 @@ struct private_openssl_ec_diffie_hellman_t {
 	/**
 	 * Diffie Hellman group number.
 	 */
-	u_int16_t group;
+	diffie_hellman_group_t group;
 
 	/**
 	 * EC private (public) key
diff --git a/src/libstrongswan/plugins/pkcs11/pkcs11_dh.c b/src/libstrongswan/plugins/pkcs11/pkcs11_dh.c
index 2e5af95fff0d..068ce7d2a74b 100644
--- a/src/libstrongswan/plugins/pkcs11/pkcs11_dh.c
+++ b/src/libstrongswan/plugins/pkcs11/pkcs11_dh.c
@@ -47,7 +47,7 @@ struct private_pkcs11_dh_t {
 	/**
 	 * Diffie Hellman group number.
 	 */
-	u_int16_t group;
+	diffie_hellman_group_t group;
 
 	/**
 	 * Handle for own private value
-- 
1.9.1

