Skip to content

Commit 5d5fb38

Browse files
committed
Add CertKeyData structure
See: RustCrypto/SSH#233 Signed-off-by: Wiktor Kwapisiewicz <wiktor@metacode.biz>
1 parent 486792b commit 5d5fb38

File tree

7 files changed

+90
-12
lines changed

7 files changed

+90
-12
lines changed

examples/openpgp-card-agent.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,8 @@ impl Session for CardSession {
173173
return Ok::<_, Box<dyn std::error::Error>>(Some(Identity {
174174
pubkey: KeyData::Ed25519(Ed25519PublicKey(
175175
e.data().try_into()?,
176-
)),
176+
))
177+
.into(),
177178
comment: ident,
178179
}));
179180
}
@@ -231,7 +232,8 @@ impl Session for CardSession {
231232
return Ok::<_, Box<dyn std::error::Error>>(Some(Identity {
232233
pubkey: KeyData::Ed25519(Ed25519PublicKey(
233234
e.data().try_into()?,
234-
)),
235+
))
236+
.into(),
235237
comment: ident,
236238
}));
237239
}

examples/pgp-wrapper.rs

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ use service_binding::Binding;
6464
use ssh_agent_lib::{
6565
agent::Session,
6666
client::connect,
67-
proto::{Extension, SignRequest},
67+
proto::{CertKeyData, Extension, SignRequest},
6868
};
6969
use ssh_key::public::KeyData;
7070
use tokio::runtime::Runtime;
@@ -372,7 +372,10 @@ fn main() -> testresult::TestResult {
372372
let mut keyflags = KeyFlags::default();
373373
keyflags.set_encrypt_comms(true);
374374
keyflags.set_encrypt_storage(true);
375-
let pk = ssh_to_pgp(decryption_id.pubkey.clone(), KeyRole::Decryption);
375+
let CertKeyData::Key(pubkey) = &decryption_id.pubkey else {
376+
panic!("Only pubkeys are supported.");
377+
};
378+
let pk = ssh_to_pgp(pubkey.clone(), KeyRole::Decryption);
376379
vec![pgp::PublicSubkey::new(
377380
pgp::packet::PublicSubkey::new(
378381
pk.packet_version(),
@@ -388,6 +391,9 @@ fn main() -> testresult::TestResult {
388391
vec![]
389392
};
390393

394+
let CertKeyData::Key(pubkey) = pubkey else {
395+
panic!("Only pubkeys are supported.");
396+
};
391397
let signer = WrappedKey::new(pubkey.clone(), client, KeyRole::Signing);
392398
let mut keyflags = KeyFlags::default();
393399
keyflags.set_sign(true);
@@ -411,6 +417,9 @@ fn main() -> testresult::TestResult {
411417
signed_pk.to_writer(&mut std::io::stdout())?;
412418
}
413419
Args::Sign => {
420+
let CertKeyData::Key(pubkey) = pubkey else {
421+
panic!("Only pubkeys are supported.");
422+
};
414423
let signer = WrappedKey::new(pubkey.clone(), client, KeyRole::Signing);
415424
let signature = SignatureConfig::new_v4(
416425
SignatureVersion::V4,
@@ -445,8 +454,10 @@ fn main() -> testresult::TestResult {
445454
pgp::packet::write_packet(&mut std::io::stdout(), &signature)?;
446455
}
447456
Args::Decrypt => {
448-
let decryptor =
449-
WrappedKey::new(decrypt_ids[0].pubkey.clone(), client, KeyRole::Decryption);
457+
let CertKeyData::Key(pubkey) = decrypt_ids[0].pubkey else {
458+
panic!("Only pubkeys are supported");
459+
};
460+
let decryptor = WrappedKey::new(pubkey.clone(), client, KeyRole::Decryption);
450461
let message = Message::from_bytes(std::io::stdin())?;
451462

452463
let Message::Encrypted { esk, edata } = message else {

src/proto/message.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
//! Agent protocol message structures.
22
33
mod add_remove;
4+
mod cert_key_data;
45
mod extension;
56
mod identity;
67
mod request;
@@ -9,7 +10,8 @@ mod sign;
910
mod unparsed;
1011

1112
pub use self::{
12-
add_remove::*, extension::*, identity::*, request::*, response::*, sign::*, unparsed::*,
13+
add_remove::*, cert_key_data::*, extension::*, identity::*, request::*, response::*, sign::*,
14+
unparsed::*,
1315
};
1416
#[doc(hidden)]
1517
/// For compatibility with pre-0.5.0 type alias in this module

src/proto/message/cert_key_data.rs

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
use std::str::FromStr as _;
2+
3+
use ssh_encoding::{CheckedSum as _, Decode, Encode, Reader};
4+
use ssh_key::{public::KeyData, Algorithm, Certificate, PublicKey};
5+
6+
use crate::proto::{Error, Result};
7+
8+
#[derive(Debug, PartialEq, Eq, Clone)]
9+
pub enum CertKeyData {
10+
Key(KeyData),
11+
Cert(Certificate),
12+
}
13+
14+
impl Decode for CertKeyData {
15+
type Error = Error;
16+
17+
fn decode(reader: &mut impl Reader) -> core::result::Result<Self, Self::Error> {
18+
let alg = String::decode(reader)?;
19+
let cert_alg = Algorithm::new_certificate(&alg);
20+
21+
if let Ok(algorithm) = cert_alg {
22+
let certificate = Certificate::decode_as(algorithm.clone(), reader)?;
23+
Ok(Self::Cert(certificate))
24+
} else {
25+
let algorithm = Algorithm::from_str(&alg).map_err(ssh_encoding::Error::from)?;
26+
let pubkey = KeyData::decode_as(reader, algorithm)?;
27+
Ok(Self::Key(pubkey))
28+
}
29+
}
30+
}
31+
32+
impl Encode for CertKeyData {
33+
fn encoded_len(&self) -> std::result::Result<usize, ssh_encoding::Error> {
34+
match self {
35+
Self::Key(pubkey) => pubkey.encoded_len(),
36+
Self::Cert(certificate) => certificate.encoded_len(),
37+
}
38+
}
39+
40+
fn encode(
41+
&self,
42+
writer: &mut impl ssh_encoding::Writer,
43+
) -> std::result::Result<(), ssh_encoding::Error> {
44+
match self {
45+
Self::Key(pubkey) => pubkey.encode(writer),
46+
Self::Cert(certificate) => certificate.encode(writer),
47+
}
48+
}
49+
}
50+
51+
impl From<KeyData> for CertKeyData {
52+
fn from(value: KeyData) -> Self {
53+
Self::Key(value)
54+
}
55+
}
56+
57+
impl From<Certificate> for CertKeyData {
58+
fn from(value: Certificate) -> Self {
59+
Self::Cert(value)
60+
}
61+
}

src/proto/message/identity.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
use ssh_encoding::{self, CheckedSum, Decode, Encode, Reader, Writer};
44
use ssh_key::public::KeyData;
55

6+
use super::cert_key_data::CertKeyData;
67
use crate::proto::{Error, Result};
78

89
/// Data returned to the client when listing keys.
@@ -13,7 +14,7 @@ use crate::proto::{Error, Result};
1314
#[derive(Clone, PartialEq, Debug)]
1415
pub struct Identity {
1516
/// A standard public-key encoding of an underlying key.
16-
pub pubkey: KeyData,
17+
pub pubkey: CertKeyData,
1718

1819
/// A human-readable comment
1920
pub comment: String,
@@ -36,7 +37,7 @@ impl Decode for Identity {
3637
type Error = Error;
3738

3839
fn decode(reader: &mut impl Reader) -> Result<Self> {
39-
let pubkey = reader.read_prefixed(KeyData::decode)?;
40+
let pubkey = reader.read_prefixed(CertKeyData::decode)?;
4041
let comment = String::decode(reader)?;
4142

4243
Ok(Self { pubkey, comment })

src/proto/message/sign.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
use ssh_encoding::{self, CheckedSum, Decode, Encode, Reader, Writer};
44
use ssh_key::public::KeyData;
55

6+
use super::cert_key_data::CertKeyData;
67
use crate::proto::{Error, Result};
78

89
/// Signature request with data to be signed with a key in an agent.
@@ -13,7 +14,7 @@ use crate::proto::{Error, Result};
1314
#[derive(Clone, PartialEq, Debug)]
1415
pub struct SignRequest {
1516
/// The public key portion of the [`Identity`](super::Identity) in the agent to sign the data with
16-
pub pubkey: KeyData,
17+
pub pubkey: CertKeyData,
1718

1819
/// Binary data to be signed
1920
pub data: Vec<u8>,
@@ -27,7 +28,7 @@ impl Decode for SignRequest {
2728
type Error = Error;
2829

2930
fn decode(reader: &mut impl Reader) -> Result<Self> {
30-
let pubkey = reader.read_prefixed(KeyData::decode)?;
31+
let pubkey = reader.read_prefixed(CertKeyData::decode)?;
3132
let data = Vec::decode(reader)?;
3233
let flags = u32::decode(reader)?;
3334

tests/roundtrip/expected/resp_parse_identities.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use super::fixtures;
55

66
pub fn expected() -> Response {
77
Response::IdentitiesAnswer(vec![Identity {
8-
pubkey: KeyData::Ecdsa(fixtures::demo_key().into()),
8+
pubkey: KeyData::Ecdsa(fixtures::demo_key().into()).into(),
99
comment: "baloo@angela".to_string(),
1010
}])
1111
}

0 commit comments

Comments
 (0)