[openssl-dev] [openssl.org #4429] Cannot decrypt RC4-encrypted CMS object

Viktor Dukhovni openssl-users at dukhovni.org
Tue Mar 15 07:47:17 UTC 2016

On Tue, Mar 15, 2016 at 06:33:32AM +0000, Viktor Dukhovni wrote:

> This is completely untested, may not even compile!  Enjoy.

It does seem to work, so one key remaining questions is whether it
is interoperable:

    $ ./util/shlib_wrap.sh ./apps/openssl req -config apps/openssl.cnf -new -x509 -newkey rsa:2048 -keyout key.pem -nodes -out cert.pem -days 100 -subj "/CN=RC4 CMS Test"
    <copious output>
    $ ./util/shlib_wrap.sh ./apps/openssl x509 -in cert.pem -noout -serial
    $ echo sesame > data.txt
    $ ./util/shlib_wrap.sh ./apps/openssl cms -rc4 -encrypt -binary -in data.txt -out data.txt.cms -outform DER cert.pem
    $ ./util/shlib_wrap.sh ./apps/openssl cms -decrypt -in data.txt.cms -inform DER -out data2.txt -inkey key.pem -recip cert.pem
    $ diff -u data.txt data2.txt
    <no output>
    $ openssl asn1parse -inform DER -in data.txt.cms
	0:d=0  hl=4 l= 380 cons: SEQUENCE
	4:d=1  hl=2 l=   9 prim: OBJECT            :pkcs7-envelopedData
       15:d=1  hl=4 l= 365 cons: cont [ 0 ]
       19:d=2  hl=4 l= 361 cons: SEQUENCE
       23:d=3  hl=2 l=   1 prim: INTEGER           :00
       26:d=3  hl=4 l= 320 cons: SET
       30:d=4  hl=4 l= 316 cons: SEQUENCE
       34:d=5  hl=2 l=   1 prim: INTEGER           :00
       37:d=5  hl=2 l=  36 cons: SEQUENCE
       39:d=6  hl=2 l=  23 cons: SEQUENCE
       41:d=7  hl=2 l=  21 cons: SET
       43:d=8  hl=2 l=  19 cons: SEQUENCE
       45:d=9  hl=2 l=   3 prim: OBJECT            :commonName
       50:d=9  hl=2 l=  12 prim: UTF8STRING        :RC4 CMS Test
       64:d=6  hl=2 l=   9 prim: INTEGER           :ACD5DEDE758B9AA6
       75:d=5  hl=2 l=  13 cons: SEQUENCE
       77:d=6  hl=2 l=   9 prim: OBJECT            :rsaEncryption
       88:d=6  hl=2 l=   0 prim: NULL
       90:d=5  hl=4 l= 256 prim: OCTET STRING      [HEX DUMP]:70BD8B31ACD24F8184A54AF52446D10898DC09E4636456B8E14B3073701CAD5226C0AA03C0AD45B7056DB0A10F01487DC4DE0D35FDE7291875D665DEBB76049C6D660C885A011949A051874DF0CCEA181F9D60BC6BB8BD989B69900E917CCE170F60A34DC77A0EEFB935E13578F3AC9703AE02D972F853DBB3302BEB28F1F8E54964E7528E9E24EEA6950535EF2D1027C31CCAEB1FAB8F454ADBEB1DB9FD2A0F61F276498E64931483FDD40E90DD956BF991C3524C9EDA70211A256BEEFED941474B26ED7A4516873A12240C505813B6BD6EDFE6ED367FEAC86AEC2602A8E1C0C5ACE9C2745FA1B6702F1550FD1ECE322CD7F165DA621E984F1186CA981829AE
      350:d=3  hl=2 l=  32 cons: SEQUENCE
      352:d=4  hl=2 l=   9 prim: OBJECT            :pkcs7-data
      363:d=4  hl=2 l=  10 cons: SEQUENCE
      365:d=5  hl=2 l=   8 prim: OBJECT            :rc4
      375:d=4  hl=2 l=   7 prim: cont [ 0 ]
    $ tail -c8 data.txt.cms | od -tx1
    0000000   07  c3  e2  69  a0  ab  3b  ec

That said, stream ciphers with unsigned CMS are especially unsafe.
Since the payload has no MAC or padding of any kind, it is trivial
to XOR any desired mask into the received plaintext:

    $ < data.txt.cms perl -e '
	($a, $b) = map { unpack("Q", "0$_\n") } qw(sesame unsafe);
	$/ = undef; $cms = <STDIN>;
	substr($cms, -8) = pack("Q", unpack("Q", substr($cms, -8)) ^ $a ^ $b);
	print $cms' > data.txt.cms2
    $ ./util/shlib_wrap.sh ./apps/openssl cms -decrypt -in data.txt.cms2 -inform DER -out data3.txt -inkey key.pem -recip cert.pem
    $ cat data3.txt

In the above example, a ciphertext-only transformation changes
'sesame' to 'unsafe'.  That, plus RC4's biases, make it unwise in
this context.  At the very least the CMS message MUST be signed,
and the first 256 bytes should not contain sensitive and yet
frequently transmitted content.

Don't let your children play with RC4 in CMS.

Of course, unsigned CMS payloads are also vulnerable to silent
corruption even with block ciphers in CBC mode, XOR of a mask into
a ciphertext block randomizes the plaintext of that block, but
makes a predictable change in the plaintext of the next block.

So, don't expect data integrity from unsigned CMS.


More information about the openssl-dev mailing list