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(
74        &'_ self,
75    ) -> sop::Result<Box<dyn UpdateKey<'_, Self, Self::Certs, Self::Keys> + '_>> {
76        Err(sop::errors::Error::NotImplemented) // TODO
77    }
78
79    fn merge_certs(&'_ self) -> sop::Result<Box<dyn MergeCerts<'_, Self, Self::Certs> + '_>> {
80        Ok(Box::new(cmd::merge_certs::MergeCerts::new()))
81    }
82
83    fn certify_userid(
84        &'_ self,
85    ) -> sop::Result<Box<dyn CertifyUserID<'_, Self, Self::Certs, Self::Keys> + '_>> {
86        Err(sop::errors::Error::NotImplemented) // TODO
87    }
88
89    fn validate_userid(
90        &'_ self,
91    ) -> sop::Result<Box<dyn ValidateUserID<'_, Self, Self::Certs> + '_>> {
92        Err(sop::errors::Error::NotImplemented) // TODO
93    }
94
95    fn sign(
96        &'_ self,
97    ) -> sop::Result<Box<dyn sop::ops::Sign<'_, Self, Self::Keys, Self::Sigs> + '_>> {
98        Ok(Box::new(cmd::sign::Sign::new()))
99    }
100
101    fn verify(
102        &'_ self,
103    ) -> sop::Result<Box<dyn sop::ops::Verify<'_, Self, Self::Certs, Self::Sigs> + '_>> {
104        Ok(Box::new(cmd::verify::Verify::new()))
105    }
106
107    fn encrypt(
108        &'_ self,
109    ) -> sop::Result<Box<dyn sop::ops::Encrypt<'_, Self, Self::Certs, Self::Keys> + '_>> {
110        Ok(Box::new(cmd::encrypt::Encrypt::new()))
111    }
112
113    fn decrypt(
114        &'_ self,
115    ) -> sop::Result<Box<dyn sop::ops::Decrypt<'_, Self, Self::Certs, Self::Keys> + '_>> {
116        Ok(Box::new(cmd::decrypt::Decrypt::new()))
117    }
118
119    fn armor(&'_ self) -> sop::Result<Box<dyn sop::ops::Armor<'_>>> {
120        Ok(Box::new(cmd::armor::Armor::new()))
121    }
122
123    fn dearmor(&'_ self) -> sop::Result<Box<dyn sop::ops::Dearmor<'_>>> {
124        Ok(Box::new(cmd::dearmor::Dearmor::new()))
125    }
126
127    fn inline_detach(&'_ self) -> sop::Result<Box<dyn sop::ops::InlineDetach<'_, Self::Sigs>>> {
128        Ok(Box::new(cmd::detach::InlineDetach::new()))
129    }
130
131    fn inline_verify(
132        &'_ self,
133    ) -> sop::Result<Box<dyn sop::ops::InlineVerify<'_, Self, Self::Certs> + '_>> {
134        Ok(Box::new(cmd::inline_verify::InlineVerify::new()))
135    }
136
137    fn inline_sign(
138        &'_ self,
139    ) -> sop::Result<Box<dyn sop::ops::InlineSign<'_, Self, Self::Keys> + '_>> {
140        Ok(Box::new(cmd::inline_sign::InlineSign::new()))
141    }
142}
143
144impl sop::Load<'_, RPGSOP> for Certs {
145    fn from_reader(
146        _sop: &RPGSOP,
147        mut source: &mut (dyn io::Read + Send + Sync),
148        source_name: Option<String>,
149    ) -> sop::Result<Self> {
150        let certs = Certificate::load(&mut source).map_err(|e| match e {
151            rpgpie::Error::Io(e) => sop::errors::Error::IoError(e),
152            _ => sop::errors::Error::UnspecifiedFailure,
153        })?;
154
155        Ok(Certs { certs, source_name })
156    }
157
158    fn source_name(&self) -> Option<&str> {
159        self.source_name.as_deref()
160    }
161}
162
163impl sop::Save for Certs {
164    fn to_writer(
165        &self,
166        armored: bool,
167        sink: &mut (dyn io::Write + Send + Sync),
168    ) -> sop::Result<()> {
169        Certificate::save_all(&self.certs, armored, sink).map_err(|e| match e {
170            rpgpie::Error::Io(e) => sop::errors::Error::IoError(e),
171            _ => sop::errors::Error::UnspecifiedFailure,
172        })?;
173
174        Ok(())
175    }
176}
177
178impl sop::Load<'_, RPGSOP> for Keys {
179    fn from_reader(
180        _sop: &'_ RPGSOP,
181        mut source: &mut (dyn io::Read + Send + Sync),
182        source_name: Option<String>,
183    ) -> sop::Result<Self> {
184        let keys = Tsk::load(&mut source).map_err(|e| match e {
185            rpgpie::Error::Io(e) => sop::errors::Error::IoError(e),
186            _ => sop::errors::Error::UnspecifiedFailure,
187        })?;
188
189        Ok(Keys { keys, source_name })
190    }
191
192    fn source_name(&self) -> Option<&str> {
193        self.source_name.as_deref()
194    }
195}
196
197impl sop::Save for Keys {
198    fn to_writer(
199        &self,
200        armored: bool,
201        sink: &mut (dyn io::Write + Send + Sync),
202    ) -> sop::Result<()> {
203        Tsk::save_all(&self.keys, armored, sink).map_err(|e| match e {
204            rpgpie::Error::Io(e) => sop::errors::Error::IoError(e),
205            _ => sop::errors::Error::UnspecifiedFailure,
206        })?;
207
208        Ok(())
209    }
210}
211
212impl sop::Load<'_, RPGSOP> for Sigs {
213    fn from_reader(
214        _sop: &'_ RPGSOP,
215        mut source: &mut (dyn io::Read + Send + Sync),
216        source_name: Option<String>,
217    ) -> sop::Result<Self> {
218        let sigs = rpgpie::signature::load(&mut source).map_err(|e| match e {
219            rpgpie::Error::Io(e) => sop::errors::Error::IoError(e),
220            _ => sop::errors::Error::UnspecifiedFailure,
221        })?;
222
223        Ok(Sigs { sigs, source_name })
224    }
225
226    fn source_name(&self) -> Option<&str> {
227        self.source_name.as_deref()
228    }
229}
230
231impl sop::Save for Sigs {
232    fn to_writer(
233        &self,
234        armored: bool,
235        mut sink: &mut (dyn io::Write + Send + Sync),
236    ) -> sop::Result<()> {
237        rpgpie::signature::save(&self.sigs, armored, &mut sink).map_err(|e| match e {
238            rpgpie::Error::Io(e) => sop::errors::Error::IoError(e),
239            _ => sop::errors::Error::UnspecifiedFailure,
240        })?;
241
242        Ok(())
243    }
244}
245
246impl<'s> sop::plumbing::SopRef<'s, RPGSOP> for Certs {
247    fn sop(&self) -> &'s RPGSOP {
248        &SOP
249    }
250}
251
252impl<'s> sop::plumbing::SopRef<'s, RPGSOP> for Keys {
253    fn sop(&self) -> &'s RPGSOP {
254        &SOP
255    }
256}
257
258impl<'s> sop::plumbing::SopRef<'s, RPGSOP> for Sigs {
259    fn sop(&self) -> &'s RPGSOP {
260        &SOP
261    }
262}