Hi,

while doing some changes to an application I stumbled on a segmentation
fault during RSA decode. The data to be decoded is too long (longer than RSA
key modulus) so it is invalid, but I do not think that it should cause a
crash.

Platform and versions are:
Linux x86 32bit
2.6.28-15-server #52-Ubuntu SMP Wed Sep 9 11:50:50 UTC 2009
gcc version 4.3.3 (Ubuntu 4.3.3-5ubuntu4)
Crypto++ 5.6.0

I have attached a patch to fix the segmentation fault as well as a demo
program and backtrace of the demo program crashing, memcpy with Null pointer
destination is the actual cause. With the patch we instead get an exception
due to invalid cipher text which is appropriate. I have not tested the
change to pkcspad.cpp but given the code similarity to oaep.cpp I think it
is the right thing to do.

Best regards,
Fredrik Estreen

-- 
You received this message because you are subscribed to the "Crypto++ Users" 
Google Group.
To unsubscribe, send an email to [email protected].
More information about Crypto++ and this group is available at 
http://www.cryptopp.com.
#include <string>
#include <iostream>
#include <crypto/pch.h>
#include <crypto/rng.h>
#include <crypto/default.h>
#include <crypto/hex.h>
#include <crypto/files.h>
#include <crypto/rsa.h>
#include <crypto/randpool.h>
#include <crypto/osrng.h>
#include <crypto/gzip.h>

/*
g++ -L./crypto/ -I./ test.cpp -lcryptopp

segmentation fault in OAEP_Base::Unpad() doing memcpy to NULL pointer
same issue probably exist in PKCS too.
*/

using namespace CryptoPP;
using namespace std;

