The Relogix translation

Note: This is a 100% automatic translation, with no human intervention or cleaning-up of the code after translation. Relogix has automatically chosen the function prototypes, has chosen the variable types and local variable names, and has placed the assembler comments in the translated source allowing for the re-arrangement of the code flow.

In a real translation project, the translation could be further improved by providing user-defined header files to tune the names and types of variables, and the function prototypes. However, in its current state it is already working code which passes the encryption/decryption tests.




/************************************************************************
*                                                                       *
*       "sjtest.c" - Translated from file "sjtest.asm"                  *
*                                                                       *
*-----------------------------------------------------------------------*
*                                                                       *
*       Relogix Code Translator Copyright (c) MicroAPL 1990-2018        *
*                   All Rights Reserved Worldwide                       *
*                                                                       *
*************************************************************************
*
*/

/*
*-----------------------------------------------------------------------------
* SKIPJACK test program - part of SKIPJACK distribution
* Copyright 1998, 1999 Eric Smith
* $Id: sjtest.asm,v 1.2 1999/05/07 02:07:39 eric Exp $
*
* WARNING: This software may be subject to export controls
*
* http://www.brouhaha.com/~eric/pic/
* http://www.brouhaha.com/~eric/crypto/
*
* SKIPJACK is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published by
* the Free Software Foundation.  Note that I am not granting permission to
* redistribute or modify SKIPJACK under the terms of any later version of
* the General Public License.
*
* This program is distributed in the hope that it will be useful (or at least
* amusing), but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
* Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* this program (in the file "COPYING"); if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* This software has been tested using the GPASM assembler:
*       http://reality.sgi.com/jamesb/gpasm/
* and the PSIM simulator:
*       http://www.brouhaha.com/~eric/pic/psim.html
*
* It may work with Microchip's MPASM assembler, but has not been tested.
*-----------------------------------------------------------------------------
* This test program is only intended for use on the PSIM simulator.
*/


#include "rlxpic.h"
#include "pic_header.h"
#include "sjtest.h"

#define CR                   0x0d
#define LF                   0x0a
#define KEYLEN               10
#define BLOCKLEN             8
#define ROUNDS               32

/* Prototypes for private routines translated to C */
static void print_key (void);
static void print_plaintext (void);
static void print_ciphertext (void);
static void print_block (void);
static void outhb (unsigned char c);
static void outhd (unsigned char c);
static void xmit (unsigned char c);
static void msgout (unsigned char *message);
static unsigned char * half_g (unsigned char *ptr);
static void encrypt (void);
static unsigned char * half_g_inv (unsigned char *ptr);
static void decrypt (void);
static unsigned char get_f (unsigned char entry);
static void init_test_vec (void);
static void backup_test_vec_block (void);
static void skip_test_vec_block (void);
static Boolean end_of_test_vec (void);
static unsigned char get_test_vec_byte (void);
static void get_test_vec_key (unsigned char *ptr);
static void get_test_vec_block (unsigned char *ptr);
static Boolean compare_test_vec_block (unsigned char **ptr);

/* Private file-scope variables */

/* -----------------------------------------------------------------------------
    message table
   ----------------------------------------------------------------------------- */
static unsigned char banner [45] = "\r\nSKIPJACK for PIC\r\nCopyright 1998 Eric Smith";
static unsigned char crlf [] = {
        CR, LF, 0
};
static unsigned char donemsg [] = "Test completed.  Total vectors: ";
static unsigned char encmsg [] = "Encryptions ";
static unsigned char decmsg [] = "Decryptions ";
static unsigned char pcntmsg [] = "passed: ";
static unsigned char fcntmsg [] = ", failed: ";
static unsigned char passmsg [] = "  pass";
static unsigned char failmsg [] = "  FAIL!!!  Should be: ";
static unsigned char keymsg [] = "Key:         ";
static unsigned char plaintextmsg [] = "Plaintext:   ";
static unsigned char ciphertextmsg [] = "Ciphertext:  ";

/* -----------------------------------------------------------------------------
    and finally, the actual test vectors
   ----------------------------------------------------------------------------- */
static unsigned char test_vec_tab [] = {
        
        /* This vector is from the SKIPJACK protocol specification: */
        0x00, 0x99, 0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11,   /* key */
        0x33, 0x22, 0x11, 0x00, 0xdd, 0xcc, 0xbb, 0xaa,   /* plaintext */
        0x25, 0x87, 0xca, 0xe2, 0x7a, 0x12, 0xd3, 0x00,   /* ciphertext */
       
        ...further values omitted here to shorten example
};

/* -----------------------------------------------------------------------------
    RAM allocation
   ----------------------------------------------------------------------------- */
static char count;
static unsigned char tot_vec;
static unsigned char good_enc;
static unsigned char bad_enc;
static unsigned char good_dec;
static unsigned char bad_dec;

/* -----------------------------------------------------------------------------
    SKIPJACK for Microchip's midrange PIC processors
    Copyright 1998, 1999 Eric Smith
    $Id: skipjack.inc,v 1.5 1999/05/07 02:07:39 eric Exp $
    WARNING: This software may be subject to export controls
    http://www.brouhaha.com/~eric/pic/
    http://www.brouhaha.com/~eric/crypto/
    SKIPJACK is free software; you can redistribute it and/or modify it
    under the terms of the GNU General Public License version 2 as published by
    the Free Software Foundation.  Note that I am not granting permission to
    redistribute or modify SKIPJACK under the terms of any later version of
    the General Public License.
    This program is distributed in the hope that it will be useful (or at least
    amusing), but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
    Public License for more details.
    You should have received a copy of the GNU General Public License along with
    this program (in the file "COPYING"); if not, write to the Free Software
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
    This implementation is believed to be compliant with the SKIPJACK
    algorithm as described in "SKIPJACK and KEA Algorithm Specifications"
    Version 2.0 dated 29 May 1998, which is available from the National
    Institute for Standards and Technology:
          http://csrc.nist.gov/encryption/skipjack-kea.htm
    This software has been tested using the GPASM assembler:
          http://reality.sgi.com/jamesb/gpasm/
    and the PSIM simulator:
          http://www.brouhaha.com/~eric/pic/psim.html
    It may work with Microchip's MPASM assembler, but has not been tested.
   -----------------------------------------------------------------------------
   #define inline_g               ; bigger code, but slightly faster
   -----------------------------------------------------------------------------
    constants for SKIPJACK
   -----------------------------------------------------------------------------
    Don't assume that just because keylen, blocklen, and rounds are
    defined as constants, that you can change them arbitrarily and
    expect the code to still work.  It's mostly hard-coded.
    In particular, you might be tempted to change the key length to
    something other than ten bytes.  As written, the code will actually
    behave in the expected and predictable manner with any key length
    that is even.  However, lengths other than ten bytes are not
    compliant with the SKIPJACK specification.  Longer lengths can not
    be assumed to be more secure.  I suspect that key lengths that are a
    multiple of four are probably very insecure.
   -----------------------------------------------------------------------------
    RAM allocation
   ----------------------------------------------------------------------------- */
static unsigned char *temp_ptr;
static unsigned char text [8];                   /* used for both plaintext and ciphertext */
static char round;
static unsigned char temp;

/* -----------------------------------------------------------------------------
    SKIP test vectors - part of SKIPJACK distribution
    Copyright 1998, 1999 Eric L. Smith
    $Id: testvec.inc,v 1.3 1999/05/07 02:07:39 eric Exp $
    WARNING: This software may be subject to export controls
    http://www.brouhaha.com/~eric/pic/
    http://www.brouhaha.com/~eric/crypto/
    SKIPJACK is free software; you can redistribute it and/or modify it
    under the terms of the GNU General Public License version 2 as published by
    the Free Software Foundation.  Note that I am not granting permission to
    redistribute or modify SKIPJACK under the terms of any later version of
    the General Public License.
    This program is distributed in the hope that it will be useful (or at least
    amusing), but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
    Public License for more details.
    You should have received a copy of the GNU General Public License along with
    this program (in the file "COPYING"); if not, write to the Free Software
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
    This software has been tested using the GPASM assembler:
          http://reality.sgi.com/jamesb/gpasm/
    and the PSIM simulator:
          http://www.brouhaha.com/~eric/pic/psim.html
    It may work with Microchip's MPASM assembler, but has not been tested.
   -----------------------------------------------------------------------------
   -----------------------------------------------------------------------------
    RAM definitions
   ----------------------------------------------------------------------------- */
static unsigned char *vec_ptr;
static unsigned char key [10];

/*
*************************************************************************
* print_key                                                             *
*************************************************************************
*
*
* utility functions
*
*/
static void print_key (void)
{
    unsigned char *ptr;                          /* [Originally in FSR0] */

    msgout (keymsg);
    ptr = key;
    count = KEYLEN;

    while (True) {
        outhb (*ptr);
        ptr++;
        if (--count == 0)
            break;
        xmit ('.');
    }
}


/*
*************************************************************************
* print_plaintext                                                       *
*************************************************************************
*/
static void print_plaintext (void)
{
    msgout (plaintextmsg);
    print_block ();
}


/*
*************************************************************************
* print_ciphertext                                                      *
*************************************************************************
*/
static void print_ciphertext (void)
{
    msgout (ciphertextmsg);
    print_block ();
}


/*
*************************************************************************
* print_block                                                           *
*************************************************************************
*/
static void print_block (void)
{
    unsigned char *ptr;                          /* [Originally in FSR0] */

    ptr = text;
    count = BLOCKLEN;

    while (True) {
        outhb (*ptr);
        ptr++;
        if (--count == 0)
            break;
        xmit ('.');
    }
}


/*
*************************************************************************
* outhb                                                                 *
*************************************************************************
*
*
* output a byte in hexadecimal
* uses temp
*
*
* Parameters:
*
*    unsigned char c                                [Originally in W; In]
*/
static void outhb (unsigned char c)
{
    temp = c;
    outhd ((temp >> 4) | (temp << 4));
    outhd (temp);
}


/*
*************************************************************************
* outhd                                                                 *
*************************************************************************
*
* fall into outhd
*
* output a hex digit
*
*
* Parameters:
*
*    unsigned char c                                [Originally in W; In]
*/
static void outhd (unsigned char c)
{
    unsigned char the_temp;

    c &= 0x0f;
    the_temp = c;
    c += 0xf6;
    if (c < the_temp)
        c += 0x07;
    xmit (c + 0x3a);
}


/*
*************************************************************************
* xmit                                                                  *
*************************************************************************
*
* fall into xmit
*
* serial transmit character
*
*
* Parameters:
*
*    unsigned char c                                [Originally in W; In]
*/
static void xmit (unsigned char c)
{
    sim_output (c);                              /* works for simulator only */
}


/*
*************************************************************************
* msgout                                                                *
*************************************************************************
*
*
* message output subroutine
*
*
* Parameters:
*
*    unsigned char *message                         [Originally in W; In]
*/
static void msgout (unsigned char *message)
{
    temp_ptr = message;
    while (*temp_ptr != 0) {
        xmit (*temp_ptr);
        temp_ptr++;
    }
}


