Open Titan Tool is the recommended tool to generate RSA keys to use in
the ROM
.
- Inspecting a key (show the public information of a key, replace
$key_basename
by the name of your key):
bazel run //sw/host/opentitantool -- rsa key show $PWD/$key_basename.der
Example output:
{
key_num_bits: 3072,
modulus: "0xa22244f7...",
public_exponent: "0x010001",
n0_inv: "0x2af3...",
rr: "0x82ca57ba..."
}
- Generating a key pair in the current directory:
bazel run //sw/host/opentitantool -- rsa key generate $outdir $key_basename
This will generate two files $outdir/$key_basename.der
(private key)
and $outdir/$key_basename.pub.der
(public key). Note that if you want to generate
a key in the current directory, you need to set $outdir
to $PWD
since bazel
does
not run the tool in the current directory.
- Exporting a key to a header for use in the ROM:
bazel run //sw/host/opentitantool -- rsa key export $PWD/$key_basename.der
After exporting the key, it is recommended to follow the best practices and make sure that the header follows the OpenTitan convention (for example for fake keys that will be committed to the repository) by running
# from root of the repository
./util/fix_include_guard.py sw/device/.../$key_basename.h
bazel run //quality:clang_format_fix
Don't forget to add the copyright comment at the beginning of the file.
This directory contains ASN1 DER encoded development keys for signing ROM
images. It is recommended to use opentitantool
but the below snippets
can be used to generate and manipulate keys.
Generating a key pair:
$ openssl genrsa -out <basename>.pem -f4 3072
Generating RSA private key, 3072 bit long modulus (2 primes)
..............................++++
.....................................................................++++
e is 3 (0x03)
$ openssl rsa -outform DER -in <basename>.pem -out <basename>.private.der
writing RSA key
$ openssl rsa -outform DER -in <basename>.pem -pubout -out <basename>.public.der
writing RSA key
Inspecting a key:
$ openssl rsa -inform DER -pubin -in <basename>.public.der -modulus -noout
Modulus=DA81748B9EEBE1E6FABE9ACB1C0A...
$ openssl rsa -inform DER -pubin -in <basename>.public.der -noout -text
RSA Public-Key: (3072 bit)
Modulus:
00:da:81:74:8b:9e:eb:e1:e6:fa:be:9a:cb:1c:0a:
...
e0:2f:43:dd:47:25:8f:e1:4b:15
Exponent: 3 (0x3)
Calculating the digest of a message:
$ echo -n "test" | openssl dgst -sha256
(stdin)= 9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08
Signing a message:
$ echo -n "test" | openssl dgst -sha256 -keyform DER -sign <basename>.private.der -hex
(stdin)= ad46cc63c05f66deb638476a7d...
Verifying a signature:
$ echo -n "test" | openssl dgst -sha256 -keyform DER -sign <basename>.private.der -out test_sig
$ echo -n "test" | openssl dgst -sha256 -keyform DER -verify <basename>.public.der -signature test_sig
Verified OK
Printing the encoded message during signature verification:
$ openssl rsautl -verify -in test_sig -inkey <basename>.public.der -pubin -keyform DER -raw -hexdump
0000 - 00 01 ff ff ff ff ff ff-ff ff ff ff ff ff ff ff ................
0010 - ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff ................
0020 - ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff ................
0030 - ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff ................
0040 - ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff ................
0050 - ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff ................
0060 - ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff ................
0070 - ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff ................
0080 - ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff ................
0090 - ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff ................
00a0 - ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff ................
00b0 - ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff ................
00c0 - ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff ................
00d0 - ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff ................
00e0 - ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff ................
00f0 - ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff ................
0100 - ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff ................
0110 - ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff ................
0120 - ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff ................
0130 - ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff ................
0140 - ff ff ff ff ff ff ff ff-ff ff ff ff 00 30 31 30 .............010
0150 - 0d 06 09 60 86 48 01 65-03 04 02 01 05 00 04 20 ...`.H.e.......
0160 - 9f 86 d0 81 88 4c 7d 65-9a 2f ea a0 c5 5a d0 15 .....L}e./...Z..
0170 - a3 bf 4f 1b 2b 0b 82 2c-d1 5d 6c 15 b0 f0 0a 08 ..O.+..,.]l.....
Please note that openssl
outputs are big-endian while OpenTitan signature
verification uses little-endian representation. Therefore, outputs of the commands
above should be converted to little-endian before they can be used in tests or
source code. One way to do this (until we have a more ergonomic way) is to pipe
binary outputs to xxd -p -c 4 | tac
:
$ echo -n "test" | openssl dgst -sha256 -binary | xxd -p -c 4 | tac
b0f00a08
d15d6c15
2b0b822c
a3bf4f1b
c55ad015
9a2feaa0
884c7d65
9f86d081