2 * Copyright 2001-2006 Internet2
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
20 * Methods for encrypting XMLObjects and other data.
24 #include "encryption/Encrypter.h"
26 #include <xsec/enc/XSECCryptoException.hpp>
27 #include <xsec/framework/XSECException.hpp>
28 #include <xsec/framework/XSECAlgorithmMapper.hpp>
29 #include <xsec/framework/XSECAlgorithmHandler.hpp>
30 #include <xsec/xenc/XENCEncryptedData.hpp>
31 #include <xsec/xenc/XENCEncryptedKey.hpp>
33 using namespace xmlencryption;
34 using namespace xmlsignature;
35 using namespace xmltooling;
38 Encrypter::~Encrypter()
40 XMLToolingInternalConfig::getInternalConfig().m_xsecProvider->releaseCipher(m_cipher);
41 memset(m_keyBuffer,0,32);
44 void Encrypter::checkParams(EncryptionParams& encParams, KeyEncryptionParams* kencParams)
46 if (encParams.m_keyBufferSize==0) {
47 if (encParams.m_key) {
49 throw EncryptionException("Generating EncryptedKey inline requires the encryption key in raw form.");
51 else if (!encParams.m_key) {
53 throw EncryptionException("Using a generated encryption key requires a KeyEncryptionParams object.");
55 // We're generating a random key. The maximum supported length is AES-256, so we need 32 bytes.
56 if (XSECPlatformUtils::g_cryptoProvider->getRandom(m_keyBuffer,32)<32)
57 throw EncryptionException("Unable to generate random data; was PRNG seeded?");
58 encParams.m_keyBuffer=m_keyBuffer;
59 encParams.m_keyBufferSize=32;
63 if (!encParams.m_key) {
64 // We have to have a raw key now, so we need to build a wrapper around it.
65 XSECAlgorithmHandler* handler =XSECPlatformUtils::g_algorithmMapper->mapURIToHandler(encParams.m_algorithm);
67 encParams.m_key = handler->createKeyForURI(
68 encParams.m_algorithm,const_cast<unsigned char*>(encParams.m_keyBuffer),encParams.m_keyBufferSize
72 throw EncryptionException("Unable to build wrapper for key, unknown algorithm?");
75 // Set the encryption key.
76 m_cipher->setKey(encParams.m_key->clone());
79 EncryptedData* Encrypter::encryptElement(DOMElement* element, EncryptionParams& encParams, KeyEncryptionParams* kencParams)
81 // We can reuse the cipher object if the document hasn't changed.
83 if (m_cipher && m_cipher->getDocument()!=element->getOwnerDocument()) {
84 XMLToolingInternalConfig::getInternalConfig().m_xsecProvider->releaseCipher(m_cipher);
89 m_cipher=XMLToolingInternalConfig::getInternalConfig().m_xsecProvider->newCipher(element->getOwnerDocument());
90 m_cipher->setExclusiveC14nSerialisation(false);
94 checkParams(encParams,kencParams);
95 m_cipher->encryptElementDetached(element, ENCRYPT_NONE, encParams.m_algorithm);
96 return decorateAndUnmarshall(encParams, kencParams);
98 catch(XSECException& e) {
99 auto_ptr_char temp(e.getMsg());
100 throw EncryptionException(string("XMLSecurity exception while encrypting: ") + temp.get());
102 catch(XSECCryptoException& e) {
103 throw EncryptionException(string("XMLSecurity exception while encrypting: ") + e.getMsg());
107 EncryptedData* Encrypter::encryptElementContent(DOMElement* element, EncryptionParams& encParams, KeyEncryptionParams* kencParams)
109 // We can reuse the cipher object if the document hasn't changed.
111 if (m_cipher && m_cipher->getDocument()!=element->getOwnerDocument()) {
112 XMLToolingInternalConfig::getInternalConfig().m_xsecProvider->releaseCipher(m_cipher);
117 m_cipher=XMLToolingInternalConfig::getInternalConfig().m_xsecProvider->newCipher(element->getOwnerDocument());
118 m_cipher->setExclusiveC14nSerialisation(false);
122 checkParams(encParams,kencParams);
123 m_cipher->encryptElementContentDetached(element, ENCRYPT_NONE, encParams.m_algorithm);
124 return decorateAndUnmarshall(encParams, kencParams);
126 catch(XSECException& e) {
127 auto_ptr_char temp(e.getMsg());
128 throw EncryptionException(string("XMLSecurity exception while encrypting: ") + temp.get());
130 catch(XSECCryptoException& e) {
131 throw EncryptionException(string("XMLSecurity exception while encrypting: ") + e.getMsg());
135 EncryptedData* Encrypter::encryptStream(istream& input, EncryptionParams& encParams, KeyEncryptionParams* kencParams)
137 // Get a fresh cipher object and document.
140 XMLToolingInternalConfig::getInternalConfig().m_xsecProvider->releaseCipher(m_cipher);
144 DOMDocument* doc=NULL;
146 doc=XMLToolingConfig::getConfig().getParser().newDocument();
147 XercesJanitor<DOMDocument> janitor(doc);
148 m_cipher=XMLToolingInternalConfig::getInternalConfig().m_xsecProvider->newCipher(doc);
149 m_cipher->setExclusiveC14nSerialisation(false);
151 checkParams(encParams,kencParams);
152 StreamInputSource::StreamBinInputStream xstream(input);
153 m_cipher->encryptBinInputStream(&xstream, ENCRYPT_NONE, encParams.m_algorithm);
154 EncryptedData* xmlEncData = decorateAndUnmarshall(encParams, kencParams);
157 catch(XSECException& e) {
158 auto_ptr_char temp(e.getMsg());
159 throw EncryptionException(string("XMLSecurity exception while encrypting: ") + temp.get());
161 catch(XSECCryptoException& e) {
162 throw EncryptionException(string("XMLSecurity exception while encrypting: ") + e.getMsg());
166 EncryptedData* Encrypter::decorateAndUnmarshall(EncryptionParams& encParams, KeyEncryptionParams* kencParams)
168 XENCEncryptedData* encData=m_cipher->getEncryptedData();
170 throw EncryptionException("No EncryptedData element found?");
172 // Unmarshall a tooling version of EncryptedData around the DOM.
173 EncryptedData* xmlEncData=NULL;
174 auto_ptr<XMLObject> xmlObject(XMLObjectBuilder::buildOneFromElement(encData->getElement()));
175 if (!(xmlObject.get()) || !(xmlEncData=dynamic_cast<EncryptedData*>(xmlObject.get())))
176 throw EncryptionException("Unable to unmarshall into EncryptedData object.");
178 // Unbind from DOM so we can divorce this from the original document.
179 xmlEncData->releaseThisAndChildrenDOM();
182 if (encParams.m_keyInfo) {
183 xmlEncData->setKeyInfo(encParams.m_keyInfo);
184 encParams.m_keyInfo=NULL; // transfer ownership
187 // Are we doing a key encryption?
189 m_cipher->setKEK(kencParams->m_key->clone());
190 // ownership of this belongs to us, for some reason...
191 auto_ptr<XENCEncryptedKey> encKey(
192 m_cipher->encryptKey(encParams.m_keyBuffer, encParams.m_keyBufferSize, ENCRYPT_NONE, kencParams->m_algorithm)
194 EncryptedKey* xmlEncKey=NULL;
195 auto_ptr<XMLObject> xmlObjectKey(XMLObjectBuilder::buildOneFromElement(encKey->getElement()));
196 if (!(xmlObjectKey.get()) || !(xmlEncKey=dynamic_cast<EncryptedKey*>(xmlObjectKey.get())))
197 throw EncryptionException("Unable to unmarshall into EncryptedKey object.");
199 xmlEncKey->releaseThisAndChildrenDOM();
202 if (kencParams->m_recipient)
203 xmlEncKey->setRecipient(kencParams->m_recipient);
206 if (kencParams->m_keyInfo) {
207 xmlEncKey->setKeyInfo(kencParams->m_keyInfo);
208 kencParams->m_keyInfo=NULL; // transfer ownership
211 // Add the EncryptedKey.
212 if (!xmlEncData->getKeyInfo())
213 xmlEncData->setKeyInfo(KeyInfoBuilder::buildKeyInfo());
214 xmlEncData->getKeyInfo()->getUnknownXMLObjects().push_back(xmlEncKey);
215 xmlObjectKey.release();
222 EncryptedKey* Encrypter::encryptKey(const unsigned char* keyBuffer, unsigned int keyBufferSize, KeyEncryptionParams& kencParams)
224 // Get a fresh cipher object and document.
227 XMLToolingInternalConfig::getInternalConfig().m_xsecProvider->releaseCipher(m_cipher);
231 DOMDocument* doc=NULL;
233 doc=XMLToolingConfig::getConfig().getParser().newDocument();
234 XercesJanitor<DOMDocument> janitor(doc);
235 m_cipher=XMLToolingInternalConfig::getInternalConfig().m_xsecProvider->newCipher(doc);
236 m_cipher->setExclusiveC14nSerialisation(false);
237 m_cipher->setKEK(kencParams.m_key->clone());
238 auto_ptr<XENCEncryptedKey> encKey(m_cipher->encryptKey(keyBuffer, keyBufferSize, ENCRYPT_NONE, kencParams.m_algorithm));
240 EncryptedKey* xmlEncKey=NULL;
241 auto_ptr<XMLObject> xmlObjectKey(XMLObjectBuilder::buildOneFromElement(encKey->getElement()));
242 if (!(xmlObjectKey.get()) || !(xmlEncKey=dynamic_cast<EncryptedKey*>(xmlObjectKey.get())))
243 throw EncryptionException("Unable to unmarshall into EncryptedKey object.");
245 xmlEncKey->releaseThisAndChildrenDOM();
248 if (kencParams.m_recipient)
249 xmlEncKey->setRecipient(kencParams.m_recipient);
252 if (kencParams.m_keyInfo) {
253 xmlEncKey->setKeyInfo(kencParams.m_keyInfo);
254 kencParams.m_keyInfo=NULL; // transfer ownership
257 xmlObjectKey.release();
260 catch(XSECException& e) {
261 auto_ptr_char temp(e.getMsg());
262 throw EncryptionException(string("XMLSecurity exception while encrypting: ") + temp.get());
264 catch(XSECCryptoException& e) {
265 throw EncryptionException(string("XMLSecurity exception while encrypting: ") + e.getMsg());