[U-Boot] [U-Boot v2] [PATCH] rsa: add a more flexible way to support different hash algorithms (e.g. sha256)

2013-11-27 Thread andr...@oetken.name
As proposed by Heiko I made some small changes and verified the patch with the
checkpatch-script.
 
 
From 169f40e72fceb222bb15dd59c1337f42371e97a5 Mon Sep 17 00:00:00 2001
From: Andreas Oetken andreas.oet...@siemens.com
Date: Wed, 27 Nov 2013 13:09:19 +0100
Subject: [PATCH] Added rsa-sha256 support.


Signed-off-by: Andreas Oetken andreas.oet...@siemens.com
---
 common/image-sig.c          |   33 +
 include/image.h             |   20 +++-
 include/rsa-checksum.h      |   25 ++
 include/rsa.h               |   17 +++
 lib/rsa/Makefile            |    2 +-
 lib/rsa/rsa-checksum.c      |  108 +++
 lib/rsa/rsa-sign.c          |   10 ++--
 lib/rsa/rsa-verify.c        |   80 +---
 test/vboot/sign-configs.its |    2 +-
 test/vboot/sign-images.its  |    2 +-
 10 files changed, 233 insertions(+), 66 deletions(-)
 create mode 100644 include/rsa-checksum.h
 create mode 100644 lib/rsa/rsa-checksum.c

diff --git a/common/image-sig.c b/common/image-sig.c
index 973b06d..5ce6b80 100644
--- a/common/image-sig.c
+++ b/common/image-sig.c
@@ -14,15 +14,48 @@ DECLARE_GLOBAL_DATA_PTR;
 #endif /* !USE_HOSTCC*/
 #include image.h
 #include rsa.h
+#include rsa-checksum.h
 
 #define IMAGE_MAX_HASHED_NODES         100
 
+
+struct image_hash_algo image_hash_algos[] = {
+       {
+               sha1,
+               SHA1_SUM_LEN,
+#if IMAGE_ENABLE_SIGN
+               EVP_sha1,
+#else
+               sha1_calculate,
+               padding_sha1_rsa2048,
+#endif
+       },
+       {
+               sha256,
+               SHA256_SUM_LEN,
+#if IMAGE_ENABLE_SIGN
+               EVP_sha256,
+#else
+               sha256_calculate,
+               padding_sha256_rsa2048,
+#endif
+       }
+};
+
 struct image_sig_algo image_sig_algos[] = {
        {
                sha1,rsa2048,
                rsa_sign,
                rsa_add_verify_data,
                rsa_verify,
+               image_hash_algos[0],
+       },
+       {
+               sha256,rsa2048,
+               rsa_sign,
+               rsa_add_verify_data,
+               rsa_verify,
+               image_hash_algos[1],
        }
 };
 