int main(int argc, char* argv[])
{
        //Generate keys
        //string pubString, privString, result;
        string privString = 
"308204BB020100300D06092A864886F70D0101010500048204A5308204A10201000282010100C6DC6E373BDDD64A2BDA801BA8C518DBFD3771D9C53F7FFDEAF4491CA737CE25EEFD3D0E6D5FC51AB64CA7F7614A3BEC63EDEC3D7354AE1BCE123B1EF43B03D208911F6FA5BF67E08189DB25AE9927DB0F45BECF9743B6C617E572CC410D2F721F3C1337A9C067423797B46D222608A92B450EF3EEBBF21AC266FBE8B698EC3505162815393288A0DB4CDB7AB2CF55C1E490DA167D87065A875E47383311EC7A0310BC7AAD9ABC1523367A2AEBFC0C3810DF02B7C22D015998148B64C0A965575326301FCDF683F15225D328AA5A4D755965B51D2893381489D5E85552B4700C0D4062D278487E3B51E3A63641F447D6F82AA1FE5F2CDF3CC59C5C8EDDEA8CE50201110282010051E24B8027B5B29702FF9E2981BA91C3FEDA984A9C838F0E3391C3C08116FA88171CFB05F0CD14ECE1A717FC735ACD615652E8CE02500B74DC61DC1BCDFA2EBFE568EED39E9A1BB6CBED785ACF6C3D966FB34E91B6C1877EBE8BA7BD84329B10DFAF533509A993EE16E41D1DE0E27C096C2B7EA0AD98AEFBF5B1EF41B499523338639916966C52EBD162C7EF7F8BAF9D7DD7E77BA5E3AC33074A36B7B33115D2A736D74C96E69DBA7D226461C72C89BCC61E6BF7DC902A8A9C19E5C1ED3F1FFB10727009FD0F4B27E5C7C6D830B20E5A263D26EB7D1544E0D29F64C09A362FF60BC5CF82A2B910119CE9181D6EDD2141E2D597FA499C65CDD1BF9452DB429F4502818100F80CCFA89405EA462EEC712D0E32C6CCDFE7A582700D02DD0C985F924003617670ECA41719462AAB3E9CF3C59339F6993CB7A04372B8AB0171CAAF409FC1DBEE0019CE6108883830D4E71C448BBD0F18418A9955182C1826BB0562039ADB8E659B17C34A15C06B8C975F9B8ADE72982904007581FDB5FD89531538A7959F11DB02818100CD3C0935CA258BD4D47084BEDC9276BFAE784B8C5607F393D6C8875589050CDF69C37B3BDCB6C93746FCDBC10755EBAFCE6FC9F5CA16382C18E66504054E3BBE743F9ACB15B6DE5F98598AD7161164A6BAFD741E72EA5414F3DFB634D39E6D2C55915E6FB2C6A283F44DF4AD0D1F837BA8B5BB65AEB1EA767523971E0F3BF83F0281801D2EAF04C61ED0447DFDB2F63DE7DB2729668BF13A5BE2381F9974A7CB4BB11CFE39F52FE4DB1414257BE07198D9A48A7F9D21E9D142E6F11C7232BC4F07BF85696C72A20100F78D46394E9EA7072EF3CB79B7AFA87DA87D06F1930F7BA15C0BF420E9CC7B07942EA86599D41A2B996E3CB4C287C37ED288A05CD97D20A94D650281803C5CF3A668A1A198F330270AF5947D476F8CCAED0A3E92EF3F2BEB91A0C540057975BAD55F089588BA869AFC89AFDBE869E4A4CFD20688FDE934B44C7A07F374404EF14ACA26B9DFE183BF6C6FE6FF7C551D5E634EF9A04265D862C43E3DA7A3A0B248F3AD0D3EDB8416ED9C4F2762E8228FCDB47EACCC7D3182F036047B0CC702818100DAED16A1CD71D57512F10E865D037528BE21C20EC8C26850946A44B5AB1DB2CE9E3A4C8940C910170DAFEFC7BFDECA548FA81DD3FDB46B8CB67E9440F9638313B2F879288FCAAD56D18539145555CC05EE22A13EA481520AEC0643E0639C8F3E69DFE14A126FA4BB3C25FBAE002305A8206858F2BAF5CF9178CDAA70811E5722";
        string pubString = 
"30820120300D06092A864886F70D01010105000382010D00308201080282010100C6DC6E373BDDD64A2BDA801BA8C518DBFD3771D9C53F7FFDEAF4491CA737CE25EEFD3D0E6D5FC51AB64CA7F7614A3BEC63EDEC3D7354AE1BCE123B1EF43B03D208911F6FA5BF67E08189DB25AE9927DB0F45BECF9743B6C617E572CC410D2F721F3C1337A9C067423797B46D222608A92B450EF3EEBBF21AC266FBE8B698EC3505162815393288A0DB4CDB7AB2CF55C1E490DA167D87065A875E47383311EC7A0310BC7AAD9ABC1523367A2AEBFC0C3810DF02B7C22D015998148B64C0A965575326301FCDF683F15225D328AA5A4D755965B51D2893381489D5E85552B4700C0D4062D278487E3B51E3A63641F447D6F82AA1FE5F2CDF3CC59C5C8EDDEA8CE5020111";
        string trigger = 
"303e9b2cc3628dbc8c36869e3f03fa609943d4ee5a011efd62294eaff3baaaed7dc0b36b439b3de8bc164408fa48084e2478994134fdb655c69b288c4f7877dbde300cf9546a054c795e80dfc9e7a78833b93d2a46960485ec37519ead5f814ff08c5c36bcc75cb4e3c3cc0af57a30bbae446c0f7f2c67fdb6f667b484dfc40457c2804cf58cd72fe567f762bafc9c65a3e6ee32c0dbebec168add0bc584174453b19146c01f8bb0881a6aaa939a8bb99c10e9eb780c3d2cbcc69f0e4d7070aac14e7a49f57017ced3c9ac0e645fcdc02c501f2df94dc1c69349ee1e9aeddb1393e725a6e84ed85af526f02ce596227cc3f6f5e39f19d6bbc10472f06b1cce0a8ecf1afe10f49daf8284950c842d9ef42c6c24a17074b210b8351bac862bf35308001fe61dd5db757a39c740a3bdc692992fee4b3effff4dc29e4c9ce63f6ada6031bc04b4f939516a14812f7c3fcdd0722bb14f269182a8f9ef3fa6c22f58c09087f39d783c183fb818225fdfeb35c2750d342e81616515b3c771a877a10c76fd85db300bd0ebb84aa97cbd68623bc5deca399dcaa1204f23a3fd7d79ff43c907999185d3ea4eaaefdefa7cf4c3380af12e05bae40bdb13cdfa776c3f2bfa7169cd4c4e3fe60be7b3011e0cfe403e5522136a66c340710a56dd779aabfcc5e481276ad423c1f94114eafdfa1522680f2826612f054d7dc506f6b3a82d706da6";
        string result;
        
        // Decrypt trigger
        {
                StringSource privFile(privString, true, new HexDecoder);
                RSAES_OAEP_SHA_Decryptor priv(privFile);

                AutoSeededRandomPool randPool;

                StringSource(trigger, true, new HexDecoder(new 
PK_DecryptorFilter(randPool, priv, new StringSink(result))));
        }
        return 0;
}
Index: /trunk/crypto/oaep.cpp
===================================================================
--- /trunk/crypto/oaep.cpp (revision 9415)
+++ /trunk/crypto/oaep.cpp (revision 9650)
@@ -47,17 +47,17 @@
 	std::auto_ptr<MaskGeneratingFunction> pMGF(NewMGF());
 	pMGF->GenerateAndMask(*pHash, maskedDB, dbLen, maskedSeed, seedLen);
 	pMGF->GenerateAndMask(*pHash, maskedSeed, seedLen, maskedDB, dbLen);
 }
 
 DecodingResult OAEP_Base::Unpad(const byte *oaepBlock, size_t oaepBlockLen, byte *output, const NameValuePairs &parameters) const
 {
 	bool invalid = false;
-
+	invalid = (output == 0) || invalid;
 	// convert from bit length to byte length
 	if (oaepBlockLen % 8 != 0)
 	{
 		invalid = (oaepBlock[0] != 0) || invalid;
 		oaepBlock++;
 	}
 	oaepBlockLen /= 8;
Index: /trunk/crypto/pkcspad.cpp
===================================================================
--- /trunk/crypto/pkcspad.cpp (revision 9415)
+++ /trunk/crypto/pkcspad.cpp (revision 9650)
@@ -48,16 +48,17 @@
 
 	pkcsBlock[pkcsBlockLen-inputLen-1] = 0;     // separator
 	memcpy(pkcsBlock+pkcsBlockLen-inputLen, input, inputLen);
 }
 
 DecodingResult PKCS_EncryptionPaddingScheme::Unpad(const byte *pkcsBlock, size_t pkcsBlockLen, byte *output, const NameValuePairs &parameters) const
 {
 	bool invalid = false;
+	invalid = (output == 0) || invalid;
 	size_t maxOutputLen = MaxUnpaddedLength(pkcsBlockLen);
 
 	// convert from bit length to byte length
 	if (pkcsBlockLen % 8 != 0)
 	{
 		invalid = (pkcsBlock[0] != 0) || invalid;
 		pkcsBlock++;
 	}
#0  0xb7da48af in memcpy () from /lib/tls/i686/cmov/libc.so.6
#1  0x080e6a4c in CryptoPP::OAEP_Base::Unpad (this=0x8161f28, 
oaepBlock=0x81622a8 "", 
    oaepBlockLen=<value optimized out>, output=0x0, parameters=...) at 
