Merge "Add support for selecting the RSA key used for signature validation"
diff --git a/arch/arm/lib/bootb.c b/arch/arm/lib/bootb.c
index 3ff3c5e..66ba42c 100644
--- a/arch/arm/lib/bootb.c
+++ b/arch/arm/lib/bootb.c
@@ -8,11 +8,13 @@
 #include <malloc.h>
 #include <secure_boot.h>
 #include <sha1.h>
+#include <rsa_public_key.h>
 #include <rsa_verify.h>
 #include <xyzModem.h>
 #include <mach/comcerto-2000.h>
 #include <mach/gpio.h>
 #include <asm/io.h>
+#include <board_id.h>
 
 #define ULOADER_PART_SIZE 0x20000 /* 128 KB */
 #define BAREBOX_PART_SIZE 0x80000
@@ -129,6 +131,7 @@
 
 static int _verify_image(u8 *image_ptr, u32 max_image_len) {
 	sha1_context ctx;
+	const struct rsa_public_key *public_key = NULL;
 	u8 *sig, hash[20];
 	u32 image_len, sig_offset;
 
@@ -151,7 +154,12 @@
 	image_ptr += sig_offset;
 	sig = image_ptr;
 
-	return rsa_verify(sig, 256, hash);
+	if (rsa_get_public_key(OPTIMUS_BOARD_ID, &public_key) != 0) {
+		printf("ERROR: could not verify barebox image (no public key)\n");
+		return -1;
+	}
+
+	return rsa_verify(public_key, sig, 256, hash);
 }
 
 static int verify_image(u8 *image_ptr, u32 max_image_len) {
@@ -245,4 +253,3 @@
 }
 
 late_initcall(do_bootb_barebox);
-
diff --git a/commands/bootm.c b/commands/bootm.c
index bd2f2de..eb48bba 100644
--- a/commands/bootm.c
+++ b/commands/bootm.c
@@ -43,10 +43,12 @@
 #include <rtc.h>
 #include <init.h>
 #include <asm-generic/memory_layout.h>
+#include <rsa_public_key.h>
 #include <rsa_verify.h>
 #include <sha1.h>
 #include <secure_boot.h>
 #include <antirebootloop.h>
+#include <board_id.h>
 
 #ifdef CONFIG_NAND_COMCERTO_ECC_HW_BCH
 extern uint32_t temp_nand_ecc_errors[];
@@ -314,6 +316,8 @@
 		}
 
 		if (secure_boot) {
+			const struct rsa_public_key *public_key = NULL;
+
 			/* Finish off the SHA-1 hash. */
 			sha1_update(&ctx, handle->data, len);
 			sha1_update(&ctx, verity_table, verity_table_len);
@@ -327,7 +331,12 @@
 				goto err_out;
 			}
 
