int main(int argc, char *argv[]) { FILE *inf, *outf; unsigned char buf[1024], tmp_buf1[16], tmp_buf2[16], salt[16], *fname, *cp; fcrypt_ctx zcx[1]; int len, flen, err = 0; unsigned char mode; if(argc != 3) /* the command line is bad */ { err = ERROR_USAGE; goto error_0; } len = (int)strlen(argv[1]); if(len < 8) /* password is too short */ { err = ERROR_PASSWORD_LENGTH; goto error_0; } /* set the key length based on password length assuming that there */ /* are about 4 bits of entropy per password character (the key */ /* length and other mode dependent parameter values are set using */ /* macros defined in fileenc.h) */ mode = (len < 32 ? 1 : len < 48 ? 2 : 3); /* save input file name to a temporary memory area with extra space */ /* for the extension ".enc" to be added */ fname = (unsigned char*)malloc(strlen(argv[2]) + 5); if(fname == NULL) { err = ERROR_OUT_OF_MEMORY; goto error_0; } /* open the input file */ strcpy(fname, argv[2]); if((inf = fopen(fname, "rb")) == NULL) { err = ERROR_INPUT_FILE; goto error_1; } /* if the file name extension is ".enc" assume this is an encrypted */ /* file */ if((cp = strrchr(fname, '.')) && strcmp(cp, ".enc") == 0) { *cp = 0; mode |= 4; /* signal decryption */ } else /* add ".enc" to file name to mark the */ strcat(fname, ".enc"); /* the file as an encrypted one */ /* open output file for binary output */ if((outf = fopen(fname, "wb")) == NULL) { err = ERROR_OUTPUT_FILE; goto error_2; } if(!(mode & 4)) /* encryption operation */ { prng_ctx rng[1]; /* the context for the random number pool */ prng_init(entropy_fun, rng); /* initialise RNG */ prng_rand(salt, SALT_LENGTH(mode), rng); /* and the salt */ /* write salt value */ fwrite(salt, sizeof(unsigned char), SALT_LENGTH(mode), outf); /* initialise encryption and authentication */ #ifdef PASSWORD_VERIFIER fcrypt_init(mode, argv[1], (unsigned int)strlen(argv[1]), salt, tmp_buf1, zcx); /* write password verifier (if used) */ fwrite(tmp_buf1, sizeof(unsigned char), PWD_VER_LENGTH, outf); #else fcrypt_init(mode, argv[1], (unsigned int)strlen(argv[1]), salt, zcx); #endif /* encrypt and authenticate the file */ len = (int)fread(buf, sizeof(unsigned char), 1024, inf); while(len) { fcrypt_encrypt(buf, len, zcx); fwrite(buf, sizeof(unsigned char), len, outf); len = (int)fread(buf, sizeof(unsigned char), len, inf); } /* write the MAC */ fcrypt_end(tmp_buf1, zcx); fwrite(tmp_buf1, sizeof(unsigned char), MAC_LENGTH(mode), outf); /* and close random pool */ prng_end(rng); } else /* decryption operation */ { /* we need to know the file length to avoid reading the MAC */ fseek(inf, 0, SEEK_END); flen = ftell(inf); fseek(inf, 0, SEEK_SET); mode &= 3; /* recover the password salt */ fread(salt, sizeof(unsigned char), SALT_LENGTH(mode), inf); flen -= SALT_LENGTH(mode); #ifdef PASSWORD_VERIFIER /* initialise encryption and authentication */ fcrypt_init(mode, argv[1], (unsigned int)strlen(argv[1]), salt, tmp_buf2, zcx); /* recover the password verifier (if used) */ fread(tmp_buf1, sizeof(unsigned char), PWD_VER_LENGTH, inf); flen -= PWD_VER_LENGTH; /* check password verifier */ if(memcmp(tmp_buf1, tmp_buf2, PWD_VER_LENGTH)) { err = ERROR_BAD_PASSWORD; fclose(outf); goto error_2; } #else /* initialise encryption and authentication */ fcrypt_init(mode, argv[1], (unsigned int)strlen(argv[1]), salt, zcx); #endif flen -= MAC_LENGTH(mode); /* avoid reading the MAC */ /* decrypt the file */ len = (int)fread(buf, sizeof(unsigned char), (size_t)(flen < 1024 ? flen : 1024), inf); while(len) { flen -= len; fcrypt_decrypt(buf, len, zcx); fwrite(buf, sizeof(unsigned char), len, outf); len = (int)fread(buf, sizeof(unsigned char), (size_t)(flen < 1024 ? flen : 1024), inf); } /* calculate the MAC value */ fcrypt_end(tmp_buf2, zcx); /* now read the stored MAC value */ fread(tmp_buf1, sizeof(unsigned char), MAC_LENGTH(mode), inf); /* compare the stored and calculated MAC values */ if(memcmp(tmp_buf1, tmp_buf2, MAC_LENGTH(mode))) { /* authentication failed */ err = ERROR_BAD_AUTHENTICATION; fclose(outf); /* delete the (bad) output file */ remove(fname); goto error_2; } } fclose(outf); error_2: fclose(inf); error_1: free(fname); error_0: if(err) printf(err_string[err - 1], fname); return -err; }
int fcrypt_end(unsigned char mac[], fcrypt_ctx cx[1]) { /*unsigned int res = cx->mode;*/ hmac_sha_end(mac, MAC_LENGTH(cx->mode), cx->auth_ctx); memset(cx, 0, sizeof(fcrypt_ctx)); /* clear the encryption context */ return MAC_LENGTH(res); /* return MAC length in bytes */ }