mail archive of the barebox mailing list
 help / color / mirror / Atom feed
* [PATCH] commands: add md5/sha1/sha256sum commands using the digest api
@ 2011-05-17 12:10 Peter Korsgaard
  2011-05-17 12:30 ` Jean-Christophe PLAGNIOL-VILLARD
  0 siblings, 1 reply; 5+ messages in thread
From: Peter Korsgaard @ 2011-05-17 12:10 UTC (permalink / raw)
  To: barebox

The interface emulates the Linux commands, except that you can
specify a sub area - E.G.:

barebox:/ md5sum /dev/fd0 2M+1M /env/config /env/bin/boot 10+2
61c4c0180b044191d28f27545f43562f  /dev/fd0	0x00200000 ... 0x00300000
908b84bcbadd2f263583a65ff31d1cad  /env/config	0x00000000 ... 0x000003a7
f23bd15825cc5006cf5f9fd486d82d2d  /env/bin/boot	0x0000000a ... 0x0000000c

Adds around 1400 bytes (+ size of digest code) with everything enabled.

Signed-off-by: Peter Korsgaard <jacmet@sunsite.dk>
---
 commands/Kconfig  |   22 +++++++
 commands/Makefile |    1 +
 commands/digest.c |  178 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 201 insertions(+), 0 deletions(-)
 create mode 100644 commands/digest.c

diff --git a/commands/Kconfig b/commands/Kconfig
index f192d30..30eeff9 100644
--- a/commands/Kconfig
+++ b/commands/Kconfig
@@ -222,6 +222,28 @@ config CMD_CRC_CMP
 	depends on CMD_CRC
 	prompt "compare 2 files crc"
 
+config CMD_DIGEST
+       tristate
+       select DIGEST
+
+config CMD_MD5SUM
+	tristate
+	select CMD_DIGEST
+	select MD5
+	prompt "md5sum"
+
+config CMD_SHA1SUM
+	tristate
+	select CMD_DIGEST
+	select SHA1
+	prompt "sha1sum"
+
+config CMD_SHA256SUM
+	tristate
+	select CMD_DIGEST
+	select SHA256
+	prompt "sha256sum"
+
 config CMD_MTEST
 	tristate
 	prompt "mtest"
diff --git a/commands/Makefile b/commands/Makefile
index f7ef9a8..8ee4aba 100644
--- a/commands/Makefile
+++ b/commands/Makefile
@@ -26,6 +26,7 @@ obj-$(CONFIG_CMD_MOUNT)		+= mount.o
 obj-$(CONFIG_CMD_UMOUNT)	+= umount.o
 obj-$(CONFIG_CMD_REGINFO)	+= reginfo.o
 obj-$(CONFIG_CMD_CRC)		+= crc.o
+obj-$(CONFIG_CMD_DIGEST)	+= digest.o
 obj-$(CONFIG_CMD_CLEAR)		+= clear.o
 obj-$(CONFIG_CMD_TEST)		+= test.o
 obj-$(CONFIG_CMD_FLASH)		+= flash.o
diff --git a/commands/digest.c b/commands/digest.c
new file mode 100644
index 0000000..587a550
--- /dev/null
+++ b/commands/digest.c
@@ -0,0 +1,178 @@
+/*
+ * digest.c - Calculate a md5/sha1/sha256 checksum of a memory area
+ *
+ * Copyright (c) 2011 Peter Korsgaard <jacmet@sunsite.dk>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <common.h>
+#include <command.h>
+#include <fs.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <xfuncs.h>
+#include <malloc.h>
+#include <digest.h>
+#include <linux/ctype.h>
+
+static void print_digest(struct digest *d)
+{
+	unsigned char *data;
+	int i;
+
+	data = xmalloc(d->length);
+	d->final(d, data);
+
+	for (i=0; i<d->length; i++)
+		printf("%02x", data[i]);
+
+	free(data);
+}
+
+static int file_digest(struct digest *d, char *filename,
+					   ulong start, ulong size)
+{
+	ulong len = 0;
+	int fd, now, ret = 0;
+	char *buf;
+
+	d->init(d);
+
+	fd = open(filename, O_RDONLY);
+	if (fd < 0) {
+		printf("open %s: %s\n", filename, errno_str());
+		return fd;
+	}
+
+	if (start > 0) {
+		ret = lseek(fd, start, SEEK_SET);
+		if (ret == -1) {
+			perror("lseek");
+			goto out;
+		}
+	}
+
+	buf = xmalloc(4096);
+
+	while (size) {
+		now = min((ulong)4096, size);
+		now = read(fd, buf, now);
+		if (now < 0) {
+			ret = now;
+			perror("read");
+			goto out_free;
+		}
+		if (!now)
+			break;
+
+		d->update(d, buf, now);
+		size -= now;
+		len += now;
+	}
+
+	print_digest(d);
+	printf("  %s\t0x%08lx ... 0x%08lx\n", filename, start, start + len);
+
+out_free:
+	free(buf);
+out:
+	close(fd);
+
+	return ret;
+}
+
+static int do_digest(struct command *cmdtp, int argc, char *argv[])
+{
+	char algorithm[7];
+	struct digest *d;
+
+	/* digest algoritm is command name without "sum" */
+	strlcpy(algorithm, cmdtp->name,
+			strstr(cmdtp->name, "sum") + 1 - cmdtp->name);
+	d = digest_get_by_name(algorithm);
+	BUG_ON(!d);
+
+	if (argc < 2)
+		return COMMAND_ERROR_USAGE;
+
+	argv++;
+	while (*argv) {
+		char *filename = "/dev/mem";
+		ulong start = 0, size = ~0;
+
+		/* arguments are either file, file+area or area */
+		if (parse_area_spec(*argv, &start, &size)) {
+			filename = *argv;
+			if (argv[1] && !parse_area_spec(argv[1], &start, &size)) {
+				argv++;
+			}
+		}
+
+		if (file_digest(d, filename, start, size) < 0)
+			return 1;
+
+		argv++;
+	}
+
+	return 0;
+}
+
+#ifdef CONFIG_CMD_MD5SUM
+
+BAREBOX_CMD_HELP_START(md5sum)
+BAREBOX_CMD_HELP_USAGE("md5sum [[FILE] [AREA]]...\n")
+BAREBOX_CMD_HELP_SHORT("Calculate a md5 checksum of a memory area.\n")
+BAREBOX_CMD_HELP_END
+
+BAREBOX_CMD_START(md5sum)
+	.cmd		= do_digest,
+	.usage		= "md5 checksum calculation",
+	BAREBOX_CMD_HELP(cmd_md5sum_help)
+BAREBOX_CMD_END
+
+#endif /* CMD_CMD_MD5SUM */
+
+#ifdef CONFIG_CMD_SHA1SUM
+
+BAREBOX_CMD_HELP_START(sha1sum)
+BAREBOX_CMD_HELP_USAGE("sha1sum [[FILE] [AREA]]...\n")
+BAREBOX_CMD_HELP_SHORT("Calculate a sha1 checksum of a memory area.\n")
+BAREBOX_CMD_HELP_END
+
+BAREBOX_CMD_START(sha1sum)
+	.cmd		= do_digest,
+	.usage		= "sha1 checksum calculation",
+	BAREBOX_CMD_HELP(cmd_sha1sum_help)
+BAREBOX_CMD_END
+
+#endif /* CMD_CMD_SHA1SUM */
+
+#ifdef CONFIG_CMD_SHA256SUM
+
+BAREBOX_CMD_HELP_START(sha256sum)
+BAREBOX_CMD_HELP_USAGE("sha256sum [[FILE] [AREA]]...\n")
+BAREBOX_CMD_HELP_SHORT("Calculate a sha256 checksum of a memory area.\n")
+BAREBOX_CMD_HELP_END
+
+BAREBOX_CMD_START(sha256sum)
+	.cmd		= do_digest,
+	.usage		= "sha256 checksum calculation",
+	BAREBOX_CMD_HELP(cmd_sha256sum_help)
+BAREBOX_CMD_END
+
+#endif /* CMD_CMD_SHA256SUM */
-- 
1.7.4.4


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] commands: add md5/sha1/sha256sum commands using the digest api
  2011-05-17 12:10 [PATCH] commands: add md5/sha1/sha256sum commands using the digest api Peter Korsgaard
@ 2011-05-17 12:30 ` Jean-Christophe PLAGNIOL-VILLARD
  2011-05-17 13:10   ` Peter Korsgaard
  0 siblings, 1 reply; 5+ messages in thread
From: Jean-Christophe PLAGNIOL-VILLARD @ 2011-05-17 12:30 UTC (permalink / raw)
  To: Peter Korsgaard; +Cc: barebox

> +static void print_digest(struct digest *d)
> +{
> +	unsigned char *data;
> +	int i;
> +
> +	data = xmalloc(d->length);
hang here no
please use malloc it's a command we must not hang if out of mem
just because we use a digest command
> +	d->final(d, data);
> +
> +	for (i=0; i<d->length; i++)
> +		printf("%02x", data[i]);
> +
> +	free(data);
> +}
> +
> +static int file_digest(struct digest *d, char *filename,
> +					   ulong start, ulong size)
> +{
> +	ulong len = 0;
> +	int fd, now, ret = 0;
> +	char *buf;
> +
> +	d->init(d);
> +
> +	fd = open(filename, O_RDONLY);
> +	if (fd < 0) {
> +		printf("open %s: %s\n", filename, errno_str());
> +		return fd;
> +	}
> +
> +	if (start > 0) {
> +		ret = lseek(fd, start, SEEK_SET);
> +		if (ret == -1) {
> +			perror("lseek");
> +			goto out;
> +		}
> +	}
> +
> +	buf = xmalloc(4096);
ditto here
> +
> +	while (size) {
> +		now = min((ulong)4096, size);
> +		now = read(fd, buf, now);
> +		if (now < 0) {
> +			ret = now;
> +			perror("read");
> +			goto out_free;
> +		}
> +		if (!now)
> +			break;
> +
> +		d->update(d, buf, now);
> +		size -= now;
> +		len += now;
> +	}
> +
> +	print_digest(d);
> +	printf("  %s\t0x%08lx ... 0x%08lx\n", filename, start, start + len);
> +
> +out_free:
> +	free(buf);
> +out:
> +	close(fd);
> +
> +	return ret;
> +}
> +
> +static int do_digest(struct command *cmdtp, int argc, char *argv[])
> +{
> +	char algorithm[7];
> +	struct digest *d;
> +
> +	/* digest algoritm is command name without "sum" */
> +	strlcpy(algorithm, cmdtp->name,
> +			strstr(cmdtp->name, "sum") + 1 - cmdtp->name);
can we do more simple?
> +	d = digest_get_by_name(algorithm);
> +	BUG_ON(!d);
> +
> +	if (argc < 2)
> +		return COMMAND_ERROR_USAGE;
> +
> +	argv++;
> +	while (*argv) {
> +		char *filename = "/dev/mem";
> +		ulong start = 0, size = ~0;
do we really need to declare this here?
and /dev/mem as default

if yes for /dev/mem as default this should be documented in the help at least
> +
> +		/* arguments are either file, file+area or area */
> +		if (parse_area_spec(*argv, &start, &size)) {
> +			filename = *argv;
> +			if (argv[1] && !parse_area_spec(argv[1], &start, &size)) {
> +				argv++;
> +			}
> +		}
> +
> +		if (file_digest(d, filename, start, size) < 0)
> +			return 1;
do we really need to stop if ine of them is not availlable
and we should check the getc to be able to interrupt it

Best Regards,
J.

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] commands: add md5/sha1/sha256sum commands using the digest api
  2011-05-17 12:30 ` Jean-Christophe PLAGNIOL-VILLARD
@ 2011-05-17 13:10   ` Peter Korsgaard
  2011-05-17 17:09     ` Sascha Hauer
  0 siblings, 1 reply; 5+ messages in thread
From: Peter Korsgaard @ 2011-05-17 13:10 UTC (permalink / raw)
  To: Jean-Christophe PLAGNIOL-VILLARD; +Cc: barebox

>>>>> "Jean-Christophe" == Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com> writes:

Hi,

 >> +static void print_digest(struct digest *d)
 >> +{
 >> +	unsigned char *data;
 >> +	int i;
 >> +
 >> +	data = xmalloc(d->length);

 Jean-Christophe> hang here no
 Jean-Christophe> please use malloc it's a command we must not hang if out of mem
 Jean-Christophe> just because we use a digest command

Ok. This is cutnpaste from the crc command though. A quick look at
commands shows that others do the same:

git grep xmalloc commands/
commands/bootm.c:               handle->data = xmalloc(len);
commands/cat.c: buf = xmalloc(BUFSIZE);
commands/crc.c: buf = xmalloc(4096);
commands/digest.c:      data = xmalloc(d->length);
commands/digest.c:      buf = xmalloc(4096);
commands/i2c.c: buf = xmalloc(count);
commands/i2c.c: buf = xmalloc(count);
commands/mem.c: rw_buf1 = xmalloc(RW_BUF_SIZE);
commands/mem.c: buf = xmalloc(RW_BUF_SIZE);


 >> +static int do_digest(struct command *cmdtp, int argc, char *argv[])
 >> +{
 >> +	char algorithm[7];
 >> +	struct digest *d;
 >> +
 >> +	/* digest algoritm is command name without "sum" */
 >> +	strlcpy(algorithm, cmdtp->name,
 >> +			strstr(cmdtp->name, "sum") + 1 - cmdtp->name);

 Jean-Christophe> can we do more simple?

Maybe. I wanted something automatic rather than a series of strcmp
checks, but feel free to suggest something else.


 >> +	d = digest_get_by_name(algorithm);
 >> +	BUG_ON(!d);
 >> +
 >> +	if (argc < 2)
 >> +		return COMMAND_ERROR_USAGE;
 >> +
 >> +	argv++;
 >> +	while (*argv) {
 >> +		char *filename = "/dev/mem";
 >> +		ulong start = 0, size = ~0;

 Jean-Christophe> do we really need to declare this here?
 Jean-Christophe> and /dev/mem as default

Yes, or rather you need to initialize it for each iteration of the
loop. We could move the declaration up to the beginning of the function,
but as they are only used inside the loop it imho makes more sense to
put it here.

 Jean-Christophe> if yes for /dev/mem as default this should be documented in the help at least

Why? all the memory commands do that (md/mw/crc32).

 >> +
 >> +		/* arguments are either file, file+area or area */
 >> +		if (parse_area_spec(*argv, &start, &size)) {
 >> +			filename = *argv;
 >> +			if (argv[1] && !parse_area_spec(argv[1], &start, &size)) {
 >> +				argv++;
 >> +			}
 >> +		}
 >> +
 >> +		if (file_digest(d, filename, start, size) < 0)
 >> +			return 1;

 Jean-Christophe> do we really need to stop if ine of them is not availlable

I don't feel strongly about it, but it seems the simplest solution.

 Jean-Christophe> and we should check the getc to be able to interrupt it

crc doesn't do that either, but ok - I can add a ctrlc() check in the
main loop.

Thanks for the review.

-- 
Bye, Peter Korsgaard

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] commands: add md5/sha1/sha256sum commands using the digest api
  2011-05-17 13:10   ` Peter Korsgaard
@ 2011-05-17 17:09     ` Sascha Hauer
  2011-05-17 20:05       ` Peter Korsgaard
  0 siblings, 1 reply; 5+ messages in thread
From: Sascha Hauer @ 2011-05-17 17:09 UTC (permalink / raw)
  To: Peter Korsgaard; +Cc: barebox

On Tue, May 17, 2011 at 03:10:38PM +0200, Peter Korsgaard wrote:
> >>>>> "Jean-Christophe" == Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com> writes:
> 
> Hi,
> 
>  >> +static void print_digest(struct digest *d)
>  >> +{
>  >> +	unsigned char *data;
>  >> +	int i;
>  >> +
>  >> +	data = xmalloc(d->length);
> 
>  Jean-Christophe> hang here no
>  Jean-Christophe> please use malloc it's a command we must not hang if out of mem
>  Jean-Christophe> just because we use a digest command
> 
> Ok. This is cutnpaste from the crc command though. A quick look at
> commands shows that others do the same:
> 
> git grep xmalloc commands/
> commands/bootm.c:               handle->data = xmalloc(len);
> commands/cat.c: buf = xmalloc(BUFSIZE);
> commands/crc.c: buf = xmalloc(4096);
> commands/digest.c:      data = xmalloc(d->length);
> commands/digest.c:      buf = xmalloc(4096);
> commands/i2c.c: buf = xmalloc(count);
> commands/i2c.c: buf = xmalloc(count);
> commands/mem.c: rw_buf1 = xmalloc(RW_BUF_SIZE);
> commands/mem.c: buf = xmalloc(RW_BUF_SIZE);

And I am perfectly fine with this at least for fixed small length
allocations. And I consider 4096 bytes small enough.

> 
> 
>  >> +static int do_digest(struct command *cmdtp, int argc, char *argv[])
>  >> +{
>  >> +	char algorithm[7];
>  >> +	struct digest *d;
>  >> +
>  >> +	/* digest algoritm is command name without "sum" */
>  >> +	strlcpy(algorithm, cmdtp->name,
>  >> +			strstr(cmdtp->name, "sum") + 1 - cmdtp->name);
> 
>  Jean-Christophe> can we do more simple?
> 
> Maybe. I wanted something automatic rather than a series of strcmp
> checks, but feel free to suggest something else.

You could use three different functions called by the command
descriptors and pass a string with the digest name to do_digest.

> 
> 
>  >> +	d = digest_get_by_name(algorithm);
>  >> +	BUG_ON(!d);
>  >> +
>  >> +	if (argc < 2)
>  >> +		return COMMAND_ERROR_USAGE;
>  >> +
>  >> +	argv++;
>  >> +	while (*argv) {
>  >> +		char *filename = "/dev/mem";
>  >> +		ulong start = 0, size = ~0;
> 
>  Jean-Christophe> do we really need to declare this here?
>  Jean-Christophe> and /dev/mem as default
> 
> Yes, or rather you need to initialize it for each iteration of the
> loop. We could move the declaration up to the beginning of the function,
> but as they are only used inside the loop it imho makes more sense to
> put it here.
> 
>  Jean-Christophe> if yes for /dev/mem as default this should be documented in the help at least
> 
> Why? all the memory commands do that (md/mw/crc32).
> 
>  >> +
>  >> +		/* arguments are either file, file+area or area */
>  >> +		if (parse_area_spec(*argv, &start, &size)) {
>  >> +			filename = *argv;
>  >> +			if (argv[1] && !parse_area_spec(argv[1], &start, &size)) {
>  >> +				argv++;
>  >> +			}
>  >> +		}
>  >> +
>  >> +		if (file_digest(d, filename, start, size) < 0)
>  >> +			return 1;
> 
>  Jean-Christophe> do we really need to stop if ine of them is not availlable
> 
> I don't feel strongly about it, but it seems the simplest solution.

How about printing an error and continue? That's what my host md5sum
does.

> 
>  Jean-Christophe> and we should check the getc to be able to interrupt it
> 
> crc doesn't do that either, but ok - I can add a ctrlc() check in the
> main loop.

It's good practice. It's nice being able to interrupt if this command is
accidently being called on a veray large file.

Sascha


-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] commands: add md5/sha1/sha256sum commands using the digest api
  2011-05-17 17:09     ` Sascha Hauer
@ 2011-05-17 20:05       ` Peter Korsgaard
  0 siblings, 0 replies; 5+ messages in thread
From: Peter Korsgaard @ 2011-05-17 20:05 UTC (permalink / raw)
  To: Sascha Hauer; +Cc: barebox

>>>>> "Sascha" == Sascha Hauer <s.hauer@pengutronix.de> writes:

Hi,

 >> commands/mem.c: buf = xmalloc(RW_BUF_SIZE);

 Sascha> And I am perfectly fine with this at least for fixed small length
 Sascha> allocations. And I consider 4096 bytes small enough.

Ok, good.

 >> Maybe. I wanted something automatic rather than a series of strcmp
 >> checks, but feel free to suggest something else.

 Sascha> You could use three different functions called by the command
 Sascha> descriptors and pass a string with the digest name to do_digest.

Ok, will change.

 Jean-Christophe> do we really need to stop if ine of them is not availlable

 >> I don't feel strongly about it, but it seems the simplest solution.

 Sascha> How about printing an error and continue? That's what my host md5sum
 Sascha> does.

Ok, will change.

 Jean-Christophe> and we should check the getc to be able to interrupt it
 >> 
 >> crc doesn't do that either, but ok - I can add a ctrlc() check in the
 >> main loop.

 Sascha> It's good practice. It's nice being able to interrupt if this
 Sascha> command is accidently being called on a veray large file.

Ok, will change.

I'll send a v2 shortly.

-- 
Bye, Peter Korsgaard

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2011-05-17 20:05 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-05-17 12:10 [PATCH] commands: add md5/sha1/sha256sum commands using the digest api Peter Korsgaard
2011-05-17 12:30 ` Jean-Christophe PLAGNIOL-VILLARD
2011-05-17 13:10   ` Peter Korsgaard
2011-05-17 17:09     ` Sascha Hauer
2011-05-17 20:05       ` Peter Korsgaard

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox