ACK
On 3/13/2012 5:23 PM, Jan Friesse wrote:
> Signed-off-by: Jan Friesse <jfriesse@xxxxxxxxxx>
> ---
> exec/Makefile.am | 4 +-
> exec/crypto.c | 484 ----------------------------------------------------
> exec/crypto.h | 76 --------
> exec/totemcrypto.c | 484 ++++++++++++++++++++++++++++++++++++++++++++++++++++
> exec/totemcrypto.h | 76 ++++++++
> exec/totemudp.c | 2 +-
> exec/totemudpu.c | 2 +-
> 7 files changed, 564 insertions(+), 564 deletions(-)
> delete mode 100644 exec/crypto.c
> delete mode 100644 exec/crypto.h
> create mode 100644 exec/totemcrypto.c
> create mode 100644 exec/totemcrypto.h
>
> diff --git a/exec/Makefile.am b/exec/Makefile.am
> index 0db4db6..9075bcd 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 crypto.c
> + totempg.c cs_queue.h totemcrypto.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 crypto.h
> + sync.h fsm.h votequorum.h vsf_ykd.h totemcrypto.h
>
> if BUILD_DARWIN
> libtotem_pg.so.$(SONAME): $(TOTEM_OBJS)
> diff --git a/exec/crypto.c b/exec/crypto.c
> deleted file mode 100644
> index 2c6b9ef..0000000
> --- a/exec/crypto.c
> +++ /dev/null
> @@ -1,484 +0,0 @@
> -/*
> - * Copyright (c) 2006-2012 Red Hat, Inc.
> - *
> - * All rights reserved.
> - *
> - * Author: Steven Dake (sdake@xxxxxxxxxx)
> - * Christine Caulfield (ccaulfie@xxxxxxxxxx)
> - * Jan Friesse (jfriesse@xxxxxxxxxx)
> - *
> - * 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 <config.h>
> -
> -#include <assert.h>
> -#include <pthread.h>
> -#include <sys/mman.h>
> -#include <sys/types.h>
> -#include <sys/stat.h>
> -#include <sys/socket.h>
> -#include <netdb.h>
> -#include <sys/un.h>
> -#include <sys/ioctl.h>
> -#include <sys/param.h>
> -#include <netinet/in.h>
> -#include <arpa/inet.h>
> -#include <unistd.h>
> -#include <fcntl.h>
> -#include <stdlib.h>
> -#include <stdio.h>
> -#include <errno.h>
> -#include <sched.h>
> -#include <time.h>
> -#include <sys/time.h>
> -#include <sys/poll.h>
> -#include <limits.h>
> -
> -#include <corosync/sq.h>
> -#include <corosync/swab.h>
> -#include <corosync/list.h>
> -#include <qb/qbdefs.h>
> -#include <qb/qbloop.h>
> -#define LOGSYS_UTILS_ONLY 1
> -#include <corosync/logsys.h>
> -#include <corosync/totem/totem.h>
> -#include "crypto.h"
> -
> -#include "util.h"
> -
> -#include <nss.h>
> -#include <pk11pub.h>
> -#include <pkcs11.h>
> -#include <prerror.h>
> -
> -#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 {
> - PK11SymKey *nss_sym_key;
> - PK11SymKey *nss_sym_key_sign;
> -
> - unsigned char private_key[1024];
> -
> - unsigned int private_key_len;
> -
> - int crypto_crypt_type;
> -
> - int crypto_hash_type;
> -
> - 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 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;
> - }
> -
> - /*
> - * TODO: use instance info!
> - */
> - 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,
> - const unsigned char *buf_in,
> - const size_t buf_in_len,
> - unsigned char *buf_out,
> - size_t *buf_out_len)
> -{
> - PK11Context* enc_context = NULL;
> - SECStatus rv1, rv2;
> - int tmp1_outlen;
> - unsigned int tmp2_outlen;
> - unsigned char *outdata;
> - 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;
> -
> - outdata = buf_out + sizeof (struct crypto_security_header);
> - header = (struct crypto_security_header *)buf_out;
> -
> - 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());
> - 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);
> - return -1;
> - }
> - rv1 = PK11_CipherOp(enc_context, outdata,
> - &tmp1_outlen, FRAME_SIZE_MAX - sizeof(struct crypto_security_header),
> - (unsigned char *)buf_in, buf_in_len);
> - rv2 = PK11_DigestFinal(enc_context, outdata + tmp1_outlen, &tmp2_outlen,
> - FRAME_SIZE_MAX - tmp1_outlen);
> - PK11_DestroyContext(enc_context, PR_TRUE);
> -
> - *buf_out_len = tmp1_outlen + tmp2_outlen;
> -
> - 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_out_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_out_len = *buf_out_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,
> - unsigned char *buf,
> - int *buf_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 *)buf;
> - SECItem no_params;
> - SECItem ivdata;
> -
> - no_params.type = siBuffer;
> - no_params.data = 0;
> - no_params.len = 0;
> -
> - tmp1_outlen = tmp2_outlen = 0;
> - inbuf = (unsigned char *)buf;
> - datalen = *buf_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);
> - 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);
> -
> - memset(buf, 0, *buf_len);
> - memcpy(buf, outdata, result_len);
> -
> - *buf_len = result_len;
> -
> - if (rv1 != SECSuccess || rv2 != SECSuccess)
> - return -1;
> -
> - return 0;
> -}
> -
> -size_t crypto_sec_header_size(int crypt_hash_type)
> -{
> - /*
> - * TODO: add switch / size mapping
> - */
> - return sizeof(struct crypto_security_header);
> -}
> -
> -int crypto_encrypt_and_sign (
> - struct crypto_instance *instance,
> - const unsigned char *buf_in,
> - const size_t buf_in_len,
> - unsigned char *buf_out,
> - size_t *buf_out_len)
> -{
> - return (encrypt_and_sign_nss(instance, buf_in, buf_in_len, buf_out, buf_out_len));
> -}
> -
> -int crypto_authenticate_and_decrypt (struct crypto_instance *instance,
> - unsigned char *buf,
> - int *buf_len)
> -{
> - return (authenticate_and_decrypt_nss(instance, buf, buf_len));
> -}
> -
> -struct crypto_instance *crypto_init(
> - const unsigned char *private_key,
> - unsigned int private_key_len,
> - int crypto_crypt_type,
> - int crypto_hash_type,
> - 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->crypto_crypt_type = crypto_crypt_type;
> - instance->crypto_hash_type = crypto_hash_type;
> - 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
> deleted file mode 100644
> index 74c6434..0000000
> --- a/exec/crypto.h
> +++ /dev/null
> @@ -1,76 +0,0 @@
> -/*
> - * Copyright (c) 2006-2012 Red Hat, Inc.
> - *
> - * All rights reserved.
> - *
> - * Author: Steven Dake (sdake@xxxxxxxxxx)
> - * Christine Caulfield (ccaulfie@xxxxxxxxxx)
> - * Jan Friesse (jfriesse@xxxxxxxxxx)
> - *
> - * 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 <sys/types.h>
> -
> -struct crypto_instance;
> -
> -extern size_t crypto_sec_header_size(
> - int crypt_hash_type);
> -
> -extern int crypto_authenticate_and_decrypt (
> - struct crypto_instance *instance,
> - unsigned char *buf,
> - int *buf_len);
> -
> -extern int crypto_encrypt_and_sign (
> - struct crypto_instance *instance,
> - const unsigned char *buf_in,
> - const size_t buf_in_len,
> - unsigned char *buf_out,
> - size_t *buf_out_len);
> -
> -extern struct crypto_instance *crypto_init(
> - const unsigned char *private_key,
> - unsigned int private_key_len,
> - int crypto_crypt_type,
> - int crypto_hash_type,
> - 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/totemcrypto.c b/exec/totemcrypto.c
> new file mode 100644
> index 0000000..4ee839e
> --- /dev/null
> +++ b/exec/totemcrypto.c
> @@ -0,0 +1,484 @@
> +/*
> + * Copyright (c) 2006-2012 Red Hat, Inc.
> + *
> + * All rights reserved.
> + *
> + * Author: Steven Dake (sdake@xxxxxxxxxx)
> + * Christine Caulfield (ccaulfie@xxxxxxxxxx)
> + * Jan Friesse (jfriesse@xxxxxxxxxx)
> + *
> + * 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 <config.h>
> +
> +#include <assert.h>
> +#include <pthread.h>
> +#include <sys/mman.h>
> +#include <sys/types.h>
> +#include <sys/stat.h>
> +#include <sys/socket.h>
> +#include <netdb.h>
> +#include <sys/un.h>
> +#include <sys/ioctl.h>
> +#include <sys/param.h>
> +#include <netinet/in.h>
> +#include <arpa/inet.h>
> +#include <unistd.h>
> +#include <fcntl.h>
> +#include <stdlib.h>
> +#include <stdio.h>
> +#include <errno.h>
> +#include <sched.h>
> +#include <time.h>
> +#include <sys/time.h>
> +#include <sys/poll.h>
> +#include <limits.h>
> +
> +#include <corosync/sq.h>
> +#include <corosync/swab.h>
> +#include <corosync/list.h>
> +#include <qb/qbdefs.h>
> +#include <qb/qbloop.h>
> +#define LOGSYS_UTILS_ONLY 1
> +#include <corosync/logsys.h>
> +#include <corosync/totem/totem.h>
> +#include "totemcrypto.h"
> +
> +#include "util.h"
> +
> +#include <nss.h>
> +#include <pk11pub.h>
> +#include <pkcs11.h>
> +#include <prerror.h>
> +
> +#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 {
> + PK11SymKey *nss_sym_key;
> + PK11SymKey *nss_sym_key_sign;
> +
> + unsigned char private_key[1024];
> +
> + unsigned int private_key_len;
> +
> + int crypto_crypt_type;
> +
> + int crypto_hash_type;
> +
> + 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 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;
> + }
> +
> + /*
> + * TODO: use instance info!
> + */
> + 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,
> + const unsigned char *buf_in,
> + const size_t buf_in_len,
> + unsigned char *buf_out,
> + size_t *buf_out_len)
> +{
> + PK11Context* enc_context = NULL;
> + SECStatus rv1, rv2;
> + int tmp1_outlen;
> + unsigned int tmp2_outlen;
> + unsigned char *outdata;
> + 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;
> +
> + outdata = buf_out + sizeof (struct crypto_security_header);
> + header = (struct crypto_security_header *)buf_out;
> +
> + 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());
> + 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);
> + return -1;
> + }
> + rv1 = PK11_CipherOp(enc_context, outdata,
> + &tmp1_outlen, FRAME_SIZE_MAX - sizeof(struct crypto_security_header),
> + (unsigned char *)buf_in, buf_in_len);
> + rv2 = PK11_DigestFinal(enc_context, outdata + tmp1_outlen, &tmp2_outlen,
> + FRAME_SIZE_MAX - tmp1_outlen);
> + PK11_DestroyContext(enc_context, PR_TRUE);
> +
> + *buf_out_len = tmp1_outlen + tmp2_outlen;
> +
> + 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_out_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_out_len = *buf_out_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,
> + unsigned char *buf,
> + int *buf_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 *)buf;
> + SECItem no_params;
> + SECItem ivdata;
> +
> + no_params.type = siBuffer;
> + no_params.data = 0;
> + no_params.len = 0;
> +
> + tmp1_outlen = tmp2_outlen = 0;
> + inbuf = (unsigned char *)buf;
> + datalen = *buf_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);
> + 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);
> +
> + memset(buf, 0, *buf_len);
> + memcpy(buf, outdata, result_len);
> +
> + *buf_len = result_len;
> +
> + if (rv1 != SECSuccess || rv2 != SECSuccess)
> + return -1;
> +
> + return 0;
> +}
> +
> +size_t crypto_sec_header_size(int crypt_hash_type)
> +{
> + /*
> + * TODO: add switch / size mapping
> + */
> + return sizeof(struct crypto_security_header);
> +}
> +
> +int crypto_encrypt_and_sign (
> + struct crypto_instance *instance,
> + const unsigned char *buf_in,
> + const size_t buf_in_len,
> + unsigned char *buf_out,
> + size_t *buf_out_len)
> +{
> + return (encrypt_and_sign_nss(instance, buf_in, buf_in_len, buf_out, buf_out_len));
> +}
> +
> +int crypto_authenticate_and_decrypt (struct crypto_instance *instance,
> + unsigned char *buf,
> + int *buf_len)
> +{
> + return (authenticate_and_decrypt_nss(instance, buf, buf_len));
> +}
> +
> +struct crypto_instance *crypto_init(
> + const unsigned char *private_key,
> + unsigned int private_key_len,
> + int crypto_crypt_type,
> + int crypto_hash_type,
> + 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->crypto_crypt_type = crypto_crypt_type;
> + instance->crypto_hash_type = crypto_hash_type;
> + 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/totemcrypto.h b/exec/totemcrypto.h
> new file mode 100644
> index 0000000..0758f10
> --- /dev/null
> +++ b/exec/totemcrypto.h
> @@ -0,0 +1,76 @@
> +/*
> + * Copyright (c) 2006-2012 Red Hat, Inc.
> + *
> + * All rights reserved.
> + *
> + * Author: Steven Dake (sdake@xxxxxxxxxx)
> + * Christine Caulfield (ccaulfie@xxxxxxxxxx)
> + * Jan Friesse (jfriesse@xxxxxxxxxx)
> + *
> + * 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 TOTEMCRYPTO_H_DEFINED
> +#define TOTEMCRYPTO_H_DEFINED
> +
> +#include <sys/types.h>
> +
> +struct crypto_instance;
> +
> +extern size_t crypto_sec_header_size(
> + int crypt_hash_type);
> +
> +extern int crypto_authenticate_and_decrypt (
> + struct crypto_instance *instance,
> + unsigned char *buf,
> + int *buf_len);
> +
> +extern int crypto_encrypt_and_sign (
> + struct crypto_instance *instance,
> + const unsigned char *buf_in,
> + const size_t buf_in_len,
> + unsigned char *buf_out,
> + size_t *buf_out_len);
> +
> +extern struct crypto_instance *crypto_init(
> + const unsigned char *private_key,
> + unsigned int private_key_len,
> + int crypto_crypt_type,
> + int crypto_hash_type,
> + 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 /* TOTEMCRYPTO_H_DEFINED */
> diff --git a/exec/totemudp.c b/exec/totemudp.c
> index b49110b..b6f8126 100644
> --- a/exec/totemudp.c
> +++ b/exec/totemudp.c
> @@ -68,7 +68,7 @@
> #include "totemudp.h"
>
> #include "util.h"
> -#include "crypto.h"
> +#include "totemcrypto.h"
>
> #include <nss.h>
> #include <pk11pub.h>
> diff --git a/exec/totemudpu.c b/exec/totemudpu.c
> index ab1a059..d4530ce 100644
> --- a/exec/totemudpu.c
> +++ b/exec/totemudpu.c
> @@ -68,7 +68,7 @@
> #include "totemudpu.h"
>
> #include "util.h"
> -#include "crypto.h"
> +#include "totemcrypto.h"
>
> #include <nss.h>
> #include <pk11pub.h>
_______________________________________________
discuss mailing list
discuss@xxxxxxxxxxxx
http://lists.corosync.org/mailman/listinfo/discuss
[Corosync Project]
[Linux USB Devel]
[Video for Linux]
[Linux Audio Users]
[Photo]
[Yosemite News]
[Yosemite Photos]
[Free Online Dating]
[Linux Kernel]
[Linux SCSI]
[XFree86]