These notes are updated for Version 2.0.300 of the firmare.

NOTE
   All data types are LSB first unless otherwise specified!

Curious about what all 14 keyfiles are?
Well, here's the short guide.

First, each key is repeated twice, in case one copy is bad. I don't
take that into account with the existing script, although it could be
done.

key0 used to be device1.key type 1
        This is the Device's private ElGamel key. It is encrypted
        in the file with the device's blowfish key.
key1 used to be device1.key, type 2
        This is file for "__REGTICKET". This encrypted data represents
        the device in some as yet unknown manner. It is sent as a
        complete block during device initialization.
key2 used to be user1.key, type 4
        This is the user's private ElGamel key. This key is also
        encrypted with the device's blowfish key (and cannot be decrypted
        with the device private key!)
key3 used to be device1.key, type 8
        This appears to be Gemstar's public key. It is unencrypted and
        used to verify certain operations including new key certificates.
key4 used to be device1.key, type 10
        This key is currently unused by the ebook software -- the routine
        which accesses it near appears to be called.  It is 36 bytes, and
        usually starts with 3 zeros.
key5 used to be user1.key, type 400
        This key is 20 bytes of hexadecimal data. It wasn't used until
        recent firmware when it is used to modify the per-file decryption
        key.
key6 would have been type 1000
        This key is sent to the device with a Diffie-Hellman key exchange
        when it first phones home after getting the new firmware
        It is 16 bytes of binary data.

The remaining files are copies, from device2.key and user2.key respectively.

A few more details, from earlier notes --

Key Type 1: Device Private Key
   +0 DWORD Version (LSB first -- 2)
   +4 8 BYTES Random data for key decryption
   +36 DWORD Version (MSB first!, always 2)
   +40 DWORD Length of following data
   +44 BYTES Encrypted private key

This key is encrypted with Blowfish in CFB64 (Cipher Feedback, 64 bits)
The Blowfish key is 16 bytes, obtained by taking the SHA1 (FIPS 180-1) hash 
of the 8 bytes of the Device Serial number and the 8 bytes of random data.
Then, the last 4 bytes of the hash are XORed with the first.
Psuedo code:

   SHA1_INIT ctxt
   SHA1_UPDATE ctxt, serial_number, 8
   SHA1_UPDATE ctxt, random_data(keydata + 4), 8
   SHA1_TRANSFORM hash, ctxt
   bfkey[0..15] = hash[0..15]
   bfkey[0] = bfkey[0] XOR hash[16]
   bfkey[1] = bfkey[1] XOR hash[17]
   bfkey[2] = bfkey[2] XOR hash[18]
   bfkey[3] = bfkey[3] XOR hash[19]

The initialization vector is the 8 literal bytes: FE DC BA 98 76 54 32 10

Once the private key has been decrypted, the first dword should
always be: 02 01 01 02

To read the private key, use
   privkey = bufGetEGPrivateKey(keydata+44)

One can check that the key was read in correctly with the following
sequence of calls,
   public_key = bigInit(0)
   bigPow(privkey->alpha, privkey->secret, privkey->p, public_key)
   bigCompare(public_key, privkey->publicKey) == 0

Key type 4: User Private Key
   +0 DWORD Version (LSB first -- 2)
   +4 8 BYTES Random data (of unknown purpose in this type!)
   +36 DWORD Version (MSB first!, always 2)
   +40 DWORD Length of following data
   +44 BYTES Encrypted private key

he key data here is encrypted with the same blowfish key used for the
device private key.

USER-KEY CERTIFICATE FORMAT

This file is generated by Gemstar's servers to send a private key to the
device.
   Header:
	   +0 4 BYTES SIGNATURE (E0 DC DC AC)
	   +4 DWORD Version (always 2)
	   +8 DWORD Length of the entire file
	   +12 8 BYTES Random data (propagated into user1.key)
	   +20 DWORD ?? (typically 1)
	   +24 DWORD Sequence Number (*)
	   +28 BYTES Elgamal-Encrypted blowfish key
	   +x BYTES Elgamal User private Key
* The sequence number increments each time a key is downloaded. A lower or
  equal sequence number cannot override the current user key!

The length of the blowfish key data is LENGTH(privkey->p) * 8
LENGTH is a macro declared by CryptoLib.

Example code:
   usercert_in = bigInit(0);
   bufToBig(certfile+28, LENGTH(privkey->p) * 8, usercert_in);
   usercert_out = EGDecrypt(usercert_in, privkey);
   bigToBuf(usercert_out, 16, blowfish_usercert_key);

The Blowfish key is 16 bytes, and is used to decrypt the data immediately
after the encrypted key, up until the end of the file.

The initialization vector is the 8 literal bytes: FE DC BA 98 76 54 32 10,
same as before.

When decrypted, the first 16 bytes will contain the user name of the key.
   At offset +16, the version number (2) will be in MSB-first order
   At offset +20, the key size will be in MSB-first order
   At offset +24, the User's private key will start
                 This can be read with bufGetEGPrivateKey.
