public override void LoadInnerXml(XmlNodeList nodeList)
 {
     if (nodeList == null)
     {
         throw new CryptographicException(SR.Cryptography_Xml_UnknownTransform);
     }
     ExceptUris.Clear();
     foreach (XmlNode node in nodeList)
     {
         XmlElement elem = node as XmlElement;
         if (elem != null)
         {
             if (elem.LocalName == "Except" && elem.NamespaceURI == XmlDecryptionTransformNamespaceUrl)
             {
                 // the Uri is required
                 string uri = Utils.GetAttribute(elem, "URI", XmlDecryptionTransformNamespaceUrl);
                 if (uri == null || uri.Length == 0 || uri[0] != '#')
                 {
                     throw new CryptographicException(SR.Cryptography_Xml_UriRequired);
                 }
                 if (!Utils.VerifyAttributes(elem, "URI"))
                 {
                     throw new CryptographicException(SR.Cryptography_Xml_UnknownTransform);
                 }
                 string idref = Utils.ExtractIdFromLocalUri(uri);
                 ExceptUris.Add(idref);
             }
             else
             {
                 throw new CryptographicException(SR.Cryptography_Xml_UnknownTransform);
             }
         }
     }
 }
Example #2
0
        private int GetReferenceLevel(int index, ArrayList references)
        {
            if (_refProcessed[index])
            {
                return(_refLevelCache[index]);
            }
            _refProcessed[index] = true;
            Reference reference = (Reference)references[index];

            if (reference.Uri == null || reference.Uri.Length == 0 || (reference.Uri.Length > 0 && reference.Uri[0] != '#'))
            {
                _refLevelCache[index] = 0;
                return(0);
            }
            if (reference.Uri.Length > 0 && reference.Uri[0] == '#')
            {
                string idref = Utils.ExtractIdFromLocalUri(reference.Uri);
                if (idref == "xpointer(/)")
                {
                    _refLevelCache[index] = 0;
                    return(0);
                }
                // If this is pointing to another reference
                for (int j = 0; j < references.Count; ++j)
                {
                    if (((Reference)references[j]).Id == idref)
                    {
                        _refLevelCache[index] = GetReferenceLevel(j, references) + 1;
                        return(_refLevelCache[index]);
                    }
                }
                // Then the reference points to an object tag
                _refLevelCache[index] = 0;
                return(0);
            }
            // Malformed reference
            throw new CryptographicException(SR.Cryptography_Xml_InvalidReference);
        }
