diff --git a/Cargo.toml b/Cargo.toml index e2d1461..ae4e1d7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -57,6 +57,7 @@ expectrl = "0.6.0" trussed-usbip = { git = "https://github.com/trussed-dev/pc-usbip-runner", default-features = false, features = ["ccid"], rev = "f3a680ca4c9a1411838ae0774f1713f79d4c2979"} usbd-ccid = { version = "0.2.0", features = ["highspeed-usb"]} rand = "0.8.5" +asn1 = "0.15.2" [features] default = [] diff --git a/tests/pivy.rs b/tests/pivy.rs index f81a9e5..ea9b15b 100644 --- a/tests/pivy.rs +++ b/tests/pivy.rs @@ -86,6 +86,65 @@ fn ecdh() { with_vsc(WITHOUT_UUID, test); } +#[test_log::test] +fn sign() { + let test_rsa = || { + let mut p = spawn(&format!("pivy-tool -A 3des -K 010203040506070801020304050607080102030405060708 generate 9A -a rsa2048 -P 123456")).unwrap(); + p.expect(Regex("ssh-rsa (?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)? PIV_slot_9A@[A-F0-9]{20}")).unwrap(); + p.expect(Eof).unwrap(); + assert_eq!(p.wait().unwrap(), WaitStatus::Exited(p.pid(), 0)); + + let mut p = Command::new("pivy-tool") + .args(["sign", "9A", "-P", "123456"]) + .stdin(Stdio::piped()) + .stdout(Stdio::piped()) + .spawn() + .unwrap(); + let mut stdin = p.stdin.take().unwrap(); + write!(stdin, "data").unwrap(); + drop(stdin); + + assert_eq!(p.wait().unwrap().code(), Some(0)); + }; + + let test_p256 = || { + let mut p = spawn(&format!("pivy-tool -A 3des -K 010203040506070801020304050607080102030405060708 generate 9A -a eccp256 -P 123456")).unwrap(); + p.expect(Regex("ecdsa-sha2-nistp256 (?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)? PIV_slot_9A@[A-F0-9]{20}")).unwrap(); + p.expect(Eof).unwrap(); + assert_eq!(p.wait().unwrap(), WaitStatus::Exited(p.pid(), 0)); + + let mut p = Command::new("pivy-tool") + .args(["sign", "9A", "-P", "123456"]) + .stdin(Stdio::piped()) + .stdout(Stdio::piped()) + .spawn() + .unwrap(); + let mut stdin = p.stdin.take().unwrap(); + let mut stdout = p.stdout.take().unwrap(); + write!(stdin, "data").unwrap(); + drop(stdin); + + let mut out = Vec::new(); + stdout.read_to_end(&mut out).unwrap(); + // Check that the signature is an asn.1 sequence + let res: asn1::ParseResult<_> = asn1::parse(&out, |d| { + return d.read_element::()?.parse(|d| { + d.read_element::()?; + d.read_element::()?; + return Ok(()); + }); + }); + res.unwrap(); + + assert_eq!(p.wait().unwrap().code(), Some(0)); + }; + + let test = || (test_rsa(), test_p256()); + + with_vsc(WITH_UUID, test); + with_vsc(WITHOUT_UUID, test); +} + const LARGE_CERT: &str = "-----BEGIN CERTIFICATE----- MIIHNTCCBh2gAwIBAgIUBeJLVUnOULY3fhLvjaWOZe/qWfYwDQYJKoZIhvcNAQEL BQAwggIoMQswCQYDVQQGEwJURTGBizCBiAYDVQQIDIGAVEVTVFRFU1RURVNUVEVT