Add a structure to describe an algorithm which can sign and (later) verify images. Signed-off-by: Simon Glass <sjg@chromium.org>master
parent
b5f3193734
commit
3e569a6b1e
@ -0,0 +1,42 @@ |
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013, Google Inc. |
||||||
|
* |
||||||
|
* This program is free software; you can redistribute it and/or |
||||||
|
* modify it under the terms of the GNU General Public License as |
||||||
|
* published by the Free Software Foundation; either version 2 of |
||||||
|
* the License, or (at your option) any later version. |
||||||
|
* |
||||||
|
* This program is distributed in the hope that it will be useful, |
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||||
|
* GNU General Public License for more details. |
||||||
|
* |
||||||
|
* You should have received a copy of the GNU General Public License |
||||||
|
* along with this program; if not, write to the Free Software |
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, |
||||||
|
* MA 02111-1307 USA |
||||||
|
*/ |
||||||
|
|
||||||
|
#ifdef USE_HOSTCC |
||||||
|
#include "mkimage.h" |
||||||
|
#include <time.h> |
||||||
|
#else |
||||||
|
#include <common.h> |
||||||
|
#endif /* !USE_HOSTCC*/ |
||||||
|
#include <errno.h> |
||||||
|
#include <image.h> |
||||||
|
|
||||||
|
struct image_sig_algo image_sig_algos[] = { |
||||||
|
}; |
||||||
|
|
||||||
|
struct image_sig_algo *image_get_sig_algo(const char *name) |
||||||
|
{ |
||||||
|
int i; |
||||||
|
|
||||||
|
for (i = 0; i < ARRAY_SIZE(image_sig_algos); i++) { |
||||||
|
if (!strcmp(image_sig_algos[i].name, name)) |
||||||
|
return &image_sig_algos[i]; |
||||||
|
} |
||||||
|
|
||||||
|
return NULL; |
||||||
|
} |
@ -0,0 +1,216 @@ |
|||||||
|
U-Boot FIT Signature Verification |
||||||
|
================================= |
||||||
|
|
||||||
|
Introduction |
||||||
|
------------ |
||||||
|
FIT supports hashing of images so that these hashes can be checked on |
||||||
|
loading. This protects against corruption of the image. However it does not |
||||||
|
prevent the substitution of one image for another. |
||||||
|
|
||||||
|
The signature feature allows the hash to be signed with a private key such |
||||||
|
that it can be verified using a public key later. Provided that the private |
||||||
|
key is kept secret and the public key is stored in a non-volatile place, |
||||||
|
any image can be verified in this way. |
||||||
|
|
||||||
|
See verified-boot.txt for more general information on verified boot. |
||||||
|
|
||||||
|
|
||||||
|
Concepts |
||||||
|
-------- |
||||||
|
Some familiarity with public key cryptography is assumed in this section. |
||||||
|
|
||||||
|
The procedure for signing is as follows: |
||||||
|
|
||||||
|
- hash an image in the FIT |
||||||
|
- sign the hash with a private key to produce a signature |
||||||
|
- store the resulting signature in the FIT |
||||||
|
|
||||||
|
The procedure for verification is: |
||||||
|
|
||||||
|
- read the FIT |
||||||
|
- obtain the public key |
||||||
|
- extract the signature from the FIT |
||||||
|
- hash the image from the FIT |
||||||
|
- verify (with the public key) that the extracted signature matches the |
||||||
|
hash |
||||||
|
|
||||||
|
The signing is generally performed by mkimage, as part of making a firmware |
||||||
|
image for the device. The verification is normally done in U-Boot on the |
||||||
|
device. |
||||||
|
|
||||||
|
|
||||||
|
Algorithms |
||||||
|
---------- |
||||||
|
In principle any suitable algorithm can be used to sign and verify a hash. |
||||||
|
At present only one class of algorithms is supported: SHA1 hashing with RSA. |
||||||
|
This works by hashing the image to produce a 20-byte hash. |
||||||
|
|
||||||
|
While it is acceptable to bring in large cryptographic libraries such as |
||||||
|
openssl on the host side (e.g. mkimage), it is not desirable for U-Boot. |
||||||
|
For the run-time verification side, it is important to keep code and data |
||||||
|
size as small as possible. |
||||||
|
|
||||||
|
For this reason the RSA image verification uses pre-processed public keys |
||||||
|
which can be used with a very small amount of code - just some extraction |
||||||
|
of data from the FDT and exponentiation mod n. Code size impact is a little |
||||||
|
under 5KB on Tegra Seaboard, for example. |
||||||
|
|
||||||
|
It is relatively straightforward to add new algorithms if required. If |
||||||
|
another RSA variant is needed, then it can be added to the table in |
||||||
|
image-sig.c. If another algorithm is needed (such as DSA) then it can be |
||||||
|
placed alongside rsa.c, and its functions added to the table in image-sig.c |
||||||
|
also. |
||||||
|
|
||||||
|
|
||||||
|
Creating an RSA key and certificate |
||||||
|
----------------------------------- |
||||||
|
To create a new public key, size 2048 bits: |
||||||
|
|
||||||
|
$ openssl genrsa -F4 -out keys/dev.key 2048 |
||||||
|
|
||||||
|
To create a certificate for this: |
||||||
|
|
||||||
|
$ openssl req -batch -new -x509 -key keys/dev.key -out keys/dev.crt |
||||||
|
|
||||||
|
If you like you can look at the public key also: |
||||||
|
|
||||||
|
$ openssl rsa -in keys/dev.key -pubout |
||||||
|
|
||||||
|
|
||||||
|
Device Tree Bindings |
||||||
|
-------------------- |
||||||
|
The following properties are required in the FIT's signature node(s) to |
||||||
|
allow thes signer to operate. These should be added to the .its file. |
||||||
|
Signature nodes sit at the same level as hash nodes and are called |
||||||
|
signature@1, signature@2, etc. |
||||||
|
|
||||||
|
- algo: Algorithm name (e.g. "sha1,rs2048") |
||||||
|
|
||||||
|
- key-name-hint: Name of key to use for signing. The keys will normally be in |
||||||
|
a single directory (parameter -k to mkimage). For a given key <name>, its |
||||||
|
private key is stored in <name>.key and the certificate is stored in |
||||||
|
<name>.crt. |
||||||
|
|
||||||
|
When the image is signed, the following properties are added (mandatory): |
||||||
|
|
||||||
|
- value: The signature data (e.g. 256 bytes for 2048-bit RSA) |
||||||
|
|
||||||
|
When the image is signed, the following properties are optional: |
||||||
|
|
||||||
|
- timestamp: Time when image was signed (standard Unix time_t format) |
||||||
|
|
||||||
|
- signer-name: Name of the signer (e.g. "mkimage") |
||||||
|
|
||||||
|
- signer-version: Version string of the signer (e.g. "2013.01") |
||||||
|
|
||||||
|
- comment: Additional information about the signer or image |
||||||
|
|
||||||
|
|
||||||
|
Example: See sign-images.its for an example image tree source file. |
||||||
|
|
||||||
|
|
||||||
|
Public Key Storage |
||||||
|
------------------ |
||||||
|
In order to verify an image that has been signed with a public key we need to |
||||||
|
have a trusted public key. This cannot be stored in the signed image, since |
||||||
|
it would be easy to alter. For this implementation we choose to store the |
||||||
|
public key in U-Boot's control FDT (using CONFIG_OF_CONTROL). |
||||||
|
|
||||||
|
Public keys should be stored as sub-nodes in a /signature node. Required |
||||||
|
properties are: |
||||||
|
|
||||||
|
- algo: Algorithm name (e.g. "sha1,rs2048") |
||||||
|
|
||||||
|
Optional properties are: |
||||||
|
|
||||||
|
- key-name-hint: Name of key used for signing. This is only a hint since it |
||||||
|
is possible for the name to be changed. Verification can proceed by checking |
||||||
|
all available signing keys until one matches. |
||||||
|
|
||||||
|
- required: If present this indicates that the key must be verified for the |
||||||
|
image / configuration to be considered valid. Only required keys are |
||||||
|
normally verified by the FIT image booting algorithm. Valid values are |
||||||
|
"image" to force verification of all images, and "conf" to force verfication |
||||||
|
of the selected configuration (which then relies on hashes in the images to |
||||||
|
verify those). |
||||||
|
|
||||||
|
Each signing algorithm has its own additional properties. |
||||||
|
|
||||||
|
For RSA the following are mandatory: |
||||||
|
|
||||||
|
- rsa,num-bits: Number of key bits (e.g. 2048) |
||||||
|
- rsa,modulus: Modulus (N) as a big-endian multi-word integer |
||||||
|
- rsa,r-squared: (2^num-bits)^2 as a big-endian multi-word integer |
||||||
|
- rsa,n0-inverse: -1 / modulus[0] mod 2^32 |
||||||
|
|
||||||
|
|
||||||
|
Verification |
||||||
|
------------ |
||||||
|
FITs are verified when loaded. After the configuration is selected a list |
||||||
|
of required images is produced. If there are 'required' public keys, then |
||||||
|
each image must be verified against those keys. This means that every image |
||||||
|
that might be used by the target needs to be signed with 'required' keys. |
||||||
|
|
||||||
|
This happens automatically as part of a bootm command when FITs are used. |
||||||
|
|
||||||
|
|
||||||
|
Enabling FIT Verification |
||||||
|
------------------------- |
||||||
|
In addition to the options to enable FIT itself, the following CONFIGs must |
||||||
|
be enabled: |
||||||
|
|
||||||
|
CONFIG_FIT_SIGNATURE - enable signing and verfication in FITs |
||||||
|
CONFIG_RSA - enable RSA algorithm for signing |
||||||
|
|
||||||
|
|
||||||
|
Testing |
||||||
|
------- |
||||||
|
An easy way to test signing and verfication is to use the test script |
||||||
|
provided in test/vboot/vboot_test.sh. This uses sandbox (a special version |
||||||
|
of U-Boot which runs under Linux) to show the operation of a 'bootm' |
||||||
|
command loading and verifying images. |
||||||
|
|
||||||
|
A sample run is show below: |
||||||
|
|
||||||
|
$ make O=sandbox sandbox_config |
||||||
|
$ make O=sandbox |
||||||
|
$ O=sandbox ./test/vboot/vboot_test.sh |
||||||
|
Simple Verified Boot Test |
||||||
|
========================= |
||||||
|
|
||||||
|
Please see doc/uImage.FIT/verified-boot.txt for more information |
||||||
|
|
||||||
|
Build keys |
||||||
|
Build FIT with signed images |
||||||
|
Test Verified Boot Run: unsigned signatures:: OK |
||||||
|
Sign images |
||||||
|
Test Verified Boot Run: signed images: OK |
||||||
|
Build FIT with signed configuration |
||||||
|
Test Verified Boot Run: unsigned config: OK |
||||||
|
Sign images |
||||||
|
Test Verified Boot Run: signed config: OK |
||||||
|
|
||||||
|
Test passed |
||||||
|
|
||||||
|
|
||||||
|
Future Work |
||||||
|
----------- |
||||||
|
- Roll-back protection using a TPM is done using the tpm command. This can |
||||||
|
be scripted, but we might consider a default way of doing this, built into |
||||||
|
bootm. |
||||||
|
|
||||||
|
|
||||||
|
Possible Future Work |
||||||
|
-------------------- |
||||||
|
- Add support for other RSA/SHA variants, such as rsa4096,sha512. |
||||||
|
- Other algorithms besides RSA |
||||||
|
- More sandbox tests for failure modes |
||||||
|
- Passwords for keys/certificates |
||||||
|
- Perhaps implement OAEP |
||||||
|
- Enhance bootm to permit scripted signature verification (so that a script |
||||||
|
can verify an image but not actually boot it) |
||||||
|
|
||||||
|
|
||||||
|
Simon Glass |
||||||
|
sjg@chromium.org |
||||||
|
1-1-13 |
Loading…
Reference in new issue