[PATCH] totemcrypto: major code cleanup (no functional or onwire changes)

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: "Fabio M. Di Nitto" <fdinitto@xxxxxxxxxx>

- cleanup include list
- reorder code and functions (crypto then hash)
- split crypt/decrypt/hash functions
- some micro optimizations by dropping a few memcpy
- make the code more readable (better var names and buffers mapping)
- improve exit paths on error (return codes and free)
- store crypto header size instead of recalculating it per packet

Signed-off-by: Fabio M. Di Nitto <fdinitto@xxxxxxxxxx>
---
 exec/totemcrypto.c |  632 +++++++++++++++++++++++++---------------------------
 1 files changed, 304 insertions(+), 328 deletions(-)

diff --git a/exec/totemcrypto.c b/exec/totemcrypto.c
index 8b21533..49ed00e 100644
--- a/exec/totemcrypto.c
+++ b/exec/totemcrypto.c
@@ -6,6 +6,7 @@
  * Author: Steven Dake (sdake@xxxxxxxxxx)
  *         Christine Caulfield (ccaulfie@xxxxxxxxxx)
  *         Jan Friesse (jfriesse@xxxxxxxxxx)
+ *         Fabio M. Di Nitto (fdinitto@xxxxxxxxxx)
  *
  * This software licensed under BSD license, the text of which follows:
  *
@@ -34,42 +35,7 @@
  * 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 "config.h"
 
 #include <nss.h>
 #include <pk11pub.h>
@@ -78,7 +44,14 @@
 #include <blapit.h>
 #include <hasht.h>
 
-#define SALT_SIZE 16
+#define LOGSYS_UTILS_ONLY 1
+#include <corosync/logsys.h>
+#include <corosync/totem/totem.h>
+#include "totemcrypto.h"
+
+/*
+ * define onwire crypto header
+ */
 
 struct crypto_config_header {
 	uint8_t	crypto_cipher_type;
@@ -87,6 +60,12 @@ struct crypto_config_header {
 	uint8_t __pad1;
 } __attribute__((packed));
 
+/*
+ * crypto definitions and conversion tables
+ */
+
+#define SALT_SIZE 16
+
 enum crypto_crypt_t {
 	CRYPTO_CIPHER_TYPE_NONE = 0,
 	CRYPTO_CIPHER_TYPE_AES256 = 1
@@ -107,6 +86,10 @@ size_t cypher_block_len[] = {
 	AES_BLOCK_SIZE			/* CRYPTO_CIPHER_TYPE_AES256 */
 };
 
+/*
+ * hash definitions and conversion tables
+ */
+
 enum crypto_hash_t {
 	CRYPTO_HASH_TYPE_NONE	= 0,
 	CRYPTO_HASH_TYPE_MD5	= 1,
@@ -155,6 +138,8 @@ struct crypto_instance {
 
 	enum crypto_hash_t crypto_hash_type;
 
+	unsigned int crypto_header_size;
+
 	void (*log_printf_func) (
 		int level,
 		int subsys,
@@ -178,117 +163,73 @@ do {									\
 		(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 int init_nss_crypto(struct crypto_instance *instance,
-			   const char *crypto_cipher_type,
-			   const char *crypto_hash_type)
+/*
+ * crypt/decrypt functions
+ */
+
+static int string_to_crypto_cipher_type(const char* crypto_cipher_type)
+{
+	if (strcmp(crypto_cipher_type, "none") == 0) {
+		return CRYPTO_CIPHER_TYPE_NONE;
+	} else if (strcmp(crypto_cipher_type, "aes256") == 0) {
+		return CRYPTO_CIPHER_TYPE_AES256;
+	}
+	return CRYPTO_CIPHER_TYPE_AES256;
+}
+
+static int init_nss_crypto(struct crypto_instance *instance)
 {
 	PK11SlotInfo*	crypt_slot = NULL;
-	PK11SlotInfo*	hash_slot = NULL;
 	SECItem		crypt_param;
-	SECItem		hash_param;
 
-	if ((!cipher_to_nss[instance->crypto_cipher_type]) &&
-	    (!hash_to_nss[instance->crypto_hash_type])) {
-		log_printf(instance->log_level_notice,
-			   "Initializing transmit/receive security: NONE");
+	if (!cipher_to_nss[instance->crypto_cipher_type]) {
 		return 0;
 	}
 
-	log_printf(instance->log_level_notice,
-		   "Initializing transmit/receive security: NSS crypto: %s hash: %s",
-		   crypto_cipher_type, crypto_hash_type);
+	crypt_param.type = siBuffer;
+	crypt_param.data = instance->private_key;
+	crypt_param.len = cipher_key_len[instance->crypto_cipher_type];
 
-	if (NSS_NoDB_Init(".") != SECSuccess) {
-		log_printf(instance->log_level_security, "NSS initialization failed (err %d)",
+	crypt_slot = PK11_GetBestSlot(cipher_to_nss[instance->crypto_cipher_type], NULL);
+	if (crypt_slot == NULL) {
+		log_printf(instance->log_level_security, "Unable to find security slot (err %d)",
 			   PR_GetError());
-		goto out;
-	}
-
-	if (cipher_to_nss[instance->crypto_cipher_type]) {
-		crypt_param.type = siBuffer;
-		crypt_param.data = instance->private_key;
-		crypt_param.len = cipher_key_len[instance->crypto_cipher_type];
-
-		crypt_slot = PK11_GetBestSlot(cipher_to_nss[instance->crypto_cipher_type], NULL);
-		if (crypt_slot == NULL) {
-			log_printf(instance->log_level_security, "Unable to find security slot (err %d)",
-				   PR_GetError());
-			goto out;
-		}
-		instance->nss_sym_key = PK11_ImportSymKey(crypt_slot,
-							  cipher_to_nss[instance->crypto_cipher_type],
-							  PK11_OriginUnwrap, CKA_ENCRYPT|CKA_DECRYPT,
-							  &crypt_param, 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;
-		}
+		return -1;
 	}
 
-	if (hash_to_nss[instance->crypto_hash_type]) {
-		hash_param.type = siBuffer;
-		hash_param.data = 0;
-		hash_param.len = 0;
-
-		hash_slot = PK11_GetBestSlot(hash_to_nss[instance->crypto_hash_type], NULL);
-		if (hash_slot == NULL) {
-			log_printf(instance->log_level_security, "Unable to find security slot (err %d)",
-				   PR_GetError());
-			goto out;
-		}
-
-		instance->nss_sym_key_sign = PK11_ImportSymKey(hash_slot,
-							       hash_to_nss[instance->crypto_hash_type],
-							       PK11_OriginUnwrap, CKA_SIGN,
-							       &hash_param, 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;
-		}
+	instance->nss_sym_key = PK11_ImportSymKey(crypt_slot,
+						  cipher_to_nss[instance->crypto_cipher_type],
+						  PK11_OriginUnwrap, CKA_ENCRYPT|CKA_DECRYPT,
+						  &crypt_param, NULL);
+	if (instance->nss_sym_key == NULL) {
+		log_printf(instance->log_level_security, "Failure to import key into NSS (err %d)",
+			   PR_GetError());
+		return -1;
 	}
 
 	return 0;
-out:
-	return -1;
 }
 
-static int encrypt_and_sign_nss (
+static int encrypt_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;
+	PK11Context*	crypt_context = NULL;
 	SECItem		crypt_param;
-	SECItem		hash_param;
 	SECItem		*nss_sec_param = NULL;
-
-	unsigned char	*outdata;
 	int		tmp1_outlen = 0;
 	unsigned int	tmp2_outlen = 0;
-
-	unsigned char	salt[SALT_SIZE];
-	unsigned char	hash_block[hash_block_len[instance->crypto_hash_type]];
-
-	outdata = buf_out + hash_len[instance->crypto_hash_type];
+	unsigned char	*salt = buf_out;
+	unsigned char	*data = buf_out + SALT_SIZE;
+	int		err = -1;
 
 	if (!cipher_to_nss[instance->crypto_cipher_type]) {
-		memcpy(outdata, buf_in, buf_in_len);
+		memcpy(buf_out, buf_in, buf_in_len);
 		*buf_out_len = buf_in_len;
-		goto only_hash;
+		return 0;
 	}
 
 	if (PK11_GenerateRandom (salt, SALT_SIZE) != SECSuccess) {
@@ -297,7 +238,6 @@ static int encrypt_and_sign_nss (
 			PR_GetError());
 		goto out;
 	}
-	memcpy(outdata, salt, SALT_SIZE);
 
 	crypt_param.type = siBuffer;
 	crypt_param.data = salt;
@@ -315,11 +255,11 @@ static int encrypt_and_sign_nss (
 	/*
 	 * Create cipher context for encryption
 	 */
-	enc_context = PK11_CreateContextBySymKey (cipher_to_nss[instance->crypto_cipher_type],
-						  CKA_ENCRYPT,
-						  instance->nss_sym_key,
-						  nss_sec_param);
-	if (!enc_context) {
+	crypt_context = PK11_CreateContextBySymKey (cipher_to_nss[instance->crypto_cipher_type],
+						    CKA_ENCRYPT,
+						    instance->nss_sym_key,
+						    nss_sec_param);
+	if (!crypt_context) {
 		log_printf(instance->log_level_security,
 			   "PK11_CreateContext failed (encrypt) crypt_type=%d (err %d)",
 			   (int)cipher_to_nss[instance->crypto_cipher_type],
@@ -327,9 +267,9 @@ static int encrypt_and_sign_nss (
 		goto out;
 	}
 
-	if (PK11_CipherOp(enc_context, outdata + SALT_SIZE,
+	if (PK11_CipherOp(crypt_context, data,
 			  &tmp1_outlen,
-			  FRAME_SIZE_MAX - (sizeof(struct crypto_config_header) + hash_len[instance->crypto_hash_type] + SALT_SIZE),
+			  FRAME_SIZE_MAX - instance->crypto_header_size,
 			  (unsigned char *)buf_in, buf_in_len) != SECSuccess) {
 		log_printf(instance->log_level_security,
 			   "PK11_CipherOp failed (encrypt) crypt_type=%d (err %d)",
@@ -337,7 +277,8 @@ static int encrypt_and_sign_nss (
 			   PR_GetError());
 		goto out;
 	}
-	if (PK11_DigestFinal(enc_context, outdata + SALT_SIZE + tmp1_outlen,
+
+	if (PK11_DigestFinal(crypt_context, data + tmp1_outlen,
 			     &tmp2_outlen, FRAME_SIZE_MAX - tmp1_outlen) != SECSuccess) {
 		log_printf(instance->log_level_security,
 			   "PK11_DigestFinal failed (encrypt) crypt_type=%d (err %d)",
@@ -347,260 +288,317 @@ static int encrypt_and_sign_nss (
 
 	}
 
-	if (enc_context) {
-		PK11_DestroyContext(enc_context, PR_TRUE);
-		enc_context = 0;
-	}
-
 	*buf_out_len = tmp1_outlen + tmp2_outlen + SALT_SIZE;
 
-only_hash:
+	err = 0;
 
-	if (!hash_to_nss[instance->crypto_hash_type]) {
-		goto no_hash;
+out:
+	if (crypt_context) {
+		PK11_DestroyContext(crypt_context, PR_TRUE);
 	}
+	if (nss_sec_param) {
+		SECITEM_FreeItem(nss_sec_param, PR_TRUE);
+	}
+	return err;
+}
 
-	/* Now do the digest */
-	hash_param.type = siBuffer;
-	hash_param.data = 0;
-	hash_param.len = 0;
+static int decrypt_nss (
+	struct crypto_instance *instance,
+	unsigned char *buf,
+	int *buf_len)
+{
+	PK11Context*	decrypt_context = NULL;
+	SECItem		decrypt_param;
+	int		tmp1_outlen = 0;
+	unsigned int	tmp2_outlen = 0;
+	unsigned char	*salt = buf;
+	unsigned char	*data = salt + SALT_SIZE;
+	int		datalen = *buf_len - SALT_SIZE;
+	unsigned char	outbuf[FRAME_SIZE_MAX];
+	int		outbuf_len;
+	int		err = -1;
 
-	enc_context = PK11_CreateContextBySymKey(hash_to_nss[instance->crypto_hash_type],
-						 CKA_SIGN,
-						 instance->nss_sym_key_sign,
-						 &hash_param);
-	if (!enc_context) {
-		log_printf(instance->log_level_security,
-			   "PK11_CreateContext failed (hash) hash_type=%d (err %d)",
-			   (int)hash_to_nss[instance->crypto_hash_type],
-			   PR_GetError());
-		goto out;
+	if (!cipher_to_nss[instance->crypto_cipher_type]) {
+		return 0;
 	}
 
-	if (PK11_DigestBegin(enc_context) != SECSuccess) {
+	/* Create cipher context for decryption */
+	decrypt_param.type = siBuffer;
+	decrypt_param.data = salt;
+	decrypt_param.len = SALT_SIZE;
+
+	decrypt_context = PK11_CreateContextBySymKey(cipher_to_nss[instance->crypto_cipher_type],
+						     CKA_DECRYPT,
+						     instance->nss_sym_key, &decrypt_param);
+	if (!decrypt_context) {
 		log_printf(instance->log_level_security,
-			   "PK11_DigestBegin failed (hash) hash_type=%d (err %d)",
-			   (int)hash_to_nss[instance->crypto_hash_type],
+			   "PK11_CreateContext (decrypt) failed (err %d)",
 			   PR_GetError());
 		goto out;
 	}
 
-	if (PK11_DigestOp(enc_context,
-			  outdata,
-			  *buf_out_len) != SECSuccess) {
+	if (PK11_CipherOp(decrypt_context, outbuf, &tmp1_outlen,
+			  sizeof(outbuf), data, datalen) != SECSuccess) {
 		log_printf(instance->log_level_security,
-			   "PK11_DigestOp failed (hash) hash_type=%d (err %d)",
-			   (int)hash_to_nss[instance->crypto_hash_type],
+			   "PK11_CipherOp (decrypt) failed (err %d)",
 			   PR_GetError());
 		goto out;
 	}
-	if (PK11_DigestFinal(enc_context,
-			     hash_block,
-			     &tmp2_outlen,
-			     hash_block_len[instance->crypto_hash_type]) != SECSuccess) {
+
+	if (PK11_DigestFinal(decrypt_context, outbuf + tmp1_outlen, &tmp2_outlen,
+			     sizeof(outbuf) - tmp1_outlen) != SECSuccess) {
 		log_printf(instance->log_level_security,
-			   "PK11_DigestFinale failed (hash) hash_type=%d (err %d)",
-			   (int)hash_to_nss[instance->crypto_hash_type],
-			   PR_GetError());
+			   "PK11_DigestFinal (decrypt) failed (err %d)",
+			   PR_GetError()); 
 		goto out;
 	}
 
-	if (enc_context) {
-		PK11_DestroyContext(enc_context, PR_TRUE);
-		enc_context = 0;
-	}
-
-	memcpy(buf_out, hash_block, hash_len[instance->crypto_hash_type]);
+	outbuf_len = tmp1_outlen + tmp2_outlen;
 
-	*buf_out_len = *buf_out_len + hash_len[instance->crypto_hash_type];
+	memset(buf, 0, *buf_len);
+	memcpy(buf, outbuf, outbuf_len);
 
-no_hash:
+	*buf_len = outbuf_len;
 
-	SECITEM_FreeItem(nss_sec_param, PR_TRUE);
-
-	return 0;
+	err = 0;
 
 out:
-	if (enc_context) {
-		PK11_DestroyContext(enc_context, PR_TRUE);
+	if (decrypt_context) {
+		PK11_DestroyContext(decrypt_context, PR_TRUE);
 	}
-	if (nss_sec_param) {
-		SECITEM_FreeItem(nss_sec_param, PR_TRUE);
+
+	return err;
+}
+
+
+/*
+ * hash/hmac/digest functions
+ */
+
+static int string_to_crypto_hash_type(const char* crypto_hash_type)
+{
+	if (strcmp(crypto_hash_type, "none") == 0) {
+		return CRYPTO_HASH_TYPE_NONE;
+	} else if (strcmp(crypto_hash_type, "md5") == 0) {
+		return CRYPTO_HASH_TYPE_MD5;
+	} else if (strcmp(crypto_hash_type, "sha1") == 0) {
+		return CRYPTO_HASH_TYPE_SHA1;
+	} else if (strcmp(crypto_hash_type, "sha256") == 0) {
+		return CRYPTO_HASH_TYPE_SHA256;
+	} else if (strcmp(crypto_hash_type, "sha384") == 0) {
+		return CRYPTO_HASH_TYPE_SHA384;
+	} else if (strcmp(crypto_hash_type, "sha512") == 0) {
+		return CRYPTO_HASH_TYPE_SHA512;
 	}
-	return -1;
+
+	return CRYPTO_HASH_TYPE_SHA1;
 }
 
-static int authenticate_and_decrypt_nss (
-	struct crypto_instance *instance,
-	unsigned char *buf,
-	int *buf_len)
+static int init_nss_hash(struct crypto_instance *instance)
 {
-	PK11Context*	enc_context = NULL;
-	SECItem		crypt_param;
+	PK11SlotInfo*	hash_slot = NULL;
 	SECItem		hash_param;
-	unsigned char	hash_block[hash_block_len[instance->crypto_hash_type]];
 
-	int		tmp1_outlen = 0;
-	unsigned int	tmp2_outlen = 0;
+	if (!hash_to_nss[instance->crypto_hash_type]) {
+		return 0;
+	}
 
-	unsigned char	*data;
-	size_t		datalen;
+	hash_param.type = siBuffer;
+	hash_param.data = 0;
+	hash_param.len = 0;
 
-	unsigned char	outbuf[FRAME_SIZE_MAX];
+	hash_slot = PK11_GetBestSlot(hash_to_nss[instance->crypto_hash_type], NULL);
+	if (hash_slot == NULL) {
+		log_printf(instance->log_level_security, "Unable to find security slot (err %d)",
+			   PR_GetError());
+		return -1;
+	}
 
-	int		result_len;
+	instance->nss_sym_key_sign = PK11_ImportSymKey(hash_slot,
+						       hash_to_nss[instance->crypto_hash_type],
+						       PK11_OriginUnwrap, CKA_SIGN,
+						       &hash_param, NULL);
+	if (instance->nss_sym_key_sign == NULL) {
+		log_printf(instance->log_level_security, "Failure to import key into NSS (err %d)",
+			   PR_GetError());
+		return -1;
+	}
 
-	data = buf + hash_len[instance->crypto_hash_type];
-	datalen = *buf_len - hash_len[instance->crypto_hash_type];
+	return 0;
+}
 
-	if (!hash_to_nss[instance->crypto_hash_type]) {
-		goto only_decrypt;
-	}
+static int calculate_nss_hash(
+	struct crypto_instance *instance,
+	const unsigned char *buf,
+	const size_t buf_len,
+	unsigned char *hash)
+{
+	PK11Context*	hash_context = NULL;
+	SECItem		hash_param;
+	unsigned int	hash_tmp_outlen = 0;
+	unsigned char	hash_block[hash_block_len[instance->crypto_hash_type]];
+	int		err = -1;
 
+	/* Now do the digest */
 	hash_param.type = siBuffer;
 	hash_param.data = 0;
 	hash_param.len = 0;
 
-	/* Check the digest */
-	enc_context = PK11_CreateContextBySymKey (hash_to_nss[instance->crypto_hash_type],
-						  CKA_SIGN,
-						  instance->nss_sym_key_sign,
-						  &hash_param);
-	if (!enc_context) {
+	hash_context = PK11_CreateContextBySymKey(hash_to_nss[instance->crypto_hash_type],
+						 CKA_SIGN,
+						 instance->nss_sym_key_sign,
+						 &hash_param);
+
+	if (!hash_context) {
 		log_printf(instance->log_level_security,
-			   "PK11_CreateContext failed (check digest) err %d",
+			   "PK11_CreateContext failed (hash) hash_type=%d (err %d)",
+			   (int)hash_to_nss[instance->crypto_hash_type],
 			   PR_GetError());
 		goto out;
 	}
 
-	if (PK11_DigestBegin(enc_context) != SECSuccess) {
+	if (PK11_DigestBegin(hash_context) != SECSuccess) {
 		log_printf(instance->log_level_security,
-			  "PK11_DigestBegin failed (check digest) err %d",
-			  PR_GetError());
+			   "PK11_DigestBegin failed (hash) hash_type=%d (err %d)",
+			   (int)hash_to_nss[instance->crypto_hash_type],
+			   PR_GetError());
 		goto out;
 	}
 
-	if (PK11_DigestOp(enc_context, data, datalen) != SECSuccess) {
+	if (PK11_DigestOp(hash_context,
+			  buf,
+			  buf_len) != SECSuccess) {
 		log_printf(instance->log_level_security,
-			   "PK11_DigestOp failed (check digest) err %d",
+			   "PK11_DigestOp failed (hash) hash_type=%d (err %d)",
+			   (int)hash_to_nss[instance->crypto_hash_type],
 			   PR_GetError());
 		goto out;
 	}
 
-	if (PK11_DigestFinal(enc_context, hash_block,
-			     &tmp2_outlen, hash_block_len[instance->crypto_hash_type]) != SECSuccess) {
+	if (PK11_DigestFinal(hash_context,
+			     hash_block,
+			     &hash_tmp_outlen,
+			     hash_block_len[instance->crypto_hash_type]) != SECSuccess) {
 		log_printf(instance->log_level_security,
-			   "PK11_DigestFinal failed (check digest) err %d",
+			   "PK11_DigestFinale failed (hash) hash_type=%d (err %d)",
+			   (int)hash_to_nss[instance->crypto_hash_type],
 			   PR_GetError());
 		goto out;
 	}
 
-	if (enc_context) {
-		PK11_DestroyContext(enc_context, PR_TRUE);
-		enc_context = 0;
-	}
+	memcpy(hash, hash_block, hash_len[instance->crypto_hash_type]);
+	err = 0;
 
-	if (memcmp(hash_block, buf, tmp2_outlen) != 0) {
-		log_printf(instance->log_level_error, "Digest does not match");
-		goto out;
+out:
+	if (hash_context) {
+		PK11_DestroyContext(hash_context, PR_TRUE);
 	}
 
-only_decrypt:
-
-	if (!cipher_to_nss[instance->crypto_cipher_type]) {
-		memcpy(outbuf, data, datalen);
-		result_len = datalen;
-		goto no_decrypt;
-	}
+	return err;
+}
 
-	/* Create cipher context for decryption */
-	crypt_param.type = siBuffer;
-	crypt_param.data = data;
-	crypt_param.len = SALT_SIZE;
+/*
+ * global/glue nss functions
+ */
 
-	/*
-	 * Get rid of salt
-	 */
-	data += SALT_SIZE;
-	datalen -= SALT_SIZE;
+static int init_nss_db(struct crypto_instance *instance)
+{
+	if ((!cipher_to_nss[instance->crypto_cipher_type]) &&
+	    (!hash_to_nss[instance->crypto_hash_type])) {
+		return 0;
+	}
 
-	enc_context = PK11_CreateContextBySymKey(cipher_to_nss[instance->crypto_cipher_type],
-						 CKA_DECRYPT,
-						 instance->nss_sym_key, &crypt_param);
-	if (!enc_context) {
-		log_printf(instance->log_level_security,
-			   "PK11_CreateContext (decrypt) failed (err %d)",
+	if (NSS_NoDB_Init(".") != SECSuccess) {
+		log_printf(instance->log_level_security, "NSS DB initialization failed (err %d)",
 			   PR_GetError());
-		goto out;
+		return -1;
 	}
 
-	if (PK11_CipherOp(enc_context, outbuf, &tmp1_outlen,
-			  sizeof(outbuf), data, datalen) != SECSuccess) {
-		log_printf(instance->log_level_security,
-			   "PK11_CipherOp (decrypt) failed (err %d)",
-			   PR_GetError());
-		goto out;
+	return 0;
+}
+
+static int init_nss(struct crypto_instance *instance,
+		    const char *crypto_cipher_type,
+		    const char *crypto_hash_type)
+{
+	log_printf(instance->log_level_notice,
+		   "Initializing transmit/receive security (NSS) crypto: %s hash: %s",
+		   crypto_cipher_type, crypto_hash_type);
+
+	if (init_nss_db(instance) < 0) {
+		return -1;
 	}
-	if (PK11_DigestFinal(enc_context, outbuf + tmp1_outlen, &tmp2_outlen,
-			     sizeof(outbuf) - tmp1_outlen) != SECSuccess) {
-		log_printf(instance->log_level_security,
-			   "PK11_DigestFinal (decrypt) failed (err %d)",
-			   PR_GetError()); 
-		goto out;
+
+	if (init_nss_crypto(instance) < 0) {
+		return -1;
 	}
 
-	if (enc_context) {
-		PK11_DestroyContext(enc_context, PR_TRUE);
-		enc_context = 0;
+	if (init_nss_hash(instance) < 0) {
+		return -1;
 	}
 
-	result_len = tmp1_outlen + tmp2_outlen;
+	return 0;
+}
 
-no_decrypt:
+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)
+{
+	unsigned char	*hash = buf_out;
+	unsigned char	*data = hash + hash_len[instance->crypto_hash_type];
 
-	memset(buf, 0, *buf_len);
-	memcpy(buf, outbuf, result_len);
+	if (encrypt_nss(instance, buf_in, buf_in_len, data, buf_out_len) < 0) {
+		return -1;
+	}
 
-	*buf_len = result_len;
+	if (hash_to_nss[instance->crypto_hash_type]) {
+		if (calculate_nss_hash(instance, data, *buf_out_len, hash) < 0) {
+			return -1;
+		}
+		*buf_out_len = *buf_out_len + hash_len[instance->crypto_hash_type];
+	}
 
 	return 0;
-
-out:
-	if (enc_context) {
-		PK11_DestroyContext(enc_context, PR_TRUE);
-	}
-	return -1;
 }
 
-static int string_to_crypto_cipher_type(const char* crypto_cipher_type)
+static int authenticate_and_decrypt_nss (
+	struct crypto_instance *instance,
+	unsigned char *buf,
+	int *buf_len)
 {
-	if (strcmp(crypto_cipher_type, "none") == 0) {
-		return CRYPTO_CIPHER_TYPE_NONE;
-	} else if (strcmp(crypto_cipher_type, "aes256") == 0) {
-		return CRYPTO_CIPHER_TYPE_AES256;
+	if (hash_to_nss[instance->crypto_hash_type]) {
+		unsigned char	tmp_hash[hash_len[instance->crypto_hash_type]];
+		unsigned char	*hash = buf;
+		unsigned char	*data = hash + hash_len[instance->crypto_hash_type];
+		int		datalen = *buf_len - hash_len[instance->crypto_hash_type];
+
+		if (calculate_nss_hash(instance, data, datalen, tmp_hash) < 0) {
+			return -1;
+		}
+
+		if (memcmp(tmp_hash, hash, hash_len[instance->crypto_hash_type]) != 0) {
+			log_printf(instance->log_level_error, "Digest does not match");
+			return -1;
+		}
+
+		memmove(buf, data, datalen);
+		*buf_len = datalen;
 	}
-	return CRYPTO_CIPHER_TYPE_AES256;
-}
 
-static int string_to_crypto_hash_type(const char* crypto_hash_type)
-{
-	if (strcmp(crypto_hash_type, "none") == 0) {
-		return CRYPTO_HASH_TYPE_NONE;
-	} else if (strcmp(crypto_hash_type, "md5") == 0) {
-		return CRYPTO_HASH_TYPE_MD5;
-	} else if (strcmp(crypto_hash_type, "sha1") == 0) {
-		return CRYPTO_HASH_TYPE_SHA1;
-	} else if (strcmp(crypto_hash_type, "sha256") == 0) {
-		return CRYPTO_HASH_TYPE_SHA256;
-	} else if (strcmp(crypto_hash_type, "sha384") == 0) {
-		return CRYPTO_HASH_TYPE_SHA384;
-	} else if (strcmp(crypto_hash_type, "sha512") == 0) {
-		return CRYPTO_HASH_TYPE_SHA512;
+	if (decrypt_nss(instance, buf, buf_len) < 0) {
+		return -1;
 	}
 
-	return CRYPTO_HASH_TYPE_SHA1;
+	return 0;
 }
 
+/*
+ * exported API
+ */
+
 size_t crypto_sec_header_size(
 	const char *crypto_cipher_type,
 	const char *crypto_hash_type)
@@ -630,26 +628,19 @@ int crypto_encrypt_and_sign (
 	unsigned char *buf_out,
 	size_t *buf_out_len)
 {
-	int err = 0;
-	struct crypto_config_header *cch;
+	struct crypto_config_header *cch = (struct crypto_config_header *)buf_out;
+	int err;
 
-	cch = (struct crypto_config_header *)buf_out;
 	cch->crypto_cipher_type = instance->crypto_cipher_type;
 	cch->crypto_hash_type = instance->crypto_hash_type;
 	cch->__pad0 = 0;
 	cch->__pad1 = 0;
 
-	if ((!cipher_to_nss[instance->crypto_cipher_type]) &&
-	    (!hash_to_nss[instance->crypto_hash_type])) {
-		memcpy(buf_out + sizeof(struct crypto_config_header), buf_in, buf_in_len);
-		*buf_out_len = buf_in_len;
-		err = 0;
-	} else {
-		err = encrypt_and_sign_nss(instance,
-					   buf_in, buf_in_len,
-					   buf_out + sizeof(struct crypto_config_header),
-					   buf_out_len);
-	}
+	buf_out += sizeof(struct crypto_config_header);
+
+	err = encrypt_and_sign_nss(instance,
+				   buf_in, buf_in_len,
+				   buf_out, buf_out_len);
 
 	*buf_out_len = *buf_out_len + sizeof(struct crypto_config_header);
 
@@ -661,9 +652,7 @@ int crypto_authenticate_and_decrypt (struct crypto_instance *instance,
 	int *buf_len)
 {
 	int err = 0;
-	struct crypto_config_header *cch;
-
-	cch = (struct crypto_config_header *)buf;
+	struct crypto_config_header *cch = (struct crypto_config_header *)buf;
 
 	/*
 	 * decode crypto config of incoming packets
@@ -688,28 +677,13 @@ int crypto_authenticate_and_decrypt (struct crypto_instance *instance,
 	}
 
 	/*
-	 * invalidate config header
+	 * invalidate config header and kill it
 	 */
 	cch = NULL;
-
-	/*
-	 * and kill it
-	 */
-	*buf_len = *buf_len - sizeof(struct crypto_config_header);
+	*buf_len -= sizeof(struct crypto_config_header);
 	memmove(buf, buf + sizeof(struct crypto_config_header), *buf_len);
 
-
-	/*
-	 * if crypto is totally disabled, there is no work for us
-	 */
-	if ((!cipher_to_nss[instance->crypto_cipher_type]) &&
-	    (!hash_to_nss[instance->crypto_hash_type])) {
-		err = 0;
-	} else {
-		err = authenticate_and_decrypt_nss(instance, buf, buf_len);
-	}
-
-	return err;
+	return authenticate_and_decrypt_nss(instance, buf, buf_len);
 }
 
 struct crypto_instance *crypto_init(
@@ -743,13 +717,15 @@ struct crypto_instance *crypto_init(
 	instance->crypto_cipher_type = string_to_crypto_cipher_type(crypto_cipher_type);
 	instance->crypto_hash_type = string_to_crypto_hash_type(crypto_hash_type);
 
+	instance->crypto_header_size = crypto_sec_header_size(crypto_cipher_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;
 
-	if (init_nss_crypto(instance, crypto_cipher_type, crypto_hash_type) < 0) {
+	if (init_nss(instance, crypto_cipher_type, crypto_hash_type) < 0) {
 		free(instance);
 		return(NULL);
 	}
-- 
1.7.7.6

_______________________________________________
discuss mailing list
discuss@xxxxxxxxxxxx
http://lists.corosync.org/mailman/listinfo/discuss


[Index of Archives]     [Linux Clusters]     [Corosync Project]     [Linux USB Devel]     [Linux Audio Users]     [Photo]     [Yosemite News]    [Yosemite Photos]    [Linux Kernel]     [Linux SCSI]     [X.Org]

  Powered by Linux