
#pragma hdrstop
/* crypto/rijndael/rijndael.c */

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <openssl/rijndael.h>
#include <openssl/evp.h>
//---------------------------------------------------------------------------
static unsigned char k[32]={
	0x01,0x23,0x45,0x67,0x12,0x34,0x56,0x78,
	0x23,0x45,0x67,0x89,0x34,0x56,0x78,0x9A,
	0x11,0x33,0x55,0x77,0x22,0x44,0x66,0x88,
	0x33,0x55,0x77,0x99,0x44,0x66,0x88,0xAA
	};

static int k_len[3]={128,192,256};

#define DATA_LEN 16

static unsigned char in[DATA_LEN]={ 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x02, 0x24, 0x46, 0x68, 0x8A, 0xAC, 0xCE, 0xF0 };

static unsigned char c[3][DATA_LEN]={
        {0xD1,0x02,0x64,0x49,0x5C,0x6E,0x79,0xCF,0xB7,0xCB,0xF6,0xB0,0xE5,0x1B,0x07,0x66},
        {0x45,0xA4,0xFC,0x38,0x3E,0x98,0x61,0x86,0x43,0x8F,0x67,0xB1,0x27,0xD8,0x1B,0x6F},
        {0xC2,0xFB,0x40,0x7D,0xD8,0xEC,0x7F,0x96,0xAB,0xEF,0x62,0x31,0x98,0x36,0x31,0x4D}
        };

static unsigned char c_evp[3][DATA_LEN*2]={
  {0xD1,0x02,0x64,0x49,0x5C,0x6E,0x79,0xCF,0xB7,0xCB,0xF6,0xB0,0xE5,0x1B,0x07,0x66,
   0xFC,0x2B,0xC5,0xBA,0x2E,0x5E,0x40,0x21,0x32,0x27,0x49,0x77,0x84,0xF0,0x11,0x35},
  {0x45,0xA4,0xFC,0x38,0x3E,0x98,0x61,0x86,0x43,0x8F,0x67,0xB1,0x27,0xD8,0x1B,0x6F,
   0xA7,0x2B,0xEF,0x0C,0x9A,0x61,0x9A,0x4B,0x43,0x26,0x5A,0x1B,0x5E,0x66,0x0B,0x28},
  {0xC2,0xFB,0x40,0x7D,0xD8,0xEC,0x7F,0x96,0xAB,0xEF,0x62,0x31,0x98,0x36,0x31,0x4D,
   0x7D,0xA8,0x40,0x1E,0x1B,0x8C,0x5B,0x00,0x23,0xB1,0x12,0xE3,0xEE,0x9C,0x69,0xFA}
 };

static unsigned char d_evp[3][DATA_LEN*2]={
  {0xA5,0xA3,0x8B,0xC8,0x39,0xD8,0x9B,0x79,0x97,0x83,0x4F,0x69,0x17,0xAB,0xE6,0x96,
   0x84,0x9E,0xD5,0xA4,0xD9,0x23,0x3E,0x2A,0x43,0xF3,0x17,0x9A,0xDF,0x10,0x5E,0xE8},
  {0x81,0xDB,0xC6,0x1C,0x09,0xF4,0x40,0xB6,0x13,0xD2,0x0E,0x3E,0x3D,0xB5,0x20,0x6C,
   0x40,0x6F,0xF8,0xB6,0x0F,0x36,0xEC,0xAE,0xB8,0x1C,0x31,0x8A,0xFA,0x15,0x9D,0x57},
  {0x42,0x94,0xC0,0x5B,0x19,0xD1,0x6C,0x05,0x83,0xB5,0x1E,0xE0,0x31,0xB9,0x3E,0xC7,
   0xE8,0xE1,0x6C,0x05,0xD9,0x5D,0x19,0x71,0x14,0x08,0x39,0xD5,0x26,0xA6,0x44,0x9E}
 };

static unsigned char out[80];

