2 * Copyright 2001-2010 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 * A helper class for working with keys, certificates, etc.
25 #include "io/HTTPResponse.h"
26 #include "security/OpenSSLCryptoX509CRL.h"
27 #include "security/SecurityHelper.h"
28 #include "security/X509Credential.h"
29 #include "soap/HTTPSOAPTransport.h"
33 #include <openssl/evp.h>
34 #include <openssl/pem.h>
35 #include <openssl/pkcs12.h>
36 #include <xsec/enc/XSECCryptoException.hpp>
37 #include <xsec/enc/OpenSSL/OpenSSLCryptoX509.hpp>
38 #include <xsec/enc/OpenSSL/OpenSSLCryptoKeyRSA.hpp>
39 #include <xsec/enc/OpenSSL/OpenSSLCryptoKeyDSA.hpp>
40 #include <xercesc/util/Base64.hpp>
42 using namespace xmltooling::logging;
43 using namespace xmltooling;
46 // OpenSSL password callback...
47 static int passwd_callback(char* buf, int len, int verify, void* passwd)
51 if(passwd && len > strlen(reinterpret_cast<char*>(passwd)))
53 strcpy(buf,reinterpret_cast<char*>(passwd));
60 const char* SecurityHelper::guessEncodingFormat(const char* pathname)
62 const char* format=nullptr;
63 BIO* in=BIO_new(BIO_s_file_internal());
64 if (in && BIO_read_filename(in, pathname)>0) {
65 const int READSIZE = 1;
69 // Examine the first byte.
71 if ((mark = BIO_tell(in)) < 0)
72 throw XMLSecurityException("Error loading file: BIO_tell() can't get the file position.");
73 if (BIO_read(in, buf, READSIZE) <= 0)
74 throw XMLSecurityException("Error loading file: BIO_read() can't read from the stream.");
75 if (BIO_seek(in, mark) < 0)
76 throw XMLSecurityException("Error loading file: BIO_seek() can't reset the file position.");
84 // Check the first byte of the file. If it's some kind of DER-encoded structure
85 // (including PKCS12), it will begin with ASCII 048. Otherwise, assume it's PEM.
90 // Here we know it's DER-encoded, now try to parse it as a PKCS12 ASN.1 structure.
91 // If it fails, must be another kind of DER-encoded structure.
93 if ((p12=d2i_PKCS12_bio(in, nullptr)) == nullptr) {
106 throw XMLSecurityException("Unable to determine encoding for file ($1).", params(1,pathname));
109 XSECCryptoKey* SecurityHelper::loadKeyFromFile(const char* pathname, const char* format, const char* password)
112 NDC ndc("loadKeyFromFile");
114 Category& log = Category::getInstance(XMLTOOLING_LOGCAT".SecurityHelper");
115 log.info("loading private key from file (%s)", pathname);
119 EVP_PKEY* pkey=nullptr;
121 BIO* in=BIO_new(BIO_s_file_internal());
122 if (in && BIO_read_filename(in, pathname)>0) {
123 // If the format isn't set, try and guess it.
124 if (!format || !*format) {
125 const int READSIZE = 1;
129 // Examine the first byte.
131 if ((mark = BIO_tell(in)) < 0)
132 throw XMLSecurityException("Error loading key: BIO_tell() can't get the file position.");
133 if (BIO_read(in, buf, READSIZE) <= 0)
134 throw XMLSecurityException("Error loading key: BIO_read() can't read from the stream.");
135 if (BIO_seek(in, mark) < 0)
136 throw XMLSecurityException("Error loading key: BIO_seek() can't reset the file position.");
144 // Check the first byte of the file. If it's some kind of DER-encoded structure
145 // (including PKCS12), it will begin with ASCII 048. Otherwise, assume it's PEM.
150 // Here we know it's DER-encoded, now try to parse it as a PKCS12 ASN.1 structure.
151 // If it fails, must be another kind of DER-encoded structure.
152 if ((p12=d2i_PKCS12_bio(in, nullptr)) == nullptr) {
154 if (BIO_seek(in, mark) < 0) {
157 throw XMLSecurityException("Error loading key: BIO_seek() can't reset the file position.");
164 log.debug("key encoding format for (%s) dynamically resolved as (%s)", pathname, format);
167 // The format should be known, so parse accordingly.
168 if (!strcmp(format, "PEM")) {
169 pkey = PEM_read_bio_PrivateKey(in, nullptr, passwd_callback, const_cast<char*>(password));
171 else if (!strcmp(format, "DER")) {
172 pkey=d2i_PrivateKey_bio(in, nullptr);
174 else if (!strcmp(format, "PKCS12")) {
176 p12 = d2i_PKCS12_bio(in, nullptr);
179 PKCS12_parse(p12, const_cast<char*>(password), &pkey, &x, nullptr);
185 log.error("unknown key encoding format (%s)", format);
191 // Now map it to an XSEC wrapper.
193 XSECCryptoKey* ret=nullptr;
194 switch (pkey->type) {
196 ret=new OpenSSLCryptoKeyRSA(pkey);
200 ret=new OpenSSLCryptoKeyDSA(pkey);
204 log.error("unsupported private key type");
212 throw XMLSecurityException("Unable to load private key from file ($1).", params(1, pathname));
215 vector<XSECCryptoX509*>::size_type SecurityHelper::loadCertificatesFromFile(
216 vector<XSECCryptoX509*>& certs, const char* pathname, const char* format, const char* password
220 NDC ndc("loadCertificatesFromFile");
222 Category& log = Category::getInstance(XMLTOOLING_LOGCAT".SecurityHelper");
223 log.info("loading certificate(s) from file (%s)", pathname);
225 vector<XSECCryptoX509*>::size_type count = certs.size();
231 BIO* in=BIO_new(BIO_s_file_internal());
232 if (in && BIO_read_filename(in, pathname)>0) {
233 // If the format isn't set, try and guess it.
234 if (!format || !*format) {
235 const int READSIZE = 1;
239 // Examine the first byte.
241 if ((mark = BIO_tell(in)) < 0)
242 throw XMLSecurityException("Error loading certificate: BIO_tell() can't get the file position.");
243 if (BIO_read(in, buf, READSIZE) <= 0)
244 throw XMLSecurityException("Error loading certificate: BIO_read() can't read from the stream.");
245 if (BIO_seek(in, mark) < 0)
246 throw XMLSecurityException("Error loading certificate: BIO_seek() can't reset the file position.");
254 // Check the first byte of the file. If it's some kind of DER-encoded structure
255 // (including PKCS12), it will begin with ASCII 048. Otherwise, assume it's PEM.
260 // Here we know it's DER-encoded, now try to parse it as a PKCS12 ASN.1 structure.
261 // If it fails, must be another kind of DER-encoded structure.
262 if ((p12=d2i_PKCS12_bio(in, nullptr)) == nullptr) {
264 if (BIO_seek(in, mark) < 0) {
267 throw XMLSecurityException("Error loading certificate: BIO_seek() can't reset the file position.");
276 // The format should be known, so parse accordingly.
277 if (!strcmp(format, "PEM")) {
278 while (x=PEM_read_bio_X509(in, nullptr, nullptr, nullptr)) {
279 certs.push_back(new OpenSSLCryptoX509(x));
283 else if (!strcmp(format, "DER")) {
284 x=d2i_X509_bio(in, nullptr);
286 certs.push_back(new OpenSSLCryptoX509(x));
290 else if (!strcmp(format, "PKCS12")) {
292 p12 = d2i_PKCS12_bio(in, nullptr);
294 EVP_PKEY* pkey=nullptr;
295 STACK_OF(X509)* CAstack = sk_X509_new_null();
296 PKCS12_parse(p12, const_cast<char*>(password), &pkey, &x, &CAstack);
300 certs.push_back(new OpenSSLCryptoX509(x));
303 x = sk_X509_pop(CAstack);
305 certs.push_back(new OpenSSLCryptoX509(x));
307 x = sk_X509_pop(CAstack);
309 sk_X509_free(CAstack);
316 if (certs.size() == count) {
318 throw XMLSecurityException("Unable to load certificate(s) from file ($1).", params(1, pathname));
324 vector<XSECCryptoX509CRL*>::size_type SecurityHelper::loadCRLsFromFile(
325 vector<XSECCryptoX509CRL*>& crls, const char* pathname, const char* format
329 NDC ndc("loadCRLsFromFile");
331 Category& log = Category::getInstance(XMLTOOLING_LOGCAT".SecurityHelper");
332 log.info("loading CRL(s) from file (%s)", pathname);
334 vector<XSECCryptoX509CRL*>::size_type count = crls.size();
336 BIO* in=BIO_new(BIO_s_file_internal());
337 if (in && BIO_read_filename(in, pathname)>0) {
338 // If the format isn't set, try and guess it.
339 if (!format || !*format) {
340 const int READSIZE = 1;
344 // Examine the first byte.
346 if ((mark = BIO_tell(in)) < 0)
347 throw XMLSecurityException("Error loading CRL: BIO_tell() can't get the file position.");
348 if (BIO_read(in, buf, READSIZE) <= 0)
349 throw XMLSecurityException("Error loading CRL: BIO_read() can't read from the stream.");
350 if (BIO_seek(in, mark) < 0)
351 throw XMLSecurityException("Error loading CRL: BIO_seek() can't reset the file position.");
359 // Check the first byte of the file. If it's some kind of DER-encoded structure
360 // it will begin with ASCII 048. Otherwise, assume it's PEM.
367 log.debug("CRL encoding format for (%s) dynamically resolved as (%s)", pathname, format);
370 X509_CRL* crl=nullptr;
371 if (!strcmp(format, "PEM")) {
372 while (crl=PEM_read_bio_X509_CRL(in, nullptr, nullptr, nullptr)) {
373 crls.push_back(new OpenSSLCryptoX509CRL(crl));
377 else if (!strcmp(format, "DER")) {
378 crl=d2i_X509_CRL_bio(in, nullptr);
380 crls.push_back(new OpenSSLCryptoX509CRL(crl));
385 log.error("unknown CRL encoding format (%s)", format);
391 if (crls.size() == count) {
393 throw XMLSecurityException("Unable to load CRL(s) from file ($1).", params(1, pathname));
399 XSECCryptoKey* SecurityHelper::loadKeyFromURL(SOAPTransport& transport, const char* backing, const char* format, const char* password)
403 istream& msg = transport.receive();
405 // Check for "not modified" status.
406 if (dynamic_cast<HTTPSOAPTransport*>(&transport) && transport.getStatusCode() == HTTPResponse::XMLTOOLING_HTTP_STATUS_NOTMODIFIED)
407 throw (long)HTTPResponse::XMLTOOLING_HTTP_STATUS_NOTMODIFIED;
409 // Dump to output file.
410 ofstream out(backing, fstream::trunc|fstream::binary);
414 return loadKeyFromFile(backing, format, password);
417 vector<XSECCryptoX509*>::size_type SecurityHelper::loadCertificatesFromURL(
418 vector<XSECCryptoX509*>& certs, SOAPTransport& transport, const char* backing, const char* format, const char* password
422 istream& msg = transport.receive();
424 // Check for "not modified" status.
425 if (dynamic_cast<HTTPSOAPTransport*>(&transport) && transport.getStatusCode() == HTTPResponse::XMLTOOLING_HTTP_STATUS_NOTMODIFIED)
426 throw (long)HTTPResponse::XMLTOOLING_HTTP_STATUS_NOTMODIFIED;
428 // Dump to output file.
429 ofstream out(backing, fstream::trunc|fstream::binary);
433 return loadCertificatesFromFile(certs, backing, format, password);
436 vector<XSECCryptoX509CRL*>::size_type SecurityHelper::loadCRLsFromURL(
437 vector<XSECCryptoX509CRL*>& crls, SOAPTransport& transport, const char* backing, const char* format
442 istream& msg = transport.receive();
444 // Check for "not modified" status.
445 if (dynamic_cast<HTTPSOAPTransport*>(&transport) && transport.getStatusCode() == HTTPResponse::XMLTOOLING_HTTP_STATUS_NOTMODIFIED)
446 throw (long)HTTPResponse::XMLTOOLING_HTTP_STATUS_NOTMODIFIED;
448 // Dump to output file.
449 ofstream out(backing, fstream::trunc|fstream::binary);
453 return loadCRLsFromFile(crls, backing, format);
456 bool SecurityHelper::matches(const XSECCryptoKey& key1, const XSECCryptoKey& key2)
458 if (key1.getProviderName()!=DSIGConstants::s_unicodeStrPROVOpenSSL ||
459 key2.getProviderName()!=DSIGConstants::s_unicodeStrPROVOpenSSL) {
460 Category::getInstance(XMLTOOLING_LOGCAT".SecurityHelper").warn("comparison of non-OpenSSL keys not supported");
464 // If one key is public or both, just compare the public key half.
465 if (key1.getKeyType()==XSECCryptoKey::KEY_RSA_PUBLIC || key1.getKeyType()==XSECCryptoKey::KEY_RSA_PAIR) {
466 if (key2.getKeyType()!=XSECCryptoKey::KEY_RSA_PUBLIC && key2.getKeyType()!=XSECCryptoKey::KEY_RSA_PAIR)
468 const RSA* rsa1 = static_cast<const OpenSSLCryptoKeyRSA&>(key1).getOpenSSLRSA();
469 const RSA* rsa2 = static_cast<const OpenSSLCryptoKeyRSA&>(key2).getOpenSSLRSA();
470 return (rsa1 && rsa2 && BN_cmp(rsa1->n,rsa2->n) == 0 && BN_cmp(rsa1->e,rsa2->e) == 0);
473 // For a private key, compare the private half.
474 if (key1.getKeyType()==XSECCryptoKey::KEY_RSA_PRIVATE) {
475 if (key2.getKeyType()!=XSECCryptoKey::KEY_RSA_PRIVATE && key2.getKeyType()!=XSECCryptoKey::KEY_RSA_PAIR)
477 const RSA* rsa1 = static_cast<const OpenSSLCryptoKeyRSA&>(key1).getOpenSSLRSA();
478 const RSA* rsa2 = static_cast<const OpenSSLCryptoKeyRSA&>(key2).getOpenSSLRSA();
479 return (rsa1 && rsa2 && BN_cmp(rsa1->n,rsa2->n) == 0 && BN_cmp(rsa1->d,rsa2->d) == 0);
482 // If one key is public or both, just compare the public key half.
483 if (key1.getKeyType()==XSECCryptoKey::KEY_DSA_PUBLIC || key1.getKeyType()==XSECCryptoKey::KEY_DSA_PAIR) {
484 if (key2.getKeyType()!=XSECCryptoKey::KEY_DSA_PUBLIC && key2.getKeyType()!=XSECCryptoKey::KEY_DSA_PAIR)
486 const DSA* dsa1 = static_cast<const OpenSSLCryptoKeyDSA&>(key1).getOpenSSLDSA();
487 const DSA* dsa2 = static_cast<const OpenSSLCryptoKeyDSA&>(key2).getOpenSSLDSA();
488 return (dsa1 && dsa2 && BN_cmp(dsa1->pub_key,dsa2->pub_key) == 0);
491 // For a private key, compare the private half.
492 if (key1.getKeyType()==XSECCryptoKey::KEY_DSA_PRIVATE) {
493 if (key2.getKeyType()!=XSECCryptoKey::KEY_DSA_PRIVATE && key2.getKeyType()!=XSECCryptoKey::KEY_DSA_PAIR)
495 const DSA* dsa1 = static_cast<const OpenSSLCryptoKeyDSA&>(key1).getOpenSSLDSA();
496 const DSA* dsa2 = static_cast<const OpenSSLCryptoKeyDSA&>(key2).getOpenSSLDSA();
497 return (dsa1 && dsa2 && BN_cmp(dsa1->priv_key,dsa2->priv_key) == 0);
500 Category::getInstance(XMLTOOLING_LOGCAT".SecurityHelper").warn("unsupported key type for comparison");
504 string SecurityHelper::doHash(const char* hashAlg, const char* buf, unsigned long buflen, bool toHex)
506 static char DIGITS[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
509 const EVP_MD* md = EVP_get_digestbyname(hashAlg);
511 Category::getInstance(XMLTOOLING_LOGCAT".SecurityHelper").error("hash algorithm (%s) not available", hashAlg);
515 BIO* chain = BIO_new(BIO_s_mem());
516 BIO* b = BIO_new(BIO_f_md());
518 chain = BIO_push(b, chain);
519 BIO_write(chain, buf, buflen);
522 char digest[EVP_MAX_MD_SIZE];
523 int len = BIO_gets(chain, digest, EVP_MD_size(md));
525 if (len != EVP_MD_size(md)) {
526 Category::getInstance(XMLTOOLING_LOGCAT".SecurityHelper").error(
527 "hash result length (%d) did not match expected value (%d)", len, EVP_MD_size(md)
532 for (int i=0; i < len; ++i) {
533 ret += (DIGITS[((unsigned char)(0xF0 & digest[i])) >> 4 ]);
534 ret += (DIGITS[0x0F & digest[i]]);
538 for (int i=0; i < len; ++i) {
545 string SecurityHelper::getDEREncoding(const XSECCryptoKey& key, const char* hash, bool nowrap)
549 if (key.getProviderName()!=DSIGConstants::s_unicodeStrPROVOpenSSL) {
550 Category::getInstance(XMLTOOLING_LOGCAT".SecurityHelper").warn("encoding of non-OpenSSL keys not supported");
554 if (key.getKeyType() == XSECCryptoKey::KEY_RSA_PUBLIC || key.getKeyType() == XSECCryptoKey::KEY_RSA_PAIR) {
555 const RSA* rsa = static_cast<const OpenSSLCryptoKeyRSA&>(key).getOpenSSLRSA();
557 Category::getInstance(XMLTOOLING_LOGCAT".SecurityHelper").warn("key was not populated");
560 const EVP_MD* md=nullptr;
562 md = EVP_get_digestbyname(hash);
564 Category::getInstance(XMLTOOLING_LOGCAT".SecurityHelper").error("hash algorithm (%s) not available", hash);
568 BIO* chain = BIO_new(BIO_s_mem());
569 BIO* b = BIO_new(BIO_f_base64());
571 BIO_set_flags(b, BIO_FLAGS_BASE64_NO_NL);
572 chain = BIO_push(b, chain);
574 b = BIO_new(BIO_f_md());
576 chain = BIO_push(b, chain);
578 i2d_RSA_PUBKEY_bio(chain, const_cast<RSA*>(rsa));
581 char digest[EVP_MAX_MD_SIZE];
582 int len = BIO_gets(chain, digest, EVP_MD_size(md));
583 if (len != EVP_MD_size(md)) {
591 BIO_write(chain, digest, len);
594 BUF_MEM* bptr=nullptr;
595 BIO_get_mem_ptr(chain, &bptr);
596 if (bptr && bptr->length > 0)
597 ret.append(bptr->data, bptr->length);
600 else if (key.getKeyType() == XSECCryptoKey::KEY_DSA_PUBLIC || key.getKeyType() == XSECCryptoKey::KEY_DSA_PAIR) {
601 const DSA* dsa = static_cast<const OpenSSLCryptoKeyDSA&>(key).getOpenSSLDSA();
603 Category::getInstance(XMLTOOLING_LOGCAT".SecurityHelper").warn("key was not populated");
606 const EVP_MD* md=nullptr;
608 md = EVP_get_digestbyname(hash);
610 Category::getInstance(XMLTOOLING_LOGCAT".SecurityHelper").error("hash algorithm (%s) not available", hash);
614 BIO* chain = BIO_new(BIO_s_mem());
615 BIO* b = BIO_new(BIO_f_base64());
617 BIO_set_flags(b, BIO_FLAGS_BASE64_NO_NL);
618 chain = BIO_push(b, chain);
620 b = BIO_new(BIO_f_md());
622 chain = BIO_push(b, chain);
624 i2d_DSA_PUBKEY_bio(chain, const_cast<DSA*>(dsa));
627 char digest[EVP_MAX_MD_SIZE];
628 int len = BIO_gets(chain, digest, EVP_MD_size(md));
629 if (len != EVP_MD_size(md)) {
637 BIO_write(chain, digest, len);
640 BUF_MEM* bptr=nullptr;
641 BIO_get_mem_ptr(chain, &bptr);
642 if (bptr && bptr->length > 0)
643 ret.append(bptr->data, bptr->length);
647 Category::getInstance(XMLTOOLING_LOGCAT".SecurityHelper").warn("encoding of non-RSA/DSA public keys not supported");
652 string SecurityHelper::getDEREncoding(const XSECCryptoX509& cert, const char* hash, bool nowrap)
656 if (cert.getProviderName()!=DSIGConstants::s_unicodeStrPROVOpenSSL) {
657 Category::getInstance(XMLTOOLING_LOGCAT".SecurityHelper").warn("encoding of non-OpenSSL keys not supported");
661 const EVP_MD* md=nullptr;
663 md = EVP_get_digestbyname(hash);
665 Category::getInstance(XMLTOOLING_LOGCAT".SecurityHelper").error("hash algorithm (%s) not available", hash);
670 const X509* x = static_cast<const OpenSSLCryptoX509&>(cert).getOpenSSLX509();
671 EVP_PKEY* key = X509_get_pubkey(const_cast<X509*>(x));
673 BIO* chain = BIO_new(BIO_s_mem());
674 BIO* b = BIO_new(BIO_f_base64());
676 BIO_set_flags(b, BIO_FLAGS_BASE64_NO_NL);
677 chain = BIO_push(b, chain);
679 b = BIO_new(BIO_f_md());
681 chain = BIO_push(b, chain);
683 i2d_PUBKEY_bio(chain, key);
687 char digest[EVP_MAX_MD_SIZE];
688 int len = BIO_gets(chain, digest, EVP_MD_size(md));
689 if (len != EVP_MD_size(md)) {
697 BIO_write(chain, digest, len);
700 BUF_MEM* bptr=nullptr;
701 BIO_get_mem_ptr(chain, &bptr);
702 if (bptr && bptr->length > 0)
703 ret.append(bptr->data, bptr->length);
708 string SecurityHelper::getDEREncoding(const Credential& cred, const char* hash, bool nowrap)
710 const X509Credential* x509 = dynamic_cast<const X509Credential*>(&cred);
711 if (x509 && !x509->getEntityCertificateChain().empty())
712 return getDEREncoding(*(x509->getEntityCertificateChain().front()), hash, nowrap);
713 else if (cred.getPublicKey())
714 return getDEREncoding(*(cred.getPublicKey()), hash, nowrap);
718 string SecurityHelper::getDEREncoding(const XSECCryptoKey& key, bool hash, bool nowrap)
720 return getDEREncoding(key, hash ? "SHA1" : nullptr, nowrap);
723 string SecurityHelper::getDEREncoding(const XSECCryptoX509& cert, bool hash, bool nowrap)
725 return getDEREncoding(cert, hash ? "SHA1" : nullptr, nowrap);
728 string SecurityHelper::getDEREncoding(const Credential& cred, bool hash, bool nowrap)
730 return getDEREncoding(cred, hash ? "SHA1" : nullptr, nowrap);
733 XSECCryptoKey* SecurityHelper::fromDEREncoding(const char* buf, unsigned long buflen, bool base64)
736 XMLByte* decoded=nullptr;
738 decoded = xercesc::Base64::decode(reinterpret_cast<const XMLByte*>(buf), &x);
740 Category::getInstance(XMLTOOLING_LOGCAT".SecurityHelper").error("base64 decode failed");
745 BIO* b = BIO_new_mem_buf((void*)(base64 ? (char*)decoded : buf), (base64 ? x : buflen));
746 EVP_PKEY* pkey = d2i_PUBKEY_bio(b, nullptr);
749 #ifdef XMLTOOLING_XERCESC_HAS_XMLBYTE_RELEASE
750 XMLString::release(&decoded);
752 XMLString::release((char**)&decoded);
757 // Now map it to an XSEC wrapper.
758 XSECCryptoKey* ret = nullptr;
760 switch (pkey->type) {
762 ret = new OpenSSLCryptoKeyRSA(pkey);
766 ret = new OpenSSLCryptoKeyDSA(pkey);
770 Category::getInstance(XMLTOOLING_LOGCAT".SecurityHelper").error("unsupported public key type");
773 catch (XSECCryptoException& ex) {
774 Category::getInstance(XMLTOOLING_LOGCAT".SecurityHelper").error(ex.getMsg());
783 XSECCryptoKey* SecurityHelper::fromDEREncoding(const XMLCh* buf)
786 XMLByte* decoded = xercesc::Base64::decodeToXMLByte(buf, &x);
788 Category::getInstance(XMLTOOLING_LOGCAT".SecurityHelper").error("base64 decode failed");
791 XSECCryptoKey* ret = fromDEREncoding((const char*)decoded, x, false);
792 #ifdef XMLTOOLING_XERCESC_HAS_XMLBYTE_RELEASE
793 XMLString::release(&decoded);
795 XMLString::release((char**)&decoded);