File RijnType.h in HTML format
for block cipher RijnType,
an extended fast Rijndael clone.


[Several other documents on this site are referred to repeatedly within. All the links to these documents are given here; return here if you want to view the contents.
rt_home.html - The main entry to the RijnType section.
rtdotcpp.html - The C++ code for the 'dot-h' file within.
rtrefs.html - The references for Rijndael.
rtreport.html - An discussion of Rijndael and RijnType.
  Below I shall just write e.g. 'rtreport' (single quotes) when referring to any of the files above.]

/***************** 
 To recover file RijnType.h file from this document (rtdoth.html) using
Internet Explorer, select File->Save As, input 'RijnType.txt' as the output
filename and 'Text File (*.txt)' as the output format. The resulting file
(after renaming RijnType.h) will be stripped of html tags and will be near
to a viable '.h' file.
  (A string "RTdoth" at the start of this file will need removing) I use 
'viable' here in the sense that my Borland compiler accepts it.
Other browsers and compilers may not be so cooperative. You may need to open
this file in Notepad, Wordpad, or similar, to polish up the formatting and/or
edit items that your particular compiler baulks at.
  A discussion of the workings of each class can be found in 'rtreport'. 
******************/ 


#ifndef __RIJNTYPE_H 
  #define __RIJNTYPE_H 
#if !defined __STDIO_H 
  #include "stdio.h" 
#endif 
#if !defined __STDLIB_H 
  #include "stdlib.h"
#endif 
  
typedef unsigned char  word8 ; 
typedef unsigned int   word16 ; 
typedef unsigned long  word32 ; 
/* -------------------------------------- 
        This is file RijnType.h (in html format) 
           for the BLOCK CIPHER RIJNTYPE, 
          an extended fast Rijndael clone.
Date   July 2008; 

Author N. Hensor
          Flat 3, 5 Tregonwell Road,
             Bournemouth,
                Dorset,
                   BH2-5NR, England. 

       EMail :-   enquiries@kahnet.co.uk 
       Phone :-  [U.K.] 07949 - 385425  (U.K. business hours only)

   Block cipher RijnType takes its inspiration from block cipher
Rijndael, the winner of the international AES competition in 2000 to find
a block cipher to replace DES.
   When block cipher RijnType is used within the limits of block cipher
Rijndael (see below) then RijnType is a 'Rijndael clone'.
(see the comments on little endian problems in 'rtreport') 

   Block cipher RijnType can be set up to encrypt data in blocks from
128 to 512 bits in size, in steps of 32 bits. The key bit size can vary
from 128 to 1024 bits, in steps of 32, independently of the data block size. 
[Other pages on this site related to this page include :- 
  (a) My overall web site home page. (start here for elliptic curve pages) 
  (b) The block cipher RijnType home page. 
  (c) 'rtreport' discusses details of the implementation of RijnType.
  (d) 'rtdotcpp' gives the C++ code corresponding to this '.h' file. 
  (e) 'rtrefs' lists technical references for this work.]

#------------------------#
Recall the Rijndael terminology (used unchanged in block cipher RijnType):- 
   Nk = the number of 32 bit words of key material, 
   Nb = the number of 32 bit words in an input/output block 
   Nr = the number of rounds in the block cipher.

For Rijndael, both Nk and Nb can vary independently from 4 to 8 in steps of 1. 
[For the version of Rijndael submitted to the AES competition,
   Nb is fixed at 4 and Nk can be 4, 6, or 8.
This 'cut down' variant I refer to as AES Rijndael below.] 

   For block cipher RijnType, Nb can vary from 4 to 16,
     and Nk can vary from 4 to 32, both in steps of 1. 
   These limits are 'defined' by parameters
     MIN_NBK, MAX_NB and MAX_NK below. 

   Nr is set from :- Nr = 6 + max(Nk, Nb) ; 
[This copies the Rijndael formula.] 
[When Nk is at its maximum of 32, Nr is 38.] 
  
Classes KeyHandler, KeyedLFSR, ShiftRow and RT_ByteOps
(declared below, defined in 'rtdotcpp')
are not intended to be used independently of RijnType.

Classes RijnType, RT_CBC (implements 'cipher block chaining' using RijnType) 
RT_MAC (uses RT_CBC to generate a 'MAC' or message authentication code) and 
RT_Hash (uses the Miyaguchi-Preneel algorithm to generate a modification 
detection code (MDC) or Hash) expect the following conditions to be applied.
 
Conditions :- 
  (1) The input and output arrays are assumed within to be Nb sized linear 
arrays of word32's. The Nb value is set in the constructor and fixed for the 
life of the object. 
   ** It is the users responsibility to ensure
                   the correct size of IP/OP arrays. ** 
  (2) Nk can vary independently of Nb for all classes except RT_Hash, for which 
Nk = Nb. Nk is also set in the relevant constructor and fixed for the life of 
the object. 
      (Two constructors are provided for RT_MAC; for one of these
         Nk = Nb, the other provides for Nk to be independent of Nb) 
  (3) Both RT_MAC and RT_Hash have methods restart_for_new_...(). 
      These methods MUST be called before subsequent message MAC's/Hash's are 
started using the same key (i.e. repeated use of the same object).

    Failure to call this method between calculations will cause rubbish to be 
generated! 

Three other conditions apply to all this work :- 
  (4) On reading this work, many modifications to block cipher RijnType
will suggest themselves. If changes are made, please change the name of
the resulting block cipher. It is very unwise to have incompatible variants
of any block cipher 'in the wild'. 
  (5) Some readers of this report will be searching for nothing more than a
fast implementation of block cipher Rijndael. As discussed in 'rtreport',
block cipher RijnType is both a Rijndael clone (within the limits of definition
of Rijndael) and several times faster than the reference implementation in Ref 2, 
Appendix E. This speed gain is largely due to the use of look-up tables 
discussed in Ref.2 but not listed there. Such readers would be well advised to 
change all references to RijnType to Rijndael and then treat this site as 
providing an alternative implementation of Rijndael.

[In this file and 'rtdotcpp' the string "RD=", embedded in comments, 
indicates changes needed to generate a Rijndael block cipher from RijnType.
See also the comments in 'rtreport' regarding little-endian problems,
to complete this change.] 

  (6) This code is placed in the public domain without any warranty of fitness 
for any purpose. 
            ----------------------------------------- */

  /* The next 3 parameters ** cannot be changed **
      (without some code rewriting) :- */ 
#define  MIN_NBK    4     /* minimum IP[] #32 bit words = 128 bits */ 
#define  MAX_NB     16    /* maximum ditto = 512 bits  */ /* RD=8 */ 
#define  MAX_NK     32    /* maximum Key[] #32 bit words = 1024 bits */
                          /* RD=8 */ 
#define  MAX_NROUNDS     (MAX_NK + 6) 
#define  MAX_KEYSPACE    (MAX_NB * (MAX_NROUNDS + 1)) /* = 624 word32's */ 
#define  ENCRYPT_MODE  1 
#define  DECRYPT_MODE  2 

/********** 
   The RT_Hash class forces Nb to equal Nk. 
   This need not be the case with RT_MAC. 
   However, when the RT_MAC and RT_Hash classes are used at
     one of the 3 'standard' strengths then 
   Nb = Nk = element from {HASHMACSTD, HASHMACSTRONG, HASHMACMAX} 
***********/

#define  HASHMACSTD     MIN_NBK    /* provides a 128 bit Hash or MAC */ 
#define  HASHMACSTRONG  10         /* provides a 320 bit ditto */ 
#define  HASHMACMAX     MAX_NB     /* provides a 512 bit ditto */ 
#define  BOOL   word16 
#define  TRUE   1 
#define  FALSE  0 
/* parameters in RT_ByteOps::RotByte() calls :-  */ 
#define  ONEBYTE    8 
#define  TWOBYTE    16 
#define  THREEBYTE  24 

/* ############################# */ 
class RT_ByteOps { 
private: 
  static const word8 S[256] ; /* The standard Rijndael/RijnType S-boxes */ 
  static const word8 Si[256] ; 
public: 
  RT_ByteOps (void) ; 
  ~RT_ByteOps (void) ; 
  word32  RotByte (word32 IP, word8 shift=ONEBYTE) ; 
  word32  SubByte (word32 IP) ; 
  word32  InvSubByte (word32 IP) ; 
} ; 
/* ############################# */ 

class ShiftRow { 
private: 
  word32  col0_blank, col1_blank, col2_blank, col3_blank ; 
  word16  C2, C3 ; 
  void set_C2_C3 (word16 Nb) ; 
  void wipe (void) ; 
protected: 
  word32  colsource[MAX_NB], coldest[MAX_NB] ; 
  void do_shift (word16 Mode, word16 Nb) ; 
public: 
  ShiftRow (word16 Nb) ; 
  ~ShiftRow (void) ; 
} ; 
/* ############################# */

