| /* |
| --------------------------------------------------------------------------- |
| Copyright (c) 2002, Dr Brian Gladman < >, Worcester, UK. |
| All rights reserved. |
| |
| LICENSE TERMS |
| |
| The free distribution and use of this software in both source and binary |
| form is allowed (with or without changes) provided that: |
| |
| 1. distributions of this source code include the above copyright |
| notice, this list of conditions and the following disclaimer; |
| |
| 2. distributions in binary form include the above copyright |
| notice, this list of conditions and the following disclaimer |
| in the documentation and/or other associated materials; |
| |
| 3. the copyright holder's name is not used to endorse products |
| built using this software without specific written permission. |
| |
| ALTERNATIVELY, provided that this notice is retained in full, this product |
| may be distributed under the terms of the GNU General Public License (GPL), |
| in which case the provisions of the GPL apply INSTEAD OF those given above. |
| |
| DISCLAIMER |
| |
| This software is provided 'as is' with no explicit or implied warranties |
| in respect of its properties, including, but not limited to, correctness |
| and/or fitness for purpose. |
| ------------------------------------------------------------------------- |
| Issue Date: 24/01/2003 |
| |
| This file implements password based file encryption and authentication |
| using AES in CTR mode, HMAC-SHA1 authentication and RFC2898 password |
| based key derivation. |
| |
| */ |
| |
| #include <memory.h> |
| |
| #include "fileenc.h" |
| |
| #if defined(__cplusplus) |
| extern "C" |
| { |
| #endif |
| |
| /* subroutine for data encryption/decryption */ |
| /* this could be speeded up a lot by aligning */ |
| /* buffers and using 32 bit operations */ |
| |
| static void encr_data(unsigned char data[], unsigned long d_len, fcrypt_ctx cx[1]) |
| { unsigned long i = 0; |
| unsigned int pos = cx->encr_pos; |
| |
| while(i < d_len) |
| { |
| if(pos == BLOCK_SIZE) |
| { unsigned int j = 0; |
| /* increment encryption nonce */ |
| while(j < 8 && !++cx->nonce[j]) |
| ++j; |
| /* encrypt the nonce to form next xor buffer */ |
| aes_encrypt_block(cx->nonce, cx->encr_bfr, cx->encr_ctx); |
| pos = 0; |
| } |
| |
| data[i++] ^= cx->encr_bfr[pos++]; |
| } |
| |
| cx->encr_pos = pos; |
| } |
| |
| int _zip_fcrypt_init( |
| unsigned int mode, /* the mode to be used (input) */ |
| const unsigned char pwd[], /* the user specified password (input) */ |
| unsigned int pwd_len, /* the length of the password (input) */ |
| const unsigned char salt[], /* the salt (input) */ |
| #ifdef PASSWORD_VERIFIER |
| unsigned char pwd_ver[PWD_VER_LENGTH], /* 2 byte password verifier (output) */ |
| #endif |
| fcrypt_ctx cx[1]) /* the file encryption context (output) */ |
| { unsigned char kbuf[2 * MAX_KEY_LENGTH + PWD_VER_LENGTH]; |
| |
| if(pwd_len > MAX_PWD_LENGTH) |
| return PASSWORD_TOO_LONG; |
| |
| if(mode < 1 || mode > 3) |
| return BAD_MODE; |
| |
| cx->mode = mode; |
| cx->pwd_len = pwd_len; |
| |
| /* derive the encryption and authetication keys and the password verifier */ |
| derive_key(pwd, pwd_len, salt, SALT_LENGTH(mode), KEYING_ITERATIONS, |
| kbuf, 2 * KEY_LENGTH(mode) + PWD_VER_LENGTH); |
| |
| /* initialise the encryption nonce and buffer pos */ |
| cx->encr_pos = BLOCK_SIZE; |
| /* if we need a random component in the encryption */ |
| /* nonce, this is where it would have to be set */ |
| memset(cx->nonce, 0, BLOCK_SIZE * sizeof(unsigned char)); |
| |
| /* initialise for encryption using key 1 */ |
| aes_set_encrypt_key(kbuf, KEY_LENGTH(mode), cx->encr_ctx); |
| |
| /* initialise for authentication using key 2 */ |
| hmac_sha1_begin(cx->auth_ctx); |
| hmac_sha1_key(kbuf + KEY_LENGTH(mode), KEY_LENGTH(mode), cx->auth_ctx); |
| |
| #ifdef PASSWORD_VERIFIER |
| memcpy(pwd_ver, kbuf + 2 * KEY_LENGTH(mode), PWD_VER_LENGTH); |
| #endif |
| |
| return GOOD_RETURN; |
| } |
| |
| /* perform 'in place' encryption and authentication */ |
| |
| void _zip_fcrypt_encrypt(unsigned char data[], unsigned int data_len, fcrypt_ctx cx[1]) |
| { |
| encr_data(data, data_len, cx); |
| hmac_sha1_data(data, data_len, cx->auth_ctx); |
| } |
| |
| /* perform 'in place' authentication and decryption */ |
| |
| void _zip_fcrypt_decrypt(unsigned char data[], unsigned int data_len, fcrypt_ctx cx[1]) |
| { |
| hmac_sha1_data(data, data_len, cx->auth_ctx); |
| encr_data(data, data_len, cx); |
| } |
| |
| /* close encryption/decryption and return the MAC value */ |
| |
| int _zip_fcrypt_end(unsigned char mac[], fcrypt_ctx cx[1]) |
| { |
| hmac_sha1_end(mac, MAC_LENGTH(cx->mode), cx->auth_ctx); |
| return MAC_LENGTH(cx->mode); /* return MAC length in bytes */ |
| } |
| |
| #if defined(__cplusplus) |
| } |
| #endif |