1 /**
2  * Licensed to the University Corporation for Advanced Internet
3  * Development, Inc. (UCAID) under one or more contributor license
4  * agreements. See the NOTICE file distributed with this work for
5  * additional information regarding copyright ownership.
6  *
7  * UCAID licenses this file to you under the Apache License,
8  * Version 2.0 (the "License"); you may not use this file except
9  * in compliance with the License. You may obtain a copy of the
10  * License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing,
15  * software distributed under the License is distributed on an
16  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
17  * either express or implied. See the License for the specific
18  * language governing permissions and limitations under the License.
19  */
20 
21 /**
22  * XMLSecSignatureImpl.cpp
23  *
24  * Signature class for XMLSec-based signature-handling.
25  */
26 
27 #include "internal.h"
28 #include "exceptions.h"
29 #include "logging.h"
30 #include "impl/UnknownElement.h"
31 #include "security/Credential.h"
32 #include "signature/ContentReference.h"
33 #include "signature/KeyInfo.h"
34 #include "signature/Signature.h"
35 #include "util/NDC.h"
36 #include "util/XMLConstants.h"
37 #include "util/XMLHelper.h"
38 
39 #include <xercesc/framework/MemBufInputSource.hpp>
40 #include <xercesc/framework/Wrapper4InputSource.hpp>
41 #include <xercesc/util/XMLUniDefs.hpp>
42 #include <xsec/dsig/DSIGKeyInfoX509.hpp>
43 #include <xsec/dsig/DSIGReference.hpp>
44 #include <xsec/enc/XSECCryptoException.hpp>
45 #include <xsec/framework/XSECAlgorithmHandler.hpp>
46 #include <xsec/framework/XSECAlgorithmMapper.hpp>
47 #include <xsec/framework/XSECException.hpp>
48 #include <xsec/transformers/TXFMSB.hpp>
49 #include <xsec/transformers/TXFMChain.hpp>
50 #include <xsec/transformers/TXFMOutputFile.hpp>
51 
52 using namespace xmlsignature;
53 using namespace xmltooling::logging;
54 using namespace xmltooling;
55 using namespace xercesc;
56 using namespace std;
57 using xmlconstants::XMLSIG_NS;
58 using xmlconstants::XMLSIG_PREFIX;
59 
60 namespace xmlsignature {
61 
62 #if defined (_MSC_VER)
63     #pragma warning( push )
64     #pragma warning( disable : 4250 4251 )
65 #endif
66 
67     class XMLTOOL_DLLLOCAL XMLSecSignatureImpl : public UnknownElementImpl, public virtual Signature
68     {
69     public:
XMLSecSignatureImpl()70         XMLSecSignatureImpl() : AbstractXMLObject(XMLSIG_NS, Signature::LOCAL_NAME, XMLSIG_PREFIX),
71             UnknownElementImpl(XMLSIG_NS, Signature::LOCAL_NAME, XMLSIG_PREFIX),
72             m_signature(nullptr), m_c14n(nullptr), m_sm(nullptr), m_key(nullptr), m_keyInfo(nullptr), m_reference(nullptr) {}
73         virtual ~XMLSecSignatureImpl();
74 
75         void releaseDOM() const;
releaseChildrenDOM(bool propagateRelease=true) const76         void releaseChildrenDOM(bool propagateRelease=true) const {
77             if (m_keyInfo) {
78                 m_keyInfo->releaseDOM();
79                 if (propagateRelease)
80                     m_keyInfo->releaseChildrenDOM();
81             }
82         }
83         XMLObject* clone() const;
84         Signature* cloneSignature() const;
85 
86         DOMElement* marshall(DOMDocument* document=nullptr, const vector<Signature*>* sigs=nullptr, const Credential* credential=nullptr) const;
87         DOMElement* marshall(DOMElement* parentElement, const vector<Signature*>* sigs=nullptr, const Credential* credential=nullptr) const;
88         XMLObject* unmarshall(DOMElement* element, bool bindDocument=false);
89 
90         // Getters
getCanonicalizationMethod() const91         const XMLCh* getCanonicalizationMethod() const {
92             if (m_signature)
93                 return m_signature->getCanonicalizationMethod();
94             return m_c14n ? m_c14n : DSIGConstants::s_unicodeStrURIEXC_C14N_NOC;
95         }
getSignatureAlgorithm() const96         const XMLCh* getSignatureAlgorithm() const {
97             if (!m_sm && m_signature) {
98                 m_sm = XMLString::replicate(m_signature->getAlgorithmURI());
99             }
100             return m_sm;
101         }
102 
getKeyInfo() const103         KeyInfo* getKeyInfo() const { return m_keyInfo; }
getContentReference() const104         ContentReference* getContentReference() const { return m_reference; }
getXMLSignature() const105         DSIGSignature* getXMLSignature() const { return m_signature; }
106 
107         // Setters
setCanonicalizationMethod(const XMLCh * c14n)108         void setCanonicalizationMethod(const XMLCh* c14n) { m_c14n = prepareForAssignment(m_c14n,c14n); }
setSignatureAlgorithm(const XMLCh * sm)109         void setSignatureAlgorithm(const XMLCh* sm) { m_sm = prepareForAssignment(m_sm,sm); }
setSigningKey(XSECCryptoKey * signingKey)110         void setSigningKey(XSECCryptoKey* signingKey) {
111             delete m_key;
112             m_key=signingKey;
113         }
setKeyInfo(KeyInfo * keyInfo)114         void setKeyInfo(KeyInfo* keyInfo) {
115             prepareForAssignment(m_keyInfo, keyInfo);
116             m_keyInfo=keyInfo;
117         }
setContentReference(ContentReference * reference)118         void setContentReference(ContentReference* reference) {
119             delete m_reference;
120             m_reference=reference;
121         }
122 
123         void sign(const Credential* credential=nullptr);
124 
125     private:
126         mutable DSIGSignature* m_signature;
127         XMLCh* m_c14n;
128         mutable XMLCh* m_sm;
129         XSECCryptoKey* m_key;
130         mutable KeyInfo* m_keyInfo;
131         ContentReference* m_reference;
132     };
133 
134 #if defined (_MSC_VER)
135     #pragma warning( pop )
136 #endif
137 };
138 
ContentReference()139 ContentReference::ContentReference()
140 {
141 }
142 
~ContentReference()143 ContentReference::~ContentReference()
144 {
145 }
146 
Signature()147 Signature::Signature()
148 {
149 }
150 
~Signature()151 Signature::~Signature()
152 {
153 }
154 
~XMLSecSignatureImpl()155 XMLSecSignatureImpl::~XMLSecSignatureImpl()
156 {
157     // Release the associated signature.
158     if (m_signature)
159         XMLToolingInternalConfig::getInternalConfig().m_xsecProvider->releaseSignature(m_signature);
160 
161     XMLString::release(&m_c14n);
162     XMLString::release(&m_sm);
163     delete m_key;
164     delete m_keyInfo;
165     delete m_reference;
166 }
167 
releaseDOM() const168 void XMLSecSignatureImpl::releaseDOM() const
169 {
170     if (getDOM()) {
171         // This should save off the DOM
172         UnknownElementImpl::releaseDOM();
173 
174         // Release the associated signature.
175         if (m_signature) {
176             XMLToolingInternalConfig::getInternalConfig().m_xsecProvider->releaseSignature(m_signature);
177             m_signature=nullptr;
178         }
179     }
180 }
181 
clone() const182 XMLObject* XMLSecSignatureImpl::clone() const
183 {
184     return cloneSignature();
185 }
186 
cloneSignature() const187 Signature* XMLSecSignatureImpl::cloneSignature() const
188 {
189     XMLSecSignatureImpl* ret=new XMLSecSignatureImpl();
190 
191     ret->m_c14n=XMLString::replicate(m_c14n);
192     ret->m_sm=XMLString::replicate(m_sm);
193     if (m_key)
194         ret->m_key=m_key->clone();
195     if (m_keyInfo)
196         ret->m_keyInfo=m_keyInfo->cloneKeyInfo();
197 
198     // If there's no XML locally, serialize this object into the new one, otherwise just copy it over.
199     if (m_xml.empty())
200         serialize(ret->m_xml);
201     else
202         ret->m_xml=m_xml;
203 
204     return ret;
205 }
206 
sign(const Credential * credential)207 void XMLSecSignatureImpl::sign(const Credential* credential)
208 {
209     Category& log=Category::getInstance(XMLTOOLING_LOGCAT ".Signature");
210     log.debug("applying signature");
211 
212     if (!m_signature)
213         throw SignatureException("Only a marshalled Signature object can be signed.");
214     else if (!m_reference)
215         throw SignatureException("No ContentReference object set for signature creation.");
216 
217     const XSECCryptoKey* key = credential ? credential->getPrivateKey() : m_key;
218     if (!key)
219         throw SignatureException("No signing key available for signature creation.");
220 
221     try {
222         log.debug("creating signature reference(s)");
223         DSIGReferenceList* refs = m_signature->getReferenceList();
224         while (refs && refs->getSize())
225             delete refs->removeReference(0);
226         m_reference->createReferences(m_signature);
227 
228         log.debug("computing signature");
229         m_signature->setSigningKey(key->clone());
230         m_signature->sign();
231     }
232     catch(const XSECException& e) {
233         auto_ptr_char temp(e.getMsg());
234         throw SignatureException(string("Caught an XMLSecurity exception while signing: ") + temp.get());
235     }
236     catch(const XSECCryptoException& e) {
237         throw SignatureException(string("Caught an XMLSecurity exception while signing: ") + e.getMsg());
238     }
239 }
240 
marshall(DOMDocument * document,const vector<Signature * > * sigs,const Credential * credential) const241 DOMElement* XMLSecSignatureImpl::marshall(DOMDocument* document, const vector<Signature*>* sigs, const Credential* credential) const
242 {
243 #ifdef _DEBUG
244     xmltooling::NDC ndc("marshall");
245 #endif
246 
247     Category& log=Category::getInstance(XMLTOOLING_LOGCAT ".Signature");
248     log.debug("marshalling ds:Signature");
249 
250     DOMElement* cachedDOM=getDOM();
251     if (cachedDOM) {
252         if (!document || document==cachedDOM->getOwnerDocument()) {
253             log.debug("Signature has a usable cached DOM, reusing it");
254             if (document)
255                 setDocumentElement(cachedDOM->getOwnerDocument(),cachedDOM);
256             releaseParentDOM(true);
257             return cachedDOM;
258         }
259 
260         // We have a DOM but it doesn't match the document we were given. This both sucks and blows.
261         // Without an adoptNode option to maintain the child pointers, we have to either import the
262         // DOM while somehow reassigning all the nested references (which amounts to a complete
263         // *unmarshall* operation), or we just release the existing DOM and hope that we can get
264         // it back. This depends on all objects being able to preserve their DOM at all costs.
265         releaseChildrenDOM(true);
266         releaseDOM();
267     }
268 
269     // If we get here, we didn't have a usable DOM.
270     bool bindDocument=false;
271     if (m_xml.empty()) {
272         // Fresh signature, so we just create an empty one.
273         log.debug("creating empty Signature element");
274         if (!document) {
275             document=DOMImplementationRegistry::getDOMImplementation(nullptr)->createDocument();
276             bindDocument=true;
277         }
278         DSIGSignature* temp=XMLToolingInternalConfig::getInternalConfig().m_xsecProvider->newSignature();
279         temp->setDSIGNSPrefix(XMLSIG_PREFIX);
280         const XMLCh* alg = getSignatureAlgorithm();
281         if (!alg) {
282 #ifdef XSEC_OPENSSL_HAVE_SHA2
283             alg = DSIGConstants::s_unicodeStrURIRSA_SHA256;
284 #else
285             alg = DSIGConstants::s_unicodeStrURIRSA_SHA1;
286 #endif
287         }
288         cachedDOM=temp->createBlankSignature(document, getCanonicalizationMethod(), alg);
289         m_signature = temp;
290     }
291     else {
292         // We need to reparse the XML we saved off into a new DOM.
293         MemBufInputSource src(reinterpret_cast<const XMLByte*>(m_xml.c_str()),m_xml.length(),"XMLSecSignatureImpl");
294         Wrapper4InputSource dsrc(&src,false);
295         log.debug("parsing Signature XML back into DOM tree");
296         DOMDocument* internalDoc=XMLToolingConfig::getConfig().getParser().parse(dsrc);
297         if (document) {
298             // The caller insists on using his own document, so we now have to import the thing
299             // into it. Then we're just dumping the one we built.
300             log.debug("reimporting new DOM into caller-supplied document");
301             try {
302                 cachedDOM=static_cast<DOMElement*>(document->importNode(internalDoc->getDocumentElement(), true));
303             }
304             catch (XMLException& ex) {
305                 internalDoc->release();
306                 auto_ptr_char temp(ex.getMessage());
307                 throw XMLParserException(
308                     string("Error importing DOM into caller-supplied document: ") + (temp.get() ? temp.get() : "no message")
309                     );
310             }
311             internalDoc->release();
312         }
313         else {
314             // We just bind the document we built to the object as the result.
315             cachedDOM=static_cast<DOMElement*>(internalDoc->getDocumentElement());
316             document=internalDoc;
317             bindDocument=true;
318         }
319 
320         // Now reload the signature from the DOM.
321         try {
322             m_signature=XMLToolingInternalConfig::getInternalConfig().m_xsecProvider->newSignatureFromDOM(
323                 document, cachedDOM
324                 );
325             m_signature->load();
326         }
327         catch(const XSECException& e) {
328             if (bindDocument)
329                 document->release();
330             auto_ptr_char temp(e.getMsg());
331             throw MarshallingException(string("Caught an XMLSecurity exception while loading signature: ") + temp.get());
332         }
333         catch(const XSECCryptoException& e) {
334             if (bindDocument)
335                 document->release();
336             throw MarshallingException(string("Caught an XMLSecurity exception while loading signature: ") + e.getMsg());
337         }
338     }
339 
340     // Marshall KeyInfo data.
341     if (credential) {
342         delete m_keyInfo;
343         m_keyInfo = nullptr;
344         m_keyInfo = credential->getKeyInfo();
345     }
346     if (m_keyInfo && (!m_signature->getKeyInfoList() || m_signature->getKeyInfoList()->isEmpty())) {
347         m_keyInfo->marshall(cachedDOM);
348     }
349 
350     // Recache the DOM and clear the serialized copy.
351     setDocumentElement(document, cachedDOM);
352     log.debug("caching DOM for Signature (document is %sbound)", bindDocument ? "" : "not ");
353     setDOM(cachedDOM, bindDocument);
354     releaseParentDOM(true);
355     m_xml.erase();
356     return cachedDOM;
357 }
358 
marshall(DOMElement * parentElement,const vector<Signature * > * sigs,const Credential * credential) const359 DOMElement* XMLSecSignatureImpl::marshall(DOMElement* parentElement, const vector<Signature*>* sigs, const Credential* credential) const
360 {
361 #ifdef _DEBUG
362     xmltooling::NDC ndc("marshall");
363 #endif
364 
365     Category& log=Category::getInstance(XMLTOOLING_LOGCAT ".Signature");
366     log.debug("marshalling ds:Signature");
367 
368     DOMElement* cachedDOM=getDOM();
369     if (cachedDOM) {
370         if (parentElement->getOwnerDocument()==cachedDOM->getOwnerDocument()) {
371             log.debug("Signature has a usable cached DOM, reusing it");
372             if (parentElement!=cachedDOM->getParentNode()) {
373                 parentElement->appendChild(cachedDOM);
374                 releaseParentDOM(true);
375             }
376             return cachedDOM;
377         }
378 
379         // We have a DOM but it doesn't match the document we were given. This both sucks and blows.
380         // Without an adoptNode option to maintain the child pointers, we have to either import the
381         // DOM while somehow reassigning all the nested references (which amounts to a complete
382         // *unmarshall* operation), or we just release the existing DOM and hope that we can get
383         // it back. This depends on all objects being able to preserve their DOM at all costs.
384         releaseChildrenDOM(true);
385         releaseDOM();
386     }
387 
388     // If we get here, we didn't have a usable DOM.
389     if (m_xml.empty()) {
390         // Fresh signature, so we just create an empty one.
391         log.debug("creating empty Signature element");
392         DSIGSignature* temp=XMLToolingInternalConfig::getInternalConfig().m_xsecProvider->newSignature();
393         temp->setDSIGNSPrefix(XMLSIG_PREFIX);
394         const XMLCh* alg = getSignatureAlgorithm();
395         if (!alg)
396             alg = DSIGConstants::s_unicodeStrURIRSA_SHA1;
397         cachedDOM=temp->createBlankSignature(parentElement->getOwnerDocument(), getCanonicalizationMethod(), alg);
398         m_signature = temp;
399     }
400     else {
401         MemBufInputSource src(reinterpret_cast<const XMLByte*>(m_xml.c_str()),m_xml.length(),"XMLSecSignatureImpl");
402         Wrapper4InputSource dsrc(&src,false);
403         log.debug("parsing XML back into DOM tree");
404         DOMDocument* internalDoc=XMLToolingConfig::getConfig().getParser().parse(dsrc);
405 
406         log.debug("reimporting new DOM into caller-supplied document");
407         try {
408             cachedDOM=static_cast<DOMElement*>(parentElement->getOwnerDocument()->importNode(internalDoc->getDocumentElement(),true));
409         }
410         catch (const XMLException& ex) {
411             internalDoc->release();
412             auto_ptr_char temp(ex.getMessage());
413             throw XMLParserException(
414                 string("Error importing DOM into caller-supplied document: ") + (temp.get() ? temp.get() : "no message")
415                 );
416         }
417         internalDoc->release();
418 
419         // Now reload the signature from the DOM.
420         try {
421             m_signature=XMLToolingInternalConfig::getInternalConfig().m_xsecProvider->newSignatureFromDOM(
422                 parentElement->getOwnerDocument(), cachedDOM
423                 );
424             m_signature->load();
425         }
426         catch(const XSECException& e) {
427             auto_ptr_char temp(e.getMsg());
428             throw MarshallingException(string("Caught an XMLSecurity exception while loading signature: ") + temp.get());
429         }
430         catch(const XSECCryptoException& e) {
431             throw MarshallingException(string("Caught an XMLSecurity exception while loading signature: ") + e.getMsg());
432         }
433     }
434 
435     // Marshall KeyInfo data.
436     if (credential) {
437         delete m_keyInfo;
438         m_keyInfo = nullptr;
439         m_keyInfo = credential->getKeyInfo();
440     }
441     if (m_keyInfo && (!m_signature->getKeyInfoList() || m_signature->getKeyInfoList()->isEmpty())) {
442         m_keyInfo->marshall(cachedDOM);
443     }
444 
445     // Recache the DOM and clear the serialized copy.
446     parentElement->appendChild(cachedDOM);
447     log.debug("caching DOM for Signature");
448     setDOM(cachedDOM, false);
449     releaseParentDOM(true);
450     m_xml.erase();
451     return cachedDOM;
452 }
453 
unmarshall(DOMElement * element,bool bindDocument)454 XMLObject* XMLSecSignatureImpl::unmarshall(DOMElement* element, bool bindDocument)
455 {
456     Category::getInstance(XMLTOOLING_LOGCAT ".Signature").debug("unmarshalling ds:Signature");
457 
458     try {
459         m_signature=XMLToolingInternalConfig::getInternalConfig().m_xsecProvider->newSignatureFromDOM(
460             element->getOwnerDocument(), element
461             );
462         m_signature->load();
463     }
464     catch(const XSECException& e) {
465         auto_ptr_char temp(e.getMsg());
466         throw UnmarshallingException(string("Caught an XMLSecurity exception while loading signature: ") + temp.get());
467     }
468     catch(const XSECCryptoException& e) {
469         throw UnmarshallingException(string("Caught an XMLSecurity exception while loading signature: ") + e.getMsg());
470     }
471 
472     setDOM(element, bindDocument);
473     return this;
474 }
475 
476 #ifdef HAVE_COVARIANT_RETURNS
477 Signature*
478 #else
479 XMLObject*
480 #endif
buildObject(const XMLCh * nsURI,const XMLCh * localName,const XMLCh * prefix,const xmltooling::QName * schemaType) const481 SignatureBuilder::buildObject(
482     const XMLCh* nsURI, const XMLCh* localName, const XMLCh* prefix, const xmltooling::QName* schemaType
483     ) const
484 {
485     if (!XMLString::equals(nsURI,XMLSIG_NS) || !XMLString::equals(localName,Signature::LOCAL_NAME))
486         throw XMLObjectException("XMLSecSignatureBuilder requires standard Signature element name.");
487     return buildObject();
488 }
489 
490 #ifdef HAVE_COVARIANT_RETURNS
491 Signature*
492 #else
493 XMLObject*
494 #endif
buildObject() const495 SignatureBuilder::buildObject() const
496 {
497     return new XMLSecSignatureImpl();
498 }
499 
buildSignature()500 Signature* SignatureBuilder::buildSignature() {
501     const SignatureBuilder* b = dynamic_cast<const SignatureBuilder*>(
502         XMLObjectBuilder::getBuilder(xmltooling::QName(xmlconstants::XMLSIG_NS,Signature::LOCAL_NAME))
503         );
504     if (b) {
505 #ifdef HAVE_COVARIANT_RETURNS
506         return b->buildObject();
507 #else
508         return dynamic_cast<Signature*>(b->buildObject());
509 #endif
510     }
511     throw XMLObjectException("Unable to obtain typed builder for Signature.");
512 }
513 
514 const XMLCh Signature::LOCAL_NAME[] = UNICODE_LITERAL_9(S,i,g,n,a,t,u,r,e);
515 
516 // Raw signature methods.
517 
createRawSignature(const XSECCryptoKey * key,const XMLCh * sigAlgorithm,const char * in,unsigned int in_len,char * out,unsigned int out_len)518 unsigned int Signature::createRawSignature(
519     const XSECCryptoKey* key, const XMLCh* sigAlgorithm, const char* in, unsigned int in_len, char* out, unsigned int out_len
520     )
521 {
522     try {
523         const XSECAlgorithmHandler* handler = XSECPlatformUtils::g_algorithmMapper->mapURIToHandler(sigAlgorithm);
524         if (!handler) {
525             auto_ptr_char alg(sigAlgorithm);
526             throw SignatureException("Unsupported signature algorithm ($1).", params(1,alg.get()));
527         }
528 
529         // Move input into a safeBuffer to source the transform chain.
530         safeBuffer sb,sbout;
531         sb.sbStrncpyIn(in,in_len);
532         TXFMSB* sbt = new TXFMSB(nullptr);
533         sbt->setInput(sb, in_len);
534         TXFMChain tx(sbt);
535 
536         // Sign the chain.
537         unsigned int siglen = handler->signToSafeBuffer(&tx, sigAlgorithm, key, out_len-1, sbout);
538         if (siglen >= out_len)
539             throw SignatureException("Signature size exceeded output buffer size.");
540 
541         // Push all non-whitespace into buffer.
542         unsigned int ret_len = 0;
543         const char* source = sbout.rawCharBuffer();
544         while (siglen--) {
545             if (isspace(*source))
546                 ++source;
547             else {
548                 *out++ = *source++;
549                 ++ret_len;
550             }
551         }
552         *out = 0;
553         return ret_len;
554     }
555     catch(const XSECException& e) {
556         auto_ptr_char temp(e.getMsg());
557         throw SignatureException(string("Caught an XMLSecurity exception while creating raw signature: ") + temp.get());
558     }
559     catch(const XSECCryptoException& e) {
560         throw SignatureException(string("Caught an XMLSecurity exception while creating raw signature: ") + e.getMsg());
561     }
562 }
563 
verifyRawSignature(const XSECCryptoKey * key,const XMLCh * sigAlgorithm,const char * signature,const char * in,unsigned int in_len)564 bool Signature::verifyRawSignature(
565     const XSECCryptoKey* key, const XMLCh* sigAlgorithm, const char* signature, const char* in, unsigned int in_len
566     )
567 {
568     try {
569         const XSECAlgorithmHandler* handler = XSECPlatformUtils::g_algorithmMapper->mapURIToHandler(sigAlgorithm);
570         if (!handler) {
571             auto_ptr_char alg(sigAlgorithm);
572             throw SignatureException("Unsupported signature algorithm ($1).", params(1,alg.get()));
573         }
574 
575         // Move input into a safeBuffer to source the transform chain.
576         safeBuffer sb;
577         sb.sbStrncpyIn(in,in_len);
578         TXFMSB* sbt = new TXFMSB(nullptr);
579         sbt->setInput(sb, in_len);
580         TXFMChain tx(sbt);
581 
582         // Verify the chain.
583         return handler->verifyBase64Signature(&tx, sigAlgorithm, signature, 0, key);
584     }
585     catch(const XSECException& e) {
586         auto_ptr_char temp(e.getMsg());
587         throw SignatureException(string("Caught an XMLSecurity exception while verifying raw signature: ") + temp.get());
588     }
589     catch(const XSECCryptoException& e) {
590         throw SignatureException(string("Caught an XMLSecurity exception while verifying raw signature: ") + e.getMsg());
591     }
592 }
593