in xsec/enc/OpenSSL/OpenSSLCryptoSymmetricKey.cpp [486:597]
unsigned int OpenSSLCryptoSymmetricKey::decryptFinish(unsigned char * plainBuf,
unsigned int maxOutLength) {
int outl = maxOutLength;
m_initialised = false;
#if defined (XSEC_OPENSSL_CANSET_PADDING)
if (EVP_DecryptFinal(mp_ctx, plainBuf, &outl) == 0) {
throw XSECCryptoException(XSECCryptoException::SymmetricError,
"OpenSSL:SymmetricKey - Error during OpenSSL decrypt finalisation");
}
if (outl > 0) {
// Should never see any bytes output, as we are not padding
throw XSECCryptoException(XSECCryptoException::SymmetricError,
"OpenSSL:SymmetricKey - Unexpectedly received bytes from EVP_DecryptFinal_ex");
}
// Calculate any padding issues
if (m_doPad && m_bytesInLastBlock == m_blockSize) {
outl = m_blockSize - m_lastBlock[m_blockSize - 1];
if (outl > m_blockSize || outl < 0) {
throw XSECCryptoException(XSECCryptoException::SymmetricError,
"OpenSSL:SymmetricKey::decryptFinish - Out of range padding value in final block");
}
memcpy(plainBuf, m_lastBlock, outl);
}
if ((unsigned int) outl > maxOutLength) {
throw XSECCryptoException(XSECCryptoException::SymmetricError,
"OpenSSLSymmetricKey::decryptFinish - **WARNING** - Plaintext output > maxOutLength!");
}
return outl;
#else
/* Working with a version of OpenSSL that *always* performs padding
so we need to work around it */
unsigned char *scrPlainBuf;
unsigned char *cipherBuf;
scrPlainBuf = new unsigned char[3 * m_blockSize];
ArrayJanitor<unsigned char> j_scrPlainBuf(scrPlainBuf);
cipherBuf = new unsigned char[m_blockSize];
ArrayJanitor<unsigned char> j_cipherBuf(cipherBuf);
/* Zeroise the cipher buffer */
memset(cipherBuf, 0, m_blockSize);
unsigned int offset = 0;
/* Get any previous bytes from the m_lastBlock */
if (m_bytesInLastBlock > 0 && m_bytesInLastBlock <= m_blockSize) {
memcpy(scrPlainBuf, m_lastBlock, m_bytesInLastBlock);
offset = m_bytesInLastBlock;
}
outl = m_blockSize;
/* This is really ugly - but we have to trick OpenSSL into thinking there
is more, so that it sends us the lasts block with the padding in it.
We can then clean that up ourselves
*/
if (EVP_DecryptUpdate(mp_ctx, &scrPlainBuf[offset], &outl, cipherBuf, m_blockSize) == 0) {
throw XSECCryptoException(XSECCryptoException::SymmetricError,
"OpenSSL:SymmetricKey - Error cecrypting final block during OpenSSL");
}
outl += offset;
if (m_doPad && outl > 0) {
/* Strip any padding */
outl -= scrPlainBuf[outl - 1];
if (outl > (2 * m_blockSize) || outl < 0) {
throw XSECCryptoException(XSECCryptoException::SymmetricError,
"OpenSSL:SymmetricKey::decryptFinish - Out of range padding value in final block");
}
}
if (outl > (int) maxOutLength) {
throw XSECCryptoException(XSECCryptoException::SymmetricError,
"OpenSSLSymmetricKey::decryptFinish - **WARNING** - Plaintext output > maxOutLength!");
}
if (outl > 0) {
memcpy(plainBuf, scrPlainBuf, outl);
}
return outl;
#endif
}