1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166
|
/****************************************************************
* *
* Copyright 2013, 2014 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
* under a license. If you do not know the terms of *
* the license, please stop and do not read further. *
* *
****************************************************************/
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdarg.h>
#include <sys/stat.h>
#include <ctype.h>
#include <assert.h>
#include <errno.h>
#include <gpgme.h> /* gpgme functions */
#include <gpg-error.h> /* gcry*_err_t */
#include <libconfig.h>
#include "gtmxc_types.h"
#include "gtmcrypt_util.h"
#include "gtmcrypt_interface.h" /* Function prototypes for gtmcrypt*.* functions */
#include "gtmcrypt_ref.h"
#include "gtmcrypt_dbk_ref.h"
#include "gtmcrypt_sym_ref.h"
#include "gtmcrypt_pk_ref.h"
#ifndef USE_OPENSSL
/*
* Initialize encryption state if libgcrypt is used.
*
* Returns: 0 if the initialization succeeded; -1 otherwise.
*/
int gc_sym_init()
{
gcry_error_t rv;
if (!gcry_check_version(GCRYPT_VERSION))
{
UPDATE_ERROR_STRING("libgcrypt version mismatch. %s or higher is required", GCRYPT_VERSION);
return -1;
}
if (0 != (rv = gcry_control(GCRYCTL_DISABLE_SECMEM, 0)))
{
GC_APPEND_GCRY_ERROR(rv, "Failed to disable secure memory.");
return -1;
}
if (0 != (rv = gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0)))
{
GC_APPEND_GCRY_ERROR(rv, "Failed to finish encryption initialization.")
return -1;
}
return 0;
}
#endif
/*
* Destroy the specified encryption / decryption state object.
*
* Arguments: handle Encryption / decryption state object to destroy.
*/
void gc_sym_destroy_cipher_handle(crypt_key_t handle)
{
# ifdef USE_OPENSSL
EVP_CIPHER_CTX_cleanup(&handle);
# endif
# ifdef USE_GCRYPT
if (handle)
gcry_cipher_close(handle);
# endif
}
/*
* Create an encryption / decryption state object based on the specified key and IV and assign it to the passed pointer.
*
* Arguments: raw_key Raw contents of the symmetric key to use.
* iv Initialization vector to use.
* handle Pointer to assign the newly created encryption / decryption state object to.
* direction Indicator of whether encryption or decryption state object is to be constructed.
*
* Returns: 0 if the state object was successfully constructed; -1 otherwise.
*/
int gc_sym_create_cipher_handle(unsigned char *raw_key, unsigned char *iv, crypt_key_t *handle, int direction)
{
int rv, plain_text_length;
# ifdef USE_OPENSSL
EVP_CIPHER_CTX_init(handle);
if (!EVP_CipherInit(handle, ALGO, raw_key, iv, direction))
{
GC_APPEND_OPENSSL_ERROR("Failed to initialize encryption key handle.");
return -1;
}
# else
if (0 != (rv = gcry_cipher_open(handle, ALGO, MODE, 0)))
{
GC_APPEND_GCRY_ERROR(rv, "Failed to initialize encryption key handle ('gcry_cipher_open').");
return -1;
}
if (0 != (rv = gcry_cipher_setkey(*handle, raw_key, SYMMETRIC_KEY_MAX)))
{
GC_APPEND_GCRY_ERROR(rv, "Failed to initialize encryption key handle ('gcry_cipher_setkey').");
return -1;
}
gcry_cipher_setiv(*handle, iv, GTMCRYPT_IV_LEN);
# endif
return 0;
}
/*
* Perform an encryption or decryption operation using the specified state object and buffers (or buffer, if in-place).
*
* Arguments: key Pointer to the encryption / decryption state object.
* in_block Block from which to take the input data for the operation.
* in_block_len Length of the block from which to take the input data for the operation; it should match the length
* of the block for the output data, if not NULL.
* out_block Block where to place the output data from the operation.
* flag Indicator of whether encryption or decryption is to be performed.
*
* Returns: 0 if the operation went successfully; -1 otherwise.
*/
int gc_sym_encrypt_decrypt(crypt_key_t *key, unsigned char *in_block, int in_block_len, unsigned char *out_block, int flag)
{
int rv, tmp_len, out_block_len;
assert(in_block);
assert(0 < in_block_len);
if (NULL == out_block)
out_block = in_block;
out_block_len = in_block_len;
# ifdef USE_GCRYPT
if (out_block == in_block)
{
in_block = NULL;
in_block_len = 0;
}
rv = (GTMCRYPT_OP_ENCRYPT == flag)
? gcry_cipher_encrypt(*key, out_block, out_block_len, in_block, in_block_len)
: gcry_cipher_decrypt(*key, out_block, out_block_len, in_block, in_block_len);
if (0 != rv)
{
GC_APPEND_GCRY_ERROR(rv, "Libgcrypt function 'gcry_cipher_encrypt' or 'gcry_cipher_decrypt' failed.");
return -1;
}
# endif
# ifdef USE_OPENSSL
if (!EVP_CipherUpdate(key, out_block, &out_block_len, in_block, in_block_len))
{
GC_APPEND_OPENSSL_ERROR("OpenSSL function 'EVP_CipherUpdate' failed.")
return -1;
}
if (!EVP_CipherFinal(key, out_block + out_block_len, &tmp_len))
{
GC_APPEND_OPENSSL_ERROR("OpenSSL function 'EVP_CipherFinal' failed.")
return -1;
}
# endif
return 0;
}
|