ssh_agent_lib/proto/message/add_remove/
credential.rs1use core::str::FromStr;
4
5use ssh_encoding::{self, CheckedSum, Decode, Encode, Reader, Writer};
6use ssh_key::{certificate::Certificate, private::KeypairData, Algorithm};
7
8use crate::proto::{Error, PrivateKeyData, Result};
9
10#[derive(Clone, PartialEq, Debug)]
19pub enum Credential {
20 Key {
22 privkey: KeypairData,
24
25 comment: String,
27 },
28
29 Cert {
31 algorithm: Algorithm,
33
34 certificate: Certificate,
36
37 privkey: PrivateKeyData,
39
40 comment: String,
42 },
43}
44
45impl Decode for Credential {
46 type Error = Error;
47
48 fn decode(reader: &mut impl Reader) -> Result<Self> {
49 let alg = String::decode(reader)?;
50 let cert_alg = Algorithm::new_certificate(&alg);
51
52 if let Ok(algorithm) = cert_alg {
53 let certificate = reader.read_prefixed(|reader| {
54 let cert = Certificate::decode(reader)?;
55 Ok::<_, Error>(cert)
56 })?;
57 let privkey = PrivateKeyData::decode_as(reader, algorithm.clone())?;
58 let comment = String::decode(reader)?;
59
60 Ok(Credential::Cert {
61 algorithm,
62 certificate,
63 privkey,
64 comment,
65 })
66 } else {
67 let algorithm = Algorithm::from_str(&alg).map_err(ssh_encoding::Error::from)?;
68 let privkey = KeypairData::decode_as(reader, algorithm)?;
69 let comment = String::decode(reader)?;
70 Ok(Credential::Key { privkey, comment })
71 }
72 }
73}
74
75impl Encode for Credential {
76 fn encoded_len(&self) -> ssh_encoding::Result<usize> {
77 match self {
78 Self::Key { privkey, comment } => {
79 [privkey.encoded_len()?, comment.encoded_len()?].checked_sum()
80 }
81 Self::Cert {
82 algorithm,
83 certificate,
84 privkey,
85 comment,
86 } => [
87 algorithm.to_certificate_type().encoded_len()?,
88 certificate.encoded_len_prefixed()?,
89 privkey.encoded_len()?,
90 comment.encoded_len()?,
91 ]
92 .checked_sum(),
93 }
94 }
95
96 fn encode(&self, writer: &mut impl Writer) -> ssh_encoding::Result<()> {
97 match self {
98 Self::Key { privkey, comment } => {
99 privkey.encode(writer)?;
100 comment.encode(writer)
101 }
102 Self::Cert {
103 algorithm,
104 certificate,
105 privkey,
106 comment,
107 } => {
108 algorithm.to_certificate_type().encode(writer)?;
109 certificate.encode_prefixed(writer)?;
110 privkey.encode(writer)?;
111 comment.encode(writer)
112 }
113 }
114 }
115}