diff options
21 files changed, 174 insertions, 26 deletions
diff --git a/firmware/2lib/2rsa.c b/firmware/2lib/2rsa.c index 7862b133..48e1ec33 100644 --- a/firmware/2lib/2rsa.c +++ b/firmware/2lib/2rsa.c @@ -73,6 +73,25 @@ static void montMulAdd(const struct vb2_public_key *key, } /** + * Montgomery c[] += 0 * b[] / R % mod + */ +static void montMulAdd0(const struct vb2_public_key *key, + uint32_t *c, + const uint32_t *b) +{ + uint32_t d0 = c[0] * key->n0inv; + uint64_t B = (uint64_t)d0 * key->n[0] + c[0]; + uint32_t i; + + for (i = 1; i < key->arrsize; ++i) { + B = (B >> 32) + (uint64_t)d0 * key->n[i] + c[i]; + c[i - 1] = (uint32_t)B; + } + + c[i - 1] = B >> 32; +} + +/** * Montgomery c[] = a[] * b[] / R % mod */ static void montMul(const struct vb2_public_key *key, @@ -89,16 +108,32 @@ static void montMul(const struct vb2_public_key *key, } } +/* Montgomery c[] = a[] * 1 / R % key. */ +static void montMul1(const struct vb2_public_key *key, + uint32_t *c, + const uint32_t *a) +{ + int i; + + for (i = 0; i < key->arrsize; ++i) + c[i] = 0; + + montMulAdd(key, c, 1, a); + for (i = 1; i < key->arrsize; ++i) + montMulAdd0(key, c, a); +} + /** - * In-place public exponentiation. (65537} + * In-place public exponentiation. * * @param key Key to use in signing * @param inout Input and output big-endian byte array * @param workbuf32 Work buffer; caller must verify this is * (3 * key->arrsize) elements long. + * @param exp RSA public exponent: either 65537 (F4) or 3 */ -static void modpowF4(const struct vb2_public_key *key, uint8_t *inout, - uint32_t *workbuf32) +static void modpow(const struct vb2_public_key *key, uint8_t *inout, + uint32_t *workbuf32, int exp) { uint32_t *a = workbuf32; uint32_t *aR = a + key->arrsize; @@ -117,12 +152,18 @@ static void modpowF4(const struct vb2_public_key *key, uint8_t *inout, } montMul(key, aR, a, key->rr); /* aR = a * RR / R mod M */ - for (i = 0; i < 16; i+=2) { - montMul(key, aaR, aR, aR); /* aaR = aR * aR / R mod M */ - montMul(key, aR, aaR, aaR); /* aR = aaR * aaR / R mod M */ + if (exp == 3) { + montMul(key, aaR, aR, aR); /* aaR = aR * aR / R mod M */ + montMul(key, a, aaR, aR); /* a = aaR * aR / R mod M */ + montMul1(key, aaa, a); /* aaa = a * 1 / R mod M */ + } else { + /* Exponent 65537 */ + for (i = 0; i < 16; i+=2) { + montMul(key, aaR, aR, aR); /* aaR = aR * aR / R mod M */ + montMul(key, aR, aaR, aaR); /* aR = aaR * aaR / R mod M */ + } + montMul(key, aaa, aR, a); /* aaa = aR * a / R mod M */ } - montMul(key, aaa, aR, a); /* aaa = aR * a / R mod M */ - /* Make sure aaa < mod; aaa is at most 1x mod too large. */ if (vb2_mont_ge(key, aaa)) { @@ -153,6 +194,9 @@ static const uint8_t crypto_to_sig[] = { VB2_SIG_RSA8192, VB2_SIG_RSA8192, VB2_SIG_RSA8192, + VB2_SIG_RSA2048_EXP3, + VB2_SIG_RSA2048_EXP3, + VB2_SIG_RSA2048_EXP3, }; /** @@ -178,6 +222,7 @@ uint32_t vb2_rsa_sig_size(enum vb2_signature_algorithm sig_alg) case VB2_SIG_RSA1024: return 1024 / 8; case VB2_SIG_RSA2048: + case VB2_SIG_RSA2048_EXP3: return 2048 / 8; case VB2_SIG_RSA4096: return 4096 / 8; @@ -188,6 +233,27 @@ uint32_t vb2_rsa_sig_size(enum vb2_signature_algorithm sig_alg) } } +/** + * Return the exponent used by an RSA algorithm + * + * @param sig_alg Signature algorithm + * @return The exponent to use (3 or 65537(F4)), or 0 if error. + */ +static uint32_t vb2_rsa_exponent(enum vb2_signature_algorithm sig_alg) +{ + switch (sig_alg) { + case VB2_SIG_RSA1024: + case VB2_SIG_RSA2048: + case VB2_SIG_RSA4096: + case VB2_SIG_RSA8192: + return 65537; + case VB2_SIG_RSA2048_EXP3: + return 3; + default: + return 0; + } +} + uint32_t vb2_packed_key_size(enum vb2_signature_algorithm sig_alg) { uint32_t sig_size = vb2_rsa_sig_size(sig_alg); @@ -298,13 +364,15 @@ int vb2_rsa_verify_digest(const struct vb2_public_key *key, uint32_t key_bytes; int sig_size; int pad_size; + int exp; int rv; if (!key || !sig || !digest) return VB2_ERROR_RSA_VERIFY_PARAM; sig_size = vb2_rsa_sig_size(key->sig_alg); - if (!sig_size) { + exp = vb2_rsa_exponent(key->sig_alg); + if (!sig_size || !exp) { VB2_DEBUG("Invalid signature type!\n"); return VB2_ERROR_RSA_VERIFY_ALGORITHM; } @@ -322,7 +390,7 @@ int vb2_rsa_verify_digest(const struct vb2_public_key *key, return VB2_ERROR_RSA_VERIFY_WORKBUF; } - modpowF4(key, sig, workbuf32); + modpow(key, sig, workbuf32, exp); vb2_workbuf_free(&wblocal, 3 * key_bytes); diff --git a/firmware/2lib/2sha_utility.c b/firmware/2lib/2sha_utility.c index dd74f290..7193091b 100644 --- a/firmware/2lib/2sha_utility.c +++ b/firmware/2lib/2sha_utility.c @@ -40,6 +40,9 @@ static const uint8_t crypto_to_hash[] = { CTH_SHA1, CTH_SHA256, CTH_SHA512, + CTH_SHA1, + CTH_SHA256, + CTH_SHA512, }; enum vb2_hash_algorithm vb2_crypto_to_hash(uint32_t algorithm) diff --git a/firmware/2lib/include/2crypto.h b/firmware/2lib/include/2crypto.h index da1c2ddf..a33b5360 100644 --- a/firmware/2lib/include/2crypto.h +++ b/firmware/2lib/include/2crypto.h @@ -23,7 +23,9 @@ enum vb2_crypto_algorithm { VB2_ALG_RSA8192_SHA1 = 9, VB2_ALG_RSA8192_SHA256 = 10, VB2_ALG_RSA8192_SHA512 = 11, - + VB2_ALG_RSA2048_EXP3_SHA1 = 12, + VB2_ALG_RSA2048_EXP3_SHA256 = 13, + VB2_ALG_RSA2048_EXP3_SHA512 = 14, /* Number of algorithms */ VB2_ALG_COUNT }; @@ -44,6 +46,7 @@ enum vb2_signature_algorithm { VB2_SIG_RSA2048 = 3, VB2_SIG_RSA4096 = 4, VB2_SIG_RSA8192 = 5, + VB2_SIG_RSA2048_EXP3 = 6, /* Last index. Don't add anything below. */ VB2_SIG_ALG_COUNT, diff --git a/futility/file_type_usbpd1.c b/futility/file_type_usbpd1.c index 81430855..131e0033 100644 --- a/futility/file_type_usbpd1.c +++ b/futility/file_type_usbpd1.c @@ -256,6 +256,7 @@ done: */ static enum vb2_signature_algorithm sigs[] = { VB2_SIG_RSA2048, + VB2_SIG_RSA2048_EXP3, VB2_SIG_RSA1024, VB2_SIG_RSA4096, VB2_SIG_RSA8192, @@ -277,6 +278,7 @@ static uint32_t usbpd1_packed_key_size(enum vb2_signature_algorithm sig_alg) case VB2_SIG_RSA1024: return 272; case VB2_SIG_RSA2048: + case VB2_SIG_RSA2048_EXP3: return 528; case VB2_SIG_RSA4096: return 1040; diff --git a/host/lib21/host_key.c b/host/lib21/host_key.c index ecb7328b..be36df71 100644 --- a/host/lib21/host_key.c +++ b/host/lib21/host_key.c @@ -23,6 +23,7 @@ const struct vb2_text_vs_enum vb2_text_vs_sig[] = { {"RSA2048", VB2_SIG_RSA2048}, {"RSA4096", VB2_SIG_RSA4096}, {"RSA8192", VB2_SIG_RSA8192}, + {"RSA2048EXP3", VB2_SIG_RSA2048_EXP3}, {0, 0} }; @@ -403,7 +404,10 @@ int vb2_public_key_read_keyb(struct vb2_public_key **key_ptr, if (vb2_read_file(filename, &key_data, &key_size)) return VB2_ERROR_READ_KEYB_DATA; - /* Guess the signature algorithm from the key size */ + /* Guess the signature algorithm from the key size + * Note: This only considers exponent F4 keys, as there is no way to + * distinguish between exp 3 and F4 based on size. Vboot API 2.1 is + * required to make proper use of exp 3 keys. */ for (sig_alg = VB2_SIG_RSA1024; sig_alg <= VB2_SIG_RSA8192; sig_alg++) { if (key_size == vb2_packed_key_size(sig_alg)) break; @@ -560,17 +564,27 @@ int vb2_public_key_hash(struct vb2_public_key *key, enum vb2_signature_algorithm vb2_rsa_sig_alg(struct rsa_st *rsa) { + int exp = BN_get_word(rsa->e); int bits = BN_num_bits(rsa->n); - switch (bits) { - case 1024: - return VB2_SIG_RSA1024; - case 2048: - return VB2_SIG_RSA2048; - case 4096: - return VB2_SIG_RSA4096; - case 8192: - return VB2_SIG_RSA8192; + switch (exp) { + case RSA_3: + switch (bits) { + case 2048: + return VB2_SIG_RSA2048_EXP3; + } + break; + case RSA_F4: + switch (bits) { + case 1024: + return VB2_SIG_RSA1024; + case 2048: + return VB2_SIG_RSA2048; + case 4096: + return VB2_SIG_RSA4096; + case 8192: + return VB2_SIG_RSA8192; + } } /* no clue */ diff --git a/tests/common.sh b/tests/common.sh index 2b017cc5..78a47fa8 100644 --- a/tests/common.sh +++ b/tests/common.sh @@ -28,7 +28,7 @@ COL_BLUE='\E[34;1m' COL_STOP='\E[0;m' hash_algos=( sha1 sha256 sha512 ) -key_lengths=( 1024 2048 4096 8192 ) +key_lengths=( 1024 2048 4096 8192 2048_exp3 ) function happy { echo -e "${COL_GREEN}$*${COL_STOP}" 1>&2 diff --git a/tests/futility/test_show_rwsig.sh b/tests/futility/test_show_rwsig.sh index 7ff25571..915842d6 100755 --- a/tests/futility/test_show_rwsig.sh +++ b/tests/futility/test_show_rwsig.sh @@ -13,7 +13,7 @@ DATADIR="${SCRIPTDIR}/data" TESTKEYS=${SRCDIR}/tests/testkeys # Do not test 8192 as the signature length is > 1024 bytes -SIGS="1024 2048 4096" +SIGS="1024 2048 4096 2048_exp3" HASHES="SHA1 SHA256 SHA512" set -o pipefail diff --git a/tests/gen_test_keys.sh b/tests/gen_test_keys.sh index dbb17419..04315ac3 100755 --- a/tests/gen_test_keys.sh +++ b/tests/gen_test_keys.sh @@ -25,7 +25,15 @@ function generate_keys { continue fi - openssl genrsa -F4 -out ${key_base}.pem $i + # Extract exponent from key_length name, if necessary + exp="F4" + bits=$i + if [ "${i##*_exp}" != "${i}" ]; then + exp="${i##*_exp}" + bits="${i%%_exp${exp}}" + fi + + openssl genrsa -${exp} -out ${key_base}.pem ${bits} # Generate self-signed certificate from key. openssl req -batch -new -x509 -key ${key_base}.pem \ -out ${key_base}.crt diff --git a/tests/testcases/test_file.rsa2048_exp3_sha1.sig b/tests/testcases/test_file.rsa2048_exp3_sha1.sig Binary files differnew file mode 100644 index 00000000..75cd3ba4 --- /dev/null +++ b/tests/testcases/test_file.rsa2048_exp3_sha1.sig diff --git a/tests/testcases/test_file.rsa2048_exp3_sha256.sig b/tests/testcases/test_file.rsa2048_exp3_sha256.sig new file mode 100644 index 00000000..1192c8e3 --- /dev/null +++ b/tests/testcases/test_file.rsa2048_exp3_sha256.sig @@ -0,0 +1,2 @@ + _#ٌ%:aollnLNAUʩu4yѷ_02mԩ*a.Ъa-f@9+"+|+YxH4~ƛVW<vO5:@8bp'XzLLQ4 +J~6 iQC9]Sa qOnl_x-inuyzKi2|xԂIVg=ݬ~Gΰ^ u7TȘ =Kk,%*
\ No newline at end of file diff --git a/tests/testcases/test_file.rsa2048_exp3_sha512.sig b/tests/testcases/test_file.rsa2048_exp3_sha512.sig Binary files differnew file mode 100644 index 00000000..155474a1 --- /dev/null +++ b/tests/testcases/test_file.rsa2048_exp3_sha512.sig diff --git a/tests/testkeys/key_rsa2048_exp3.crt b/tests/testkeys/key_rsa2048_exp3.crt new file mode 100644 index 00000000..1c88aea8 --- /dev/null +++ b/tests/testkeys/key_rsa2048_exp3.crt @@ -0,0 +1,20 @@ +-----BEGIN CERTIFICATE----- +MIIDWzCCAkOgAwIBAgIJAO+pvxf/+8DVMA0GCSqGSIb3DQEBCwUAMEUxCzAJBgNV +BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX +aWRnaXRzIFB0eSBMdGQwHhcNMTcwMjA3MDgzNTQ5WhcNMTcwMzA5MDgzNTQ5WjBF +MQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50 +ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIIBIDANBgkqhkiG9w0BAQEFAAOCAQ0AMIIB +CAKCAQEA3UvKSmYs87zzCjmpwlSJlOdsoz+7JFekYTbUizUwf+k20mz9d042zL3X +PFenwKsNwrqS0+iJ+zwLMXmDG5+Jnh/4k1xCpjz9gAoIuTHYSR+nFfvJBocdZhiX +LAZW1RSbqYaZJn67JR4GgajrmhJkk1nOhY1y4kPqEwuVbWFX5V50ZiDta0iqUyph +ADb3Z0xBRS6SjRJAtyV2KiR6oi15qnKCD9rxIOtWAUMUjmhZeSpxUS4+iPsEh7j4 +oKlMys7Ty2NXxxo12f6orz0vJn3zcaj2XFgQZNZF56W5N5VjXIiDPNYoNArDICXm +BhhtAYRh+tGGsUotNKiC4k4hufEvVQIBA6NQME4wHQYDVR0OBBYEFHfxG/+7G+zh +jH4d8VpC/dnCXTN0MB8GA1UdIwQYMBaAFHfxG/+7G+zhjH4d8VpC/dnCXTN0MAwG +A1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAMJe2ClDV+DeQudWz++yTLUz +qgn6XHSgPv/jgyWXxEcguh6G4GXuCgEykkJ2l4Zyb9+0QurOa4/cDv1Vu54p60ZF +OhQyX0YFNTXIXJkuFy2KEClSpQ0yglrFaPzBmpmJY4LMR2Dbxze/f+i94HaeQDFd +Sze8VyJxnqagBNX6QgxWEhUvIs/OVwkkJ2ZoK7JkhX9gDzxUZ01EvFkoszQNxDgy +ETFxBf/pbZspKiyOVoWCm4OzKXIAqRqWX1Gg2BFUdxLof6XbD/F96xcsUgZkTBuu +thBMQrCxGwmbZhwnfoZ0PgcagCdqlLkUUsOJuj4AGDK+4X8Rdzlc5wbjPBAgt9U= +-----END CERTIFICATE----- diff --git a/tests/testkeys/key_rsa2048_exp3.keyb b/tests/testkeys/key_rsa2048_exp3.keyb Binary files differnew file mode 100644 index 00000000..3f8c5645 --- /dev/null +++ b/tests/testkeys/key_rsa2048_exp3.keyb diff --git a/tests/testkeys/key_rsa2048_exp3.pem b/tests/testkeys/key_rsa2048_exp3.pem new file mode 100644 index 00000000..ca3127c0 --- /dev/null +++ b/tests/testkeys/key_rsa2048_exp3.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEA3UvKSmYs87zzCjmpwlSJlOdsoz+7JFekYTbUizUwf+k20mz9 +d042zL3XPFenwKsNwrqS0+iJ+zwLMXmDG5+Jnh/4k1xCpjz9gAoIuTHYSR+nFfvJ +BocdZhiXLAZW1RSbqYaZJn67JR4GgajrmhJkk1nOhY1y4kPqEwuVbWFX5V50ZiDt +a0iqUyphADb3Z0xBRS6SjRJAtyV2KiR6oi15qnKCD9rxIOtWAUMUjmhZeSpxUS4+ +iPsEh7j4oKlMys7Ty2NXxxo12f6orz0vJn3zcaj2XFgQZNZF56W5N5VjXIiDPNYo +NArDICXmBhhtAYRh+tGGsUotNKiC4k4hufEvVQIBAwKCAQEAk4fcMZlzTSiiBtEb +1uMGY0TzF3/SGDptliSNsiN1qpt54Z3+T4l53dPk0uUagHIJLHxh4psGp31cy6ZX +Z7+xFBVQYj2BxCipAAawe3aQML/EuVKGBFoTmWW6HVmPOLhnxlm7bv8nbhQEVnCd +EWGYYjvfA7Oh7C1Gt10OSOuP7j26NRur2gNita/MT2FCKxQ6Dnu2lkTc9I5XkP2+ +v7BhLG/zkwvOcGeXtSbmAXXh5ON/igSe0WZvMKj0ql+f8S7vnevoDOFIeHm7diCO +Ej0fWavFMAPOZokBzQycSuQ0awrV8gM4xMpahBjwRcC3UMoNLmlvo8kcbkxJ0Sbv +AcLMMwKBgQD+ZjSJyf6Or48fyOlWG0/do1mpJogoawyOK5mF3Z7O6wVm+DMpXQsE +ApIZzblMajmZQcvZ/AR+/mDV2s34x6WGFkR7GMIHHoaIuA3Qk6jm/qFdgcAmumHU +vtrGDX+votDfBeoIb+bWCRjjD3SeEpoNjy/1DYNQmYkRQ0zIJZ9QUwKBgQDesELh +2kUHkxOOwDu+C14MjBtXhSLM3UNkpQ5WpQYY/MUtuxYSG0Tubvahvn46N5uYwFt2 +UtzewFqzxkvkGWLmSD0AmwZCBsGGxf6Jd3ldbIXxEpI0EKbudTgIub9lGSdjS+dK +nPRlUOeajgK79btApgNqLhkx9a0C5UbzEa2stwKBgQCpmXhb2/8Jyl9qhfDkEjU+ +bOZwxFrFnLMJcmZZPmnfR1jvUCIbk1ytVwwRM9DdnCZmK907/VhUqZXj5zP7L8Ou +uYL8uywEvwRbJV6LDRtEqcDpASrEfEE4fzyECP/KbIs/WUawSpnkBhCXX6MUDGaz +tMqjXleLEQYLgjMwGRTgNwKBgQCUdYHr5tivt2JfKtJ+sj6zCBI6WMHd6NeYbgmP +GK67Uy4efLlhZ4NJn08Wfv7Reme7KuekNz3p1ZHNLt1Cu5dEMCirEgQsBIEEg/8G +T6Y+SFlLYbbNYG9Jo3qwe9TuEMTs3UTcaKLuNe+8Xqx9TnzVxAJGyWYhTnNXQ4Si +C8kdzwKBgQCmfbKHyzXa0E1dFQKU59hXBhSKBp6ZvD/pF5Ed4tZW0ubdCVs7665p +cdi5ljpJsjqHzWTn8TLdbXZ2jYPPNTC89wZ8F1lrPHCYz/Ifnoahlcbp7OIiIcWx +S6YTzuFdpxAAdwstY91LMxzzMZm47hZUw/KzEVfzIpdyLbeCouohzg== +-----END RSA PRIVATE KEY----- diff --git a/tests/testkeys/key_rsa2048_exp3.sha1.vbprivk b/tests/testkeys/key_rsa2048_exp3.sha1.vbprivk Binary files differnew file mode 100644 index 00000000..357a53a7 --- /dev/null +++ b/tests/testkeys/key_rsa2048_exp3.sha1.vbprivk diff --git a/tests/testkeys/key_rsa2048_exp3.sha1.vbpubk b/tests/testkeys/key_rsa2048_exp3.sha1.vbpubk Binary files differnew file mode 100644 index 00000000..8f17ce92 --- /dev/null +++ b/tests/testkeys/key_rsa2048_exp3.sha1.vbpubk diff --git a/tests/testkeys/key_rsa2048_exp3.sha256.vbprivk b/tests/testkeys/key_rsa2048_exp3.sha256.vbprivk Binary files differnew file mode 100644 index 00000000..eb10c73c --- /dev/null +++ b/tests/testkeys/key_rsa2048_exp3.sha256.vbprivk diff --git a/tests/testkeys/key_rsa2048_exp3.sha256.vbpubk b/tests/testkeys/key_rsa2048_exp3.sha256.vbpubk Binary files differnew file mode 100644 index 00000000..70bfcf6e --- /dev/null +++ b/tests/testkeys/key_rsa2048_exp3.sha256.vbpubk diff --git a/tests/testkeys/key_rsa2048_exp3.sha512.vbprivk b/tests/testkeys/key_rsa2048_exp3.sha512.vbprivk Binary files differnew file mode 100644 index 00000000..0e1f862c --- /dev/null +++ b/tests/testkeys/key_rsa2048_exp3.sha512.vbprivk diff --git a/tests/testkeys/key_rsa2048_exp3.sha512.vbpubk b/tests/testkeys/key_rsa2048_exp3.sha512.vbpubk Binary files differnew file mode 100644 index 00000000..429d2c3d --- /dev/null +++ b/tests/testkeys/key_rsa2048_exp3.sha512.vbpubk diff --git a/utility/dumpRSAPublicKey.c b/utility/dumpRSAPublicKey.c index b3b7b96b..fc238d7f 100644 --- a/utility/dumpRSAPublicKey.c +++ b/utility/dumpRSAPublicKey.c @@ -23,8 +23,9 @@ int check(RSA* key) { int public_exponent = BN_get_word(key->e); int modulus = BN_num_bits(key->n); - if (public_exponent != 65537) { - fprintf(stderr, "WARNING: Public exponent should be 65537 (but is %d).\n", + if (public_exponent != 3 && public_exponent != 65537) { + fprintf(stderr, + "WARNING: Public exponent should be 3 or 65537 (but is %d).\n", public_exponent); } |