/* * Copyright 2003-2005 The Apache Software Foundation. * * Licensed 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 * * XSECAlgorithmHandlerDefault := Interface class to define handling of * default encryption algorithms * * $Id: XENCAlgorithmHandlerDefault.cpp 422122 2006-07-15 00:58:21Z blautenb $ * */ // XSEC Includes #include #include #include #include #include #include #include #include #include #include "XENCAlgorithmHandlerDefault.hpp" #include #include XERCES_CPP_NAMESPACE_USE #define _MY_MAX_KEY_SIZE 2048 unsigned char s_3DES_CMS_IV [] = { 0x4a, 0xdd, 0xa2, 0x2c, 0x79, 0xe8, 0x21, 0x05 }; unsigned char s_AES_IV [] = { 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6 }; // -------------------------------------------------------------------------------- // Compare URI to key type // -------------------------------------------------------------------------------- void XENCAlgorithmHandlerDefault::mapURIToKey(const XMLCh * uri, XSECCryptoKey * key, XSECCryptoKey::KeyType &kt, XSECCryptoSymmetricKey::SymmetricKeyType &skt, bool &isSymmetricKeyWrap) { if (key == NULL) { throw XSECException(XSECException::CipherError, "XENCAlgorithmHandlerDefault::mapURIToKey - trying to process a NULL key"); } XSECCryptoSymmetricKey * keySymmetric; bool keyOK = false; kt = key->getKeyType(); skt = XSECCryptoSymmetricKey::KEY_NONE; isSymmetricKeyWrap = false; switch (kt) { case XSECCryptoKey::KEY_RSA_PUBLIC : case XSECCryptoKey::KEY_RSA_PAIR : case XSECCryptoKey::KEY_RSA_PRIVATE : keyOK = strEquals(uri, DSIGConstants::s_unicodeStrURIRSA_1_5) || strEquals(uri, DSIGConstants::s_unicodeStrURIRSA_OAEP_MGFP1); break; case XSECCryptoKey::KEY_SYMMETRIC : keySymmetric = (XSECCryptoSymmetricKey *) key; if (keySymmetric != NULL) { skt = keySymmetric->getSymmetricKeyType(); switch (skt) { case XSECCryptoSymmetricKey::KEY_3DES_192 : isSymmetricKeyWrap = strEquals(uri, DSIGConstants::s_unicodeStrURIKW_3DES); keyOK = isSymmetricKeyWrap || strEquals(uri, DSIGConstants::s_unicodeStrURI3DES_CBC); break; case XSECCryptoSymmetricKey::KEY_AES_128 : isSymmetricKeyWrap = strEquals(uri, DSIGConstants::s_unicodeStrURIKW_AES128); keyOK = isSymmetricKeyWrap || strEquals(uri, DSIGConstants::s_unicodeStrURIAES128_CBC); break; case XSECCryptoSymmetricKey::KEY_AES_192 : isSymmetricKeyWrap = strEquals(uri, DSIGConstants::s_unicodeStrURIKW_AES192); keyOK = isSymmetricKeyWrap || strEquals(uri, DSIGConstants::s_unicodeStrURIAES192_CBC); break; case XSECCryptoSymmetricKey::KEY_AES_256 : isSymmetricKeyWrap = strEquals(uri, DSIGConstants::s_unicodeStrURIKW_AES256); keyOK = isSymmetricKeyWrap || strEquals(uri, DSIGConstants::s_unicodeStrURIAES256_CBC); break; default: break; } } break; default: break; } if (keyOK == false) { throw XSECException(XSECException::CipherError, "XENCAlgorithmHandlerDefault::mapURIToKey - key inappropriate for URI"); } } // -------------------------------------------------------------------------------- // AES Key wrap/unwrap // -------------------------------------------------------------------------------- unsigned int XENCAlgorithmHandlerDefault::unwrapKeyAES( TXFMChain * cipherText, XSECCryptoKey * key, safeBuffer & result) { // Cat the encrypted key XMLByte buf[_MY_MAX_KEY_SIZE]; XMLByte aesBuf[16]; XMLByte aesOutBuf[16]; TXFMBase * b = cipherText->getLastTxfm(); int sz = b->readBytes(buf, _MY_MAX_KEY_SIZE); if (sz <= 0) { throw XSECException(XSECException::CipherError, "XENCAlgorithmHandlerDefault - AES Wrapped Key not found"); } if (sz == _MY_MAX_KEY_SIZE) { throw XSECException(XSECException::CipherError, "XENCAlgorithmHandlerDefault - Key to decrypt too big!"); } // Find number of blocks, and ensure we are a multiple of 64 bits if (sz % 8 != 0) { throw XSECException(XSECException::CipherError, "XENCAlgorithmHandlerDefault - AES wrapped key not a multiple of 64"); } // Do the decrypt - this cast will throw if wrong, but we should // not have been able to get through algorithm checks otherwise XSECCryptoSymmetricKey * sk = (XSECCryptoSymmetricKey *) key; int blocks = sz / 8; int n = blocks - 1; for (int j = 5; j >= 0; j--) { for (int i = n ; i > 0 ; --i) { // Gather blocks to decrypt // A memcpy(aesBuf, buf, 8); // Ri memcpy(&aesBuf[8], &buf[8 * i], 8); // A mod t aesBuf[7] ^= ((n * j) + i); // do decrypt sk->decryptInit(false, XSECCryptoSymmetricKey::MODE_ECB); // No padding int sz = sk->decrypt(aesBuf, aesOutBuf, 16, 16); sz += sk->decryptFinish(&aesOutBuf[sz], 16 - sz); if (sz != 16) { throw XSECException(XSECException::CipherError, "XENCAlgorithmHandlerDefault - Error performing decrypt in AES Unwrap"); } // Copy back to where we are // A memcpy(buf, aesOutBuf, 8); // Ri memcpy(&buf[8 * i], &aesOutBuf[8], 8); } } // Check is valid if (memcmp(buf, s_AES_IV, 8) != 0) { throw XSECException(XSECException::CipherError, "XENCAlgorithmHandlerDefault - decrypt failed - AES IV is not correct"); } // Copy to safebuffer result.sbMemcpyIn(&buf[8], n * 8); return n * 8; } bool XENCAlgorithmHandlerDefault::wrapKeyAES( TXFMChain * cipherText, XSECCryptoKey * key, safeBuffer & result) { // get the raw key XMLByte buf[_MY_MAX_KEY_SIZE + 8]; memcpy(buf, s_AES_IV, 8); XMLByte aesBuf[16]; XMLByte aesOutBuf[32]; // Give this an extra block for WinCAPI TXFMBase * b = cipherText->getLastTxfm(); int sz = b->readBytes(&buf[8], _MY_MAX_KEY_SIZE); if (sz <= 0) { throw XSECException(XSECException::CipherError, "XENCAlgorithmHandlerDefault - Key not found"); } if (sz == _MY_MAX_KEY_SIZE) { throw XSECException(XSECException::CipherError, "XENCAlgorithmHandlerDefault - Key to encrypt too big!"); } // Find number of blocks, and ensure we are a multiple of 64 bits if (sz % 8 != 0) { throw XSECException(XSECException::CipherError, "XENCAlgorithmHandlerDefault - AES wrapped key not a multiple of 64"); } // Do the decrypt - this cast will throw if wrong, but we should // not have been able to get through algorithm checks otherwise XSECCryptoSymmetricKey * sk = (XSECCryptoSymmetricKey *) key; int n = sz / 8; for (int j = 0; j <= 5; ++j) { for (int i = 1 ; i <= n ; ++i) { // Gather blocks to decrypt // A memcpy(aesBuf, buf, 8); // Ri memcpy(&aesBuf[8], &buf[8 * i], 8); // do encrypt sk->encryptInit(false, XSECCryptoSymmetricKey::MODE_ECB); int sz = sk->encrypt(aesBuf, aesOutBuf, 16, 32); sz += sk->encryptFinish(&aesOutBuf[sz], 32 - sz); if (sz != 16) { throw XSECException(XSECException::CipherError, "XENCAlgorithmHandlerDefault - Error performing encrypt in AES wrap"); } // Copy back to where we are // A memcpy(buf, aesOutBuf, 8); // A mod t buf[7] ^= ((n * j) + i); // Ri memcpy(&buf[8 * i], &aesOutBuf[8], 8); } } // Now we have to base64 encode XSECCryptoBase64 * b64 = XSECPlatformUtils::g_cryptoProvider->base64(); if (!b64) { throw XSECException(XSECException::CryptoProviderError, "XENCAlgorithmHandlerDefault - Error getting base64 encoder in AES wrap"); } Janitor j_b64(b64); unsigned char * b64Buffer; int bufLen = ((n + 1) * 8) * 3; XSECnew(b64Buffer, unsigned char[bufLen + 1]);// Overkill ArrayJanitor j_b64Buffer(b64Buffer); b64->encodeInit(); int outputLen = b64->encode (buf, (n+1) * 8, b64Buffer, bufLen); outputLen += b64->encodeFinish(&b64Buffer[outputLen], bufLen - outputLen); b64Buffer[outputLen] = '\0'; // Copy to safebuffer result.sbStrcpyIn((const char *) b64Buffer); return true; } // -------------------------------------------------------------------------------- // DES CMS Key wrap/unwrap // -------------------------------------------------------------------------------- unsigned int XENCAlgorithmHandlerDefault::unwrapKey3DES( TXFMChain * cipherText, XSECCryptoKey * key, safeBuffer & result) { // Perform an unwrap on the key safeBuffer cipherSB; // Cat the encrypted key XMLByte buf[_MY_MAX_KEY_SIZE]; TXFMBase * b = cipherText->getLastTxfm(); int offset = 0; int sz = b->readBytes(buf, _MY_MAX_KEY_SIZE); while (sz > 0) { cipherSB.sbMemcpyIn(offset, buf, sz); offset += sz; sz = b->readBytes(buf, _MY_MAX_KEY_SIZE); } if (offset > _MY_MAX_KEY_SIZE) { throw XSECException(XSECException::CipherError, "XENCAlgorithmHandlerDefault - Key to decrypt too big!"); } // Do the decrypt - this cast will throw if wrong, but we should // not have been able to get through algorithm checks otherwise XSECCryptoSymmetricKey * sk = (XSECCryptoSymmetricKey *) key; sk->decryptInit(false, XSECCryptoSymmetricKey::MODE_CBC, s_3DES_CMS_IV); // If key is bigger than this, then we have a problem sz = sk->decrypt(cipherSB.rawBuffer(), buf, offset, _MY_MAX_KEY_SIZE); sz += sk->decryptFinish(&buf[sz], _MY_MAX_KEY_SIZE - sz); if (sz <= 0) { throw XSECException(XSECException::CipherError, "XENCAlgorithmHandlerDefault - Error decrypting key!"); } // We now have the first cut, reverse the cipher text XMLByte buf2[_MY_MAX_KEY_SIZE]; for (int i = 0; i < sz; ++ i) { buf2[sz - i - 1] = buf[i]; } // decrypt again sk->decryptInit(false); offset = sk->decrypt(buf2, buf, sz, _MY_MAX_KEY_SIZE); offset += sk->decryptFinish(&buf[offset], _MY_MAX_KEY_SIZE - offset); // Calculate the CMS Key Checksum XSECCryptoHash * sha1 = XSECPlatformUtils::g_cryptoProvider->hashSHA1(); if (!sha1) { throw XSECException(XSECException::CryptoProviderError, "XENCAlgorithmHandlerDefault - Error getting SHA-1 object in 3DES unwrap"); } Janitor j_sha1(sha1); sha1->reset(); sha1->hash(buf, offset - 8); sha1->finish(buf2, _MY_MAX_KEY_SIZE); // Compare for (int j = 0; j < 8; ++j) { if (buf[offset - 8 + j] != buf2[j]) { throw XSECException(XSECException::CipherError, "XENCAlgorithmHandlerDefault::unwrapKey3DES - CMS Key Checksum does not match"); } } result.sbMemcpyIn(buf, offset - 8); return offset - 8; } bool XENCAlgorithmHandlerDefault::wrapKey3DES( TXFMChain * cipherText, XSECCryptoKey * key, safeBuffer & result) { // Cat the plaintext key XMLByte buf[_MY_MAX_KEY_SIZE + 16]; TXFMBase * b = cipherText->getLastTxfm(); int offset = 0; int sz = b->readBytes(buf, _MY_MAX_KEY_SIZE); if (sz <= 0) { throw XSECException(XSECException::CipherError, "XENCAlgorithmHandlerDefault::wrapKey3DES - Unable to read key"); } if (sz >= _MY_MAX_KEY_SIZE) { throw XSECException(XSECException::CipherError, "XENCAlgorithmHandlerDefault::wrapKey3DES - Key to decrypt too big!"); } if (sz % 8 != 0) { throw XSECException(XSECException::CipherError, "XENCAlgorithmHandlerDefault::wrapKey3DES - Key to encrypt not a multiple of 8 bytes"); } // Calculate the CMS Key Checksum // Do the first encrypt XMLByte buf2[_MY_MAX_KEY_SIZE + 16]; XSECCryptoHash * sha1 = XSECPlatformUtils::g_cryptoProvider->hashSHA1(); if (!sha1) { throw XSECException(XSECException::CryptoProviderError, "XENCAlgorithmHandlerDefault - Error getting SHA-1 object in 3DES wrap"); } Janitor j_sha1(sha1); sha1->reset(); sha1->hash(buf, sz); sha1->finish(buf2, _MY_MAX_KEY_SIZE); for (int j = 0; j < 8 ; ++j) buf[sz++] = buf2[j]; // Do the first encrypt - this cast will throw if wrong, but we should // not have been able to get through algorithm checks otherwise XSECCryptoSymmetricKey * sk = (XSECCryptoSymmetricKey *) key; sk->encryptInit(false); // If key is bigger than this, then we have a problem sz = sk->encrypt(buf, buf2, sz, _MY_MAX_KEY_SIZE); sz += sk->encryptFinish(&buf2[sz], _MY_MAX_KEY_SIZE - sz); if (sz <= 0) { throw XSECException(XSECException::CipherError, "XENCAlgorithmHandlerDefault::wrapKey3DES - Error encrypting key!"); } // We now have the first cut, reverse the cipher text for (int i = 0; i < sz; ++ i) { buf[sz - i - 1] = buf2[i]; } // encrypt again sk->encryptInit(false, XSECCryptoSymmetricKey::MODE_CBC, s_3DES_CMS_IV); offset = sk->encrypt(buf, buf2, sz, _MY_MAX_KEY_SIZE); offset += sk->encryptFinish(&buf2[offset], _MY_MAX_KEY_SIZE - offset); // Base64 encode XSECCryptoBase64 * b64 = XSECPlatformUtils::g_cryptoProvider->base64(); if (!b64) { throw XSECException(XSECException::CryptoProviderError, "XENCAlgorithmHandlerDefault - Error getting base64 encoder in 3DES wrap"); } Janitor j_b64(b64); unsigned char * b64Buffer; int bufLen = (offset + 9) * 3; XSECnew(b64Buffer, unsigned char[bufLen + 1]);// Overkill ArrayJanitor j_b64Buffer(b64Buffer); b64->encodeInit(); int outputLen = b64->encode (&buf2[8], offset-8, b64Buffer, bufLen); outputLen += b64->encodeFinish(&b64Buffer[outputLen], bufLen - outputLen); b64Buffer[outputLen] = '\0'; // Copy to safebuffer result.sbStrcpyIn((const char *) b64Buffer); return true; } // -------------------------------------------------------------------------------- // InputStream decryption // -------------------------------------------------------------------------------- bool XENCAlgorithmHandlerDefault::appendDecryptCipherTXFM( TXFMChain * cipherText, XENCEncryptionMethod * encryptionMethod, XSECCryptoKey * key, XERCES_CPP_NAMESPACE_QUALIFIER DOMDocument * doc ) { // We only support this for bulk Symmetric key algorithms XSECCryptoKey::KeyType kt; XSECCryptoSymmetricKey::SymmetricKeyType skt; bool isKeyWrap = false; mapURIToKey(encryptionMethod->getAlgorithm(), key, kt, skt, isKeyWrap); if (kt != XSECCryptoKey::KEY_SYMMETRIC || isKeyWrap == true) { throw XSECException(XSECException::CipherError, "XENCAlgorithmHandlerDefault::appendDecryptCipherTXFM - only supports bulk symmetric algorithms"); } // Add the decryption TXFM TXFMCipher * tcipher; XSECnew(tcipher, TXFMCipher(doc, key, false)); cipherText->appendTxfm(tcipher); return true; } // -------------------------------------------------------------------------------- // RSA SafeBuffer decryption // -------------------------------------------------------------------------------- unsigned int XENCAlgorithmHandlerDefault::doRSADecryptToSafeBuffer( TXFMChain * cipherText, XENCEncryptionMethod * encryptionMethod, XSECCryptoKey * key, DOMDocument * doc, safeBuffer & result) { // Only works with RSA_PRIVATE or PAIR if (key->getKeyType() == XSECCryptoKey::KEY_RSA_PUBLIC) { throw XSECException(XSECException::CipherError, "XENCAlgorithmHandlerDefault - RSA Decrypt must use private key"); } // Know this is an RSA key, so just cast XSECCryptoKeyRSA * rsa = (XSECCryptoKeyRSA *) key; // Allocate an output buffer unsigned char * decBuf; XSECnew(decBuf, unsigned char[rsa->getLength()]); ArrayJanitor j_decBuf(decBuf); // Input TXFMBase * b = cipherText->getLastTxfm(); safeBuffer cipherSB; XMLByte buf[1024]; unsigned int offset = 0; int bytesRead = b->readBytes(buf, 1024); while (bytesRead > 0) { cipherSB.sbMemcpyIn(offset, buf, bytesRead); offset += bytesRead; bytesRead = b->readBytes(buf, 1024); } unsigned int decryptLen; // Now we find out what kind of padding if (strEquals(encryptionMethod->getAlgorithm(), DSIGConstants::s_unicodeStrURIRSA_1_5)) { // Do decrypt decryptLen = rsa->privateDecrypt(cipherSB.rawBuffer(), decBuf, offset, rsa->getLength(), XSECCryptoKeyRSA::PAD_PKCS_1_5, HASH_NONE); } else if (strEquals(encryptionMethod->getAlgorithm(), DSIGConstants::s_unicodeStrURIRSA_OAEP_MGFP1)) { if (!strEquals(encryptionMethod->getDigestMethod(), DSIGConstants::s_unicodeStrURISHA1)) { throw XSECException(XSECException::CipherError, "XENCAlgorithmHandlerDefault::doRSADecryptToSafeBuffer - Currently only SHA-1 is supported for OAEP"); } // Read out any OAEP params unsigned char * oaepParamsBuf = NULL; const XMLCh * oaepParams = encryptionMethod->getOAEPparams(); unsigned int sz = 0; if (oaepParams != NULL) { char * oaepParamsStr = XMLString::transcode(oaepParams); ArrayJanitor j_oaepParamsStr(oaepParamsStr); unsigned int bufLen = (unsigned int) strlen(oaepParamsStr); oaepParamsBuf = new unsigned char[bufLen]; ArrayJanitor j_oaepParamsBuf(oaepParamsBuf); XSECCryptoBase64 * b64 = XSECPlatformUtils::g_cryptoProvider->base64(); Janitor j_b64(b64); b64->decodeInit(); sz = b64->decode((unsigned char *) oaepParamsStr, bufLen, oaepParamsBuf, bufLen); sz += b64->decodeFinish(&oaepParamsBuf[sz], bufLen - sz); rsa->setOAEPparams(oaepParamsBuf, sz); } else rsa->setOAEPparams(NULL, 0); decryptLen = rsa->privateDecrypt(cipherSB.rawBuffer(), decBuf, offset, rsa->getLength(), XSECCryptoKeyRSA::PAD_OAEP_MGFP1, HASH_SHA1); } else { throw XSECException(XSECException::CipherError, "XENCAlgorithmHandlerDefault::doRSADecryptToSafeBuffer - Unknown padding type"); } // Copy to output result.sbMemcpyIn(decBuf, decryptLen); memset(decBuf, 0, decryptLen); return decryptLen; } // -------------------------------------------------------------------------------- // SafeBuffer decryption // -------------------------------------------------------------------------------- unsigned int XENCAlgorithmHandlerDefault::decryptToSafeBuffer( TXFMChain * cipherText, XENCEncryptionMethod * encryptionMethod, XSECCryptoKey * key, DOMDocument * doc, safeBuffer & result ) { XSECCryptoKey::KeyType kt; XSECCryptoSymmetricKey::SymmetricKeyType skt; bool isKeyWrap = false; if (encryptionMethod == NULL) { throw XSECException(XSECException::CipherError, "XENCAlgorithmHandlerDefault::decryptToSafeBuffer - Cannot operate with NULL encryption Method"); } // Check the uri against the key type mapURIToKey(encryptionMethod->getAlgorithm(), key, kt, skt, isKeyWrap); // RSA? if (kt == XSECCryptoKey::KEY_RSA_PAIR || kt == XSECCryptoKey::KEY_RSA_PUBLIC || kt == XSECCryptoKey::KEY_RSA_PRIVATE) { return doRSADecryptToSafeBuffer(cipherText, encryptionMethod, key, doc, result); } // Ensure is symmetric before we continue if (kt != XSECCryptoKey::KEY_SYMMETRIC) { throw XSECException(XSECException::CipherError, "XENCAlgorithmHandlerDefault::decryptToSafeBuffer - Not an RSA key, but not symmetric"); } // Key wrap? if (isKeyWrap == true) { if (skt == XSECCryptoSymmetricKey::KEY_AES_128 || skt == XSECCryptoSymmetricKey::KEY_AES_192 || skt == XSECCryptoSymmetricKey::KEY_AES_256) { return unwrapKeyAES(cipherText, key, result); } else if (skt == XSECCryptoSymmetricKey::KEY_3DES_192) { return unwrapKey3DES(cipherText, key, result); } else { throw XSECException(XSECException::CipherError, "XENCAlgorithmHandlerDefault::decryptToSafeBuffer - don't know how to do key wrap for algorithm"); } } // It's symmetric and it's not a key wrap, so just treat as a block algorithm TXFMCipher * tcipher; XSECnew(tcipher, TXFMCipher(doc, key, false)); cipherText->appendTxfm(tcipher); // Do the decrypt to the safeBuffer result.sbStrcpyIn(""); unsigned int offset = 0; XMLByte buf[1024]; TXFMBase * b = cipherText->getLastTxfm(); int bytesRead = b->readBytes(buf, 1024); while (bytesRead > 0) { result.sbMemcpyIn(offset, buf, bytesRead); offset += bytesRead; bytesRead = b->readBytes(buf, 1024); } result[offset] = '\0'; return offset; } // -------------------------------------------------------------------------------- // RSA SafeBuffer encryption // -------------------------------------------------------------------------------- bool XENCAlgorithmHandlerDefault::doRSAEncryptToSafeBuffer( TXFMChain * plainText, XENCEncryptionMethod * encryptionMethod, XSECCryptoKey * key, XERCES_CPP_NAMESPACE_QUALIFIER DOMDocument * doc, safeBuffer & result ) { // Only works with RSA_PRIVATE or PAIR if (key->getKeyType() == XSECCryptoKey::KEY_RSA_PRIVATE) { throw XSECException(XSECException::CipherError, "XENCAlgorithmHandlerDefault - RSA Encrypt must use public key"); } XSECCryptoKeyRSA * rsa = (XSECCryptoKeyRSA *) key; // Allocate an output buffer unsigned char * encBuf; XSECnew(encBuf, unsigned char[rsa->getLength()]); ArrayJanitor j_encBuf(encBuf); // Input TXFMBase * b = plainText->getLastTxfm(); safeBuffer plainSB; plainSB.isSensitive(); XMLByte buf[1024]; unsigned int offset = 0; int bytesRead = b->readBytes(buf, 1024); while (bytesRead > 0) { plainSB.sbMemcpyIn(offset, buf, bytesRead); offset += bytesRead; bytesRead = b->readBytes(buf, 1024); } unsigned int encryptLen; // Do decrypt if (strEquals(encryptionMethod->getAlgorithm(), DSIGConstants::s_unicodeStrURIRSA_1_5)) { encryptLen = rsa->publicEncrypt(plainSB.rawBuffer(), encBuf, offset, rsa->getLength(), XSECCryptoKeyRSA::PAD_PKCS_1_5, HASH_NONE); } else if (strEquals(encryptionMethod->getAlgorithm(), DSIGConstants::s_unicodeStrURIRSA_OAEP_MGFP1)) { encryptionMethod->setDigestMethod(DSIGConstants::s_unicodeStrURISHA1); // Check for OAEP params int oaepParamsLen = rsa->getOAEPparamsLen(); if (oaepParamsLen > 0) { unsigned char * oaepParamsB64; XSECnew(oaepParamsB64, unsigned char[oaepParamsLen * 2]); ArrayJanitor j_oaepParamsB64(oaepParamsB64); XSECCryptoBase64 * b64 = XSECPlatformUtils::g_cryptoProvider->base64(); Janitor j_b64(b64); b64->encodeInit(); int sz = b64->encode(rsa->getOAEPparams(), oaepParamsLen, oaepParamsB64, oaepParamsLen *2); sz += b64->encodeFinish(&oaepParamsB64[sz], (oaepParamsLen * 2) - sz); oaepParamsB64[sz] = '\0'; XMLCh * xBuf = XMLString::transcode((char *) oaepParamsB64); ArrayJanitor j_xBuf(xBuf); encryptionMethod->setOAEPparams(xBuf); } encryptLen = rsa->publicEncrypt(plainSB.rawBuffer(), encBuf, offset, rsa->getLength(), XSECCryptoKeyRSA::PAD_OAEP_MGFP1, HASH_SHA1); } else { throw XSECException(XSECException::CipherError, "XENCAlgorithmHandlerDefault::doRSAEncryptToSafeBuffer - Unknown padding type"); } // Now need to base64 encode XSECCryptoBase64 * b64 = XSECPlatformUtils::g_cryptoProvider->base64(); Janitor j_b64(b64); b64->encodeInit(); encryptLen = b64->encode(encBuf, encryptLen, buf, 1024); result.sbMemcpyIn(buf, encryptLen); unsigned int finalLen = b64->encodeFinish(buf, 1024); result.sbMemcpyIn(encryptLen, buf, finalLen); result[encryptLen + finalLen] = '\0'; // This is a string, so set the buffer correctly result.setBufferType(safeBuffer::BUFFER_CHAR); return true; } // -------------------------------------------------------------------------------- // SafeBuffer encryption // -------------------------------------------------------------------------------- bool XENCAlgorithmHandlerDefault::encryptToSafeBuffer( TXFMChain * plainText, XENCEncryptionMethod * encryptionMethod, XSECCryptoKey * key, XERCES_CPP_NAMESPACE_QUALIFIER DOMDocument * doc, safeBuffer & result ) { XSECCryptoKey::KeyType kt; XSECCryptoSymmetricKey::SymmetricKeyType skt; bool isKeyWrap = false; if (encryptionMethod == NULL) { throw XSECException(XSECException::CipherError, "XENCAlgorithmHandlerDefault::encryptToSafeBuffer - Cannot operate with NULL encryption Method"); } // Check the uri against the key type mapURIToKey(encryptionMethod->getAlgorithm(), key, kt, skt, isKeyWrap); // RSA? if (kt == XSECCryptoKey::KEY_RSA_PRIVATE || kt == XSECCryptoKey::KEY_RSA_PUBLIC || kt == XSECCryptoKey::KEY_RSA_PAIR) { return doRSAEncryptToSafeBuffer(plainText, encryptionMethod, key, doc, result); } // Ensure is symmetric before we continue if (kt != XSECCryptoKey::KEY_SYMMETRIC) { throw XSECException(XSECException::CipherError, "XENCAlgorithmHandlerDefault::encryptToSafeBuffer - Not an RSA key, but not symmetric"); } if (isKeyWrap == true) { if (skt == XSECCryptoSymmetricKey::KEY_AES_128 || skt == XSECCryptoSymmetricKey::KEY_AES_192 || skt == XSECCryptoSymmetricKey::KEY_AES_256) { return wrapKeyAES(plainText, key, result); } if (skt == XSECCryptoSymmetricKey::KEY_3DES_192) { return wrapKey3DES(plainText, key, result); } else { throw XSECException(XSECException::CipherError, "XENCAlgorithmHandlerDefault::decryptToSafeBuffer - don't know how to do key wrap for algorithm"); } } // Must be bulk symmetric - do the encryption TXFMCipher *tcipher; XSECnew(tcipher, TXFMCipher(doc, key, true)); plainText->appendTxfm(tcipher); // Transform to Base64 TXFMBase64 * tb64; XSECnew(tb64, TXFMBase64(doc, false)); plainText->appendTxfm(tb64); // Read into the safeBuffer result = ""; result << plainText->getLastTxfm(); return true; } // -------------------------------------------------------------------------------- // Key Creation // -------------------------------------------------------------------------------- XSECCryptoKey * XENCAlgorithmHandlerDefault::createKeyForURI( const XMLCh * uri, const unsigned char * keyBuffer, unsigned int keyLen ) { XSECCryptoSymmetricKey * sk = NULL; if (strEquals(uri, DSIGConstants::s_unicodeStrURI3DES_CBC)) { sk = XSECPlatformUtils::g_cryptoProvider->keySymmetric(XSECCryptoSymmetricKey::KEY_3DES_192); } else if (strEquals(uri, DSIGConstants::s_unicodeStrURIAES128_CBC)) { sk = XSECPlatformUtils::g_cryptoProvider->keySymmetric(XSECCryptoSymmetricKey::KEY_AES_128); } else if (strEquals(uri, DSIGConstants::s_unicodeStrURIAES192_CBC)) { sk = XSECPlatformUtils::g_cryptoProvider->keySymmetric(XSECCryptoSymmetricKey::KEY_AES_192); } else if (strEquals(uri, DSIGConstants::s_unicodeStrURIAES256_CBC)) { sk = XSECPlatformUtils::g_cryptoProvider->keySymmetric(XSECCryptoSymmetricKey::KEY_AES_256); } if (sk != NULL) { sk->setKey(keyBuffer, keyLen); return sk; } throw XSECException(XSECException::CipherError, "XENCAlgorithmHandlerDefault - URI Provided, but cannot create associated key"); } // -------------------------------------------------------------------------------- // Clone // -------------------------------------------------------------------------------- XSECAlgorithmHandler * XENCAlgorithmHandlerDefault::clone(void) const { XENCAlgorithmHandlerDefault * ret; XSECnew(ret, XENCAlgorithmHandlerDefault); return ret; } // -------------------------------------------------------------------------------- // Unsupported operations // -------------------------------------------------------------------------------- unsigned int XENCAlgorithmHandlerDefault::signToSafeBuffer( TXFMChain * inputBytes, const XMLCh * URI, XSECCryptoKey * key, unsigned int outputLength, safeBuffer & result) { throw XSECException(XSECException::AlgorithmMapperError, "XENCAlgorithmHandlerDefault - Signature operations not supported"); } bool XENCAlgorithmHandlerDefault::appendSignatureHashTxfm( TXFMChain * inputBytes, const XMLCh * URI, XSECCryptoKey * key) { throw XSECException(XSECException::AlgorithmMapperError, "XENCAlgorithmHandlerDefault - Signature operations not supported"); } bool XENCAlgorithmHandlerDefault::verifyBase64Signature( TXFMChain * inputBytes, const XMLCh * URI, const char * sig, unsigned int outputLength, XSECCryptoKey * key) { throw XSECException(XSECException::AlgorithmMapperError, "XENCAlgorithmHandlerDefault - Signature operations not supported"); } bool XENCAlgorithmHandlerDefault::appendHashTxfm( TXFMChain * inputBytes, const XMLCh * URI) { throw XSECException(XSECException::AlgorithmMapperError, "XENCAlgorithmHandlerDefault - Hash operations not supported"); }