cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
Highlighted
Observer
Observer
5,100 Views
Registered: ‎09-09-2016

Decrypt (or encrypt) serie 7 bitstream : help

Jump to solution

Hi, I would like to decrypt a serie 7 bitstream to make coherency check in firmware diffusion tool. In particular I need to check USERCODE and WBSTART for good version identification and flash location (update and not golden location).

I have to way to do it : get an uncrypted bit/bin file, read write register values and then crypt it before diffusion. The other way is to take a crypted one, decrypt and read write register values before send it.

Anyway I need to encrypt or decrypt bitstream. I prefer to decrypt it as I prefer to trust Xilinx generated bin/bit files.

 

I read several topics about serie 7 and serie 6 that seems to same crypting way. I read manuals, application notes and topics of forum in particular this one https://forums.xilinx.com/t5/Design-Tools-Others/Is-it-possible-to-encrypt-an-existing-bit-file/m-p/723252#M9058 . I saw several posts of people arriving to my point but never ahead :

It is stated that Xilinx is using AES256-CBC as describe in FIPS document. Encrypted part is after DWC. I never succeed to decrypt flow.

 

This is in detail the simplest example I’ve tested. I don’t think I violate any restriction in this post as these information are available on the Net and provided by XIlinx.

I make a dummy project with just a fixed output on an Artix7. Properties HKEY, KEY0 and STARTCBC are fixed to all zero (no problem of bytes or bits swapping). The property COMPRESS this set to True but that just change total size of bitstream, will still could see Type1 packets.

set_property BITSTREAM.ENCRYPTION.HKEY 256'h0000000000000000000000000000000000000000000000000000000000000000 [current_design]
set_property BITSTREAM.ENCRYPTION.KEY0 256'h0000000000000000000000000000000000000000000000000000000000000000 [current_design]
set_property BITSTREAM.ENCRYPTION.STARTCBC 128'h00000000000000000000000000000000 [current_design]
set_property BITSTREAM.ENCRYPTION.ENCRYPT YES [current_design]
set_property BITSTREAM.GENERAL.COMPRESS TRUE [current_design]

This is an extract of the resulting bitstream commented using Serie 7 configuration guide and figure provided in this topic :

0000000: ffffffff

Skipped dummy bytes and synchronization

Start of packets

0000034: 20000000

0000038: 3003e001

Skipped NOP and AES with BBRAM KEY

0000098: 20000000

STARTCBC : all null

000009c: 30016004

00000a0: 00000000

00000a4: 00000000

00000a8: 00000000

00000ac: 00000000

DWC Decrypt Word Count 'hA438 words that is 'h290E0 bytes

00000b0: 30034001

00000b4: 0000a438

Should be start of crypted bitstream to decode with AES256-CBC, IV=128'0, KEY0=256'0

Figure in topic indicate that first words are HKEY (in blue same in downward C source)

00000b8: d14f37c5

00000bc: 3d649c6c

00000c0: e3a03cb7

00000c4: 886a5d5e

00000c8: a468ba29

00000cc: 50431041

00000d0: 0a0fac5a

00000d4: 1f111961

00000d8: 98870adc

00000dc: c7e575a9

00000e0: b5d7153e

00000e4: b76d692f

00000e8: bb6a8392

00000ec: 64465c2e

00000f0: 80219c1d

00000f4: f2296795

00000f8: 8e793b22

00000fc: e1c8084b

0000100: 1b124367

0000104: cdbd6078

...

skipped crypted bytes

...

0029180: a369ca6d

0029184: 7022854c

0029188: 6adb971f

002918c: 5ea2cc36

0029190: 6ddff4f8

0029194: 507c637a

End of crypted bitstream A438 words later

0029198: 20000000

NOPs until the end

 

Now if I apply an AES256-CBC decrypt to the firsts bytes with a CBC all nulls and a KEY of 256b of nulls. The AES decryptor have been tested with the example for AES256 in the FIPS reference document

 

>>>>cat ec.cc

#include <assert.h>

#include <stdio.h>

#include <string.h>

#include <openssl/aes.h>

main()

