
  Series 09 Nanocommands.


1 Nanocommands..hmmm.. what's that ?


  As you know, a decoder of a VideoCrypt system sends some
  instructions to the card or receives data from the card.
  The most important instruction is 74hex with the following
  32 bytes to the card. This 32 byte data-packet includes all
  the needed information to descramble the video signal. Beside
  the encrypted seed for the PRBS (Pseudo-Random-Byte-Sequence)
  generator it includes channel-id, subchannel-id, an electronic
  signature, scramble status (soft- or hardscrambled) and, of course,
  the nanocommands with their parameters. The main reason to send
  nanocommands is to get control about what happens inside a genuine
  Sky Viewing Card. For example, with a specific nanocommand you can
  alter the value of a RAM address inside the card or read out parts
  of the ROM or RAM of the smartcard. If BSkyB sends one of this
  'tricky bastards' we call it an ECM (Electronic-Counter-Measure).
  Every time Sky sends a new (and unknown) nanocommand or parameter
  for a known nanocommand, we have to find out what happens inside
  the card. The main reason to find out the function of every single
  nanocommand is, that they will be used for the decryption of the
  PRBS seed.



2 How to decrypt nanocommands


  A typical 74hex instruction:


  BUFFER + 0  1  2  3  4  5  6  7  8  9  10 11 12 13 14 15 16 17 18 19 20 21

           ³  ³  ³  ³  ³  ³  ³  ³  ³  ³  ³  ³  ³  ³  ³  ³  ³  ³  ³  ³  ³  ³

           E8 4F 22 9A 0C 52 2C 92 F4 14 AB 00 E3 F1 9F DA 95 DA 95 AC 98 B5
              ÀÄÄÄÄÄÄÙ                         ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
           BYTES TO DECRYPT NANOCOMMANDS           ENCRYPTED NANOCOMMANDS

  BUFFER + 22 23 24 25 26 27 28 29 30 31

           ³  ³  ³  ³  ³  ³  ³  ³  ³  ³

           44 18 BF 7E E7 7A F4 5E 62 46
           ÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
           MAX. 15 BYTES


  Steps to decrypt the nanocommands:                 Examples:

   * load BUFFER + 1 and XOR with BUFFER + 2      -> 4F XOR 22      = 6D
   * swap Nibbles 0-3 with 4-7                    -> SWAP 6D        = D6
   * save value                                   -> VALUE1         = D6
   * load BUFFER + 2 and store value              -> VALUE2         = 22

   * load VALUE2                                  -> 22
   * rotate one bit left                          -> RL 22          = 44
   * add VALUE1                                   -> D6 + 44        = 1A
   * store result in NANOBUFFER                   -> NANOBUFFER + 0 = 1A
   * store result in VALUE2                       -> VALUE2         = 1A

   * load VALUE2                                  -> 1A
   * rotate one bit left                          -> RL 1A          = 34
   * add VALUE1                                   -> D6 + 34        = 0A
   * store result in NANOBUFFER                   -> NANOBUFFER + 1 = 0A
   * store result in VALUE2                       -> VALUE2         = 0A

   * load VALUE2                                  -> 0A
   * rotate one bit left                          -> RL 0A          = 14
   * add VALUE1                                   -> D6 + 14        = EA
   * store result in NANOBUFFER                   -> NANOBUFFER + 2 = EA
   * store result in VALUE2                       -> VALUE2         = EA

   * load VALUE2                                  -> EA
   * rotate one bit left                          -> RL EA          = BA
   * add VALUE1                                   -> D6 + BA        = 90
   * store result in NANOBUFFER                   -> NANOBUFFER + 3 = 90

  current NANOBUFFER -> 1A 0A EA 90

   * load BUFFER + 3 and XOR with NANOBUFFER + 0  -> 9A XOR 1A      = 80

  If the last value is 80hex then the above 74hex data packet contain
  nanocommands, otherweise the data packet contain NO nanocommands !

   * load NANOBUFFER + 2                          -> VALUE3         = EA
   * in this last step you have to XOR fifteen
     bytes with VALUE3 starting with BUFFER + 12
     and to store the results in the NANOBUFFER

     BYTECOUNT = 0

     load BUFFER + 12 [+BYTECOUNT] <ÄÄÄÄÄÄÄÄÄÄ¿
     XOR with VALUE3                          ³
     store into NANOBUFFER [+BYTECOUNT]       ³
                                              ³
     BYTECOUNT = BYTECOUNT + 1                ³
     BYTECOUNT = 15 ?  if not GOTO ÄÄÄÄÄÄÄÄÄÄÄÙ


     For example, after executing the last step, the NANOBUFFER
     contain the following values:


     09 1B 75 30 7F 30 7F 46   72 5F AE F2 55 94 0D
     ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ   ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
     ³    NANOCOMMANDS     ³         GARBAGE