Example #3
0
        // Try to decrypt the EncryptedKey given the key mapping
        public virtual byte[] DecryptEncryptedKey(EncryptedKey encryptedKey)
        {
            if (encryptedKey == null)
            {
                throw new ArgumentNullException("encryptedKey");
            }
            if (encryptedKey.KeyInfo == null)
            {
                return(null);
            }

            IEnumerator            keyInfoEnum = encryptedKey.KeyInfo.GetEnumerator();
            KeyInfoName            kiName;
            KeyInfoX509Data        kiX509Data;
            KeyInfoRetrievalMethod kiRetrievalMethod;
            KeyInfoEncryptedKey    kiEncKey;
            EncryptedKey           ek = null;
            bool fOAEP = false;

            while (keyInfoEnum.MoveNext())
            {
                kiName = keyInfoEnum.Current as KeyInfoName;
                if (kiName != null)
                {
                    // Get the decryption key from the key mapping
                    string keyName = kiName.Value;
                    Object kek     = m_keyNameMapping[keyName];
                    if (kek != null)
                    {
                        if (!Utils.GetLeaveCipherValueUnchecked() && (encryptedKey.CipherData == null || encryptedKey.CipherData.CipherValue == null))
                        {
                            throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_MissingAlgorithm"));
                        }
                        // kek is either a SymmetricAlgorithm or an RSA key, otherwise, we wouldn't be able to insert it in the hash table
                        if (kek is SymmetricAlgorithm)
                        {
                            return(EncryptedXml.DecryptKey(encryptedKey.CipherData.CipherValue, (SymmetricAlgorithm)kek));
                        }

                        // kek is an RSA key: get fOAEP from the algorithm, default to false
                        fOAEP = (encryptedKey.EncryptionMethod != null && encryptedKey.EncryptionMethod.KeyAlgorithm == EncryptedXml.XmlEncRSAOAEPUrl);
                        return(EncryptedXml.DecryptKey(encryptedKey.CipherData.CipherValue, (RSA)kek, fOAEP));
                    }
                    break;
                }
                kiX509Data = keyInfoEnum.Current as KeyInfoX509Data;
                if (kiX509Data != null)
                {
                    X509Certificate2Collection collection = Utils.BuildBagOfCerts(kiX509Data, CertUsageType.Decryption);
                    foreach (X509Certificate2 certificate in collection)
                    {
                        using (RSA privateKey = certificate.GetRSAPrivateKey()) {
                            if (privateKey != null)
                            {
                                if (!Utils.GetLeaveCipherValueUnchecked() && (encryptedKey.CipherData == null || encryptedKey.CipherData.CipherValue == null))
                                {
                                    throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_MissingAlgorithm"));
                                }
                                fOAEP = (encryptedKey.EncryptionMethod != null && encryptedKey.EncryptionMethod.KeyAlgorithm == EncryptedXml.XmlEncRSAOAEPUrl);
                                return(EncryptedXml.DecryptKey(encryptedKey.CipherData.CipherValue, privateKey, fOAEP));
                            }
                        }
                    }
                    break;
                }
                kiRetrievalMethod = keyInfoEnum.Current as KeyInfoRetrievalMethod;
                if (kiRetrievalMethod != null)
                {
                    string idref = Utils.ExtractIdFromLocalUri(kiRetrievalMethod.Uri);
                    ek = new EncryptedKey();
                    ek.LoadXml(GetIdElement(m_document, idref));
                    try {
                        //Following checks if XML dsig processing is in loop and within the limit defined by machine
                        // admin or developer. Once the recursion depth crosses the defined limit it will throw exception.
                        m_xmlDsigSearchDepthCounter++;
                        if (IsOverXmlDsigRecursionLimit())
                        {
                            //Throw exception once recursion limit is hit.
                            throw new CryptoSignedXmlRecursionException();
                        }
                        else
                        {
                            return(DecryptEncryptedKey(ek));
                        }
                    }
                    finally {
                        m_xmlDsigSearchDepthCounter--;
                    }
                }
                kiEncKey = keyInfoEnum.Current as KeyInfoEncryptedKey;
                if (kiEncKey != null)
                {
                    ek = kiEncKey.EncryptedKey;
                    // recursively process EncryptedKey elements
                    byte[] encryptionKey = DecryptEncryptedKey(ek);
                    if (encryptionKey != null)
                    {
                        // this is a symmetric algorithm for sure
                        SymmetricAlgorithm symAlg = Utils.CreateFromName <SymmetricAlgorithm>(encryptedKey.EncryptionMethod.KeyAlgorithm);
                        if (symAlg == null)
                        {
                            throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_MissingAlgorithm"));
                        }
                        symAlg.Key = encryptionKey;
                        if (!Utils.GetLeaveCipherValueUnchecked() && (encryptedKey.CipherData == null || encryptedKey.CipherData.CipherValue == null))
                        {
                            throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_MissingAlgorithm"));
                        }
                        return(EncryptedXml.DecryptKey(encryptedKey.CipherData.CipherValue, symAlg));
                    }
                }
            }
            return(null);
        }
Example #4
0
        // default behaviour is to look for keys defined by an EncryptedKey clause
        // either directly or through a KeyInfoRetrievalMethod, and key names in the key mapping
        public virtual SymmetricAlgorithm GetDecryptionKey(EncryptedData encryptedData, string symmetricAlgorithmUri)
        {
            if (encryptedData == null)
            {
                throw new ArgumentNullException("encryptedData");
            }

            if (encryptedData.KeyInfo == null)
            {
                return(null);
            }
            IEnumerator            keyInfoEnum = encryptedData.KeyInfo.GetEnumerator();
            KeyInfoRetrievalMethod kiRetrievalMethod;
            KeyInfoName            kiName;
            KeyInfoEncryptedKey    kiEncKey;
            EncryptedKey           ek = null;

            while (keyInfoEnum.MoveNext())
            {
                kiName = keyInfoEnum.Current as KeyInfoName;
                if (kiName != null)
                {
                    // Get the decryption key from the key mapping
                    string keyName = kiName.Value;
                    if ((SymmetricAlgorithm)m_keyNameMapping[keyName] != null)
                    {
                        return((SymmetricAlgorithm)m_keyNameMapping[keyName]);
                    }
                    // try to get it from a CarriedKeyName
                    XmlNamespaceManager nsm = new XmlNamespaceManager(m_document.NameTable);
                    nsm.AddNamespace("enc", EncryptedXml.XmlEncNamespaceUrl);
                    XmlNodeList encryptedKeyList = m_document.SelectNodes("//enc:EncryptedKey", nsm);
                    if (encryptedKeyList != null)
                    {
                        foreach (XmlNode encryptedKeyNode in encryptedKeyList)
                        {
                            XmlElement   encryptedKeyElement = encryptedKeyNode as XmlElement;
                            EncryptedKey ek1 = new EncryptedKey();
                            ek1.LoadXml(encryptedKeyElement);
                            if (ek1.CarriedKeyName == keyName && ek1.Recipient == this.Recipient)
                            {
                                ek = ek1;
                                break;
                            }
                        }
                    }
                    break;
                }
                kiRetrievalMethod = keyInfoEnum.Current as KeyInfoRetrievalMethod;
                if (kiRetrievalMethod != null)
                {
                    string idref = Utils.ExtractIdFromLocalUri(kiRetrievalMethod.Uri);
                    ek = new EncryptedKey();
                    ek.LoadXml(GetIdElement(m_document, idref));
                    break;
                }
                kiEncKey = keyInfoEnum.Current as KeyInfoEncryptedKey;
                if (kiEncKey != null)
                {
                    ek = kiEncKey.EncryptedKey;
                    break;
                }
            }

            // if we have an EncryptedKey, decrypt to get the symmetric key
            if (ek != null)
            {
                // now process the EncryptedKey, loop recursively
                // If the Uri is not provided by the application, try to get it from the EncryptionMethod
                if (symmetricAlgorithmUri == null)
                {
                    if (encryptedData.EncryptionMethod == null)
                    {
                        throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_MissingAlgorithm"));
                    }
                    symmetricAlgorithmUri = encryptedData.EncryptionMethod.KeyAlgorithm;
                }
                byte[] key = DecryptEncryptedKey(ek);
                if (key == null)
                {
                    throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_MissingDecryptionKey"));
                }

                SymmetricAlgorithm symAlg = Utils.CreateFromName <SymmetricAlgorithm>(symmetricAlgorithmUri);
                if (symAlg == null)
                {
                    throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_MissingAlgorithm"));
                }
                symAlg.Key = key;
                return(symAlg);
            }
            return(null);
        }
Example #5
0
        //
        // private methods
        //

        private byte[] GetCipherValue(CipherData cipherData)
        {
            if (cipherData == null)
            {
                throw new ArgumentNullException("cipherData");
            }

            WebResponse response    = null;
            Stream      inputStream = null;

            if (cipherData.CipherValue != null)
            {
                return(cipherData.CipherValue);
            }
            else if (cipherData.CipherReference != null)
            {
                if (cipherData.CipherReference.CipherValue != null)
                {
                    return(cipherData.CipherReference.CipherValue);
                }
                Stream decInputStream = null;
                // See if the CipherReference is a local URI
                if (!Utils.GetLeaveCipherValueUnchecked() && cipherData.CipherReference.Uri == null)
                {
                    throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_UriNotSupported"));
                }
                if (cipherData.CipherReference.Uri.Length == 0)
                {
                    // self referenced Uri
                    string         baseUri = (m_document == null ? null : m_document.BaseURI);
                    TransformChain tc      = cipherData.CipherReference.TransformChain;
                    if (!Utils.GetLeaveCipherValueUnchecked() && tc == null)
                    {
                        throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_UriNotSupported"));
                    }
                    decInputStream = tc.TransformToOctetStream(m_document, m_xmlResolver, baseUri);
                }
                else if (cipherData.CipherReference.Uri[0] == '#')
                {
                    string idref = Utils.ExtractIdFromLocalUri(cipherData.CipherReference.Uri);
                    // Serialize
                    if (Utils.GetLeaveCipherValueUnchecked())
                    {
                        inputStream = new MemoryStream(m_encoding.GetBytes(GetIdElement(m_document, idref).OuterXml));
                    }
                    else
                    {
                        XmlElement idElem = GetIdElement(m_document, idref);
                        if (idElem == null || idElem.OuterXml == null)
                        {
                            throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_UriNotSupported"));
                        }
                        inputStream = new MemoryStream(m_encoding.GetBytes(idElem.OuterXml));
                    }

                    string         baseUri = (m_document == null ? null : m_document.BaseURI);
                    TransformChain tc      = cipherData.CipherReference.TransformChain;
                    if (!Utils.GetLeaveCipherValueUnchecked() && tc == null)
                    {
                        throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_UriNotSupported"));
                    }
                    decInputStream = tc.TransformToOctetStream(inputStream, m_xmlResolver, baseUri);
                }
                else
                {
                    DownloadCipherValue(cipherData, out inputStream, out decInputStream, out response);
                }
                // read the output stream into a memory stream
                byte[] cipherValue = null;
                using (MemoryStream ms = new MemoryStream()) {
                    Utils.Pump(decInputStream, ms);
                    cipherValue = ms.ToArray();
                    // Close the stream and return
                    if (response != null)
                    {
                        response.Close();
                    }
                    if (inputStream != null)
                    {
                        inputStream.Close();
                    }
                    decInputStream.Close();
                }

                // cache the cipher value for Perf reasons in case we call this routine twice
                cipherData.CipherReference.CipherValue = cipherValue;
                return(cipherValue);
            }

            // Throw a CryptographicException if we were unable to retrieve the cipher data.
            throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_MissingCipherData"));
        }
        // Try to decrypt the EncryptedKey given the key mapping
        public virtual byte[] DecryptEncryptedKey(EncryptedKey encryptedKey)
        {
            if (encryptedKey == null)
            {
                throw new ArgumentNullException("encryptedKey");
            }
            if (encryptedKey.KeyInfo == null)
            {
                return(null);
            }

            IEnumerator            keyInfoEnum = encryptedKey.KeyInfo.GetEnumerator();
            KeyInfoName            kiName;
            KeyInfoX509Data        kiX509Data;
            KeyInfoRetrievalMethod kiRetrievalMethod;
            KeyInfoEncryptedKey    kiEncKey;
            EncryptedKey           ek = null;
            bool fOAEP = false;

            while (keyInfoEnum.MoveNext())
            {
                kiName = keyInfoEnum.Current as KeyInfoName;
                if (kiName != null)
                {
                    // Get the decryption key from the key mapping
                    string keyName = kiName.Value;
                    Object kek     = m_keyNameMapping[keyName];
                    if (kek != null)
                    {
                        // kek is either a SymmetricAlgorithm or an RSA key, otherwise, we wouldn't be able to insert it in the hash table
                        if (kek is SymmetricAlgorithm)
                        {
                            return(EncryptedXml.DecryptKey(encryptedKey.CipherData.CipherValue, (SymmetricAlgorithm)kek));
                        }

                        // kek is an RSA key: get fOAEP from the algorithm, default to false
                        fOAEP = (encryptedKey.EncryptionMethod != null && encryptedKey.EncryptionMethod.KeyAlgorithm == EncryptedXml.XmlEncRSAOAEPUrl);
                        return(EncryptedXml.DecryptKey(encryptedKey.CipherData.CipherValue, (RSA)kek, fOAEP));
                    }
                    break;
                }
                kiX509Data = keyInfoEnum.Current as KeyInfoX509Data;
                if (kiX509Data != null)
                {
                    X509Certificate2Collection collection = Utils.BuildBagOfCerts(kiX509Data, CertUsageType.Decryption);
                    foreach (X509Certificate2 certificate in collection)
                    {
                        RSA privateKey = certificate.PrivateKey as RSA;
                        if (privateKey != null)
                        {
                            fOAEP = (encryptedKey.EncryptionMethod != null && encryptedKey.EncryptionMethod.KeyAlgorithm == EncryptedXml.XmlEncRSAOAEPUrl);
                            return(EncryptedXml.DecryptKey(encryptedKey.CipherData.CipherValue, privateKey, fOAEP));
                        }
                    }
                    break;
                }
                kiRetrievalMethod = keyInfoEnum.Current as KeyInfoRetrievalMethod;
                if (kiRetrievalMethod != null)
                {
                    string idref = Utils.ExtractIdFromLocalUri(kiRetrievalMethod.Uri);
                    ek = new EncryptedKey();
                    ek.LoadXml(GetIdElement(m_document, idref));
                    return(DecryptEncryptedKey(ek));
                }
                kiEncKey = keyInfoEnum.Current as KeyInfoEncryptedKey;
                if (kiEncKey != null)
                {
                    ek = kiEncKey.EncryptedKey;
                    // recursively process EncryptedKey elements
                    byte[] encryptionKey = DecryptEncryptedKey(ek);
                    if (encryptionKey != null)
                    {
                        // this is a symmetric algorithm for sure
                        SymmetricAlgorithm symAlg = (SymmetricAlgorithm)CryptoConfig.CreateFromName(encryptedKey.EncryptionMethod.KeyAlgorithm);
                        symAlg.Key = encryptionKey;
                        return(EncryptedXml.DecryptKey(encryptedKey.CipherData.CipherValue, symAlg));
                    }
                }
            }
            return(null);
        }
