xsec/tools/cipher/XencInteropResolver.cpp (399 lines of code) (raw):

/** * 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); }