There is other verification stuff which is not covered by this document.

.RB ENCRYPTION DETAILS:

As covered in other documentation about the .RB format, an RB file typically
has 264 bytes between the header and the table of contents.

   RB Header (see rb_format.html for details)
      +0 DWORD SIGNATURE (B0 0C B0 0C, B0 0C C0 DE )
      +4 DWORD Version (2)
      +8 DWORD Creator? (0 or 'NUVO'?)
     +12 DWORD Creation date??
     +16 DWORD ?? (non-zero in my samples)
     +20 DWORD ?? (non-zero in my samples)
     +24 DWORD Offset of TOC
     +28 DWORD Total file length
     +32 DWORD Start of ElGamal encrypted book-key
    +288 DWORD 8 bytes of encrypted data, high 20 bits are always clear

For old files (version 2) the blowfish key for the book is 16 bytes. 
It is decrypted with the user's private key, as shown by the following code:
   bufToBig(rbfile+32, LENGTH(userprivkey->p) * 8, filekey_in);
   filekey_out = EGDecrypt(filekey_in, userprivkey);
   bigToBuf(filekey_out, 16, blowfish_filekey_data);
   BF_set_key(&blowfish_file_key, 16, blowfish_filekey_data);
The initialization vector is the 8 literal bytes: FE DC BA 98 76 54 32 10,
just like above.

The RB file format changed (from version 2 to version 3). This is reflected
in the header, and in a new file-encrypted flag (0x80) instead of the old
(0x01). Finally, the "NEWBODY" tag is added to the info file so the
update-or-else message is displayed. These files should make them glad they
were so persistent.

In the misty past, when the firmware was young and yet virginal decrypting
a book was simple. The RB file contained an ElGamel encrypted chunk at
offset 32 which decrypted to a 16 byte blowfish key which could easily be
used to decrypt all the files.

Now, as of 2.0.300, the process is similar -- the RB file contains the same
encrypted chunk with 16 bytes of key data. Before that key data can be used,
it is xorred with the key6 data, the 8 bytes resulting from converting the
first 16 characters of key5 to binary (repeated twice), and finally 8 bytes
of magic data in the RAM.RFF file which appears to be the same for all users.
After all this to get the key, they still have another 8 bytes of secret data 
which they use for the blowfish IV (Initialization vector).