{

   AES_KEY key; // AES internal key context

   unsigned char pkey[32]; // Key value : KEY0

   unsigned char iv[16];       // Initial Vector : STARTCBC

 

   memset(pkey, 0x00, sizeof(pkey)); // KEY0: all nulls

   memset(iv, 0x00, sizeof(iv));   // STARTCBC: all nulls

   // Start of crypted bitstream just after length in DWC : 5 block of AES

   unsigned char in[5*16] = {

0xd1,0x4f,0x37,0xc5,0x3d,0x64,0x9c,0x6c,0xe3,0xa0,0x3c,0xb7,0x88,0x6a,0x5d,0x5e,0xa4,0x68,0xba,0x29,0x50,0x43,0x10,0x41,0x0a,0x0f,0xac,0x5a,0x1f,0x11,0x19,0x61,0x98,0x87,0x0a,0xdc,0xc7,0xe5,0x75,0xa9,0xb5,0xd7,0x15,0x3e,0xb7,0x6d,0x69,0x2f,0xbb,0x6a,0x83,0x92,0x64,0x46,0x5c,0x2e,0x80,0x21,0x9c,0x1d,0xf2,0x29,0x67,0x95,0x8e,0x79,0x3b,0x22,0xe1,0xc8,0x08,0x4b,0x1b,0x12,0x43,0x67,0xcd,0xbd,0x60,0x78};

   unsigned char out[5*16];   // Result

 

   // Initialize AES256 context with the key

   assert(AES_set_decrypt_key(pkey, sizeof(pkey)*8, &key)==0);

  // decrypt

   AES_cbc_encrypt(in, out, sizeof(in), &key, iv, AES_DECRYPT);

 // Print

   for (int i = 0; i < sizeof(out); ++i)

         printf("%02x ", out[i]);

   printf("\n");

}

 

The result is :

35 3e 38 a1 7b 89 58 7c b4 3c 5d c5 a9 8a eb 57 71 92 22 09 dc cb a2 a7 05 b2 d8 03 89 2a 49 6c 00 d7 96 2e ad 0b af 20 0f 9c 63 e5 c6 c3 5a e1 54 23 52 30 63 0e ac 0f 55 2d 67 40 99 e1 9b 60 0a d3 af fb 95 cd 17 51 75 10 47 63 de 05 bc 48

 

HKEY is 8 words length. May be there is a Write Register packet just before... Here there is nothings looking like the nulls of HKEY nor Type1 or Type2 packets…

Then there is something I missing to decrypt MY bitstream but what ??

Please help.  I don't do it by pleasure to decrypt but for a firmware quality chain requirement

Regards

0 Kudos
1 Solution

Accepted Solutions
Highlighted
Observer
Observer
8,507 Views
Registered: ‎09-09-2016

Ok then the quick answer is bits swapping and bytes swapping  on 32b word.

 

To be clear what I done is not an attack to security but how to use Xilinx stated description and use my keys and my bitstream  : I do not make any tampers.

I do not nor make a reverse engineering on bitstream to fully understand the HMAC implementation as all I want is to decrypt it when it still could be trusted. No need for me to check or generate the MAC with HMAC.

 

An imortant point is that I use the .bit file bitstream ( or .bin for QSPI flash, may be not in same endian for BPI and others).

To my point of view Xilinx doesn't fully follow FIPS document in way it doesn't follow bit ordering and byte ordering indicated in document (in .bit).

For developers to use standard AES256 crypto libraries the bitsteam must be bit swapped 32b words by 32b word ( todecrypt[31:0] <= bitstream[0:31] ) before decrypt and after decrypt.

Keyfile.nky keys byte array must be byte swapped and bit swapped !

I think it's the same for the CBC IV but i'm not concerned about as that only concern the first AES256 decoded bloc that is part of HMAC key and that I don't check.

 

I expect that will help .

 

 

 

View solution in original post

0 Kudos
6 Replies
Highlighted
Scholar
Scholar
5,089 Views
Registered: ‎02-27-2008

s-,

 

