X-Git-Url: http://www.project-moonshot.org/gitweb/?a=blobdiff_plain;f=xmltooling%2Fencryption%2Fimpl%2FEncrypter.cpp;h=97583a7c316818ee94f1a61b9e6a4219ca7e240a;hb=420effca96f38dfa5f2a6549679a5d455a3945a7;hp=43185e835c83cff80f2adf45d3d1095102140208;hpb=b32808be870c0b5caa096cdc579cdf29b8c8ab09;p=shibboleth%2Fcpp-xmltooling.git diff --git a/xmltooling/encryption/impl/Encrypter.cpp b/xmltooling/encryption/impl/Encrypter.cpp index 43185e8..97583a7 100644 --- a/xmltooling/encryption/impl/Encrypter.cpp +++ b/xmltooling/encryption/impl/Encrypter.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2001-2006 Internet2 + * Copyright 2001-2010 Internet2 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,19 +22,47 @@ #include "internal.h" #include "encryption/Encrypter.h" +#include "encryption/Encryption.h" +#include "security/Credential.h" +#include "signature/KeyInfo.h" #include #include #include #include +#include #include #include using namespace xmlencryption; using namespace xmlsignature; using namespace xmltooling; +using namespace xercesc; using namespace std; +Encrypter::EncryptionParams::EncryptionParams( + const XMLCh* algorithm, const unsigned char* keyBuffer, unsigned int keyBufferSize, const Credential* credential, bool compact + ) : m_algorithm(algorithm), m_keyBuffer(keyBuffer), m_keyBufferSize(keyBufferSize), m_credential(credential), m_compact(compact) +{ +} + +Encrypter::EncryptionParams::~EncryptionParams() +{ +} + +Encrypter::KeyEncryptionParams::KeyEncryptionParams(const Credential& credential, const XMLCh* algorithm, const XMLCh* recipient) + : m_credential(credential), m_algorithm(algorithm), m_recipient(recipient) +{ +} + +Encrypter::KeyEncryptionParams::~KeyEncryptionParams() +{ +} + +Encrypter::Encrypter() : m_cipher(nullptr) +{ +} + Encrypter::~Encrypter() { XMLToolingInternalConfig::getInternalConfig().m_xsecProvider->releaseCipher(m_cipher); @@ -44,11 +72,11 @@ Encrypter::~Encrypter() void Encrypter::checkParams(EncryptionParams& encParams, KeyEncryptionParams* kencParams) { if (encParams.m_keyBufferSize==0) { - if (encParams.m_key) { + if (encParams.m_credential) { if (kencParams) throw EncryptionException("Generating EncryptedKey inline requires the encryption key in raw form."); } - else if (!encParams.m_key) { + else { if (!kencParams) throw EncryptionException("Using a generated encryption key requires a KeyEncryptionParams object."); @@ -60,20 +88,42 @@ void Encrypter::checkParams(EncryptionParams& encParams, KeyEncryptionParams* ke } } - if (!encParams.m_key) { + XSECCryptoKey* key=nullptr; + if (encParams.m_credential) { + key = encParams.m_credential->getPrivateKey(); + if (!key) + throw EncryptionException("Credential in EncryptionParams structure did not supply a private/secret key."); + // Set the encryption key. + m_cipher->setKey(key->clone()); + } + else { // We have to have a raw key now, so we need to build a wrapper around it. XSECAlgorithmHandler* handler =XSECPlatformUtils::g_algorithmMapper->mapURIToHandler(encParams.m_algorithm); - if (handler != NULL) - encParams.m_key = handler->createKeyForURI( + if (handler != nullptr) + key = handler->createKeyForURI( encParams.m_algorithm,const_cast(encParams.m_keyBuffer),encParams.m_keyBufferSize ); - if (!encParams.m_key) + if (!key) throw EncryptionException("Unable to build wrapper for key, unknown algorithm?"); + // Overwrite the length if known. + switch (static_cast(key)->getSymmetricKeyType()) { + case XSECCryptoSymmetricKey::KEY_3DES_192: + encParams.m_keyBufferSize = 192/8; + break; + case XSECCryptoSymmetricKey::KEY_AES_128: + encParams.m_keyBufferSize = 128/8; + break; + case XSECCryptoSymmetricKey::KEY_AES_192: + encParams.m_keyBufferSize = 192/8; + break; + case XSECCryptoSymmetricKey::KEY_AES_256: + encParams.m_keyBufferSize = 256/8; + break; + } + // Set the encryption key. + m_cipher->setKey(key); } - - // Set the encryption key. - m_cipher->setKey(encParams.m_key->clone()); } EncryptedData* Encrypter::encryptElement(DOMElement* element, EncryptionParams& encParams, KeyEncryptionParams* kencParams) @@ -82,7 +132,7 @@ EncryptedData* Encrypter::encryptElement(DOMElement* element, EncryptionParams& if (m_cipher && m_cipher->getDocument()!=element->getOwnerDocument()) { XMLToolingInternalConfig::getInternalConfig().m_xsecProvider->releaseCipher(m_cipher); - m_cipher=NULL; + m_cipher=nullptr; } if (!m_cipher) { @@ -110,7 +160,7 @@ EncryptedData* Encrypter::encryptElementContent(DOMElement* element, EncryptionP if (m_cipher && m_cipher->getDocument()!=element->getOwnerDocument()) { XMLToolingInternalConfig::getInternalConfig().m_xsecProvider->releaseCipher(m_cipher); - m_cipher=NULL; + m_cipher=nullptr; } if (!m_cipher) { @@ -138,10 +188,10 @@ EncryptedData* Encrypter::encryptStream(istream& input, EncryptionParams& encPar if (m_cipher) { XMLToolingInternalConfig::getInternalConfig().m_xsecProvider->releaseCipher(m_cipher); - m_cipher=NULL; + m_cipher=nullptr; } - DOMDocument* doc=NULL; + DOMDocument* doc=nullptr; try { doc=XMLToolingConfig::getConfig().getParser().newDocument(); XercesJanitor janitor(doc); @@ -151,8 +201,7 @@ EncryptedData* Encrypter::encryptStream(istream& input, EncryptionParams& encPar checkParams(encParams,kencParams); StreamInputSource::StreamBinInputStream xstream(input); m_cipher->encryptBinInputStream(&xstream, ENCRYPT_NONE, encParams.m_algorithm); - EncryptedData* xmlEncData = decorateAndUnmarshall(encParams, kencParams); - return xmlEncData; + return decorateAndUnmarshall(encParams, kencParams); } catch(XSECException& e) { auto_ptr_char temp(e.getMsg()); @@ -170,7 +219,7 @@ EncryptedData* Encrypter::decorateAndUnmarshall(EncryptionParams& encParams, Key throw EncryptionException("No EncryptedData element found?"); // Unmarshall a tooling version of EncryptedData around the DOM. - EncryptedData* xmlEncData=NULL; + EncryptedData* xmlEncData=nullptr; auto_ptr xmlObject(XMLObjectBuilder::buildOneFromElement(encData->getElement())); if (!(xmlObject.get()) || !(xmlEncData=dynamic_cast(xmlObject.get()))) throw EncryptionException("Unable to unmarshall into EncryptedData object."); @@ -179,19 +228,26 @@ EncryptedData* Encrypter::decorateAndUnmarshall(EncryptionParams& encParams, Key xmlEncData->releaseThisAndChildrenDOM(); // KeyInfo? - if (encParams.m_keyInfo) { - xmlEncData->setKeyInfo(encParams.m_keyInfo); - encParams.m_keyInfo=NULL; // transfer ownership - } + KeyInfo* kinfo = encParams.m_credential ? encParams.m_credential->getKeyInfo(encParams.m_compact) : nullptr; + if (kinfo) + xmlEncData->setKeyInfo(kinfo); // Are we doing a key encryption? if (kencParams) { - m_cipher->setKEK(kencParams->m_key->clone()); + XSECCryptoKey* kek = kencParams->m_credential.getPublicKey(); + if (!kek) + throw EncryptionException("Credential in KeyEncryptionParams structure did not supply a public key."); + if (!kencParams->m_algorithm) + kencParams->m_algorithm = getKeyTransportAlgorithm(kencParams->m_credential, encParams.m_algorithm); + if (!kencParams->m_algorithm) + throw EncryptionException("Unable to derive a supported key encryption algorithm."); + + m_cipher->setKEK(kek->clone()); // ownership of this belongs to us, for some reason... auto_ptr encKey( m_cipher->encryptKey(encParams.m_keyBuffer, encParams.m_keyBufferSize, ENCRYPT_NONE, kencParams->m_algorithm) ); - EncryptedKey* xmlEncKey=NULL; + EncryptedKey* xmlEncKey=nullptr; auto_ptr xmlObjectKey(XMLObjectBuilder::buildOneFromElement(encKey->getElement())); if (!(xmlObjectKey.get()) || !(xmlEncKey=dynamic_cast(xmlObjectKey.get()))) throw EncryptionException("Unable to unmarshall into EncryptedKey object."); @@ -203,15 +259,14 @@ EncryptedData* Encrypter::decorateAndUnmarshall(EncryptionParams& encParams, Key xmlEncKey->setRecipient(kencParams->m_recipient); // KeyInfo? - if (kencParams->m_keyInfo) { - xmlEncKey->setKeyInfo(kencParams->m_keyInfo); - kencParams->m_keyInfo=NULL; // transfer ownership - } + kinfo = kencParams->m_credential.getKeyInfo(encParams.m_compact); + if (kinfo) + xmlEncKey->setKeyInfo(kinfo); - // Add the EncryptedKey. + // Add the EncryptedKey inline. if (!xmlEncData->getKeyInfo()) xmlEncData->setKeyInfo(KeyInfoBuilder::buildKeyInfo()); - xmlEncData->getKeyInfo()->getOthers().push_back(xmlEncKey); + xmlEncData->getKeyInfo()->getUnknownXMLObjects().push_back(xmlEncKey); xmlObjectKey.release(); } @@ -219,25 +274,34 @@ EncryptedData* Encrypter::decorateAndUnmarshall(EncryptionParams& encParams, Key return xmlEncData; } -EncryptedKey* Encrypter::encryptKey(const unsigned char* keyBuffer, unsigned int keyBufferSize, KeyEncryptionParams& kencParams) +EncryptedKey* Encrypter::encryptKey( + const unsigned char* keyBuffer, unsigned int keyBufferSize, KeyEncryptionParams& kencParams, bool compact + ) { + if (!kencParams.m_algorithm) + throw EncryptionException("KeyEncryptionParams structure did not include a key encryption algorithm."); + // Get a fresh cipher object and document. if (m_cipher) { XMLToolingInternalConfig::getInternalConfig().m_xsecProvider->releaseCipher(m_cipher); - m_cipher=NULL; + m_cipher=nullptr; } - - DOMDocument* doc=NULL; + + XSECCryptoKey* kek = kencParams.m_credential.getPublicKey(); + if (!kek) + throw EncryptionException("Credential in KeyEncryptionParams structure did not supply a public key."); + + DOMDocument* doc=nullptr; try { doc=XMLToolingConfig::getConfig().getParser().newDocument(); XercesJanitor janitor(doc); m_cipher=XMLToolingInternalConfig::getInternalConfig().m_xsecProvider->newCipher(doc); m_cipher->setExclusiveC14nSerialisation(false); - m_cipher->setKEK(kencParams.m_key->clone()); + m_cipher->setKEK(kek->clone()); auto_ptr encKey(m_cipher->encryptKey(keyBuffer, keyBufferSize, ENCRYPT_NONE, kencParams.m_algorithm)); - EncryptedKey* xmlEncKey=NULL; + EncryptedKey* xmlEncKey=nullptr; auto_ptr xmlObjectKey(XMLObjectBuilder::buildOneFromElement(encKey->getElement())); if (!(xmlObjectKey.get()) || !(xmlEncKey=dynamic_cast(xmlObjectKey.get()))) throw EncryptionException("Unable to unmarshall into EncryptedKey object."); @@ -249,10 +313,9 @@ EncryptedKey* Encrypter::encryptKey(const unsigned char* keyBuffer, unsigned int xmlEncKey->setRecipient(kencParams.m_recipient); // KeyInfo? - if (kencParams.m_keyInfo) { - xmlEncKey->setKeyInfo(kencParams.m_keyInfo); - kencParams.m_keyInfo=NULL; // transfer ownership - } + KeyInfo* kinfo = kencParams.m_credential.getKeyInfo(compact); + if (kinfo) + xmlEncKey->setKeyInfo(kinfo); xmlObjectKey.release(); return xmlEncKey; @@ -265,3 +328,44 @@ EncryptedKey* Encrypter::encryptKey(const unsigned char* keyBuffer, unsigned int throw EncryptionException(string("XMLSecurity exception while encrypting: ") + e.getMsg()); } } + +const XMLCh* Encrypter::getKeyTransportAlgorithm(const Credential& credential, const XMLCh* encryptionAlg) +{ + XMLToolingConfig& conf = XMLToolingConfig::getConfig(); + const char* alg = credential.getAlgorithm(); + if (!alg || !strcmp(alg, "RSA")) { + if (XMLString::equals(encryptionAlg,DSIGConstants::s_unicodeStrURI3DES_CBC)) { + if (conf.isXMLAlgorithmSupported(DSIGConstants::s_unicodeStrURIRSA_1_5, XMLToolingConfig::ALGTYPE_KEYENCRYPT)) + return DSIGConstants::s_unicodeStrURIRSA_1_5; + else if (conf.isXMLAlgorithmSupported(DSIGConstants::s_unicodeStrURIRSA_OAEP_MGFP1, XMLToolingConfig::ALGTYPE_KEYENCRYPT)) + return DSIGConstants::s_unicodeStrURIRSA_OAEP_MGFP1; + } + else { + if (conf.isXMLAlgorithmSupported(DSIGConstants::s_unicodeStrURIRSA_OAEP_MGFP1, XMLToolingConfig::ALGTYPE_KEYENCRYPT)) + return DSIGConstants::s_unicodeStrURIRSA_OAEP_MGFP1; + else if (conf.isXMLAlgorithmSupported(DSIGConstants::s_unicodeStrURIRSA_1_5, XMLToolingConfig::ALGTYPE_KEYENCRYPT)) + return DSIGConstants::s_unicodeStrURIRSA_1_5; + } + } + else if (!strcmp(alg, "AES")) { + const XMLCh* ret = nullptr; + switch (credential.getKeySize()) { + case 128: + ret = DSIGConstants::s_unicodeStrURIKW_AES128; + case 192: + ret = DSIGConstants::s_unicodeStrURIKW_AES192; + case 256: + ret = DSIGConstants::s_unicodeStrURIKW_AES256; + default: + return nullptr; + } + if (conf.isXMLAlgorithmSupported(ret, XMLToolingConfig::ALGTYPE_KEYENCRYPT)) + return ret; + } + else if (!strcmp(alg, "DESede")) { + if (conf.isXMLAlgorithmSupported(DSIGConstants::s_unicodeStrURIKW_3DES, XMLToolingConfig::ALGTYPE_KEYENCRYPT)) + return DSIGConstants::s_unicodeStrURIKW_3DES; + } + + return nullptr; +}