static int fit_image_setup_verify(struct image_sign_info *info,
const void *fit, int noffset,
- int required_keynode, char **err_msgp)
+ const void *key_blob, int required_keynode,
+ char **err_msgp)
{
- char *algo_name;
+ const char *algo_name;
const char *padding_name;
if (fdt_totalsize(fit) > CONFIG_VAL(FIT_SIGNATURE_MAX_SIZE)) {
info->checksum = image_get_checksum_algo(algo_name);
info->crypto = image_get_crypto_algo(algo_name);
info->padding = image_get_padding_algo(padding_name);
- info->fdt_blob = gd_fdt_blob();
+ info->fdt_blob = key_blob;
info->required_keynode = required_keynode;
printf("%s:%s", algo_name, info->keyname);
}
int fit_image_check_sig(const void *fit, int noffset, const void *data,
- size_t size, int required_keynode, char **err_msgp)
+ size_t size, const void *key_blob, int required_keynode,
+ char **err_msgp)
{
struct image_sign_info info;
struct image_region region;
int fit_value_len;
*err_msgp = NULL;
- if (fit_image_setup_verify(&info, fit, noffset, required_keynode,
- err_msgp))
+ if (fit_image_setup_verify(&info, fit, noffset, key_blob,
+ required_keynode, err_msgp))
return -1;
if (fit_image_hash_get_value(fit, noffset, &fit_value,
static int fit_image_verify_sig(const void *fit, int image_noffset,
const char *data, size_t size,
- const void *sig_blob, int sig_offset)
+ const void *key_blob, int key_offset)
{
int noffset;
char *err_msg = "";
}
if (!strncmp(name, FIT_SIG_NODENAME,
strlen(FIT_SIG_NODENAME))) {
- ret = fit_image_check_sig(fit, noffset, data,
- size, -1, &err_msg);
+ ret = fit_image_check_sig(fit, noffset, data, size,
+ key_blob, -1, &err_msg);
if (ret) {
puts("- ");
} else {
int fit_image_verify_required_sigs(const void *fit, int image_noffset,
const char *data, size_t size,
- const void *sig_blob, int *no_sigsp)
+ const void *key_blob, int *no_sigsp)
{
int verify_count = 0;
int noffset;
- int sig_node;
+ int key_node;
/* Work out what we need to verify */
*no_sigsp = 1;
- sig_node = fdt_subnode_offset(sig_blob, 0, FIT_SIG_NODENAME);
- if (sig_node < 0) {
+ key_node = fdt_subnode_offset(key_blob, 0, FIT_SIG_NODENAME);
+ if (key_node < 0) {
debug("%s: No signature node found: %s\n", __func__,
- fdt_strerror(sig_node));
+ fdt_strerror(key_node));
return 0;
}
- fdt_for_each_subnode(noffset, sig_blob, sig_node) {
+ fdt_for_each_subnode(noffset, key_blob, key_node) {
const char *required;
int ret;
- required = fdt_getprop(sig_blob, noffset, FIT_KEY_REQUIRED,
+ required = fdt_getprop(key_blob, noffset, FIT_KEY_REQUIRED,
NULL);
if (!required || strcmp(required, "image"))
continue;
ret = fit_image_verify_sig(fit, image_noffset, data, size,
- sig_blob, noffset);
+ key_blob, noffset);
if (ret) {
printf("Failed to verify required signature '%s'\n",
- fit_get_name(sig_blob, noffset, NULL));
+ fit_get_name(key_blob, noffset, NULL));
return ret;
}
verify_count++;
/**
* fit_config_check_sig() - Check the signature of a config
*
+ * Here we are looking at a particular signature that needs verification (here
+ * signature-1):
+ *
+ * configurations {
+ * default = "conf-1";
+ * conf-1 {
+ * kernel = "kernel-1";
+ * fdt = "fdt-1";
+ * signature-1 {
+ * algo = "sha1,rsa2048";
+ * value = <...conf 1 signature...>;
+ * };
+ * };
+ *
* @fit: FIT to check
- * @noffset: Offset of configuration node (e.g. /configurations/conf-1)
- * @required_keynode: Offset in the control FDT of the required key node,
+ * @noffset: Offset of the signature node being checked (e.g.
+ * /configurations/conf-1/signature-1)
+ * @conf_noffset: Offset of configuration node (e.g. /configurations/conf-1)
+ * @key_blob: Blob containing the keys to check against
+ * @required_keynode: Offset in @key_blob of the required key node,
* if any. If this is given, then the configuration wil not
* pass verification unless that key is used. If this is
* -1 then any signature will do.
- * @conf_noffset: Offset of the configuration subnode being checked (e.g.
- * /configurations/conf-1/kernel)
* @err_msgp: In the event of an error, this will be pointed to a
* help error string to display to the user.
* Return: 0 if all verified ok, <0 on error
*/
-static int fit_config_check_sig(const void *fit, int noffset,
- int required_keynode, int conf_noffset,
+static int fit_config_check_sig(const void *fit, int noffset, int conf_noffset,
+ const void *key_blob, int required_keynode,
char **err_msgp)
{
static char * const exc_prop[] = {
- "data",
- "data-size",
- "data-position",
- "data-offset"
+ FIT_DATA_PROP,
+ FIT_DATA_SIZE_PROP,
+ FIT_DATA_POSITION_PROP,
+ FIT_DATA_OFFSET_PROP,
};
const char *prop, *end, *name;
int count;
config_name = fit_get_name(fit, conf_noffset, NULL);
- debug("%s: fdt=%p, conf='%s', sig='%s'\n", __func__, gd_fdt_blob(),
+ debug("%s: fdt=%p, conf='%s', sig='%s'\n", __func__, key_blob,
fit_get_name(fit, noffset, NULL),
- fit_get_name(gd_fdt_blob(), required_keynode, NULL));
+ fit_get_name(key_blob, required_keynode, NULL));
*err_msgp = NULL;
- if (fit_image_setup_verify(&info, fit, noffset, required_keynode,
- err_msgp))
+ if (fit_image_setup_verify(&info, fit, noffset, key_blob,
+ required_keynode, err_msgp))
return -1;
if (fit_image_hash_get_value(fit, noffset, &fit_value,
return 0;
}
-static int fit_config_verify_sig(const void *fit, int conf_noffset,
- const void *sig_blob, int sig_offset)
+/**
+ * fit_config_verify_key() - Verify that a configuration is signed with a key
+ *
+ * Here we are looking at a particular configuration that needs verification:
+ *
+ * configurations {
+ * default = "conf-1";
+ * conf-1 {
+ * kernel = "kernel-1";
+ * fdt = "fdt-1";
+ * signature-1 {
+ * algo = "sha1,rsa2048";
+ * value = <...conf 1 signature...>;
+ * };
+ * };
+ *
+ * We must check each of the signature subnodes of conf-1. Hopefully one of them
+ * will match the key at key_offset.
+ *
+ * @fit: FIT to check
+ * @conf_noffset: Offset of the configuration node to check (e.g.
+ * /configurations/conf-1)
+ * @key_blob: Blob containing the keys to check against
+ * @key_offset: Offset of the key to check within @key_blob
+ * @return 0 if OK, -EPERM if any signatures did not verify, or the
+ * configuration node has an invalid name
+ */
+static int fit_config_verify_key(const void *fit, int conf_noffset,
+ const void *key_blob, int key_offset)
{
int noffset;
char *err_msg = "No 'signature' subnode found";
if (!strncmp(name, FIT_SIG_NODENAME,
strlen(FIT_SIG_NODENAME))) {
- ret = fit_config_check_sig(fit, noffset, sig_offset,
- conf_noffset, &err_msg);
+ ret = fit_config_check_sig(fit, noffset, conf_noffset,
+ key_blob, key_offset,
+ &err_msg);
if (ret) {
puts("- ");
} else {
return -EPERM;
}
-static int fit_config_verify_required_sigs(const void *fit, int conf_noffset,
- const void *sig_blob)
+/**
+ * fit_config_verify_required_keys() - verify any required signatures for config
+ *
+ * This looks through all the signatures we expect and verifies that at least
+ * all the required ones are valid signatures for the configuration
+ *
+ * @fit: FIT to check
+ * @conf_noffset: Offset of the configuration node to check (e.g.
+ * /configurations/conf-1)
+ * @key_blob: Blob containing the keys to check against
+ * @return 0 if OK, -EPERM if any signatures did not verify, or the
+ * configuration node has an invalid name
+ */
+static int fit_config_verify_required_keys(const void *fit, int conf_noffset,
+ const void *key_blob)
{
const char *name = fit_get_name(fit, conf_noffset, NULL);
int noffset;
- int sig_node;
+ int key_node;
int verified = 0;
int reqd_sigs = 0;
bool reqd_policy_all = true;
}
/* Work out what we need to verify */
- sig_node = fdt_subnode_offset(sig_blob, 0, FIT_SIG_NODENAME);
- if (sig_node < 0) {
+ key_node = fdt_subnode_offset(key_blob, 0, FIT_SIG_NODENAME);
+ if (key_node < 0) {
debug("%s: No signature node found: %s\n", __func__,
- fdt_strerror(sig_node));
+ fdt_strerror(key_node));
return 0;
}
/* Get required-mode policy property from DTB */
- reqd_mode = fdt_getprop(sig_blob, sig_node, "required-mode", NULL);
+ reqd_mode = fdt_getprop(key_blob, key_node, "required-mode", NULL);
if (reqd_mode && !strcmp(reqd_mode, "any"))
reqd_policy_all = false;
debug("%s: required-mode policy set to '%s'\n", __func__,
reqd_policy_all ? "all" : "any");
- fdt_for_each_subnode(noffset, sig_blob, sig_node) {
+ /*
+ * The algorithm here is a little convoluted due to how we want it to
+ * work. Here we work through each of the signature nodes in the
+ * public-key area. These are in the U-Boot control devicetree. Each
+ * node was created by signing a configuration, so we check if it is
+ * 'required' and if so, request that it be verified.
+ */
+ fdt_for_each_subnode(noffset, key_blob, key_node) {
const char *required;
int ret;
- required = fdt_getprop(sig_blob, noffset, FIT_KEY_REQUIRED,
+ required = fdt_getprop(key_blob, noffset, FIT_KEY_REQUIRED,
NULL);
if (!required || strcmp(required, "conf"))
continue;
reqd_sigs++;
- ret = fit_config_verify_sig(fit, conf_noffset, sig_blob,
+ ret = fit_config_verify_key(fit, conf_noffset, key_blob,
noffset);
if (ret) {
if (reqd_policy_all) {
printf("Failed to verify required signature '%s'\n",
- fit_get_name(sig_blob, noffset, NULL));
+ fit_get_name(key_blob, noffset, NULL));
return ret;
}
} else {
int fit_config_verify(const void *fit, int conf_noffset)
{
- return fit_config_verify_required_sigs(fit, conf_noffset,
+ return fit_config_verify_required_keys(fit, conf_noffset,
gd_fdt_blob());
}