From my previous posts part 1, part 2, part 3 and part 4 I believe I have calculated/decrypted everything correctly and ready to attempt to decrypt the client encrypted handshake message. I'm stuck on the next step once I have all the keys. I've been reading and researching this for a couple days and just plain stuck.

Following the guidelines from my previous posts I have come up with

20 bytes for a client MAC key: 64666eafe1cbd51f2e2b50799b40f6007c3dc56f
20 bytes for a server MAC key: e0aac1312d35b5e8b6bf9af6ecf07e1dff27c784
32 bytes client encryption key:
32 bytes for a server encryption key:

My encrypted client handshake message:

Hex.       FILE SIZE: 40
 ADDRESS   000 001 002 003 004 005 006 007       ASCII
00000000   09A 01B 0F3 06B 078 06C 03B 059      ~Z  ^[  -s   k   x   l   ;   Y
00000008   085 061 07C 076 0AF 0D9 085 0D6      ~E   a   |   v  -/  -Y  ~E  -V
00000010   08F 0FD 0AF 06D 09F 01A 025 0EF      ~O  -}  -/   m  ~_  ^Z   %  -o
00000018   040 015 097 002 0B5 0AD 0EF 040       @  ^U  ~W  ^B  -5  --  -o   @
00000020   02B 0DB 051 096 0CE 076 0A9 03F       +  -[   Q  ~V  -N   v  -)   ?
00000028   0D7 030 049 03A 0CC 0F9 029 044      -W   0   I   :  -L  -y   )   D
00000030   07F 0A9 0C6 0F1 017 02D 06B 040      ^?  -)  -F  -q  ^W   -   k   @
00000038   035 0F5 057 08E 0BF 0E9 05C 06D       5  -u   W  ~N  -?  -i   \   m

I believe I need to use a variation of openssl end -d -K but stumbling around here between the RFC and google to find a solution/example that clearly explains it. Does anyone know how/if I can do this at the command line in openssl? Thanks

Update. I am not sure why/how I overlooked in the RFC 7.4.9 PRF(master_secret, finished_label, Hash(handshake_messages)) I do have logged all the handshake messages can someone explain how I can simulate this with just openssl command line with the data I have captured/decrypted to this point.? It looks like the hash of the handshake messages is what I need to perform prior to this RFC section 5 I am assuming that I am going to use the master_secret I generated I am not sure what the seed for this should be using the openssl the way I have been previously using it. I don't see that for this hash there is a label concatenated so do I just use all the handshake messages to this point concatenated together? There are many steps I am getting lost where I am at. Thanks

openssl dgst -sha256 -mac hmac -macopt hexkey:$key <seed -binary >a1

I'm intrigued that you seem to use a new file-dump format each time you post :-)

