Page Menu
Home
ClusterLabs Projects
Search
Configure Global Search
Log In
Files
F3152958
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
39 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/libknet/crypto_nss.c b/libknet/crypto_nss.c
index b2eff193..9191d9a3 100644
--- a/libknet/crypto_nss.c
+++ b/libknet/crypto_nss.c
@@ -1,820 +1,824 @@
/*
* Copyright (C) 2012-2018 Red Hat, Inc. All rights reserved.
*
* Author: Fabio M. Di Nitto <fabbione@kronosnet.org>
*
* This software licensed under GPL-2.0+, LGPL-2.0+
*/
#define KNET_MODULE
#include "config.h"
#include <errno.h>
#include <stdlib.h>
#include <nss.h>
#include <nspr.h>
#include <pk11pub.h>
#include <pkcs11.h>
#include <prerror.h>
#include <blapit.h>
#include <hasht.h>
#include <pthread.h>
#include <secerr.h>
#include <prinit.h>
#include "crypto_model.h"
#include "logging.h"
static int nss_db_is_init = 0;
static void nss_atexit_handler(void)
{
if (nss_db_is_init) {
NSS_Shutdown();
if (PR_Initialized()) {
PL_ArenaFinish();
PR_Cleanup();
}
}
return;
}
/*
* crypto definitions and conversion tables
*/
#define SALT_SIZE 16
/*
* This are defined in new NSS. For older one, we will define our own
*/
#ifndef AES_256_KEY_LENGTH
#define AES_256_KEY_LENGTH 32
#endif
#ifndef AES_192_KEY_LENGTH
#define AES_192_KEY_LENGTH 24
#endif
#ifndef AES_128_KEY_LENGTH
#define AES_128_KEY_LENGTH 16
#endif
enum nsscrypto_crypt_t {
CRYPTO_CIPHER_TYPE_NONE = 0,
CRYPTO_CIPHER_TYPE_AES256 = 1,
CRYPTO_CIPHER_TYPE_AES192 = 2,
CRYPTO_CIPHER_TYPE_AES128 = 3,
CRYPTO_CIPHER_TYPE_3DES = 4
};
CK_MECHANISM_TYPE cipher_to_nss[] = {
0, /* CRYPTO_CIPHER_TYPE_NONE */
CKM_AES_CBC_PAD, /* CRYPTO_CIPHER_TYPE_AES256 */
CKM_AES_CBC_PAD, /* CRYPTO_CIPHER_TYPE_AES192 */
CKM_AES_CBC_PAD, /* CRYPTO_CIPHER_TYPE_AES128 */
CKM_DES3_CBC_PAD /* CRYPTO_CIPHER_TYPE_3DES */
};
size_t nsscipher_key_len[] = {
0, /* CRYPTO_CIPHER_TYPE_NONE */
AES_256_KEY_LENGTH, /* CRYPTO_CIPHER_TYPE_AES256 */
AES_192_KEY_LENGTH, /* CRYPTO_CIPHER_TYPE_AES192 */
AES_128_KEY_LENGTH, /* CRYPTO_CIPHER_TYPE_AES128 */
24 /* CRYPTO_CIPHER_TYPE_3DES */
};
size_t nsscypher_block_len[] = {
0, /* CRYPTO_CIPHER_TYPE_NONE */
AES_BLOCK_SIZE, /* CRYPTO_CIPHER_TYPE_AES256 */
AES_BLOCK_SIZE, /* CRYPTO_CIPHER_TYPE_AES192 */
AES_BLOCK_SIZE, /* CRYPTO_CIPHER_TYPE_AES128 */
0 /* CRYPTO_CIPHER_TYPE_3DES */
};
/*
* hash definitions and conversion tables
*/
enum nsscrypto_hash_t {
CRYPTO_HASH_TYPE_NONE = 0,
CRYPTO_HASH_TYPE_MD5 = 1,
CRYPTO_HASH_TYPE_SHA1 = 2,
CRYPTO_HASH_TYPE_SHA256 = 3,
CRYPTO_HASH_TYPE_SHA384 = 4,
CRYPTO_HASH_TYPE_SHA512 = 5
};
CK_MECHANISM_TYPE hash_to_nss[] = {
0, /* CRYPTO_HASH_TYPE_NONE */
CKM_MD5_HMAC, /* CRYPTO_HASH_TYPE_MD5 */
CKM_SHA_1_HMAC, /* CRYPTO_HASH_TYPE_SHA1 */
CKM_SHA256_HMAC, /* CRYPTO_HASH_TYPE_SHA256 */
CKM_SHA384_HMAC, /* CRYPTO_HASH_TYPE_SHA384 */
CKM_SHA512_HMAC /* CRYPTO_HASH_TYPE_SHA512 */
};
size_t nsshash_len[] = {
0, /* CRYPTO_HASH_TYPE_NONE */
MD5_LENGTH, /* CRYPTO_HASH_TYPE_MD5 */
SHA1_LENGTH, /* CRYPTO_HASH_TYPE_SHA1 */
SHA256_LENGTH, /* CRYPTO_HASH_TYPE_SHA256 */
SHA384_LENGTH, /* CRYPTO_HASH_TYPE_SHA384 */
SHA512_LENGTH /* CRYPTO_HASH_TYPE_SHA512 */
};
enum sym_key_type {
SYM_KEY_TYPE_CRYPT,
SYM_KEY_TYPE_HASH
};
struct nsscrypto_instance {
PK11SymKey *nss_sym_key;
PK11SymKey *nss_sym_key_sign;
unsigned char *private_key;
unsigned int private_key_len;
int crypto_cipher_type;
int crypto_hash_type;
};
/*
* crypt/decrypt functions
*/
static int nssstring_to_crypto_cipher_type(const char* crypto_cipher_type)
{
if (strcmp(crypto_cipher_type, "none") == 0) {
return CRYPTO_CIPHER_TYPE_NONE;
} else if (strcmp(crypto_cipher_type, "aes256") == 0) {
return CRYPTO_CIPHER_TYPE_AES256;
} else if (strcmp(crypto_cipher_type, "aes192") == 0) {
return CRYPTO_CIPHER_TYPE_AES192;
} else if (strcmp(crypto_cipher_type, "aes128") == 0) {
return CRYPTO_CIPHER_TYPE_AES128;
} else if (strcmp(crypto_cipher_type, "3des") == 0) {
return CRYPTO_CIPHER_TYPE_3DES;
}
return -1;
}
static PK11SymKey *nssimport_symmetric_key(knet_handle_t knet_h, enum sym_key_type key_type)
{
struct nsscrypto_instance *instance = knet_h->crypto_instance->model_instance;
SECItem key_item;
PK11SlotInfo *slot;
PK11SymKey *res_key;
CK_MECHANISM_TYPE cipher;
CK_ATTRIBUTE_TYPE operation;
CK_MECHANISM_TYPE wrap_mechanism;
int wrap_key_len;
PK11SymKey *wrap_key;
PK11Context *wrap_key_crypt_context;
SECItem tmp_sec_item;
SECItem wrapped_key;
int wrapped_key_len;
unsigned char wrapped_key_data[KNET_MAX_KEY_LEN];
memset(&key_item, 0, sizeof(key_item));
slot = NULL;
wrap_key = NULL;
res_key = NULL;
wrap_key_crypt_context = NULL;
key_item.type = siBuffer;
key_item.data = instance->private_key;
switch (key_type) {
case SYM_KEY_TYPE_CRYPT:
key_item.len = nsscipher_key_len[instance->crypto_cipher_type];
cipher = cipher_to_nss[instance->crypto_cipher_type];
operation = CKA_ENCRYPT|CKA_DECRYPT;
break;
case SYM_KEY_TYPE_HASH:
key_item.len = instance->private_key_len;
cipher = hash_to_nss[instance->crypto_hash_type];
operation = CKA_SIGN;
break;
default:
log_err(knet_h, KNET_SUB_NSSCRYPTO, "Import symmetric key failed. Unknown keyimport request");
goto exit_res_key;
break;
}
slot = PK11_GetBestSlot(cipher, NULL);
if (slot == NULL) {
log_err(knet_h, KNET_SUB_NSSCRYPTO, "Unable to find security slot (%d): %s",
PR_GetError(), PR_ErrorToString(PR_GetError(), PR_LANGUAGE_I_DEFAULT));
goto exit_res_key;
}
/*
* Without FIPS it would be possible to just use
* res_key = PK11_ImportSymKey(slot, cipher, PK11_OriginUnwrap, operation, &key_item, NULL);
* with FIPS NSS Level 2 certification has to be "workarounded" (so it becomes Level 1) by using
* following method:
* 1. Generate wrap key
* 2. Encrypt authkey with wrap key
* 3. Unwrap encrypted authkey using wrap key
*/
/*
* Generate wrapping key
*/
wrap_mechanism = PK11_GetBestWrapMechanism(slot);
wrap_key_len = PK11_GetBestKeyLength(slot, wrap_mechanism);
wrap_key = PK11_KeyGen(slot, wrap_mechanism, NULL, wrap_key_len, NULL);
if (wrap_key == NULL) {
log_err(knet_h, KNET_SUB_NSSCRYPTO, "Unable to generate wrapping key (%d): %s",
PR_GetError(), PR_ErrorToString(PR_GetError(), PR_LANGUAGE_I_DEFAULT));
goto exit_res_key;
}
/*
* Encrypt authkey with wrapping key
*/
/*
* Initialization of IV is not needed because PK11_GetBestWrapMechanism should return ECB mode
*/
memset(&tmp_sec_item, 0, sizeof(tmp_sec_item));
wrap_key_crypt_context = PK11_CreateContextBySymKey(wrap_mechanism, CKA_ENCRYPT,
wrap_key, &tmp_sec_item);
if (wrap_key_crypt_context == NULL) {
log_err(knet_h, KNET_SUB_NSSCRYPTO, "Unable to create encrypt context (%d): %s",
PR_GetError(), PR_ErrorToString(PR_GetError(), PR_LANGUAGE_I_DEFAULT));
goto exit_res_key;
}
wrapped_key_len = (int)sizeof(wrapped_key_data);
if (PK11_CipherOp(wrap_key_crypt_context, wrapped_key_data, &wrapped_key_len,
sizeof(wrapped_key_data), key_item.data, key_item.len) != SECSuccess) {
log_err(knet_h, KNET_SUB_NSSCRYPTO, "Unable to encrypt authkey (%d): %s",
PR_GetError(), PR_ErrorToString(PR_GetError(), PR_LANGUAGE_I_DEFAULT));
goto exit_res_key;
}
if (PK11_Finalize(wrap_key_crypt_context) != SECSuccess) {
log_err(knet_h, KNET_SUB_NSSCRYPTO, "Unable to finalize encryption of authkey (%d): %s",
PR_GetError(), PR_ErrorToString(PR_GetError(), PR_LANGUAGE_I_DEFAULT));
goto exit_res_key;
}
/*
* Finally unwrap sym key
*/
memset(&tmp_sec_item, 0, sizeof(tmp_sec_item));
wrapped_key.data = wrapped_key_data;
wrapped_key.len = wrapped_key_len;
res_key = PK11_UnwrapSymKey(wrap_key, wrap_mechanism, &tmp_sec_item, &wrapped_key,
cipher, operation, key_item.len);
if (res_key == NULL) {
log_err(knet_h, KNET_SUB_NSSCRYPTO, "Failure to import key into NSS (%d): %s",
PR_GetError(), PR_ErrorToString(PR_GetError(), PR_LANGUAGE_I_DEFAULT));
if (PR_GetError() == SEC_ERROR_BAD_DATA) {
/*
* Maximum key length for FIPS enabled softtoken is limited to
* MAX_KEY_LEN (pkcs11i.h - 256) and checked in NSC_UnwrapKey. Returned
* error is CKR_TEMPLATE_INCONSISTENT which is mapped to SEC_ERROR_BAD_DATA.
*/
log_err(knet_h, KNET_SUB_NSSCRYPTO, "Secret key is probably too long. "
"Try reduce it to 256 bytes");
}
goto exit_res_key;
}
exit_res_key:
if (wrap_key_crypt_context != NULL) {
PK11_DestroyContext(wrap_key_crypt_context, PR_TRUE);
}
if (wrap_key != NULL) {
PK11_FreeSymKey(wrap_key);
}
if (slot != NULL) {
PK11_FreeSlot(slot);
}
return (res_key);
}
static int init_nss_crypto(knet_handle_t knet_h)
{
struct nsscrypto_instance *instance = knet_h->crypto_instance->model_instance;
if (!cipher_to_nss[instance->crypto_cipher_type]) {
return 0;
}
instance->nss_sym_key = nssimport_symmetric_key(knet_h, SYM_KEY_TYPE_CRYPT);
if (instance->nss_sym_key == NULL) {
errno = ENXIO; /* NSS reported error */
return -1;
}
return 0;
}
static int encrypt_nss(
knet_handle_t knet_h,
const struct iovec *iov,
int iovcnt,
unsigned char *buf_out,
ssize_t *buf_out_len)
{
struct nsscrypto_instance *instance = knet_h->crypto_instance->model_instance;
PK11Context* crypt_context = NULL;
SECItem crypt_param;
SECItem *nss_sec_param = NULL;
int tmp_outlen = 0, tmp1_outlen = 0;
unsigned int tmp2_outlen = 0;
unsigned char *salt = buf_out;
unsigned char *data = buf_out + SALT_SIZE;
int err = -1;
int i;
if (PK11_GenerateRandom(salt, SALT_SIZE) != SECSuccess) {
log_err(knet_h, KNET_SUB_NSSCRYPTO, "Failure to generate a random number (err %d): %s",
PR_GetError(), PR_ErrorToString(PR_GetError(), PR_LANGUAGE_I_DEFAULT));
goto out;
}
crypt_param.type = siBuffer;
crypt_param.data = salt;
crypt_param.len = SALT_SIZE;
nss_sec_param = PK11_ParamFromIV(cipher_to_nss[instance->crypto_cipher_type],
&crypt_param);
if (nss_sec_param == NULL) {
log_err(knet_h, KNET_SUB_NSSCRYPTO, "Failure to set up PKCS11 param (err %d): %s",
PR_GetError(), PR_ErrorToString(PR_GetError(), PR_LANGUAGE_I_DEFAULT));
goto out;
}
/*
* Create cipher context for encryption
*/
crypt_context = PK11_CreateContextBySymKey(cipher_to_nss[instance->crypto_cipher_type],
CKA_ENCRYPT,
instance->nss_sym_key,
nss_sec_param);
if (!crypt_context) {
log_err(knet_h, KNET_SUB_NSSCRYPTO, "PK11_CreateContext failed (encrypt) crypt_type=%d (err %d): %s",
(int)cipher_to_nss[instance->crypto_cipher_type],
PR_GetError(), PR_ErrorToString(PR_GetError(), PR_LANGUAGE_I_DEFAULT));
goto out;
}
for (i=0; i<iovcnt; i++) {
if (PK11_CipherOp(crypt_context, data,
&tmp_outlen,
KNET_DATABUFSIZE_CRYPT,
(unsigned char *)iov[i].iov_base,
iov[i].iov_len) != SECSuccess) {
log_err(knet_h, KNET_SUB_NSSCRYPTO, "PK11_CipherOp failed (encrypt) crypt_type=%d (err %d): %s",
(int)cipher_to_nss[instance->crypto_cipher_type],
PR_GetError(), PR_ErrorToString(PR_GetError(), PR_LANGUAGE_I_DEFAULT));
goto out;
}
tmp1_outlen = tmp1_outlen + tmp_outlen;
}
if (PK11_DigestFinal(crypt_context, data + tmp1_outlen,
&tmp2_outlen, KNET_DATABUFSIZE_CRYPT - tmp1_outlen) != SECSuccess) {
log_err(knet_h, KNET_SUB_NSSCRYPTO, "PK11_DigestFinal failed (encrypt) crypt_type=%d (err %d): %s",
(int)cipher_to_nss[instance->crypto_cipher_type],
PR_GetError(), PR_ErrorToString(PR_GetError(), PR_LANGUAGE_I_DEFAULT));
goto out;
}
*buf_out_len = tmp1_outlen + tmp2_outlen + SALT_SIZE;
err = 0;
out:
if (crypt_context) {
PK11_DestroyContext(crypt_context, PR_TRUE);
}
if (nss_sec_param) {
SECITEM_FreeItem(nss_sec_param, PR_TRUE);
}
return err;
}
static int decrypt_nss (
knet_handle_t knet_h,
const unsigned char *buf_in,
const ssize_t buf_in_len,
unsigned char *buf_out,
ssize_t *buf_out_len)
{
struct nsscrypto_instance *instance = knet_h->crypto_instance->model_instance;
PK11Context* decrypt_context = NULL;
SECItem decrypt_param;
int tmp1_outlen = 0;
unsigned int tmp2_outlen = 0;
unsigned char *salt = (unsigned char *)buf_in;
unsigned char *data = salt + SALT_SIZE;
int datalen = buf_in_len - SALT_SIZE;
int err = -1;
+ if (datalen <= 0) {
+ log_err(knet_h, KNET_SUB_NSSCRYPTO, "Packet is too short");
+ goto out;
+ }
+
/* Create cipher context for decryption */
decrypt_param.type = siBuffer;
decrypt_param.data = salt;
decrypt_param.len = SALT_SIZE;
decrypt_context = PK11_CreateContextBySymKey(cipher_to_nss[instance->crypto_cipher_type],
CKA_DECRYPT,
instance->nss_sym_key, &decrypt_param);
if (!decrypt_context) {
log_err(knet_h, KNET_SUB_NSSCRYPTO, "PK11_CreateContext (decrypt) failed (err %d): %s",
PR_GetError(), PR_ErrorToString(PR_GetError(), PR_LANGUAGE_I_DEFAULT));
goto out;
}
if (PK11_CipherOp(decrypt_context, buf_out, &tmp1_outlen,
KNET_DATABUFSIZE_CRYPT, data, datalen) != SECSuccess) {
log_err(knet_h, KNET_SUB_NSSCRYPTO, "PK11_CipherOp (decrypt) failed (err %d): %s",
PR_GetError(), PR_ErrorToString(PR_GetError(), PR_LANGUAGE_I_DEFAULT));
goto out;
}
if (PK11_DigestFinal(decrypt_context, buf_out + tmp1_outlen, &tmp2_outlen,
KNET_DATABUFSIZE_CRYPT - tmp1_outlen) != SECSuccess) {
log_err(knet_h, KNET_SUB_NSSCRYPTO, "PK11_DigestFinal (decrypt) failed (err %d): %s",
PR_GetError(), PR_ErrorToString(PR_GetError(), PR_LANGUAGE_I_DEFAULT));
goto out;
}
*buf_out_len = tmp1_outlen + tmp2_outlen;
err = 0;
out:
if (decrypt_context) {
PK11_DestroyContext(decrypt_context, PR_TRUE);
}
return err;
}
-
/*
* hash/hmac/digest functions
*/
static int nssstring_to_crypto_hash_type(const char* crypto_hash_type)
{
if (strcmp(crypto_hash_type, "none") == 0) {
return CRYPTO_HASH_TYPE_NONE;
} else if (strcmp(crypto_hash_type, "md5") == 0) {
return CRYPTO_HASH_TYPE_MD5;
} else if (strcmp(crypto_hash_type, "sha1") == 0) {
return CRYPTO_HASH_TYPE_SHA1;
} else if (strcmp(crypto_hash_type, "sha256") == 0) {
return CRYPTO_HASH_TYPE_SHA256;
} else if (strcmp(crypto_hash_type, "sha384") == 0) {
return CRYPTO_HASH_TYPE_SHA384;
} else if (strcmp(crypto_hash_type, "sha512") == 0) {
return CRYPTO_HASH_TYPE_SHA512;
}
return -1;
}
static int init_nss_hash(knet_handle_t knet_h)
{
struct nsscrypto_instance *instance = knet_h->crypto_instance->model_instance;
if (!hash_to_nss[instance->crypto_hash_type]) {
return 0;
}
instance->nss_sym_key_sign = nssimport_symmetric_key(knet_h, SYM_KEY_TYPE_HASH);
if (instance->nss_sym_key_sign == NULL) {
errno = ENXIO; /* NSS reported error */
return -1;
}
return 0;
}
static int calculate_nss_hash(
knet_handle_t knet_h,
const unsigned char *buf,
const size_t buf_len,
unsigned char *hash)
{
struct nsscrypto_instance *instance = knet_h->crypto_instance->model_instance;
PK11Context* hash_context = NULL;
SECItem hash_param;
unsigned int hash_tmp_outlen = 0;
int err = -1;
/* Now do the digest */
hash_param.type = siBuffer;
hash_param.data = 0;
hash_param.len = 0;
hash_context = PK11_CreateContextBySymKey(hash_to_nss[instance->crypto_hash_type],
CKA_SIGN,
instance->nss_sym_key_sign,
&hash_param);
if (!hash_context) {
log_err(knet_h, KNET_SUB_NSSCRYPTO, "PK11_CreateContext failed (hash) hash_type=%d (err %d): %s",
(int)hash_to_nss[instance->crypto_hash_type],
PR_GetError(), PR_ErrorToString(PR_GetError(), PR_LANGUAGE_I_DEFAULT));
goto out;
}
if (PK11_DigestBegin(hash_context) != SECSuccess) {
log_err(knet_h, KNET_SUB_NSSCRYPTO, "PK11_DigestBegin failed (hash) hash_type=%d (err %d): %s",
(int)hash_to_nss[instance->crypto_hash_type],
PR_GetError(), PR_ErrorToString(PR_GetError(), PR_LANGUAGE_I_DEFAULT));
goto out;
}
if (PK11_DigestOp(hash_context, buf, buf_len) != SECSuccess) {
log_err(knet_h, KNET_SUB_NSSCRYPTO, "PK11_DigestOp failed (hash) hash_type=%d (err %d): %s",
(int)hash_to_nss[instance->crypto_hash_type],
PR_GetError(), PR_ErrorToString(PR_GetError(), PR_LANGUAGE_I_DEFAULT));
goto out;
}
if (PK11_DigestFinal(hash_context, hash,
&hash_tmp_outlen, nsshash_len[instance->crypto_hash_type]) != SECSuccess) {
log_err(knet_h, KNET_SUB_NSSCRYPTO, "PK11_DigestFinale failed (hash) hash_type=%d (err %d): %s",
(int)hash_to_nss[instance->crypto_hash_type],
PR_GetError(), PR_ErrorToString(PR_GetError(), PR_LANGUAGE_I_DEFAULT));
goto out;
}
err = 0;
out:
if (hash_context) {
PK11_DestroyContext(hash_context, PR_TRUE);
}
return err;
}
/*
* global/glue nss functions
*/
static int init_nss(knet_handle_t knet_h)
{
static int at_exit_registered = 0;
if (!at_exit_registered) {
if (atexit(nss_atexit_handler)) {
log_err(knet_h, KNET_SUB_NSSCRYPTO, "Unable to register NSS atexit handler");
errno = EAGAIN;
return -1;
}
at_exit_registered = 1;
}
if (!nss_db_is_init) {
- if (NSS_NoDB_Init(".") != SECSuccess) {
+ if (NSS_NoDB_Init(NULL) != SECSuccess) {
log_err(knet_h, KNET_SUB_NSSCRYPTO, "NSS DB initialization failed (err %d): %s",
PR_GetError(), PR_ErrorToString(PR_GetError(), PR_LANGUAGE_I_DEFAULT));
errno = EAGAIN;
return -1;
}
nss_db_is_init = 1;
}
if (init_nss_crypto(knet_h) < 0) {
return -1;
}
if (init_nss_hash(knet_h) < 0) {
return -1;
}
return 0;
}
/*
* exported API
*/
static int nsscrypto_encrypt_and_signv (
knet_handle_t knet_h,
const struct iovec *iov_in,
int iovcnt_in,
unsigned char *buf_out,
ssize_t *buf_out_len)
{
struct nsscrypto_instance *instance = knet_h->crypto_instance->model_instance;
int i;
if (cipher_to_nss[instance->crypto_cipher_type]) {
if (encrypt_nss(knet_h, iov_in, iovcnt_in, buf_out, buf_out_len) < 0) {
return -1;
}
} else {
*buf_out_len = 0;
for (i=0; i<iovcnt_in; i++) {
memmove(buf_out + *buf_out_len, iov_in[i].iov_base, iov_in[i].iov_len);
*buf_out_len = *buf_out_len + iov_in[i].iov_len;
}
}
if (hash_to_nss[instance->crypto_hash_type]) {
if (calculate_nss_hash(knet_h, buf_out, *buf_out_len, buf_out + *buf_out_len) < 0) {
return -1;
}
*buf_out_len = *buf_out_len + nsshash_len[instance->crypto_hash_type];
}
return 0;
}
static int nsscrypto_encrypt_and_sign (
knet_handle_t knet_h,
const unsigned char *buf_in,
const ssize_t buf_in_len,
unsigned char *buf_out,
ssize_t *buf_out_len)
{
struct iovec iov_in;
memset(&iov_in, 0, sizeof(iov_in));
iov_in.iov_base = (unsigned char *)buf_in;
iov_in.iov_len = buf_in_len;
return nsscrypto_encrypt_and_signv(knet_h, &iov_in, 1, buf_out, buf_out_len);
}
static int nsscrypto_authenticate_and_decrypt (
knet_handle_t knet_h,
const unsigned char *buf_in,
const ssize_t buf_in_len,
unsigned char *buf_out,
ssize_t *buf_out_len)
{
struct nsscrypto_instance *instance = knet_h->crypto_instance->model_instance;
ssize_t temp_len = buf_in_len;
if (hash_to_nss[instance->crypto_hash_type]) {
unsigned char tmp_hash[nsshash_len[instance->crypto_hash_type]];
ssize_t temp_buf_len = buf_in_len - nsshash_len[instance->crypto_hash_type];
- if ((temp_buf_len < 0) || (temp_buf_len > KNET_MAX_PACKET_SIZE)) {
+ if ((temp_buf_len <= 0) || (temp_buf_len > KNET_MAX_PACKET_SIZE)) {
log_err(knet_h, KNET_SUB_NSSCRYPTO, "Incorrect packet size.");
return -1;
}
if (calculate_nss_hash(knet_h, buf_in, temp_buf_len, tmp_hash) < 0) {
return -1;
}
if (memcmp(tmp_hash, buf_in + temp_buf_len, nsshash_len[instance->crypto_hash_type]) != 0) {
log_err(knet_h, KNET_SUB_NSSCRYPTO, "Digest does not match");
return -1;
}
temp_len = temp_len - nsshash_len[instance->crypto_hash_type];
*buf_out_len = temp_len;
}
if (cipher_to_nss[instance->crypto_cipher_type]) {
if (decrypt_nss(knet_h, buf_in, temp_len, buf_out, buf_out_len) < 0) {
return -1;
}
} else {
memmove(buf_out, buf_in, temp_len);
*buf_out_len = temp_len;
}
return 0;
}
static void nsscrypto_fini(
knet_handle_t knet_h)
{
struct nsscrypto_instance *nsscrypto_instance = knet_h->crypto_instance->model_instance;
if (nsscrypto_instance) {
if (nsscrypto_instance->nss_sym_key) {
PK11_FreeSymKey(nsscrypto_instance->nss_sym_key);
nsscrypto_instance->nss_sym_key = NULL;
}
if (nsscrypto_instance->nss_sym_key_sign) {
PK11_FreeSymKey(nsscrypto_instance->nss_sym_key_sign);
nsscrypto_instance->nss_sym_key_sign = NULL;
}
free(nsscrypto_instance);
knet_h->crypto_instance->model_instance = NULL;
knet_h->sec_header_size = 0;
}
return;
}
static int nsscrypto_init(
knet_handle_t knet_h,
struct knet_handle_crypto_cfg *knet_handle_crypto_cfg)
{
struct nsscrypto_instance *nsscrypto_instance = NULL;
int savederrno;
log_debug(knet_h, KNET_SUB_NSSCRYPTO,
"Initizializing nss crypto module [%s/%s]",
knet_handle_crypto_cfg->crypto_cipher_type,
knet_handle_crypto_cfg->crypto_hash_type);
knet_h->crypto_instance->model_instance = malloc(sizeof(struct nsscrypto_instance));
if (!knet_h->crypto_instance->model_instance) {
log_err(knet_h, KNET_SUB_NSSCRYPTO, "Unable to allocate memory for nss model instance");
savederrno = ENOMEM;
return -1;
}
nsscrypto_instance = knet_h->crypto_instance->model_instance;
memset(nsscrypto_instance, 0, sizeof(struct nsscrypto_instance));
nsscrypto_instance->crypto_cipher_type = nssstring_to_crypto_cipher_type(knet_handle_crypto_cfg->crypto_cipher_type);
if (nsscrypto_instance->crypto_cipher_type < 0) {
log_err(knet_h, KNET_SUB_NSSCRYPTO, "unknown crypto cipher type requested");
savederrno = ENXIO;
goto out_err;
}
nsscrypto_instance->crypto_hash_type = nssstring_to_crypto_hash_type(knet_handle_crypto_cfg->crypto_hash_type);
if (nsscrypto_instance->crypto_hash_type < 0) {
log_err(knet_h, KNET_SUB_NSSCRYPTO, "unknown crypto hash type requested");
savederrno = ENXIO;
goto out_err;
}
if ((nsscrypto_instance->crypto_cipher_type > 0) &&
(nsscrypto_instance->crypto_hash_type == 0)) {
log_err(knet_h, KNET_SUB_NSSCRYPTO, "crypto communication requires hash specified");
savederrno = EINVAL;
goto out_err;
}
nsscrypto_instance->private_key = knet_handle_crypto_cfg->private_key;
nsscrypto_instance->private_key_len = knet_handle_crypto_cfg->private_key_len;
if (init_nss(knet_h) < 0) {
savederrno = errno;
goto out_err;
}
knet_h->sec_header_size = 0;
if (nsscrypto_instance->crypto_hash_type > 0) {
knet_h->sec_header_size += nsshash_len[nsscrypto_instance->crypto_hash_type];
knet_h->sec_hash_size = nsshash_len[nsscrypto_instance->crypto_hash_type];
}
if (nsscrypto_instance->crypto_cipher_type > 0) {
int block_size;
if (nsscypher_block_len[nsscrypto_instance->crypto_cipher_type]) {
block_size = nsscypher_block_len[nsscrypto_instance->crypto_cipher_type];
} else {
block_size = PK11_GetBlockSize(nsscrypto_instance->crypto_cipher_type, NULL);
if (block_size < 0) {
savederrno = ENXIO;
goto out_err;
}
}
knet_h->sec_header_size += (block_size * 2);
knet_h->sec_header_size += SALT_SIZE;
knet_h->sec_salt_size = SALT_SIZE;
knet_h->sec_block_size = block_size;
}
return 0;
out_err:
nsscrypto_fini(knet_h);
errno = savederrno;
return -1;
}
crypto_ops_t crypto_model = {
KNET_CRYPTO_MODEL_ABI,
nsscrypto_init,
nsscrypto_fini,
nsscrypto_encrypt_and_sign,
nsscrypto_encrypt_and_signv,
nsscrypto_authenticate_and_decrypt
};
diff --git a/libknet/crypto_openssl.c b/libknet/crypto_openssl.c
index 13e2d8f4..93ebc4fd 100644
--- a/libknet/crypto_openssl.c
+++ b/libknet/crypto_openssl.c
@@ -1,606 +1,614 @@
/*
* Copyright (C) 2017-2018 Red Hat, Inc. All rights reserved.
*
* Author: Fabio M. Di Nitto <fabbione@kronosnet.org>
*
* This software licensed under GPL-2.0+, LGPL-2.0+
*/
#define KNET_MODULE
#include "config.h"
#include <string.h>
#include <errno.h>
#include <dlfcn.h>
#include <openssl/conf.h>
#include <openssl/evp.h>
#include <openssl/hmac.h>
#include <openssl/rand.h>
#include <openssl/err.h>
#include "logging.h"
#include "crypto_model.h"
/*
* 1.0.2 requires at least 120 bytes
* 1.1.0 requires at least 256 bytes
*/
#define SSLERR_BUF_SIZE 512
/*
* crypto definitions and conversion tables
*/
#define SALT_SIZE 16
struct opensslcrypto_instance {
void *private_key;
int private_key_len;
const EVP_CIPHER *crypto_cipher_type;
const EVP_MD *crypto_hash_type;
};
/*
* crypt/decrypt functions openssl1.0
*/
#ifdef BUILDCRYPTOOPENSSL10
static int encrypt_openssl(
knet_handle_t knet_h,
const struct iovec *iov,
int iovcnt,
unsigned char *buf_out,
ssize_t *buf_out_len)
{
struct opensslcrypto_instance *instance = knet_h->crypto_instance->model_instance;
EVP_CIPHER_CTX ctx;
int tmplen = 0, offset = 0;
unsigned char *salt = buf_out;
unsigned char *data = buf_out + SALT_SIZE;
int err = 0;
int i;
char sslerr[SSLERR_BUF_SIZE];
EVP_CIPHER_CTX_init(&ctx);
/*
* contribute to PRNG for each packet we send/receive
*/
RAND_seed((unsigned char *)iov[iovcnt - 1].iov_base, iov[iovcnt - 1].iov_len);
if (!RAND_bytes(salt, SALT_SIZE)) {
ERR_error_string_n(ERR_get_error(), sslerr, sizeof(sslerr));
log_err(knet_h, KNET_SUB_OPENSSLCRYPTO, "Unable to get random salt data: %s", sslerr);
err = -1;
goto out;
}
/*
* add warning re keylength
*/
EVP_EncryptInit_ex(&ctx, instance->crypto_cipher_type, NULL, instance->private_key, salt);
for (i=0; i<iovcnt; i++) {
if (!EVP_EncryptUpdate(&ctx,
data + offset, &tmplen,
(unsigned char *)iov[i].iov_base, iov[i].iov_len)) {
ERR_error_string_n(ERR_get_error(), sslerr, sizeof(sslerr));
log_err(knet_h, KNET_SUB_OPENSSLCRYPTO, "Unable to encrypt: %s", sslerr);
err = -1;
goto out;
}
offset = offset + tmplen;
}
if (!EVP_EncryptFinal_ex(&ctx, data + offset, &tmplen)) {
ERR_error_string_n(ERR_get_error(), sslerr, sizeof(sslerr));
log_err(knet_h, KNET_SUB_OPENSSLCRYPTO, "Unable to finalize encrypt: %s", sslerr);
err = -1;
goto out;
}
*buf_out_len = offset + tmplen + SALT_SIZE;
out:
EVP_CIPHER_CTX_cleanup(&ctx);
return err;
}
static int decrypt_openssl (
knet_handle_t knet_h,
const unsigned char *buf_in,
const ssize_t buf_in_len,
unsigned char *buf_out,
ssize_t *buf_out_len)
{
struct opensslcrypto_instance *instance = knet_h->crypto_instance->model_instance;
EVP_CIPHER_CTX ctx;
int tmplen1 = 0, tmplen2 = 0;
unsigned char *salt = (unsigned char *)buf_in;
unsigned char *data = salt + SALT_SIZE;
int datalen = buf_in_len - SALT_SIZE;
int err = 0;
char sslerr[SSLERR_BUF_SIZE];
EVP_CIPHER_CTX_init(&ctx);
/*
* contribute to PRNG for each packet we send/receive
*/
RAND_seed(buf_in, buf_in_len);
/*
* add warning re keylength
*/
EVP_DecryptInit_ex(&ctx, instance->crypto_cipher_type, NULL, instance->private_key, salt);
if (!EVP_DecryptUpdate(&ctx, buf_out, &tmplen1, data, datalen)) {
ERR_error_string_n(ERR_get_error(), sslerr, sizeof(sslerr));
log_err(knet_h, KNET_SUB_OPENSSLCRYPTO, "Unable to decrypt: %s", sslerr);
err = -1;
goto out;
}
if (!EVP_DecryptFinal_ex(&ctx, buf_out + tmplen1, &tmplen2)) {
ERR_error_string_n(ERR_get_error(), sslerr, sizeof(sslerr));
log_err(knet_h, KNET_SUB_OPENSSLCRYPTO, "Unable to finalize decrypt: %s", sslerr);
err = -1;
goto out;
}
*buf_out_len = tmplen1 + tmplen2;
out:
EVP_CIPHER_CTX_cleanup(&ctx);
return err;
}
#endif
#ifdef BUILDCRYPTOOPENSSL11
static int encrypt_openssl(
knet_handle_t knet_h,
const struct iovec *iov,
int iovcnt,
unsigned char *buf_out,
ssize_t *buf_out_len)
{
struct opensslcrypto_instance *instance = knet_h->crypto_instance->model_instance;
EVP_CIPHER_CTX *ctx;
int tmplen = 0, offset = 0;
unsigned char *salt = buf_out;
unsigned char *data = buf_out + SALT_SIZE;
int err = 0;
int i;
char sslerr[SSLERR_BUF_SIZE];
ctx = EVP_CIPHER_CTX_new();
/*
* contribute to PRNG for each packet we send/receive
*/
RAND_seed((unsigned char *)iov[iovcnt - 1].iov_base, iov[iovcnt - 1].iov_len);
if (!RAND_bytes(salt, SALT_SIZE)) {
ERR_error_string_n(ERR_get_error(), sslerr, sizeof(sslerr));
log_err(knet_h, KNET_SUB_OPENSSLCRYPTO, "Unable to get random salt data: %s", sslerr);
err = -1;
goto out;
}
/*
* add warning re keylength
*/
EVP_EncryptInit_ex(ctx, instance->crypto_cipher_type, NULL, instance->private_key, salt);
for (i=0; i<iovcnt; i++) {
if (!EVP_EncryptUpdate(ctx,
data + offset, &tmplen,
(unsigned char *)iov[i].iov_base, iov[i].iov_len)) {
ERR_error_string_n(ERR_get_error(), sslerr, sizeof(sslerr));
log_err(knet_h, KNET_SUB_OPENSSLCRYPTO, "Unable to encrypt: %s", sslerr);
err = -1;
goto out;
}
offset = offset + tmplen;
}
if (!EVP_EncryptFinal_ex(ctx, data + offset, &tmplen)) {
ERR_error_string_n(ERR_get_error(), sslerr, sizeof(sslerr));
log_err(knet_h, KNET_SUB_OPENSSLCRYPTO, "Unable to finalize encrypt: %s", sslerr);
err = -1;
goto out;
}
*buf_out_len = offset + tmplen + SALT_SIZE;
out:
EVP_CIPHER_CTX_free(ctx);
return err;
}
static int decrypt_openssl (
knet_handle_t knet_h,
const unsigned char *buf_in,
const ssize_t buf_in_len,
unsigned char *buf_out,
ssize_t *buf_out_len)
{
struct opensslcrypto_instance *instance = knet_h->crypto_instance->model_instance;
- EVP_CIPHER_CTX *ctx;
+ EVP_CIPHER_CTX *ctx = NULL;
int tmplen1 = 0, tmplen2 = 0;
unsigned char *salt = (unsigned char *)buf_in;
unsigned char *data = salt + SALT_SIZE;
int datalen = buf_in_len - SALT_SIZE;
int err = 0;
char sslerr[SSLERR_BUF_SIZE];
+ if (datalen <= 0) {
+ log_err(knet_h, KNET_SUB_OPENSSLCRYPTO, "Packet is too short");
+ err = -1;
+ goto out;
+ }
+
ctx = EVP_CIPHER_CTX_new();
/*
* contribute to PRNG for each packet we send/receive
*/
RAND_seed(buf_in, buf_in_len);
/*
* add warning re keylength
*/
EVP_DecryptInit_ex(ctx, instance->crypto_cipher_type, NULL, instance->private_key, salt);
if (!EVP_DecryptUpdate(ctx, buf_out, &tmplen1, data, datalen)) {
ERR_error_string_n(ERR_get_error(), sslerr, sizeof(sslerr));
log_err(knet_h, KNET_SUB_OPENSSLCRYPTO, "Unable to decrypt: %s", sslerr);
err = -1;
goto out;
}
if (!EVP_DecryptFinal_ex(ctx, buf_out + tmplen1, &tmplen2)) {
ERR_error_string_n(ERR_get_error(), sslerr, sizeof(sslerr));
log_err(knet_h, KNET_SUB_OPENSSLCRYPTO, "Unable to finalize decrypt: %s", sslerr);
err = -1;
goto out;
}
*buf_out_len = tmplen1 + tmplen2;
out:
- EVP_CIPHER_CTX_free(ctx);
+ if (ctx) {
+ EVP_CIPHER_CTX_free(ctx);
+ }
return err;
}
#endif
/*
* hash/hmac/digest functions
*/
static int calculate_openssl_hash(
knet_handle_t knet_h,
const unsigned char *buf,
const size_t buf_len,
unsigned char *hash)
{
struct opensslcrypto_instance *instance = knet_h->crypto_instance->model_instance;
unsigned int hash_len = 0;
unsigned char *hash_out = NULL;
char sslerr[SSLERR_BUF_SIZE];
hash_out = HMAC(instance->crypto_hash_type,
instance->private_key, instance->private_key_len,
buf, buf_len,
hash, &hash_len);
if ((!hash_out) || (hash_len != knet_h->sec_hash_size)) {
ERR_error_string_n(ERR_get_error(), sslerr, sizeof(sslerr));
log_err(knet_h, KNET_SUB_OPENSSLCRYPTO, "Unable to calculate hash: %s", sslerr);
return -1;
}
return 0;
}
/*
* exported API
*/
static int opensslcrypto_encrypt_and_signv (
knet_handle_t knet_h,
const struct iovec *iov_in,
int iovcnt_in,
unsigned char *buf_out,
ssize_t *buf_out_len)
{
struct opensslcrypto_instance *instance = knet_h->crypto_instance->model_instance;
int i;
if (instance->crypto_cipher_type) {
if (encrypt_openssl(knet_h, iov_in, iovcnt_in, buf_out, buf_out_len) < 0) {
return -1;
}
} else {
*buf_out_len = 0;
for (i=0; i<iovcnt_in; i++) {
memmove(buf_out + *buf_out_len, iov_in[i].iov_base, iov_in[i].iov_len);
*buf_out_len = *buf_out_len + iov_in[i].iov_len;
}
}
if (instance->crypto_hash_type) {
if (calculate_openssl_hash(knet_h, buf_out, *buf_out_len, buf_out + *buf_out_len) < 0) {
return -1;
}
*buf_out_len = *buf_out_len + knet_h->sec_hash_size;
}
return 0;
}
static int opensslcrypto_encrypt_and_sign (
knet_handle_t knet_h,
const unsigned char *buf_in,
const ssize_t buf_in_len,
unsigned char *buf_out,
ssize_t *buf_out_len)
{
struct iovec iov_in;
memset(&iov_in, 0, sizeof(iov_in));
iov_in.iov_base = (unsigned char *)buf_in;
iov_in.iov_len = buf_in_len;
return opensslcrypto_encrypt_and_signv(knet_h, &iov_in, 1, buf_out, buf_out_len);
}
static int opensslcrypto_authenticate_and_decrypt (
knet_handle_t knet_h,
const unsigned char *buf_in,
const ssize_t buf_in_len,
unsigned char *buf_out,
ssize_t *buf_out_len)
{
struct opensslcrypto_instance *instance = knet_h->crypto_instance->model_instance;
ssize_t temp_len = buf_in_len;
if (instance->crypto_hash_type) {
unsigned char tmp_hash[knet_h->sec_hash_size];
ssize_t temp_buf_len = buf_in_len - knet_h->sec_hash_size;
- if ((temp_buf_len < 0) || (temp_buf_len > KNET_MAX_PACKET_SIZE)) {
+ if ((temp_buf_len <= 0) || (temp_buf_len > KNET_MAX_PACKET_SIZE)) {
log_err(knet_h, KNET_SUB_OPENSSLCRYPTO, "Incorrect packet size.");
return -1;
}
if (calculate_openssl_hash(knet_h, buf_in, temp_buf_len, tmp_hash) < 0) {
return -1;
}
if (memcmp(tmp_hash, buf_in + temp_buf_len, knet_h->sec_hash_size) != 0) {
log_err(knet_h, KNET_SUB_OPENSSLCRYPTO, "Digest does not match");
return -1;
}
temp_len = temp_len - knet_h->sec_hash_size;
*buf_out_len = temp_len;
}
if (instance->crypto_cipher_type) {
if (decrypt_openssl(knet_h, buf_in, temp_len, buf_out, buf_out_len) < 0) {
return -1;
}
} else {
memmove(buf_out, buf_in, temp_len);
*buf_out_len = temp_len;
}
return 0;
}
#ifdef BUILDCRYPTOOPENSSL10
static pthread_mutex_t *openssl_internal_lock;
static void openssl_internal_locking_callback(int mode, int type, char *file, int line)
{
if (mode & CRYPTO_LOCK) {
pthread_mutex_lock(&(openssl_internal_lock[type]));
} else {
pthread_mutex_unlock(&(openssl_internal_lock[type]));
}
}
static unsigned long openssl_internal_thread_id(void)
{
return (unsigned long)pthread_self();
}
static void openssl_internal_lock_cleanup(void)
{
int i;
CRYPTO_set_locking_callback(NULL);
CRYPTO_set_id_callback(NULL);
for (i = 0; i < CRYPTO_num_locks(); i++) {
pthread_mutex_destroy(&(openssl_internal_lock[i]));
}
if (openssl_internal_lock) {
free(openssl_internal_lock);
}
return;
}
static int openssl_internal_lock_setup(void)
{
int savederrno = 0, err = 0;
int i;
openssl_internal_lock = malloc(CRYPTO_num_locks() * sizeof(pthread_mutex_t));
if (!openssl_internal_lock) {
savederrno = errno;
err = -1;
goto out;
}
for (i = 0; i < CRYPTO_num_locks(); i++) {
savederrno = pthread_mutex_init(&(openssl_internal_lock[i]), NULL);
if (savederrno) {
err = -1;
goto out;
}
}
CRYPTO_set_id_callback((unsigned long (*)(void))openssl_internal_thread_id);
CRYPTO_set_locking_callback((void *)&openssl_internal_locking_callback);
out:
if (err) {
openssl_internal_lock_cleanup();
}
errno = savederrno;
return err;
}
#endif
static void opensslcrypto_fini(
knet_handle_t knet_h)
{
struct opensslcrypto_instance *opensslcrypto_instance = knet_h->crypto_instance->model_instance;
if (opensslcrypto_instance) {
#ifdef BUILDCRYPTOOPENSSL10
openssl_internal_lock_cleanup();
#endif
if (opensslcrypto_instance->private_key) {
free(opensslcrypto_instance->private_key);
opensslcrypto_instance->private_key = NULL;
}
free(opensslcrypto_instance);
knet_h->crypto_instance->model_instance = NULL;
knet_h->sec_header_size = 0;
}
return;
}
static int opensslcrypto_init(
knet_handle_t knet_h,
struct knet_handle_crypto_cfg *knet_handle_crypto_cfg)
{
static int openssl_is_init = 0;
struct opensslcrypto_instance *opensslcrypto_instance = NULL;
int savederrno;
log_debug(knet_h, KNET_SUB_OPENSSLCRYPTO,
"Initizializing openssl crypto module [%s/%s]",
knet_handle_crypto_cfg->crypto_cipher_type,
knet_handle_crypto_cfg->crypto_hash_type);
if (!openssl_is_init) {
#ifdef BUILDCRYPTOOPENSSL10
ERR_load_crypto_strings();
OPENSSL_add_all_algorithms_noconf();
#endif
#ifdef BUILDCRYPTOOPENSSL11
if (!OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS \
| OPENSSL_INIT_ADD_ALL_DIGESTS, NULL)) {
log_err(knet_h, KNET_SUB_OPENSSLCRYPTO, "Unable to init openssl");
errno = EAGAIN;
return -1;
}
#endif
openssl_is_init = 1;
}
#ifdef BUILDCRYPTOOPENSSL10
if (openssl_internal_lock_setup() < 0) {
log_err(knet_h, KNET_SUB_OPENSSLCRYPTO, "Unable to init openssl");
errno = EAGAIN;
return -1;
}
#endif
knet_h->crypto_instance->model_instance = malloc(sizeof(struct opensslcrypto_instance));
if (!knet_h->crypto_instance->model_instance) {
log_err(knet_h, KNET_SUB_OPENSSLCRYPTO, "Unable to allocate memory for openssl model instance");
errno = ENOMEM;
return -1;
}
opensslcrypto_instance = knet_h->crypto_instance->model_instance;
memset(opensslcrypto_instance, 0, sizeof(struct opensslcrypto_instance));
if (strcmp(knet_handle_crypto_cfg->crypto_cipher_type, "none") == 0) {
opensslcrypto_instance->crypto_cipher_type = NULL;
} else {
opensslcrypto_instance->crypto_cipher_type = EVP_get_cipherbyname(knet_handle_crypto_cfg->crypto_cipher_type);
if (!opensslcrypto_instance->crypto_cipher_type) {
log_err(knet_h, KNET_SUB_OPENSSLCRYPTO, "unknown crypto cipher type requested");
savederrno = ENXIO;
goto out_err;
}
}
if (strcmp(knet_handle_crypto_cfg->crypto_hash_type, "none") == 0) {
opensslcrypto_instance->crypto_hash_type = NULL;
} else {
opensslcrypto_instance->crypto_hash_type = EVP_get_digestbyname(knet_handle_crypto_cfg->crypto_hash_type);
if (!opensslcrypto_instance->crypto_hash_type) {
log_err(knet_h, KNET_SUB_OPENSSLCRYPTO, "unknown crypto hash type requested");
savederrno = ENXIO;
goto out_err;
}
}
if ((opensslcrypto_instance->crypto_cipher_type) &&
(!opensslcrypto_instance->crypto_hash_type)) {
log_err(knet_h, KNET_SUB_OPENSSLCRYPTO, "crypto communication requires hash specified");
savederrno = EINVAL;
goto out_err;
}
opensslcrypto_instance->private_key = malloc(knet_handle_crypto_cfg->private_key_len);
if (!opensslcrypto_instance->private_key) {
log_err(knet_h, KNET_SUB_OPENSSLCRYPTO, "Unable to allocate memory for openssl private key");
savederrno = ENOMEM;
goto out_err;
}
memmove(opensslcrypto_instance->private_key, knet_handle_crypto_cfg->private_key, knet_handle_crypto_cfg->private_key_len);
opensslcrypto_instance->private_key_len = knet_handle_crypto_cfg->private_key_len;
knet_h->sec_header_size = 0;
if (opensslcrypto_instance->crypto_hash_type) {
knet_h->sec_hash_size = EVP_MD_size(opensslcrypto_instance->crypto_hash_type);
knet_h->sec_header_size += knet_h->sec_hash_size;
}
if (opensslcrypto_instance->crypto_cipher_type) {
size_t block_size;
block_size = EVP_CIPHER_block_size(opensslcrypto_instance->crypto_cipher_type);
knet_h->sec_header_size += (block_size * 2);
knet_h->sec_header_size += SALT_SIZE;
knet_h->sec_salt_size = SALT_SIZE;
knet_h->sec_block_size = block_size;
}
return 0;
out_err:
opensslcrypto_fini(knet_h);
errno = savederrno;
return -1;
}
crypto_ops_t crypto_model = {
KNET_CRYPTO_MODEL_ABI,
opensslcrypto_init,
opensslcrypto_fini,
opensslcrypto_encrypt_and_sign,
opensslcrypto_encrypt_and_signv,
opensslcrypto_authenticate_and_decrypt
};
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Tue, Feb 25, 6:33 AM (1 d, 11 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1464713
Default Alt Text
(39 KB)
Attached To
Mode
rK kronosnet
Attached
Detach File
Event Timeline
Log In to Comment