Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
E
ezynq
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
Elphel
ezynq
Commits
e05b5888
Commit
e05b5888
authored
Dec 27, 2018
by
Oleg Dzhimiev
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
common/image-sig.c
parent
40ed41b8
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
519 additions
and
0 deletions
+519
-0
image-sig.c
u-boot-tree/common/image-sig.c
+519
-0
No files found.
u-boot-tree/common/image-sig.c
0 → 100644
View file @
e05b5888
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (c) 2013, Google Inc.
*/
#ifdef USE_HOSTCC
#include "mkimage.h"
#include <time.h>
#else
#include <common.h>
#include <malloc.h>
DECLARE_GLOBAL_DATA_PTR
;
#endif
/* !USE_HOSTCC*/
#include <image.h>
#include <u-boot/rsa.h>
#include <u-boot/rsa-checksum.h>
#define IMAGE_MAX_HASHED_NODES 100
#ifdef USE_HOSTCC
void
*
host_blob
;
void
image_set_host_blob
(
void
*
blob
)
{
host_blob
=
blob
;
}
void
*
image_get_host_blob
(
void
)
{
return
host_blob
;
}
#endif
struct
checksum_algo
checksum_algos
[]
=
{
{
.
name
=
"sha1"
,
.
checksum_len
=
SHA1_SUM_LEN
,
.
der_len
=
SHA1_DER_LEN
,
.
der_prefix
=
sha1_der_prefix
,
#if IMAGE_ENABLE_SIGN
.
calculate_sign
=
EVP_sha1
,
#endif
.
calculate
=
hash_calculate
,
},
{
.
name
=
"sha256"
,
.
checksum_len
=
SHA256_SUM_LEN
,
.
der_len
=
SHA256_DER_LEN
,
.
der_prefix
=
sha256_der_prefix
,
#if IMAGE_ENABLE_SIGN
.
calculate_sign
=
EVP_sha256
,
#endif
.
calculate
=
hash_calculate
,
}
};
struct
crypto_algo
crypto_algos
[]
=
{
{
.
name
=
"rsa2048"
,
.
key_len
=
RSA2048_BYTES
,
.
sign
=
rsa_sign
,
.
add_verify_data
=
rsa_add_verify_data
,
.
verify
=
rsa_verify
,
},
{
.
name
=
"rsa4096"
,
.
key_len
=
RSA4096_BYTES
,
.
sign
=
rsa_sign
,
.
add_verify_data
=
rsa_add_verify_data
,
.
verify
=
rsa_verify
,
}
};
struct
padding_algo
padding_algos
[]
=
{
{
.
name
=
"pkcs-1.5"
,
.
verify
=
padding_pkcs_15_verify
,
},
#ifdef CONFIG_FIT_ENABLE_RSASSA_PSS_SUPPORT
{
.
name
=
"pss"
,
.
verify
=
padding_pss_verify
,
}
#endif
/* CONFIG_FIT_ENABLE_RSASSA_PSS_SUPPORT */
};
struct
checksum_algo
*
image_get_checksum_algo
(
const
char
*
full_name
)
{
int
i
;
const
char
*
name
;
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
checksum_algos
);
i
++
)
{
name
=
checksum_algos
[
i
].
name
;
/* Make sure names match and next char is a comma */
if
(
!
strncmp
(
name
,
full_name
,
strlen
(
name
))
&&
full_name
[
strlen
(
name
)]
==
','
)
return
&
checksum_algos
[
i
];
}
return
NULL
;
}
struct
crypto_algo
*
image_get_crypto_algo
(
const
char
*
full_name
)
{
int
i
;
const
char
*
name
;
/* Move name to after the comma */
name
=
strchr
(
full_name
,
','
);
if
(
!
name
)
return
NULL
;
name
+=
1
;
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
crypto_algos
);
i
++
)
{
if
(
!
strcmp
(
crypto_algos
[
i
].
name
,
name
))
return
&
crypto_algos
[
i
];
}
return
NULL
;
}
struct
padding_algo
*
image_get_padding_algo
(
const
char
*
name
)
{
int
i
;
if
(
!
name
)
return
NULL
;
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
padding_algos
);
i
++
)
{
if
(
!
strcmp
(
padding_algos
[
i
].
name
,
name
))
return
&
padding_algos
[
i
];
}
return
NULL
;
}
/**
* fit_region_make_list() - Make a list of image regions
*
* Given a list of fdt_regions, create a list of image_regions. This is a
* simple conversion routine since the FDT and image code use different
* structures.
*
* @fit: FIT image
* @fdt_regions: Pointer to FDT regions
* @count: Number of FDT regions
* @region: Pointer to image regions, which must hold @count records. If
* region is NULL, then (except for an SPL build) the array will be
* allocated.
* @return: Pointer to image regions
*/
struct
image_region
*
fit_region_make_list
(
const
void
*
fit
,
struct
fdt_region
*
fdt_regions
,
int
count
,
struct
image_region
*
region
)
{
int
i
;
debug
(
"Hash regions:
\n
"
);
debug
(
"%10s %10s
\n
"
,
"Offset"
,
"Size"
);
/*
* Use malloc() except in SPL (to save code size). In SPL the caller
* must allocate the array.
*/
#ifndef CONFIG_SPL_BUILD
if
(
!
region
)
region
=
calloc
(
sizeof
(
*
region
),
count
);
#endif
if
(
!
region
)
return
NULL
;
for
(
i
=
0
;
i
<
count
;
i
++
)
{
debug
(
"%10x %10x
\n
"
,
fdt_regions
[
i
].
offset
,
fdt_regions
[
i
].
size
);
region
[
i
].
data
=
fit
+
fdt_regions
[
i
].
offset
;
region
[
i
].
size
=
fdt_regions
[
i
].
size
;
}
return
region
;
}
static
int
fit_image_setup_verify
(
struct
image_sign_info
*
info
,
const
void
*
fit
,
int
noffset
,
int
required_keynode
,
char
**
err_msgp
)
{
char
*
algo_name
;
const
char
*
padding_name
;
if
(
fdt_totalsize
(
fit
)
>
CONFIG_FIT_SIGNATURE_MAX_SIZE
)
{
*
err_msgp
=
"Total size too large"
;
return
1
;
}
if
(
fit_image_hash_get_algo
(
fit
,
noffset
,
&
algo_name
))
{
*
err_msgp
=
"Can't get hash algo property"
;
return
-
1
;
}
padding_name
=
fdt_getprop
(
fit
,
noffset
,
"padding"
,
NULL
);
if
(
!
padding_name
)
padding_name
=
RSA_DEFAULT_PADDING_NAME
;
memset
(
info
,
'\0'
,
sizeof
(
*
info
));
info
->
keyname
=
fdt_getprop
(
fit
,
noffset
,
"key-name-hint"
,
NULL
);
info
->
fit
=
(
void
*
)
fit
;
info
->
node_offset
=
noffset
;
info
->
name
=
algo_name
;
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
->
required_keynode
=
required_keynode
;
printf
(
"%s:%s"
,
algo_name
,
info
->
keyname
);
if
(
!
info
->
checksum
||
!
info
->
crypto
)
{
*
err_msgp
=
"Unknown signature algorithm"
;
return
-
1
;
}
return
0
;
}
int
fit_image_check_sig
(
const
void
*
fit
,
int
noffset
,
const
void
*
data
,
size_t
size
,
int
required_keynode
,
char
**
err_msgp
)
{
struct
image_sign_info
info
;
struct
image_region
region
;
uint8_t
*
fit_value
;
int
fit_value_len
;
*
err_msgp
=
NULL
;
if
(
fit_image_setup_verify
(
&
info
,
fit
,
noffset
,
required_keynode
,
err_msgp
))
return
-
1
;
if
(
fit_image_hash_get_value
(
fit
,
noffset
,
&
fit_value
,
&
fit_value_len
))
{
*
err_msgp
=
"Can't get hash value property"
;
return
-
1
;
}
region
.
data
=
data
;
region
.
size
=
size
;
if
(
info
.
crypto
->
verify
(
&
info
,
&
region
,
1
,
fit_value
,
fit_value_len
))
{
*
err_msgp
=
"Verification failed"
;
return
-
1
;
}
return
0
;
}
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
)
{
int
noffset
;
char
*
err_msg
=
""
;
int
verified
=
0
;
int
ret
;
/* Process all hash subnodes of the component image node */
fdt_for_each_subnode
(
noffset
,
fit
,
image_noffset
)
{
const
char
*
name
=
fit_get_name
(
fit
,
noffset
,
NULL
);
if
(
!
strncmp
(
name
,
FIT_SIG_NODENAME
,
strlen
(
FIT_SIG_NODENAME
)))
{
ret
=
fit_image_check_sig
(
fit
,
noffset
,
data
,
size
,
-
1
,
&
err_msg
);
if
(
ret
)
{
puts
(
"- "
);
}
else
{
puts
(
"+ "
);
verified
=
1
;
break
;
}
}
}
if
(
noffset
==
-
FDT_ERR_TRUNCATED
||
noffset
==
-
FDT_ERR_BADSTRUCTURE
)
{
err_msg
=
"Corrupted or truncated tree"
;
goto
error
;
}
return
verified
?
0
:
-
EPERM
;
error:
printf
(
" error!
\n
%s for '%s' hash node in '%s' image node
\n
"
,
err_msg
,
fit_get_name
(
fit
,
noffset
,
NULL
),
fit_get_name
(
fit
,
image_noffset
,
NULL
));
return
-
1
;
}
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
)
{
int
verify_count
=
0
;
int
noffset
;
int
sig_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
)
{
debug
(
"%s: No signature node found: %s
\n
"
,
__func__
,
fdt_strerror
(
sig_node
));
return
0
;
}
fdt_for_each_subnode
(
noffset
,
sig_blob
,
sig_node
)
{
const
char
*
required
;
int
ret
;
required
=
fdt_getprop
(
sig_blob
,
noffset
,
"required"
,
NULL
);
if
(
!
required
||
strcmp
(
required
,
"image"
))
continue
;
ret
=
fit_image_verify_sig
(
fit
,
image_noffset
,
data
,
size
,
sig_blob
,
noffset
);
if
(
ret
)
{
printf
(
"Failed to verify required signature '%s'
\n
"
,
fit_get_name
(
sig_blob
,
noffset
,
NULL
));
return
ret
;
}
verify_count
++
;
}
if
(
verify_count
)
*
no_sigsp
=
0
;
return
0
;
}
int
fit_config_check_sig
(
const
void
*
fit
,
int
noffset
,
int
required_keynode
,
char
**
err_msgp
)
{
char
*
const
exc_prop
[]
=
{
"data"
};
const
char
*
prop
,
*
end
,
*
name
;
struct
image_sign_info
info
;
const
uint32_t
*
strings
;
uint8_t
*
fit_value
;
int
fit_value_len
;
int
max_regions
;
int
i
,
prop_len
;
char
path
[
200
];
int
count
;
debug
(
"%s: fdt=%p, conf='%s', sig='%s'
\n
"
,
__func__
,
gd_fdt_blob
(),
fit_get_name
(
fit
,
noffset
,
NULL
),
fit_get_name
(
gd_fdt_blob
(),
required_keynode
,
NULL
));
*
err_msgp
=
NULL
;
if
(
fit_image_setup_verify
(
&
info
,
fit
,
noffset
,
required_keynode
,
err_msgp
))
return
-
1
;
if
(
fit_image_hash_get_value
(
fit
,
noffset
,
&
fit_value
,
&
fit_value_len
))
{
*
err_msgp
=
"Can't get hash value property"
;
return
-
1
;
}
/* Count the number of strings in the property */
prop
=
fdt_getprop
(
fit
,
noffset
,
"hashed-nodes"
,
&
prop_len
);
end
=
prop
?
prop
+
prop_len
:
prop
;
for
(
name
=
prop
,
count
=
0
;
name
<
end
;
name
++
)
if
(
!*
name
)
count
++
;
if
(
!
count
)
{
*
err_msgp
=
"Can't get hashed-nodes property"
;
return
-
1
;
}
if
(
prop
&&
prop_len
>
0
&&
prop
[
prop_len
-
1
]
!=
'\0'
)
{
*
err_msgp
=
"hashed-nodes property must be null-terminated"
;
return
-
1
;
}
/* Add a sanity check here since we are using the stack */
if
(
count
>
IMAGE_MAX_HASHED_NODES
)
{
*
err_msgp
=
"Number of hashed nodes exceeds maximum"
;
return
-
1
;
}
/* Create a list of node names from those strings */
char
*
node_inc
[
count
];
debug
(
"Hash nodes (%d):
\n
"
,
count
);
for
(
name
=
prop
,
i
=
0
;
name
<
end
;
name
+=
strlen
(
name
)
+
1
,
i
++
)
{
debug
(
" '%s'
\n
"
,
name
);
node_inc
[
i
]
=
(
char
*
)
name
;
}
/*
* Each node can generate one region for each sub-node. Allow for
* 7 sub-nodes (hash-1, signature-1, etc.) and some extra.
*/
max_regions
=
20
+
count
*
7
;
struct
fdt_region
fdt_regions
[
max_regions
];
/* Get a list of regions to hash */
count
=
fdt_find_regions
(
fit
,
node_inc
,
count
,
exc_prop
,
ARRAY_SIZE
(
exc_prop
),
fdt_regions
,
max_regions
-
1
,
path
,
sizeof
(
path
),
0
);
if
(
count
<
0
)
{
*
err_msgp
=
"Failed to hash configuration"
;
return
-
1
;
}
if
(
count
==
0
)
{
*
err_msgp
=
"No data to hash"
;
return
-
1
;
}
if
(
count
>=
max_regions
-
1
)
{
*
err_msgp
=
"Too many hash regions"
;
return
-
1
;
}
/* Add the strings */
strings
=
fdt_getprop
(
fit
,
noffset
,
"hashed-strings"
,
NULL
);
if
(
strings
)
{
/*
* The strings region offset must be a static 0x0.
* This is set in tool/image-host.c
*/
fdt_regions
[
count
].
offset
=
fdt_off_dt_strings
(
fit
);
fdt_regions
[
count
].
size
=
fdt32_to_cpu
(
strings
[
1
]);
count
++
;
}
/* Allocate the region list on the stack */
struct
image_region
region
[
count
];
fit_region_make_list
(
fit
,
fdt_regions
,
count
,
region
);
if
(
info
.
crypto
->
verify
(
&
info
,
region
,
count
,
fit_value
,
fit_value_len
))
{
*
err_msgp
=
"Verification failed"
;
return
-
1
;
}
return
0
;
}
static
int
fit_config_verify_sig
(
const
void
*
fit
,
int
conf_noffset
,
const
void
*
sig_blob
,
int
sig_offset
)
{
int
noffset
;
char
*
err_msg
=
""
;
int
verified
=
0
;
int
ret
;
/* Process all hash subnodes of the component conf node */
fdt_for_each_subnode
(
noffset
,
fit
,
conf_noffset
)
{
const
char
*
name
=
fit_get_name
(
fit
,
noffset
,
NULL
);
if
(
!
strncmp
(
name
,
FIT_SIG_NODENAME
,
strlen
(
FIT_SIG_NODENAME
)))
{
ret
=
fit_config_check_sig
(
fit
,
noffset
,
sig_offset
,
&
err_msg
);
if
(
ret
)
{
puts
(
"- "
);
}
else
{
puts
(
"+ "
);
verified
=
1
;
break
;
}
}
}
if
(
noffset
==
-
FDT_ERR_TRUNCATED
||
noffset
==
-
FDT_ERR_BADSTRUCTURE
)
{
err_msg
=
"Corrupted or truncated tree"
;
goto
error
;
}
return
verified
?
0
:
-
EPERM
;
error:
printf
(
" error!
\n
%s for '%s' hash node in '%s' config node
\n
"
,
err_msg
,
fit_get_name
(
fit
,
noffset
,
NULL
),
fit_get_name
(
fit
,
conf_noffset
,
NULL
));
return
-
1
;
}
int
fit_config_verify_required_sigs
(
const
void
*
fit
,
int
conf_noffset
,
const
void
*
sig_blob
)
{
int
noffset
;
int
sig_node
;
/* Work out what we need to verify */
sig_node
=
fdt_subnode_offset
(
sig_blob
,
0
,
FIT_SIG_NODENAME
);
if
(
sig_node
<
0
)
{
debug
(
"%s: No signature node found: %s
\n
"
,
__func__
,
fdt_strerror
(
sig_node
));
return
0
;
}
fdt_for_each_subnode
(
noffset
,
sig_blob
,
sig_node
)
{
const
char
*
required
;
int
ret
;
required
=
fdt_getprop
(
sig_blob
,
noffset
,
"required"
,
NULL
);
if
(
!
required
||
strcmp
(
required
,
"conf"
))
continue
;
ret
=
fit_config_verify_sig
(
fit
,
conf_noffset
,
sig_blob
,
noffset
);
if
(
ret
)
{
printf
(
"Failed to verify required signature '%s'
\n
"
,
fit_get_name
(
sig_blob
,
noffset
,
NULL
));
return
ret
;
}
}
return
0
;
}
int
fit_config_verify
(
const
void
*
fit
,
int
conf_noffset
)
{
return
fit_config_verify_required_sigs
(
fit
,
conf_noffset
,
gd_fdt_blob
());
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment