Root/tools/firmware-utils/src/pc1crypt.c

1/*
2 * Copyright (C) 2009 Gabor Juhos <juhosg@openwrt.org>
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 2 as published
6 * by the Free Software Foundation.
7 *
8 * This code was based on:
9 * PC1 Cipher Algorithm ( Pukall Cipher 1 )
10 * By Alexander PUKALL 1991
11 * free code no restriction to use
12 * please include the name of the Author in the final software
13 * the Key is 128 bits
14 * http://membres.lycos.fr/pc1/
15 *
16 */
17
18#include <stdio.h>
19#include <stdlib.h>
20#include <stdint.h>
21#include <string.h>
22#include <unistd.h> /* for unlink() */
23#include <libgen.h>
24#include <getopt.h> /* for getopt() */
25#include <stdarg.h>
26#include <errno.h>
27#include <sys/stat.h>
28
29struct pc1_ctx {
30    unsigned short ax;
31    unsigned short bx;
32    unsigned short cx;
33    unsigned short dx;
34    unsigned short si;
35    unsigned short tmp;
36    unsigned short x1a2;
37    unsigned short x1a0[8];
38    unsigned short res;
39    unsigned short i;
40    unsigned short inter;
41    unsigned short cfc;
42    unsigned short cfd;
43    unsigned short compte;
44    unsigned char cle[17];
45    short c;
46};
47
48static void pc1_finish(struct pc1_ctx *pc1)
49{
50    /* erase all variables */
51    memset(pc1, 0, sizeof(struct pc1_ctx));
52}
53
54static void pc1_code(struct pc1_ctx *pc1)
55{
56    pc1->dx = pc1->x1a2 + pc1->i;
57    pc1->ax = pc1->x1a0[pc1->i];
58    pc1->cx = 0x015a;
59    pc1->bx = 0x4e35;
60
61    pc1->tmp = pc1->ax;
62    pc1->ax = pc1->si;
63    pc1->si = pc1->tmp;
64
65    pc1->tmp = pc1->ax;
66    pc1->ax = pc1->dx;
67    pc1->dx = pc1->tmp;
68
69    if (pc1->ax != 0) {
70        pc1->ax = pc1->ax * pc1->bx;
71    }
72
73    pc1->tmp = pc1->ax;
74    pc1->ax = pc1->cx;
75    pc1->cx = pc1->tmp;
76
77    if (pc1->ax != 0) {
78        pc1->ax = pc1->ax * pc1->si;
79        pc1->cx = pc1->ax + pc1->cx;
80    }
81
82    pc1->tmp = pc1->ax;
83    pc1->ax = pc1->si;
84    pc1->si = pc1->tmp;
85    pc1->ax = pc1->ax * pc1->bx;
86    pc1->dx = pc1->cx + pc1->dx;
87
88    pc1->ax = pc1->ax + 1;
89
90    pc1->x1a2 = pc1->dx;
91    pc1->x1a0[pc1->i] = pc1->ax;
92
93    pc1->res = pc1->ax ^ pc1->dx;
94    pc1->i = pc1->i + 1;
95}
96
97static void pc1_assemble(struct pc1_ctx *pc1)
98{
99    pc1->x1a0[0] = (pc1->cle[0] * 256) + pc1->cle[1];
100
101    pc1_code(pc1);
102    pc1->inter = pc1->res;
103
104    pc1->x1a0[1] = pc1->x1a0[0] ^ ((pc1->cle[2]*256) + pc1->cle[3]);
105    pc1_code(pc1);
106    pc1->inter = pc1->inter ^ pc1->res;
107
108    pc1->x1a0[2] = pc1->x1a0[1] ^ ((pc1->cle[4]*256) + pc1->cle[5]);
109    pc1_code(pc1);
110    pc1->inter = pc1->inter ^ pc1->res;
111
112    pc1->x1a0[3] = pc1->x1a0[2] ^ ((pc1->cle[6]*256) + pc1->cle[7]);
113    pc1_code(pc1);
114    pc1->inter = pc1->inter ^ pc1->res;
115
116    pc1->x1a0[4] = pc1->x1a0[3] ^ ((pc1->cle[8]*256) + pc1->cle[9]);
117    pc1_code(pc1);
118    pc1->inter = pc1->inter ^ pc1->res;
119
120    pc1->x1a0[5] = pc1->x1a0[4] ^ ((pc1->cle[10]*256) + pc1->cle[11]);
121    pc1_code(pc1);
122    pc1->inter = pc1->inter ^ pc1->res;
123
124    pc1->x1a0[6] = pc1->x1a0[5] ^ ((pc1->cle[12]*256) + pc1->cle[13]);
125    pc1_code(pc1);
126    pc1->inter = pc1->inter ^ pc1->res;
127
128    pc1->x1a0[7] = pc1->x1a0[6] ^ ((pc1->cle[14]*256) + pc1->cle[15]);
129    pc1_code(pc1);
130    pc1->inter = pc1->inter ^ pc1->res;
131
132    pc1->i = 0;
133}
134
135static unsigned char pc1_decrypt(struct pc1_ctx *pc1, short c)
136{
137    pc1_assemble(pc1);
138    pc1->cfc = pc1->inter >> 8;
139    pc1->cfd = pc1->inter & 255; /* cfc^cfd = random byte */
140
141    c = c ^ (pc1->cfc ^ pc1->cfd);
142    for (pc1->compte = 0; pc1->compte <= 15; pc1->compte++) {
143        /* we mix the plaintext byte with the key */
144        pc1->cle[pc1->compte] = pc1->cle[pc1->compte] ^ c;
145    }
146
147    return c;
148}
149
150static unsigned char pc1_encrypt(struct pc1_ctx *pc1, short c)
151{
152    pc1_assemble(pc1);
153    pc1->cfc = pc1->inter >> 8;
154    pc1->cfd = pc1->inter & 255; /* cfc^cfd = random byte */
155
156    for (pc1->compte = 0; pc1->compte <= 15; pc1->compte++) {
157        /* we mix the plaintext byte with the key */
158        pc1->cle[pc1->compte] = pc1->cle[pc1->compte] ^ c;
159    }
160    c = c ^ (pc1->cfc ^ pc1->cfd);
161
162    return c;
163}
164
165static void pc1_init(struct pc1_ctx *pc1)
166{
167    memset(pc1, 0, sizeof(struct pc1_ctx));
168
169    /* ('Remsaalps!123456') is the key used, you can change it */
170    strcpy(pc1->cle, "Remsaalps!123456");
171}
172
173static void pc1_decrypt_buf(struct pc1_ctx *pc1, unsigned char *buf,
174                unsigned len)
175{
176    unsigned i;
177
178    for (i = 0; i < len; i++)
179        buf[i] = pc1_decrypt(pc1, buf[i]);
180}
181
182static void pc1_encrypt_buf(struct pc1_ctx *pc1, unsigned char *buf,
183                unsigned len)
184{
185    unsigned i;
186
187    for (i = 0; i < len; i++)
188        buf[i] = pc1_encrypt(pc1, buf[i]);
189}
190
191/*
192 * Globals
193 */
194static char *ifname;
195static char *progname;
196static char *ofname;
197static int decrypt;
198
199/*
200 * Message macros
201 */
202#define ERR(fmt, ...) do { \
203    fflush(0); \
204    fprintf(stderr, "[%s] *** error: " fmt "\n", \
205            progname, ## __VA_ARGS__ ); \
206} while (0)
207
208#define ERRS(fmt, ...) do { \
209    int save = errno; \
210    fflush(0); \
211    fprintf(stderr, "[%s] *** error: " fmt "\n", \
212            progname, ## __VA_ARGS__, strerror(save)); \
213} while (0)
214
215void usage(int status)
216{
217    FILE *stream = (status != EXIT_SUCCESS) ? stderr : stdout;
218    struct board_info *board;
219
220    fprintf(stream, "Usage: %s [OPTIONS...]\n", progname);
221    fprintf(stream,
222"\n"
223"Options:\n"
224" -d decrypt instead of encrypt"
225" -i <file> read input from the file <file>\n"
226" -o <file> write output to the file <file>\n"
227" -h show this screen\n"
228    );
229
230    exit(status);
231}
232
233#define BUFSIZE (64 * 1024)
234
235int main(int argc, char *argv[])
236{
237    struct pc1_ctx pc1;
238    int res = EXIT_FAILURE;
239    int err;
240    struct stat st;
241    char *buf;
242    unsigned total;
243
244    FILE *outfile, *infile;
245
246    progname = basename(argv[0]);
247
248    while ( 1 ) {
249        int c;
250
251        c = getopt(argc, argv, "di:o:h");
252        if (c == -1)
253            break;
254
255        switch (c) {
256        case 'd':
257            decrypt = 1;
258            break;
259        case 'i':
260            ifname = optarg;
261            break;
262        case 'o':
263            ofname = optarg;
264            break;
265        case 'h':
266            usage(EXIT_SUCCESS);
267            break;
268        default:
269            usage(EXIT_FAILURE);
270            break;
271        }
272    }
273
274    if (ifname == NULL) {
275        ERR("no input file specified");
276        goto err;
277    }
278
279    if (ofname == NULL) {
280        ERR("no output file specified");
281        goto err;
282    }
283
284    err = stat(ifname, &st);
285    if (err){
286        ERRS("stat failed on %s", ifname);
287        goto err;
288    }
289
290    total = st.st_size;
291    buf = malloc(BUFSIZE);
292    if (!buf) {
293        ERR("no memory for buffer\n");
294        goto err;
295    }
296
297    infile = fopen(ifname, "r");
298    if (infile == NULL) {
299        ERRS("could not open \"%s\" for reading", ifname);
300        goto err_free;
301    }
302
303    outfile = fopen(ofname, "w");
304    if (outfile == NULL) {
305        ERRS("could not open \"%s\" for writing", ofname);
306        goto err_close_in;
307    }
308
309    pc1_init(&pc1);
310    while (total > 0) {
311        unsigned datalen;
312
313        if (total > BUFSIZE)
314            datalen = BUFSIZE;
315        else
316            datalen = total;
317
318        errno = 0;
319        fread(buf, datalen, 1, infile);
320        if (errno != 0) {
321            ERRS("unable to read from file %s", ifname);
322            goto err_close_out;
323        }
324
325        if (decrypt)
326            pc1_decrypt_buf(&pc1, buf, datalen);
327        else
328            pc1_encrypt_buf(&pc1, buf, datalen);
329
330        errno = 0;
331        fwrite(buf, datalen, 1, outfile);
332        if (errno) {
333            ERRS("unable to write to file %s", ofname);
334            goto err_close_out;
335        }
336
337        total -= datalen;
338    }
339    pc1_finish(&pc1);
340
341    res = EXIT_SUCCESS;
342
343 out_flush:
344    fflush(outfile);
345
346 err_close_out:
347    fclose(outfile);
348    if (res != EXIT_SUCCESS) {
349        unlink(ofname);
350    }
351
352 err_close_in:
353    fclose(infile);
354
355 err_free:
356    free(buf);
357
358 err:
359    return res;
360}
361
362

Archive Download this file



interactive