-			if (rsa_verify(sig, SB_SIG_LEN, hash) != 0) {
+			if (rsa_get_public_key(OPTIMUS_BOARD_ID, &public_key) != 0) {
+				printf("Could not get public key!\n");
+				goto err_out;
+			}
+
+			if (rsa_verify(public_key, sig, SB_SIG_LEN, hash) != 0) {
 				printf("Authentication failed!\n");
 				goto err_out;
 			}
diff --git a/include/rsa_public_key.h b/include/rsa_public_key.h
index 7a98218..71a0825 100644
--- a/include/rsa_public_key.h
+++ b/include/rsa_public_key.h
@@ -1,9 +1,3 @@
-/*
- * Automatically generated from generate_public_key_code.c
- *
- * DO NOT EDIT.
- */
-
 #ifndef _RSA_PUBLIC_KEY_H
 #define _RSA_PUBLIC_KEY_H
 
@@ -11,32 +5,18 @@
 
 #define KEY_LEN_WORDS 64
 
-uint32_t n0inv = 324625445u;
-uint32_t modulus[] = {
-	0xdd47e853, 0xcc40a072, 0xccc006f4, 0xc941d763, 0x8f53aa97, 0x26f1e34a,
-	0xb476f79a, 0xf4aaaaaa, 0x676ae350, 0xd8b0d648, 0x18fc6347, 0x984bb7d3,
-	0xa894b4a0, 0x51ea64c3, 0xeda9ea3c, 0xdcff20c7, 0x88afc95f, 0xa485fce7,
-	0xd7010b97, 0x6e821430, 0xf836bbda, 0x004b61fe, 0xcddcc51a, 0x8e2f01f0,
-	0x92647f40, 0xb60cc2e2, 0x570c6692, 0x40e51f0a, 0x34e9036f, 0x6b56ad55,
-	0xe4d044e4, 0x2d32bd77, 0xfed334b5, 0x7505311f, 0x98f0fc46, 0xa557619e,
-	0xb1158093, 0xf3a785c1, 0xf6e77d38, 0xe0e29c9b, 0x3aba8b7f, 0x212ee1f4,
-	0x636549c6, 0x5bc9597b, 0xf2f35938, 0xf0ab94b7, 0x63519a73, 0x62dd79e6,
-	0x3e0863f8, 0xf9d67dab, 0x2dbf66b7, 0x45bb69e6, 0xdc3836bb, 0xd253d7f4,
-	0x975d5f43, 0x40eac67c, 0xd27139fa, 0xb2c73104, 0xced1c1f2, 0x7353f693,
-	0xee23ed71, 0xc710fdf4, 0x330f3b81, 0xb4a49e97
+/**
+ * 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 {
+	uint32_t n0inv; /* -1 / modulus[0] mod 2^32 */
+	uint32_t modulus[64];      /* modulus as little endian array */
+	uint32_t rr[64];   /* R^2 as little endian array */
 };
-uint32_t rr[] = {
-	0xc416ec5a, 0x8f35e335, 0x7860fdb6, 0xe3dd9018, 0xb021e1a8, 0x950621cb,
-	0xb4d3c3e5, 0xe52c0288, 0x25366c47, 0xae481186, 0x8f4f42e4, 0x5203857d,
-	0x60517eb4, 0xa49474c0, 0x952bdc12, 0xbdba6b4b, 0xac90fe1d, 0xbf7e29f9,
-	0x41fb4116, 0xc2b9ca56, 0xf48e1cbd, 0xe7f43887, 0xebdf65f6, 0x694773f6,
-	0x1efd33be, 0x4d7c0c9d, 0xd01b12f9, 0xde65788a, 0x93db7132, 0x8a8e23b1,
-	0x0faab0b6, 0x7fd78d30, 0xe7e04e64, 0xdd0b2eab, 0xa93630d2, 0x07928be0,
-	0x4ff324a5, 0x494b52da, 0xbed79044, 0x93d5c5b6, 0xdfb6b89b, 0x3c0ad0f5,
-	0xdfaf19b6, 0x07d4e67f, 0xba2fc62a, 0x58697a86, 0x1c973e7f, 0x66a26c99,
-	0x45a0ded5, 0x4f69d633, 0xbe326828, 0xd9d31655, 0x699b6a54, 0x2cb1ee8b,
-	0x69dcbbc0, 0x9469b4fa, 0xf3b23e6b, 0x886ec86a, 0x2e9410a9, 0xa41074cf,
-	0xa4c4ca4f, 0xd3ec5963, 0xf36f1929, 0x22bf4a0b
-};
+
+int rsa_get_public_key(int board_id, const struct rsa_public_key **key);
 
 #endif
diff --git a/include/rsa_verify.h b/include/rsa_verify.h
index fc7a89b..6c277f3 100644
--- a/include/rsa_verify.h
+++ b/include/rsa_verify.h
@@ -31,16 +31,18 @@
 #define _RSA_VERIFY_H
 
 #include <common.h>
+#include <rsa_public_key.h>
 
 /**
  * rsa_verify() - Verifies a RSA PKCS1.5 signature against a hash.
  *
+ * @key:	The RSA public key
  * @sig:	The RSA signature
  * @sig_len:	The signature length
  * @hash:	The hash to compare against
  * @return:	0 if verified, -ve on error
  */
-int rsa_verify(uint8_t *sig, uint32_t sig_len, uint8_t hash[20]);
+int rsa_verify(const struct rsa_public_key * key, uint8_t *sig,
+	uint32_t sig_len, uint8_t hash[20]);
 
 #endif
-
diff --git a/lib/rsa/Makefile b/lib/rsa/Makefile
index 3e63350..b9e452c 100644
--- a/lib/rsa/Makefile
+++ b/lib/rsa/Makefile
@@ -1 +1 @@
-obj-$(CONFIG_RSA_VERIFY)	+= rsa_verify.o
+obj-$(CONFIG_RSA_VERIFY)	+= rsa_verify.o rsa_public_keys.o
diff --git a/lib/rsa/rsa_public_keys.c b/lib/rsa/rsa_public_keys.c
new file mode 100644
index 0000000..a23eb19
--- /dev/null
+++ b/lib/rsa/rsa_public_keys.c
@@ -0,0 +1,66 @@
+#include <common.h>
+#include <stdint.h>
+#include <rsa_public_key.h>
+#include <board_id.h>
+
+#define MAX_BOARD_ID	SIDESWIPE_BOARD_ID
+
+static int board_id_to_key_index[] = {
+	0, /* OPTIMUS_BOARD_ID */
+	0, /* SIDESWIPE_BOARD_ID */
+};
+
+/*
+ * The keys are generated from generate_public_key_code.c
+ */
+static const struct rsa_public_key public_keys[] = {
+	/* Optimus / Sideswipe */
+	{ .n0inv = 324625445u,
+	  .modulus = {
+			0xdd47e853, 0xcc40a072, 0xccc006f4, 0xc941d763, 0x8f53aa97, 0x26f1e34a,
+			0xb476f79a, 0xf4aaaaaa, 0x676ae350, 0xd8b0d648, 0x18fc6347, 0x984bb7d3,
+			0xa894b4a0, 0x51ea64c3, 0xeda9ea3c, 0xdcff20c7, 0x88afc95f, 0xa485fce7,
+			0xd7010b97, 0x6e821430, 0xf836bbda, 0x004b61fe, 0xcddcc51a, 0x8e2f01f0,
+			0x92647f40, 0xb60cc2e2, 0x570c6692, 0x40e51f0a, 0x34e9036f, 0x6b56ad55,
+			0xe4d044e4, 0x2d32bd77, 0xfed334b5, 0x7505311f, 0x98f0fc46, 0xa557619e,
+			0xb1158093, 0xf3a785c1, 0xf6e77d38, 0xe0e29c9b, 0x3aba8b7f, 0x212ee1f4,
+			0x636549c6, 0x5bc9597b, 0xf2f35938, 0xf0ab94b7, 0x63519a73, 0x62dd79e6,
+			0x3e0863f8, 0xf9d67dab, 0x2dbf66b7, 0x45bb69e6, 0xdc3836bb, 0xd253d7f4,
+			0x975d5f43, 0x40eac67c, 0xd27139fa, 0xb2c73104, 0xced1c1f2, 0x7353f693,
+			0xee23ed71, 0xc710fdf4, 0x330f3b81, 0xb4a49e97
+		},
+	  .rr = {
+			0xc416ec5a, 0x8f35e335, 0x7860fdb6, 0xe3dd9018, 0xb021e1a8, 0x950621cb,
+			0xb4d3c3e5, 0xe52c0288, 0x25366c47, 0xae481186, 0x8f4f42e4, 0x5203857d,
+			0x60517eb4, 0xa49474c0, 0x952bdc12, 0xbdba6b4b, 0xac90fe1d, 0xbf7e29f9,
+			0x41fb4116, 0xc2b9ca56, 0xf48e1cbd, 0xe7f43887, 0xebdf65f6, 0x694773f6,
+			0x1efd33be, 0x4d7c0c9d, 0xd01b12f9, 0xde65788a, 0x93db7132, 0x8a8e23b1,
+			0x0faab0b6, 0x7fd78d30, 0xe7e04e64, 0xdd0b2eab, 0xa93630d2, 0x07928be0,
+			0x4ff324a5, 0x494b52da, 0xbed79044, 0x93d5c5b6, 0xdfb6b89b, 0x3c0ad0f5,
+			0xdfaf19b6, 0x07d4e67f, 0xba2fc62a, 0x58697a86, 0x1c973e7f, 0x66a26c99,
+			0x45a0ded5, 0x4f69d633, 0xbe326828, 0xd9d31655, 0x699b6a54, 0x2cb1ee8b,
+			0x69dcbbc0, 0x9469b4fa, 0xf3b23e6b, 0x886ec86a, 0x2e9410a9, 0xa41074cf,
+			0xa4c4ca4f, 0xd3ec5963, 0xf36f1929, 0x22bf4a0b
+		}
+	},
+};
+
+static int get_key_id(int board_id) {
+	if ((board_id < 0) || (board_id > MAX_BOARD_ID)) {
+		printf("Invalid board ID: %d\n", board_id);
+		return -1;
+	}
+
+	return board_id_to_key_index[board_id];
+}
+
+int rsa_get_public_key(int board_id, const struct rsa_public_key **key) {
+	int index = get_key_id(board_id);
+	if (index < 0) {
+		return -1;
+	}
+
+	*key = &public_keys[index];
+
+	return 0;
+}
diff --git a/lib/rsa/rsa_verify.c b/lib/rsa/rsa_verify.c
index b756b68..6ecf838 100644
--- a/lib/rsa/rsa_verify.c
+++ b/lib/rsa/rsa_verify.c
@@ -30,22 +30,8 @@
 #include <sha1.h>
 #include <asm/byteorder.h>
 #include <asm/unaligned.h>
-
-/* The file that contains the public key; autogenerated. */
 #include <rsa_public_key.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 {
-	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 */
-};
-
 #define RSA2048_BYTES	(2048 / 8)
 
 /* This is the maximum key size we support, in bits */
@@ -219,9 +205,9 @@
 	return 0;
 }
 
-int rsa_verify(uint8_t *sig, uint32_t sig_len, uint8_t *hash)
+int rsa_verify(const struct rsa_public_key *key, uint8_t *sig, uint32_t sig_len,
+	uint8_t *hash)
 {
-	struct rsa_public_key key;
 	const uint8_t *padding;
 	int ret, pad_len;
 
@@ -233,13 +219,8 @@
 		return -EIO;
 	}
 
-	/* Set up the public key with the information from the header. */
-	key.n0inv = n0inv;
-	key.modulus = modulus;
-	key.rr = rr;
-
-	if (!sig || !hash) {
-		printf("!sig || !hash\n");
+	if (!key || !sig || !hash) {
+		printf("!key || !sig || !hash\n");
 		ret = -EIO;
 		goto end;
 	}
@@ -268,7 +249,7 @@
 		goto end;
 	}
 
-	ret = pow_mod(&key, buf);
+	ret = pow_mod(key, buf);
 
 	/* Determine padding to use depending on the signature type. */
 	padding = padding_sha1_rsa2048;
@@ -290,4 +271,3 @@
 	free(buf);
 	return ret;
 }
-