Skip to content
Snippets Groups Projects
Commit 97b3ffa2 authored by Olav Morken's avatar Olav Morken
Browse files

Minimal backport of key oracle fixes.

This is a backport of the changes in r2953, with one small change
from r2952.

git-svn-id: https://simplesamlphp.googlecode.com/svn/branches/simplesamlphp-1.8@2955 44740490-163a-0410-bde0-09ae8108e29a
parent f55cc1e3
No related branches found
No related tags found
No related merge requests found
...@@ -344,8 +344,41 @@ class SAML2_Utils { ...@@ -344,8 +344,41 @@ class SAML2_Utils {
$encKey = $symmetricKeyInfo->encryptedCtx; $encKey = $symmetricKeyInfo->encryptedCtx;
$symmetricKeyInfo->key = $inputKey->key; $symmetricKeyInfo->key = $inputKey->key;
$key = $encKey->decryptKey($symmetricKeyInfo);
$keySizes = array(
XMLSecurityKey::TRIPLEDES_CBC => 24,
XMLSecurityKey::AES128_CBC => 16,
XMLSecurityKey::AES192_CBC => 24,
XMLSecurityKey::AES256_CBC => 32,
);
if (!isset($keySizes[$symmetricKey->type])) {
/* To protect against "key oracle" attacks, we need to be able to create a
* symmetric key, and for that we need to know the key size.
*/
throw new Exception('Unsupported encryption algorithm: ' . var_export($symmetricKey->type, TRUE));
}
$keySize = $keySizes[$symmetricKey->type];
try {
$key = $encKey->decryptKey($symmetricKeyInfo);
} catch (Exception $e) {
/* We failed to decrypt this key. Log it, and substitute a "random" key. */
SimpleSAML_Logger::error('Failed to decrypt symmetric key: ' . $e->getMessage());
/* Create a replacement key, so that it looks like we fail in the same way as if the key was correctly padded. */
/* We base the symmetric key on the encrypted key, so that we always behave the same way for a given input key. */
$encryptedKey = $encKey->getCipherValue();
$key = md5($encryptedKey, TRUE);
/* Make sure that the key has the correct length. */
if (strlen($key) > $keySize) {
$key = substr($key, 0, $keySize);
} elseif (strlen($key) < $keySize) {
$key = str_pad($key, $keySize);
}
}
$symmetricKey->loadkey($key); $symmetricKey->loadkey($key);
} else { } else {
$symKeyAlgo = $symmetricKey->getAlgorith(); $symKeyAlgo = $symmetricKey->getAlgorith();
/* Make sure that the input key has the correct format. */ /* Make sure that the input key has the correct format. */
......
...@@ -1454,23 +1454,50 @@ class XMLSecEnc { ...@@ -1454,23 +1454,50 @@ class XMLSecEnc {
$this->type = $curType; $this->type = $curType;
} }
public function decryptNode($objKey, $replace=TRUE) { /**
$data = ''; * Retrieve the CipherValue text from this encrypted node.
*
* @return string|NULL The Ciphervalue text, or NULL if no CipherValue is found.
*/
public function getCipherValue() {
if (empty($this->rawNode)) { if (empty($this->rawNode)) {
throw new Exception('Node to decrypt has not been set'); throw new Exception('Node to decrypt has not been set');
} }
if (! $objKey instanceof XMLSecurityKey) {
throw new Exception('Invalid Key');
}
$doc = $this->rawNode->ownerDocument; $doc = $this->rawNode->ownerDocument;
$xPath = new DOMXPath($doc); $xPath = new DOMXPath($doc);
$xPath->registerNamespace('xmlencr', XMLSecEnc::XMLENCNS); $xPath->registerNamespace('xmlencr', XMLSecEnc::XMLENCNS);
/* Only handles embedded content right now and not a reference */ /* Only handles embedded content right now and not a reference */
$query = "./xmlencr:CipherData/xmlencr:CipherValue"; $query = "./xmlencr:CipherData/xmlencr:CipherValue";
$nodeset = $xPath->query($query, $this->rawNode); $nodeset = $xPath->query($query, $this->rawNode);
$node = $nodeset->item(0);
if (!$node) {
return NULL;
}
return base64_decode($node->nodeValue);
}
/**
* Decrypt this encrypted node.
*
* The behaviour of this function depends on the value of $replace.
* If $replace is FALSE, we will return the decrypted data as a string.
* If $replace is TRUE, we will insert the decrypted element(s) into the
* document, and return the decrypted element(s).
*
* @params XMLSecurityKey $objKey The decryption key that should be used when decrypting the node.
* @params boolean $replace Whether we should replace the encrypted node in the XML document with the decrypted data. The default is TRUE.
* @return string|DOMElement The decrypted data.
*/
public function decryptNode($objKey, $replace=TRUE) {
if (! $objKey instanceof XMLSecurityKey) {
throw new Exception('Invalid Key');
}
if ($node = $nodeset->item(0)) { $encryptedData = $this->getCipherValue();
$encryptedData = base64_decode($node->nodeValue); if ($encryptedData) {
$decrypted = $objKey->decryptData($encryptedData); $decrypted = $objKey->decryptData($encryptedData);
if ($replace) { if ($replace) {
switch ($this->type) { switch ($this->type) {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment