SVN-Revision: 16550master
parent
f1a87ef24a
commit
c1a4eef483
@ -0,0 +1,361 @@ |
|||||||
|
/*
|
||||||
|
* 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; |
||||||
|
} |
||||||
|
|
Loading…
Reference in new issue