Decrypt SSL traffic with the openssl command line tool - continued part 3

From my previous questions/thread starting part 1 and follow up part 2 following my guided explanation since my files/data I am capturing is binary in nature I used the following openssl commands where I began with my premaster secret derived from:

openssl rsautl -in cpre.key -inkey key.pem -decrypt -out spre.key

This created my 48 byte server pre master secret file spre.key (I think is correct) and in decimal for (viewing using bed) as:

003 003 203 048 063 215 047 196 221 221 221 014 019 072 011 100 217 080 111 073 217 026 234 082 022 217 232 025 096 063 115 080 016 094 015 170 148 126 092 118 109 228 246 149 208 195 044 220

Hex: 0303CB303FD72FC4DDDDDD0E13480B64D9506F49D91AEA5216D9E819603F7350105E0FAA947E5C766DE4F695D0C32CDC

And concatenating the literal "master secret" + client.random + server.random I created mseed.key and again viewing with bed the same way as decimal I created:

109 097 115 116 101 114 032 115 101 099 114 101 116 173 212 147 215 014 129 225 102 157 027 001 125 167 097 014 085 064 025 114 025 024 248 096 254 044 235 151 130 033 151 015 133 251 114 232 095 213 076 194 057 175 106 225 088 206 069 187 050 168 031 217 080 198 061 180 043

Hex: 6D617374657220736563726574ADD493D70E81E1669D1B017DA7610E554019721918F860FE2CEB978221970F85FB72E85FD54CC239AF6AE158CE45BB32A81FD950C63DB42B
for a total of 69 bytes

Next I put that together and since I was advised that the data being in binary files I used the following to generate the master secret and keys.

openssl dgst -sha256 -hmac spre.key <mseed.key -binary >a1
openssl dgst -sha256 -hmac spre.key <a1 -binary >a2
openssl dgst -sha256 -hmac spre.key <a2 -binary >a3
openssl dgst -sha256 -hmac spre.key <a3 -binary >a4

This created 4 32 byte files.

followed up by creating the keys with:

cat a1 mseed.key | openssl dgst -sha256 -hmac spre.key -binary >k1
cat a2 mseed.key | openssl dgst -sha256 -hmac spre.key -binary >k2
cat a3 mseed.key | openssl dgst -sha256 -hmac spre.key -binary >k3
cat 42 mseed.key | openssl dgst -sha256 -hmac spre.key -binary >k4

This created 4 32 byte files.

Following along with the examples I was given and reading the RFC as I understand it the master key at this point would be the first 48 bytes of a1+a2 is that correct or did I miss something? Since I'm not actually able to see what the master_secret PRF returns or is doing I think from running the command line as above that is how I would get the master secret. Thanks David


Solution 1:

First, your mseed file (the label+seed value in the PRF) should be 77 bytes, not 69. You must have messed up the client and/or server nonces somehow.

Second, -hmac spre.key is badly wrong. It uses the actual characters s p r e . k e y i.e. the octets 73 70 72 65 2e 6b 65 79 as the HMAC key. You need to use the value of the decrypted premaster secret, which is the contents of your spre.key file. And because that is binary data that can include bytes which are special character codes like null, tab, dollarsign, quote, backslash, delete, etc. you can't safely pass it directly, as -hmac {key} or even -hmac '{key}'; instead you need to use -mac hmac -macopt hexkey:{hex key value} as I showed in the previous answer, except using the actual hex key value you showed in this Q namely 0303CB30...2CDC.

Third, as I showed in the previous answer, you concatenate the results of the second layer of HMACs i.e. in my notation k1,k2,... to form the output (which in that example was 100 octets):

$ cat k1 k2 k3 k4 | head -c100 | xxd

but as I went on to say:

... for the actual TLS1.2 handshake also, adjusted for the correct lengths: 48 for the master secret, and depending on the ciphersuite for the working keys.

For the first (premaster-to-master) derivation you need 48 octets, so you only need the first two chunks of 32 (a0->a1->a2 a1+a0->k1 a2+a0->k2) then concatenate k1+k2 and take the first 48 octets.

For the second (master-to-working) derivation the length you need depends on the ciphersuite that was negotiated. You said you are using RSA-with-AES256CBC-SHA which (in TLS1.2, or 1.1 but not 1.0) needs 40 octets of HMAC keys and 64 octets of encryption keys totalling 104 octets. For 104 ocets you need to compute 4 chunks of 32, concatenate k1+k2+k3+k4, and parcel it out to client-MAC, server-MAC, client-encryption, server-encryption in that order. See 6.3 of the RFC. Also note that the label is different, and for this derivation the seed is (label+)server_random+client_random, not (label+)client_random+server_random as in the first one.