| 
									
										
										
										
											2015-12-02 16:54:09 -08:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * Demo to do the rough equivalent of: | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  *    openssl enc -aes-256-cbc -pass pass:foobar -in infile -out outfile -p | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Compilation: | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  *    $(CC) -I /path/to/headers -L .../libs \ | 
					
						
							|  |  |  |  *          -o openssl-enc \ | 
					
						
							|  |  |  |  *          openssl-enc.c -ltomcrypt | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Usage: | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  *    ./openssl-enc <enc|dec> infile outfile "passphrase" [salt] | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * If provided, the salt must be EXACTLY a 16-char hex string. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Demo is an example of: | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * - (When decrypting) yanking salt out of the OpenSSL "Salted__..." header | 
					
						
							|  |  |  |  * - OpenSSL-compatible key derivation (in OpenSSL's modified PKCS#5v1 approach) | 
					
						
							|  |  |  |  * - Grabbing an Initialization Vector from the key generator | 
					
						
							|  |  |  |  * - Performing simple block encryption using AES | 
					
						
							|  |  |  |  * - PKCS#7-type padding (which hopefully can get ripped out of this demo and | 
					
						
							|  |  |  |  *   made a libtomcrypt thing someday). | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This program is free for all purposes without any express guarantee it | 
					
						
							|  |  |  |  * works. If you really want to see a license here, assume the WTFPL :-) | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * BJ Black, bblack@barracuda.com, https://wjblack.com
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * BUGS: | 
					
						
							|  |  |  |  *       Passing a password on a command line is a HORRIBLE idea.  Don't use | 
					
						
							|  |  |  |  *       this program for serious work! | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <tomcrypt.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifndef LTC_RIJNDAEL
 | 
					
						
							|  |  |  | #error Cannot compile this demo; Rijndael (AES) required
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | #ifndef LTC_CBC_MODE
 | 
					
						
							|  |  |  | #error Cannot compile this demo; CBC mode required
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | #ifndef LTC_PKCS_5
 | 
					
						
							|  |  |  | #error Cannot compile this demo; PKCS5 required
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | #ifndef LTC_RNG_GET_BYTES
 | 
					
						
							|  |  |  | #error Cannot compile this demo; random generator required
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* OpenSSL by default only runs one hash round */ | 
					
						
							|  |  |  | #define OPENSSL_ITERATIONS 1
 | 
					
						
							|  |  |  | /* Use aes-256-cbc, so 256 bits of key, 128 of IV */ | 
					
						
							|  |  |  | #define KEY_LENGTH (256>>3)
 | 
					
						
							|  |  |  | #define IV_LENGTH (128>>3)
 | 
					
						
							|  |  |  | /* PKCS#5v1 requires exactly an 8-byte salt */ | 
					
						
							|  |  |  | #define SALT_LENGTH 8
 | 
					
						
							|  |  |  | /* The header OpenSSL puts on an encrypted file */ | 
					
						
							|  |  |  | static char salt_header[] = { 'S', 'a', 'l', 't', 'e', 'd', '_', '_' }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <errno.h>
 | 
					
						
							|  |  |  | #include <stdio.h>
 | 
					
						
							|  |  |  | #include <string.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* A simple way to handle the possibility that a block may increase in size
 | 
					
						
							|  |  |  |    after padding. */ | 
					
						
							|  |  |  | union paddable { | 
					
						
							| 
									
										
										
										
											2017-03-15 08:59:49 +01:00
										 |  |  |    unsigned char unpad[1024]; | 
					
						
							|  |  |  |    unsigned char pad[1024+MAXBLOCKSIZE]; | 
					
						
							| 
									
										
										
										
											2015-12-02 16:54:09 -08:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * Print usage and exit with a bad status (and perror() if any errno). | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Input:        argv[0] and the error string | 
					
						
							|  |  |  |  * Output:       <no return> | 
					
						
							|  |  |  |  * Side Effects: print messages and barf (does exit(3)) | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | void barf(char *pname, char *err) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |    printf("Usage: %s <enc|dec> infile outfile [salt]\n", pname); | 
					
						
							|  |  |  |    printf("\n"); | 
					
						
							|  |  |  |    printf("       # encrypts infile->outfile, random salt\n"); | 
					
						
							|  |  |  |    printf("       %s enc infile outfile \"passphrase\"\n", pname); | 
					
						
							|  |  |  |    printf("\n"); | 
					
						
							|  |  |  |    printf("       # encrypts infile->outfile, salt from cmdline\n"); | 
					
						
							|  |  |  |    printf("       %s enc infile outfile pass 0123456789abcdef\n", pname); | 
					
						
							|  |  |  |    printf("\n"); | 
					
						
							|  |  |  |    printf("       # decrypts infile->outfile, pulls salt from infile\n"); | 
					
						
							|  |  |  |    printf("       %s dec infile outfile pass\n", pname); | 
					
						
							|  |  |  |    printf("\n"); | 
					
						
							|  |  |  |    printf("       # decrypts infile->outfile, salt specified\n"); | 
					
						
							|  |  |  |    printf("       # (don't try to read the salt from infile)\n"); | 
					
						
							|  |  |  |    printf("       %s dec infile outfile pass 0123456789abcdef" | 
					
						
							|  |  |  |           "\n", pname); | 
					
						
							|  |  |  |    printf("\n"); | 
					
						
							|  |  |  |    printf("Application Error: %s\n", err); | 
					
						
							|  |  |  |    if(errno) | 
					
						
							|  |  |  |       perror("     System Error"); | 
					
						
							|  |  |  |    exit(-1); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * Parse a salt value passed in on the cmdline. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Input:        string passed in and a buf to put it in (exactly 8 bytes!) | 
					
						
							|  |  |  |  * Output:       CRYPT_OK if parsed OK, CRYPT_ERROR if not | 
					
						
							|  |  |  |  * Side Effects: none | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | int parse_hex_salt(unsigned char *in, unsigned char *out) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |    int idx; | 
					
						
							|  |  |  |    for(idx=0; idx<SALT_LENGTH; idx++) | 
					
						
							| 
									
										
										
										
											2017-03-15 08:59:49 +01:00
										 |  |  |       if(sscanf((char*)in+idx*2, "%02hhx", out+idx) != 1) | 
					
						
							| 
									
										
										
										
											2015-12-02 16:54:09 -08:00
										 |  |  |          return CRYPT_ERROR; | 
					
						
							|  |  |  |    return CRYPT_OK; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * Parse the Salted__[+8 bytes] from an OpenSSL-compatible file header. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Input:        file to read from and a to put the salt in (exactly 8 bytes!) | 
					
						
							|  |  |  |  * Output:       CRYPT_OK if parsed OK, CRYPT_ERROR if not | 
					
						
							|  |  |  |  * Side Effects: infile's read pointer += 16 | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | int parse_openssl_header(FILE *in, unsigned char *out) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |    unsigned char tmp[SALT_LENGTH]; | 
					
						
							|  |  |  |    if(fread(tmp, 1, sizeof(tmp), in) != sizeof(tmp)) | 
					
						
							|  |  |  |       return CRYPT_ERROR; | 
					
						
							|  |  |  |    if(memcmp(tmp, salt_header, sizeof(tmp))) | 
					
						
							|  |  |  |       return CRYPT_ERROR; | 
					
						
							|  |  |  |    if(fread(tmp, 1, sizeof(tmp), in) != sizeof(tmp)) | 
					
						
							|  |  |  |       return CRYPT_ERROR; | 
					
						
							|  |  |  |    memcpy(out, tmp, sizeof(tmp)); | 
					
						
							|  |  |  |    return CRYPT_OK; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * Dump a hexed stream of bytes (convenience func). | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Input:        buf to read from, length | 
					
						
							|  |  |  |  * Output:       none | 
					
						
							|  |  |  |  * Side Effects: bytes printed as a hex blob, no lf at the end | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | void dump_bytes(unsigned char *in, unsigned long len) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |    unsigned long idx; | 
					
						
							|  |  |  |    for(idx=0; idx<len; idx++) | 
					
						
							|  |  |  |       printf("%02hhX", *(in+idx)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * Pad or unpad a message using PKCS#7 padding. | 
					
						
							|  |  |  |  * Padding will add 1-(blocksize) bytes and unpadding will remove that amount. | 
					
						
							|  |  |  |  * Set is_padding to 1 to pad, 0 to unpad. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Input:        paddable buffer, size read, block length of cipher, mode | 
					
						
							|  |  |  |  * Output:       none | 
					
						
							|  |  |  |  * Side Effects: bytes printed as a hex blob, no lf at the end | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | size_t pkcs7_pad(union paddable *buf, size_t nb, int block_length, | 
					
						
							|  |  |  |                  int is_padding) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |    unsigned char padval; | 
					
						
							|  |  |  |    off_t idx; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    if(is_padding) { | 
					
						
							|  |  |  |       /* We are PADDING this block (and therefore adding bytes) */ | 
					
						
							|  |  |  |       /* The pad value in PKCS#7 is the number of bytes remaining in
 | 
					
						
							|  |  |  |          the block, so for a 16-byte block and 3 bytes left, it's | 
					
						
							|  |  |  |          0x030303.  In the oddball case where nb is an exact multiple | 
					
						
							|  |  |  |          multiple of block_length, set the padval to blocksize (i.e. | 
					
						
							|  |  |  |          add one full block) */ | 
					
						
							|  |  |  |       padval = (unsigned char) (block_length - (nb % block_length)); | 
					
						
							|  |  |  |       padval = padval ? padval : block_length; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-15 08:59:49 +01:00
										 |  |  |       memset(buf->pad+nb, padval, padval); | 
					
						
							| 
									
										
										
										
											2015-12-02 16:54:09 -08:00
										 |  |  |       return nb+padval; | 
					
						
							|  |  |  |    } else { | 
					
						
							|  |  |  |       /* We are UNPADDING this block (and removing bytes)
 | 
					
						
							|  |  |  |          We really just need to verify that the pad bytes are correct, | 
					
						
							|  |  |  |          so start at the end of the string and work backwards. */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       /* Figure out what the padlength should be by looking at the
 | 
					
						
							|  |  |  |          last byte */ | 
					
						
							|  |  |  |       idx = nb-1; | 
					
						
							|  |  |  |       padval = buf->pad[idx]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       /* padval must be nonzero and <= block length */ | 
					
						
							|  |  |  |       if(padval <= 0 || padval > block_length) | 
					
						
							|  |  |  |          return -1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       /* First byte's accounted for; do the rest */ | 
					
						
							|  |  |  |       idx--; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-15 08:59:49 +01:00
										 |  |  |       while(idx >= (off_t)(nb-padval)) | 
					
						
							| 
									
										
										
										
											2015-12-02 16:54:09 -08:00
										 |  |  |          if(buf->pad[idx] != padval) | 
					
						
							|  |  |  |             return -1; | 
					
						
							|  |  |  |          else | 
					
						
							|  |  |  |             idx--; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       /* If we got here, the pad checked out, so return a smaller
 | 
					
						
							|  |  |  |          number of bytes than nb (basically where we left off+1) */ | 
					
						
							|  |  |  |       return idx+1; | 
					
						
							|  |  |  |    } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * Perform an encrypt/decrypt operation to/from files using AES+CBC+PKCS7 pad. | 
					
						
							|  |  |  |  * Set encrypt to 1 to encrypt, 0 to decrypt. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Input:        in/out files, key, iv, and mode | 
					
						
							|  |  |  |  * Output:       CRYPT_OK if no error | 
					
						
							|  |  |  |  * Side Effects: bytes slurped from infile, pushed to outfile, fds updated. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | int do_crypt(FILE *infd, FILE *outfd, unsigned char *key, unsigned char *iv, | 
					
						
							|  |  |  |              int encrypt) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |    union paddable inbuf, outbuf; | 
					
						
							|  |  |  |    int cipher, ret; | 
					
						
							|  |  |  |    symmetric_CBC cbc; | 
					
						
							|  |  |  |    size_t nb; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    /* Register your cipher! */ | 
					
						
							|  |  |  |    cipher = register_cipher(&aes_desc); | 
					
						
							|  |  |  |    if(cipher == -1) | 
					
						
							|  |  |  |       return CRYPT_INVALID_CIPHER; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    /* Start a CBC session with cipher/key/val params */ | 
					
						
							|  |  |  |    ret = cbc_start(cipher, iv, key, KEY_LENGTH, 0, &cbc); | 
					
						
							|  |  |  |    if( ret != CRYPT_OK ) | 
					
						
							|  |  |  |       return -1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    do { | 
					
						
							|  |  |  |       /* Get bytes from the source */ | 
					
						
							|  |  |  |       nb = fread(inbuf.unpad, 1, sizeof(inbuf.unpad), infd); | 
					
						
							|  |  |  |       if(!nb) | 
					
						
							|  |  |  |          return encrypt ? CRYPT_OK : CRYPT_ERROR; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       /* Barf if we got a read error */ | 
					
						
							|  |  |  |       if(ferror(infd)) | 
					
						
							|  |  |  |          return CRYPT_ERROR; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       if(encrypt) { | 
					
						
							|  |  |  |          /* We're encrypting, so pad first (if at EOF) and then
 | 
					
						
							|  |  |  |             crypt */ | 
					
						
							|  |  |  |          if(feof(infd)) | 
					
						
							|  |  |  |             nb = pkcs7_pad(&inbuf, nb, | 
					
						
							|  |  |  |                            aes_desc.block_length, 1); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |          ret = cbc_encrypt(inbuf.pad, outbuf.pad, nb, &cbc); | 
					
						
							|  |  |  |          if(ret != CRYPT_OK) | 
					
						
							|  |  |  |             return ret; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       } else { | 
					
						
							|  |  |  |          /* We're decrypting, so decrypt and then unpad if at
 | 
					
						
							|  |  |  |             EOF */ | 
					
						
							|  |  |  |          ret = cbc_decrypt(inbuf.unpad, outbuf.unpad, nb, &cbc); | 
					
						
							|  |  |  |          if( ret != CRYPT_OK ) | 
					
						
							|  |  |  |             return ret; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |          if( feof(infd) ) | 
					
						
							|  |  |  |             nb = pkcs7_pad(&outbuf, nb, | 
					
						
							|  |  |  |                            aes_desc.block_length, 0); | 
					
						
							| 
									
										
										
										
											2017-03-15 08:59:49 +01:00
										 |  |  |          if(nb == -1) | 
					
						
							| 
									
										
										
										
											2015-12-02 16:54:09 -08:00
										 |  |  |             /* The file didn't decrypt correctly */ | 
					
						
							|  |  |  |             return CRYPT_ERROR; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       /* Push bytes to outfile */ | 
					
						
							|  |  |  |       if(fwrite(outbuf.unpad, 1, nb, outfd) != nb) | 
					
						
							|  |  |  |          return CRYPT_ERROR; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    } while(!feof(infd)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    /* Close up */ | 
					
						
							|  |  |  |    cbc_done(&cbc); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    return CRYPT_OK; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Convenience macro for the various barfable places below */ | 
					
						
							|  |  |  | #define BARF(a) { \
 | 
					
						
							|  |  |  |    if(infd) fclose(infd); \ | 
					
						
							|  |  |  |    if(outfd) { fclose(outfd); remove(argv[3]); } \ | 
					
						
							|  |  |  |    barf(argv[0], a); \ | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * The main routine.  Mostly validate cmdline params, open files, run the KDF, | 
					
						
							|  |  |  |  * and do the crypt. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | int main(int argc, char *argv[]) { | 
					
						
							|  |  |  |    unsigned char salt[SALT_LENGTH]; | 
					
						
							|  |  |  |    FILE *infd = NULL, *outfd = NULL; | 
					
						
							|  |  |  |    int encrypt = -1; | 
					
						
							|  |  |  |    int hash = -1; | 
					
						
							|  |  |  |    int ret; | 
					
						
							|  |  |  |    unsigned char keyiv[KEY_LENGTH + IV_LENGTH]; | 
					
						
							|  |  |  |    unsigned long keyivlen = (KEY_LENGTH + IV_LENGTH); | 
					
						
							|  |  |  |    unsigned char *key, *iv; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    /* Check proper number of cmdline args */ | 
					
						
							|  |  |  |    if(argc < 5 || argc > 6) | 
					
						
							|  |  |  |       BARF("Invalid number of arguments"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    /* Check proper mode of operation */ | 
					
						
							| 
									
										
										
										
											2017-03-15 08:59:49 +01:00
										 |  |  |    if     (!strncmp(argv[1], "enc", 3)) | 
					
						
							| 
									
										
										
										
											2015-12-02 16:54:09 -08:00
										 |  |  |       encrypt = 1; | 
					
						
							| 
									
										
										
										
											2017-03-15 08:59:49 +01:00
										 |  |  |    else if(!strncmp(argv[1], "dec", 3)) | 
					
						
							| 
									
										
										
										
											2015-12-02 16:54:09 -08:00
										 |  |  |       encrypt = 0; | 
					
						
							|  |  |  |    else | 
					
						
							|  |  |  |       BARF("Bad command name"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    /* Check we can open infile/outfile */ | 
					
						
							|  |  |  |    infd = fopen(argv[2], "rb"); | 
					
						
							|  |  |  |    if(infd == NULL) | 
					
						
							|  |  |  |       BARF("Could not open infile"); | 
					
						
							|  |  |  |    outfd = fopen(argv[3], "wb"); | 
					
						
							|  |  |  |    if(outfd == NULL) | 
					
						
							|  |  |  |       BARF("Could not open outfile"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    /* Get the salt from wherever */ | 
					
						
							|  |  |  |    if(argc == 6) { | 
					
						
							|  |  |  |       /* User-provided */ | 
					
						
							|  |  |  |       if(parse_hex_salt((unsigned char*) argv[5], salt) != CRYPT_OK) | 
					
						
							|  |  |  |          BARF("Bad user-specified salt"); | 
					
						
							| 
									
										
										
										
											2017-03-15 08:59:49 +01:00
										 |  |  |    } else if(!strncmp(argv[1], "enc", 3)) { | 
					
						
							| 
									
										
										
										
											2015-12-02 16:54:09 -08:00
										 |  |  |       /* Encrypting; get from RNG */ | 
					
						
							|  |  |  |       if(rng_get_bytes(salt, sizeof(salt), NULL) != sizeof(salt)) | 
					
						
							|  |  |  |          BARF("Not enough random data"); | 
					
						
							|  |  |  |    } else { | 
					
						
							|  |  |  |       /* Parse from infile (decrypt only) */ | 
					
						
							|  |  |  |       if(parse_openssl_header(infd, salt) != CRYPT_OK) | 
					
						
							|  |  |  |          BARF("Invalid OpenSSL header in infile"); | 
					
						
							|  |  |  |    } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    /* Fetch the MD5 hasher for PKCS#5 */ | 
					
						
							|  |  |  |    hash = register_hash(&md5_desc); | 
					
						
							|  |  |  |    if(hash == -1) | 
					
						
							|  |  |  |       BARF("Could not register MD5 hash"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    /* Set things to a sane initial state */ | 
					
						
							|  |  |  |    zeromem(keyiv, sizeof(keyiv)); | 
					
						
							|  |  |  |    key = keyiv + 0;      /* key comes first */ | 
					
						
							|  |  |  |    iv = keyiv + KEY_LENGTH;   /* iv comes next */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    /* Run the key derivation from the provided passphrase.  This gets us
 | 
					
						
							|  |  |  |       the key and iv. */ | 
					
						
							| 
									
										
										
										
											2017-03-15 08:59:49 +01:00
										 |  |  |    ret = pkcs_5_alg1_openssl((unsigned char*)argv[4], strlen(argv[4]), salt, | 
					
						
							| 
									
										
										
										
											2015-12-02 16:54:09 -08:00
										 |  |  |                              OPENSSL_ITERATIONS, hash, keyiv, &keyivlen ); | 
					
						
							|  |  |  |    if(ret != CRYPT_OK) | 
					
						
							|  |  |  |       BARF("Could not derive key/iv from passphrase"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    /* Display the salt/key/iv like OpenSSL cmdline does when -p */ | 
					
						
							|  |  |  |    printf("salt="); dump_bytes(salt, sizeof(salt)); printf("\n"); | 
					
						
							|  |  |  |    printf("key=");  dump_bytes(key, KEY_LENGTH);    printf("\n"); | 
					
						
							|  |  |  |    printf("iv =");  dump_bytes(iv,  IV_LENGTH );    printf("\n"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    /* If we're encrypting, write the salt header as OpenSSL does */ | 
					
						
							| 
									
										
										
										
											2017-03-15 08:59:49 +01:00
										 |  |  |    if(!strncmp(argv[1], "enc", 3)) { | 
					
						
							| 
									
										
										
										
											2015-12-02 16:54:09 -08:00
										 |  |  |       if(fwrite(salt_header, 1, sizeof(salt_header), outfd) != | 
					
						
							|  |  |  |          sizeof(salt_header) ) | 
					
						
							|  |  |  |          BARF("Error writing salt header to outfile"); | 
					
						
							|  |  |  |       if(fwrite(salt, 1, sizeof(salt), outfd) != sizeof(salt)) | 
					
						
							|  |  |  |          BARF("Error writing salt to outfile"); | 
					
						
							|  |  |  |    } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    /* At this point, the files are open, the salt has been figured out,
 | 
					
						
							|  |  |  |       and we're ready to pump data through crypt. */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    /* Do the crypt operation */ | 
					
						
							|  |  |  |    if(do_crypt(infd, outfd, key, iv, encrypt) != CRYPT_OK) | 
					
						
							|  |  |  |       BARF("Error during crypt operation"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    /* Clean up */ | 
					
						
							|  |  |  |    fclose(infd); fclose(outfd); | 
					
						
							|  |  |  |    return 0; | 
					
						
							|  |  |  | } |