From 3a5eb0b7d4cf5662cb8a2a68b0e5aaf01426a77f Mon Sep 17 00:00:00 2001
From: Mike Hibler <hibler@cs.utah.edu>
Date: Thu, 2 Jun 2011 15:31:41 -0600
Subject: [PATCH] More cleanup, get frisbee on board with signed/encrypted
 images.

---
 os/frisbee.redux/GNUmakefile.in | 11 ++++++--
 os/frisbee.redux/client.c       | 12 +++------
 os/imagezip/checksum.c          | 19 -------------
 os/imagezip/imagedump.c         | 16 +++++++----
 os/imagezip/imageunzip.c        | 42 +++++++++++++++++------------
 os/imagezip/imagezip.c          | 47 ++++++++++++++++++---------------
 6 files changed, 75 insertions(+), 72 deletions(-)

diff --git a/os/frisbee.redux/GNUmakefile.in b/os/frisbee.redux/GNUmakefile.in
index 64de343a97..24251351e7 100644
--- a/os/frisbee.redux/GNUmakefile.in
+++ b/os/frisbee.redux/GNUmakefile.in
@@ -13,8 +13,12 @@ DISTFILES	= TODO client.c decls.h event.c event.h log.c log.h \
 		  network.c queue.h server.c trace.c trace.h utils.c utils.h
 EXPANDCOPYRIGHT	= /usr/site/lib/copyright/expand-copyr
 
-# Set to 1 for "secure frisbee" support.  Requires openssl libraries.
+#
+# Support encrypted and signed-checksumed images.
+# Requires openssl libraries.
+#
 WITH_CRYPTO	= 1
+WITH_SIGNING	= 1
 
 SYSTEM	:= $(shell uname -s)
 
@@ -103,7 +107,10 @@ IUZFLAGS	= -DFRISBEE
 IUZLIBS		= 
 
 ifeq ($(WITH_CRYPTO),1)
-IUZFLAGS	+= -DWITH_CRYPTO -DSIGN_CHECKSUM
+IUZFLAGS	+= -DWITH_CRYPTO
+ifeq ($(WITH_SIGNING),1)
+IUZFLAGS	+= -DSIGN_CHECKSUM
+endif
 IUZLIBS		+= -lcrypto
 endif
 
diff --git a/os/frisbee.redux/client.c b/os/frisbee.redux/client.c
index 5f40a8e1b3..d4de2fa634 100644
--- a/os/frisbee.redux/client.c
+++ b/os/frisbee.redux/client.c
@@ -78,7 +78,7 @@ static int	GotBlock(Packet_t *p);
 static void	RequestChunk(int timedout);
 static int	RequestStamp(int chunk, int block, int count, void *arg);
 static int	RequestRedoTime(int chunk, unsigned long long curtime);
-extern int	ImageUnzipInitKeys(char *uuid, char *sig_keyfile,
+extern int	ImageUnzipInitKeys(char *uuidstr, char *sig_keyfile,
 				   char *enc_keyfile);
 extern int	ImageUnzipInit(char *filename, int slice, int debug, int zero,
 			       int nothreads, int dostype, int dodots,
@@ -219,7 +219,7 @@ main(int argc, char **argv)
 	char   *filename = NULL;
 	int	dostype = -1;
 	int	slice = 0;
-	char	*sig_keyfile = 0, *enc_keyfile = 0, *uuid = 0;
+	char	*sig_keyfile = 0, *enc_keyfile = 0, *uuidstr = 0;
 
 	while ((ch = getopt(argc, argv, "dqhp:m:s:i:tbznT:r:E:D:C:W:S:M:R:I:ONc:e:u:K:B:F:Q:P:X:")) != -1)
 		switch(ch) {
@@ -391,12 +391,8 @@ main(int argc, char **argv)
 			break;
 
 		case 'u':
-		{
-			extern char *str_to_uuid(char *);
-
-			uuid = str_to_uuid(optarg);
+			uuidstr = optarg;
 			break;
-		}
 
 		case 'K':
 			keepalive = atoi(optarg);
@@ -626,7 +622,7 @@ main(int argc, char **argv)
 	/*
 	 * Initialize keys for authentication/encryption.
 	 */
-	ImageUnzipInitKeys(uuid, sig_keyfile, enc_keyfile);
+	ImageUnzipInitKeys(uuidstr, sig_keyfile, enc_keyfile);
 
 	/*
 	 * Pass in assorted parameters and fire off the disk writer thread.
diff --git a/os/imagezip/checksum.c b/os/imagezip/checksum.c
index 9a166d7788..3ee2d5c1c5 100644
--- a/os/imagezip/checksum.c
+++ b/os/imagezip/checksum.c
@@ -254,22 +254,3 @@ hexstr_to_mem(unsigned char * dest, const char * source, int memsize)
 	}
 	return result;
 }
-
-/*
- * XXX hack for frisbee use.
- * So we don't have to worry about UUID_LENGTH constant there.
- */
-char *
-str_to_uuid(char *srcstr)
-{
-	unsigned char *buf = calloc(UUID_LENGTH, 1);
-	
-	if (!buf)
-		return NULL;
-	if (!hexstr_to_mem(buf, srcstr, UUID_LENGTH)) {
-		free(buf);
-		return NULL;
-	}
-
-	return (char *)buf;
-}
diff --git a/os/imagezip/imagedump.c b/os/imagezip/imagedump.c
index 9a3ce1d7f5..0c90d71f2b 100644
--- a/os/imagezip/imagedump.c
+++ b/os/imagezip/imagedump.c
@@ -291,9 +291,12 @@ dumpfile(char *name, int fd)
 				       magic - COMPRESSED_MAGIC_BASE + 1);
 				if (magic >= COMPRESSED_V4) {
 					sigtype = hdr->csum_type;
-					if (sigtype != CSUM_NONE)
-						printf(", signed (%d)",
-						       sigtype);
+					if (sigtype != CSUM_NONE) {
+						printf(", ");
+						if (sigtype & CSUM_SIGNED)
+							printf("signed ");
+						printf("csum (0x%x)", sigtype);
+					}
 					enctype = hdr->enc_cipher;
 					if (enctype != ENC_NONE)
 						printf(", encrypted (%d)",
@@ -461,10 +464,10 @@ dumpchunk(char *name, char *buf, int chunkno, int checkindex)
 			}
 		}
 		if (checksums && hdr->csum_type != CSUM_NONE) {
-			if (hdr->csum_type != CSUM_SHA1) {
+			if ((hdr->csum_type & CSUM_TYPE) != CSUM_SHA1) {
 				printf("%s: unsupported checksum type %d in "
 				       "chunk %d", name,
-				       hdr->csum_type,
+				       (hdr->csum_type & CSUM_TYPE),
 				       chunkno);
 				return 1;
 			}
@@ -517,6 +520,9 @@ dumpchunk(char *name, char *buf, int chunkno, int checkindex)
 			if (hdr->csum_type != CSUM_NONE) {
 				len = 0;
 				switch (hdr->csum_type) {
+				case CSUM_SIGNED|CSUM_SHA1:
+					len = CSUM_MAX_LEN;
+					break;
 				case CSUM_SHA1:
 					len = CSUM_SHA1_LEN;
 					break;
diff --git a/os/imagezip/imageunzip.c b/os/imagezip/imageunzip.c
index 0ae026c778..3594a03e8d 100644
--- a/os/imagezip/imageunzip.c
+++ b/os/imagezip/imageunzip.c
@@ -131,7 +131,7 @@ static int	*chunklist, *nextchunk;
 #endif
 
 /* UUID for the current image, all chunks must have the same ID */
-static unsigned char imageid[UUID_LENGTH];
+static unsigned char uuid[UUID_LENGTH];
 static int has_id = 0;
 
 /*
@@ -200,7 +200,7 @@ unsigned long		splits;
 /* security */
 static int do_checksum = 0;
 static int do_decrypt = 0;
-static char *cipherarg = NULL;
+static int cipher = ENC_NONE;
 static unsigned char encryption_key[ENC_MAX_KEYLEN];
 #endif
 
@@ -653,8 +653,10 @@ main(int argc, char *argv[])
 
 		case 'e':
 			/* Encryption cipher */
-			cipherarg = optarg;
-			if (strcmp(cipherarg, "bf_cbc") != 0) {
+			if (strcmp(optarg, "bf_cbc") == 0) {
+				cipher = ENC_BLOWFISH_CBC;
+			}
+			else {
 				fprintf(stderr,
 					"Only know \"bf_cbc\" (blowfish CBC)\n");
 				usage();
@@ -666,12 +668,15 @@ main(int argc, char *argv[])
 			if (!encrypt_readkey(optarg, encryption_key,
 					     ENC_MAX_KEYLEN))
 				exit(1);
+			/* XXX can you intuit the cipher from the key? */
+			if (cipher == ENC_NONE)
+				cipher = ENC_BLOWFISH_CBC;
 			do_decrypt = 1;
 			break;
 #endif
 		case 'u':
 			/* UUID for image id. */
-			if (!hexstr_to_mem(imageid, optarg, UUID_LENGTH))
+			if (!hexstr_to_mem(uuid, optarg, UUID_LENGTH))
 				usage();
 			has_id = 1;
 			break;
@@ -913,14 +918,17 @@ main(int argc, char *argv[])
  * When compiled for frisbee, act as a library.
  */
 int
-ImageUnzipInitKeys(char *uuid, char *sig_keyfile, char *enc_keyfile)
+ImageUnzipInitKeys(char *uuidstr, char *sig_keyfile, char *enc_keyfile)
 {
-	if (uuid) {
-		memcpy(imageid, uuid, UUID_LENGTH);
+	if (uuidstr) {
+		if (!hexstr_to_mem(uuid, uuidstr, UUID_LENGTH)) {
+			fprintf(stderr, "Bogus UUID\n");
+			exit(1);
+		}
 		has_id = 1;
 	}
-#ifdef WITH_CRYPTO
 
+#ifdef WITH_CRYPTO
 	if (sig_keyfile) {
 #ifdef SIGN_CHECKSUM
 		if (!init_checksum(sig_keyfile))
@@ -1233,12 +1241,12 @@ decrypt_buffer(unsigned char *dest, const unsigned char *source,
 	int final_count = 0;
 	int error = 0;
 	EVP_CIPHER_CTX context;
-	EVP_CIPHER const *cipher;
+	EVP_CIPHER const *ecipher;
 
 	EVP_CIPHER_CTX_init(&context);
-	cipher = EVP_bf_cbc();
+	ecipher = EVP_bf_cbc();
 
-	EVP_DecryptInit(&context, cipher, NULL, header->enc_iv);
+	EVP_DecryptInit(&context, ecipher, NULL, header->enc_iv);
 	EVP_CIPHER_CTX_set_key_length(&context, ENC_MAX_KEYLEN);
 	EVP_DecryptInit(&context, NULL, encryption_key, NULL);
 
@@ -1361,15 +1369,15 @@ inflate_subblock(const char *chunkbufp)
 		 */
 		if (has_id == 0) {
 			has_id = 1;
-			memcpy(imageid, blockhdr->imageid, UUID_LENGTH);
-		} else if (memcmp(imageid, blockhdr->imageid, UUID_LENGTH)) {
+			memcpy(uuid, blockhdr->imageid, UUID_LENGTH);
+		} else if (memcmp(uuid, blockhdr->imageid, UUID_LENGTH)) {
 			char uuidstr[UUID_LENGTH*2 + 1];
 
 			fprintf(stderr, "Incorrect Image ID in chunk %d:\n",
 				blockhdr->blockindex);
 			mem_to_hexstr(uuidstr, blockhdr->imageid, UUID_LENGTH);
 			fprintf(stderr, "  In chunk:  0x%s\n", uuidstr);
-			mem_to_hexstr(uuidstr, imageid, UUID_LENGTH);
+			mem_to_hexstr(uuidstr, uuid, UUID_LENGTH);
 			fprintf(stderr, "  Should be: 0x%s\n", uuidstr);
 			exit(1);
 		}
@@ -1383,9 +1391,9 @@ inflate_subblock(const char *chunkbufp)
 				fprintf(stderr, "Chunk has no cipher\n");
 				exit(1);
 			}
-			if (blockhdr->enc_cipher != ENC_BLOWFISH_CBC) {
+			if (blockhdr->enc_cipher != cipher) {
 				fprintf(stderr,
-					"Chunk cipher type %d not supported\n",
+					"Wrong cipher type %d in chunk\n",
 					blockhdr->enc_cipher);
 				exit(1);
 			}
diff --git a/os/imagezip/imagezip.c b/os/imagezip/imagezip.c
index fada78dcf0..df83b2fd13 100644
--- a/os/imagezip/imagezip.c
+++ b/os/imagezip/imagezip.c
@@ -72,9 +72,9 @@ int	dorelocs  = 1;
 int	metaoptimize = 0;
 int	filemode  = 0;
 int	do_encrypt = 0;
-char	*cipherarg = NULL;
+int	cipher = ENC_NONE;
 int	do_checksum = 0;
-char	*sighasharg = NULL;
+int	csumalg = CSUM_NONE;
 off_t	datawritten;
 partmap_t ignore, forceraw;
 static	int got_imageid;
@@ -492,14 +492,17 @@ main(int argc, char *argv[])
 		case 'a':
 #ifdef WITH_CRYPTO
 			/* Authentication (checksum) hash algorithm */
-			sighasharg = optarg;
-			if (strcmp(sighasharg, "SHA1") != 0) {
-				fprintf(stderr,
-					"Only know \"SHA1\"\n");
+			if (strcmp(optarg, "SHA1") == 0) {
+				csumalg = CSUM_SHA1;
+			}
+			else {
+				fprintf(stderr, "Only know \"SHA1\"\n");
 				usage();
 			}
 			do_checksum++;
-#ifndef SIGN_CHECKSUM
+#ifdef SIGN_CHECKSUM
+			csumalg |= CSUM_SIGNED;
+#else
 			fprintf(stderr, "WARNING: checksum is not signed\n");
 #endif
 #else
@@ -511,8 +514,10 @@ main(int argc, char *argv[])
 		case 'e':
 #ifdef WITH_CRYPTO
 			/* Encryption cipher */
-			cipherarg = optarg;
-			if (strcmp(cipherarg, "bf_cbc") != 0) {
+			if (strcmp(optarg, "bf_cbc") == 0) {
+				cipher = ENC_BLOWFISH_CBC;
+			}
+			else {
 				fprintf(stderr,
 					"Only know \"bf_cbc\" (blowfish CBC)\n");
 				usage();
@@ -530,6 +535,9 @@ main(int argc, char *argv[])
 			if (enc_key == NULL ||
 			    !encrypt_readkey(optarg, enc_key, ENC_MAX_KEYLEN))
 				usage();
+			/* XXX can you intuit the cipher from the key? */
+			if (cipher == ENC_NONE)
+				cipher = ENC_BLOWFISH_CBC;
 #else
 			fprintf(stderr, "'k' option not supported\n");
 			usage();
@@ -1809,7 +1817,7 @@ static off_t	compress_chunk(off_t, off_t, int *, uint32_t *);
 static int	compress_finish(uint32_t *subblksize);
 static void	compress_status(int sig);
 #ifdef WITH_CRYPTO
-static void	checksum_start(blockhdr_t *hdr);
+static void	checksum_start(blockhdr_t *hdr, int alg);
 static void	checksum_chunk(uint8_t *buf, off_t size);
 static void	checksum_finish(blockhdr_t *hdr);
 static void	encrypt_start(blockhdr_t *hdr);
@@ -2062,7 +2070,7 @@ compress_image(void)
 		 */
 		if (do_checksum) {
 			assert(!compat);
-			checksum_start(blkhdr);
+			checksum_start(blkhdr, csumalg);
 			checksum_chunk(output_buffer,
 				       blkhdr->size + blkhdr->regionsize);
 			checksum_finish(blkhdr);
@@ -2190,7 +2198,7 @@ compress_image(void)
 		 */
 		if (do_checksum) {
 			assert(!compat);
-			checksum_start(blkhdr);
+			checksum_start(blkhdr, csumalg);
 			checksum_chunk(output_buffer,
 				       blkhdr->size + blkhdr->regionsize);
 			checksum_finish(blkhdr);
@@ -2532,7 +2540,7 @@ compress_finish(uint32_t *subblksize)
  */
 SHA_CTX sha_ctx;
 void
-checksum_start(blockhdr_t *hdr)
+checksum_start(blockhdr_t *hdr, int alg)
 {
 	/*
 	 * Start with the checksum zeroed out - this way, we can put the
@@ -2542,10 +2550,7 @@ checksum_start(blockhdr_t *hdr)
 	memset(hdr->checksum, 0, sizeof(hdr->checksum));
 
 	/* type is part of the checksum */
-	hdr->csum_type = CSUM_SHA1;
-#ifdef SIGN_CHECKSUM
-	hdr->csum_type |= CSUM_SIGNED;
-#endif
+	hdr->csum_type = alg;
 
 	SHA1_Init(&sha_ctx);
 }
@@ -2706,7 +2711,7 @@ checksum_finish(blockhdr_t *hdr)
  * Encryption functions
  */
 static EVP_CIPHER_CTX cipher_ctx;
-static const EVP_CIPHER *cipher;
+static const EVP_CIPHER *ecipher;
 /* XXX: the size of the IV may have to change with different ciphers */
 static uint8_t iv[ENC_MAX_KEYLEN];
 
@@ -2726,7 +2731,7 @@ encrypt_start(blockhdr_t *hdr)
 	 * Pick our cipher - currently, only Blowfish in CBC mode is supported
 	 */
 	EVP_CIPHER_CTX_init(&cipher_ctx);
-	cipher = EVP_bf_cbc();
+	ecipher = EVP_bf_cbc();
 
 	/*
 	 * If this is the first chunk, generate a new IV. Otherwise, we use
@@ -2767,7 +2772,7 @@ encrypt_start(blockhdr_t *hdr)
 	/*
 	 * Set the cipher and IV
 	 */
-	EVP_EncryptInit(&cipher_ctx, cipher, NULL, iv);
+	EVP_EncryptInit(&cipher_ctx, ecipher, NULL, iv);
 
 	/*
 	 * Bump up the key length and set the key
@@ -2815,7 +2820,7 @@ encrypt_finish(blockhdr_t *hdr, uint8_t *outbuf, uint32_t *out_size)
 	assert(encrypted_bytes <= CHUNKMAX);
 	memcpy(outbuf, encryption_buffer, encrypted_bytes);
 
-	hdr->enc_cipher = ENC_BLOWFISH_CBC;
+	hdr->enc_cipher = cipher;
 
 	*out_size = encrypted_bytes;
 }
-- 
GitLab