Assuming you are as before using (RSA-with-)AES256CBC-(HMAC)SHA1: yes, you can decrypt TLS CBC ciphers with openssl enc, except for ARIA. (Also RC4, although you should avoid using RC4 for any purpose including TLS. OTOH enc can't do any AEAD ciphers: not GCM or CCM, and not ChaCha/Poly.) The record format in TLS1.2 (and 1.1) for a CBC cipher is covered in RFC5246 section For AES, the first 16 octets are the IV and the remainder are the ciphertext, which should decrypt to the plaintext record body (in this case the Finished message) plus HMAC plus padding -- but TLS padding is not the same as the PKCS5/7 padding supported by enc (and internally by the EVP_{??crypt,Cipher}* API), so you need to do that part yourself.

As described in its man page on your system or on the web, and quite a few questions on several Stacks (although most I have noted are about matching commandline to other code like Java and python etc. not to a spec), openssl enc defaults to password-based encryption (PBE) which is not what you want here. To do 'key-based' decryption, you need to specify -d, -K (uppercase not lowercase) with the key in hex, and -iv with the IV in hex if used by the cipher (AES-CBC does):

$ echo $key; echo $iv
$ sed 1,2d <1346633.dat
$ sed 1,2d <1346633.dat |xxd -p -r |openssl aes-256-cbc -d -K $key -iv $iv -nopad |xxd
0000000: f730 34cc b90f b0b0 6313 9a0f 239c 6e87  .04.....c...#.n.
0000010: 187f ff00 52d1 3e9c 2aef d5cd c07e 15be  ....R.>.*....~..
0000020: dee0 aa95 6994 5ce6 768d 1952 ac00 17ba  ....i.\.v..R....

Unfortunately, as you can see, this decryption is invalid: it doesn't end with TLS-style padding, and it doesn't begin with a Finished message, which is what the first post-CCS transmission by the client must be. Either your derived key is wrong, or your dump of this record is.

One suggestion that might help: make a connection using (edit) openssl s_client -debug and log its output to a file. This dumps all the records in hex (and ASCII) which you can use as data for or to verify the various inputs (including the encrypted record containing Finished), AND the 'SSL-Session' block at the end includes the correct value of the master secret which you can use as a cross-check. You can add -msg to also get dump the encrypted messages; this is bulkier but a bit more convenient and is what I did below. Another possibility, a little more work to setup, is to connect from a Java SSL/TLS (JSSE) client program run with sysprop javax.net.debug=ssl and log; that dumps lots of info including the master secret and working keys.

As an example of how this should work, I went through the procedure on a logged sample session (which I actually created on your first Q a few weeks ago), doing by hand the master and working derivations and decrypting and verifying the client's Finished message:

$ cat tempc
2f e9 97 3e e4 11 89 81 c5 bc 18   11 7b c9 e9 3d
64 cb 88 6e a4 ac f2 01 95 05 d7
fe 3d 09 f4 13 4a d7 39 77 bf 50 dc f4 7b 9b b8
3c 0b 2f bf 98 5a 9c 4c 2d 28 6c 6a b6 93 a9 29
c5 5f f1 a3 cd
$ # this is the hexdump of from s_client -debug, cleaned up 
$ echo $key; echo $iv
$ # you can see the IV is the first line (16 bytes) of tempc
$ sed 1d tempc |xxd -p -r |openssl aes-256-cbc -d -K $key -iv $iv -nopad |tee tempc! |xxd
0000000: 1400 000c 5bbc 39d8 6c5d dbb1 076b b91b  ....[.9.l]...k..
0000010: 9f4e 5c55 fd9e a185 6901 4bc0 6f02 2c0d  .N\U....i.K.o.,.
0000020: 5bb0 d8c9 0b0b 0b0b 0b0b 0b0b 0b0b 0b0b  [...............
$ # those last 12 bytes are SSL/TLS-style padding 
$ # the first 4 bytes are a handshake message header for x14=Finished,
$ # followed by the 12 byte verify_data value, total 16 bytes 
$ echo $mkey
$ { printf '\0\0\0\0\0\0\0\0\x16\x03\x03\0\x10'; head -c16 tempc! ; } \
> |openssl sha1 -mac hmac -macopt hexkey:$mkey -binary |xxd -p 
$ # the 20 bytes after the 16-byte message and before the padding 
$ # correctly match HMAC-SHA1 of the pseudoheader plus the message

As to the 'verify_data' in the Finished message, yes you need to take the hash of all of the prior handshake messages as described in 7.4.9 (in TLS1.3 this is named a 'transcript' hash) and then the PRF (as discussed in previous posts) where the key is the master secret and the seed is the fixed label 'client finished' or 'server finished' (as applicable) plus that transcript hash. That is a good deal more work and I didn't do it for the example, although I probably can if necessary.

  • Dave, Thanks... since I am not sure what step in my shell script may be wrong deriving the key. I posted my first step here. Can you take a look and see if I've perhaps not captured my client encrypted premaster correctly. That is the only thing I can think of I may have done wrong. Comparing what I see In wireshark and the file I created byte for byte they are exact so I don't think my first ste is wrong. here is the data including my private key.
    – David B
    Aug 8 '18 at 13:26
  • p.s. I followed your outline to a "t" first using the data you gave in the example for $key and $lbsd to make sure I got exactly the same outcome and I did. My shell script is based on most of that with the exception of a couple of things. Then expand that to the keys.
    – David B
    Aug 8 '18 at 18:06

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.