rpgpie_sop/
lib.rs

1// SPDX-FileCopyrightText: Heiko Schaefer <heiko@schaefer.name>
2// SPDX-License-Identifier: MIT OR Apache-2.0
3
4mod cmd;
5mod util;
6
7use std::io;
8
9use pgp::packet::Signature;
10use rpgpie::certificate::Certificate;
11use rpgpie::tsk::Tsk;
12use sop::ops::{CertifyUserID, MergeCerts, UpdateKey, ValidateUserID};
13
14#[derive(Clone, Copy, Default)]
15pub struct RPGSOP {}
16
17// SOP singleton
18const SOP: RPGSOP = RPGSOP {};
19
20#[derive(Clone, Default)]
21pub struct Certs {
22    certs: Vec<Certificate>,
23    source_name: Option<String>,
24}
25
26pub struct Keys {
27    keys: Vec<Tsk>,
28    source_name: Option<String>,
29}
30
31pub struct Sigs {
32    sigs: Vec<Signature>,
33    source_name: Option<String>,
34}
35
36impl sop::SOP<'_> for RPGSOP {
37    type Keys = Keys;
38    type Certs = Certs;
39    type Sigs = Sigs;
40
41    fn sopv_version(&self) -> sop::Result<&'static str> {
42        Ok("1.0")
43    }
44
45    fn version(&'_ self) -> sop::Result<Box<dyn sop::ops::Version>> {
46        Ok(Box::new(cmd::version::Version::new()))
47    }
48
49    fn generate_key(
50        &'_ self,
51    ) -> sop::Result<Box<dyn sop::ops::GenerateKey<Self, Self::Keys> + '_>> {
52        Ok(Box::new(cmd::generate::GenerateKey::new()))
53    }
54
55    fn change_key_password(
56        &'_ self,
57    ) -> sop::Result<Box<dyn sop::ops::ChangeKeyPassword<Self, Self::Keys>>> {
58        Ok(Box::new(cmd::password::ChangeKeyPassword::new()))
59    }
60
61    fn revoke_key(
62        &'_ self,
63    ) -> sop::Result<Box<dyn sop::ops::RevokeKey<Self, Self::Certs, Self::Keys>>> {
64        Ok(Box::new(cmd::revoke_key::RevokeKey::new()))
65    }
66
67    fn extract_cert(
68        &'_ self,
69    ) -> sop::Result<Box<dyn sop::ops::ExtractCert<Self, Self::Certs, Self::Keys> + '_>> {
70        Ok(Box::new(cmd::extract_cert::ExtractCert::new()))
71    }
72
73    fn update_key(&'_ self) -> sop::Result<Box<dyn UpdateKey<Self, Self::Certs, Self::Keys> + '_>> {
74        Err(sop::errors::Error::NotImplemented) // TODO
75    }
76
77    fn merge_certs(&'_ self) -> sop::Result<Box<dyn MergeCerts<Self, Self::Certs> + '_>> {
78        Ok(Box::new(cmd::merge_certs::MergeCerts::new()))
79    }
80
81    fn certify_userid(
82        &'_ self,
83    ) -> sop::Result<Box<dyn CertifyUserID<Self, Self::Certs, Self::Keys> + '_>> {
84        Err(sop::errors::Error::NotImplemented) // TODO
85    }
86
87    fn validate_userid(&'_ self) -> sop::Result<Box<dyn ValidateUserID<Self, Self::Certs> + '_>> {
88        Err(sop::errors::Error::NotImplemented) // TODO
89    }
90
91    fn sign(&'_ self) -> sop::Result<Box<dyn sop::ops::Sign<Self, Self::Keys, Self::Sigs> + '_>> {
92        Ok(Box::new(cmd::sign::Sign::new()))
93    }
94
95    fn verify(
96        &'_ self,
97    ) -> sop::Result<Box<dyn sop::ops::Verify<Self, Self::Certs, Self::Sigs> + '_>> {
98        Ok(Box::new(cmd::verify::Verify::new()))
99    }
100
101    fn encrypt(
102        &'_ self,
103    ) -> sop::Result<Box<dyn sop::ops::Encrypt<Self, Self::Certs, Self::Keys> + '_>> {
104        Ok(Box::new(cmd::encrypt::Encrypt::new()))
105    }
106
107    fn decrypt(
108        &'_ self,
109    ) -> sop::Result<Box<dyn sop::ops::Decrypt<Self, Self::Certs, Self::Keys> + '_>> {
110        Ok(Box::new(cmd::decrypt::Decrypt::new()))
111    }
112
113    fn armor(&'_ self) -> sop::Result<Box<dyn sop::ops::Armor>> {
114        Ok(Box::new(cmd::armor::Armor::new()))
115    }
116
117    fn dearmor(&'_ self) -> sop::Result<Box<dyn sop::ops::Dearmor>> {
118        Ok(Box::new(cmd::dearmor::Dearmor::new()))
119    }
120
121    fn inline_detach(&'_ self) -> sop::Result<Box<dyn sop::ops::InlineDetach<Self::Sigs>>> {
122        Ok(Box::new(cmd::detach::InlineDetach::new()))
123    }
124
125    fn inline_verify(
126        &'_ self,
127    ) -> sop::Result<Box<dyn sop::ops::InlineVerify<Self, Self::Certs> + '_>> {
128        Ok(Box::new(cmd::inline_verify::InlineVerify::new()))
129    }
130
131    fn inline_sign(&'_ self) -> sop::Result<Box<dyn sop::ops::InlineSign<Self, Self::Keys> + '_>> {
132        Ok(Box::new(cmd::inline_sign::InlineSign::new()))
133    }
134}
135
136impl sop::Load<'_, RPGSOP> for Certs {
137    fn from_reader(
138        _sop: &RPGSOP,
139        mut source: &mut (dyn io::Read + Send + Sync),
140        source_name: Option<String>,
141    ) -> sop::Result<Self> {
142        let certs = Certificate::load(&mut source).map_err(|e| match e {
143            rpgpie::Error::Io(e) => sop::errors::Error::IoError(e),
144            _ => sop::errors::Error::UnspecifiedFailure,
145        })?;
146
147        Ok(Certs { certs, source_name })
148    }
149
150    fn source_name(&self) -> Option<&str> {
151        self.source_name.as_deref()
152    }
153}
154
155impl sop::Save for Certs {
156    fn to_writer(
157        &self,
158        armored: bool,
159        sink: &mut (dyn io::Write + Send + Sync),
160    ) -> sop::Result<()> {
161        Certificate::save_all(&self.certs, armored, sink).map_err(|e| match e {
162            rpgpie::Error::Io(e) => sop::errors::Error::IoError(e),
163            _ => sop::errors::Error::UnspecifiedFailure,
164        })?;
165
166        Ok(())
167    }
168}
169
170impl sop::Load<'_, RPGSOP> for Keys {
171    fn from_reader(
172        _sop: &'_ RPGSOP,
173        mut source: &mut (dyn io::Read + Send + Sync),
174        source_name: Option<String>,
175    ) -> sop::Result<Self> {
176        let keys = Tsk::load(&mut source).map_err(|e| match e {
177            rpgpie::Error::Io(e) => sop::errors::Error::IoError(e),
178            _ => sop::errors::Error::UnspecifiedFailure,
179        })?;
180
181        Ok(Keys { keys, source_name })
182    }
183
184    fn source_name(&self) -> Option<&str> {
185        self.source_name.as_deref()
186    }
187}
188
189impl sop::Save for Keys {
190    fn to_writer(
191        &self,
192        armored: bool,
193        sink: &mut (dyn io::Write + Send + Sync),
194    ) -> sop::Result<()> {
195        Tsk::save_all(&self.keys, armored, sink).map_err(|e| match e {
196            rpgpie::Error::Io(e) => sop::errors::Error::IoError(e),
197            _ => sop::errors::Error::UnspecifiedFailure,
198        })?;
199
200        Ok(())
201    }
202}
203
204impl sop::Load<'_, RPGSOP> for Sigs {
205    fn from_reader(
206        _sop: &'_ RPGSOP,
207        mut source: &mut (dyn io::Read + Send + Sync),
208        source_name: Option<String>,
209    ) -> sop::Result<Self> {
210        let sigs = rpgpie::signature::load(&mut source).map_err(|e| match e {
211            rpgpie::Error::Io(e) => sop::errors::Error::IoError(e),
212            _ => sop::errors::Error::UnspecifiedFailure,
213        })?;
214
215        Ok(Sigs { sigs, source_name })
216    }
217
218    fn source_name(&self) -> Option<&str> {
219        self.source_name.as_deref()
220    }
221}
222
223impl sop::Save for Sigs {
224    fn to_writer(
225        &self,
226        armored: bool,
227        mut sink: &mut (dyn io::Write + Send + Sync),
228    ) -> sop::Result<()> {
229        rpgpie::signature::save(&self.sigs, armored, &mut sink).map_err(|e| match e {
230            rpgpie::Error::Io(e) => sop::errors::Error::IoError(e),
231            _ => sop::errors::Error::UnspecifiedFailure,
232        })?;
233
234        Ok(())
235    }
236}
237
238impl<'s> sop::plumbing::SopRef<'s, RPGSOP> for Certs {
239    fn sop(&self) -> &'s RPGSOP {
240        &SOP
241    }
242}
243
244impl<'s> sop::plumbing::SopRef<'s, RPGSOP> for Keys {
245    fn sop(&self) -> &'s RPGSOP {
246        &SOP
247    }
248}
249
250impl<'s> sop::plumbing::SopRef<'s, RPGSOP> for Sigs {
251    fn sop(&self) -> &'s RPGSOP {
252        &SOP
253    }
254}