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