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