int raw_test_encrypt_ecb( char out[80], int z )
{
 EVP_CIPHER *type;
 EVP_CIPHER_CTX ctx;
 int result;
     
 type=EVP_rijndael_ecb();
 result=EVP_CipherInit(&ctx, type, k, NULL, 1 );
 if (result!=1)
   {
    printf( "Rijndael_ecb - Init failed.\n" );
    return( 1 );
   }
 result=EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_SET_KEY_LENGTH, k_len[z]/8, NULL);
 if (result!=1)
   {
    printf( "Rijndael_ecb - set_key_length %d failed.\n", k_len[z] );
    return( 1 );
   }
 result=EVP_CipherInit(&ctx, NULL, k, NULL, 1 );
 if (result!=1)
   {
    printf( "Rijndael_ecb - Init failed.\n" );
    return( 1 );
   }
 result=Rijndael_Encrypt_ECB( &ctx, in, DATA_LEN*8, out, DATA_LEN*8);
 if (result!=(DATA_LEN*8))
   {
    printf("Rijndael_Encrypt_ECB failed for size %d.\n", k_len[z] );
    return( 1 );
   }
 return( 0 );
}

int raw_test_decrypt_ecb( char *out, char *in, int z )
{
 EVP_CIPHER *type;
 EVP_CIPHER_CTX ctx;
 int result;
     
 type=EVP_rijndael_ecb();
 result=EVP_CipherInit(&ctx, type, k, NULL, 0 );
 if (result!=1)
   {
    printf( "Rijndael_ecb - Init failed.\n" );
    return( 1 );
   }
 result=EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_SET_KEY_LENGTH, k_len[z]/8, NULL);
 if (result!=1)
   {
    printf( "Rijndael_ecb - set_key_length %d failed.\n", k_len[z] );
    return( 1 );
   }
 result=EVP_CipherInit(&ctx, NULL, k, NULL, 0 );
 if (result!=1)
   {
    printf( "Rijndael_ecb - Init failed.\n" );
    return( 1 );
   }
 result=Rijndael_Decrypt_ECB( &ctx, in, DATA_LEN*8, out, DATA_LEN*8);
 if (result!=(DATA_LEN*8))
   {
    printf("Rijndael_Decrypt_ECB failed for size %d.\n", k_len[z] );
    return( 1 );
   }
 return( 0 );
}

int raw_test()
{
 /* Rijndael_cipherInstance cipher;
 Rijndael_key key_d;
 Rijndael_key key;
 int i,err=0, result;
 Rijndael_cipherInstance cipher_d;
 EVP_CIPHER_CTX ctx, ctx2;*/
 int z, result, i;
 char out2[80];

 for (z=0; z<3; z++)
  {
    result=raw_test_encrypt_ecb( out, z );
    if (result) return( result );
    if (memcmp(out,&(c[z][0]),DATA_LEN) != 0)
        {
        printf("ecb Rijndael error encrypting for keysize %d\n",k_len[z]);
        printf("got     :");
        for (i=0; i<DATA_LEN; i++)
            printf("%02X ",out[i]);
        printf("\n");
        printf("expected:");
        for (i=0; i<DATA_LEN; i++)
            printf("%02X ",c[z][i]);
        printf("\n");
        return( 1 );
        }
    result=raw_test_decrypt_ecb( out2, out, z );
    if (result) return( result );
    if (memcmp(out2,in,DATA_LEN) != 0)
       {
	printf("ecb rijndael error decrypting for keysize %d\n",k_len[z]);
	printf("got     :");
	for (i=0; i<DATA_LEN; i++)
	  printf("%02X ",out2[i]);
	printf("\n");
	printf("expected:");
	for (i=0; i<DATA_LEN; i++)
	  printf("%02X ",in[i]);
	printf("\n");
	return( 1 );
       }
  }
 printf("ecb rijndael ok\n");
 return(0);
}