/*
*************************************************************************
* reset                                                                 *
*************************************************************************
*
*
* initialization code
*
*/
void reset (void)
{
    unsigned char *ptr;                          /* [Originally in FSR0] */

    TRISA = 0xff;                                /* all port pins are inputs (or inactive
                                                    open-drain outputs) */
    TRISB = 0xff;
    PORTA = 0;
    PORTB = 0;
    tot_vec = 0;
    good_enc = 0;
    bad_enc = 0;
    good_dec = 0;
    bad_dec = 0;
    msgout (banner);

    /* -----------------------------------------------------------------------------
        main loop
       ----------------------------------------------------------------------------- */
    init_test_vec ();
    do {
        tot_vec++;
        get_test_vec_key (key);
        print_key ();
        msgout (crlf);
        get_test_vec_block (text);
        print_plaintext ();
        msgout (crlf);
        encrypt ();
        print_ciphertext ();
        ptr = text;

        if (compare_test_vec_block (&ptr)) {
            good_enc++;
            msgout (passmsg);
        } else {
            bad_enc++;
            msgout (failmsg);
            backup_test_vec_block ();
            get_test_vec_block (ptr);
            print_block ();
        }

        msgout (crlf);
        decrypt ();
        print_plaintext ();
        ptr = text;
        backup_test_vec_block ();
        backup_test_vec_block ();

        if (compare_test_vec_block (&ptr)) {
            good_dec++;
            msgout (passmsg);
        } else {
            bad_dec++;
            msgout (failmsg);
            backup_test_vec_block ();
            get_test_vec_block (ptr);
            print_block ();
        }

        msgout (crlf);
        skip_test_vec_block ();
        msgout (crlf);
        msgout (crlf);
    } while (!end_of_test_vec ());

    msgout (donemsg);
    outhb (tot_vec);
    msgout (crlf);
    msgout (encmsg);
    msgout (pcntmsg);
    outhb (good_enc);
    msgout (fcntmsg);
    outhb (bad_enc);
    msgout (crlf);
    msgout (decmsg);
    msgout (pcntmsg);
    outhb (good_dec);
    msgout (fcntmsg);
    outhb (bad_dec);
    msgout (crlf);
    while (True)
        ;
}


/*
*************************************************************************
* half_g                                                                *
*************************************************************************
*
* Parameters:
*
*    unsigned char *ptr                             [Originally in FSR0; In]
*
* Result:
*
*    unsigned char *                                [Originally in FSR0]
*/
static unsigned char * half_g (unsigned char *ptr)
{
    text [2] ^= get_f (*ptr ^ text [3]);
    ptr++;                                       /* key length is even, so this will never
                                                      pass the end of the table */
    text [3] ^= get_f (*ptr ^ text [2]);
    if (++ptr == &key [KEYLEN])
        ptr = key;
    return ptr;
}


/*
*************************************************************************
* encrypt                                                               *
*************************************************************************
*/
static void encrypt (void)
{
    unsigned char *ptr;                          /* [Originally in FSR0] */

    ptr = key;
    round = 0;
    do {
        temp = text [6];                         /* rotate plaintext right 16 bits */
        text [6] = text [4];
        text [4] = text [2];
        text [2] = text [0];
        text [0] = temp;
        temp = text [7];
        text [7] = text [5];
        text [5] = text [3];
        text [3] = text [1];
        text [1] = temp;
        if (round & BIT3) {
            text [4] ^= text [2];                /* rule b */
            text [5] ^= (round + 1) ^ text [3];
        }
        ptr = half_g (ptr);
        ptr = half_g (ptr);
        if ((round & BIT3) == 0) {
            text [0] ^= text [2];                /* rule a */
            text [1] ^= (round + 1) ^ text [3];
        }
    } while ((++round & BIT5) == 0);
}


/*
*************************************************************************
* half_g_inv                                                            *
*************************************************************************
*
* Parameters:
*
*    unsigned char *ptr                             [Originally in FSR0; In]
*
* Result:
*
*    unsigned char *                                [Originally in FSR0]
*/
static unsigned char * half_g_inv (unsigned char *ptr)
{
    text [1] ^= get_f (*ptr ^ text [0]);
    ptr--;
    text [0] ^= get_f (*ptr ^ text [1]);
    if (--ptr == &key [-1])
        ptr = &key [KEYLEN - 1];
    return ptr;
}


/*
*************************************************************************
* decrypt                                                               *
*************************************************************************
*/
static void decrypt (void)
{
    unsigned char *ptr;                          /* [Originally in FSR0] */

    ptr = &key [(ROUNDS * 4 - 1) % KEYLEN];
    round = 31;
    do {
        temp = text [0];                         /* rotate plaintext left 16 bits */
        text [0] = text [2];
        text [2] = text [4];
        text [4] = text [6];
        text [6] = temp;
        temp = text [1];
        text [1] = text [3];
        text [3] = text [5];
        text [5] = text [7];
        text [7] = temp;
        if ((round & BIT3) == 0) {
            text [6] ^= text [0];                /* rule a inv */
            text [7] ^= (round + 1) ^ text [1];
        }
        ptr = half_g_inv (ptr);
        ptr = half_g_inv (ptr);
        if (round & BIT3) {
            text [2] ^= text [0];                /* rule b inv */
            text [3] ^= (round + 1) ^ text [1];
        }
    } while ((--round & BIT7) == 0);
}