Why do you not use a secure hash for authentication?  That way you completely avoid encrypting and decrypting (which creates a back door opportunity or vulnerability?

 

Contact your Xilinx or distributor FAE for assistance in seeing how we use the AES-CBC.  Getting one bit (byte) wrong will result in garbage (as you have discovered).

 

http://ieeexplore.ieee.org/stamp/stamp.jsp?arnumber=6849432

Austin Lesea
Principal Engineer
Xilinx San Jose
0 Kudos
Highlighted
Observer
Observer
5,080 Views
Registered: ‎09-09-2016
Thanks Austin for the reply.
The USERCODE contains the hardware and software version to know if the firmware is compatible with hardware and newer. The bitstream is not decoded by the flashing tool but by a prepare software that encapsulate bin with required information for flashing.

Anyway after one week I swap to the good way and now I have some coherent values (HMAC ) and I am very close to the solution.

Can I share on the forum the critical point I discovered in AES256-CBC use without problems from Xilinx ? I don't want to violate restrictions.
Regards
0 Kudos
Highlighted
Scholar
Scholar
5,056 Views
Registered: ‎02-27-2008

s-

 

Absolutely!  The security is in the choice of standards, not in any peculiar or odd behavior.

 

Sharing what you did to solve your problem is what these forums are all about.

 

I am curious what the problem was, and how you solved it.

 

Thank you for asking.  Generally, Xilinx is friendly to research and academia:  the more who try to break it, the more we learn.  All I ask is that we get a chance to look at results so we can help you with any mistakes you may have made (improve the quality and usefulness of the results).

 

"There is no security in obscurity."

Austin Lesea
Principal Engineer
Xilinx San Jose
0 Kudos
Highlighted
Observer
Observer
8,508 Views
Registered: ‎09-09-2016

Ok then the quick answer is bits swapping and bytes swapping  on 32b word.

 

To be clear what I done is not an attack to security but how to use Xilinx stated description and use my keys and my bitstream  : I do not make any tampers.

I do not nor make a reverse engineering on bitstream to fully understand the HMAC implementation as all I want is to decrypt it when it still could be trusted. No need for me to check or generate the MAC with HMAC.

 

An imortant point is that I use the .bit file bitstream ( or .bin for QSPI flash, may be not in same endian for BPI and others).

To my point of view Xilinx doesn't fully follow FIPS document in way it doesn't follow bit ordering and byte ordering indicated in document (in .bit).

For developers to use standard AES256 crypto libraries the bitsteam must be bit swapped 32b words by 32b word ( todecrypt[31:0] <= bitstream[0:31] ) before decrypt and after decrypt.

Keyfile.nky keys byte array must be byte swapped and bit swapped !

I think it's the same for the CBC IV but i'm not concerned about as that only concern the first AES256 decoded bloc that is part of HMAC key and that I don't check.

 

I expect that will help .

 

 

 

View solution in original post

0 Kudos
Highlighted
Visitor
Visitor
622 Views
Registered: ‎12-02-2019
Hi
I'm facing a degree thesis and I'm studying for the first time the concepts of cryptography applied to FPGA.
I am in the same condition as you were. I swapped the encrypted bitstream (in particular from the first 16 bytes following DWC, as I am looking for the HMAC_key), the AES256 key and the IV. Nevertheless, the result of the decryption does not correspond to the first 16 bytes of HMAC_key I used. (I also tried swapping the result without success). It occurs to me that maybe I'm wrong to swap the data?

I need an answer as soon as possible. thank you very much
0 Kudos
Highlighted
Observer
Observer
576 Views
Registered: ‎09-09-2016

Hi,

It's make a long time for me... The only things I remember is when I take the .bit byte stream i'm align to 4 bytes.

Before inserting any data to the AES256 crypto libraries (key, vector, bytestream, ...) I first byte swap data 4bytes/4bytes : B'[0] <= B[3], B'[1] <= B[2],  B'[2] <= B[1], B'[3] <= B[0] then for each byte I swap bits : bits[0..7] <= bits[7..0]. After I provide it to hte standard crypto librarie and with the resulting stream from the crypto librarie I apply the same swapping and then all is OK.

 

Good luke

Sylvain

0 Kudos