Skip to content

Commit cf4965a

Browse files
committed
rsa: Introduce rsa driver
Add rsa driver based on the implementation in aspeed zephyr sdk. The patch also add functional test and rsa test data generator. How to verify driver: 1. You may use the existing test vectors in tests/functional/rsa_test_vec.rs, or 2. Generate fresh vectors by running: python3 scripts/rsa_test_vec_gen.py > src/tests/functional/rsa_test_vec.rs 3. Build and run the image Signed-off-by: Steven Lee <steven_lee@aspeedtech.com>
1 parent a5606b4 commit cf4965a

File tree

7 files changed

+1220
-1
lines changed

7 files changed

+1220
-1
lines changed

scripts/rsa_test_vec_gen.py

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
from cryptography.hazmat.primitives.asymmetric import rsa, padding
2+
from cryptography.hazmat.primitives import hashes
3+
from cryptography.hazmat.backends import default_backend
4+
from textwrap import wrap
5+
import hashlib
6+
import os
7+
8+
def format_hex_array(data: bytes) -> str:
9+
lines = wrap(data.hex(), 64)
10+
return '\n'.join('"' + line + '"' for line in lines)
11+
12+
def rust_hex(label: str, data: bytes, indent: int = 16) -> str:
13+
from textwrap import wrap
14+
15+
hex_lines = wrap(data.hex(), 64)
16+
hex_body = '\n'.join(" " * indent + f'"{line}"' for line in hex_lines)
17+
return f"{label}: &hex!(\n{hex_body}\n{' ' * 8}),"
18+
19+
def get_hash_algorithm(name: str):
20+
if name == "sha256":
21+
return hashes.SHA256(), hashlib.sha256
22+
elif name == "sha384":
23+
return hashes.SHA384(), hashlib.sha384
24+
elif name == "sha512":
25+
return hashes.SHA512(), hashlib.sha512
26+
else:
27+
raise ValueError("Unsupported hash algorithm")
28+
29+
def gen_rsa_testvec(key_size: int, hash_name: str) -> str:
30+
hash_algo, hashlib_fn = get_hash_algorithm(hash_name)
31+
32+
key = rsa.generate_private_key(
33+
public_exponent=65537,
34+
key_size=key_size,
35+
backend=default_backend()
36+
)
37+
38+
private_numbers = key.private_numbers()
39+
public_numbers = private_numbers.public_numbers
40+
41+
modulus_len = key_size // 8
42+
n = public_numbers.n.to_bytes(modulus_len, byteorder='big')
43+
e = public_numbers.e.to_bytes(3, byteorder='big')
44+
d = private_numbers.d.to_bytes(modulus_len, byteorder='big')
45+
46+
message = os.urandom(64)
47+
message_digest = hashlib_fn(message).digest()
48+
49+
digest = hashes.Hash(hash_algo, backend=default_backend())
50+
digest.update(message_digest)
51+
digest_value = digest.finalize()
52+
53+
signature = key.sign(
54+
message_digest,
55+
padding.PKCS1v15(),
56+
hash_algo
57+
)
58+
59+
lines = []
60+
lines.append(f" // RSA-{key_size} with {hash_name.upper()}")
61+
lines.append(" RsaTestVec {")
62+
lines.append(" k: RsaKey {")
63+
lines.append(" " + rust_hex('m', n))
64+
lines.append(" " + rust_hex('d', d))
65+
lines.append(" " + rust_hex('e', e))
66+
lines.append(f" m_bits: {key_size},")
67+
lines.append(f" d_bits: {key_size},")
68+
lines.append(f" e_bits: {len(e) * 8},")
69+
lines.append(" },")
70+
lines.append(" " + rust_hex('digest', digest_value))
71+
lines.append(" " + rust_hex('signature', signature))
72+
lines.append(f" s_size: {len(signature)},")
73+
lines.append(f" d_size: {len(digest_value)},")
74+
lines.append(" },")
75+
return "\n".join(lines)
76+
77+
def main():
78+
print("""use hex_literal::hex;
79+
80+
pub struct RsaKey {
81+
pub m: &'static [u8],
82+
pub d: &'static [u8],
83+
pub e: &'static [u8],
84+
pub m_bits: usize,
85+
pub d_bits: usize,
86+
pub e_bits: usize,
87+
}
88+
89+
pub struct RsaTestVec {
90+
pub k: RsaKey,
91+
pub digest: &'static [u8],
92+
pub signature: &'static [u8],
93+
pub s_size: usize,
94+
pub d_size: usize,
95+
}""")
96+
97+
print()
98+
print("pub static RSA_VERIFY_TV: &[RsaTestVec] = &[")
99+
for key_size in [2048, 3072, 4096]:
100+
for hash_name in ["sha256", "sha384", "sha512"]:
101+
print(gen_rsa_testvec(key_size, hash_name))
102+
print("];")
103+
104+
if __name__ == "__main__":
105+
main()
106+

src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,6 @@ pub mod uart;
33
pub mod watchdog;
44
pub mod hash;
55
pub mod ecdsa;
6+
pub mod rsa;
67
pub mod tests;
78
pub mod syscon;

src/main.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,12 @@ use aspeed_ddk::watchdog::WdtController;
1111
use fugit::MillisDurationU32 as MilliSeconds;
1212
use aspeed_ddk::hash::Controller;
1313
use aspeed_ddk::syscon::SysCon;
14-
use aspeed_ddk::ecdsa::{AspeedEcdsa};
14+
use aspeed_ddk::ecdsa::AspeedEcdsa;
15+
use aspeed_ddk::rsa::AspeedRsa;
1516

1617
use aspeed_ddk::tests::functional::hash_test::run_hash_tests;
1718
use aspeed_ddk::tests::functional::ecdsa_test::run_ecdsa_tests;
19+
use aspeed_ddk::tests::functional::rsa_test::run_rsa_tests;
1820
use panic_halt as _;
1921

2022
use cortex_m_rt::entry;
@@ -143,6 +145,9 @@ fn main() -> ! {
143145
let mut ecdsa = AspeedEcdsa::new(&secure, delay.clone());
144146
run_ecdsa_tests(&mut uart_controller, &mut ecdsa);
145147

148+
let mut rsa = AspeedRsa::new(&secure, delay);
149+
run_rsa_tests(&mut uart_controller, &mut rsa);
150+
146151
test_wdt(&mut uart_controller);
147152
// Initialize the peripherals here if needed
148153
loop {}

0 commit comments

Comments
 (0)