| /** |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| |
| /* |
| * XSEC |
| * |
| * XencInteropResolver := Class to resolve key elements into certificates for |
| * interop test |
| * |
| * $Id$ |
| * |
| */ |
| |
| // XSEC |
| |
| #include "XencInteropResolver.hpp" |
| |
| #include <xsec/framework/XSECDefs.hpp> |
| #include <xsec/framework/XSECProvider.hpp> |
| #include <xsec/enc/XSECKeyInfoResolver.hpp> |
| #include <xsec/dsig/DSIGKeyInfoName.hpp> |
| #include <xsec/dsig/DSIGKeyInfoX509.hpp> |
| #include <xsec/xenc/XENCCipher.hpp> |
| #include <xsec/xenc/XENCEncryptedKey.hpp> |
| |
| #include "../../utils/XSECDOMUtils.hpp" |
| |
| #include <xercesc/util/Janitor.hpp> |
| #include <xercesc/util/XMLUniDefs.hpp> |
| |
| XERCES_CPP_NAMESPACE_USE |
| |
| #include <iostream> |
| |
| #if defined (XSEC_HAVE_OPENSSL) |
| # include <openssl/x509.h> |
| # include <openssl/pem.h> |
| # include <xsec/enc/OpenSSL/OpenSSLCryptoX509.hpp> |
| # include <xsec/enc/OpenSSL/OpenSSLCryptoKeyRSA.hpp> |
| # include <xsec/enc/OpenSSL/OpenSSLCryptoSymmetricKey.hpp> |
| #endif |
| |
| #if defined (XSEC_HAVE_WINCAPI) |
| # include <xsec/enc/WinCAPI/WinCAPICryptoProvider.hpp> |
| # include <xsec/enc/WinCAPI/WinCAPICryptoSymmetricKey.hpp> |
| #endif |
| |
| #if defined (XSEC_HAVE_NSS) |
| # include <xsec/enc/NSS/NSSCryptoProvider.hpp> |
| # include <xsec/enc/NSS/NSSCryptoSymmetricKey.hpp> |
| #endif |
| |
| // -------------------------------------------------------------------------------- |
| // Merlin Xenc-Five keys and Strings |
| // -------------------------------------------------------------------------------- |
| |
| static XMLCh s_bobName[] = { |
| chLatin_b, |
| chLatin_o, |
| chLatin_b, |
| chNull |
| }; |
| |
| static XMLCh s_jobName[] = { |
| chLatin_j, |
| chLatin_o, |
| chLatin_b, |
| chNull |
| }; |
| |
| static XMLCh s_jebName[] = { |
| chLatin_j, |
| chLatin_e, |
| chLatin_b, |
| chNull |
| }; |
| |
| static XMLCh s_jedName[] = { |
| chLatin_j, |
| chLatin_e, |
| chLatin_d, |
| chNull |
| }; |
| |
| static char s_bobKey[] = "abcdefghijklmnopqrstuvwx"; |
| static char s_jobKey[] = "abcdefghijklmnop"; |
| static char s_jebKey[] = "abcdefghijklmnopqrstuvwx"; |
| static char s_jedKey[] = "abcdefghijklmnopqrstuvwxyz012345"; |
| |
| // -------------------------------------------------------------------------------- |
| // Phaos xenc-three strings and keys |
| // -------------------------------------------------------------------------------- |
| |
| static XMLCh s_phaosRSAName[] = { |
| chLatin_m, |
| chLatin_y, |
| chDash, |
| chLatin_r, |
| chLatin_s, |
| chLatin_a, |
| chDash, |
| chLatin_k, |
| chLatin_e, |
| chLatin_y, |
| chNull |
| }; |
| |
| static XMLCh s_phaosTripleDESName[] = { |
| chLatin_m, |
| chLatin_y, |
| chDash, |
| chLatin_t, |
| chLatin_r, |
| chLatin_i, |
| chLatin_p, |
| chLatin_l, |
| chLatin_e, |
| chLatin_d, |
| chLatin_e, |
| chLatin_s, |
| chDash, |
| chLatin_k, |
| chLatin_e, |
| chLatin_y, |
| chNull |
| }; |
| |
| static XMLCh s_phaos3DESName[] = { |
| chLatin_m, |
| chLatin_y, |
| chDash, |
| chDigit_3, |
| chLatin_d, |
| chLatin_e, |
| chLatin_s, |
| chDash, |
| chLatin_k, |
| chLatin_e, |
| chLatin_y, |
| chNull |
| }; |
| |
| static XMLCh s_phaosAES128Name[] = { |
| chLatin_m, |
| chLatin_y, |
| chDash, |
| chLatin_a, |
| chLatin_e, |
| chLatin_s, |
| chDigit_1, |
| chDigit_2, |
| chDigit_8, |
| chDash, |
| chLatin_k, |
| chLatin_e, |
| chLatin_y, |
| chNull |
| }; |
| |
| static XMLCh s_phaosAES192Name[] = { |
| chLatin_m, |
| chLatin_y, |
| chDash, |
| chLatin_a, |
| chLatin_e, |
| chLatin_s, |
| chDigit_1, |
| chDigit_9, |
| chDigit_2, |
| chDash, |
| chLatin_k, |
| chLatin_e, |
| chLatin_y, |
| chNull |
| }; |
| |
| static XMLCh s_phaosAES256Name[] = { |
| chLatin_m, |
| chLatin_y, |
| chDash, |
| chLatin_a, |
| chLatin_e, |
| chLatin_s, |
| chDigit_2, |
| chDigit_5, |
| chDigit_6, |
| chDash, |
| chLatin_k, |
| chLatin_e, |
| chLatin_y, |
| chNull |
| }; |
| |
| unsigned char s_phaos3DESKey[] = { |
| |
| 0xc8, 0x8f, 0x89, 0xd5, 0xfd, 0xe9, 0xb9, 0x80, |
| 0x04, 0x46, 0x32, 0x1c, 0x4f, 0xab, 0xdf, 0x83, |
| 0xa4, 0x62, 0xb6, 0x62, 0x97, 0xf2, 0x70, 0xf4 |
| |
| }; |
| |
| unsigned char s_phaosAES128Key[] = { |
| |
| 0xd3, 0x5f, 0xb2, 0xb9, 0x0d, 0xa1, 0xb8, 0xf4, |
| 0xb5, 0xf9, 0x0b, 0xf4, 0x2c, 0x7f, 0xb3, 0x69 |
| |
| }; |
| |
| unsigned char s_phaosAES192Key[] = { |
| |
| 0x22, 0x57, 0xee, 0x4b, 0x8d, 0x0b, 0xbd, 0x2b, |
| 0x55, 0x53, 0x43, 0x23, 0xf1, 0xe3, 0xeb, 0xac, |
| 0x61, 0xd5, 0x84, 0x06, 0xf8, 0xf3, 0x2f, 0xbe |
| |
| }; |
| |
| unsigned char s_phaosAES256Key[] = { |
| |
| 0x66, 0x16, 0x78, 0xbf, 0x74, 0x65, 0xc1, 0x39, |
| 0x42, 0x10, 0xea, 0x48, 0xac, 0x77, 0xcb, 0x29, |
| 0x5c, 0x89, 0x38, 0x10, 0xed, 0x10, 0x93, 0x8e, |
| 0x40, 0x36, 0xad, 0xff, 0x8c, 0x51, 0xd5, 0xb0 |
| |
| }; |
| |
| // -------------------------------------------------------------------------------- |
| // Construct/Destruct |
| // -------------------------------------------------------------------------------- |
| |
| |
| XencInteropResolver::XencInteropResolver(DOMDocument * doc, const XMLCh * baseURI) { |
| |
| if (baseURI != NULL) |
| mp_baseURI = XMLString::replicate(baseURI); |
| else |
| mp_baseURI = NULL; |
| |
| #if !defined(_WIN32) |
| m_fcount = 0; |
| #endif |
| |
| mp_doc = doc; |
| |
| } |
| |
| |
| XencInteropResolver::~XencInteropResolver() { |
| |
| if (mp_baseURI != NULL) |
| XSEC_RELEASE_XMLCH(mp_baseURI); |
| |
| } |
| // -------------------------------------------------------------------------------- |
| // Utility functions |
| // -------------------------------------------------------------------------------- |
| #if defined(_WIN32) |
| |
| void reverseSlash(safeBuffer &path) { |
| |
| for (int i = 0; i < (int) strlen(path.rawCharBuffer()); ++i) { |
| |
| if (path[i] == '/') |
| path[i] = '\\'; |
| |
| } |
| |
| } |
| |
| #endif |
| |
| XSECCryptoSymmetricKey * XencInteropResolver::makeSymmetricKey(XSECCryptoSymmetricKey::SymmetricKeyType type) { |
| |
| XSECCryptoSymmetricKey * k = XSECPlatformUtils::g_cryptoProvider->keySymmetric(type); |
| return k; |
| } |
| |
| #if defined (XSEC_HAVE_OPENSSL) |
| |
| BIO * createFileBIO(const XMLCh * baseURI, const char * name) { |
| |
| // Open file URI relative to the encrypted file |
| |
| BIO * bioFile; |
| if ((bioFile = BIO_new(BIO_s_file())) == NULL) { |
| |
| return NULL; |
| |
| } |
| |
| safeBuffer fname; |
| fname.sbTranscodeIn(baseURI); |
| fname.sbStrcatIn("/"); |
| fname.sbStrcatIn(name); |
| |
| #if defined(_WIN32) |
| reverseSlash(fname); |
| #endif |
| |
| if (BIO_read_filename(bioFile, fname.rawCharBuffer()) <= 0) { |
| |
| return NULL; |
| |
| } |
| |
| return bioFile; |
| } |
| #endif |
| // -------------------------------------------------------------------------------- |
| // Resolver |
| // -------------------------------------------------------------------------------- |
| |
| XSECCryptoKey * XencInteropResolver::resolveKey(const DSIGKeyInfoList * lst) const { |
| |
| int lstSize = (int) lst->getSize(); |
| |
| for (int i = 0; i < lstSize; ++i) { |
| |
| const DSIGKeyInfo * ki = lst->item(i); |
| |
| if (ki->getKeyInfoType() == DSIGKeyInfo::KEYINFO_NAME) { |
| |
| const DSIGKeyInfoName * kn = static_cast<const DSIGKeyInfoName*>(ki); |
| |
| const XMLCh * name = kn->getKeyName(); |
| |
| // Check if this is a key we know |
| |
| if (strEquals(s_bobName, name)) { |
| XSECCryptoSymmetricKey * k = |
| XSECPlatformUtils::g_cryptoProvider->keySymmetric(XSECCryptoSymmetricKey::KEY_3DES_192); |
| try { |
| k->setKey((unsigned char *) s_bobKey, (unsigned int) strlen(s_bobKey)); |
| } catch (...) { |
| delete k; |
| throw; |
| } |
| return k; |
| } |
| if (strEquals(s_jobName, name)) { |
| XSECCryptoSymmetricKey * k = |
| XSECPlatformUtils::g_cryptoProvider->keySymmetric(XSECCryptoSymmetricKey::KEY_AES_128); |
| try { |
| k->setKey((unsigned char *) s_jobKey, (unsigned int) strlen(s_jobKey)); |
| } catch(...) { |
| delete k; |
| throw; |
| } |
| return k; |
| } |
| if (strEquals(s_jebName, name)) { |
| XSECCryptoSymmetricKey * k = |
| XSECPlatformUtils::g_cryptoProvider->keySymmetric(XSECCryptoSymmetricKey::KEY_AES_192); |
| try { |
| k->setKey((unsigned char *) s_jebKey, (unsigned int) strlen(s_jebKey)); |
| } catch(...) { |
| delete k; |
| throw; |
| } |
| return k; |
| } |
| if (strEquals(s_jedName, name)) { |
| XSECCryptoSymmetricKey * k = |
| XSECPlatformUtils::g_cryptoProvider->keySymmetric(XSECCryptoSymmetricKey::KEY_AES_256); |
| try { |
| k->setKey((unsigned char *) s_jedKey, (unsigned int) strlen(s_jedKey)); |
| } catch(...) { |
| delete k; |
| throw; |
| } |
| return k; |
| } |
| // PHAOS Keys |
| if (strEquals(s_phaos3DESName, name) || strEquals(s_phaosTripleDESName, name)) { |
| XSECCryptoSymmetricKey * k = |
| XSECPlatformUtils::g_cryptoProvider->keySymmetric(XSECCryptoSymmetricKey::KEY_3DES_192); |
| try { |
| k->setKey(s_phaos3DESKey, 24); |
| } catch (...) { |
| delete k; |
| throw; |
| } |
| return k; |
| } |
| if (strEquals(s_phaosAES128Name, name)) { |
| XSECCryptoSymmetricKey * k = |
| XSECPlatformUtils::g_cryptoProvider->keySymmetric(XSECCryptoSymmetricKey::KEY_AES_128); |
| try { |
| k->setKey(s_phaosAES128Key, 16); |
| } catch(...) { |
| delete k; |
| throw; |
| } |
| return k; |
| } |
| if (strEquals(s_phaosAES192Name, name)) { |
| XSECCryptoSymmetricKey * k = |
| XSECPlatformUtils::g_cryptoProvider->keySymmetric(XSECCryptoSymmetricKey::KEY_AES_192); |
| try { |
| k->setKey(s_phaosAES192Key, 24); |
| } catch(...) { |
| delete k; |
| throw; |
| } |
| return k; |
| } |
| if (strEquals(s_phaosAES256Name, name)) { |
| XSECCryptoSymmetricKey * k = |
| XSECPlatformUtils::g_cryptoProvider->keySymmetric(XSECCryptoSymmetricKey::KEY_AES_256); |
| try { |
| k->setKey(s_phaosAES256Key, 32); |
| } catch(...) { |
| delete k; |
| throw; |
| } |
| return k; |
| } |
| #if defined (XSEC_HAVE_OPENSSL) |
| if (strEquals(s_phaosRSAName, name)) { |
| |
| // This is the Phaos RSA key |
| BIO * rsaFile = createFileBIO(mp_baseURI, "rsa-priv-key.der"); |
| if (rsaFile == NULL) |
| return NULL; |
| |
| PKCS8_PRIV_KEY_INFO * p8inf; |
| p8inf = d2i_PKCS8_PRIV_KEY_INFO_bio(rsaFile, NULL); |
| |
| EVP_PKEY * pk = EVP_PKCS82PKEY(p8inf); |
| OpenSSLCryptoKeyRSA * k = new OpenSSLCryptoKeyRSA(pk); |
| PKCS8_PRIV_KEY_INFO_free(p8inf); |
| BIO_free_all(rsaFile); |
| return k; |
| |
| } |
| #endif |
| |
| // If we get this far, we don't know it. So look for EncryptedKey elements |
| // containing this name as a CarriedKeyName |
| |
| DOMNode * c = mp_doc->getDocumentElement()->getFirstChild(); |
| while (c != NULL) { |
| |
| if (c->getNodeType() == DOMNode::ELEMENT_NODE && |
| strEquals(getDSIGLocalName(c), MAKE_UNICODE_STRING("KeyInfo"))) { |
| |
| DOMNode * ek = c->getFirstChild(); |
| while (ek != NULL) { |
| |
| if (ek->getNodeType() == DOMNode::ELEMENT_NODE && |
| strEquals(getXENCLocalName(ek), MAKE_UNICODE_STRING("EncryptedKey"))) { |
| |
| // Load |
| XSECProvider prov; |
| XENCCipher * cipher = prov.newCipher(mp_doc); |
| |
| XENCEncryptedKey * xek = cipher->loadEncryptedKey(static_cast<DOMElement*>(ek)); |
| Janitor<XENCEncryptedKey> j_xek(xek); |
| |
| if (strEquals(xek->getCarriedKeyName(), name) && |
| strEquals(xek->getRecipient(), MAKE_UNICODE_STRING("you"))) { |
| |
| // This is it! |
| cipher->setKeyInfoResolver(this); |
| unsigned char keyBuf[1024]; |
| int sz = cipher->decryptKey(xek, keyBuf, 1024); |
| |
| if (sz > 0) { |
| XSECCryptoSymmetricKey * k = |
| XSECPlatformUtils::g_cryptoProvider->keySymmetric(XSECCryptoSymmetricKey::KEY_AES_256); |
| try { |
| k->setKey(keyBuf, sz); |
| } catch (...) { |
| delete k; |
| throw; |
| } |
| |
| return k; |
| } |
| } |
| } |
| ek = ek->getNextSibling(); |
| } |
| } |
| |
| c = c->getNextSibling(); |
| } |
| |
| } |
| |
| else if (ki->getKeyInfoType() == DSIGKeyInfo::KEYINFO_X509) { |
| |
| DSIGKeyInfoX509 * kix = (DSIGKeyInfoX509 *) ki; |
| |
| XSECCryptoX509 * XCX509 = kix->getCertificateCryptoItem(0); |
| |
| if (XCX509 != 0) { |
| #if defined (XSEC_HAVE_OPENSSL) |
| |
| |
| if (strEquals(XCX509->getProviderName(),DSIGConstants::s_unicodeStrPROVOpenSSL)) { |
| |
| OpenSSLCryptoX509 * OSSLX509 = (OpenSSLCryptoX509 *) XCX509; |
| X509 * x509 = OSSLX509->getOpenSSLX509(); |
| |
| // Check the serial number |
| |
| BIGNUM * bnserial = ASN1_INTEGER_to_BN(X509_get_serialNumber(x509), NULL); |
| BN_free(bnserial); |
| |
| BIO * rsaFile = createFileBIO(mp_baseURI, "rsa.p8"); |
| if (rsaFile == NULL) |
| return NULL; |
| |
| PKCS8_PRIV_KEY_INFO * p8inf; |
| p8inf = d2i_PKCS8_PRIV_KEY_INFO_bio(rsaFile, NULL); |
| |
| EVP_PKEY * pk = EVP_PKCS82PKEY(p8inf); |
| OpenSSLCryptoKeyRSA * k = new OpenSSLCryptoKeyRSA(pk); |
| PKCS8_PRIV_KEY_INFO_free(p8inf); |
| BIO_free_all(rsaFile); |
| return k; |
| |
| } |
| #if defined (XSEC_HAVE_WINCAPI) |
| else { |
| #endif /* XSEC_HAVE_WINCAPI */ |
| #endif /* XSEC_HAVE_OPENSSL */ |
| |
| #if defined (XSEC_HAVE_WINCAPI) |
| std::cerr << "WARNING - Unable to load PKCS8 private key file into Windows CAPI" << std::endl; |
| #if defined (XSEC_HAVE_OPENSSL) |
| } |
| #endif /* XSEC_HAVE_WINCAPI */ |
| #endif /* XSEC_HAVE_OPENSSL */ |
| } |
| } |
| } |
| |
| return NULL; |
| |
| } |
| |
| XSECKeyInfoResolver * XencInteropResolver::clone(void) const { |
| |
| return new XencInteropResolver(mp_doc, mp_baseURI); |
| |
| } |