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>
43 # if (OPENSSL_VERSION_NUMBER >= 0x00907000)
44 # define XMLTOOLING_OPENSSL_HAVE_EC 1
48 #if defined(XMLTOOLING_XMLSEC_ECC) && defined(XMLTOOLING_OPENSSL_HAVE_EC)
49 # include <xsec/enc/OpenSSL/OpenSSLCryptoKeyEC.hpp>
52 using namespace xmltooling::logging;
53 using namespace xmltooling;
56 // OpenSSL password callback...
57 static int passwd_callback(char* buf, int len, int verify, void* passwd)
61 if(passwd && len > strlen(reinterpret_cast<char*>(passwd)))
63 strcpy(buf,reinterpret_cast<char*>(passwd));
70 const char* SecurityHelper::guessEncodingFormat(const char* pathname)
72 const char* format=nullptr;
73 BIO* in=BIO_new(BIO_s_file_internal());
74 if (in && BIO_read_filename(in, pathname)>0) {
75 const int READSIZE = 1;
79 // Examine the first byte.
81 if ((mark = BIO_tell(in)) < 0)
82 throw XMLSecurityException("Error loading file: BIO_tell() can't get the file position.");
83 if (BIO_read(in, buf, READSIZE) <= 0)
84 throw XMLSecurityException("Error loading file: BIO_read() can't read from the stream.");
85 if (BIO_seek(in, mark) < 0)
86 throw XMLSecurityException("Error loading file: BIO_seek() can't reset the file position.");
94 // Check the first byte of the file. If it's some kind of DER-encoded structure
95 // (including PKCS12), it will begin with ASCII 048. Otherwise, assume it's PEM.
100 // Here we know it's DER-encoded, now try to parse it as a PKCS12 ASN.1 structure.
101 // If it fails, must be another kind of DER-encoded structure.
103 if ((p12=d2i_PKCS12_bio(in, nullptr)) == nullptr) {
116 throw XMLSecurityException("Unable to determine encoding for file ($1).", params(1,pathname));
119 XSECCryptoKey* SecurityHelper::loadKeyFromFile(const char* pathname, const char* format, const char* password)
122 NDC ndc("loadKeyFromFile");
124 Category& log = Category::getInstance(XMLTOOLING_LOGCAT".SecurityHelper");
125 log.info("loading private key from file (%s)", pathname);
129 EVP_PKEY* pkey=nullptr;
131 BIO* in=BIO_new(BIO_s_file_internal());
132 if (in && BIO_read_filename(in, pathname)>0) {
133 // If the format isn't set, try and guess it.
134 if (!format || !*format) {
135 const int READSIZE = 1;
139 // Examine the first byte.
141 if ((mark = BIO_tell(in)) < 0)
142 throw XMLSecurityException("Error loading key: BIO_tell() can't get the file position.");
143 if (BIO_read(in, buf, READSIZE) <= 0)
144 throw XMLSecurityException("Error loading key: BIO_read() can't read from the stream.");
145 if (BIO_seek(in, mark) < 0)
146 throw XMLSecurityException("Error loading key: BIO_seek() can't reset the file position.");
154 // Check the first byte of the file. If it's some kind of DER-encoded structure
155 // (including PKCS12), it will begin with ASCII 048. Otherwise, assume it's PEM.
160 // Here we know it's DER-encoded, now try to parse it as a PKCS12 ASN.1 structure.
161 // If it fails, must be another kind of DER-encoded structure.
162 if ((p12=d2i_PKCS12_bio(in, nullptr)) == nullptr) {
164 if (BIO_seek(in, mark) < 0) {
167 throw XMLSecurityException("Error loading key: BIO_seek() can't reset the file position.");
174 log.debug("key encoding format for (%s) dynamically resolved as (%s)", pathname, format);
177 // The format should be known, so parse accordingly.
178 if (!strcmp(format, "PEM")) {
179 pkey = PEM_read_bio_PrivateKey(in, nullptr, passwd_callback, const_cast<char*>(password));
181 else if (!strcmp(format, "DER")) {
182 pkey=d2i_PrivateKey_bio(in, nullptr);
184 else if (!strcmp(format, "PKCS12")) {
186 p12 = d2i_PKCS12_bio(in, nullptr);
189 PKCS12_parse(p12, const_cast<char*>(password), &pkey, &x, nullptr);
195 log.error("unknown key encoding format (%s)", format);
201 // Now map it to an XSEC wrapper.
203 XSECCryptoKey* ret=nullptr;
204 switch (pkey->type) {
206 ret=new OpenSSLCryptoKeyRSA(pkey);
210 ret=new OpenSSLCryptoKeyDSA(pkey);
213 #if defined(XMLTOOLING_XMLSEC_ECC) && defined(XMLTOOLING_OPENSSL_HAVE_EC)
215 ret=new OpenSSLCryptoKeyEC(pkey);
219 log.error("unsupported private key type");
227 throw XMLSecurityException("Unable to load private key from file ($1).", params(1, pathname));
230 vector<XSECCryptoX509*>::size_type SecurityHelper::loadCertificatesFromFile(
231 vector<XSECCryptoX509*>& certs, const char* pathname, const char* format, const char* password
235 NDC ndc("loadCertificatesFromFile");
237 Category& log = Category::getInstance(XMLTOOLING_LOGCAT".SecurityHelper");
238 log.info("loading certificate(s) from file (%s)", pathname);
240 vector<XSECCryptoX509*>::size_type count = certs.size();
246 BIO* in=BIO_new(BIO_s_file_internal());
247 if (in && BIO_read_filename(in, pathname)>0) {
248 // If the format isn't set, try and guess it.
249 if (!format || !*format) {
250 const int READSIZE = 1;
254 // Examine the first byte.
256 if ((mark = BIO_tell(in)) < 0)
257 throw XMLSecurityException("Error loading certificate: BIO_tell() can't get the file position.");
258 if (BIO_read(in, buf, READSIZE) <= 0)
259 throw XMLSecurityException("Error loading certificate: BIO_read() can't read from the stream.");
260 if (BIO_seek(in, mark) < 0)
261 throw XMLSecurityException("Error loading certificate: BIO_seek() can't reset the file position.");
269 // Check the first byte of the file. If it's some kind of DER-encoded structure
270 // (including PKCS12), it will begin with ASCII 048. Otherwise, assume it's PEM.
275 // Here we know it's DER-encoded, now try to parse it as a PKCS12 ASN.1 structure.
276 // If it fails, must be another kind of DER-encoded structure.
277 if ((p12=d2i_PKCS12_bio(in, nullptr)) == nullptr) {
279 if (BIO_seek(in, mark) < 0) {
282 throw XMLSecurityException("Error loading certificate: BIO_seek() can't reset the file position.");
291 // The format should be known, so parse accordingly.
292 if (!strcmp(format, "PEM")) {
293 while (x=PEM_read_bio_X509(in, nullptr, nullptr, nullptr)) {
294 certs.push_back(new OpenSSLCryptoX509(x));
298 else if (!strcmp(format, "DER")) {
299 x=d2i_X509_bio(in, nullptr);
301 certs.push_back(new OpenSSLCryptoX509(x));
305 else if (!strcmp(format, "PKCS12")) {
307 p12 = d2i_PKCS12_bio(in, nullptr);
309 EVP_PKEY* pkey=nullptr;
310 STACK_OF(X509)* CAstack = sk_X509_new_null();
311 PKCS12_parse(p12, const_cast<char*>(password), &pkey, &x, &CAstack);
315 certs.push_back(new OpenSSLCryptoX509(x));
318 x = sk_X509_pop(CAstack);
320 certs.push_back(new OpenSSLCryptoX509(x));
322 x = sk_X509_pop(CAstack);
324 sk_X509_free(CAstack);
331 if (certs.size() == count) {
333 throw XMLSecurityException("Unable to load certificate(s) from file ($1).", params(1, pathname));
339 vector<XSECCryptoX509CRL*>::size_type SecurityHelper::loadCRLsFromFile(
340 vector<XSECCryptoX509CRL*>& crls, const char* pathname, const char* format
344 NDC ndc("loadCRLsFromFile");
346 Category& log = Category::getInstance(XMLTOOLING_LOGCAT".SecurityHelper");
347 log.info("loading CRL(s) from file (%s)", pathname);
349 vector<XSECCryptoX509CRL*>::size_type count = crls.size();
351 BIO* in=BIO_new(BIO_s_file_internal());
352 if (in && BIO_read_filename(in, pathname)>0) {
353 // If the format isn't set, try and guess it.
354 if (!format || !*format) {
355 const int READSIZE = 1;
359 // Examine the first byte.
361 if ((mark = BIO_tell(in)) < 0)
362 throw XMLSecurityException("Error loading CRL: BIO_tell() can't get the file position.");
363 if (BIO_read(in, buf, READSIZE) <= 0)
364 throw XMLSecurityException("Error loading CRL: BIO_read() can't read from the stream.");
365 if (BIO_seek(in, mark) < 0)
366 throw XMLSecurityException("Error loading CRL: BIO_seek() can't reset the file position.");
374 // Check the first byte of the file. If it's some kind of DER-encoded structure
375 // it will begin with ASCII 048. Otherwise, assume it's PEM.
382 log.debug("CRL encoding format for (%s) dynamically resolved as (%s)", pathname, format);
385 X509_CRL* crl=nullptr;
386 if (!strcmp(format, "PEM")) {
387 while (crl=PEM_read_bio_X509_CRL(in, nullptr, nullptr, nullptr)) {
388 crls.push_back(new OpenSSLCryptoX509CRL(crl));
392 else if (!strcmp(format, "DER")) {
393 crl=d2i_X509_CRL_bio(in, nullptr);
395 crls.push_back(new OpenSSLCryptoX509CRL(crl));
400 log.error("unknown CRL encoding format (%s)", format);
406 if (crls.size() == count) {
408 throw XMLSecurityException("Unable to load CRL(s) from file ($1).", params(1, pathname));
414 XSECCryptoKey* SecurityHelper::loadKeyFromURL(SOAPTransport& transport, const char* backing, const char* format, const char* password)
418 istream& msg = transport.receive();
420 // Check for "not modified" status.
421 if (dynamic_cast<HTTPSOAPTransport*>(&transport) && transport.getStatusCode() == HTTPResponse::XMLTOOLING_HTTP_STATUS_NOTMODIFIED)
422 throw (long)HTTPResponse::XMLTOOLING_HTTP_STATUS_NOTMODIFIED;
424 // Dump to output file.
425 ofstream out(backing, fstream::trunc|fstream::binary);
429 return loadKeyFromFile(backing, format, password);
432 vector<XSECCryptoX509*>::size_type SecurityHelper::loadCertificatesFromURL(
433 vector<XSECCryptoX509*>& certs, SOAPTransport& transport, const char* backing, const char* format, const char* password
437 istream& msg = transport.receive();
439 // Check for "not modified" status.
440 if (dynamic_cast<HTTPSOAPTransport*>(&transport) && transport.getStatusCode() == HTTPResponse::XMLTOOLING_HTTP_STATUS_NOTMODIFIED)
441 throw (long)HTTPResponse::XMLTOOLING_HTTP_STATUS_NOTMODIFIED;
443 // Dump to output file.
444 ofstream out(backing, fstream::trunc|fstream::binary);
448 return loadCertificatesFromFile(certs, backing, format, password);
451 vector<XSECCryptoX509CRL*>::size_type SecurityHelper::loadCRLsFromURL(
452 vector<XSECCryptoX509CRL*>& crls, SOAPTransport& transport, const char* backing, const char* format
457 istream& msg = transport.receive();
459 // Check for "not modified" status.
460 if (dynamic_cast<HTTPSOAPTransport*>(&transport) && transport.getStatusCode() == HTTPResponse::XMLTOOLING_HTTP_STATUS_NOTMODIFIED)
461 throw (long)HTTPResponse::XMLTOOLING_HTTP_STATUS_NOTMODIFIED;
463 // Dump to output file.
464 ofstream out(backing, fstream::trunc|fstream::binary);
468 return loadCRLsFromFile(crls, backing, format);
471 bool SecurityHelper::matches(const XSECCryptoKey& key1, const XSECCryptoKey& key2)
473 if (key1.getProviderName()!=DSIGConstants::s_unicodeStrPROVOpenSSL ||
474 key2.getProviderName()!=DSIGConstants::s_unicodeStrPROVOpenSSL) {
475 Category::getInstance(XMLTOOLING_LOGCAT".SecurityHelper").warn("comparison of non-OpenSSL keys not supported");
479 // If one key is public or both, just compare the public key half.
480 if (key1.getKeyType()==XSECCryptoKey::KEY_RSA_PUBLIC || key1.getKeyType()==XSECCryptoKey::KEY_RSA_PAIR) {
481 if (key2.getKeyType()!=XSECCryptoKey::KEY_RSA_PUBLIC && key2.getKeyType()!=XSECCryptoKey::KEY_RSA_PAIR)
483 const RSA* rsa1 = static_cast<const OpenSSLCryptoKeyRSA&>(key1).getOpenSSLRSA();
484 const RSA* rsa2 = static_cast<const OpenSSLCryptoKeyRSA&>(key2).getOpenSSLRSA();
485 return (rsa1 && rsa2 && BN_cmp(rsa1->n,rsa2->n) == 0 && BN_cmp(rsa1->e,rsa2->e) == 0);
488 // For a private key, compare the private half.
489 if (key1.getKeyType()==XSECCryptoKey::KEY_RSA_PRIVATE) {
490 if (key2.getKeyType()!=XSECCryptoKey::KEY_RSA_PRIVATE && key2.getKeyType()!=XSECCryptoKey::KEY_RSA_PAIR)
492 const RSA* rsa1 = static_cast<const OpenSSLCryptoKeyRSA&>(key1).getOpenSSLRSA();
493 const RSA* rsa2 = static_cast<const OpenSSLCryptoKeyRSA&>(key2).getOpenSSLRSA();
494 return (rsa1 && rsa2 && BN_cmp(rsa1->n,rsa2->n) == 0 && BN_cmp(rsa1->d,rsa2->d) == 0);
497 // If one key is public or both, just compare the public key half.
498 if (key1.getKeyType()==XSECCryptoKey::KEY_DSA_PUBLIC || key1.getKeyType()==XSECCryptoKey::KEY_DSA_PAIR) {
499 if (key2.getKeyType()!=XSECCryptoKey::KEY_DSA_PUBLIC && key2.getKeyType()!=XSECCryptoKey::KEY_DSA_PAIR)
501 const DSA* dsa1 = static_cast<const OpenSSLCryptoKeyDSA&>(key1).getOpenSSLDSA();
502 const DSA* dsa2 = static_cast<const OpenSSLCryptoKeyDSA&>(key2).getOpenSSLDSA();
503 return (dsa1 && dsa2 && BN_cmp(dsa1->pub_key,dsa2->pub_key) == 0);
506 // For a private key, compare the private half.
507 if (key1.getKeyType()==XSECCryptoKey::KEY_DSA_PRIVATE) {
508 if (key2.getKeyType()!=XSECCryptoKey::KEY_DSA_PRIVATE && key2.getKeyType()!=XSECCryptoKey::KEY_DSA_PAIR)
510 const DSA* dsa1 = static_cast<const OpenSSLCryptoKeyDSA&>(key1).getOpenSSLDSA();
511 const DSA* dsa2 = static_cast<const OpenSSLCryptoKeyDSA&>(key2).getOpenSSLDSA();
512 return (dsa1 && dsa2 && BN_cmp(dsa1->priv_key,dsa2->priv_key) == 0);
515 #if defined(XMLTOOLING_XMLSEC_ECC) && defined(XMLTOOLING_OPENSSL_HAVE_EC)
516 // If one key is public or both, just compare the public key half.
517 if (key1.getKeyType()==XSECCryptoKey::KEY_EC_PUBLIC || key1.getKeyType()==XSECCryptoKey::KEY_EC_PAIR) {
518 if (key2.getKeyType()!=XSECCryptoKey::KEY_EC_PUBLIC && key2.getKeyType()!=XSECCryptoKey::KEY_EC_PAIR)
520 const EC_KEY* ec1 = static_cast<const OpenSSLCryptoKeyEC&>(key1).getOpenSSLEC();
521 const EC_KEY* ec2 = static_cast<const OpenSSLCryptoKeyEC&>(key2).getOpenSSLEC();
524 if (EC_GROUP_cmp(EC_KEY_get0_group(ec1), EC_KEY_get0_group(ec2), nullptr) != 0)
526 return (EC_POINT_cmp(EC_KEY_get0_group(ec1), EC_KEY_get0_public_key(ec1), EC_KEY_get0_public_key(ec2), nullptr) == 0);
529 // For a private key, compare the private half.
530 if (key1.getKeyType()==XSECCryptoKey::KEY_EC_PRIVATE) {
531 if (key2.getKeyType()!=XSECCryptoKey::KEY_EC_PRIVATE && key2.getKeyType()!=XSECCryptoKey::KEY_EC_PAIR)
533 const EC_KEY* ec1 = static_cast<const OpenSSLCryptoKeyEC&>(key1).getOpenSSLEC();
534 const EC_KEY* ec2 = static_cast<const OpenSSLCryptoKeyEC&>(key2).getOpenSSLEC();
535 return (ec1 && ec2 && BN_cmp(EC_KEY_get0_private_key(ec1), EC_KEY_get0_private_key(ec2)) == 0);
539 Category::getInstance(XMLTOOLING_LOGCAT".SecurityHelper").warn("unsupported key type for comparison");
543 string SecurityHelper::doHash(const char* hashAlg, const char* buf, unsigned long buflen, bool toHex)
545 static char DIGITS[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
548 const EVP_MD* md = EVP_get_digestbyname(hashAlg);
550 Category::getInstance(XMLTOOLING_LOGCAT".SecurityHelper").error("hash algorithm (%s) not available", hashAlg);
554 BIO* chain = BIO_new(BIO_s_mem());
555 BIO* b = BIO_new(BIO_f_md());
557 chain = BIO_push(b, chain);
558 BIO_write(chain, buf, buflen);
561 char digest[EVP_MAX_MD_SIZE];
562 int len = BIO_gets(chain, digest, EVP_MD_size(md));
564 if (len != EVP_MD_size(md)) {
565 Category::getInstance(XMLTOOLING_LOGCAT".SecurityHelper").error(
566 "hash result length (%d) did not match expected value (%d)", len, EVP_MD_size(md)
571 for (int i=0; i < len; ++i) {
572 ret += (DIGITS[((unsigned char)(0xF0 & digest[i])) >> 4 ]);
573 ret += (DIGITS[0x0F & digest[i]]);
577 for (int i=0; i < len; ++i) {
584 string SecurityHelper::getDEREncoding(const XSECCryptoKey& key, const char* hash, bool nowrap)
588 if (key.getProviderName()!=DSIGConstants::s_unicodeStrPROVOpenSSL) {
589 Category::getInstance(XMLTOOLING_LOGCAT".SecurityHelper").warn("encoding of non-OpenSSL keys not supported");
593 const RSA* rsa = nullptr;
594 const DSA* dsa = nullptr;
595 #if defined(XMLTOOLING_XMLSEC_ECC) && defined(XMLTOOLING_OPENSSL_HAVE_EC)
596 const EC_KEY* ec = nullptr;
599 if (key.getKeyType() == XSECCryptoKey::KEY_RSA_PUBLIC || key.getKeyType() == XSECCryptoKey::KEY_RSA_PAIR) {
600 rsa = static_cast<const OpenSSLCryptoKeyRSA&>(key).getOpenSSLRSA();
602 Category::getInstance(XMLTOOLING_LOGCAT".SecurityHelper").warn("key was not populated");
606 else if (key.getKeyType() == XSECCryptoKey::KEY_DSA_PUBLIC || key.getKeyType() == XSECCryptoKey::KEY_DSA_PAIR) {
607 dsa = static_cast<const OpenSSLCryptoKeyDSA&>(key).getOpenSSLDSA();
609 Category::getInstance(XMLTOOLING_LOGCAT".SecurityHelper").warn("key was not populated");
613 #if defined(XMLTOOLING_XMLSEC_ECC) && defined(XMLTOOLING_OPENSSL_HAVE_EC)
614 else if (key.getKeyType() == XSECCryptoKey::KEY_EC_PUBLIC || key.getKeyType() == XSECCryptoKey::KEY_EC_PAIR) {
615 ec = static_cast<const OpenSSLCryptoKeyEC&>(key).getOpenSSLEC();
617 Category::getInstance(XMLTOOLING_LOGCAT".SecurityHelper").warn("key was not populated");
623 Category::getInstance(XMLTOOLING_LOGCAT".SecurityHelper").warn("public key type not supported");
627 const EVP_MD* md=nullptr;
629 md = EVP_get_digestbyname(hash);
631 Category::getInstance(XMLTOOLING_LOGCAT".SecurityHelper").error("hash algorithm (%s) not available", hash);
636 BIO* chain = BIO_new(BIO_s_mem());
637 BIO* b = BIO_new(BIO_f_base64());
639 BIO_set_flags(b, BIO_FLAGS_BASE64_NO_NL);
640 chain = BIO_push(b, chain);
642 b = BIO_new(BIO_f_md());
644 chain = BIO_push(b, chain);
648 i2d_RSA_PUBKEY_bio(chain, const_cast<RSA*>(rsa));
650 i2d_DSA_PUBKEY_bio(chain, const_cast<DSA*>(dsa));
651 #if defined(XMLTOOLING_XMLSEC_ECC) && defined(XMLTOOLING_OPENSSL_HAVE_EC)
653 i2d_EC_PUBKEY_bio(chain, const_cast<EC_KEY*>(ec));
658 char digest[EVP_MAX_MD_SIZE];
659 int len = BIO_gets(chain, digest, EVP_MD_size(md));
660 if (len != EVP_MD_size(md)) {
668 BIO_write(chain, digest, len);
671 BUF_MEM* bptr=nullptr;
672 BIO_get_mem_ptr(chain, &bptr);
673 if (bptr && bptr->length > 0)
674 ret.append(bptr->data, bptr->length);
680 string SecurityHelper::getDEREncoding(const XSECCryptoX509& cert, const char* hash, bool nowrap)
684 if (cert.getProviderName()!=DSIGConstants::s_unicodeStrPROVOpenSSL) {
685 Category::getInstance(XMLTOOLING_LOGCAT".SecurityHelper").warn("encoding of non-OpenSSL keys not supported");
689 const EVP_MD* md=nullptr;
691 md = EVP_get_digestbyname(hash);
693 Category::getInstance(XMLTOOLING_LOGCAT".SecurityHelper").error("hash algorithm (%s) not available", hash);
698 const X509* x = static_cast<const OpenSSLCryptoX509&>(cert).getOpenSSLX509();
699 EVP_PKEY* key = X509_get_pubkey(const_cast<X509*>(x));
701 BIO* chain = BIO_new(BIO_s_mem());
702 BIO* b = BIO_new(BIO_f_base64());
704 BIO_set_flags(b, BIO_FLAGS_BASE64_NO_NL);
705 chain = BIO_push(b, chain);
707 b = BIO_new(BIO_f_md());
709 chain = BIO_push(b, chain);
711 i2d_PUBKEY_bio(chain, key);
715 char digest[EVP_MAX_MD_SIZE];
716 int len = BIO_gets(chain, digest, EVP_MD_size(md));
717 if (len != EVP_MD_size(md)) {
725 BIO_write(chain, digest, len);
728 BUF_MEM* bptr=nullptr;
729 BIO_get_mem_ptr(chain, &bptr);
730 if (bptr && bptr->length > 0)
731 ret.append(bptr->data, bptr->length);
736 string SecurityHelper::getDEREncoding(const Credential& cred, const char* hash, bool nowrap)
738 const X509Credential* x509 = dynamic_cast<const X509Credential*>(&cred);
739 if (x509 && !x509->getEntityCertificateChain().empty())
740 return getDEREncoding(*(x509->getEntityCertificateChain().front()), hash, nowrap);
741 else if (cred.getPublicKey())
742 return getDEREncoding(*(cred.getPublicKey()), hash, nowrap);
746 string SecurityHelper::getDEREncoding(const XSECCryptoKey& key, bool hash, bool nowrap)
748 return getDEREncoding(key, hash ? "SHA1" : nullptr, nowrap);
751 string SecurityHelper::getDEREncoding(const XSECCryptoX509& cert, bool hash, bool nowrap)
753 return getDEREncoding(cert, hash ? "SHA1" : nullptr, nowrap);
756 string SecurityHelper::getDEREncoding(const Credential& cred, bool hash, bool nowrap)
758 return getDEREncoding(cred, hash ? "SHA1" : nullptr, nowrap);
761 XSECCryptoKey* SecurityHelper::fromDEREncoding(const char* buf, unsigned long buflen, bool base64)
764 XMLByte* decoded=nullptr;
766 decoded = xercesc::Base64::decode(reinterpret_cast<const XMLByte*>(buf), &x);
768 Category::getInstance(XMLTOOLING_LOGCAT".SecurityHelper").error("base64 decode failed");
773 BIO* b = BIO_new_mem_buf((void*)(base64 ? (char*)decoded : buf), (base64 ? x : buflen));
774 EVP_PKEY* pkey = d2i_PUBKEY_bio(b, nullptr);
777 #ifdef XMLTOOLING_XERCESC_HAS_XMLBYTE_RELEASE
778 XMLString::release(&decoded);
780 XMLString::release((char**)&decoded);
785 // Now map it to an XSEC wrapper.
786 XSECCryptoKey* ret = nullptr;
788 switch (pkey->type) {
790 ret = new OpenSSLCryptoKeyRSA(pkey);
794 ret = new OpenSSLCryptoKeyDSA(pkey);
797 #if defined(XMLTOOLING_XMLSEC_ECC) && defined(XMLTOOLING_OPENSSL_HAVE_EC)
799 ret = new OpenSSLCryptoKeyEC(pkey);
803 Category::getInstance(XMLTOOLING_LOGCAT".SecurityHelper").error("unsupported public key type");
806 catch (XSECCryptoException& ex) {
807 Category::getInstance(XMLTOOLING_LOGCAT".SecurityHelper").error(ex.getMsg());
816 XSECCryptoKey* SecurityHelper::fromDEREncoding(const XMLCh* buf)
819 XMLByte* decoded = xercesc::Base64::decodeToXMLByte(buf, &x);
821 Category::getInstance(XMLTOOLING_LOGCAT".SecurityHelper").error("base64 decode failed");
824 XSECCryptoKey* ret = fromDEREncoding((const char*)decoded, x, false);
825 #ifdef XMLTOOLING_XERCESC_HAS_XMLBYTE_RELEASE
826 XMLString::release(&decoded);
828 XMLString::release((char**)&decoded);