/usr/include/bits/string3.h:52
#2  0x080e7e62 in CryptoPP::TF_DecryptorBase::Decrypt (this=0xbffff300, 
rng=..., 
    ciphertext=0x81625b8 
"0>\233,\303b\215\274\214\066\206\236?\003\372`\231C\324\356Z\001\036\375b)N\257\363\272\252\355}\300\263kC\233=\350\274\026D\b\372H\bN$x\231A4\375\266U?(\214Oxw\333\336\060\f\371Tj\005Ly^\200\337\311?3\271=*F\226\004\205\354\067Q\236\255_\201O\360\214\\6\274\307\\\264\343\303\314\n\365z0\273\256Dl\017\177,g\375\266\366g\264\204\337\304\004W\302\200L\365\214\327/\345g\367b\272\374\234e\243\346\356\062\300\333\353\354\026\212\335\v?\027DS\261\221F\300\037\213\260\210\032j\252\223\232\213\271\234\020\351\353x\f=,\274?\016Mpp\252\301NzI\365p\027",
 <incomplete sequence \316>..., ciphertextLength=512, plaintext=0x0, 
parameters=...) at pubkey.cpp:142
#3  0x08058e41 in CryptoPP::PK_DefaultDecryptionFilter::Put2(unsigned char 
const*, unsigned int, int, bool) ()
#4  0x0804a5cd in CryptoPP::BufferedTransformation::MessageEnd(int, bool) ()
#5  0x0804aa54 in CryptoPP::SimpleProxyFilter::LastPut(unsigned char const*, 
unsigned int) ()
#6  0x080a41bc in CryptoPP::FilterWithBufferedInput::PutMaybeModifiable 
(this=0x8161238, 
    inString=0x8161b68 "\246\261\350\267x\261\350\267\020", length=0, 
messageEnd=-2, blocking=true, modifiable=false)
    at filters.cpp:408
#7  0x08050464 in CryptoPP::FilterWithBufferedInput::Put2(unsigned char const*, 
unsigned int, int, bool) ()
#8  0x080567a6 in CryptoPP::BufferedTransformation::ChannelPut2 
(this=0x8161238, channel=..., 
    begin=0x8161b68 "\246\261\350\267x\261\350\267\020", length=0, 
messageEnd=-2, blocking=<value optimized out>)
    at cryptlib.cpp:350
#9  0x0809f1ec in CryptoPP::Filter::Output (this=0x81619e8, outputSite=2, 
    inString=0x8161b68 "\246\261\350\267x\261\350\267\020", length=0, 
messageEnd=-2, blocking=<value optimized out>, 
    channel=...) at filters.cpp:115
---Type <return> to continue, or q <return> to quit---
#10 0x08051e3d in CryptoPP::BaseN_Decoder::Put2 (this=0x81619e8, begin=0x0, 
length=0, messageEnd=-1, 
    blocking=<value optimized out>) at basecode.cpp:163
#11 0x080567a6 in CryptoPP::BufferedTransformation::ChannelPut2 
(this=0x81619e8, channel=..., begin=0x0, length=0, 
    messageEnd=-1, blocking=<value optimized out>) at cryptlib.cpp:350
#12 0x08053fd9 in CryptoPP::BufferedTransformation::ChannelMessageEnd 
(this=0xbffff404, target=..., 
    messagecou...@0xbffff1f4, channel=..., blocking=true) at cryptlib.h:998
#13 CryptoPP::BufferedTransformation::TransferMessagesTo2 (this=0xbffff404, 
target=..., messagecou...@0xbffff1f4, 
    channel=..., blocking=true) at cryptlib.cpp:507
#14 0x08054178 in CryptoPP::BufferedTransformation::TransferAllTo2 
(this=0xbffff404, target=..., channel=..., 
    blocking=true) at cryptlib.cpp:548
#15 0x0805104b in 
CryptoPP::SourceTemplate<CryptoPP::StringStore>::PumpAll2(bool) ()
#16 0x0804a822 in CryptoPP::Source::PumpAll() ()
#17 0x0804a85a in CryptoPP::Source::SourceInitialize(bool, 
CryptoPP::NameValuePairs const&) ()
#18 0x080515ec in CryptoPP::StringSource::StringSource(std::string const&, 
bool, CryptoPP::BufferedTransformation*) ()
#19 0x0804a297 in main ()

Reply via email to