3  Detailed description


   3.1. Nanocommand 03hex (1 byte)


        03 <no parameters>

        Break and execute the last 64 Iterations with the current
        index into the NANOBUFFER



   3.2  Nanocommand 09hex (3 bytes)

        09 MSB LSB

        Set address for nanocommand 30hex, execute hash with value
        63hex and 00hex.

        Example:

        POINTER_MSB = MSB
        POINTER_LSB = LSB

        VALUE = 63hex
        CALL HASH
        VALUE = 00hex
        CALL HASH
        INDEX_INTO_NANOBUFFER + 3



   3.3  Nanocommand 0Chex (2 bytes)

        Execute hash with 00hex twice.

        Example:

        VALUE = 00hex
        CALL HASH
        VALUE = 00hex
        CALL HASH
        INDEX_INTO_NANOBUFFER + 2



   3.4  Nanocommand 0Fhex (2 bytes)

        0F XX

        Write value XX to card. The current address for this write
        command is stored in card address BFhex (MSB) and C0hex (LSB).
        After executing the write command, this nanocommand will act
        like nanocommand 03hex (Break and exit).


        Example:

        POINTER_HIGH = @BF                    ; load indirect from BFhex
        POINTER_HIGH = POINTER_HIGH AND 1Fhex ; only bit 0-4
        POINTER_LOW  = @C0                    ; load indirect from C0hex
        @POINTER = XX                         ; store value into address




   3.5  Nanocommand 11hex (4 bytes)

        11 XX MSB LSB

        This nanocommand writes value XX into the card ram (addresses 00-FF).
        If the address is greater than 00FFhex, the write command will be
        skipped. Also this command sets the address for nanocommand 30hex.

        Example:

        POINTER_HIGH = MSB
        POINTER_LOW  = LSB                    ; set pointer for card write

        If POINTER_HIGH <> 0 then ÄÄÄÄ¿       ; if address is greater 00FFhex
                                      ³       ; then skip write command
        @POINTER = XX                 ³       ; otherwise write value
                                      ³
        VALUE = XX   <ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
        CALL HASH
        VALUE = 00hex
        CALL HASH
        INDEX_INTO_NANOBUFFER + 4


        Some known addresses:


        Cardram address 08hex  WRITE-ONLY
        ---------------------

        Select ROMPAGE 1 or 2 depending on value XX, Bit 7
        If bit 7 is set to one, ROMPAGE 1 will be used, if bit 7 is
        set to zero, ROMPAGE 2 will be used with nanocommand 30hex.
        After executing the page select, you have to AND value XX
        with B7hex and to set bit 6 (OR with 40hex). After that store
        the value into ram address 81hex.


        Cardram address 81hex  READ/WRITE
        ---------------------

        This is very simple - just AND value XX with B7hex and set bit 6
        (OR with 40hex) and write the value to address 81hex.



        Cardram address EEhex  READ/WRITE
        ---------------------

        This address seems to be the internal pointer INTO the nanobuffer.
        First of all you have to write value XX to address EEhex, then
        value XX is the NEW pointer into the buffer.

        For example:


        Nanobuffer + 0  1  2  3  4  5  6  7  8  9  A  B  C

                     ³  ³  ³  ³  ³  ³  ³  ³  ³  ³  ³  ³  ³

                     11 80 00 88 30 00 11 0A 00 EE 30 00 03
                                       ^
                                       ³
                                       current index into buffer (=6)



        INDEX_INTO_NANOBUFFER = 0Ahex (this is the new value)

        Nanobuffer + 0  1  2  3  4  5  6  7  8  9  A  B  C

                     ³  ³  ³  ³  ³  ³  ³  ³  ³  ³  ³  ³  ³

                     11 80 00 88 30 00 11 0A 00 EE 30 00 03
                                                   ^
                                                   ³
                                                   NEW index into buffer


        INDEX_INTO_NANOBUFFER = INDEX_INTO_NANOBUFFER - 2

        Nanobuffer + 0  1  2  3  4  5  6  7  8  9  A  B  C

                     ³  ³  ³  ³  ³  ³  ³  ³  ³  ³  ³  ³  ³

                     11 80 00 88 30 00 11 0A 00 EE 30 00 03
                                             ^
                                             ³
                                             NEW index into buffer


        After processing nanocommand 11hex (see above)

        INDEX_INTO_NANOBUFFER = INDEX_INTO_NANOBUFFER + 4

        Nanobuffer + 0  1  2  3  4  5  6  7  8  9  A  B  C

                     ³  ³  ³  ³  ³  ³  ³  ³  ³  ³  ³  ³  ³

                     11 80 00 88 30 00 11 0A 00 EE 30 00 03
                                                         ^
                                                         ³
                        CURRENT index after nanoprocessing


        The above example will skip nanocommand 30hex 00hex !

        After checking the above addresses 08hex, 81hex and EEhex
        you have to check for addresses LOWER than AAhex. If the
        current address is lower than AAhex, the write command
        will be skipped - this means all addresses LOWER than AAhex
        are READ-ONLY addresses. If the current address is HIGHER or
        equal AAhex, you have to write value XX to that address.




   3.6  Nanocommand 14hex (5 bytes)

        14 xx xx xx xx


        Execute hash with value 00hex TWICE.

        Example:

        VALUE = 00hex
        CALL HASH
        VALUE = 00hex
        CALL HASH
        INDEX_INTO_NANOBUFFER + 5



   3.7  Nanocommand 19hex (1 byte)

        19 <no parameters>

        Execute hash with current index into nanobuffer and execute hash
        with value 19hex.

        Example:

        VALUE = INDEX_INTO_NANOBUFFER
        CALL HASH
        VALUE = 19hex
        CALL HASH
        INDEX_INTO_NANOBUFFER + 1


   3.8  Nanocommand 1Dhex (2 bytes)

        1D xx

        Execute hash with value 00hex TWICE

        Example:

        VALUE = 00hex
        CALL HASH
        VALUE = 00hex
        CALL HASH
        INDEX_INTO_NANOBUFFER + 2



   3.9  Nanocommand 24hex (3 bytes)

        24 xx xx

        Execute hash with value 00hex TWICE

        Example:

        VALUE = 00hex
        CALL HASH
        VALUE = 00hex
        CALL HASH
        INDEX_INTO_NANOBUFFER + 3


   3.10 Nanocommand 28hex (5 bytes)

        28 AA BB CC DD

        First of all write all parameters from AA-DD to cardram addresses
        8Dhex-90hex. After that execute hash with the last value DD, and
        execute hash again with the current index into the nanobuffer.

        Example:

        CARDRAM_ADDRESS 8Dhex = AA
        CARDRAM_ADDRESS 8Ehex = BB
        CARDRAM_ADDRESS 8Fhex = CC
        CARDRAM_ADDRESS 90hex = DD
        VALUE = DD
        CALL HASH
        VALUE = INDEX_INTO_NANOBUFFER
        CALL HASH
        INDEX_INTO_NANOBUFFER + 5


   3.11 Nanocommand 30hex (2 bytes)

        30 CNT

        This is the READ-COMMAND, this means, with this command you can read
        out the card RAM or ROM. The current address for this command was set
        from nanocommand 09hex or 11hex. The second byte CNT is the counter,
        how much bytes will be read from RAM or ROM. CNT is a 6-bit value,
        therefore a maximum of 127 bytes can be read with a single command.
        If CNT is zero, only one byte will be read. First of all you have to
        mask bits 0-6 with AND 7Fhex. After that you have to check, if the
        MSB of the current address is zero or not. If the MSB is zero (or
        in other words lower than 0100hex) the card RAM will be read. If
        the MSB is NOT zero, the card ROM (0100-1FFF) will be read. With
        every single byte the hash function will be executed.



        Example:


        COUNTER = CNT AND 7Fhex               ; load bytecounter (bit 0-6)

        if POINTER <> 007Ehex then Ä¿<Ä¿      ; cardram address 7Ehex ?
        POINTER = 00FEhex           ³  ³      ; yes -> set to address FEhex !
        VALUE = @POINTER   <ÄÄÄÄÄÄÄÄÙ  ³      ; read from cardram or cardrom
        CALL HASH                      ³      ; execute hash with value
                                       ³
        VALUE = COUNTER                ³      ; store current counter
        COUNTER = COUNTER - 1          ³      ; decr. counter
        if VALUE <> 0 then   ÄÄÄÄÄÄÄÄÄÄÙ      ; counter <> 0 ?

        VALUE = @POINTER                      ; load last value
        CALL HASH                             ; execute hash
        VALUE = COUNTER                       ; load counter (= FFhex)
        CALL HASH                             ; execute hash
        INDEX_INTO_NANOBUFFER + 2




   3.12 Nanocommand 34hex (4 bytes)

        34 xx xx xx

        Execute hash with value 00hex TWICE

        Example:

        VALUE = 00hex
        CALL HASH
        VALUE = 00hex
        CALL HASH
        INDEX_INTO_NANOBUFFER + 4



   3.13 Nanocommand 39hex (2 bytes)

        39 XX

        Write value XX to cardaddress 92hex and execute hash with value
        XX, after that execute hash with value 00hex.

        Example:

        CARDRAM_ADDRESS 92hex = XX
        VALUE = XX
        CALL HASH
        VALUE = 00hex
        CALL HASH
        INDEX_INTO_NANOBUFFER + 2



   3.14 Nanocommand 3Chex (1 byte)

        3C <no parameters>

        Execute hash with value 3Chex TWICE

        Example:

        VALUE = 3Chex
        CALL HASH
        VALUE = 3Chex
        CALL HASH
        INDEX_INTO_NANOBUFFER + 1



   3.15 Nanocommand 41hex (1 byte)

        41 <no parameters>

        Execute hash with value 41hex and 00hex.

        Example:

        VALUE = 41hex
        CALL HASH
        VALUE = 00hex
        CALL HASH
        INDEX_INTO_NANOBUFFER + 1



   3.16 Nanocommand 46hex (1 byte)

        46 <no parameters>

        Exit nanoproccessing .. all done.



   3.17 Nanocommand 49hex (1 byte)


        49 <no parameters>

        Execute hash with value 60hex and 49hex.

        Example:

        VALUE = 60hex
        CALL HASH
        VALUE = 49hex
        CALL HASH
        INDEX_INTO_NANOBUFFER + 1




   3.18 Nanocommand FFhex (1 byte)

        FF <no parameters>

        Execute hash with value 00hex TWICE

        Example:

        VALUE = 00hex
        CALL HASH
        VALUE = 00hex
        CALL HASH
        INDEX_INTO_NANOBUFFER + 1




*end of file*
