/* Handle s case. */ int p_handler(va_list args) { unsigned long int addr; addr = va_arg(args, unsigned long int); print_str("0x"); return convert_hex(addr); }
static char * convert_escape (struct type *type, const char *dest_charset, char *p, char *limit, struct obstack *output) { /* Skip the backslash. */ ADVANCE; switch (*p) { case '\\': obstack_1grow (output, '\\'); ++p; break; case 'x': ADVANCE; if (!isxdigit (*p)) error (_("\\x used with no following hex digits.")); p = convert_hex (type, p, limit, output); break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': p = convert_octal (type, p, limit, output); break; case 'u': case 'U': { int length = *p == 'u' ? 4 : 8; ADVANCE; if (!isxdigit (*p)) error (_("\\u used with no following hex digits")); p = convert_ucn (p, limit, dest_charset, output, length); } } return p; }
int main(int argc, char *argv[]) { FILE *in, *out; cencrypted_v1_header v1header; cencrypted_v2_pwheader v2header; uint8_t hmacsha1_key[20], aes_key[16], inbuf[CHUNK_SIZE], outbuf[CHUNK_SIZE]; uint32_t chunk_no; int hdr_version, c,i, optError = 0; char inFile[512], outFile[512], passphrase[512]; int iflag = 0, oflag = 0, pflag = 0, kflag = 0, verbose = 0; extern char *optarg; extern int optind, optopt; memset(inFile, 0, 512); memset(outFile, 0, 512); memset(passphrase, 0, 512); while((c = getopt(argc, argv, "hvi:o:p:k:")) != -1) { switch(c) { case 'h': usage("Help is on the way. Stay calm."); break; case 'v': verbose++; break; case 'i': if(optarg) strncpy(inFile, optarg, sizeof(inFile)-1); iflag = 1; break; case 'o': if (optarg) strncpy(outFile, optarg, sizeof(outFile)-1); oflag = 1; break; case 'p': if (optarg) strncpy(passphrase, optarg, sizeof(passphrase)-1); pflag = 1; break; case 'k': convert_hex(optarg, aes_key, 16); convert_hex(optarg+32, hmacsha1_key, 20); kflag=1; break; case '?': fprintf(stderr, "Unknown option: -%c\n", optopt); optError++; break; } } /* check to see if our user gave incorrect options */ if (optError) usage("Incorrect arguments."); if (strlen(inFile) == 0) { in = stdin; } else { if ((in = fopen(inFile, "rb")) == NULL) { fprintf(stderr, "Error: unable to open %s\n", inFile); exit(1); } } if (strlen(outFile) == 0) { out = stdout; } else { if ((out = fopen(outFile, "wb")) == NULL) { fprintf(stderr, "Error: unable to open %s\n", outFile); exit(1); } } if (!pflag && !kflag) { fprintf(stderr, "No Passphrase given.\n"); exit(1); } hdr_version = determine_header_version(in); if (verbose >= 1) { if (hdr_version > 0) { fprintf(stderr, "v%d header detected.\n", hdr_version); } else { fprintf(stderr, "unknown format.\n"); exit(1); } } if (hdr_version == 1) { fseek(in, (long) -sizeof(cencrypted_v1_header), SEEK_END); if (fread(&v1header, sizeof(cencrypted_v1_header), 1, in) < 1) { fprintf(stderr, "header corrupted?\n"), exit(1); } adjust_v1_header_byteorder(&v1header); if(!kflag) unwrap_v1_header(passphrase, &v1header, aes_key, hmacsha1_key); } if (hdr_version == 2) { fseek(in, 0L, SEEK_SET); if (fread(&v2header, sizeof(cencrypted_v2_pwheader), 1, in) < 1) { fprintf(stderr, "header corrupted?\n"), exit(1); } adjust_v2_header_byteorder(&v2header); dump_v2_header(&v2header); if(!kflag) unwrap_v2_header(passphrase, &v2header, aes_key, hmacsha1_key); CHUNK_SIZE = v2header.blocksize; } HMAC_CTX_init(&hmacsha1_ctx); HMAC_Init_ex(&hmacsha1_ctx, hmacsha1_key, sizeof(hmacsha1_key), EVP_sha1(), NULL); AES_set_decrypt_key(aes_key, CIPHER_KEY_LENGTH * 8, &aes_decrypt_key); if (verbose >= 1) { fprintf(stderr, "AES Key: \n"); print_hex(aes_key, 16); fprintf(stderr, "SHA1 seed: \n"); print_hex(hmacsha1_key, 20); } if (hdr_version == 2) fseek(in, v2header.dataoffset, SEEK_SET); else fseek(in, 0L, SEEK_SET); chunk_no = 0; while(fread(inbuf, CHUNK_SIZE, 1, in) > 0) { decrypt_chunk(inbuf, outbuf, chunk_no); chunk_no++; if(hdr_version == 2 && (v2header.datasize-ftell(out)) < CHUNK_SIZE) { fwrite(outbuf, v2header.datasize - ftell(out), 1, out); break; } fwrite(outbuf, CHUNK_SIZE, 1, out); } if (verbose) fprintf(stderr, "%d chunks written\n", chunk_no); return(0); }
/* Handle x case. */ int x_handler(va_list args) { int d; d = va_arg(args, int); return convert_hex(d); }
int decrypt_root_fs(const char *crypt, const char *decrypt, char *key) { FILE *in, *out; cencrypted_v1_header v1header; cencrypted_v2_pwheader v2header; uint8_t hmacsha1_key[20], aes_key[16], inbuf[CHUNK_SIZE], outbuf[CHUNK_SIZE]; uint32_t chunk_no; int hdr_version, c,i, optError = 0; char inFile[512], outFile[512], passphrase[512]; int iflag = 0, oflag = 0, pflag = 0, kflag = 0, verbose = 0; extern char *optarg; extern int optind, optopt; memset(inFile, 0, 512); memset(outFile, 0, 512); memset(passphrase, 0, 512); verbose++; optarg=(char *)crypt; if(optarg) strncpy(inFile, optarg, sizeof(inFile)-1); iflag=1; optarg=(char *)decrypt; if (optarg) strncpy(outFile, optarg, sizeof(outFile)-1); oflag=1; optarg=key; convert_hex(optarg, aes_key, 16); convert_hex(optarg+32, hmacsha1_key, 20); kflag=1; if (strlen(inFile) == 0) { in = stdin; } else { if ((in = fopen(inFile, "rb")) == NULL) { fprintf(stderr, "Error: unable to open %s\n", inFile); exit(1); } } if (strlen(outFile) == 0) { out = stdout; } else { if ((out = fopen(outFile, "wb")) == NULL) { fprintf(stderr, "Error: unable to open %s\n", outFile); exit(1); } } hdr_version = determine_header_version(in); if (verbose >= 1) { if (hdr_version > 0) { fprintf(stderr, "v%d header detected.\n", hdr_version); } else { fprintf(stderr, "unknown format.\n"); exit(1); } } if (hdr_version == 1) { fseek(in, (long) -sizeof(cencrypted_v1_header), SEEK_END); if (fread(&v1header, sizeof(cencrypted_v1_header), 1, in) < 1) { fprintf(stderr, "header corrupted?\n"), exit(1); } adjust_v1_header_byteorder(&v1header); if(!kflag) unwrap_v1_header(passphrase, &v1header, aes_key, hmacsha1_key); } if (hdr_version == 2) { fseek(in, 0L, SEEK_SET); if (fread(&v2header, sizeof(cencrypted_v2_pwheader), 1, in) < 1) { fprintf(stderr, "header corrupted?\n"), exit(1); } adjust_v2_header_byteorder(&v2header); dump_v2_header(&v2header); if(!kflag) unwrap_v2_header(passphrase, &v2header, aes_key, hmacsha1_key); CHUNK_SIZE = v2header.blocksize; } HMAC_CTX_init(&hmacsha1_ctx); HMAC_Init_ex(&hmacsha1_ctx, hmacsha1_key, sizeof(hmacsha1_key), EVP_sha1(), NULL); AES_set_decrypt_key(aes_key, CIPHER_KEY_LENGTH * 8, &aes_decrypt_key); if (verbose >= 1) { fprintf(stderr, "AES Key: \n"); print_hex(aes_key, 16); fprintf(stderr, "SHA1 seed: \n"); print_hex(hmacsha1_key, 20); } if (hdr_version == 2) fseek(in, v2header.dataoffset, SEEK_SET); else fseek(in, 0L, SEEK_SET); chunk_no = 0; while(fread(inbuf, CHUNK_SIZE, 1, in) > 0) { decrypt_chunk(inbuf, outbuf, chunk_no); chunk_no++; if(hdr_version == 2 && (v2header.datasize-ftell(out)) < CHUNK_SIZE) { fwrite(outbuf, v2header.datasize - ftell(out), 1, out); break; } fwrite(outbuf, CHUNK_SIZE, 1, out); } if (verbose) fprintf(stderr, "%d chunks written\n", chunk_no); return 0; return 0; }
/* *uart_printf(char*) *Converts and formats values to be sent via char UART. Works similar to normal printf function. *INPUT: Char* EX: uart_printf("DATA: %i\r\n", datvar); *RETURN: None */ void uart_printf(char *format, ...) { char c; int i; long l; va_list list; //Make the arguement list va_start(list, format); while(c = *format++) //run through the input till the end. { if(c == '%') //% denotes the variable format character { switch(c = *format++) { case 's': // strings uart_puts(va_arg(list, char*)); break; case 'c': // chars uart_putc(va_arg(list, char)); break; case 'i': // signed ints i = va_arg(list, int); if(i < 0) { i = -i; uart_putc('-'); } convert_dec((unsigned)i, divider + 5); break; case 'u': // unsigned ints i = va_arg(list, int); convert_dec((unsigned)i, divider + 5); break; case 'l': // signed longs l = va_arg(list, long); if(l < 0) { l = -l; uart_putc('-'); } convert_dec((unsigned long)l, divider); break; case 'n': // unsigned longs l = va_arg(list, long); convert_dec((unsigned long)l, divider); break; case 'x': // 16bit Hex i = va_arg(list, int); uart_putc(convert_hex(i >> 12)); uart_putc(convert_hex(i >> 8)); uart_putc(convert_hex(i >> 4)); uart_putc(convert_hex(i)); break; case 0: return; default: uart_putc(c); //can't find formating. just print it. } } else { uart_putc(c); } }
/** \fn int main(int argc, char *argv[]) \brief main routine \param argc number of commandline arguments + 1 \param argv string array containing commandline arguments (argv[0] contains name of executable) \return dummy return code (not used) Main routine for import, programming, and check routines */ int main(int argc, char ** argv) { char *appname; // name of application without path char portname[STRLEN]; // name of communication port int baudrate; // communication baudrate [Baud] uint8_t resetSTM8; // 0=no reset; 1=HW reset via DTR (RS232/USB) or GPIO18 (Raspi); 2=SW reset by sending 0x55+0xAA uint8_t enableBSL; // don't enable ROM bootloader after upload (caution!) uint8_t jumpFlash; // jump to flash after upload uint8_t pauseOnLaunch; // prompt for <return> prior to upload int flashsize; // size of flash (kB) for w/e routines uint8_t versBSL; // BSL version for w/e routines char hexfile[STRLEN]; // name of file to flash HANDLE ptrPort; // handle to communication port char buf[BUFSIZE]; // buffer for hexfiles char image[BUFSIZE]; // memory image buffer uint32_t imageStart; // starting address of image uint32_t numBytes; // number of bytes in image char *ptr=NULL; // pointer to memory int i, j; // generic variables //char Tx[100], Rx[100]; // debug: buffer for tests // initialize global variables g_pauseOnExit = 1; // wait for <return> before terminating g_UARTmode = 0; // 2-wire interface with UART duplex mode verbose = false; // verbose output when requested only // initialize default arguments portname[0] = '\0'; // no default port name baudrate = 230400; // default baudrate resetSTM8 = 0; // don't automatically reset STM8 jumpFlash = 1; // jump to flash after uploade pauseOnLaunch = 1; // prompt for return prior to upload enableBSL = 1; // enable bootloader after upload hexfile[0] = '\0'; // no default hexfile // for debugging only //sprintf(portname, "/dev/tty.usbserial-A4009I0O"); // required for strncpy() portname[STRLEN-1] = '\0'; hexfile[STRLEN-1] = '\0'; // reset console color (needs to be called once for Win32) setConsoleColor(PRM_COLOR_DEFAULT); //////// // parse commandline arguments //////// for (i=1; i<argc; i++) { // debug: print argument //printf("arg %d: '%s'\n", (int) i, argv[i]); // name of communication port if (!strcmp(argv[i], "-p")) strncpy(portname, argv[++i], STRLEN-1); // communication baudrate else if (!strcmp(argv[i], "-b")) sscanf(argv[++i],"%d",&baudrate); // UART mode: 0=duplex, 1=1-wire reply, 2=2-wire reply (default: duplex)\n"); else if (!strcmp(argv[i], "-u")) { sscanf(argv[++i], "%d", &j); g_UARTmode = j; } // name of hexfile else if (!strcmp(argv[i], "-f")) strncpy(hexfile, argv[++i], STRLEN-1); // HW reset STM8 via DTR line (RS232/USB) or GPIO18 (Raspi only) else if (!strcmp(argv[i], "-r")) { sscanf(argv[++i], "%d", &j); resetSTM8 = j; } // don't enable ROM bootloader after upload (caution!) else if (!strcmp(argv[i], "-x")) enableBSL = 0; // don't jump to address after upload else if (!strcmp(argv[i], "-j")) jumpFlash = 0; // don't prompt for <return> prior to upload else if (!strcmp(argv[i], "-Q")) pauseOnLaunch = 0; // don't prompt for <return> prior to exit else if (!strcmp(argv[i], "-q")) g_pauseOnExit = 0; // verbose output else if (!strcmp(argv[i], "-v")) verbose = true; // else print list of commandline arguments and language commands else { if (strrchr(argv[0],'\\')) appname = strrchr(argv[0],'\\')+1; // windows else if (strrchr(argv[0],'/')) appname = strrchr(argv[0],'/')+1; // Posix else appname = argv[0]; printf("\n"); printf("usage: %s [-h] [-p port] [-b rate] [-u mode] [-f file] [-r ch] [-x] [-j] [-Q] [-q] [-v]\n\n", appname); printf(" -h print this help\n"); printf(" -p port name of communication port (default: list all ports and query)\n"); printf(" -b rate communication baudrate in Baud (default: 230400)\n"); printf(" -u mode UART mode: 0=duplex, 1=1-wire reply, 2=2-wire reply (default: duplex)\n"); printf(" -f file name of s19 or intel-hex file to flash (default: none)\n"); #ifdef __ARMEL__ printf(" -r ch reset STM8: 1=DTR line (RS232), 2=send 'Re5eT!' @ 115.2kBaud, 3=GPIO18 pin (Raspi) (default: no reset)\n"); #else printf(" -r ch reset STM8: 1=DTR line (RS232), 2=send 'Re5eT!' @ 115.2kBaud (default: no reset)\n"); #endif printf(" -x don't enable ROM bootloader after upload (default: enable)\n"); printf(" -j don't jump to flash after upload (default: jump to flash)\n"); printf(" -Q don't prompt for <return> prior to upload (default: prompt)\n"); printf(" -q don't prompt for <return> prior to exit (default: prompt)\n"); printf(" -v verbose output\n"); printf("\n"); Exit(0, 0); } } // process commandline arguments //////// // print app name & version, and change console title //////// get_app_name(argv[0], VERSION, buf); printf("\n%s\n", buf); setConsoleTitle(buf); //////// // if no port name is given, list all available ports and query //////// if (strlen(portname) == 0) { printf(" enter comm port name ( "); list_ports(); printf(" ): "); scanf("%s", portname); getchar(); } // if no comm port name // If specified import hexfile - do it early here to be able to report file read errors before others if (strlen(hexfile)>0) { const char *shortname = strrchr(hexfile, '/'); if (!shortname) shortname = hexfile; // convert to memory image, depending on file type const char *dot = strrchr (hexfile, '.'); if (dot && !strcmp(dot, ".s19")) { if (verbose) printf(" Loading Motorola S-record file %s …\n", shortname); load_hexfile(hexfile, buf, BUFSIZE); convert_s19(buf, &imageStart, &numBytes, image); } else if (dot && (!strcmp(dot, ".hex") || !strcmp(dot, ".ihx"))) { if (verbose) printf(" Loading Intel hex file %s …\n", shortname); load_hexfile(hexfile, buf, BUFSIZE); convert_hex(buf, &imageStart, &numBytes, image); } else { if (verbose) printf(" Loading binary file %s …\n", shortname); load_binfile(hexfile, image, &imageStart, &numBytes, BUFSIZE); } } //////// // put STM8 into bootloader mode //////// if (pauseOnLaunch) { printf(" activate STM8 bootloader and press <return>"); fflush(stdout); fflush(stdin); getchar(); } //////// // open port with given properties //////// printf(" open port '%s' with %gkBaud ... ", portname, (float) baudrate / 1000.0); fflush(stdout); if (g_UARTmode == 0) ptrPort = init_port(portname, baudrate, 1000, 8, 2, 1, 0, 0); // use even parity else ptrPort = init_port(portname, baudrate, 1000, 8, 0, 1, 0, 0); // use no parity printf("ok\n"); fflush(stdout); // debug: communication test (echo+1 test-SW on STM8) /* printf("open: %d\n", ptrPort); for (i=0; i<254; i++) { Tx[0] = i; send_port(ptrPort, 1, Tx); receive_port(ptrPort, 1, Rx); printf("%d %d\n", (int) Tx[0], (int) Rx[0]); } printf("done\n"); Exit(1,0); */ //////// // communicate with STM8 bootloader //////// // HW reset STM8 using DTR line (USB/RS232) if (resetSTM8 == 1) { printf(" reset via DTR ... "); pulse_DTR(ptrPort, 10); printf("done\n"); SLEEP(5); // allow BSL to initialize } // SW reset STM8 via command 'Re5eT!' at 115.2kBaud (requires respective STM8 SW) else if (resetSTM8 == 2) { set_baudrate(ptrPort, 115200); // expect STM8 SW to receive at 115.2kBaud printf(" reset via UART command ... "); sprintf(buf, "Re5eT!"); // reset command (same as in STM8 SW!) for (i=0; i<6; i++) { send_port(ptrPort, 1, buf+i); // send reset command bytewise to account for slow handling SLEEP(10); } printf("done\n"); set_baudrate(ptrPort, baudrate); // restore specified baudrate } // HW reset STM8 using GPIO18 pin (only Raspberry Pi!) #ifdef __ARMEL__ else if (resetSTM8 == 3) { printf(" reset via GPIO18 ... "); pulse_GPIO(18, 10); printf("done\n"); SLEEP(5); // allow BSL to initialize } #endif // __ARMEL__ // synchronize baudrate bsl_sync(ptrPort); // get bootloader info for selecting flash w/e routines bsl_getInfo(ptrPort, &flashsize, &versBSL); // select device dependent flash routines for upload if ((flashsize==32) && (versBSL==0x10)) { ptr = (char*) STM8_Routines_E_W_ROUTINEs_32K_ver_1_0_s19; ptr[STM8_Routines_E_W_ROUTINEs_32K_ver_1_0_s19_len]=0; } else if ((flashsize==32) && (versBSL==0x12)) { ptr = (char*) STM8_Routines_E_W_ROUTINEs_32K_ver_1_2_s19; ptr[STM8_Routines_E_W_ROUTINEs_32K_ver_1_2_s19_len]=0; } else if ((flashsize==32) && (versBSL==0x13)) { ptr = (char*) STM8_Routines_E_W_ROUTINEs_32K_ver_1_3_s19; ptr[STM8_Routines_E_W_ROUTINEs_32K_ver_1_3_s19_len]=0; } else if ((flashsize==32) && (versBSL==0x14)) { ptr = (char*) STM8_Routines_E_W_ROUTINEs_32K_ver_1_4_s19; ptr[STM8_Routines_E_W_ROUTINEs_32K_ver_1_4_s19_len]=0; } else if ((flashsize==128) && (versBSL==0x20)) { ptr = (char*) STM8_Routines_E_W_ROUTINEs_128K_ver_2_0_s19; ptr[STM8_Routines_E_W_ROUTINEs_128K_ver_2_0_s19_len]=0; } else if ((flashsize==128) && (versBSL==0x21)) { ptr = (char*) STM8_Routines_E_W_ROUTINEs_128K_ver_2_1_s19; ptr[STM8_Routines_E_W_ROUTINEs_128K_ver_2_1_s19_len]=0; } else if ((flashsize==128) && (versBSL==0x22)) { ptr = (char*) STM8_Routines_E_W_ROUTINEs_128K_ver_2_2_s19; ptr[STM8_Routines_E_W_ROUTINEs_128K_ver_2_2_s19_len]=0; } else if ((flashsize==128) && (versBSL==0x24)) { ptr = (char*) STM8_Routines_E_W_ROUTINEs_128K_ver_2_4_s19; ptr[STM8_Routines_E_W_ROUTINEs_128K_ver_2_4_s19_len]=0; } else if ((flashsize==256) && (versBSL==0x10)) { ptr = (char*) STM8_Routines_E_W_ROUTINEs_256K_ver_1_0_s19; ptr[STM8_Routines_E_W_ROUTINEs_256K_ver_1_0_s19_len]=0; } else { setConsoleColor(PRM_COLOR_RED); fprintf(stderr, "\n\nerror: unsupported device, exit!\n\n"); Exit(1, g_pauseOnExit); } { char ramImage[8192]; uint32_t ramImageStart; uint32_t numRamBytes; convert_s19(ptr, &ramImageStart, &numRamBytes, ramImage); if (verbose) printf("Uploading RAM routines\n"); bsl_memWrite(ptrPort, ramImageStart, numRamBytes, ramImage, 0); } // if specified upload hexfile if (strlen(hexfile)>0) bsl_memWrite(ptrPort, imageStart, numBytes, image, 1); // memory read //imageStart = 0x8000; numBytes = 128*1024; // complete 128kB flash //imageStart = 0x00A0; numBytes = 352; // RAM //bsl_memRead(ptrPort, imageStart, numBytes, image); // enable ROM bootloader after upload (option bytes always on same address) if (enableBSL==1) { printf(" activate bootloader ... "); bsl_memWrite(ptrPort, 0x487E, 2, (char*)"\x55\xAA", 0); printf("done\n"); } // jump to flash start address after upload (reset vector always on same address) if (jumpFlash) bsl_jumpTo(ptrPort, 0x8000); //////// // clean up and exit //////// close_port(&ptrPort); if (verbose) printf("done with program\n"); Exit(0, g_pauseOnExit); // avoid compiler warnings return(0); } // main
int main(int argc, char *argv[]) { FILE *in, *out; cencrypted_v1_header v1header; cencrypted_v2_pwheader v2header; char hmacsha1_key_str[20*2+1]; char aes_key_str[16*2+1]; uint8_t hmacsha1_key[20]; uint8_t aes_key[16]; uint8_t inbuf[CHUNK_SIZE], outbuf[CHUNK_SIZE]; uint32_t chunk_no; int hdr_version; /* getopts */ int c; int optError; char inFile[512] = ""; char outFile[512] = ""; char passphrase[512]; int kflag = 0, iflag = 0, oflag = 0, pflag = 0, mflag = 0; int verbose = 0; extern char *optarg; extern int optind, optopt; memset(hmacsha1_key_str, '0', sizeof(hmacsha1_key_str)-1); hmacsha1_key_str[sizeof(hmacsha1_key_str)-1] = '\0'; optError = 0; while((c = getopt(argc, argv, "hvi:o::p::k:m:")) != -1){ switch(c) { case 'h': usage("Help is on the way. Stay calm."); break; case 'v': verbose = verbose + 1; break; case 'i': if(optarg) { strncpy(inFile, optarg, sizeof(inFile)-1); } iflag = 1; break; case 'o': if (optarg) { strncpy(outFile, optarg, sizeof(outFile)-1); } oflag = 1; break; case 'p': if (optarg) { strncpy(passphrase, optarg, sizeof(passphrase)-1); } pflag = 1; break; case 'k': if (optarg) { if (strlen(optarg) == 2*(16+20)) { strncpy(aes_key_str, optarg, sizeof(aes_key_str)); aes_key_str[sizeof(aes_key_str)-1] = '\0'; strncpy(hmacsha1_key_str, optarg+(2*16), sizeof(hmacsha1_key_str)); hmacsha1_key_str[sizeof(hmacsha1_key_str)-1] = '\0'; mflag = 1; } else if(strlen(optarg) == 2*16) { strncpy(aes_key_str, optarg, sizeof(aes_key_str)); aes_key_str[sizeof(aes_key_str)-1] = '\0'; } else { usage("you should either specify a aeskey||hmacsha1key or simply aeskey"); optError++; } } kflag = 1; break; case 'm': if (mflag) { usage("hmacsha1 key has already been specified!"); optError++; } if (optarg && strlen(optarg) == 2*20) { strncpy(hmacsha1_key_str, optarg, sizeof(hmacsha1_key_str)); hmacsha1_key_str[sizeof(hmacsha1_key_str)-1] = '\0'; } else { usage("Perhaps you'd like to give us 40 hex bytes of the HMACSHA1 key?"); optError++; } mflag = 1; break; case '?': fprintf(stderr, "Unknown option: -%c\n", optopt); optError++; break; } } /* check to see if our user gave incorrect options */ if (optError) { usage("Incorrect arguments."); } if (strlen(inFile) == 0) { in = stdin; } else { if ((in = fopen(inFile, "rb")) == NULL) { fprintf(stderr, "Error: unable to open %s\n", inFile); exit(1); } } if (strlen(outFile) == 0) { out = stdout; } else { if ((out = fopen(outFile, "wb")) == NULL) { fprintf(stderr, "Error: unable to open %s\n", outFile); exit(1); } } /* Obviously change this if we implement brute force methods inside vfdecrypt */ if (!kflag && !pflag) { fprintf(stderr, "Neither a passphrase nor a valid key/hmac combo were given.\n"); exit(1); } if (kflag && !mflag) { fprintf(stderr, "Setting HMAC-SHA1 key to all zeros!\n"); } hdr_version = determine_header_version(in); if (verbose >= 1) { if (hdr_version > 0) { fprintf(stderr, "v%d header detected.\n", hdr_version); } else { fprintf(stderr, "unknown format.\n"); exit(1); } } if (hdr_version == 1) { fseek(in, (long) -sizeof(cencrypted_v1_header), SEEK_END); if (fread(&v1header, sizeof(cencrypted_v1_header), 1, in) < 1) { fprintf(stderr, "header corrupted?\n"), exit(1); } adjust_v1_header_byteorder(&v1header); if(!kflag) unwrap_v1_header(passphrase, &v1header, aes_key, hmacsha1_key); } if (hdr_version == 2) { fseek(in, 0L, SEEK_SET); if (fread(&v2header, sizeof(cencrypted_v2_pwheader), 1, in) < 1) { fprintf(stderr, "header corrupted?\n"), exit(1); } adjust_v2_header_byteorder(&v2header); if (verbose >= 1) { dump_v2_header(&v2header); } if(!kflag) unwrap_v2_header(passphrase, &v2header, aes_key, hmacsha1_key); CHUNK_SIZE = v2header.blocksize; } if (kflag) { convert_hex(aes_key_str, aes_key, 16); convert_hex(hmacsha1_key_str, hmacsha1_key, 20); } HMAC_CTX_init(&hmacsha1_ctx); HMAC_Init_ex(&hmacsha1_ctx, hmacsha1_key, sizeof(hmacsha1_key), EVP_sha1(), NULL); AES_set_decrypt_key(aes_key, CIPHER_KEY_LENGTH * 8, &aes_decrypt_key); if (verbose >= 1) { fprintf(stderr, "aeskey:\n"); print_hex(stderr, aes_key, 16); } if (verbose >= 1) { fprintf(stderr, "hmacsha1key:\n"); print_hex(stderr, hmacsha1_key, 20); } if (hdr_version == 2) { if (verbose >= 1) { fprintf(stderr, "data offset : %llu\n", v2header.dataoffset); fprintf(stderr, "data size : %llu\n", v2header.datasize); } fseek(in, v2header.dataoffset, SEEK_SET); } else { fseek(in, 0L, SEEK_SET); } chunk_no = 0; while(fread(inbuf, CHUNK_SIZE, 1, in) > 0) { decrypt_chunk(inbuf, outbuf, chunk_no); chunk_no++; // fix for last chunk if(hdr_version == 2 && (v2header.datasize-ftell(out)) < CHUNK_SIZE) { fwrite(outbuf, v2header.datasize - ftell(out), 1, out); break; } fwrite(outbuf, CHUNK_SIZE, 1, out); } if (verbose >= 1) { fprintf(stderr, "%d chunks written\n", chunk_no); } fclose(in); fclose(out); return(0); }