int evp_test()
{
  int result;
  int i, out_len, out_len2, out_len3, j;
  unsigned char out2[80];
  EVP_CIPHER_CTX ctx, octx;
  EVP_CIPHER *type;
  unsigned char *iv=NULL;

  for (i=0;i<3;i++)
    {
     memset( out, 0, 80 );
     type=EVP_rijndael_ecb();
     result=EVP_CipherInit(&ctx, type, k, iv, 1 );
     if (result!=1)
      {
        printf( "EVP_Rijndael_ecb - Init failed.\n" );
        return( 1 );
      }
    result=EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_SET_KEY_LENGTH, k_len[i]/8, NULL);
    if (result!=1)
      {
        printf( "EVP_Rijndael_ecb - set_key_length %d failed.\n", k_len[i] );
        return( 1 );
      }
     result=EVP_CipherInit(&ctx, NULL, k, iv, 1 );
     if (result!=1)
      {
        printf( "EVP_Rijndael_ecb - Init failed.\n" );
        return( 1 );
      }
     out_len=80;
     result=EVP_CipherUpdate(&ctx, out, &out_len, in, DATA_LEN );
     if (result!=1)
       {
	 printf( "EVP_Rijndael_ecb - CipherUpdate failed for %d.\n", k_len[i] );
	 return( 1 );
       }     
     out_len2=80-out_len;
     result=EVP_CipherFinal( &ctx, &out[out_len], &out_len2 );
     if (result!=1)
      {
	 printf( "EVP_Rijndael_ecb - CipherFinal failed for %d.\n", k_len[i] );
	 return( 1 );
       }
     out_len+=out_len2;
    if (memcmp(out,&(c_evp[i][0]),DATA_LEN*2) != 0)
        {
        printf("EVP_Rijndael_ecb error encrypting for keysize %d\n",k_len[i]);
        printf("got     :");
        for (j=0; j<DATA_LEN*2; j++)
            printf("%02X ",out[j]);
        printf("\n");
        printf("expected:");
        for (j=0; j<DATA_LEN*2; j++)
            printf("%02X ",c_evp[i][j]);
        printf("\n");
	return( 1 );
        }

     type=EVP_rijndael_ecb();
     result=EVP_CipherInit(&octx, type, k, iv, 0 );
     if (result!=1)
      {
        printf( "EVP_Rijndael_ecb - Init failed.\n" );
        return( 1 );
      }
    result=EVP_CIPHER_CTX_ctrl(&octx, EVP_CTRL_SET_KEY_LENGTH, k_len[i]/8, NULL);
    if (result!=1)
      {
        printf( "EVP_Rijndael_ecb - set_key_length %d failed.\n", k_len[i] );
        return( 1 );
      }
     result=EVP_CipherInit(&octx, NULL, k, iv, 0 );
     if (result!=1)
      {
        printf( "EVP_Rijndael_ecb - Init failed.\n" );
        return( 1 );
      }
     out_len2=80;
     result=EVP_CipherUpdate(&octx, out2, &out_len2, out, out_len );
     if (result!=1)
       {
	 printf( "EVP_Rijndael_ecb - CipherUpdate failed for %d.\n", k_len[i] );
	 return( 1 );
       }     
     out_len3=80-out_len2;
     result=EVP_CipherFinal( &octx, &out2[out_len2], &out_len3 );
     if (result!=1 && result!=0)
      {
	 printf( "EVP_Rijndael_ecb - CipherFinal failed for %d.\n", k_len[i] );
	 return( 1 );
       }
     out_len3+=out_len2;
     if (memcmp( out2, in, DATA_LEN ))
       {
	 printf( "EVP_Rijndael_ecb - decrypt failure for %d.\n", k_len[i] );
        printf("got     :");
        for (j=0; j<DATA_LEN*2; j++)
            printf("%02X ",out2[j]);
        printf("\n");
        printf("expected:");
        for (j=0; j<DATA_LEN*2; j++)
            printf("%02X ",in[j]);
        printf("\n");
	return( 1 );
       }
   }
  printf( "evp_ecb rijndael ok.\n" );
  return( 0 );
}

