kanidmd_lib/valueset/
eckey.rs

1use super::ValueSet;
2use crate::be::dbvalue::DbValueSetV2;
3use crate::prelude::*;
4use crate::value::{PartialValue, SyntaxType, Value};
5use crate::valueset::ScimResolveStatus;
6use openssl::ec::EcKey;
7use openssl::pkey::{Private, Public};
8use std::iter::{self};
9
10#[derive(Debug, Clone)]
11struct EcKeyPrivate {
12    priv_key: EcKey<Private>,
13    pub_key: EcKey<Public>,
14}
15
16#[derive(Debug, Clone)]
17pub struct ValueSetEcKeyPrivate {
18    set: Option<EcKeyPrivate>,
19}
20
21impl ValueSetEcKeyPrivate {
22    pub fn new(key: &EcKey<Private>) -> Box<Self> {
23        #[allow(clippy::expect_used)]
24        let pub_key = Self::private_key_to_public_key(key).expect(
25            "Unable to retrieve public key from private key, likely corrupted. You must restore from backup.",
26        );
27
28        Box::new(ValueSetEcKeyPrivate {
29            set: Some(EcKeyPrivate {
30                priv_key: key.clone(),
31                pub_key,
32            }),
33        })
34    }
35
36    fn push(&mut self, key: &EcKey<Private>) -> bool {
37        #[allow(clippy::expect_used)]
38        let pub_key = Self::private_key_to_public_key(key).expect(
39            "Unable to retrieve public key from private key, likely corrupted. You must restore from backup.",
40        );
41        self.set = Some(EcKeyPrivate {
42            priv_key: key.clone(),
43            pub_key,
44        });
45        true
46    }
47
48    fn valueset_from_key_der(key_der: &[u8]) -> Result<ValueSet, OperationError> {
49        let option_key = EcKey::private_key_from_der(key_der);
50        if let Ok(key) = option_key {
51            Ok(Self::new(&key))
52        } else {
53            Err(OperationError::InvalidDbState)
54        }
55    }
56
57    fn private_key_to_public_key(private_key: &EcKey<Private>) -> Option<EcKey<Public>> {
58        let public_key = private_key.public_key();
59        let group = private_key.group();
60        EcKey::from_public_key(group, public_key).ok()
61    }
62
63    pub fn from_dbvs2(key_der: &[u8]) -> Result<ValueSet, OperationError> {
64        Self::valueset_from_key_der(key_der)
65    }
66}
67
68impl ValueSetT for ValueSetEcKeyPrivate {
69    fn insert_checked(&mut self, value: crate::value::Value) -> Result<bool, OperationError> {
70        match value {
71            Value::EcKeyPrivate(k) => Ok(self.push(&k)),
72            _ => {
73                debug_assert!(false);
74                Err(OperationError::InvalidValueState)
75            }
76        }
77    }
78
79    fn clear(&mut self) {
80        self.set = None;
81    }
82
83    fn remove(&mut self, _pv: &crate::value::PartialValue, _cid: &Cid) -> bool {
84        false
85    }
86
87    fn contains(&self, _pv: &crate::value::PartialValue) -> bool {
88        false
89    }
90
91    fn substring(&self, _pv: &crate::value::PartialValue) -> bool {
92        false
93    }
94
95    fn startswith(&self, _pv: &PartialValue) -> bool {
96        false
97    }
98
99    fn endswith(&self, _pv: &PartialValue) -> bool {
100        false
101    }
102
103    fn lessthan(&self, _pv: &crate::value::PartialValue) -> bool {
104        false
105    }
106
107    fn len(&self) -> usize {
108        1
109    }
110
111    fn generate_idx_eq_keys(&self) -> Vec<String> {
112        Vec::with_capacity(0)
113    }
114
115    fn syntax(&self) -> SyntaxType {
116        SyntaxType::EcKeyPrivate
117    }
118
119    fn validate(&self, _schema_attr: &crate::schema::SchemaAttribute) -> bool {
120        match self.set.as_ref() {
121            Some(key) => key.priv_key.check_key().is_ok() && key.pub_key.check_key().is_ok(),
122            None => false,
123        }
124    }
125
126    fn to_proto_string_clone_iter(&self) -> Box<dyn Iterator<Item = String> + '_> {
127        Box::new(iter::once(String::from("hidden")))
128    }
129
130    fn to_scim_value(&self) -> Option<ScimResolveStatus> {
131        None
132    }
133
134    fn to_db_valueset_v2(&self) -> DbValueSetV2 {
135        #[allow(clippy::expect_used)]
136        let key_der = self
137            .set
138            .as_ref()
139            .map(|key| {
140                key.priv_key.private_key_to_der().expect(
141        "Unable to process eckey to der, likely corrupted. You must restore from backup.",
142    )
143            })
144            .unwrap_or_default();
145        DbValueSetV2::EcKeyPrivate(key_der)
146    }
147
148    fn to_partialvalue_iter(&self) -> Box<dyn Iterator<Item = crate::value::PartialValue> + '_> {
149        Box::new(iter::once(PartialValue::SecretValue))
150    }
151
152    fn to_value_iter(&self) -> Box<dyn Iterator<Item = crate::value::Value> + '_> {
153        match &self.set {
154            Some(key) => Box::new(iter::once(Value::EcKeyPrivate(key.priv_key.clone()))),
155            None => Box::new(iter::empty::<Value>()),
156        }
157    }
158
159    fn equal(&self, other: &super::ValueSet) -> bool {
160        #[allow(clippy::expect_used)]
161        other.as_ec_key_private().is_some_and(|other_key| {
162            self.set.as_ref().is_some_and(|key| {
163                key.priv_key
164                    .private_key_to_der()
165                    .expect("Failed to retrieve key der")
166                    == other_key
167                        .private_key_to_der()
168                        .expect("Failed to retrieve key der")
169            })
170        })
171    }
172
173    fn merge(&mut self, other: &super::ValueSet) -> Result<(), OperationError> {
174        if let Some(other_key) = other.as_ec_key_private() {
175            let priv_key = other_key.clone();
176            let pub_key = Self::private_key_to_public_key(&priv_key)
177                .ok_or(OperationError::CryptographyError)?;
178            self.set = Some(EcKeyPrivate { pub_key, priv_key });
179            Ok(())
180        } else {
181            debug_assert!(false);
182            Err(OperationError::InvalidValueState)
183        }
184    }
185
186    fn as_ec_key_private(&self) -> Option<&EcKey<Private>> {
187        match self.set.as_ref() {
188            Some(key) => Some(&key.priv_key),
189            None => None,
190        }
191    }
192
193    fn to_eckey_private_single(&self) -> Option<&EcKey<Private>> {
194        match self.set.as_ref() {
195            Some(key) => Some(&key.priv_key),
196            None => None,
197        }
198    }
199
200    fn to_eckey_public_single(&self) -> Option<&EcKey<Public>> {
201        match self.set.as_ref() {
202            Some(key) => Some(&key.pub_key),
203            None => None,
204        }
205    }
206}