|
Packit |
8681c6 |
/*
|
|
Packit |
8681c6 |
* COPYRIGHT (c) International Business Machines Corp. 2001-2017
|
|
Packit |
8681c6 |
*
|
|
Packit |
8681c6 |
* This program is provided under the terms of the Common Public License,
|
|
Packit |
8681c6 |
* version 1.0 (CPL-1.0). Any use, reproduction or distribution for this
|
|
Packit |
8681c6 |
* software constitutes recipient's acceptance of CPL-1.0 terms which can be
|
|
Packit |
8681c6 |
* found in the file LICENSE file or at
|
|
Packit |
8681c6 |
* https://opensource.org/licenses/cpl1.0.php
|
|
Packit |
8681c6 |
*/
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
#include <stdio.h>
|
|
Packit |
8681c6 |
#include <string.h>
|
|
Packit |
8681c6 |
#include <stdlib.h>
|
|
Packit |
8681c6 |
#include <stdint.h>
|
|
Packit |
8681c6 |
#include <sys/types.h>
|
|
Packit |
8681c6 |
#include <sys/stat.h>
|
|
Packit |
8681c6 |
#include <openssl/des.h>
|
|
Packit |
8681c6 |
#include <openssl/aes.h>
|
|
Packit Service |
8aa27d |
#include <openssl/evp.h>
|
|
Packit |
8681c6 |
#include <fcntl.h>
|
|
Packit |
8681c6 |
#include "pkcs11types.h"
|
|
Packit |
8681c6 |
#include "p11util.h"
|
|
Packit |
8681c6 |
#include "defs.h"
|
|
Packit |
8681c6 |
#include "host_defs.h"
|
|
Packit |
8681c6 |
#include "h_extern.h"
|
|
Packit |
8681c6 |
#include "trace.h"
|
|
Packit |
8681c6 |
#include "sw_crypt.h"
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
CK_RV sw_des3_cbc(CK_BYTE *in_data,
|
|
Packit |
8681c6 |
CK_ULONG in_data_len,
|
|
Packit |
8681c6 |
CK_BYTE *out_data,
|
|
Packit |
8681c6 |
CK_ULONG *out_data_len,
|
|
Packit |
8681c6 |
CK_BYTE *init_v, CK_BYTE *key_value, CK_BYTE encrypt)
|
|
Packit |
8681c6 |
{
|
|
Packit Service |
8aa27d |
#if OPENSSL_VERSION_NUMBER < 0x10100000L
|
|
Packit |
8681c6 |
DES_key_schedule des_key1;
|
|
Packit |
8681c6 |
DES_key_schedule des_key2;
|
|
Packit |
8681c6 |
DES_key_schedule des_key3;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
const_DES_cblock key_SSL1, key_SSL2, key_SSL3;
|
|
Packit |
8681c6 |
DES_cblock ivec;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
// the des decrypt will only fail if the data length is not evenly divisible
|
|
Packit |
8681c6 |
// by DES_BLOCK_SIZE
|
|
Packit |
8681c6 |
if (in_data_len % DES_BLOCK_SIZE) {
|
|
Packit |
8681c6 |
TRACE_ERROR("%s\n", ock_err(ERR_DATA_LEN_RANGE));
|
|
Packit |
8681c6 |
return CKR_DATA_LEN_RANGE;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
// The key as passed in is a 24 byte string containing 3 keys
|
|
Packit |
8681c6 |
// pick it apart and create the key schedules
|
|
Packit |
8681c6 |
memcpy(&key_SSL1, key_value, (size_t) 8);
|
|
Packit |
8681c6 |
memcpy(&key_SSL2, key_value + 8, (size_t) 8);
|
|
Packit |
8681c6 |
memcpy(&key_SSL3, key_value + 16, (size_t) 8);
|
|
Packit |
8681c6 |
DES_set_key_unchecked(&key_SSL1, &des_key1);
|
|
Packit |
8681c6 |
DES_set_key_unchecked(&key_SSL2, &des_key2);
|
|
Packit |
8681c6 |
DES_set_key_unchecked(&key_SSL3, &des_key3);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
memcpy(ivec, init_v, sizeof(ivec));
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
// Encrypt or decrypt the data
|
|
Packit |
8681c6 |
if (encrypt) {
|
|
Packit |
8681c6 |
DES_ede3_cbc_encrypt(in_data,
|
|
Packit |
8681c6 |
out_data,
|
|
Packit |
8681c6 |
in_data_len,
|
|
Packit |
8681c6 |
&des_key1,
|
|
Packit |
8681c6 |
&des_key2, &des_key3, &ivec, DES_ENCRYPT);
|
|
Packit |
8681c6 |
*out_data_len = in_data_len;
|
|
Packit |
8681c6 |
} else {
|
|
Packit |
8681c6 |
DES_ede3_cbc_encrypt(in_data,
|
|
Packit |
8681c6 |
out_data,
|
|
Packit |
8681c6 |
in_data_len,
|
|
Packit |
8681c6 |
&des_key1,
|
|
Packit |
8681c6 |
&des_key2, &des_key3, &ivec, DES_DECRYPT);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
*out_data_len = in_data_len;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
return CKR_OK;
|
|
Packit Service |
8aa27d |
#else
|
|
Packit Service |
8aa27d |
CK_RV rc;
|
|
Packit Service |
8aa27d |
int outlen;
|
|
Packit Service |
8aa27d |
const EVP_CIPHER *cipher = EVP_des_ede3_cbc();
|
|
Packit Service |
8aa27d |
EVP_CIPHER_CTX *ctx = NULL;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
if (in_data_len % DES_BLOCK_SIZE || in_data_len > INT_MAX) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("%s\n", ock_err(ERR_DATA_LEN_RANGE));
|
|
Packit Service |
8aa27d |
return CKR_DATA_LEN_RANGE;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
ctx = EVP_CIPHER_CTX_new();
|
|
Packit Service |
8aa27d |
if (ctx == NULL) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY));
|
|
Packit Service |
8aa27d |
rc = ERR_HOST_MEMORY;
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
if (EVP_CipherInit_ex(ctx, cipher,
|
|
Packit Service |
8aa27d |
NULL, key_value, init_v, encrypt ? 1 : 0) != 1
|
|
Packit Service |
8aa27d |
|| EVP_CIPHER_CTX_set_padding(ctx, 0) != 1
|
|
Packit Service |
8aa27d |
|| EVP_CipherUpdate(ctx, out_data, &outlen, in_data, in_data_len) != 1
|
|
Packit Service |
8aa27d |
|| EVP_CipherFinal_ex(ctx, out_data, &outlen) != 1) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("%s\n", ock_err(ERR_GENERAL_ERROR));
|
|
Packit Service |
8aa27d |
rc = ERR_GENERAL_ERROR;
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
*out_data_len = in_data_len;
|
|
Packit Service |
8aa27d |
rc = CKR_OK;
|
|
Packit Service |
8aa27d |
done:
|
|
Packit Service |
8aa27d |
EVP_CIPHER_CTX_free(ctx);
|
|
Packit Service |
8aa27d |
return rc;
|
|
Packit Service |
8aa27d |
#endif
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
CK_RV sw_aes_cbc(CK_BYTE *in_data,
|
|
Packit |
8681c6 |
CK_ULONG in_data_len,
|
|
Packit |
8681c6 |
CK_BYTE *out_data,
|
|
Packit |
8681c6 |
CK_ULONG *out_data_len,
|
|
Packit |
8681c6 |
CK_BYTE *init_v, CK_BYTE *key_value, CK_ULONG keylen,
|
|
Packit |
8681c6 |
CK_BYTE encrypt)
|
|
Packit |
8681c6 |
{
|
|
Packit Service |
8aa27d |
#if OPENSSL_VERSION_NUMBER < 0x10100000L
|
|
Packit |
8681c6 |
AES_KEY aes_key;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
UNUSED(out_data_len); //XXX can this parameter be removed ?
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
memset(&aes_key, 0, sizeof(aes_key));
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
// the aes decrypt will only fail if the data length is not evenly divisible
|
|
Packit |
8681c6 |
// by AES_BLOCK_SIZE
|
|
Packit |
8681c6 |
if (in_data_len % AES_BLOCK_SIZE) {
|
|
Packit |
8681c6 |
TRACE_ERROR("%s\n", ock_err(ERR_DATA_LEN_RANGE));
|
|
Packit |
8681c6 |
return CKR_DATA_LEN_RANGE;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
// Encrypt or decrypt the data
|
|
Packit |
8681c6 |
if (encrypt) {
|
|
Packit |
8681c6 |
AES_set_encrypt_key(key_value, keylen * 8, &aes_key);
|
|
Packit |
8681c6 |
AES_cbc_encrypt(in_data, out_data, in_data_len, &aes_key,
|
|
Packit |
8681c6 |
init_v, AES_ENCRYPT);
|
|
Packit |
8681c6 |
} else {
|
|
Packit |
8681c6 |
AES_set_decrypt_key(key_value, keylen * 8, &aes_key);
|
|
Packit |
8681c6 |
AES_cbc_encrypt(in_data, out_data, in_data_len, &aes_key,
|
|
Packit |
8681c6 |
init_v, AES_DECRYPT);
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
return CKR_OK;
|
|
Packit Service |
8aa27d |
#else
|
|
Packit Service |
8aa27d |
CK_RV rc;
|
|
Packit Service |
8aa27d |
int outlen;
|
|
Packit Service |
8aa27d |
const EVP_CIPHER *cipher = NULL;
|
|
Packit Service |
8aa27d |
EVP_CIPHER_CTX *ctx = NULL;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
UNUSED(out_data_len);
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
if (keylen == 128 / 8)
|
|
Packit Service |
8aa27d |
cipher = EVP_aes_128_cbc();
|
|
Packit Service |
8aa27d |
else if (keylen == 192 / 8)
|
|
Packit Service |
8aa27d |
cipher = EVP_aes_192_cbc();
|
|
Packit Service |
8aa27d |
else if (keylen == 256 / 8)
|
|
Packit Service |
8aa27d |
cipher = EVP_aes_256_cbc();
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
if (in_data_len % AES_BLOCK_SIZE || in_data_len > INT_MAX) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("%s\n", ock_err(ERR_DATA_LEN_RANGE));
|
|
Packit Service |
8aa27d |
rc = CKR_DATA_LEN_RANGE;
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
ctx = EVP_CIPHER_CTX_new();
|
|
Packit Service |
8aa27d |
if (ctx == NULL) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY));
|
|
Packit Service |
8aa27d |
rc = ERR_HOST_MEMORY;
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
if (EVP_CipherInit_ex(ctx, cipher,
|
|
Packit Service |
8aa27d |
NULL, key_value, init_v, encrypt ? 1 : 0) != 1
|
|
Packit Service |
8aa27d |
|| EVP_CIPHER_CTX_set_padding(ctx, 0) != 1
|
|
Packit Service |
8aa27d |
|| EVP_CipherUpdate(ctx, out_data, &outlen, in_data, in_data_len) != 1
|
|
Packit Service |
8aa27d |
|| EVP_CipherFinal_ex(ctx, out_data, &outlen) != 1) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("%s\n", ock_err(ERR_GENERAL_ERROR));
|
|
Packit Service |
8aa27d |
rc = ERR_GENERAL_ERROR;
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
rc = CKR_OK;
|
|
Packit Service |
8aa27d |
done:
|
|
Packit Service |
8aa27d |
EVP_CIPHER_CTX_free(ctx);
|
|
Packit Service |
8aa27d |
return rc;
|
|
Packit Service |
8aa27d |
#endif
|
|
Packit |
8681c6 |
}
|