size_t Put2(const byte *inString, size_t length, int messageEnd, bool blocking) { FILTER_BEGIN; m_ciphertextQueue.Put(inString, length); if (messageEnd) { { size_t ciphertextLength; if (!SafeConvert(m_ciphertextQueue.CurrentSize(), ciphertextLength)) throw InvalidArgument("PK_DefaultDecryptionFilter: ciphertext too long"); size_t maxPlaintextLength = m_decryptor.MaxPlaintextLength(ciphertextLength); SecByteBlock ciphertext(ciphertextLength); m_ciphertextQueue.Get(ciphertext, ciphertextLength); m_plaintext.resize(maxPlaintextLength); m_result = m_decryptor.Decrypt(m_rng, ciphertext, ciphertextLength, m_plaintext, m_parameters); if (!m_result.isValidCoding) throw InvalidCiphertext(m_decryptor.AlgorithmName() + ": invalid ciphertext"); } FILTER_OUTPUT(1, m_plaintext, m_result.messageLength, messageEnd); } FILTER_END_NO_MESSAGE_END; }
unsigned int Put2(const byte *inString, unsigned int length, int messageEnd, bool blocking) { FILTER_BEGIN; m_ciphertextQueue.Put(inString, length); if (messageEnd) { { unsigned int ciphertextLength = m_ciphertextQueue.CurrentSize(); unsigned int maxPlaintextLength = m_decryptor.MaxPlaintextLength(ciphertextLength); SecByteBlock ciphertext(ciphertextLength); m_ciphertextQueue.Get(ciphertext, ciphertextLength); m_plaintext.resize(maxPlaintextLength); m_result = m_decryptor.Decrypt(m_rng, ciphertext, ciphertextLength, m_plaintext, m_parameters); if (!m_result.isValidCoding) throw InvalidCiphertext(m_decryptor.AlgorithmName() + ": invalid ciphertext"); } FILTER_OUTPUT(1, m_plaintext, m_result.messageLength, messageEnd); } FILTER_END_NO_MESSAGE_END; }
bool IsolatedMessageEnd(bool blocking) { switch (m_continueAt) { case 0: { unsigned int ciphertextLength = m_inQueue.CurrentSize(); unsigned int maxPlaintextLength = m_decryptor.MaxPlaintextLength(ciphertextLength); SecByteBlock ciphertext(ciphertextLength); m_inQueue.Get(ciphertext, ciphertextLength); m_plaintext.resize(maxPlaintextLength); m_result = m_decryptor.Decrypt(ciphertext, ciphertextLength, m_plaintext); if (!m_result.isValidCoding) throw InvalidCiphertext(m_decryptor.AlgorithmName() + ": invalid ciphertext"); } case 1: if (!Output(1, m_plaintext, m_result.messageLength, 0, blocking)) return false; } return true; }
void StreamTransformationFilter::LastPut(const byte *inString, size_t length) { byte *space = NULL; switch (m_padding) { case NO_PADDING: case ZEROS_PADDING: if (length > 0) { size_t minLastBlockSize = m_cipher.MinLastBlockSize(); bool isForwardTransformation = m_cipher.IsForwardTransformation(); if (isForwardTransformation && m_padding == ZEROS_PADDING && (minLastBlockSize == 0 || length < minLastBlockSize)) { // do padding size_t blockSize = STDMAX(minLastBlockSize, (size_t)m_cipher.MandatoryBlockSize()); space = HelpCreatePutSpace(*AttachedTransformation(), DEFAULT_CHANNEL, blockSize); if (inString) {memcpy(space, inString, length);} memset(space + length, 0, blockSize - length); m_cipher.ProcessLastBlock(space, space, blockSize); AttachedTransformation()->Put(space, blockSize); } else { if (minLastBlockSize == 0) { if (isForwardTransformation) throw InvalidDataFormat("StreamTransformationFilter: plaintext length is not a multiple of block size and NO_PADDING is specified"); else throw InvalidCiphertext("StreamTransformationFilter: ciphertext length is not a multiple of block size"); } space = HelpCreatePutSpace(*AttachedTransformation(), DEFAULT_CHANNEL, length, m_optimalBufferSize); m_cipher.ProcessLastBlock(space, inString, length); AttachedTransformation()->Put(space, length); } } break; case PKCS_PADDING: case ONE_AND_ZEROS_PADDING: unsigned int s; s = m_cipher.MandatoryBlockSize(); assert(s > 1); space = HelpCreatePutSpace(*AttachedTransformation(), DEFAULT_CHANNEL, s, m_optimalBufferSize); if (m_cipher.IsForwardTransformation()) { assert(length < s); if (inString) {memcpy(space, inString, length);} if (m_padding == PKCS_PADDING) { assert(s < 256); byte pad = byte(s-length); memset(space+length, pad, s-length); } else { space[length] = 0x80; memset(space+length+1, 0, s-length-1); } m_cipher.ProcessData(space, space, s); AttachedTransformation()->Put(space, s); } else { if (length != s) throw InvalidCiphertext("StreamTransformationFilter: ciphertext length is not a multiple of block size"); m_cipher.ProcessData(space, inString, s); if (m_padding == PKCS_PADDING) { byte pad = space[s-1]; if (pad < 1 || pad > s || std::find_if(space+s-pad, space+s, std::bind2nd(std::not_equal_to<byte>(), pad)) != space+s) throw InvalidCiphertext("StreamTransformationFilter: invalid PKCS #7 block padding found"); length = s-pad; } else { while (length > 1 && space[length-1] == 0) --length; if (space[--length] != 0x80) throw InvalidCiphertext("StreamTransformationFilter: invalid ones-and-zeros padding found"); } AttachedTransformation()->Put(space, length); } break; default: assert(false); } }