xorcat.c (2374B)
1#include <unistd.h> 2#include <err.h> 3#include <stdbool.h> 4#include <string.h> 5#include <stdint.h> 6#include <stdio.h> 7#include <stdlib.h> 8 9static const char usage[] = "USAGE: xorcat [-h] [-m] KEYMASK"; 10 11void 12xorcat(uint8_t *indata, size_t insize, uint8_t *key, size_t keylen) 13{ 14 uint8_t writebuf[4098]; 15 size_t i, nout, pos; 16 17 pos = 0; 18 while (pos < insize) { 19 for (i = 0; i < sizeof(writebuf) && i < insize - pos; i++) 20 writebuf[i] = indata[pos + i] ^ key[(pos + i) % keylen]; 21 nout = write(STDOUT_FILENO, writebuf, i); 22 if (nout != i) err(1, "write"); 23 pos += i; 24 } 25} 26 27uint8_t * 28collect(size_t *size) 29{ 30 uint8_t readbuf[4098]; 31 uint8_t *data; 32 size_t nread, cap; 33 34 cap = 4098; 35 data = malloc(cap); 36 if (!data) err(1, "malloc"); 37 38 *size = 0; 39 while (1) { 40 nread = read(STDIN_FILENO, readbuf, sizeof(readbuf)); 41 if (nread <= 0) break; 42 if (cap < *size + nread) { 43 cap *= 2; 44 data = realloc(data, cap); 45 } 46 memcpy(data + *size, readbuf, nread); 47 *size += nread; 48 } 49 50 return data; 51} 52 53int 54main(int argc, const char **argv) 55{ 56 uint8_t *mask, *key, keyb; 57 const char *maskarg; 58 size_t keylen; 59 uint8_t *indata; 60 size_t insize; 61 bool markers; 62 ssize_t i; 63 64 if (argc <= 1) { 65 printf("%s\n", usage); 66 exit(0); 67 } 68 69 maskarg = NULL; 70 markers = false; 71 for (i = 1; i < argc; i++) { 72 if (!strcmp(argv[i], "-h")) { 73 printf("%s\n", usage); 74 exit(0); 75 } else if (!strcmp(argv[i], "-m")) { 76 markers = true; 77 } else if (maskarg) { 78 errx(1, "Multiple mask arguments"); 79 } else { 80 maskarg = argv[i]; 81 } 82 } 83 84 if (!maskarg) 85 errx(1, "Missing mask"); 86 87 if (strlen(maskarg) % 2) 88 errx(1, "Bad mask length"); 89 90 keylen = strlen(maskarg) / 2; 91 mask = calloc(keylen, 1); 92 key = calloc(keylen, 1); 93 if (!mask || !key) err(1, "malloc"); 94 95 for (i = 0; i < keylen; i++) { 96 if (!strncmp(argv[1] + 2 * i, "??", 2)) { 97 mask[i] = 1; 98 } else { 99 if (!sscanf(maskarg + 2 * i, "%02hhX", &keyb)) 100 errx(1, "Bad mask"); 101 key[i] = (uint8_t) keyb; 102 } 103 } 104 105 indata = collect(&insize); 106 while (1) { 107 if (markers) { 108 printf("\n"); 109 printf(">>>>>>>>>>>>>>>>>>>>>>>>>>>>> "); 110 for (i = 0; i < keylen; i++) 111 printf("%02X", key[i]); 112 printf("\n"); 113 fflush(stdout); 114 } 115 116 xorcat(indata, insize, key, keylen); 117 118 for (i = keylen - 1; i >= 0; i--) { 119 if (mask[i]) { 120 key[i] += 1; 121 if (key[i]) break; 122 } 123 } 124 if (i < 0) break; 125 } 126 127 free(key); 128 free(mask); 129}