/* -----------------------------------------------------------------------
 *
 * Copyright (c) 2002-2005 Mr Ludovic FLAMENT <ludovic.flament@free.fr>, LIEVIN, FRANCE
 *
 * Termes :
 *
 * L'utilisation et/ou la redistribution de ce code (avec ou sans modification),
 * ainsi que de tous les composants du produit (librairies, documentation, exemples, ...)
 * est soumise aux termes de la licence qui vous est attribuée par son auteur.
 *
 * -----------------------------------------------------------------------
 */

#include <stdlib.h>
#include <stdio.h>

#include <include/ecctk-prototype.h>
#include <include/ecctk-cipher.h>

/* example is only for RC4
 */
s2byte encrypt_file_stepbystep()
{
	/* set input/output file name
	 */
	s1byte	infile[]	= "plain_file",
			outfile[]	= "protected_file";

	/* set a static 192 bits key
	 */
	u1byte	key[] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
					 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
					 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77};

	/* tmp buffer to read input file by block
	 * and buffer to write encrypted data
	 */
	u1byte	rbuff[8192],
			out[8192]; /* no padding with RC4 */

	s4byte	rsize = 0,
			outsize = 0;

	FILE	*file_in,
			*file_out;

	/* RC4 context
	 */
	RC4_CTX	*ctx;

	/* initialize the context
	 */
	ctx = RC4_Init(ECCTK_CIPHER_ENCRYPT, key, sizeof(key));
	if (ctx == NULL)
	{
		fprintf(stderr, "Initialize RC4 context failed\n");
		return EXIT_FAILURE;
	}

	/* open input file
	 */
	file_in = fopen(infile, "rb");
	if (file_in == NULL)
	{
		fprintf(stderr, "Open %s failed\n", infile);
		return EXIT_FAILURE;
	}
	
	/* open output file
	 */
	file_out = fopen(outfile, "wb");
	if (file_out == NULL)
	{
		fprintf(stderr, "Open %s failed\n", outfile);

		fclose(file_in);
		return EXIT_FAILURE;
	}

	/* read input file by block and update decrypt
	 */
	while (!feof(file_in))
	{
		if (outsize)
		{
			/* write encrypted data
			 */
			if (fwrite(out, sizeof(u1byte), outsize, file_out) <= 0)
			{
				fprintf(stderr, "Write on %s failed\n", outfile);

				fclose(file_in);
				fclose(file_out);
				RC4_Free(ctx);
				return EXIT_FAILURE;
			}
		}

		/* read plain data
		 */
		rsize = fread(rbuff, sizeof(u1byte), sizeof(rbuff), file_in);
		if (rsize <= 0)
		{
			fprintf(stderr, "Read on %s failed\n", infile);

			fclose(file_in);
			fclose(file_out);
			RC4_Free(ctx);
			return EXIT_FAILURE;
		}

		/* update the read block
		 */
		outsize = RC4_Update(ctx, rbuff, out, rsize);
		if (outsize < ECCTK_CIPHER_NO_ERROR)
		{
			fprintf(stderr, "Update RC4 context failed (Error : %ld)\n", outsize);

			fclose(file_in);
			fclose(file_out);
			RC4_Free(ctx);
			return EXIT_FAILURE;
		}
	}

	/* finalize last block
	 */
	outsize = RC4_Final(ctx, out);
	if (outsize < ECCTK_CIPHER_NO_ERROR)
	{
		fprintf(stderr, "Finalize RC4 context failed (Error : %ld)\n", outsize);

		fclose(file_in);
		fclose(file_out);
		RC4_Free(ctx);
		return EXIT_FAILURE;
	}

	if (outsize)
	{
		/* write encrypted data
		 */
		if (fwrite(out, sizeof(u1byte), outsize, file_out) <= 0)
		{
			fprintf(stderr, "Write on %s failed\n", outfile);

			fclose(file_in);
			fclose(file_out);
			RC4_Free(ctx);
			return EXIT_FAILURE;
		}
	}

	fprintf(stdout, "Decrypt %s success, %s generated\n", infile, outfile);

	/* close file, free context
	 */
	fclose(file_in);
	fclose(file_out);
	RC4_Free(ctx);

	return EXIT_SUCCESS;
}
