From 80d08fecb7f7f20b5b5db26bed1b2dfc133547a7 Mon Sep 17 00:00:00 2001 From: "Bernhard M. Wiedemann" Date: Mon, 10 Oct 2016 15:09:07 +0200 Subject: [PATCH 1/3] [digest] split out hashing part --- src/hci/commands/digest_cmd.c | 52 ++++++++++++++++++++--------------- 1 file changed, 30 insertions(+), 22 deletions(-) diff --git a/src/hci/commands/digest_cmd.c b/src/hci/commands/digest_cmd.c index 71308064fb..5de5cffb03 100644 --- a/src/hci/commands/digest_cmd.c +++ b/src/hci/commands/digest_cmd.c @@ -48,6 +48,35 @@ static struct command_descriptor digest_cmd = COMMAND_DESC ( struct digest_options, digest_opts, 1, MAX_ARGUMENTS, " [...]" ); +static int digest_one(char *imageuri, uint8_t *digest_out, struct image **image, struct digest_algorithm *digest) { + uint8_t digest_ctx[digest->ctxsize]; + size_t frag_len; + uint8_t buf[128]; + size_t offset; + size_t len; + int rc; + + /* Acquire image */ + if ( ( rc = imgacquire ( imageuri, 0, image ) ) != 0 ) + return rc; + offset = 0; + len = (*image)->len; + + /* calculate digest */ + digest_init ( digest, digest_ctx ); + while ( len ) { + frag_len = len; + if ( frag_len > sizeof ( buf ) ) + frag_len = sizeof ( buf ); + copy_from_user ( buf, (*image)->data, offset, frag_len ); + digest_update ( digest, digest_ctx, buf, frag_len ); + len -= frag_len; + offset += frag_len; + } + digest_final ( digest, digest_ctx, digest_out ); + return 0; +} + /** * The "digest" command * @@ -60,12 +89,7 @@ static int digest_exec ( int argc, char **argv, struct digest_algorithm *digest ) { struct digest_options opts; struct image *image; - uint8_t digest_ctx[digest->ctxsize]; uint8_t digest_out[digest->digestsize]; - uint8_t buf[128]; - size_t offset; - size_t len; - size_t frag_len; int i; unsigned j; int rc; @@ -76,24 +100,8 @@ static int digest_exec ( int argc, char **argv, for ( i = optind ; i < argc ; i++ ) { - /* Acquire image */ - if ( ( rc = imgacquire ( argv[i], 0, &image ) ) != 0 ) + if ( ( rc = digest_one ( argv[i], digest_out, &image, digest) ) != 0 ) continue; - offset = 0; - len = image->len; - - /* calculate digest */ - digest_init ( digest, digest_ctx ); - while ( len ) { - frag_len = len; - if ( frag_len > sizeof ( buf ) ) - frag_len = sizeof ( buf ); - copy_from_user ( buf, image->data, offset, frag_len ); - digest_update ( digest, digest_ctx, buf, frag_len ); - len -= frag_len; - offset += frag_len; - } - digest_final ( digest, digest_ctx, digest_out ); for ( j = 0 ; j < sizeof ( digest_out ) ; j++ ) printf ( "%02x", digest_out[j] ); From 07f50e49126f2c98c1cb5160287bc2de447f95e0 Mon Sep 17 00:00:00 2001 From: "Bernhard M. Wiedemann" Date: Mon, 10 Oct 2016 15:47:45 +0200 Subject: [PATCH 2/3] [digest] add sha1verify command This allows to get a trusted image with known digest value that is embedded in the ipxe script making http downloads safe to use this way example usage: kernel http://boot.ipxe.org/memtest.0 sha1verify memtest.0 5d78d4c7e97c99bca3d3dff602b84dde5b70c5bf boot an md5verify cmd could easily be added, but would not be recommended to use because of known weaknesses with MD5 digests --- src/hci/commands/digest_cmd.c | 70 +++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) diff --git a/src/hci/commands/digest_cmd.c b/src/hci/commands/digest_cmd.c index 5de5cffb03..324799f2da 100644 --- a/src/hci/commands/digest_cmd.c +++ b/src/hci/commands/digest_cmd.c @@ -48,6 +48,13 @@ static struct command_descriptor digest_cmd = COMMAND_DESC ( struct digest_options, digest_opts, 1, MAX_ARGUMENTS, " [...]" ); +struct digest_verify_options {}; + +/** "digest_verify" command descriptor */ +static struct command_descriptor digest_verify_cmd = + COMMAND_DESC ( struct digest_verify_options, digest_opts, 1, MAX_ARGUMENTS, + " " ); + static int digest_one(char *imageuri, uint8_t *digest_out, struct image **image, struct digest_algorithm *digest) { uint8_t digest_ctx[digest->ctxsize]; size_t frag_len; @@ -112,6 +119,60 @@ static int digest_exec ( int argc, char **argv, return 0; } +/** + * The "digest_verify" command + * + * @v argc Argument count + * @v argv Argument list + * @v digest Digest algorithm + * @ret rc Return status code + */ +static int digest_verify_exec ( int argc, char **argv, + struct digest_algorithm *digest ) { + struct digest_options opts; + struct image *image; + uint8_t digest_out[digest->digestsize]; + unsigned j; + int rc; + char *intended_digest; + char digest_str[3]; + + /* Parse options */ + if ( ( rc = parse_options ( argc, argv, &digest_verify_cmd, &opts ) ) != 0 ) + return rc; + + if ( argc != 3 ) { + printf( "argc should be 3, not %i\n", argc ); + sleep( 2 ); + return -1; + } + + if ( ( rc = digest_one ( argv[optind], digest_out, &image, digest) ) != 0 ) + return rc; + intended_digest = argv[optind+1]; + if ( strlen(intended_digest) != 2 * sizeof ( digest_out ) ) { + printf ( "reference digest has wrong length\n" ); + sleep ( 2 ); + return 1; + } + + for ( j = 0 ; j < sizeof ( digest_out ) ; j++ ) { + snprintf ( digest_str, 3, "%02x", digest_out[j] ); +#ifndef NDEBUG + printf ( "comparing %s to %s\n", digest_str, intended_digest ); +#endif + if ( strncmp(digest_str, intended_digest, 2) != 0 ) { + printf ( "digest verification failed for %s %s\n", argv[optind], argv[optind+1] ); + sleep ( 2 ); + return 1; + } + intended_digest+=2; + } + + printf ( " verified %s\n", image->name ); + return 0; +} + static int md5sum_exec ( int argc, char **argv ) { return digest_exec ( argc, argv, &md5_algorithm ); } @@ -120,6 +181,10 @@ static int sha1sum_exec ( int argc, char **argv ) { return digest_exec ( argc, argv, &sha1_algorithm ); } +static int sha1verify_exec ( int argc, char **argv ) { + return digest_verify_exec ( argc, argv, &sha1_algorithm ); +} + struct command md5sum_command __command = { .name = "md5sum", .exec = md5sum_exec, @@ -129,3 +194,8 @@ struct command sha1sum_command __command = { .name = "sha1sum", .exec = sha1sum_exec, }; + +struct command sha1verify_command __command = { + .name = "sha1verify", + .exec = sha1verify_exec, +}; From 0bc371d4ab27f7baee1968a5064fef1094bb224b Mon Sep 17 00:00:00 2001 From: "Bernhard M. Wiedemann" Date: Wed, 12 Oct 2016 15:16:09 +0200 Subject: [PATCH 3/3] [digest] shift more code into shared function because we are only ever interested in the hex string of the digest value --- src/hci/commands/digest_cmd.c | 40 ++++++++++++++++------------------- 1 file changed, 18 insertions(+), 22 deletions(-) diff --git a/src/hci/commands/digest_cmd.c b/src/hci/commands/digest_cmd.c index 324799f2da..8e1340a386 100644 --- a/src/hci/commands/digest_cmd.c +++ b/src/hci/commands/digest_cmd.c @@ -55,12 +55,14 @@ static struct command_descriptor digest_verify_cmd = COMMAND_DESC ( struct digest_verify_options, digest_opts, 1, MAX_ARGUMENTS, " " ); -static int digest_one(char *imageuri, uint8_t *digest_out, struct image **image, struct digest_algorithm *digest) { +static int digest_one(char *imageuri, char *digest_out_hex, struct image **image, struct digest_algorithm *digest) { uint8_t digest_ctx[digest->ctxsize]; size_t frag_len; uint8_t buf[128]; + uint8_t digest_out[digest->digestsize]; size_t offset; size_t len; + unsigned j; int rc; /* Acquire image */ @@ -81,6 +83,10 @@ static int digest_one(char *imageuri, uint8_t *digest_out, struct image **image, offset += frag_len; } digest_final ( digest, digest_ctx, digest_out ); + for ( j = 0 ; j < sizeof ( digest_out ) ; j++ ) { + snprintf ( digest_out_hex + 2 * j, 3, "%02x", digest_out[j] ); + } + return 0; } @@ -96,9 +102,8 @@ static int digest_exec ( int argc, char **argv, struct digest_algorithm *digest ) { struct digest_options opts; struct image *image; - uint8_t digest_out[digest->digestsize]; + char digest_out_hex[1 + 2 * digest->digestsize]; int i; - unsigned j; int rc; /* Parse options */ @@ -107,13 +112,10 @@ static int digest_exec ( int argc, char **argv, for ( i = optind ; i < argc ; i++ ) { - if ( ( rc = digest_one ( argv[i], digest_out, &image, digest) ) != 0 ) + if ( ( rc = digest_one ( argv[i], digest_out_hex, &image, digest) ) != 0 ) continue; - for ( j = 0 ; j < sizeof ( digest_out ) ; j++ ) - printf ( "%02x", digest_out[j] ); - - printf ( " %s\n", image->name ); + printf ( "%s %s\n", digest_out_hex, image->name ); } return 0; @@ -131,11 +133,9 @@ static int digest_verify_exec ( int argc, char **argv, struct digest_algorithm *digest ) { struct digest_options opts; struct image *image; - uint8_t digest_out[digest->digestsize]; - unsigned j; + char digest_out_hex[1 + 2 * digest->digestsize]; int rc; char *intended_digest; - char digest_str[3]; /* Parse options */ if ( ( rc = parse_options ( argc, argv, &digest_verify_cmd, &opts ) ) != 0 ) @@ -147,26 +147,22 @@ static int digest_verify_exec ( int argc, char **argv, return -1; } - if ( ( rc = digest_one ( argv[optind], digest_out, &image, digest) ) != 0 ) + if ( ( rc = digest_one ( argv[optind], digest_out_hex, &image, digest) ) != 0 ) return rc; intended_digest = argv[optind+1]; - if ( strlen(intended_digest) != 2 * sizeof ( digest_out ) ) { + if ( strlen( intended_digest ) != 2 * digest->digestsize ) { printf ( "reference digest has wrong length\n" ); sleep ( 2 ); return 1; } - for ( j = 0 ; j < sizeof ( digest_out ) ; j++ ) { - snprintf ( digest_str, 3, "%02x", digest_out[j] ); #ifndef NDEBUG - printf ( "comparing %s to %s\n", digest_str, intended_digest ); + printf ( "comparing %s to %s\n", digest_out_hex, intended_digest ); #endif - if ( strncmp(digest_str, intended_digest, 2) != 0 ) { - printf ( "digest verification failed for %s %s\n", argv[optind], argv[optind+1] ); - sleep ( 2 ); - return 1; - } - intended_digest+=2; + if ( strncmp( digest_out_hex, intended_digest, 2 * digest->digestsize ) != 0 ) { + printf ( "digest verification failed for %s %s\n", argv[optind], argv[optind+1] ); + sleep ( 2 ); + return 1; } printf ( " verified %s\n", image->name );