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