* [PATCH v3 09/12] libfdt: Add fdt_find_regions()
[not found] ` <1371161411-2834-1-git-send-email-sjg-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
@ 2013-06-13 22:10 ` Simon Glass
2013-06-26 20:24 ` [U-Boot] [PATCH v3 0/12] Verified boot implementation based on FIT Tom Rini
1 sibling, 0 replies; 3+ messages in thread
From: Simon Glass @ 2013-06-13 22:10 UTC (permalink / raw)
To: U-Boot Mailing List
Cc: Joel A Fernandes, Will Drewry, Wolfgang Denk, Devicetree Discuss,
u-boot-review-hpIqsD4AKlfQT0dZR+AlfA, Bill Richardson,
Randall Spangler, Tom Rini, Vadim Bendebury, Andreas Bäck,
Kees Cook
Add a function to find regions in device tree given a list of nodes to
include and properties to exclude.
See the header file for full documentation.
Signed-off-by: Simon Glass <sjg-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
---
Changes in v3: None
Changes in v2:
- Fix checkpatch checks about parenthesis alignment
include/libfdt.h | 64 +++++++++++++++++++++++++
lib/libfdt/fdt_wip.c | 129 +++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 193 insertions(+)
diff --git a/include/libfdt.h b/include/libfdt.h
index c5ec2ac..765d84f 100644
--- a/include/libfdt.h
+++ b/include/libfdt.h
@@ -1511,4 +1511,68 @@ int fdt_del_node(void *fdt, int nodeoffset);
const char *fdt_strerror(int errval);
+struct fdt_region {
+ int offset;
+ int size;
+};
+
+/**
+ * fdt_find_regions() - find regions in device tree
+ *
+ * Given a list of nodes to include and properties to exclude, find
+ * the regions of the device tree which describe those included parts.
+ *
+ * The intent is to get a list of regions which will be invariant provided
+ * those parts are invariant. For example, if you request a list of regions
+ * for all nodes but exclude the property "data", then you will get the
+ * same region contents regardless of any change to "data" properties.
+ *
+ * This function can be used to produce a byte-stream to send to a hashing
+ * function to verify that critical parts of the FDT have not changed.
+ *
+ * Nodes which are given in 'inc' are included in the region list, as
+ * are the names of the immediate subnodes nodes (but not the properties
+ * or subnodes of those subnodes).
+ *
+ * For eaxample "/" means to include the root node, all root properties
+ * and the FDT_BEGIN_NODE and FDT_END_NODE of all subnodes of /. The latter
+ * ensures that we capture the names of the subnodes. In a hashing situation
+ * it prevents the root node from changing at all Any change to non-excluded
+ * properties, names of subnodes or number of subnodes would be detected.
+ *
+ * When used with FITs this provides the ability to hash and sign parts of
+ * the FIT based on different configurations in the FIT. Then it is
+ * impossible to change anything about that configuration (include images
+ * attached to the configuration), but it may be possible to add new
+ * configurations, new images or new signatures within the existing
+ * framework.
+ *
+ * Adding new properties to a device tree may result in the string table
+ * being extended (if the new property names are different from those
+ * already added). This function can optionally include a region for
+ * the string table so that this can be part of the hash too.
+ *
+ * The device tree header is not included in the list.
+ *
+ * @fdt: Device tree to check
+ * @inc: List of node paths to included
+ * @inc_count: Number of node paths in list
+ * @exc_prop: List of properties names to exclude
+ * @exc_prop_count: Number of properties in exclude list
+ * @region: Returns list of regions
+ * @max_region: Maximum length of region list
+ * @path: Pointer to a temporary string for the function to use for
+ * building path names
+ * @path_len: Length of path, must be large enough to hold the longest
+ * path in the tree
+ * @add_string_tab: 1 to add a region for the string table
+ * @return number of regions in list. If this is >max_regions then the
+ * region array was exhausted. You should increase max_regions and try
+ * the call again.
+ */
+int fdt_find_regions(const void *fdt, char * const inc[], int inc_count,
+ char * const exc_prop[], int exc_prop_count,
+ struct fdt_region region[], int max_regions,
+ char *path, int path_len, int add_string_tab);
+
#endif /* _LIBFDT_H */
diff --git a/lib/libfdt/fdt_wip.c b/lib/libfdt/fdt_wip.c
index 63e67b7..b9e3c4a 100644
--- a/lib/libfdt/fdt_wip.c
+++ b/lib/libfdt/fdt_wip.c
@@ -120,3 +120,132 @@ int fdt_nop_node(void *fdt, int nodeoffset)
endoffset - nodeoffset);
return 0;
}
+
+#define FDT_MAX_DEPTH 32
+
+static int str_in_list(const char *str, char * const list[], int count)
+{
+ int i;
+
+ for (i = 0; i < count; i++)
+ if (!strcmp(list[i], str))
+ return 1;
+
+ return 0;
+}
+
+int fdt_find_regions(const void *fdt, char * const inc[], int inc_count,
+ char * const exc_prop[], int exc_prop_count,
+ struct fdt_region region[], int max_regions,
+ char *path, int path_len, int add_string_tab)
+{
+ int stack[FDT_MAX_DEPTH];
+ char *end;
+ int nextoffset = 0;
+ uint32_t tag;
+ int count = 0;
+ int start = -1;
+ int depth = -1;
+ int want = 0;
+ int base = fdt_off_dt_struct(fdt);
+
+ end = path;
+ *end = '\0';
+ do {
+ const struct fdt_property *prop;
+ const char *name;
+ const char *str;
+ int include = 0;
+ int stop_at = 0;
+ int offset;
+ int len;
+
+ offset = nextoffset;
+ tag = fdt_next_tag(fdt, offset, &nextoffset);
+ stop_at = nextoffset;
+
+ switch (tag) {
+ case FDT_PROP:
+ include = want >= 2;
+ stop_at = offset;
+ prop = fdt_get_property_by_offset(fdt, offset, NULL);
+ str = fdt_string(fdt, fdt32_to_cpu(prop->nameoff));
+ if (str_in_list(str, exc_prop, exc_prop_count))
+ include = 0;
+ break;
+
+ case FDT_NOP:
+ include = want >= 2;
+ stop_at = offset;
+ break;
+
+ case FDT_BEGIN_NODE:
+ depth++;
+ if (depth == FDT_MAX_DEPTH)
+ return -FDT_ERR_BADSTRUCTURE;
+ name = fdt_get_name(fdt, offset, &len);
+ if (end - path + 2 + len >= path_len)
+ return -FDT_ERR_NOSPACE;
+ if (end != path + 1)
+ *end++ = '/';
+ strcpy(end, name);
+ end += len;
+ stack[depth] = want;
+ if (want == 1)
+ stop_at = offset;
+ if (str_in_list(path, inc, inc_count))
+ want = 2;
+ else if (want)
+ want--;
+ else
+ stop_at = offset;
+ include = want;
+ break;
+
+ case FDT_END_NODE:
+ include = want;
+ want = stack[depth--];
+ while (end > path && *--end != '/')
+ ;
+ *end = '\0';
+ break;
+
+ case FDT_END:
+ include = 1;
+ break;
+ }
+
+ if (include && start == -1) {
+ /* Should we merge with previous? */
+ if (count && count <= max_regions &&
+ offset == region[count - 1].offset +
+ region[count - 1].size - base)
+ start = region[--count].offset - base;
+ else
+ start = offset;
+ }
+
+ if (!include && start != -1) {
+ if (count < max_regions) {
+ region[count].offset = base + start;
+ region[count].size = stop_at - start;
+ }
+ count++;
+ start = -1;
+ }
+ } while (tag != FDT_END);
+
+ if (nextoffset != fdt_size_dt_struct(fdt))
+ return -FDT_ERR_BADLAYOUT;
+
+ /* Add a region for the END tag and the string table */
+ if (count < max_regions) {
+ region[count].offset = base + start;
+ region[count].size = nextoffset - start;
+ if (add_string_tab)
+ region[count].size += fdt_size_dt_strings(fdt);
+ }
+ count++;
+
+ return count;
+}
--
1.8.3
^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [U-Boot] [PATCH v3 0/12] Verified boot implementation based on FIT
[not found] ` <1371161411-2834-1-git-send-email-sjg-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
2013-06-13 22:10 ` [PATCH v3 09/12] libfdt: Add fdt_find_regions() Simon Glass
@ 2013-06-26 20:24 ` Tom Rini
1 sibling, 0 replies; 3+ messages in thread
From: Tom Rini @ 2013-06-26 20:24 UTC (permalink / raw)
To: Simon Glass
Cc: Joel A Fernandes, Will Drewry,
u-boot-review-hpIqsD4AKlfQT0dZR+AlfA, U-Boot Mailing List,
Devicetree Discuss, Bill Richardson, Joe Hershberger,
Randall Spangler, Vadim Bendebury, Andreas B??ck, Kees Cook
[-- Attachment #1.1: Type: text/plain, Size: 6411 bytes --]
On Thu, Jun 13, 2013 at 03:09:59PM -0700, Simon Glass wrote:
> This series implemented a verified boot system based around FIT images
> as discussed on the U-Boot mailing list, including on this thread:
>
> http://permalink.gmane.org/gmane.comp.boot-loaders.u-boot/147830
>
> RSA is used to implement the encryption. Images are signed by mkimage
> using private keys created by the user. Public keys are written into
> U-Boot control FDT (CONFIG_OF_CONTROL) for access by bootm etc. at
> run-time. The control FDT must be stored in a secure place where it
> cannot be changed after manufacture. Some notes are provided in the
> documentaion on how this can be achieved. The implementation is fairly
> efficient and fits nicely into U-Boot. FIT plus RSA adds around 18KB
> to SPL size which is manageable on modern SoCs.
>
> When images are loaded, they are verified with the public keys.
>
> It is important to have a test framework for this series. For this, sandbox
> is used, and a script is provided which signs images and gets sandbox to
> load them using a script, to check that all is well.
>
> Rollback prevention has been added in a separate TPM patch. This ensures
> that an attacker cannot boot your system with an old image that has been
> compromised. Support for this is not built into bootm, but instead must
> be scripted in U-Boot. It is possible that a standard scheme for this could
> be devised by adding version number tags to the signing procedure. However
> scripts do provide more flexibility. See the 'tpm' command for more
> information.
>
> Two patches affect libfdt and have material which is not yet upstream in
> that project:
>
> image: Add support for signing of FIT configurations
> libfdt: Add fdt_find_regions()
>
> If these are not desired, then the rest of the series can stand alone,
> just without the configuration-signing feature.
>
> This series requires the 'trace' series since it sits on top of the bootm
> refactor there.
>
> This series is available at:
>
> http://git.denx.de/u-boot-x86.git
>
> in the branch 'vboot'.
>
> Changes in v3:
> - Fix 'compile' typo
> - Rebase to master
> - Use new fdt_first/next_subnode()
>
> Changes in v2:
> - Add sanity checks on key sizes in RSA (improves security)
> - Adjust how signing enable works in image.h
> - Adjust mkimage help to separate out signing options
> - Avoid using malloc in RSA routines (for smaller SPL code size)
> - Build signing support unconditionally in mkimage
> - Fix FDT error handling in fit_image_write_sig()
> - Fix checkpatch checks about parenthesis alignment
> - Fix checkpatch warnings about split strings
> - Fix spelling of multiply in rsa-verify.c
> - Only build RSA support into mkimage if CONFIG_RSA is defined
> - Rebase on previous patches
> - Require CONFIG_FIT_SIGNATURE in image.h for mkimage to support signing
> - Support RSA library version without ERR_remove_thread_state()
> - Tweak tools/Makefile to make image signing optional
> - Update README to fix typos
> - Update README to fix typos and clarify some points
> - Use U-Boot's -c option instead of hard-coding a boot script
> - Use stack instead of calloc() within U-Boot's signature verification code
> - gd->fdt_blob is now available on all archs (generic board landed)
>
> Simon Glass (12):
> image: Add signing infrastructure
> image: Support signing of images
> image: Add RSA support for image signing
> mkimage: Add -k option to specify key directory
> mkimage: Add -K to write public keys to an FDT blob
> mkimage: Add -F option to modify an existing .fit file
> mkimage: Add -c option to specify a comment for key signing
> mkimage: Add -r option to specify keys that must be verified
> libfdt: Add fdt_find_regions()
> image: Add support for signing of FIT configurations
> sandbox: config: Enable FIT signatures with RSA
> Add verified boot information and test
>
> Makefile | 1 +
> README | 15 ++
> common/Makefile | 1 +
> common/image-fit.c | 83 ++++--
> common/image-sig.c | 422 +++++++++++++++++++++++++++++++
> config.mk | 1 +
> doc/mkimage.1 | 73 +++++-
> doc/uImage.FIT/sign-configs.its | 45 ++++
> doc/uImage.FIT/sign-images.its | 42 ++++
> doc/uImage.FIT/signature.txt | 382 ++++++++++++++++++++++++++++
> doc/uImage.FIT/verified-boot.txt | 104 ++++++++
> include/configs/sandbox.h | 2 +
> include/image.h | 165 +++++++++++-
> include/libfdt.h | 64 +++++
> include/rsa.h | 108 ++++++++
> lib/libfdt/fdt_wip.c | 129 ++++++++++
> lib/rsa/Makefile | 48 ++++
> lib/rsa/rsa-sign.c | 460 ++++++++++++++++++++++++++++++++++
> lib/rsa/rsa-verify.c | 385 ++++++++++++++++++++++++++++
> test/vboot/.gitignore | 3 +
> test/vboot/sandbox-kernel.dts | 7 +
> test/vboot/sandbox-u-boot.dts | 7 +
> test/vboot/sign-configs.its | 45 ++++
> test/vboot/sign-images.its | 42 ++++
> test/vboot/vboot_test.sh | 126 ++++++++++
> tools/Makefile | 19 +-
> tools/fit_image.c | 44 +++-
> tools/image-host.c | 527 ++++++++++++++++++++++++++++++++++++++-
> tools/mkimage.c | 36 ++-
> tools/mkimage.h | 4 +
> 30 files changed, 3333 insertions(+), 57 deletions(-)
> create mode 100644 common/image-sig.c
> create mode 100644 doc/uImage.FIT/sign-configs.its
> create mode 100644 doc/uImage.FIT/sign-images.its
> create mode 100644 doc/uImage.FIT/signature.txt
> create mode 100644 doc/uImage.FIT/verified-boot.txt
> create mode 100644 include/rsa.h
> create mode 100644 lib/rsa/Makefile
> create mode 100644 lib/rsa/rsa-sign.c
> create mode 100644 lib/rsa/rsa-verify.c
> create mode 100644 test/vboot/.gitignore
> create mode 100644 test/vboot/sandbox-kernel.dts
> create mode 100644 test/vboot/sandbox-u-boot.dts
> create mode 100644 test/vboot/sign-configs.its
> create mode 100644 test/vboot/sign-images.its
> create mode 100755 test/vboot/vboot_test.sh
Applied to u-boot/master, thanks!
--
Tom
[-- Attachment #1.2: Digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]
[-- Attachment #2: Type: text/plain, Size: 192 bytes --]
_______________________________________________
devicetree-discuss mailing list
devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ@public.gmane.org
https://lists.ozlabs.org/listinfo/devicetree-discuss
^ permalink raw reply [flat|nested] 3+ messages in thread