/*
*************************************************************************
* get_f                                                                 *
*************************************************************************
*
*
* SKIPJACK F table
*
* get an entry from the f table
* On entry:      table index in W.  high byte of table address in pclath.
* On return:     table value in W.
*
* Parameters:
*
*    unsigned char entry                            [Originally in W; In]
*
* Result:
*
*    unsigned char                                  [Originally in W]
*/
static unsigned char get_f (unsigned char entry)
{
    static const unsigned char table [256] = {
        0xa3, 0xd7, 0x09, 0x83, 0xf8, 0x48, 0xf6, 0xf4, 
        0xb3, 0x21, 0x15, 0x78, 0x99, 0xb1, 0xaf, 0xf9, 
        0xe7, 0x2d, 0x4d, 0x8a, 0xce, 0x4c, 0xca, 0x2e, 
        0x52, 0x95, 0xd9, 0x1e, 0x4e, 0x38, 0x44, 0x28, 
        0x0a, 0xdf, 0x02, 0xa0, 0x17, 0xf1, 0x60, 0x68, 
        0x12, 0xb7, 0x7a, 0xc3, 0xe9, 0xfa, 0x3d, 0x53, 
        0x96, 0x84, 0x6b, 0xba, 0xf2, 0x63, 0x9a, 0x19, 
        0x7c, 0xae, 0xe5, 0xf5, 0xf7, 0x16, 0x6a, 0xa2, 
        0x39, 0xb6, 0x7b, 0x0f, 0xc1, 0x93, 0x81, 0x1b, 
        0xee, 0xb4, 0x1a, 0xea, 0xd0, 0x91, 0x2f, 0xb8, 
        0x55, 0xb9, 0xda, 0x85, 0x3f, 0x41, 0xbf, 0xe0, 
        0x5a, 0x58, 0x80, 0x5f, 0x66, 0x0b, 0xd8, 0x90, 
        0x35, 0xd5, 0xc0, 0xa7, 0x33, 0x06, 0x65, 0x69, 
        0x45, 0x00, 0x94, 0x56, 0x6d, 0x98, 0x9b, 0x76, 
        0x97, 0xfc, 0xb2, 0xc2, 0xb0, 0xfe, 0xdb, 0x20, 
        0xe1, 0xeb, 0xd6, 0xe4, 0xdd, 0x47, 0x4a, 0x1d, 
        0x42, 0xed, 0x9e, 0x6e, 0x49, 0x3c, 0xcd, 0x43, 
        0x27, 0xd2, 0x07, 0xd4, 0xde, 0xc7, 0x67, 0x18, 
        0x89, 0xcb, 0x30, 0x1f, 0x8d, 0xc6, 0x8f, 0xaa, 
        0xc8, 0x74, 0xdc, 0xc9, 0x5d, 0x5c, 0x31, 0xa4, 
        0x70, 0x88, 0x61, 0x2c, 0x9f, 0x0d, 0x2b, 0x87, 
        0x50, 0x82, 0x54, 0x64, 0x26, 0x7d, 0x03, 0x40, 
        0x34, 0x4b, 0x1c, 0x73, 0xd1, 0xc4, 0xfd, 0x3b, 
        0xcc, 0xfb, 0x7f, 0xab, 0xe6, 0x3e, 0x5b, 0xa5, 
        0xad, 0x04, 0x23, 0x9c, 0x14, 0x51, 0x22, 0xf0, 
        0x29, 0x79, 0x71, 0x7e, 0xff, 0x8c, 0x0e, 0xe2, 
        0x0c, 0xef, 0xbc, 0x72, 0x75, 0x6f, 0x37, 0xa1, 
        0xec, 0xd3, 0x8e, 0x62, 0x8b, 0x86, 0x10, 0xe8, 
        0x08, 0x77, 0x11, 0xbe, 0x92, 0x4f, 0x24, 0xc5, 
        0x32, 0x36, 0x9d, 0xcf, 0xf3, 0xa6, 0xbb, 0xac, 
        0x5e, 0x6c, 0xa9, 0x13, 0x57, 0x25, 0xb5, 0xe3, 
        0xbd, 0xa8, 0x3a, 0x01, 0x05, 0x59, 0x2a, 0x46
    };

    return table [entry];
}


/*
*************************************************************************
* init_test_vec                                                         *
*************************************************************************
*
*
* init_test_vec
*
*/
static void init_test_vec (void)
{
    vec_ptr = test_vec_tab;
}


/*
*************************************************************************
* backup_test_vec_block                                                 *
*************************************************************************
*
*
* backup_test_vec_block
*
*/
static void backup_test_vec_block (void)
{
    vec_ptr -= BLOCKLEN;
}


/*
*************************************************************************
* skip_test_vec_block                                                   *
*************************************************************************
*
*
* skip_test_vec_block
*
*/
static void skip_test_vec_block (void)
{
    vec_ptr += BLOCKLEN;
}


/*
*************************************************************************
* end_of_test_vec                                                       *
*************************************************************************
*
*
* end_of_test_vec
*
*
* Parameters:
*
*
* Result:
*
*    Boolean                                        [Originally condition EQ]
*/
static Boolean end_of_test_vec (void)
{
    return vec_ptr == &test_vec_tab [sizeof(test_vec_tab)];
}


/*
*************************************************************************
* get_test_vec_byte                                                     *
*************************************************************************
*
*
* get one byte from test vector array, and advance pointer
*
*
* Parameters:
*
*
* Result:
*
*    unsigned char                                  [Originally in W]
*/
static unsigned char get_test_vec_byte (void)
{
    return *vec_ptr++;
}


/*
*************************************************************************
* get_test_vec_key                                                      *
*************************************************************************
*
*
* copies keylen bytes of data from the test vector array into the RAM
* pointed to by FSR.
* on exit, the test vector pointer is increased by keylen, but FSR is
* unchanged
* uses count
*
*
* Parameters:
*
*    unsigned char *ptr                             [Originally in FSR0; In]
*/
static void get_test_vec_key (unsigned char *ptr)
{
    count = KEYLEN;
    do {
        *ptr++ = get_test_vec_byte ();
    } while (--count != 0);

    ptr -= KEYLEN;
}


/*
*************************************************************************
* get_test_vec_block                                                    *
*************************************************************************
*
*
* copies blocklen bytes of data from the test vector array into the RAM
* pointed to by FSR.
* on exit, the test vector pointer is increased by blocklen, but FSR is
* unchanged
* uses count
*
*
* Parameters:
*
*    unsigned char *ptr                             [Originally in FSR0; In]
*/
static void get_test_vec_block (unsigned char *ptr)
{
    count = BLOCKLEN;
    do {
        *ptr++ = get_test_vec_byte ();
    } while (--count != 0);

    ptr -= BLOCKLEN;
}


/*
*************************************************************************
* compare_test_vec_block                                                *
*************************************************************************
*
*
* compares blocklen bytes of data from the test vector array to the RAM
* pointed to by FSR.
* on exit, the test vector pointer is increased by blocklen, but FSR is
* unchanged.  The zero flag will be set if the test vector is equal to the
* RAM value.
* uses count, temp
*
*
* Parameters:
*
*    unsigned char **ptr                            [Originally in FSR0; InOut]
*
* Result:
*
*    Boolean                                        [Originally condition EQ]
*/
static Boolean compare_test_vec_block (unsigned char **ptr)
{
    unsigned char c;                             /* [Originally in W] */

    count = BLOCKLEN;
    temp = 0;
    do {
        c = get_test_vec_byte ();
        temp |= c ^ *(*ptr)++;
    } while (--count != 0);

    *ptr -= BLOCKLEN;

    /* set Z flag appropriately */
    return temp == 0;
}