From 42a2f69e6fc475cf1a7f4b4af3aff992f71ea194 Mon Sep 17 00:00:00 2001 From: Jan Friesse Date: Tue, 13 Mar 2012 11:34:33 +0100 Subject: [PATCH] onecrypt: move encryption code to crypto.c This will remove duplicity of code. Signed-off-by: Jan Friesse Reviewed-by: Fabio M. Di Nitto --- exec/Makefile.am | 4 +- exec/crypto.c | 545 +++++++++++++++++++++++++++++++++++++++++++++++ exec/crypto.h | 77 +++++++ exec/totemudp.c | 483 +++-------------------------------------- exec/totemudpu.c | 479 ++--------------------------------------- 5 files changed, 671 insertions(+), 917 deletions(-) create mode 100644 exec/crypto.c create mode 100644 exec/crypto.h diff --git a/exec/Makefile.am b/exec/Makefile.am index c481c0ae..0db4db69 100644 --- a/exec/Makefile.am +++ b/exec/Makefile.am @@ -37,7 +37,7 @@ INCLUDES = -I$(top_builddir)/include -I$(top_srcdir)/include $(nss_CFLAGS) $(rd TOTEM_SRC = totemip.c totemnet.c totemudp.c \ totemudpu.c totemrrp.c totemsrp.c totemmrp.c \ - totempg.c cs_queue.h + totempg.c cs_queue.h crypto.c if BUILD_RDMA TOTEM_SRC += totemiba.c endif @@ -66,7 +66,7 @@ noinst_HEADERS = apidef.h mainconfig.h main.h \ quorum.h service.h timer.h totemconfig.h \ totemmrp.h totemnet.h totemudp.h totemiba.h totemrrp.h \ totemudpu.h totemsrp.h util.h vsf.h schedwrk.h \ - sync.h fsm.h votequorum.h vsf_ykd.h + sync.h fsm.h votequorum.h vsf_ykd.h crypto.h if BUILD_DARWIN libtotem_pg.so.$(SONAME): $(TOTEM_OBJS) diff --git a/exec/crypto.c b/exec/crypto.c new file mode 100644 index 00000000..7d40efcf --- /dev/null +++ b/exec/crypto.c @@ -0,0 +1,545 @@ +/* + * Copyright (c) 2006-2012 Red Hat, Inc. + * + * All rights reserved. + * + * Author: Steven Dake (sdake@redhat.com) + * Christine Caulfield (ccaulfie@redhat.com) + * Jan Friesse (jfriesse@redhat.com) + * + * This software licensed under BSD license, the text of which follows: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * - Neither the name of the MontaVista Software, Inc. nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#define LOGSYS_UTILS_ONLY 1 +#include +#include +#include "crypto.h" + +#include "util.h" + +#include +#include +#include +#include + +struct crypto_instance { + PK11SymKey *nss_sym_key; + PK11SymKey *nss_sym_key_sign; + + unsigned char private_key[1024]; + + unsigned int private_key_len; + + void (*log_printf_func) ( + int level, + int subsys, + const char *function, + const char *file, + int line, + const char *format, + ...)__attribute__((format(printf, 6, 7))); + + int log_level_security; + int log_level_notice; + int log_level_error; + int log_subsys_id; +}; + +#define log_printf(level, format, args...) \ +do { \ + instance->log_printf_func ( \ + level, instance->log_subsys_id, \ + __FUNCTION__, __FILE__, __LINE__, \ + (const char *)format, ##args); \ +} while (0); + +#define LOGSYS_PERROR(err_num, level, fmt, args...) \ +do { \ + char _error_str[LOGSYS_MAX_PERROR_MSG_LEN]; \ + const char *_error_ptr = qb_strerror_r(err_num, _error_str, sizeof(_error_str)); \ + instance->totemudp_log_printf ( \ + level, instance->log_subsys_id, \ + __FUNCTION__, __FILE__, __LINE__, \ + fmt ": %s (%d)", ##args, _error_ptr, err_num); \ + } while(0) + + +static unsigned char *copy_from_iovec( + const struct iovec *iov, + unsigned int iov_len, + size_t *buf_size) +{ + int i; + size_t bufptr; + size_t buflen = 0; + unsigned char *newbuf; + + for (i=0; i buf_size) { + copylen = buf_size - bufptr; + } + memcpy(iov[i].iov_base, buf+bufptr, copylen); + bufptr += copylen; + if (iov[i].iov_len != copylen) { + iov[i].iov_len = copylen; + return; + } + } +} + +static void init_nss_crypto(struct crypto_instance *instance) +{ + PK11SlotInfo* aes_slot = NULL; + PK11SlotInfo* sha1_slot = NULL; + SECItem key_item; + SECStatus rv; + + log_printf(instance->log_level_notice, + "Initializing transmit/receive security: NSS AES256CBC/SHA1HMAC (mode %u).", 0); + rv = NSS_NoDB_Init("."); + if (rv != SECSuccess) + { + log_printf(instance->log_level_security, "NSS initialization failed (err %d)", + PR_GetError()); + goto out; + } + + aes_slot = PK11_GetBestSlot(CKM_AES_CBC_PAD, NULL); + if (aes_slot == NULL) + { + log_printf(instance->log_level_security, "Unable to find security slot (err %d)", + PR_GetError()); + goto out; + } + + sha1_slot = PK11_GetBestSlot(CKM_SHA_1_HMAC, NULL); + if (sha1_slot == NULL) + { + log_printf(instance->log_level_security, "Unable to find security slot (err %d)", + PR_GetError()); + goto out; + } + /* + * Make the private key into a SymKey that we can use + */ + key_item.type = siBuffer; + key_item.data = instance->private_key; + key_item.len = 32; /* Use 256 bits */ + + instance->nss_sym_key = PK11_ImportSymKey(aes_slot, + CKM_AES_CBC_PAD, + PK11_OriginUnwrap, CKA_ENCRYPT|CKA_DECRYPT, + &key_item, NULL); + if (instance->nss_sym_key == NULL) + { + log_printf(instance->log_level_security, "Failure to import key into NSS (err %d)", + PR_GetError()); + goto out; + } + + instance->nss_sym_key_sign = PK11_ImportSymKey(sha1_slot, + CKM_SHA_1_HMAC, + PK11_OriginUnwrap, CKA_SIGN, + &key_item, NULL); + if (instance->nss_sym_key_sign == NULL) { + log_printf(instance->log_level_security, "Failure to import key into NSS (err %d)", + PR_GetError()); + goto out; + } +out: + return; +} + +static int encrypt_and_sign_nss ( + struct crypto_instance *instance, + unsigned char *buf, + size_t *buf_len, + const struct iovec *iovec, + unsigned int iov_len) +{ + PK11Context* enc_context = NULL; + SECStatus rv1, rv2; + int tmp1_outlen; + unsigned int tmp2_outlen; + unsigned char *inbuf; + unsigned char *data; + unsigned char *outdata; + size_t datalen; + SECItem no_params; + SECItem iv_item; + struct crypto_security_header *header; + SECItem *nss_sec_param; + unsigned char nss_iv_data[16]; + SECStatus rv; + + no_params.type = siBuffer; + no_params.data = 0; + no_params.len = 0; + + tmp1_outlen = tmp2_outlen = 0; + inbuf = copy_from_iovec(iovec, iov_len, &datalen); + if (!inbuf) { + log_printf(instance->log_level_security, "malloc error copying buffer from iovec"); + return -1; + } + + data = inbuf + sizeof (struct crypto_security_header); + datalen -= sizeof (struct crypto_security_header); + + outdata = buf + sizeof (struct crypto_security_header); + header = (struct crypto_security_header *)buf; + + rv = PK11_GenerateRandom ( + nss_iv_data, + sizeof (nss_iv_data)); + if (rv != SECSuccess) { + log_printf(instance->log_level_security, + "Failure to generate a random number %d", + PR_GetError()); + } + + memcpy(header->salt, nss_iv_data, sizeof(nss_iv_data)); + iv_item.type = siBuffer; + iv_item.data = nss_iv_data; + iv_item.len = sizeof (nss_iv_data); + + nss_sec_param = PK11_ParamFromIV ( + CKM_AES_CBC_PAD, + &iv_item); + if (nss_sec_param == NULL) { + log_printf(instance->log_level_security, + "Failure to set up PKCS11 param (err %d)", + PR_GetError()); + free (inbuf); + return (-1); + } + + /* + * Create cipher context for encryption + */ + enc_context = PK11_CreateContextBySymKey ( + CKM_AES_CBC_PAD, + CKA_ENCRYPT, + instance->nss_sym_key, + nss_sec_param); + if (!enc_context) { + char err[1024]; + PR_GetErrorText(err); + err[PR_GetErrorTextLength()] = 0; + log_printf(instance->log_level_security, + "PK11_CreateContext failed (encrypt) crypt_type=%d (err %d): %s", + CKM_AES_CBC_PAD, + PR_GetError(), err); + free(inbuf); + return -1; + } + rv1 = PK11_CipherOp(enc_context, outdata, + &tmp1_outlen, FRAME_SIZE_MAX - sizeof(struct crypto_security_header), + data, datalen); + rv2 = PK11_DigestFinal(enc_context, outdata + tmp1_outlen, &tmp2_outlen, + FRAME_SIZE_MAX - tmp1_outlen); + PK11_DestroyContext(enc_context, PR_TRUE); + + *buf_len = tmp1_outlen + tmp2_outlen; + free(inbuf); +// memcpy(&outdata[*buf_len], nss_iv_data, sizeof(nss_iv_data)); + + if (rv1 != SECSuccess || rv2 != SECSuccess) + goto out; + + /* Now do the digest */ + enc_context = PK11_CreateContextBySymKey(CKM_SHA_1_HMAC, + CKA_SIGN, instance->nss_sym_key_sign, &no_params); + if (!enc_context) { + char err[1024]; + PR_GetErrorText(err); + err[PR_GetErrorTextLength()] = 0; + log_printf(instance->log_level_security, "encrypt: PK11_CreateContext failed (digest) err %d: %s", + PR_GetError(), err); + return -1; + } + + + PK11_DigestBegin(enc_context); + + rv1 = PK11_DigestOp(enc_context, outdata - 16, *buf_len + 16); + rv2 = PK11_DigestFinal(enc_context, header->hash_digest, &tmp2_outlen, sizeof(header->hash_digest)); + + PK11_DestroyContext(enc_context, PR_TRUE); + + if (rv1 != SECSuccess || rv2 != SECSuccess) + goto out; + + + *buf_len = *buf_len + sizeof(struct crypto_security_header); + SECITEM_FreeItem(nss_sec_param, PR_TRUE); + return 0; + +out: + return -1; +} + + +static int authenticate_and_decrypt_nss ( + struct crypto_instance *instance, + struct iovec *iov, + unsigned int iov_len) +{ + PK11Context* enc_context = NULL; + SECStatus rv1, rv2; + int tmp1_outlen; + unsigned int tmp2_outlen; + unsigned char outbuf[FRAME_SIZE_MAX]; + unsigned char digest[CRYPTO_HMAC_HASH_SIZE]; + unsigned char *outdata; + int result_len; + unsigned char *data; + unsigned char *inbuf; + size_t datalen; + struct crypto_security_header *header = (struct crypto_security_header *)iov[0].iov_base; + SECItem no_params; + SECItem ivdata; + + no_params.type = siBuffer; + no_params.data = 0; + no_params.len = 0; + + tmp1_outlen = tmp2_outlen = 0; + if (iov_len > 1) { + inbuf = copy_from_iovec(iov, iov_len, &datalen); + if (!inbuf) { + log_printf(instance->log_level_security, "malloc error copying buffer from iovec"); + return -1; + } + } + else { + inbuf = (unsigned char *)iov[0].iov_base; + datalen = iov[0].iov_len; + } + data = inbuf + sizeof (struct crypto_security_header) - 16; + datalen = datalen - sizeof (struct crypto_security_header) + 16; + + outdata = outbuf + sizeof (struct crypto_security_header); + + /* Check the digest */ + enc_context = PK11_CreateContextBySymKey ( + CKM_SHA_1_HMAC, CKA_SIGN, + instance->nss_sym_key_sign, + &no_params); + if (!enc_context) { + char err[1024]; + PR_GetErrorText(err); + err[PR_GetErrorTextLength()] = 0; + log_printf(instance->log_level_security, "PK11_CreateContext failed (check digest) err %d: %s", + PR_GetError(), err); + free (inbuf); + return -1; + } + + PK11_DigestBegin(enc_context); + + rv1 = PK11_DigestOp(enc_context, data, datalen); + rv2 = PK11_DigestFinal(enc_context, digest, &tmp2_outlen, sizeof(digest)); + + PK11_DestroyContext(enc_context, PR_TRUE); + + if (rv1 != SECSuccess || rv2 != SECSuccess) { + log_printf(instance->log_level_security, "Digest check failed"); + return -1; + } + + if (memcmp(digest, header->hash_digest, tmp2_outlen) != 0) { + log_printf(instance->log_level_error, "Digest does not match"); + return -1; + } + + /* + * Get rid of salt + */ + data += 16; + datalen -= 16; + + /* Create cipher context for decryption */ + ivdata.type = siBuffer; + ivdata.data = header->salt; + ivdata.len = sizeof(header->salt); + + enc_context = PK11_CreateContextBySymKey( + CKM_AES_CBC_PAD, + CKA_DECRYPT, + instance->nss_sym_key, &ivdata); + if (!enc_context) { + log_printf(instance->log_level_security, + "PK11_CreateContext (decrypt) failed (err %d)", + PR_GetError()); + return -1; + } + + rv1 = PK11_CipherOp(enc_context, outdata, &tmp1_outlen, + sizeof(outbuf) - sizeof (struct crypto_security_header), + data, datalen); + if (rv1 != SECSuccess) { + log_printf(instance->log_level_security, + "PK11_CipherOp (decrypt) failed (err %d)", + PR_GetError()); + } + rv2 = PK11_DigestFinal(enc_context, outdata + tmp1_outlen, &tmp2_outlen, + sizeof(outbuf) - tmp1_outlen); + PK11_DestroyContext(enc_context, PR_TRUE); + result_len = tmp1_outlen + tmp2_outlen + sizeof (struct crypto_security_header); + + /* Copy it back to the buffer */ + copy_to_iovec(iov, iov_len, outbuf, result_len); + if (iov_len > 1) + free(inbuf); + + if (rv1 != SECSuccess || rv2 != SECSuccess) + return -1; + + return 0; +} + +int crypto_encrypt_and_sign ( + struct crypto_instance *instance, + unsigned char *buf, + size_t *buf_len, + const struct iovec *iovec, + unsigned int iov_len) +{ + + return (encrypt_and_sign_nss(instance, buf, buf_len, iovec, iov_len)); +} + +int crypto_authenticate_and_decrypt (struct crypto_instance *instance, + struct iovec *iov, + unsigned int iov_len) +{ + unsigned char type; + unsigned char *endbuf = (unsigned char *)iov[iov_len-1].iov_base; + + /* + * Get the encryption type and remove it from the buffer + */ + type = endbuf[iov[iov_len-1].iov_len-1]; + iov[iov_len-1].iov_len -= 1; + + return (authenticate_and_decrypt_nss(instance, iov, iov_len)); +} + +struct crypto_instance *crypto_init( + const unsigned char *private_key, + unsigned int private_key_len, + void (*log_printf_func) ( + int level, + int subsys, + const char *function, + const char *file, + int line, + const char *format, + ...)__attribute__((format(printf, 6, 7))), + int log_level_security, + int log_level_notice, + int log_level_error, + int log_subsys_id) +{ + struct crypto_instance *instance; + instance = malloc(sizeof(*instance)); + if (instance == NULL) { + return (NULL); + } + memset(instance, 0, sizeof(struct crypto_instance)); + + memcpy(instance->private_key, private_key, private_key_len); + instance->private_key_len = private_key_len; + instance->log_printf_func = log_printf_func; + instance->log_level_security = log_level_security; + instance->log_level_notice = log_level_notice; + instance->log_level_error = log_level_error; + instance->log_subsys_id = log_subsys_id; + + init_nss_crypto(instance); + + return (instance); +} diff --git a/exec/crypto.h b/exec/crypto.h new file mode 100644 index 00000000..b98ca484 --- /dev/null +++ b/exec/crypto.h @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2006-2012 Red Hat, Inc. + * + * All rights reserved. + * + * Author: Steven Dake (sdake@redhat.com) + * Christine Caulfield (ccaulfie@redhat.com) + * Jan Friesse (jfriesse@redhat.com) + * + * This software licensed under BSD license, the text of which follows: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * - Neither the name of the MontaVista Software, Inc. nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef CRYPTO_H_DEFINED +#define CRYPTO_H_DEFINED + +#include + +#define CRYPTO_HMAC_HASH_SIZE 20 +struct crypto_security_header { + unsigned char hash_digest[CRYPTO_HMAC_HASH_SIZE]; /* The hash *MUST* be first in the data structure */ + unsigned char salt[16]; /* random number */ + char msg[0]; +} __attribute__((packed)); + +struct crypto_instance; + +extern int crypto_authenticate_and_decrypt (struct crypto_instance *instance, + struct iovec *iov, + unsigned int iov_len); + +extern int crypto_encrypt_and_sign ( + struct crypto_instance *instance, + unsigned char *buf, + size_t *buf_len, + const struct iovec *iovec, + unsigned int iov_len); + +extern struct crypto_instance *crypto_init( + const unsigned char *private_key, + unsigned int private_key_len, + void (*log_printf_func) ( + int level, + int subsys, + const char *function, + const char *file, + int line, + const char *format, + ...)__attribute__((format(printf, 6, 7))), + int log_level_security, + int log_level_notice, + int log_level_error, + int log_subsys_id); + +#endif /* CRYPTO_H_DEFINED */ diff --git a/exec/totemudp.c b/exec/totemudp.c index 407df30e..5386ede0 100644 --- a/exec/totemudp.c +++ b/exec/totemudp.c @@ -68,6 +68,7 @@ #include "totemudp.h" #include "util.h" +#include "crypto.h" #include #include @@ -88,13 +89,6 @@ #define MESSAGE_TYPE_MCAST 1 -#define HMAC_HASH_SIZE 20 -struct security_header { - unsigned char hash_digest[HMAC_HASH_SIZE]; /* The hash *MUST* be first in the data structure */ - unsigned char salt[16]; /* random number */ - char msg[0]; -} __attribute__((packed)); - struct totemudp_socket { int mcast_recv; int mcast_send; @@ -102,12 +96,7 @@ struct totemudp_socket { }; struct totemudp_instance { - PK11SymKey *nss_sym_key; - PK11SymKey *nss_sym_key_sign; - - unsigned char totemudp_private_key[1024]; - - unsigned int totemudp_private_key_len; + struct crypto_instance *crypto_inst; qb_loop_t *totemudp_poll_handle; @@ -244,439 +233,15 @@ do { \ instance->totemudp_log_printf ( \ level, instance->totemudp_subsys_id, \ __FUNCTION__, __FILE__, __LINE__, \ - fmt ": %s (%d)", ##args, _error_ptr, err_num); \ + fmt ": %s (%d)\n", ##args, _error_ptr, err_num); \ } while(0) - -static unsigned char *copy_from_iovec( - const struct iovec *iov, - unsigned int iov_len, - size_t *buf_size) -{ - int i; - size_t bufptr; - size_t buflen = 0; - unsigned char *newbuf; - - for (i=0; i buf_size) { - copylen = buf_size - bufptr; - } - memcpy(iov[i].iov_base, buf+bufptr, copylen); - bufptr += copylen; - if (iov[i].iov_len != copylen) { - iov[i].iov_len = copylen; - return; - } - } -} - -static void init_nss_crypto( - struct totemudp_instance *instance) -{ - PK11SlotInfo* aes_slot = NULL; - PK11SlotInfo* sha1_slot = NULL; - SECItem key_item; - SECStatus rv; - - log_printf(instance->totemudp_log_level_notice, - "Initializing transmit/receive security: NSS AES256CBC/SHA1HMAC (mode %u).", TOTEM_CRYPTO_AES256); - rv = NSS_NoDB_Init("."); - if (rv != SECSuccess) - { - log_printf(instance->totemudp_log_level_security, "NSS initialization failed (err %d)", - PR_GetError()); - goto out; - } - - aes_slot = PK11_GetBestSlot(instance->totem_config->crypto_crypt_type, NULL); - if (aes_slot == NULL) - { - log_printf(instance->totemudp_log_level_security, "Unable to find security slot (err %d)", - PR_GetError()); - goto out; - } - - sha1_slot = PK11_GetBestSlot(CKM_SHA_1_HMAC, NULL); - if (sha1_slot == NULL) - { - log_printf(instance->totemudp_log_level_security, "Unable to find security slot (err %d)", - PR_GetError()); - goto out; - } - /* - * Make the private key into a SymKey that we can use - */ - key_item.type = siBuffer; - key_item.data = instance->totem_config->private_key; - key_item.len = 32; /* Use 256 bits */ - - instance->nss_sym_key = PK11_ImportSymKey(aes_slot, - instance->totem_config->crypto_crypt_type, - PK11_OriginUnwrap, CKA_ENCRYPT|CKA_DECRYPT, - &key_item, NULL); - if (instance->nss_sym_key == NULL) - { - log_printf(instance->totemudp_log_level_security, "Failure to import key into NSS (err %d)", - PR_GetError()); - goto out; - } - - instance->nss_sym_key_sign = PK11_ImportSymKey(sha1_slot, - CKM_SHA_1_HMAC, - PK11_OriginUnwrap, CKA_SIGN, - &key_item, NULL); - if (instance->nss_sym_key_sign == NULL) { - log_printf(instance->totemudp_log_level_security, "Failure to import key into NSS (err %d)", - PR_GetError()); - goto out; - } -out: - return; -} - -static int encrypt_and_sign_nss ( - struct totemudp_instance *instance, - unsigned char *buf, - size_t *buf_len, - const struct iovec *iovec, - unsigned int iov_len) -{ - PK11Context* enc_context = NULL; - SECStatus rv1, rv2; - int tmp1_outlen; - unsigned int tmp2_outlen; - unsigned char *inbuf; - unsigned char *data; - unsigned char *outdata; - size_t datalen; - SECItem no_params; - SECItem iv_item; - struct security_header *header; - SECItem *nss_sec_param; - unsigned char nss_iv_data[16]; - SECStatus rv; - - no_params.type = siBuffer; - no_params.data = 0; - no_params.len = 0; - - tmp1_outlen = tmp2_outlen = 0; - inbuf = copy_from_iovec(iovec, iov_len, &datalen); - if (!inbuf) { - log_printf(instance->totemudp_log_level_security, "malloc error copying buffer from iovec"); - return -1; - } - - data = inbuf + sizeof (struct security_header); - datalen -= sizeof (struct security_header); - - outdata = buf + sizeof (struct security_header); - header = (struct security_header *)buf; - - rv = PK11_GenerateRandom ( - nss_iv_data, - sizeof (nss_iv_data)); - if (rv != SECSuccess) { - log_printf(instance->totemudp_log_level_security, - "Failure to generate a random number %d", - PR_GetError()); - } - - memcpy(header->salt, nss_iv_data, sizeof(nss_iv_data)); - iv_item.type = siBuffer; - iv_item.data = nss_iv_data; - iv_item.len = sizeof (nss_iv_data); - - nss_sec_param = PK11_ParamFromIV ( - instance->totem_config->crypto_crypt_type, - &iv_item); - if (nss_sec_param == NULL) { - log_printf(instance->totemudp_log_level_security, - "Failure to set up PKCS11 param (err %d)", - PR_GetError()); - free (inbuf); - return (-1); - } - - /* - * Create cipher context for encryption - */ - enc_context = PK11_CreateContextBySymKey ( - instance->totem_config->crypto_crypt_type, - CKA_ENCRYPT, - instance->nss_sym_key, - nss_sec_param); - if (!enc_context) { - char err[1024]; - PR_GetErrorText(err); - err[PR_GetErrorTextLength()] = 0; - log_printf(instance->totemudp_log_level_security, - "PK11_CreateContext failed (encrypt) crypt_type=%d (err %d): %s", - instance->totem_config->crypto_crypt_type, - PR_GetError(), err); - free(inbuf); - return -1; - } - rv1 = PK11_CipherOp(enc_context, outdata, - &tmp1_outlen, FRAME_SIZE_MAX - sizeof(struct security_header), - data, datalen); - rv2 = PK11_DigestFinal(enc_context, outdata + tmp1_outlen, &tmp2_outlen, - FRAME_SIZE_MAX - tmp1_outlen); - PK11_DestroyContext(enc_context, PR_TRUE); - - *buf_len = tmp1_outlen + tmp2_outlen; - free(inbuf); -// memcpy(&outdata[*buf_len], nss_iv_data, sizeof(nss_iv_data)); - - if (rv1 != SECSuccess || rv2 != SECSuccess) - goto out; - - /* Now do the digest */ - enc_context = PK11_CreateContextBySymKey(CKM_SHA_1_HMAC, - CKA_SIGN, instance->nss_sym_key_sign, &no_params); - if (!enc_context) { - char err[1024]; - PR_GetErrorText(err); - err[PR_GetErrorTextLength()] = 0; - log_printf(instance->totemudp_log_level_security, "encrypt: PK11_CreateContext failed (digest) err %d: %s", - PR_GetError(), err); - return -1; - } - - - PK11_DigestBegin(enc_context); - - rv1 = PK11_DigestOp(enc_context, outdata - 16, *buf_len + 16); - rv2 = PK11_DigestFinal(enc_context, header->hash_digest, &tmp2_outlen, sizeof(header->hash_digest)); - - PK11_DestroyContext(enc_context, PR_TRUE); - - if (rv1 != SECSuccess || rv2 != SECSuccess) - goto out; - - - *buf_len = *buf_len + sizeof(struct security_header); - SECITEM_FreeItem(nss_sec_param, PR_TRUE); - return 0; - -out: - return -1; -} - - -static int authenticate_and_decrypt_nss ( - struct totemudp_instance *instance, - struct iovec *iov, - unsigned int iov_len) -{ - PK11Context* enc_context = NULL; - SECStatus rv1, rv2; - int tmp1_outlen; - unsigned int tmp2_outlen; - unsigned char outbuf[FRAME_SIZE_MAX]; - unsigned char digest[HMAC_HASH_SIZE]; - unsigned char *outdata; - int result_len; - unsigned char *data; - unsigned char *inbuf; - size_t datalen; - struct security_header *header = (struct security_header *)iov[0].iov_base; - SECItem no_params; - SECItem ivdata; - - no_params.type = siBuffer; - no_params.data = 0; - no_params.len = 0; - - tmp1_outlen = tmp2_outlen = 0; - if (iov_len > 1) { - inbuf = copy_from_iovec(iov, iov_len, &datalen); - if (!inbuf) { - log_printf(instance->totemudp_log_level_security, "malloc error copying buffer from iovec"); - return -1; - } - } - else { - inbuf = (unsigned char *)iov[0].iov_base; - datalen = iov[0].iov_len; - } - data = inbuf + sizeof (struct security_header) - 16; - datalen = datalen - sizeof (struct security_header) + 16; - - outdata = outbuf + sizeof (struct security_header); - - /* Check the digest */ - enc_context = PK11_CreateContextBySymKey ( - CKM_SHA_1_HMAC, CKA_SIGN, - instance->nss_sym_key_sign, - &no_params); - if (!enc_context) { - char err[1024]; - PR_GetErrorText(err); - err[PR_GetErrorTextLength()] = 0; - log_printf(instance->totemudp_log_level_security, "PK11_CreateContext failed (check digest) err %d: %s", - PR_GetError(), err); - free (inbuf); - return -1; - } - - PK11_DigestBegin(enc_context); - - rv1 = PK11_DigestOp(enc_context, data, datalen); - rv2 = PK11_DigestFinal(enc_context, digest, &tmp2_outlen, sizeof(digest)); - - PK11_DestroyContext(enc_context, PR_TRUE); - - if (rv1 != SECSuccess || rv2 != SECSuccess) { - log_printf(instance->totemudp_log_level_security, "Digest check failed"); - return -1; - } - - if (memcmp(digest, header->hash_digest, tmp2_outlen) != 0) { - log_printf(instance->totemudp_log_level_error, "Digest does not match"); - return -1; - } - - /* - * Get rid of salt - */ - data += 16; - datalen -= 16; - - /* Create cipher context for decryption */ - ivdata.type = siBuffer; - ivdata.data = header->salt; - ivdata.len = sizeof(header->salt); - - enc_context = PK11_CreateContextBySymKey( - instance->totem_config->crypto_crypt_type, - CKA_DECRYPT, - instance->nss_sym_key, &ivdata); - if (!enc_context) { - log_printf(instance->totemudp_log_level_security, - "PK11_CreateContext (decrypt) failed (err %d)", - PR_GetError()); - return -1; - } - - rv1 = PK11_CipherOp(enc_context, outdata, &tmp1_outlen, - sizeof(outbuf) - sizeof (struct security_header), - data, datalen); - if (rv1 != SECSuccess) { - log_printf(instance->totemudp_log_level_security, - "PK11_CipherOp (decrypt) failed (err %d)", - PR_GetError()); - } - rv2 = PK11_DigestFinal(enc_context, outdata + tmp1_outlen, &tmp2_outlen, - sizeof(outbuf) - tmp1_outlen); - PK11_DestroyContext(enc_context, PR_TRUE); - result_len = tmp1_outlen + tmp2_outlen + sizeof (struct security_header); - - /* Copy it back to the buffer */ - copy_to_iovec(iov, iov_len, outbuf, result_len); - if (iov_len > 1) - free(inbuf); - - if (rv1 != SECSuccess || rv2 != SECSuccess) - return -1; - - return 0; -} - -static int encrypt_and_sign_worker ( - struct totemudp_instance *instance, - unsigned char *buf, - size_t *buf_len, - const struct iovec *iovec, - unsigned int iov_len) -{ - - if (instance->totem_config->crypto_type == TOTEM_CRYPTO_AES256) { - return encrypt_and_sign_nss(instance, buf, buf_len, iovec, iov_len); - } - - return -1; -} - -static int authenticate_and_decrypt ( - struct totemudp_instance *instance, - struct iovec *iov, - unsigned int iov_len) -{ - unsigned char type; - unsigned char *endbuf = (unsigned char *)iov[iov_len-1].iov_base; - int res = -1; - - /* - * Get the encryption type and remove it from the buffer - */ - type = endbuf[iov[iov_len-1].iov_len-1]; - iov[iov_len-1].iov_len -= 1; - - if (type == TOTEM_CRYPTO_AES256) { - res = authenticate_and_decrypt_nss(instance, iov, iov_len); - } - - return res; -} - -static void init_crypto( - struct totemudp_instance *instance) -{ - - init_nss_crypto(instance); -} - int totemudp_crypto_set ( void *udp_context, unsigned int type) { - struct totemudp_instance *instance = (struct totemudp_instance *)udp_context; - int res = 0; - - /* - * Validate crypto algorithm - */ - switch (type) { - case TOTEM_CRYPTO_AES256: - log_printf(instance->totemudp_log_level_security, - "Transmit security set to: NSS AES256CBC/SHA1HMAC (mode %u)", type); - break; - default: - res = -1; - break; - } - return (res); + return (0); } @@ -689,7 +254,7 @@ static inline void ucast_sendmsg ( struct msghdr msg_ucast; int res = 0; size_t buf_len; - unsigned char sheader[sizeof (struct security_header)]; + unsigned char sheader[sizeof (struct crypto_security_header)]; unsigned char encrypt_data[FRAME_SIZE_MAX]; struct iovec iovec_encrypt[2]; const struct iovec *iovec_sendmsg; @@ -700,14 +265,14 @@ static inline void ucast_sendmsg ( if (instance->totem_config->secauth == 1) { iovec_encrypt[0].iov_base = (void *)sheader; - iovec_encrypt[0].iov_len = sizeof (struct security_header); + iovec_encrypt[0].iov_len = sizeof (struct crypto_security_header); iovec_encrypt[1].iov_base = (void *)msg; iovec_encrypt[1].iov_len = msg_len; /* * Encrypt and digest the message */ - encrypt_and_sign_worker ( - instance, + crypto_encrypt_and_sign ( + instance->crypto_inst, encrypt_data, &buf_len, iovec_encrypt, @@ -765,7 +330,7 @@ static inline void mcast_sendmsg ( struct msghdr msg_mcast; int res = 0; size_t buf_len; - unsigned char sheader[sizeof (struct security_header)]; + unsigned char sheader[sizeof (struct crypto_security_header)]; unsigned char encrypt_data[FRAME_SIZE_MAX]; struct iovec iovec_encrypt[2]; struct iovec iovec; @@ -777,15 +342,15 @@ static inline void mcast_sendmsg ( if (instance->totem_config->secauth == 1) { iovec_encrypt[0].iov_base = (void *)sheader; - iovec_encrypt[0].iov_len = sizeof (struct security_header); + iovec_encrypt[0].iov_len = sizeof (struct crypto_security_header); iovec_encrypt[1].iov_base = (void *)msg; iovec_encrypt[1].iov_len = msg_len; /* * Encrypt and digest the message */ - encrypt_and_sign_worker ( - instance, + crypto_encrypt_and_sign ( + instance->crypto_inst, encrypt_data, &buf_len, iovec_encrypt, @@ -908,7 +473,7 @@ static int net_deliver_fn ( } if ((instance->totem_config->secauth == 1) && - (bytes_received < sizeof (struct security_header))) { + (bytes_received < sizeof (struct crypto_security_header))) { log_printf (instance->totemudp_log_level_security, "Received message is too short... ignoring %d.", bytes_received); return (0); @@ -920,7 +485,7 @@ static int net_deliver_fn ( * Authenticate and if authenticated, decrypt datagram */ - res = authenticate_and_decrypt (instance, iovec, 1); + res = crypto_authenticate_and_decrypt (instance->crypto_inst, iovec, 1); if (res == -1) { log_printf (instance->totemudp_log_level_security, "Received message has invalid digest... ignoring."); log_printf (instance->totemudp_log_level_security, @@ -929,8 +494,8 @@ static int net_deliver_fn ( return 0; } msg_offset = (unsigned char *)iovec->iov_base + - sizeof (struct security_header); - size_delv = bytes_received - sizeof (struct security_header); + sizeof (struct crypto_security_header); + size_delv = bytes_received - sizeof (struct crypto_security_header); } else { msg_offset = (void *)iovec->iov_base; size_delv = bytes_received; @@ -1500,13 +1065,13 @@ int totemudp_initialize ( /* * Initialize random number generator for later use to generate salt */ - memcpy (instance->totemudp_private_key, totem_config->private_key, - totem_config->private_key_len); - - instance->totemudp_private_key_len = totem_config->private_key_len; - - init_crypto(instance); - + instance->crypto_inst = crypto_init (totem_config->private_key, + totem_config->private_key_len, + instance->totemudp_log_printf, + instance->totemudp_log_level_security, + instance->totemudp_log_level_notice, + instance->totemudp_log_level_error, + instance->totemudp_subsys_id); /* * Initialize local variables for totemudp */ @@ -1656,7 +1221,7 @@ extern void totemudp_net_mtu_adjust (void *udp_context, struct totem_config *tot { #define UDPIP_HEADER_SIZE (20 + 8) /* 20 bytes for ip 8 bytes for udp */ if (totem_config->secauth == 1) { - totem_config->net_mtu -= sizeof (struct security_header) + + totem_config->net_mtu -= sizeof (struct crypto_security_header) + UDPIP_HEADER_SIZE; } else { totem_config->net_mtu -= UDPIP_HEADER_SIZE; diff --git a/exec/totemudpu.c b/exec/totemudpu.c index 36a50238..7ed366eb 100644 --- a/exec/totemudpu.c +++ b/exec/totemudpu.c @@ -68,6 +68,7 @@ #include "totemudpu.h" #include "util.h" +#include "crypto.h" #include #include @@ -86,13 +87,6 @@ #define BIND_STATE_REGULAR 1 #define BIND_STATE_LOOPBACK 2 -#define HMAC_HASH_SIZE 20 -struct security_header { - unsigned char hash_digest[HMAC_HASH_SIZE]; /* The hash *MUST* be first in the data structure */ - unsigned char salt[16]; /* random number */ - char msg[0]; -} __attribute__((packed)); - struct totemudpu_member { struct list_head list; struct totem_ip_address member; @@ -100,12 +94,7 @@ struct totemudpu_member { }; struct totemudpu_instance { - PK11SymKey *nss_sym_key; - PK11SymKey *nss_sym_key_sign; - - unsigned char totemudpu_private_key[1024]; - - unsigned int totemudpu_private_key_len; + struct crypto_instance *crypto_inst; qb_loop_t *totemudpu_poll_handle; @@ -235,435 +224,12 @@ do { \ fmt ": %s (%d)", ##args, _error_ptr, err_num); \ } while(0) -static unsigned char *copy_from_iovec( - const struct iovec *iov, - unsigned int iov_len, - size_t *buf_size) -{ - int i; - size_t bufptr; - size_t buflen = 0; - unsigned char *newbuf; - - for (i=0; i buf_size) { - copylen = buf_size - bufptr; - } - memcpy(iov[i].iov_base, buf+bufptr, copylen); - bufptr += copylen; - if (iov[i].iov_len != copylen) { - iov[i].iov_len = copylen; - return; - } - } -} - -static void init_nss_crypto( - struct totemudpu_instance *instance) -{ - PK11SlotInfo* aes_slot = NULL; - PK11SlotInfo* sha1_slot = NULL; - SECItem key_item; - SECStatus rv; - - log_printf(instance->totemudpu_log_level_notice, - "Initializing transmit/receive security: NSS AES256CBC/SHA1HMAC (mode %u).", TOTEM_CRYPTO_AES256); - rv = NSS_NoDB_Init("."); - if (rv != SECSuccess) - { - log_printf(instance->totemudpu_log_level_security, "NSS initialization failed (err %d)", - PR_GetError()); - goto out; - } - - aes_slot = PK11_GetBestSlot(instance->totem_config->crypto_crypt_type, NULL); - if (aes_slot == NULL) - { - log_printf(instance->totemudpu_log_level_security, "Unable to find security slot (err %d)", - PR_GetError()); - goto out; - } - - sha1_slot = PK11_GetBestSlot(CKM_SHA_1_HMAC, NULL); - if (sha1_slot == NULL) - { - log_printf(instance->totemudpu_log_level_security, "Unable to find security slot (err %d)", - PR_GetError()); - goto out; - } - /* - * Make the private key into a SymKey that we can use - */ - key_item.type = siBuffer; - key_item.data = instance->totem_config->private_key; - key_item.len = 32; /* Use 256 bits */ - - instance->nss_sym_key = PK11_ImportSymKey(aes_slot, - instance->totem_config->crypto_crypt_type, - PK11_OriginUnwrap, CKA_ENCRYPT|CKA_DECRYPT, - &key_item, NULL); - if (instance->nss_sym_key == NULL) - { - log_printf(instance->totemudpu_log_level_security, "Failure to import key into NSS (err %d)", - PR_GetError()); - goto out; - } - - instance->nss_sym_key_sign = PK11_ImportSymKey(sha1_slot, - CKM_SHA_1_HMAC, - PK11_OriginUnwrap, CKA_SIGN, - &key_item, NULL); - if (instance->nss_sym_key_sign == NULL) { - log_printf(instance->totemudpu_log_level_security, "Failure to import key into NSS (err %d)", - PR_GetError()); - goto out; - } -out: - return; -} - -static int encrypt_and_sign_nss ( - struct totemudpu_instance *instance, - unsigned char *buf, - size_t *buf_len, - const struct iovec *iovec, - unsigned int iov_len) -{ - PK11Context* enc_context = NULL; - SECStatus rv1, rv2; - int tmp1_outlen; - unsigned int tmp2_outlen; - unsigned char *inbuf; - unsigned char *data; - unsigned char *outdata; - size_t datalen; - SECItem no_params; - SECItem iv_item; - struct security_header *header; - SECItem *nss_sec_param; - unsigned char nss_iv_data[16]; - SECStatus rv; - - no_params.type = siBuffer; - no_params.data = 0; - no_params.len = 0; - - tmp1_outlen = tmp2_outlen = 0; - inbuf = copy_from_iovec(iovec, iov_len, &datalen); - if (!inbuf) { - log_printf(instance->totemudpu_log_level_security, "malloc error copying buffer from iovec"); - return -1; - } - - data = inbuf + sizeof (struct security_header); - datalen -= sizeof (struct security_header); - - outdata = buf + sizeof (struct security_header); - header = (struct security_header *)buf; - - rv = PK11_GenerateRandom ( - nss_iv_data, - sizeof (nss_iv_data)); - if (rv != SECSuccess) { - log_printf(instance->totemudpu_log_level_security, - "Failure to generate a random number %d", - PR_GetError()); - } - - memcpy(header->salt, nss_iv_data, sizeof(nss_iv_data)); - iv_item.type = siBuffer; - iv_item.data = nss_iv_data; - iv_item.len = sizeof (nss_iv_data); - - nss_sec_param = PK11_ParamFromIV ( - instance->totem_config->crypto_crypt_type, - &iv_item); - if (nss_sec_param == NULL) { - log_printf(instance->totemudpu_log_level_security, - "Failure to set up PKCS11 param (err %d)", - PR_GetError()); - free (inbuf); - return (-1); - } - - /* - * Create cipher context for encryption - */ - enc_context = PK11_CreateContextBySymKey ( - instance->totem_config->crypto_crypt_type, - CKA_ENCRYPT, - instance->nss_sym_key, - nss_sec_param); - if (!enc_context) { - char err[1024]; - PR_GetErrorText(err); - err[PR_GetErrorTextLength()] = 0; - log_printf(instance->totemudpu_log_level_security, - "PK11_CreateContext failed (encrypt) crypt_type=%d (err %d): %s", - instance->totem_config->crypto_crypt_type, - PR_GetError(), err); - free(inbuf); - return -1; - } - rv1 = PK11_CipherOp(enc_context, outdata, - &tmp1_outlen, FRAME_SIZE_MAX - sizeof(struct security_header), - data, datalen); - rv2 = PK11_DigestFinal(enc_context, outdata + tmp1_outlen, &tmp2_outlen, - FRAME_SIZE_MAX - tmp1_outlen); - PK11_DestroyContext(enc_context, PR_TRUE); - - *buf_len = tmp1_outlen + tmp2_outlen; - free(inbuf); -// memcpy(&outdata[*buf_len], nss_iv_data, sizeof(nss_iv_data)); - - if (rv1 != SECSuccess || rv2 != SECSuccess) - goto out; - - /* Now do the digest */ - enc_context = PK11_CreateContextBySymKey(CKM_SHA_1_HMAC, - CKA_SIGN, instance->nss_sym_key_sign, &no_params); - if (!enc_context) { - char err[1024]; - PR_GetErrorText(err); - err[PR_GetErrorTextLength()] = 0; - log_printf(instance->totemudpu_log_level_security, "encrypt: PK11_CreateContext failed (digest) err %d: %s", - PR_GetError(), err); - return -1; - } - - - PK11_DigestBegin(enc_context); - - rv1 = PK11_DigestOp(enc_context, outdata - 16, *buf_len + 16); - rv2 = PK11_DigestFinal(enc_context, header->hash_digest, &tmp2_outlen, sizeof(header->hash_digest)); - - PK11_DestroyContext(enc_context, PR_TRUE); - - if (rv1 != SECSuccess || rv2 != SECSuccess) - goto out; - - - *buf_len = *buf_len + sizeof(struct security_header); - SECITEM_FreeItem(nss_sec_param, PR_TRUE); - return 0; - -out: - return -1; -} - - -static int authenticate_and_decrypt_nss ( - struct totemudpu_instance *instance, - struct iovec *iov, - unsigned int iov_len) -{ - PK11Context* enc_context = NULL; - SECStatus rv1, rv2; - int tmp1_outlen; - unsigned int tmp2_outlen; - unsigned char outbuf[FRAME_SIZE_MAX]; - unsigned char digest[HMAC_HASH_SIZE]; - unsigned char *outdata; - int result_len; - unsigned char *data; - unsigned char *inbuf; - size_t datalen; - struct security_header *header = (struct security_header *)iov[0].iov_base; - SECItem no_params; - SECItem ivdata; - - no_params.type = siBuffer; - no_params.data = 0; - no_params.len = 0; - - tmp1_outlen = tmp2_outlen = 0; - if (iov_len > 1) { - inbuf = copy_from_iovec(iov, iov_len, &datalen); - if (!inbuf) { - log_printf(instance->totemudpu_log_level_security, "malloc error copying buffer from iovec"); - return -1; - } - } - else { - inbuf = (unsigned char *)iov[0].iov_base; - datalen = iov[0].iov_len; - } - data = inbuf + sizeof (struct security_header) - 16; - datalen = datalen - sizeof (struct security_header) + 16; - - outdata = outbuf + sizeof (struct security_header); - - /* Check the digest */ - enc_context = PK11_CreateContextBySymKey ( - CKM_SHA_1_HMAC, CKA_SIGN, - instance->nss_sym_key_sign, - &no_params); - if (!enc_context) { - char err[1024]; - PR_GetErrorText(err); - err[PR_GetErrorTextLength()] = 0; - log_printf(instance->totemudpu_log_level_security, "PK11_CreateContext failed (check digest) err %d: %s", - PR_GetError(), err); - free (inbuf); - return -1; - } - - PK11_DigestBegin(enc_context); - - rv1 = PK11_DigestOp(enc_context, data, datalen); - rv2 = PK11_DigestFinal(enc_context, digest, &tmp2_outlen, sizeof(digest)); - - PK11_DestroyContext(enc_context, PR_TRUE); - - if (rv1 != SECSuccess || rv2 != SECSuccess) { - log_printf(instance->totemudpu_log_level_security, "Digest check failed"); - return -1; - } - - if (memcmp(digest, header->hash_digest, tmp2_outlen) != 0) { - log_printf(instance->totemudpu_log_level_error, "Digest does not match"); - return -1; - } - - /* - * Get rid of salt - */ - data += 16; - datalen -= 16; - - /* Create cipher context for decryption */ - ivdata.type = siBuffer; - ivdata.data = header->salt; - ivdata.len = sizeof(header->salt); - - enc_context = PK11_CreateContextBySymKey( - instance->totem_config->crypto_crypt_type, - CKA_DECRYPT, - instance->nss_sym_key, &ivdata); - if (!enc_context) { - log_printf(instance->totemudpu_log_level_security, - "PK11_CreateContext (decrypt) failed (err %d)", - PR_GetError()); - return -1; - } - - rv1 = PK11_CipherOp(enc_context, outdata, &tmp1_outlen, - sizeof(outbuf) - sizeof (struct security_header), - data, datalen); - if (rv1 != SECSuccess) { - log_printf(instance->totemudpu_log_level_security, - "PK11_CipherOp (decrypt) failed (err %d)", - PR_GetError()); - } - rv2 = PK11_DigestFinal(enc_context, outdata + tmp1_outlen, &tmp2_outlen, - sizeof(outbuf) - tmp1_outlen); - PK11_DestroyContext(enc_context, PR_TRUE); - result_len = tmp1_outlen + tmp2_outlen + sizeof (struct security_header); - - /* Copy it back to the buffer */ - copy_to_iovec(iov, iov_len, outbuf, result_len); - if (iov_len > 1) - free(inbuf); - - if (rv1 != SECSuccess || rv2 != SECSuccess) - return -1; - - return 0; -} - -static int encrypt_and_sign_worker ( - struct totemudpu_instance *instance, - unsigned char *buf, - size_t *buf_len, - const struct iovec *iovec, - unsigned int iov_len) -{ - - if (instance->totem_config->crypto_type == TOTEM_CRYPTO_AES256) { - return encrypt_and_sign_nss(instance, buf, buf_len, iovec, iov_len); - } - - return -1; -} - -static int authenticate_and_decrypt ( - struct totemudpu_instance *instance, - struct iovec *iov, - unsigned int iov_len) -{ - unsigned char type; - unsigned char *endbuf = (unsigned char *)iov[iov_len-1].iov_base; - int res = -1; - - /* - * Get the encryption type and remove it from the buffer - */ - type = endbuf[iov[iov_len-1].iov_len-1]; - iov[iov_len-1].iov_len -= 1; - - if (type == TOTEM_CRYPTO_AES256) { - res = authenticate_and_decrypt_nss(instance, iov, iov_len); - } - - return res; -} - -static void init_crypto( - struct totemudpu_instance *instance) -{ - - init_nss_crypto(instance); -} - int totemudpu_crypto_set ( void *udpu_context, unsigned int type) { - struct totemudpu_instance *instance = (struct totemudpu_instance *)udpu_context; - int res = 0; - - /* - * Validate crypto algorithm - */ - switch (type) { - case TOTEM_CRYPTO_AES256: - log_printf(instance->totemudpu_log_level_security, - "Transmit security set to: NSS AES256CBC/SHA1HMAC (mode %u)", type); - break; - default: - res = -1; - break; - } - return (res); + return (0); } @@ -676,7 +242,7 @@ static inline void ucast_sendmsg ( struct msghdr msg_ucast; int res = 0; size_t buf_len; - unsigned char sheader[sizeof (struct security_header)]; + unsigned char sheader[sizeof (struct crypto_security_header)]; unsigned char encrypt_data[FRAME_SIZE_MAX]; struct iovec iovec_encrypt[2]; const struct iovec *iovec_sendmsg; @@ -687,15 +253,15 @@ static inline void ucast_sendmsg ( if (instance->totem_config->secauth == 1) { iovec_encrypt[0].iov_base = (void *)sheader; - iovec_encrypt[0].iov_len = sizeof (struct security_header); + iovec_encrypt[0].iov_len = sizeof (struct crypto_security_header); iovec_encrypt[1].iov_base = (void *)msg; iovec_encrypt[1].iov_len = msg_len; /* * Encrypt and digest the message */ - encrypt_and_sign_worker ( - instance, + crypto_encrypt_and_sign ( + instance->crypto_inst, encrypt_data, &buf_len, iovec_encrypt, @@ -752,7 +318,7 @@ static inline void mcast_sendmsg ( struct msghdr msg_mcast; int res = 0; size_t buf_len; - unsigned char sheader[sizeof (struct security_header)]; + unsigned char sheader[sizeof (struct crypto_security_header)]; unsigned char encrypt_data[FRAME_SIZE_MAX]; struct iovec iovec_encrypt[2]; struct iovec iovec; @@ -765,15 +331,15 @@ static inline void mcast_sendmsg ( if (instance->totem_config->secauth == 1) { iovec_encrypt[0].iov_base = (void *)sheader; - iovec_encrypt[0].iov_len = sizeof (struct security_header); + iovec_encrypt[0].iov_len = sizeof (struct crypto_security_header); iovec_encrypt[1].iov_base = (void *)msg; iovec_encrypt[1].iov_len = msg_len; /* * Encrypt and digest the message */ - encrypt_and_sign_worker ( - instance, + crypto_encrypt_and_sign ( + instance->crypto_inst, encrypt_data, &buf_len, iovec_encrypt, @@ -886,7 +452,7 @@ static int net_deliver_fn ( } if ((instance->totem_config->secauth == 1) && - (bytes_received < sizeof (struct security_header))) { + (bytes_received < sizeof (struct crypto_security_header))) { log_printf (instance->totemudpu_log_level_security, "Received message is too short... ignoring %d.", bytes_received); return (0); @@ -898,7 +464,7 @@ static int net_deliver_fn ( * Authenticate and if authenticated, decrypt datagram */ - res = authenticate_and_decrypt (instance, iovec, 1); + res = crypto_authenticate_and_decrypt (instance->crypto_inst, iovec, 1); if (res == -1) { log_printf (instance->totemudpu_log_level_security, "Received message has invalid digest... ignoring."); log_printf (instance->totemudpu_log_level_security, @@ -907,8 +473,8 @@ static int net_deliver_fn ( return 0; } msg_offset = (unsigned char *)iovec->iov_base + - sizeof (struct security_header); - size_delv = bytes_received - sizeof (struct security_header); + sizeof (struct crypto_security_header); + size_delv = bytes_received - sizeof (struct crypto_security_header); } else { msg_offset = (void *)iovec->iov_base; size_delv = bytes_received; @@ -1218,12 +784,13 @@ int totemudpu_initialize ( /* * Initialize random number generator for later use to generate salt */ - memcpy (instance->totemudpu_private_key, totem_config->private_key, - totem_config->private_key_len); - - instance->totemudpu_private_key_len = totem_config->private_key_len; - - init_crypto(instance); + instance->crypto_inst = crypto_init (totem_config->private_key, + totem_config->private_key_len, + instance->totemudpu_log_printf, + instance->totemudpu_log_level_security, + instance->totemudpu_log_level_notice, + instance->totemudpu_log_level_error, + instance->totemudpu_subsys_id); /* * Initialize local variables for totemudpu @@ -1358,7 +925,7 @@ extern void totemudpu_net_mtu_adjust (void *udpu_context, struct totem_config *t { #define UDPIP_HEADER_SIZE (20 + 8) /* 20 bytes for ip 8 bytes for udp */ if (totem_config->secauth == 1) { - totem_config->net_mtu -= sizeof (struct security_header) + + totem_config->net_mtu -= sizeof (struct crypto_security_header) + UDPIP_HEADER_SIZE; } else { totem_config->net_mtu -= UDPIP_HEADER_SIZE; -- 2.39.5