int evp_cbc_test()
{
  int result;
  int i, out_len, out_len2, out_len3, j;
  unsigned char out2[80];
  EVP_CIPHER_CTX ctx, octx;
  EVP_CIPHER *type;
  unsigned char *iv="1234567890ABCDEF";

  for (i=0;i<3;i++)
    {
     memset( out, 0, 80 );
     type=EVP_rijndael_cbc();
     result=EVP_CipherInit(&ctx, type, k, iv, 1 );
     if (result!=1)
      {
        printf( "EVP_Rijndael_cbc - Init failed.\n" );
        return( 1 );
      }
    result=EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_SET_KEY_LENGTH, k_len[i]/8, NULL);
    if (result!=1)
      {
        printf( "EVP_Rijndael_cbc - set_key_length %d failed.\n", k_len[i] );
        return( 1 );
      }
     result=EVP_CipherInit(&ctx, NULL, k, iv, 1 );
     if (result!=1)
      {
        printf( "EVP_Rijndael_cbc - Init failed.\n" );
        return( 1 );
      }
     out_len=80;
     result=EVP_CipherUpdate(&ctx, out, &out_len, in, DATA_LEN );
     if (result!=1)
       {
	 printf( "EVP_Rijndael_cbc - CipherUpdate failed for %d.\n", k_len[i] );
	 return( 1 );
       }     
     out_len2=80-out_len;
     result=EVP_CipherFinal( &ctx, &out[out_len], &out_len2 );
     if (result!=1)
      {
	 printf( "EVP_Rijndael_cbc - CipherFinal failed for %d.\n", k_len[i] );
	 return( 1 );
       }
     out_len+=out_len2;
    if (memcmp(out,&(d_evp[i][0]),DATA_LEN*2) != 0)
        {
        printf("EVP_Rijndael_cbc error encrypting for keysize %d\n",k_len[i]);
        printf("got     :");
        for (j=0; j<DATA_LEN*2; j++)
            printf("0x%02X,",out[j]);
        printf("\n");
        printf("expected:");
        for (j=0; j<DATA_LEN*2; j++)
            printf("%02X ",d_evp[i][j]);
        printf("\n");
	return( 1 );
        }

     type=EVP_rijndael_cbc();
     result=EVP_CipherInit(&octx, type, k, iv, 0 );
     if (result!=1)
      {
        printf( "EVP_Rijndael_cbc - Init failed.\n" );
        return( 1 );
      }
    result=EVP_CIPHER_CTX_ctrl(&octx, EVP_CTRL_SET_KEY_LENGTH, k_len[i]/8, NULL);
    if (result!=1)
      {
        printf( "EVP_Rijndael_cbc - set_key_length %d failed.\n", k_len[i] );
        return( 1 );
      }
     result=EVP_CipherInit(&octx, NULL, k, iv, 0 );
     if (result!=1)
      {
        printf( "EVP_Rijndael_cbc - Init failed.\n" );
        return( 1 );
      }     out_len2=80;
     result=EVP_CipherUpdate(&octx, out2, &out_len2, out, out_len );
     if (result!=1)
       {
	 printf( "EVP_Rijndael_cbc - CipherUpdate failed for %d.\n", k_len[i] );
	 return( 1 );
       }     
     out_len3=80-out_len2;
     result=EVP_CipherFinal( &octx, &out2[out_len2], &out_len3 );
     if (result!=0 && result!=1)
      {
	 printf( "EVP_Rijndael_cbc - CipherFinal failed for %d.\n", k_len[i] );
	 return( 1 );
       }
     out_len3+=out_len2;
     if (memcmp( out2, in, DATA_LEN ))
       {
	 printf( "EVP_Rijndael_cbc - decrypt failure for %d.\n", k_len[i] );
        printf("got     :");
        for (j=0; j<DATA_LEN*2; j++)
            printf("%02X ",out2[j]);
        printf("\n");
        printf("expected:");
        for (j=0; j<DATA_LEN*2; j++)
            printf("%02X ",in[j]);
        printf("\n");
	return( 1 );
       }
   }
  printf( "evp_cbc rijndael ok.\n" );
  return( 0 );
}

int main(int argc, char *argv[])
{
  int result;
  result=raw_test();
  if (result) return( result );
  result=evp_test();
  if (result) return( result );
  result=evp_cbc_test();
  if (result) return( result );
  return( 0 );
}