class KeyedLFSR { 
/********************* 
   This class is not part of Rijndael. 
    [* RD => delete this class and all references to it in 'rtdotcpp' *]
   It uses a 32 bit LFSR to provide a secondary key expansion process on
top of the Rijndael key expansion. 
   This is the ONLY component in RijnType NOT part of Rijndael, and is
used only when RijnType exceeds the limits of Rijndael (Nk > 8). 
   The LFSR used is a 'high tap' 32 bit linear feedback shift register
based on polynomial GF2_32_poly (0x67039A31 in hex), worked in
'multiply by x' mode. 
   The 'Key' material pointed to in the constructor is used to set :- 
    (a) The initial LFSR 'state'. 
    (b) The value 'runlength' which controls the number of calls to 
'next_LFSR()' (1 - 16) used in 'next_value()'. 
    (c) The value 'selector' whose bit pattern controls whether the
values returned from 'next_LFSR()' are XOR'd into the output for
'next_value()' or stepped over. 
**********************/ 

private: 
  word32  *pKey ; 
  word32  state, runlength, selector ; 
  word16  nibblectr ; 
  class   RT_ByteOps  rtbo ; 
  static  const word32  GF2_32_poly ; 
  word32  next_LFSR (void) ; 
/**************** 
    next_LFSR() cycles the LFSR once. 
    Values returned (when Key[] = all 0L) from
         successive calls to next_LFSR() = 
     0x80000000, 0x67039A31, 0xCE073462, 0xFB0DF2F5, 
     0x91187FDB, 0x45336587, 0x8A66CB0E, 0x73CE0C2D ... 
****************/ 

  void  update_LFSR (void) ;  /* resets state, runlength, selector */ 
public: 
  KeyedLFSR (word32 *Key) ; 
  ~KeyedLFSR (void) ; 
  word32  next_value (void) ; 
    /* calls next_LFSR() several times to form a composite value */ 
} ; 
/* ############################# */ 

class KeyHandler { 
/****************** 
  This class performs a KeyExpansion similar to that of
Rijndael differing only when Nb > 8. 
******************/ 
private: 
  word32  lastRC ; 
  class  KeyedLFSR *pKLFSR ;  /* RD=delete this item */ 
  static  const word32 GF2_8_poly ; 
  static  const word32 mod[16] ; 
  word32  next_RC (void) ;

/***************** 
    RC is the standard Rijndael 'round constant' (an 8 bit LFSR) 
    Values returned from successive calls from above
       (left shifted 24 bits) = 
     01, 02, 04, 08, 10, 20, 40, 80, 1B, 36, 6C, D8, ... 
      [least significant 24 bits always zero] 
******************/

  word32  InvMixColumns (word32 IP) ; 
  void  Mod (word32& value, word32 oflow_indicator) ; 
protected: 
  word32  KeySpace[MAX_KEYSPACE] ; 
  word16  KeySpaceSize ; /* actual #word32's of Key-space in use. */ 
  word16  EncDecMode, Nb, Nk, Nr ; 
  class   RT_ByteOps rtbo ; 
  void  KeyExpansion (word32 *Key) ; 
  void  restart_KeyExpansion (void) ; 
public: 
  KeyHandler (word16 Mode, word16 Nb, word32 *Key, word16 Nk) ; 
  ~KeyHandler (void) ; 
} ; 
/* ########################## */ 

class RijnType : public KeyHandler, public ShiftRow { 
private: 
  static const word32 T0[256], T1[256], T2[256], T3[256] ; 
  static const word32 iT0[256], iT1[256], iT2[256], iT3[256] ; 
protected: 
  void Encrypt (const word32 *IP, word32 *OP) ; 
  void Decrypt (const word32 *IP, word32 *OP) ; 
public: 
  RijnType (word16 Mode, word16 Nb, word32 *Key, word16 Nk) ; 
/*********** 
     Mode must be either ENCRYPT_MODE or DECRYPT_MODE only. 
      [Any other value creates a decryption object!] 
     Nb is the number of word32's in each data block [min 4; max 16] 
     Nk is the number of word32's in array Key[]     [min 4; max 32] 
      [** Note Nk can vary independently of Nb.**] 
     Key[Nk] is the array of key material. 
************/ 
  ~RijnType (void) ; 
  void Process_block (const word32 *IP, word32 *OP) ; 
/*********** 
     This performs an 'ECB' encryption or decryption depending on
the 'Mode' value set in the class constructor. 
     [ECB stands for 'Electronic Code Book'. It is a 'fundamental'
single application of the block cipher and usually only used as a
building block within more complex schemes such as some form of 'chaining'.
       (e.g. see RT_CBC below which performs 'Cipher block chaining'.) 
      ** Caution :- few cipher systems would use ECB on its own.**] 
     If 'Mode' in the constructor was set to ENCRYPT_MODE then Encrypt()
       is called within - else Decrypt() is called. 
************/ 
} ; 
/* ########################## */