diff --git a/include/image.h b/include/image.h
index ee6eb8d..1f7ca61 100644
--- a/include/image.h
+++ b/include/image.h
@@ -822,7 +822,8 @@ int calculate_hash(const void *data, int data_len, const
char *algo,
 # ifdef USE_HOSTCC
 #  define IMAGE_ENABLE_SIGN    1
 #  define IMAGE_ENABLE_VERIFY  0
-#else
+#  include  openssl/evp.h
+# else
 #  define IMAGE_ENABLE_SIGN    0
 #  define IMAGE_ENABLE_VERIFY  1
 # endif
@@ -861,6 +862,20 @@ struct image_region {
        int size;
 };
 
+struct image_hash_algo {
+       const char *name;
+       const int checksum_len;
+#if IMAGE_ENABLE_SIGN
+       EVP_MD *(*calculate)(void);
+#else
+#if IMAGE_ENABLE_VERIFY
+       void (*calculate)(const struct image_region region[],
+                         int region_count, uint8_t *checksum);
+       const uint8_t *rsa_padding;
+#endif
+#endif
+};
+
 struct image_sig_algo {
        const char *name;               /* Name of algorithm */
 
@@ -911,6 +926,9 @@ struct image_sig_algo {
        int (*verify)(struct image_sign_info *info,
                      const struct image_region region[], int region_count,
                      uint8_t *sig, uint sig_len);
+
+       /* pointer to hash algorithm */
+       struct image_hash_algo *hash_algo;
 };
 
 /**
diff --git a/include/rsa-checksum.h b/include/rsa-checksum.h
new file mode 100644
index 000..d2c6474
--- /dev/null
+++ b/include/rsa-checksum.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2013, Andreas Oetken.
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#ifndef _RSA_CHECKSUM_H
+#define _RSA_CHECKSUM_H
+
+#include errno.h
+#include image.h
+#include sha1.h
+#include sha256.h
+
+#if IMAGE_ENABLE_VERIFY
+extern const uint8_t padding_sha256_rsa2048[];
+extern const uint8_t padding_sha1_rsa2048[];
+
+void sha256_calculate(const struct image_region region[],
+                     int region_count, uint8_t *checksum);
+void sha1_calculate(const struct image_region region[],
+                   int region_count, uint8_t *checksum);
+#endif
+
+#endif
diff --git a/include/rsa.h b/include/rsa.h
index add4c78..12ae443 100644
--- a/include/rsa.h
+++ b/include/rsa.h
@@ -15,6 +15,23 @@
 #include errno.h
 #include image.h
 
+#define RSA2048_BYTES  (2048 / 8)
+
+/**
+ * struct rsa_public_key - holder for a public key
+ *
+ * An RSA public key consists of a modulus (typically called N), the inverse
+ * and R^2, where R is 2^(# key bits).
+ */
+
+struct rsa_public_key {
+       uint len;               /* Length of modulus[] in number of uint32_t */
+       uint32_t n0inv;         /* -1 / modulus[0] mod 2^32 */
+       uint32_t *modulus;      /* modulus as little endian array */
+       uint32_t *rr;           /* R^2 as little endian array */
+};
+
+
 #if IMAGE_ENABLE_SIGN
 /**
  * sign() - calculate and return signature for given 

[U-Boot] [PATCH] rsa: add a more flexible way to support different hash algorithms (e.g. sha256)

2013-11-26 Thread andr...@oetken.name
I currently need support for rsa-sha256 signatures in u-boot and found out that
the code for signatures is not very generic. Thus adding of different
hash-algorithms for rsa-signatures is not easy to do without copy-pasting the
rsa-code. I attached a patch for how I think it could be better and included
support for rsa-sha256. This is a fast first shot.

diff --git a/common/image-sig.c b/common/image-sig.c
index 973b06d..db15cb6 100644
--- a/common/image-sig.c
+++ b/common/image-sig.c
@@ -14,15 +14,48 @@ DECLARE_GLOBAL_DATA_PTR;
 #endif /* !USE_HOSTCC*/
 #include image.h
 #include rsa.h
+#include rsa-checksum.h

 #define IMAGE_MAX_HASHED_NODES100

+
+struct checksum_algo checksum_algos[] = {
+  {
+sha1,
+SHA1_SUM_LEN,
+#if IMAGE_ENABLE_SIGN
+EVP_sha1,
+#else
+sha1_calculate,
+padding_sha1_rsa2048,
+#endif
+  },
+  {
+sha256,
+SHA256_SUM_LEN,
+#if IMAGE_ENABLE_SIGN
+EVP_sha256,
+#else
+sha256_calculate,
+padding_sha256_rsa2048,
+#endif
+  }
+};
+
 struct image_sig_algo image_sig_algos[] = {
 {
 sha1,rsa2048,
 rsa_sign,
 rsa_add_verify_data,
 rsa_verify,
+checksum_algos[0],
+},
+{
+sha256,rsa2048,
+rsa_sign,
+rsa_add_verify_data,
+rsa_verify,
+checksum_algos[1],
 }
 };

diff --git a/include/image.h b/include/image.h
index ee6eb8d..47268aa 100644
--- a/include/image.h
+++ b/include/image.h
@@ -822,7 +822,8 @@ int calculate_hash(const void *data, int data_len, const
char *algo,
 # ifdef USE_HOSTCC
 #  define IMAGE_ENABLE_SIGN1
 #  define IMAGE_ENABLE_VERIFY0
-#else
+#  include  openssl/evp.h
+# else
 #  define IMAGE_ENABLE_SIGN0
 #  define IMAGE_ENABLE_VERIFY1
 # endif
@@ -861,6 +862,22 @@ struct image_region {
 int size;
 };

+#if IMAGE_ENABLE_VERIFY
+# include rsa-checksum.h
+#endif
+struct checksum_algo {
+  const char *name;
+  const int checksum_len;
+#if IMAGE_ENABLE_SIGN
+  EVP_MD *(*calculate)(void);
+#else
+#if IMAGE_ENABLE_VERIFY
+  void (*calculate)(const struct image_region region[], int region_count,
uint8_t * checksum);
+  const uint8_t * rsa_padding;
+#endif
+#endif
+};
+
 struct image_sig_algo {
 const char *name;/* Name of algorithm */

@@ -911,6 +928,10 @@ struct image_sig_algo {
 int (*verify)(struct image_sign_info *info,
   const struct image_region region[], int region_count,
   uint8_t *sig, uint sig_len);
+
+/* pointer to checksum algorithm */
+struct checksum_algo * checksum;
+
 };

 /**
diff --git a/include/rsa-checksum.h b/include/rsa-checksum.h
new file mode 100644
index 000..a318538
--- /dev/null
+++ b/include/rsa-checksum.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2013, Andreas Oetken.
+ *
+ * SPDX-License-Identifier:GPL-2.0+
+ */
+
+#ifndef _RSA_CHECKSUM_H
+#define _RSA_CHECKSUM_H
+
+#include errno.h
+#include image.h
+#include sha1.h
+#include sha256.h
+
+#if IMAGE_ENABLE_VERIFY
+extern const uint8_t padding_sha256_rsa2048[];
+extern const uint8_t padding_sha1_rsa2048[];
+
+void sha256_calculate(const struct image_region region[], int region_count,
uint8_t * checksum);
+void sha1_calculate(const struct image_region region[], int region_count,
uint8_t * checksum);
+#endif
+
+#endif
diff --git a/include/rsa.h b/include/rsa.h
index add4c78..3f6bb2c 100644
--- a/include/rsa.h
+++ b/include/rsa.h
@@ -15,6 +15,22 @@
 #include errno.h
 #include image.h

+
+/**
+ * struct rsa_public_key - holder for a public key
+ *
+ * An RSA public key consists of a modulus (typically called N), the inverse
+ * and R^2, where R is 2^(# key bits).
+ */
+
+struct rsa_public_key {
+uint len;/* Length of modulus[] in number of uint32_t */
+uint32_t n0inv;/* -1 / modulus[0] mod 2^32 */
+uint32_t *modulus;/* modulus as little endian array */
+uint32_t *rr;/* R^2 as little endian array */
+};
+
+
 #if IMAGE_ENABLE_SIGN
 /**
  * sign() - calculate and return signature for given input data
diff --git a/lib/rsa/Makefile b/lib/rsa/Makefile
index decd6e5..bf18cdc 100644
--- a/lib/rsa/Makefile
+++ b/lib/rsa/Makefile
@@ -12,7 +12,7 @@ include $(TOPDIR)/config.mk
 LIB= $(obj)librsa.o

 ifdef CONFIG_FIT_SIGNATURE
-COBJS-$(CONFIG_RSA) += rsa-verify.o
+COBJS-$(CONFIG_RSA) += rsa-verify.o rsa-checksum.o
 endif

 COBJS:= $(sort $(COBJS-y))
diff --git a/lib/rsa/rsa-checksum.c b/lib/rsa/rsa-checksum.c
new file mode 100644
index 000..fca065c
--- /dev/null
+++ b/lib/rsa/rsa-checksum.c
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2013, Andreas Oetken.
+ *
+ * SPDX-License-Identifier:GPL-2.0+
+ */
+
+#include common.h
+#include fdtdec.h
+#include rsa.h
+#include sha1.h
+#include sha256.h
+#include asm/byteorder.h
+#include asm/errno.h
+#include asm/unaligned.h
+
+#define RSA2048_BYTES 256
+
+const uint8_t padding_sha256_rsa2048[RSA2048_BYTES - SHA256_SUM_LEN] = {
+0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff,