#include #include #include #include void usage(const char *app, const char *msg) { if(msg != NULL) { fprintf(stderr, msg); fprintf(stderr, " "); } fprintf(stderr, "Usage:\n"); fprintf(stderr, "\t%s [e|d] old.bin new.bin\n\n", app); fprintf(stderr, "First argument should be `e' for encrypt, `d' for decrypt.\n"); } /* Actual codec action happens here */ int ww_crypt_core(FILE *ifp, FILE *ofp, int dir) { int ret = 0; uint8_t last, buf; uint8_t byte_cnt; uint8_t c; byte_cnt = 0; for(;;) { if(fread(&c, 1, 1, ifp) != 1) { if(feof(ifp)) /* End of file reached */ break; /* Otherwise it was an error! */ ret = -1; break; } if(byte_cnt == 0) /* Reset last to 0xFF for each XMODEM sector */ last = 0xFF; if(dir) { /* Encrypt */ c ^= last; buf = c; }else{ /* Decrypt */ buf = c; c ^= last; } last = buf; if(fwrite(&c, 1, 1, ofp) != 1) { /* Had to be an error! */ ret = -1; break; } byte_cnt++; byte_cnt &= 0x7F; /* XMODEM sectors are every 0x80 bytes */ } return ret; } int ww_crypt(const char *infn, const char *outfn, int dir) { int ret = 0; FILE *ifp, *ofp; ifp = fopen(infn, "rb"); if(ifp == NULL) { ret = -1; goto fail_noclose; } ofp = fopen(outfn, "wb"); if(ofp == NULL) { ret = -1; goto fail_closeifp; } if(ww_crypt_core(ifp, ofp, dir)) { ret = -1; goto fail_closeall; } fail_closeall: fclose(ofp); fail_closeifp: fclose(ifp); fail_noclose: return ret; } int ww_decrypt(const char *infn, const char *outfn) { return ww_crypt(infn, outfn, 0); } int ww_encrypt(const char *infn, const char *outfn) { return ww_crypt(infn, outfn, 1); } int main(int argc, const char *argv[]) { int ret = -1; fprintf(stderr, "WW_CODEC (c)2014 Alex \"trap15\" Marshall\n"); if(argc < 3) { usage(argv[0], "Too few arguments."); return EXIT_FAILURE; } switch(argv[1][0]) { case 'e': case 'E': ret = ww_encrypt(argv[2], argv[3]); break; case 'd': case 'D': ret = ww_decrypt(argv[2], argv[3]); break; default: usage(argv[0], "Invalid operation type."); return EXIT_FAILURE; } if(ret) { fprintf(stderr, "Error in codec!\n"); return EXIT_FAILURE; } return EXIT_SUCCESS; }