class RT_CBC : public RijnType { 
/****** 
     This class performs Cipher Block Chaining (CBC)
encryption/decryption, using RijnType as the block cipher. 
******/ 
private: 
protected: 
  word32 C[HASHMACMAX] ; 
public: 
  RT_CBC (word16 Mode, word16 Nb, word32 *Key, word16 Nk, word32 *IV=NULL) ;

/******** 
     This class performs CBC encryption/decryption using RijnType. 
     Mode must be either ENCRYPT_MODE or DECRYPT_MODE only. 
     Key[Nk] is the fixed key for a CBC encryption/decryption. 
     IV[Nb] is an (optional) Initialization Vector. If not supplied
     (i.e. IV=NULL) then the IV[] is zeroed in this constructor. 
********/

  ~RT_CBC (void) ; 
  void  Process_next_CBC_block (const word32 *next_block, word32 *OP) ;

/******** 
     This performs a 'CBC' encryption or decryption (depending on 'Mode'
      set in the class constructor) on the next data block. On exit,
      OP[] holds the next cipher block or plain text block in the chain. 
      Caution :- Use 1 RT_CBC object per message only.
     As coded in 'rtdotcpp',
            ** repeated use of an RT_CBC object will fail **. 
********/ 
} ; 
/* ########################## */

class RT_MAC : public RT_CBC {

     /********** 
       This class uses the CBC-MAC algorithm to generate a
        'Message Authentication Code' aka a MAC. 
     **********/
private: 
protected: 
public: 
  RT_MAC (word16 Strength, word32 *Key) ; 

     /********* 
       This constructor is intended to be used for the generation of
         one of the three 'standard' RijnType MAC's. 
       For the 'standard' MAC's, 'Strength' should be set either 
         HASHMACSTD, HASHMACSTRONG or HASHMACMAX. 
       For non-standard MAC's MIN_NBK <= Strength <= MAX_NB 
       (Nb = Nk = Strength with this constructor) 
       Key[Strength] is a fixed encryption key. 
     **********/ 

  RT_MAC (word16 Nb, word32 *Key, word16 Nk) ; 

     /************ 
       This is a general purpose MAC generator, limited only by
       the limits of RijnType itself :- 
              MIN_NBK <= Nb <= MAX_NB     MIN_NBK <= Nk <= MAX_NK 
       The large Key[Nk] permitted by this constructor provides space
       for more 'administrative' fields within itself. 
       For RT_MAC, Key[Nk] will typically contain fields to :- 
        (a) Identify the sender. 
        (b) Prevent exhaustive searching (a random section) 
        (c) Hold a time stamp, contract reference number, letter
             reference number and other administrative details. (optional) 
     *************/ 

  ~RT_MAC (void) ; 
  void  Add_next_block_to_MAC (const word32 *next_block) ; 
     /* Call repeatedly until all message blocks in sequence have
        been fed in. */ 
  void  get_MAC (word32 *MACholder) const ; 

     /*********** 
        After all message blocks have been fed in, use this to copy
         the MAC into MACholder[Strength/Nb]. 
     ***********/

  void  restart_for_new_MAC (void) ; 

     /* This MUST be called before starting the calculation for
        the MAC of a second, or subsequent, message. */ 
} ; 
/* ########################## */ 

class RT_Hash : public RijnType { 

     /********** 
       This class uses the Miyaguchi-Preneel algorithm to generate
        a 'Modification Detection Code', aka an MDC, aka a 'Hash'. 
     **********/ 

private: 
  word32  KeyCopy[MAX_NB], H[MAX_NB] ; 
  BOOL   firstpass ; 
protected: 
public: 
  RT_Hash (word16 Strength, word32 *Initial_Key) ; 

     /********** 
       For the 'standard' Hash's, 'Strength' should be set to one of 
         HASHMACSTD, HASHMACSTRONG or HASHMACMAX 
       For non-standard Hash's   MIN_NBK <= Strength <= MAX_NB 
         [Nb = Nk = Strength for this class] 
       Initial_Key[Strength] is the starting key (some references use
         the phrase 'Initialization Vector' for this item). 
     **********/

  ~RT_Hash (void) ; 
  void  Add_next_block_to_Hash (const word32 *next_block) ; 
    /* Call repeatedly until all message blocks in sequence
        have been fed in. */

  void  get_Hash (word32 *Hash_holder) const ;
    /********** 
      After all message blocks have been fed in, use this to
       copy the resulting Hash into Hash_holder[Strength]. 
     **********/ 

  void  restart_for_new_Hash (void) ; 
    /* This MUST be called before starting the calculation for
        the Hash of a second, or subsequent, message. */ 
} ; 
#endif      /* RijnType.h  */