123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361 |
- /*
- * Copyright (C) 2009 Gabor Juhos <juhosg@openwrt.org>
- *
- * This program 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.
- *
- * This code was based on:
- * PC1 Cipher Algorithm ( Pukall Cipher 1 )
- * By Alexander PUKALL 1991
- * free code no restriction to use
- * please include the name of the Author in the final software
- * the Key is 128 bits
- * http://membres.lycos.fr/pc1/
- *
- */
- #include <stdio.h>
- #include <stdlib.h>
- #include <stdint.h>
- #include <string.h>
- #include <unistd.h> /* for unlink() */
- #include <libgen.h>
- #include <getopt.h> /* for getopt() */
- #include <stdarg.h>
- #include <errno.h>
- #include <sys/stat.h>
- struct pc1_ctx {
- unsigned short ax;
- unsigned short bx;
- unsigned short cx;
- unsigned short dx;
- unsigned short si;
- unsigned short tmp;
- unsigned short x1a2;
- unsigned short x1a0[8];
- unsigned short res;
- unsigned short i;
- unsigned short inter;
- unsigned short cfc;
- unsigned short cfd;
- unsigned short compte;
- unsigned char cle[17];
- short c;
- };
- static void pc1_finish(struct pc1_ctx *pc1)
- {
- /* erase all variables */
- memset(pc1, 0, sizeof(struct pc1_ctx));
- }
- static void pc1_code(struct pc1_ctx *pc1)
- {
- pc1->dx = pc1->x1a2 + pc1->i;
- pc1->ax = pc1->x1a0[pc1->i];
- pc1->cx = 0x015a;
- pc1->bx = 0x4e35;
- pc1->tmp = pc1->ax;
- pc1->ax = pc1->si;
- pc1->si = pc1->tmp;
- pc1->tmp = pc1->ax;
- pc1->ax = pc1->dx;
- pc1->dx = pc1->tmp;
- if (pc1->ax != 0) {
- pc1->ax = pc1->ax * pc1->bx;
- }
- pc1->tmp = pc1->ax;
- pc1->ax = pc1->cx;
- pc1->cx = pc1->tmp;
- if (pc1->ax != 0) {
- pc1->ax = pc1->ax * pc1->si;
- pc1->cx = pc1->ax + pc1->cx;
- }
- pc1->tmp = pc1->ax;
- pc1->ax = pc1->si;
- pc1->si = pc1->tmp;
- pc1->ax = pc1->ax * pc1->bx;
- pc1->dx = pc1->cx + pc1->dx;
- pc1->ax = pc1->ax + 1;
- pc1->x1a2 = pc1->dx;
- pc1->x1a0[pc1->i] = pc1->ax;
- pc1->res = pc1->ax ^ pc1->dx;
- pc1->i = pc1->i + 1;
- }
- static void pc1_assemble(struct pc1_ctx *pc1)
- {
- pc1->x1a0[0] = (pc1->cle[0] * 256) + pc1->cle[1];
- pc1_code(pc1);
- pc1->inter = pc1->res;
- pc1->x1a0[1] = pc1->x1a0[0] ^ ((pc1->cle[2]*256) + pc1->cle[3]);
- pc1_code(pc1);
- pc1->inter = pc1->inter ^ pc1->res;
- pc1->x1a0[2] = pc1->x1a0[1] ^ ((pc1->cle[4]*256) + pc1->cle[5]);
- pc1_code(pc1);
- pc1->inter = pc1->inter ^ pc1->res;
- pc1->x1a0[3] = pc1->x1a0[2] ^ ((pc1->cle[6]*256) + pc1->cle[7]);
- pc1_code(pc1);
- pc1->inter = pc1->inter ^ pc1->res;
- pc1->x1a0[4] = pc1->x1a0[3] ^ ((pc1->cle[8]*256) + pc1->cle[9]);
- pc1_code(pc1);
- pc1->inter = pc1->inter ^ pc1->res;
- pc1->x1a0[5] = pc1->x1a0[4] ^ ((pc1->cle[10]*256) + pc1->cle[11]);
- pc1_code(pc1);
- pc1->inter = pc1->inter ^ pc1->res;
- pc1->x1a0[6] = pc1->x1a0[5] ^ ((pc1->cle[12]*256) + pc1->cle[13]);
- pc1_code(pc1);
- pc1->inter = pc1->inter ^ pc1->res;
- pc1->x1a0[7] = pc1->x1a0[6] ^ ((pc1->cle[14]*256) + pc1->cle[15]);
- pc1_code(pc1);
- pc1->inter = pc1->inter ^ pc1->res;
- pc1->i = 0;
- }
- static unsigned char pc1_decrypt(struct pc1_ctx *pc1, short c)
- {
- pc1_assemble(pc1);
- pc1->cfc = pc1->inter >> 8;
- pc1->cfd = pc1->inter & 255; /* cfc^cfd = random byte */
- c = c ^ (pc1->cfc ^ pc1->cfd);
- for (pc1->compte = 0; pc1->compte <= 15; pc1->compte++) {
- /* we mix the plaintext byte with the key */
- pc1->cle[pc1->compte] = pc1->cle[pc1->compte] ^ c;
- }
- return c;
- }
- static unsigned char pc1_encrypt(struct pc1_ctx *pc1, short c)
- {
- pc1_assemble(pc1);
- pc1->cfc = pc1->inter >> 8;
- pc1->cfd = pc1->inter & 255; /* cfc^cfd = random byte */
- for (pc1->compte = 0; pc1->compte <= 15; pc1->compte++) {
- /* we mix the plaintext byte with the key */
- pc1->cle[pc1->compte] = pc1->cle[pc1->compte] ^ c;
- }
- c = c ^ (pc1->cfc ^ pc1->cfd);
- return c;
- }
- static void pc1_init(struct pc1_ctx *pc1)
- {
- memset(pc1, 0, sizeof(struct pc1_ctx));
- /* ('Remsaalps!123456') is the key used, you can change it */
- strcpy(pc1->cle, "Remsaalps!123456");
- }
- static void pc1_decrypt_buf(struct pc1_ctx *pc1, unsigned char *buf,
- unsigned len)
- {
- unsigned i;
- for (i = 0; i < len; i++)
- buf[i] = pc1_decrypt(pc1, buf[i]);
- }
- static void pc1_encrypt_buf(struct pc1_ctx *pc1, unsigned char *buf,
- unsigned len)
- {
- unsigned i;
- for (i = 0; i < len; i++)
- buf[i] = pc1_encrypt(pc1, buf[i]);
- }
- /*
- * Globals
- */
- static char *ifname;
- static char *progname;
- static char *ofname;
- static int decrypt;
- /*
- * Message macros
- */
- #define ERR(fmt, ...) do { \
- fflush(0); \
- fprintf(stderr, "[%s] *** error: " fmt "\n", \
- progname, ## __VA_ARGS__ ); \
- } while (0)
- #define ERRS(fmt, ...) do { \
- int save = errno; \
- fflush(0); \
- fprintf(stderr, "[%s] *** error: " fmt "\n", \
- progname, ## __VA_ARGS__, strerror(save)); \
- } while (0)
- void usage(int status)
- {
- FILE *stream = (status != EXIT_SUCCESS) ? stderr : stdout;
- struct board_info *board;
- fprintf(stream, "Usage: %s [OPTIONS...]\n", progname);
- fprintf(stream,
- "\n"
- "Options:\n"
- " -d decrypt instead of encrypt"
- " -i <file> read input from the file <file>\n"
- " -o <file> write output to the file <file>\n"
- " -h show this screen\n"
- );
- exit(status);
- }
- #define BUFSIZE (64 * 1024)
- int main(int argc, char *argv[])
- {
- struct pc1_ctx pc1;
- int res = EXIT_FAILURE;
- int err;
- struct stat st;
- char *buf;
- unsigned total;
- FILE *outfile, *infile;
- progname = basename(argv[0]);
- while ( 1 ) {
- int c;
- c = getopt(argc, argv, "di:o:h");
- if (c == -1)
- break;
- switch (c) {
- case 'd':
- decrypt = 1;
- break;
- case 'i':
- ifname = optarg;
- break;
- case 'o':
- ofname = optarg;
- break;
- case 'h':
- usage(EXIT_SUCCESS);
- break;
- default:
- usage(EXIT_FAILURE);
- break;
- }
- }
- if (ifname == NULL) {
- ERR("no input file specified");
- goto err;
- }
- if (ofname == NULL) {
- ERR("no output file specified");
- goto err;
- }
- err = stat(ifname, &st);
- if (err){
- ERRS("stat failed on %s", ifname);
- goto err;
- }
- total = st.st_size;
- buf = malloc(BUFSIZE);
- if (!buf) {
- ERR("no memory for buffer\n");
- goto err;
- }
- infile = fopen(ifname, "r");
- if (infile == NULL) {
- ERRS("could not open \"%s\" for reading", ifname);
- goto err_free;
- }
- outfile = fopen(ofname, "w");
- if (outfile == NULL) {
- ERRS("could not open \"%s\" for writing", ofname);
- goto err_close_in;
- }
- pc1_init(&pc1);
- while (total > 0) {
- unsigned datalen;
- if (total > BUFSIZE)
- datalen = BUFSIZE;
- else
- datalen = total;
- errno = 0;
- fread(buf, datalen, 1, infile);
- if (errno != 0) {
- ERRS("unable to read from file %s", ifname);
- goto err_close_out;
- }
- if (decrypt)
- pc1_decrypt_buf(&pc1, buf, datalen);
- else
- pc1_encrypt_buf(&pc1, buf, datalen);
- errno = 0;
- fwrite(buf, datalen, 1, outfile);
- if (errno) {
- ERRS("unable to write to file %s", ofname);
- goto err_close_out;
- }
- total -= datalen;
- }
- pc1_finish(&pc1);
- res = EXIT_SUCCESS;
- out_flush:
- fflush(outfile);
- err_close_out:
- fclose(outfile);
- if (res != EXIT_SUCCESS) {
- unlink(ofname);
- }
- err_close_in:
- fclose(infile);
- err_free:
- free(buf);
- err:
- return res;
- }
|