From 68ba6fa92bd3a3fae6bca4f4eb3b541fba5c876f Mon Sep 17 00:00:00 2001
From: Olav Morken <olav.morken@uninett.no>
Date: Thu, 2 Aug 2012 10:48:28 +0000
Subject: [PATCH] SAML2: Add algorithm blacklist support.

git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@3138 44740490-163a-0410-bde0-09ae8108e29a
---
 lib/SAML2/Assertion.php          |  9 +++++----
 lib/SAML2/EncryptedAssertion.php |  5 +++--
 lib/SAML2/LogoutRequest.php      |  5 +++--
 lib/SAML2/Utils.php              | 17 ++++++++++++++---
 4 files changed, 25 insertions(+), 11 deletions(-)

diff --git a/lib/SAML2/Assertion.php b/lib/SAML2/Assertion.php
index d987fb0b9..571a74d1d 100644
--- a/lib/SAML2/Assertion.php
+++ b/lib/SAML2/Assertion.php
@@ -645,15 +645,16 @@ class SAML2_Assertion implements SAML2_SignedElement {
 	 * Decrypt the NameId of the subject in the assertion.
 	 *
 	 * @param XMLSecurityKey $key  The decryption key.
+	 * @param array $blacklist  Blacklisted decryption algorithms.
 	 */
-	public function decryptNameId(XMLSecurityKey $key) {
+	public function decryptNameId(XMLSecurityKey $key, array $blacklist = array()) {
 
 		if ($this->encryptedNameId === NULL) {
 			/* No NameID to decrypt. */
 			return;
 		}
 
-		$nameId = SAML2_Utils::decryptElement($this->encryptedNameId, $key);
+		$nameId = SAML2_Utils::decryptElement($this->encryptedNameId, $key, $blacklist);
 		SimpleSAML_Utilities::debugMessage($nameId, 'decrypt');
 		$this->nameId = SAML2_Utils::parseNameId($nameId);
 
@@ -661,14 +662,14 @@ class SAML2_Assertion implements SAML2_SignedElement {
 	}
 
 
-	public function decryptAttributes($key){
+	public function decryptAttributes($key, array $blacklist = array()){
 		if($this->encryptedAttribute === null){
 			return;
 		}
 		$attributes = $this->encryptedAttribute;
 		foreach ($attributes as $attributeEnc) {
 			/*Decrypt node <EncryptedAttribute>*/
-			$attribute = SAML2_Utils::decryptElement($attributeEnc->getElementsByTagName('EncryptedData')->item(0), $key);
+			$attribute = SAML2_Utils::decryptElement($attributeEnc->getElementsByTagName('EncryptedData')->item(0), $key, $blacklist);
 
 			if (!$attribute->hasAttribute('Name')) {
 				throw new Exception('Missing name on <saml:Attribute> element.');
diff --git a/lib/SAML2/EncryptedAssertion.php b/lib/SAML2/EncryptedAssertion.php
index 9c69ad08c..dc831789e 100644
--- a/lib/SAML2/EncryptedAssertion.php
+++ b/lib/SAML2/EncryptedAssertion.php
@@ -81,11 +81,12 @@ class SAML2_EncryptedAssertion {
 	 * Retrieve the assertion.
 	 *
 	 * @param XMLSecurityKey $key  The key we should use to decrypt the assertion.
+	 * @param array $blacklist  Blacklisted decryption algorithms.
 	 * @return SAML2_Assertion  The decrypted assertion.
 	 */
-	public function getAssertion(XMLSecurityKey $inputKey) {
+	public function getAssertion(XMLSecurityKey $inputKey, array $blacklist = array()) {
 
-		$assertionXML = SAML2_Utils::decryptElement($this->encryptedData, $inputKey);
+		$assertionXML = SAML2_Utils::decryptElement($this->encryptedData, $inputKey, $blacklist);
 
 		SimpleSAML_Utilities::debugMessage($assertionXML, 'decrypt');
 
diff --git a/lib/SAML2/LogoutRequest.php b/lib/SAML2/LogoutRequest.php
index c2369f840..1a9cf1e25 100644
--- a/lib/SAML2/LogoutRequest.php
+++ b/lib/SAML2/LogoutRequest.php
@@ -153,15 +153,16 @@ class SAML2_LogoutRequest extends SAML2_Request {
 	 * Decrypt the NameID in the LogoutRequest.
 	 *
 	 * @param XMLSecurityKey $key  The decryption key.
+	 * @param array $blacklist  Blacklisted decryption algorithms.
 	 */
-	public function decryptNameId(XMLSecurityKey $key) {
+	public function decryptNameId(XMLSecurityKey $key, array $blacklist = array()) {
 
 		if ($this->encryptedNameId === NULL) {
 			/* No NameID to decrypt. */
 			return;
 		}
 
-		$nameId = SAML2_Utils::decryptElement($this->encryptedNameId, $key);
+		$nameId = SAML2_Utils::decryptElement($this->encryptedNameId, $key, $blacklist);
 		SimpleSAML_Utilities::debugMessage($nameId, 'decrypt');
 		$this->nameId = SAML2_Utils::parseNameId($nameId);
 
diff --git a/lib/SAML2/Utils.php b/lib/SAML2/Utils.php
index 1eccf7596..6a959c261 100644
--- a/lib/SAML2/Utils.php
+++ b/lib/SAML2/Utils.php
@@ -339,9 +339,10 @@ class SAML2_Utils {
 	 *
 	 * @param DOMElement $encryptedData  The encrypted data.
 	 * @param XMLSecurityKey $inputKey  The decryption key.
+	 * @param array &$blacklist  Blacklisted decryption algorithms.
 	 * @return DOMElement  The decrypted element.
 	 */
-	private static function _decryptElement(DOMElement $encryptedData, XMLSecurityKey $inputKey) {
+	private static function _decryptElement(DOMElement $encryptedData, XMLSecurityKey $inputKey, array &$blacklist) {
 
 		$enc = new XMLSecEnc();
 
@@ -362,6 +363,10 @@ class SAML2_Utils {
 		if ($symmetricKeyInfo->isEncrypted) {
 			$symKeyInfoAlgo = $symmetricKeyInfo->getAlgorith();
 
+			if (in_array($symKeyInfoAlgo, $blacklist, TRUE)) {
+				throw new Exception('Algorithm disabled: ' . var_export($symKeyInfoAlgo, TRUE));
+			}
+
 			if ($symKeyInfoAlgo === XMLSecurityKey::RSA_OAEP_MGF1P && $inputKeyAlgo === XMLSecurityKey::RSA_1_5) {
 				/*
 				 * The RSA key formats are equal, so loading an RSA_1_5 key
@@ -426,6 +431,11 @@ class SAML2_Utils {
 			$symmetricKey = $inputKey;
 		}
 
+		$algorithm = $symmetricKey->getAlgorith();
+		if (in_array($algorithm, $blacklist, TRUE)) {
+			throw new Exception('Algorithm disabled: ' . var_export($algorithm, TRUE));
+		}
+
 		$decrypted = $enc->decryptNode($symmetricKey, FALSE);
 
 		/*
@@ -456,12 +466,13 @@ class SAML2_Utils {
 	 *
 	 * @param DOMElement $encryptedData  The encrypted data.
 	 * @param XMLSecurityKey $inputKey  The decryption key.
+	 * @param array $blacklist  Blacklisted decryption algorithms.
 	 * @return DOMElement  The decrypted element.
 	 */
-	public static function decryptElement(DOMElement $encryptedData, XMLSecurityKey $inputKey) {
+	public static function decryptElement(DOMElement $encryptedData, XMLSecurityKey $inputKey, array $blacklist = array()) {
 
 		try {
-			return self::_decryptElement($encryptedData, $inputKey);
+			return self::_decryptElement($encryptedData, $inputKey, $blacklist);
 		} catch (Exception $e) {
 			/*
 			 * Something went wrong during decryption, but for security
-- 
GitLab