• source navigation  • diff markup  • identifier search  • freetext search  • 

Sources/firmware-utils/src/pc1crypt.c

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

This page was automatically generated by LXR 0.3.1.  •  OpenWrt