The new version 3 IV is at offset 15B194 of the uncompressed version 2.0.300
firmware (to find in earlier firmwares, search for the four bytes 02 01 01 02
and move back 8 bytes.  

The 8 bytes of magic data are at 15B1C4. (These are the next non-zero bytes
after the 02 01 01 02 value). These bytes aren't included in these notes as
they are presumably copyrighted by Gemstar. 

Recap:  16 bytes from the individual book file
        16 bytes hidden in ram.rff,
        16 bytes sent by a new key exchange,
     and 8 bytes which were previously unused.
     -----------------------------------------
       448 BITS of key data.

Lesson: Size doesn't matter.

Each encrypted file in the book is encrypted with Blowfish in CFB64 mode.
The initialization vector is restored to the original for each file, if
there is more than one encrypted file.
The 8 bytes of encrypted data in the header file are not necessary - it
is possible to just ignore them, since the IV is restored before each file.
When decrypted, the low 40 bits will contain an unknown value.

SOFTWARE UPDATE FORMAT:

Typically software updates are sent encapsulated inside a .RB file, with a
signature of B0 0C C0 DE. If the internal flash is erased the recovery ROM
in the device (which is only 64KB) cannot handle private key decryption and
will accept a software update encrypted with its PUBLIC key using the TEA
algorithm.

The public key may be obtained by asking the device for the "__REGTICKET"
file.

he encrypted flag is only set on files sent to the recovery rom. The
software is stored unencrypted on the internal 8MB flash.
Typically, there are two levels of software updates in a RAM.RFF file - the
original which contains a form of boot-loader, which then loads the
secondary software update. The secondary software update is never
encrypted and searching for the software update signature will allow the
extraction of all the software.

This is the format of the RFF file, and is sufficient to generate user
code for the REB device:

  The RFF file consists of an 512 octet header and a sequence  
  of blocks, each 512 bytes in length.  Incomplete blocks must 
  be padded to the end with the octet containing all ones.     
  The format of the header is:                                 
  At offset, the data type, means                              
  +0   quad octet              DEh C0h 00h A0h is a signature  
  +4   sixty octet string      For humans to track the version 
                               information.  Isn't read        
  +64  twelve octets, data     Parsed version information,     
                               not used by the ebook ROM       
  +76  three octets  'PRR'     Describes type of RFF.          
                               only type 'P' is known.         
  +79  one octet, FFh          Padding for previous field      
  +80  quad octet              Length of complete file         
  +84  quad octet              Length of file without header   
  +88  quad octet              Where to locate data            
                               Usually 1MB, cannot be used to  
                               overwrite existing software     
  +92  quad octet              Always zero, unused             
  +96  quad octet              Always zero, unused             
  +100 quad octet              First address to execute from   
                               usually 1MB.                    
  +104 quad octet              Size of header.                 
                               This is always 512.             
  +108 quad octet              Redundant file length field     
                               Unused by ebook ROM.            
  +112 one octet               One byte checksum (1)           
  +113 one octet,              Always zero, unused             
  +114 two octets, FFh         Unused                          
  +116 quad octet              Always zero, unused             
  +120 quad octet              1 for encrypted, 0 unencrypted 
  +124 quad octet              Uncompressed length,            
                               0 for uncompressed.             
  remainder                    FFh, unused                     


The symmetric key for the TEA algorithm is obtained with the following method:
Note that a TEA key is 16 BYTES, but the algorithm operates on 8 BYTE chunks.

Fill in a 4 dword array as follows
   tmpkey[0] = *(unsigned long int *)(regticket + 256);
   tmpkey[1] = *(unsigned long int *)(regticket + 320);
   tmpkey[2] = *(unsigned long int *)(regticket + 384);
   tmpkey[3] = *(unsigned long int *)(regticket + 448);
And again, for the "decrypted data" that will become the key
   key_in[0] = *(unsigned long int *)(regticket + 512);
   key_in[1] = *(unsigned long int *)(regticket + 576);
   key_in[2] = *(unsigned long int *)(regticket + 640);
   key_in[3] = *(unsigned long int *)(regticket + 704);
Now, encrypt that data
   encipher(&key_in[0],&key_out[0], tmpkey);
   encipher(&key_in[2],&key_out[2], tmpkey);
Finally, convert from LSB to MSB
   #define BSWAP(x) \
       ((((x) >> 24) & 0xFF)|\
       (((x) >> 8) & 0xFF00)|\
       (((x) << 8) & 0xFF0000)|\
       (((x) << 24) & 0xFF000000))

       key_out[0] = BSWAP(key_out[0]);
       key_out[1] = BSWAP(key_out[1]);
       key_out[2] = BSWAP(key_out[2]);
       key_out[3] = BSWAP(key_out[3]);

Now, each 8-byte chunk of the file can be decrypted with:
   for (i = 0; i < bytes_read; i+=8)
       decipher(&buffer[i], &buffer[i], key_out);

To decompress, 
    use zlib inflate()
To compress, use
    deflateInit2(&zs, 6,Z_DEFLATED, 15, 8, Z_DEFAULT_STRATEGY);
    and deflate()
  
List of magic filenames:
   __STATUS -- Device status
   __TITLES -- List of current titles in XML form
   __REGTICKET -- Returns device public key
   __DIR -- tree-structured listing of device filesystem
   __SMDIR -- Same as above for the smart media card


"DEBUG MODE"
   The REB-1100 has a 64KB Ateml flash indepedent of the 8MB of flash
   memory. He will always start in the Atmel flash part and then load
   from the 8MB flash.

   If the ram.rff file doesn't exist (ie, if the internal flash is
   cleared with INITDIR 0 <serial #> ), or if the two paging buttons 
   are depressed during boot, this boot rom will enter a "DEBUG MODE"

   In "Debug mode", you see the often mentioned "Grid Screen" from 
   ebook forums. At this point the device is receptive to USB commands.

   In debug mode, you can fetch files such as 'ram.rff' (the system 
   software), and 'device1.key',''device2.key','user1.key',and 
   'user2.key'.

   Gemstar "fixed" this by moving the keys out of the keyfiles into
   another portion of the flash which isn't accessible directly from 
   the bootrom. They also left a stub in each of these key files.

   The device will accept an unencrypted code packet (RFF file) if
   it is in the internal flash, or if the device1.key/device2.key DO 
   NOT EXIST. The intent was to make it impossible to download new 
   code to the device with the stub key files.

   Fortunately, the Nuvomedia guys left a backdoor for the 
   enterprising enthusiast in the form of another USB command which 
   allows the boot rom to PRETEND that the device keys do not exist. 
   At this point, one can happily download unencrypted code to the 
   REB-1100. 
   The backdoor is an USB packet with type "USER REQTYPE 5" the 
   format of the data is 4 bytes of length and a four byte command
   value. Send two packets IN SEQUENTIAL ORDER, first with command 
   value 1, then with command value 3. 

   As an aside, the REB-1100 will load an RFF from the smart media
   device, but this RFF file must be encrypted if the two keyfiles
   exist. 

Compression library used by the REB-1100
   (among others -- do a strings output on the ROM)
   Inflate 1.0.3

Cryptographic Libraries used by the REB-1100
   Blowfish is from SSLEAY-0.66
   SHA1 is from libsha-0.8.2b, again by eay
   ELGamel and Encoding from cryptolib-1.X by Jack Lacey
   tea is from the reference implementation
