blob: 733a2417fc18b7bf51a00e0e1882d18f46617a27 [file] [log] [blame]
/**
* 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);
}