Example #7
0
        //
        // private methods
        //

        private byte[] GetCipherValue(CipherData cipherData)
        {
            if (cipherData == null)
            {
                throw new ArgumentNullException(nameof(cipherData));
            }

            WebResponse response    = null;
            Stream      inputStream = null;

            if (cipherData.CipherValue != null)
            {
                return(cipherData.CipherValue);
            }
            else if (cipherData.CipherReference != null)
            {
                if (cipherData.CipherReference.CipherValue != null)
                {
                    return(cipherData.CipherReference.CipherValue);
                }
                Stream decInputStream = null;
                // See if the CipherReference is a local URI
                if (cipherData.CipherReference.Uri.Length == 0)
                {
                    // self referenced Uri
                    string         baseUri = (_document == null ? null : _document.BaseURI);
                    TransformChain tc      = cipherData.CipherReference.TransformChain;
                    decInputStream = tc.TransformToOctetStream(_document, _xmlResolver, baseUri);
                }
                else if (cipherData.CipherReference.Uri[0] == '#')
                {
                    string idref = Utils.ExtractIdFromLocalUri(cipherData.CipherReference.Uri);
                    // Serialize
                    inputStream = new MemoryStream(_encoding.GetBytes(GetIdElement(_document, idref).OuterXml));
                    string         baseUri = (_document == null ? null : _document.BaseURI);
                    TransformChain tc      = cipherData.CipherReference.TransformChain;
                    decInputStream = tc.TransformToOctetStream(inputStream, _xmlResolver, baseUri);
                }
                else
                {
                    throw new CryptographicException(SR.Cryptography_Xml_UriNotResolved, cipherData.CipherReference.Uri);
                }
                // read the output stream into a memory stream
                byte[] cipherValue = null;
                using (MemoryStream ms = new MemoryStream())
                {
                    Utils.Pump(decInputStream, ms);
                    cipherValue = ms.ToArray();
                    // Close the stream and return
                    if (response != null)
                    {
                        response.Close();
                    }
                    if (inputStream != null)
                    {
                        inputStream.Close();
                    }
                    decInputStream.Close();
                }

                // cache the cipher value for Perf reasons in case we call this routine twice
                cipherData.CipherReference.CipherValue = cipherValue;
                return(cipherValue);
            }

            // Throw a CryptographicException if we were unable to retrieve the cipher data.
            throw new CryptographicException(SR.Cryptography_Xml_MissingCipherData);
        }