nethsm/
nethsm_sdk.rs

1use std::fmt::Display;
2
3use nethsm_sdk_rs::models::{SignMode, Switch, UnattendedBootConfig};
4use serde::{Deserialize, Serialize};
5use ureq::Response;
6
7/// A representation of a message body in an HTTP response
8///
9/// This type allows us to deserialize the message body when the NetHSM API triggers the return of a
10/// [`nethsm_sdk_rs::apis::Error::Ureq`].
11#[derive(Debug, Deserialize)]
12pub struct Message {
13    message: String,
14}
15
16impl From<Response> for Message {
17    fn from(value: Response) -> Self {
18        if let Ok(message) = value.into_json() {
19            message
20        } else {
21            Message {
22                message: "Deserialization error (no message in body)".to_string(),
23            }
24        }
25    }
26}
27
28impl Display for Message {
29    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
30        f.write_str(&self.message)
31    }
32}
33
34#[derive(Debug)]
35pub struct ApiErrorMessage {
36    pub status_code: u16,
37    pub message: Message,
38}
39
40impl From<(u16, Message)> for ApiErrorMessage {
41    fn from(value: (u16, Message)) -> Self {
42        Self {
43            status_code: value.0,
44            message: value.1,
45        }
46    }
47}
48
49impl Display for ApiErrorMessage {
50    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
51        f.write_str(&format!(
52            "{} (status code {})",
53            self.message, self.status_code
54        ))
55    }
56}
57
58/// A helper Error for more readable output for [`nethsm_sdk_rs::apis::Error`]
59///
60/// This type allows us to create more readable output for [`nethsm_sdk_rs::apis::Error::Ureq`] and
61/// reuse the upstream handling otherwise.
62pub struct NetHsmApiError<T> {
63    error: Option<nethsm_sdk_rs::apis::Error<T>>,
64    message: Option<String>,
65}
66
67impl<T> From<nethsm_sdk_rs::apis::Error<T>> for NetHsmApiError<T> {
68    fn from(value: nethsm_sdk_rs::apis::Error<T>) -> Self {
69        match value {
70            nethsm_sdk_rs::apis::Error::Ureq(error) => match error {
71                nethsm_sdk_rs::ureq::Error::Status(code, response) => Self {
72                    error: None,
73                    message: Some(ApiErrorMessage::from((code, response.into())).to_string()),
74                },
75                nethsm_sdk_rs::ureq::Error::Transport(transport) => Self {
76                    error: None,
77                    message: Some(format!("{transport}")),
78                },
79            },
80            nethsm_sdk_rs::apis::Error::ResponseError(resp) => Self {
81                error: None,
82                message: Some(format!(
83                    "Status code: {}: {}",
84                    resp.status,
85                    // First, try to deserialize the response as a `Message` object,
86                    // which is commonly returned by a majority of failures
87                    serde_json::from_slice::<Message>(&resp.content)
88                        .map(|m| m.message)
89                        // if that fails, as a last resort, try to return the response verbatim.
90                        .unwrap_or_else(|_| String::from_utf8_lossy(&resp.content).into())
91                )),
92            },
93            _ => Self {
94                error: Some(value),
95                message: None,
96            },
97        }
98    }
99}
100
101impl<T> Display for NetHsmApiError<T> {
102    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
103        if let Some(message) = self.message.as_ref() {
104            write!(f, "{message}")?;
105        } else if let Some(error) = self.error.as_ref() {
106            write!(f, "{error}")?;
107        }
108        Ok(())
109    }
110}
111
112/// The type of a signature
113///
114/// This enum covers all variants of [`nethsm_sdk_rs::models::SignMode`], but instead of
115/// [`nethsm_sdk_rs::models::SignMode::Ecdsa`] covers prime size specific ECDSA modes.
116#[derive(
117    Clone,
118    Copy,
119    Debug,
120    Deserialize,
121    strum::Display,
122    strum::EnumString,
123    strum::EnumIter,
124    strum::IntoStaticStr,
125    Eq,
126    PartialEq,
127    Ord,
128    PartialOrd,
129    Hash,
130    Serialize,
131)]
132#[strum(ascii_case_insensitive)]
133pub enum SignatureType {
134    /// Elliptic Curve Digital Signature Algorithm (ECDSA) signing using a key over a prime field
135    /// for a prime of size 224 bit
136    EcdsaP224,
137
138    /// Elliptic Curve Digital Signature Algorithm (ECDSA) signing using a key over a prime field
139    /// for a prime of size 256 bit
140    EcdsaP256,
141
142    /// Elliptic Curve Digital Signature Algorithm (ECDSA) signing using a key over a prime field
143    /// for a prime of size 384 bit
144    EcdsaP384,
145
146    /// Elliptic Curve Digital Signature Algorithm (ECDSA) signing using a key over a prime field
147    /// for a prime of size 521 bit
148    EcdsaP521,
149
150    /// Signing following the Edwards-curve Digital Signature Algorithm (EdDSA)
151    EdDsa,
152
153    /// RSA signing following the PKCS#1 standard
154    Pkcs1,
155
156    /// RSA signing following a "probabilistic signature scheme" (PSS) using an MD-5 hash
157    PssMd5,
158
159    /// RSA signing following a "probabilistic signature scheme" (PSS) using a SHA-1 hash
160    PssSha1,
161
162    /// RSA signing following a "probabilistic signature scheme" (PSS) using a SHA-224 hash
163    PssSha224,
164
165    /// RSA signing following a "probabilistic signature scheme" (PSS) using a SHA-256 hash
166    PssSha256,
167
168    /// RSA signing following a "probabilistic signature scheme" (PSS) using a SHA-384 hash
169    PssSha384,
170
171    /// RSA signing following a "probabilistic signature scheme" (PSS) using a SHA-512 hash
172    PssSha512,
173}
174
175impl From<SignatureType> for SignMode {
176    fn from(value: SignatureType) -> Self {
177        match value {
178            SignatureType::Pkcs1 => SignMode::Pkcs1,
179            SignatureType::PssMd5 => SignMode::PssMd5,
180            SignatureType::PssSha1 => SignMode::PssSha1,
181            SignatureType::PssSha224 => SignMode::PssSha224,
182            SignatureType::PssSha256 => SignMode::PssSha256,
183            SignatureType::PssSha384 => SignMode::PssSha384,
184            SignatureType::PssSha512 => SignMode::PssSha512,
185            SignatureType::EdDsa => SignMode::EdDsa,
186            SignatureType::EcdsaP224
187            | SignatureType::EcdsaP256
188            | SignatureType::EcdsaP384
189            | SignatureType::EcdsaP521 => SignMode::Ecdsa,
190        }
191    }
192}
193
194/// The NetHSM boot mode
195///
196/// Defines in which state the NetHSM is in during boot after provisioning (see
197/// [`crate::NetHsm::provision`]) and whether an unlock passphrase has to be provided for it to be
198/// of state [`crate::SystemState::Operational`].
199#[derive(
200    Clone,
201    Copy,
202    Debug,
203    strum::Display,
204    strum::EnumString,
205    strum::EnumIter,
206    strum::IntoStaticStr,
207    Eq,
208    PartialEq,
209)]
210#[strum(ascii_case_insensitive)]
211pub enum BootMode {
212    /// The device boots into state [`crate::SystemState::Locked`] and an unlock passphrase has to
213    /// be provided
214    Attended,
215    /// The device boots into state [`crate::SystemState::Operational`] and no unlock passphrase
216    /// has to be provided
217    Unattended,
218}
219
220impl From<UnattendedBootConfig> for BootMode {
221    fn from(value: UnattendedBootConfig) -> Self {
222        match value.status {
223            Switch::On => BootMode::Unattended,
224            Switch::Off => BootMode::Attended,
225        }
226    }
227}
228
229impl From<BootMode> for UnattendedBootConfig {
230    fn from(value: BootMode) -> Self {
231        match value {
232            BootMode::Unattended => UnattendedBootConfig { status: Switch::On },
233            BootMode::Attended => UnattendedBootConfig {
234                status: Switch::Off,
235            },
236        }
237    }
238}
239
240/// A mode for decrypting a message
241#[derive(
242    Clone,
243    Copy,
244    Debug,
245    Default,
246    Deserialize,
247    strum::Display,
248    strum::EnumString,
249    strum::EnumIter,
250    strum::IntoStaticStr,
251    Eq,
252    Hash,
253    Ord,
254    PartialEq,
255    PartialOrd,
256    Serialize,
257)]
258#[strum(ascii_case_insensitive)]
259pub enum DecryptMode {
260    /// Decryption using the Advanced Encryption Standard (AES) with Cipher Block Chaining (CBC)
261    AesCbc,
262
263    /// RSA decryption with Optimal Asymmetric Encryption Padding (OAEP) using an MD-5 hash
264    OaepMd5,
265
266    /// RSA decryption with Optimal Asymmetric Encryption Padding (OAEP) using a SHA-1 hash
267    OaepSha1,
268
269    /// RSA decryption with Optimal Asymmetric Encryption Padding (OAEP) using a SHA-224 hash
270    OaepSha224,
271
272    /// RSA decryption with Optimal Asymmetric Encryption Padding (OAEP) using a SHA-256 hash
273    OaepSha256,
274
275    /// RSA decryption with Optimal Asymmetric Encryption Padding (OAEP) using a SHA-384 hash
276    OaepSha384,
277
278    /// RSA decryption with Optimal Asymmetric Encryption Padding (OAEP) using a SHA-512 hash
279    OaepSha512,
280
281    /// RSA decryption following the PKCS#1 standard
282    Pkcs1,
283
284    /// Raw RSA decryption
285    #[default]
286    Raw,
287}
288
289impl From<DecryptMode> for nethsm_sdk_rs::models::DecryptMode {
290    fn from(value: DecryptMode) -> Self {
291        match value {
292            DecryptMode::AesCbc => Self::AesCbc,
293            DecryptMode::OaepMd5 => Self::OaepMd5,
294            DecryptMode::OaepSha1 => Self::OaepSha1,
295            DecryptMode::OaepSha224 => Self::OaepSha224,
296            DecryptMode::OaepSha256 => Self::OaepSha256,
297            DecryptMode::OaepSha384 => Self::OaepSha384,
298            DecryptMode::OaepSha512 => Self::OaepSha512,
299            DecryptMode::Pkcs1 => Self::Pkcs1,
300            DecryptMode::Raw => Self::Raw,
301        }
302    }
303}
304
305/// A mode for encrypting a message
306#[derive(
307    Clone,
308    Copy,
309    Debug,
310    Default,
311    Deserialize,
312    strum::Display,
313    strum::EnumString,
314    strum::EnumIter,
315    strum::IntoStaticStr,
316    Eq,
317    Hash,
318    Ord,
319    PartialEq,
320    PartialOrd,
321    Serialize,
322)]
323#[strum(ascii_case_insensitive)]
324pub enum EncryptMode {
325    /// Encryption using the Advanced Encryption Standard (AES) with Cipher Block Chaining (CBC)
326    #[default]
327    AesCbc,
328}
329
330impl From<EncryptMode> for nethsm_sdk_rs::models::EncryptMode {
331    fn from(value: EncryptMode) -> Self {
332        match value {
333            EncryptMode::AesCbc => Self::AesCbc,
334        }
335    }
336}
337
338/// A mechanism which can be used with a key
339#[derive(
340    Clone,
341    Copy,
342    Debug,
343    Default,
344    Deserialize,
345    strum::Display,
346    strum::EnumString,
347    strum::EnumIter,
348    strum::IntoStaticStr,
349    Hash,
350    Eq,
351    Ord,
352    PartialEq,
353    PartialOrd,
354    Serialize,
355)]
356#[strum(ascii_case_insensitive)]
357pub enum KeyMechanism {
358    /// Decryption using the Advanced Encryption Standard (AES) with Cipher Block Chaining (CBC)
359    AesDecryptionCbc,
360
361    /// Encryption using the Advanced Encryption Standard (AES) with Cipher Block Chaining (CBC)
362    AesEncryptionCbc,
363
364    /// Signing following the Elliptic Curve Digital Signature Algorithm (ECDSA)
365    EcdsaSignature,
366
367    /// Signing following the Edwards-curve Digital Signature Algorithm (EdDSA)
368    #[default]
369    EdDsaSignature,
370
371    /// RSA decryption with Optimal Asymmetric Encryption Padding (OAEP) using an MD-5 hash
372    RsaDecryptionOaepMd5,
373
374    /// RSA decryption with Optimal Asymmetric Encryption Padding (OAEP) using a SHA-1 hash
375    RsaDecryptionOaepSha1,
376
377    /// RSA decryption with Optimal Asymmetric Encryption Padding (OAEP) using a SHA-224 hash
378    RsaDecryptionOaepSha224,
379
380    /// RSA decryption with Optimal Asymmetric Encryption Padding (OAEP) using a SHA-256 hash
381    RsaDecryptionOaepSha256,
382
383    /// RSA decryption with Optimal Asymmetric Encryption Padding (OAEP) using a SHA-384 hash
384    RsaDecryptionOaepSha384,
385
386    /// RSA decryption with Optimal Asymmetric Encryption Padding (OAEP) using a SHA-512 hash
387    RsaDecryptionOaepSha512,
388
389    /// RSA decryption following the PKCS#1 standard
390    RsaDecryptionPkcs1,
391
392    /// Raw RSA decryption
393    RsaDecryptionRaw,
394
395    /// RSA signing following the PKCS#1 standard
396    RsaSignaturePkcs1,
397
398    /// RSA signing following a "probabilistic signature scheme" (PSS) using an MD-5 hash
399    RsaSignaturePssMd5,
400
401    /// RSA signing following a "probabilistic signature scheme" (PSS) using a SHA-1 hash
402    RsaSignaturePssSha1,
403
404    /// RSA signing following a "probabilistic signature scheme" (PSS) using a SHA-224 hash
405    RsaSignaturePssSha224,
406
407    /// RSA signing following a "probabilistic signature scheme" (PSS) using a SHA-256 hash
408    RsaSignaturePssSha256,
409
410    /// RSA signing following a "probabilistic signature scheme" (PSS) using a SHA-384 hash
411    RsaSignaturePssSha384,
412
413    /// RSA signing following a "probabilistic signature scheme" (PSS) using a SHA-512 hash
414    RsaSignaturePssSha512,
415}
416
417impl KeyMechanism {
418    /// Returns key mechanisms specific to Curve25519 key types
419    pub fn curve25519_mechanisms() -> Vec<KeyMechanism> {
420        vec![KeyMechanism::EdDsaSignature]
421    }
422
423    /// Returns key mechanisms specific to elliptic curve key types
424    pub fn elliptic_curve_mechanisms() -> Vec<KeyMechanism> {
425        vec![KeyMechanism::EcdsaSignature]
426    }
427
428    /// Returns key mechanisms specific to generic key types
429    pub fn generic_mechanisms() -> Vec<KeyMechanism> {
430        vec![
431            KeyMechanism::AesDecryptionCbc,
432            KeyMechanism::AesEncryptionCbc,
433        ]
434    }
435
436    /// Returns key mechanisms specific to RSA key types
437    pub fn rsa_mechanisms() -> Vec<KeyMechanism> {
438        vec![
439            KeyMechanism::RsaDecryptionRaw,
440            KeyMechanism::RsaDecryptionPkcs1,
441            KeyMechanism::RsaDecryptionOaepMd5,
442            KeyMechanism::RsaDecryptionOaepSha1,
443            KeyMechanism::RsaDecryptionOaepSha224,
444            KeyMechanism::RsaDecryptionOaepSha256,
445            KeyMechanism::RsaDecryptionOaepSha384,
446            KeyMechanism::RsaDecryptionOaepSha512,
447            KeyMechanism::RsaSignaturePkcs1,
448            KeyMechanism::RsaSignaturePssMd5,
449            KeyMechanism::RsaSignaturePssSha1,
450            KeyMechanism::RsaSignaturePssSha224,
451            KeyMechanism::RsaSignaturePssSha256,
452            KeyMechanism::RsaSignaturePssSha384,
453            KeyMechanism::RsaSignaturePssSha512,
454        ]
455    }
456}
457
458impl From<&nethsm_sdk_rs::models::KeyMechanism> for KeyMechanism {
459    fn from(value: &nethsm_sdk_rs::models::KeyMechanism) -> Self {
460        match value {
461            nethsm_sdk_rs::models::KeyMechanism::AesDecryptionCbc => Self::AesDecryptionCbc,
462            nethsm_sdk_rs::models::KeyMechanism::AesEncryptionCbc => Self::AesEncryptionCbc,
463            nethsm_sdk_rs::models::KeyMechanism::EcdsaSignature => Self::EcdsaSignature,
464            nethsm_sdk_rs::models::KeyMechanism::EdDsaSignature => Self::EdDsaSignature,
465            nethsm_sdk_rs::models::KeyMechanism::RsaDecryptionOaepMd5 => Self::RsaDecryptionOaepMd5,
466            nethsm_sdk_rs::models::KeyMechanism::RsaDecryptionOaepSha1 => {
467                Self::RsaDecryptionOaepSha1
468            }
469            nethsm_sdk_rs::models::KeyMechanism::RsaDecryptionOaepSha224 => {
470                Self::RsaDecryptionOaepSha224
471            }
472            nethsm_sdk_rs::models::KeyMechanism::RsaDecryptionOaepSha256 => {
473                Self::RsaDecryptionOaepSha256
474            }
475            nethsm_sdk_rs::models::KeyMechanism::RsaDecryptionOaepSha384 => {
476                Self::RsaDecryptionOaepSha384
477            }
478            nethsm_sdk_rs::models::KeyMechanism::RsaDecryptionOaepSha512 => {
479                Self::RsaDecryptionOaepSha512
480            }
481            nethsm_sdk_rs::models::KeyMechanism::RsaDecryptionPkcs1 => Self::RsaDecryptionPkcs1,
482            nethsm_sdk_rs::models::KeyMechanism::RsaDecryptionRaw => Self::RsaDecryptionRaw,
483            nethsm_sdk_rs::models::KeyMechanism::RsaSignaturePkcs1 => Self::RsaSignaturePkcs1,
484            nethsm_sdk_rs::models::KeyMechanism::RsaSignaturePssMd5 => Self::RsaSignaturePssMd5,
485            nethsm_sdk_rs::models::KeyMechanism::RsaSignaturePssSha1 => Self::RsaSignaturePssSha1,
486            nethsm_sdk_rs::models::KeyMechanism::RsaSignaturePssSha224 => {
487                Self::RsaSignaturePssSha224
488            }
489            nethsm_sdk_rs::models::KeyMechanism::RsaSignaturePssSha256 => {
490                Self::RsaSignaturePssSha256
491            }
492            nethsm_sdk_rs::models::KeyMechanism::RsaSignaturePssSha384 => {
493                Self::RsaSignaturePssSha384
494            }
495            nethsm_sdk_rs::models::KeyMechanism::RsaSignaturePssSha512 => {
496                Self::RsaSignaturePssSha512
497            }
498        }
499    }
500}
501
502impl From<KeyMechanism> for nethsm_sdk_rs::models::KeyMechanism {
503    fn from(value: KeyMechanism) -> Self {
504        match value {
505            KeyMechanism::AesDecryptionCbc => Self::AesDecryptionCbc,
506            KeyMechanism::AesEncryptionCbc => Self::AesEncryptionCbc,
507            KeyMechanism::EcdsaSignature => Self::EcdsaSignature,
508            KeyMechanism::EdDsaSignature => Self::EdDsaSignature,
509            KeyMechanism::RsaDecryptionOaepMd5 => Self::RsaDecryptionOaepMd5,
510            KeyMechanism::RsaDecryptionOaepSha1 => Self::RsaDecryptionOaepSha1,
511            KeyMechanism::RsaDecryptionOaepSha224 => Self::RsaDecryptionOaepSha224,
512            KeyMechanism::RsaDecryptionOaepSha256 => Self::RsaDecryptionOaepSha256,
513            KeyMechanism::RsaDecryptionOaepSha384 => Self::RsaDecryptionOaepSha384,
514            KeyMechanism::RsaDecryptionOaepSha512 => Self::RsaDecryptionOaepSha512,
515            KeyMechanism::RsaDecryptionPkcs1 => Self::RsaDecryptionPkcs1,
516            KeyMechanism::RsaDecryptionRaw => Self::RsaDecryptionRaw,
517            KeyMechanism::RsaSignaturePkcs1 => Self::RsaSignaturePkcs1,
518            KeyMechanism::RsaSignaturePssMd5 => Self::RsaSignaturePssMd5,
519            KeyMechanism::RsaSignaturePssSha1 => Self::RsaSignaturePssSha1,
520            KeyMechanism::RsaSignaturePssSha224 => Self::RsaSignaturePssSha224,
521            KeyMechanism::RsaSignaturePssSha256 => Self::RsaSignaturePssSha256,
522            KeyMechanism::RsaSignaturePssSha384 => Self::RsaSignaturePssSha384,
523            KeyMechanism::RsaSignaturePssSha512 => Self::RsaSignaturePssSha512,
524        }
525    }
526}
527
528/// The algorithm type of a key
529#[derive(
530    Clone,
531    Copy,
532    Debug,
533    Default,
534    Deserialize,
535    strum::Display,
536    strum::EnumString,
537    strum::EnumIter,
538    strum::IntoStaticStr,
539    Eq,
540    Hash,
541    Ord,
542    PartialEq,
543    PartialOrd,
544    Serialize,
545)]
546#[strum(ascii_case_insensitive)]
547pub enum KeyType {
548    /// A Montgomery curve key over a prime field for the prime number 2^255-19
549    #[default]
550    Curve25519,
551
552    /// An elliptic-curve key over a prime field for a prime of size 224 bit
553    EcP224,
554
555    /// An elliptic-curve key over a prime field for a prime of size 256 bit
556    EcP256,
557
558    /// An elliptic-curve key over a prime field for a prime of size 384 bit
559    EcP384,
560
561    /// An elliptic-curve key over a prime field for a prime of size 521 bit
562    EcP521,
563
564    /// A generic key used for block ciphers
565    Generic,
566
567    /// An RSA key
568    Rsa,
569}
570
571impl From<KeyType> for nethsm_sdk_rs::models::KeyType {
572    fn from(value: KeyType) -> Self {
573        match value {
574            KeyType::Curve25519 => Self::Curve25519,
575            KeyType::EcP224 => Self::EcP224,
576            KeyType::EcP256 => Self::EcP256,
577            KeyType::EcP384 => Self::EcP384,
578            KeyType::EcP521 => Self::EcP521,
579            KeyType::Generic => Self::Generic,
580            KeyType::Rsa => Self::Rsa,
581        }
582    }
583}
584
585impl From<nethsm_sdk_rs::models::KeyType> for KeyType {
586    fn from(value: nethsm_sdk_rs::models::KeyType) -> Self {
587        use nethsm_sdk_rs::models::KeyType;
588        match value {
589            KeyType::Curve25519 => Self::Curve25519,
590            KeyType::EcP224 => Self::EcP224,
591            KeyType::EcP256 => Self::EcP256,
592            KeyType::EcP384 => Self::EcP384,
593            KeyType::EcP521 => Self::EcP521,
594            KeyType::Generic => Self::Generic,
595            KeyType::Rsa => Self::Rsa,
596        }
597    }
598}
599
600/// The format of a key
601#[derive(
602    Clone,
603    Copy,
604    Debug,
605    Default,
606    Deserialize,
607    strum::Display,
608    strum::EnumString,
609    strum::EnumIter,
610    strum::IntoStaticStr,
611    Eq,
612    Hash,
613    Ord,
614    PartialEq,
615    PartialOrd,
616    Serialize,
617)]
618#[strum(ascii_case_insensitive)]
619pub enum KeyFormat {
620    /// Privacy-Enhanced Mail (PEM) format.
621    Pem,
622
623    /// ASN.1 DER binary format.
624    #[default]
625    Der,
626}
627
628/// A device log level
629#[derive(
630    Clone,
631    Copy,
632    Debug,
633    Default,
634    Deserialize,
635    strum::Display,
636    strum::EnumString,
637    strum::EnumIter,
638    strum::IntoStaticStr,
639    Eq,
640    Hash,
641    Ord,
642    PartialEq,
643    PartialOrd,
644    Serialize,
645)]
646#[strum(ascii_case_insensitive)]
647pub enum LogLevel {
648    /// Show debug, error, warning and info messages
649    Debug,
650
651    /// Show error, warning and info messages
652    Error,
653
654    /// Show info messages
655    #[default]
656    Info,
657
658    /// Show warning and info messages
659    Warning,
660}
661
662impl From<LogLevel> for nethsm_sdk_rs::models::LogLevel {
663    fn from(value: LogLevel) -> Self {
664        match value {
665            LogLevel::Debug => Self::Debug,
666            LogLevel::Error => Self::Error,
667            LogLevel::Info => Self::Info,
668            LogLevel::Warning => Self::Warning,
669        }
670    }
671}
672
673/// The algorithm type of a key used for TLS
674#[derive(
675    Clone,
676    Copy,
677    Debug,
678    Default,
679    Deserialize,
680    strum::Display,
681    strum::EnumString,
682    strum::EnumIter,
683    strum::IntoStaticStr,
684    Eq,
685    Hash,
686    Ord,
687    PartialEq,
688    PartialOrd,
689    Serialize,
690)]
691#[strum(ascii_case_insensitive)]
692pub enum TlsKeyType {
693    /// A Montgomery curve key over a prime field for the prime number 2^255-19
694    Curve25519,
695
696    /// An elliptic-curve key over a prime field for a prime of size 224 bit
697    EcP224,
698
699    /// An elliptic-curve key over a prime field for a prime of size 256 bit
700    EcP256,
701
702    /// An elliptic-curve key over a prime field for a prime of size 384 bit
703    EcP384,
704
705    /// An elliptic-curve key over a prime field for a prime of size 521 bit
706    EcP521,
707
708    /// An RSA key
709    #[default]
710    Rsa,
711}
712
713impl From<TlsKeyType> for nethsm_sdk_rs::models::TlsKeyType {
714    fn from(value: TlsKeyType) -> Self {
715        match value {
716            TlsKeyType::Curve25519 => Self::Curve25519,
717            TlsKeyType::EcP224 => Self::EcP224,
718            TlsKeyType::EcP256 => Self::EcP256,
719            TlsKeyType::EcP384 => Self::EcP384,
720            TlsKeyType::EcP521 => Self::EcP521,
721            TlsKeyType::Rsa => Self::Rsa,
722        }
723    }
724}
725
726/// The role of a user on a NetHSM device
727#[derive(
728    Clone,
729    Copy,
730    Debug,
731    Default,
732    Deserialize,
733    strum::Display,
734    strum::EnumString,
735    strum::EnumIter,
736    strum::IntoStaticStr,
737    Eq,
738    PartialEq,
739    Ord,
740    PartialOrd,
741    Hash,
742    Serialize,
743)]
744#[strum(ascii_case_insensitive)]
745pub enum UserRole {
746    /// A role for administrating a device, its users and keys
747    Administrator,
748    /// A role for creating backups of a device
749    Backup,
750    /// A role for reading metrics of a device
751    Metrics,
752    /// A role for using one or more keys of a device
753    #[default]
754    Operator,
755}
756
757impl From<UserRole> for nethsm_sdk_rs::models::UserRole {
758    fn from(value: UserRole) -> Self {
759        match value {
760            UserRole::Administrator => Self::Administrator,
761            UserRole::Backup => Self::Backup,
762            UserRole::Metrics => Self::Metrics,
763            UserRole::Operator => Self::Operator,
764        }
765    }
766}
767
768impl From<nethsm_sdk_rs::models::UserRole> for UserRole {
769    fn from(value: nethsm_sdk_rs::models::UserRole) -> Self {
770        match value {
771            nethsm_sdk_rs::models::UserRole::Administrator => Self::Administrator,
772            nethsm_sdk_rs::models::UserRole::Backup => Self::Backup,
773            nethsm_sdk_rs::models::UserRole::Metrics => Self::Metrics,
774            nethsm_sdk_rs::models::UserRole::Operator => Self::Operator,
775        }
776    }
777}
778
779#[cfg(test)]
780mod tests {
781    use std::str::FromStr;
782
783    use rstest::rstest;
784    use testresult::TestResult;
785
786    use super::*;
787
788    #[rstest]
789    #[case("raw", Some(DecryptMode::Raw))]
790    #[case("pkcs1", Some(DecryptMode::Pkcs1))]
791    #[case("oaepmd5", Some(DecryptMode::OaepMd5))]
792    #[case("oaepsha1", Some(DecryptMode::OaepSha1))]
793    #[case("oaepsha224", Some(DecryptMode::OaepSha224))]
794    #[case("oaepsha256", Some(DecryptMode::OaepSha256))]
795    #[case("oaepsha384", Some(DecryptMode::OaepSha384))]
796    #[case("oaepsha512", Some(DecryptMode::OaepSha512))]
797    #[case("aescbc", Some(DecryptMode::AesCbc))]
798    #[case("foo", None)]
799    fn decryptmode_fromstr(
800        #[case] input: &str,
801        #[case] expected: Option<DecryptMode>,
802    ) -> TestResult {
803        if let Some(expected) = expected {
804            assert_eq!(DecryptMode::from_str(input)?, expected);
805        } else {
806            assert!(DecryptMode::from_str(input).is_err());
807        }
808        Ok(())
809    }
810
811    #[rstest]
812    #[case("aescbc", Some(EncryptMode::AesCbc))]
813    #[case("foo", None)]
814    fn encryptmode_fromstr(
815        #[case] input: &str,
816        #[case] expected: Option<EncryptMode>,
817    ) -> TestResult {
818        if let Some(expected) = expected {
819            assert_eq!(EncryptMode::from_str(input)?, expected);
820        } else {
821            assert!(EncryptMode::from_str(input).is_err());
822        }
823        Ok(())
824    }
825
826    #[rstest]
827    #[case("rsadecryptionraw", Some(KeyMechanism::RsaDecryptionRaw))]
828    #[case("rsadecryptionpkcs1", Some(KeyMechanism::RsaDecryptionPkcs1))]
829    #[case("rsadecryptionoaepmd5", Some(KeyMechanism::RsaDecryptionOaepMd5))]
830    #[case("rsadecryptionoaepsha1", Some(KeyMechanism::RsaDecryptionOaepSha1))]
831    #[case("rsadecryptionoaepsha224", Some(KeyMechanism::RsaDecryptionOaepSha224))]
832    #[case("rsadecryptionoaepsha256", Some(KeyMechanism::RsaDecryptionOaepSha256))]
833    #[case("rsadecryptionoaepsha384", Some(KeyMechanism::RsaDecryptionOaepSha384))]
834    #[case("rsadecryptionoaepsha512", Some(KeyMechanism::RsaDecryptionOaepSha512))]
835    #[case("rsadecryptionoaepsha512", Some(KeyMechanism::RsaDecryptionOaepSha512))]
836    #[case("rsasignaturepkcs1", Some(KeyMechanism::RsaSignaturePkcs1))]
837    #[case("rsasignaturepssmd5", Some(KeyMechanism::RsaSignaturePssMd5))]
838    #[case("rsasignaturepsssha1", Some(KeyMechanism::RsaSignaturePssSha1))]
839    #[case("rsasignaturepsssha224", Some(KeyMechanism::RsaSignaturePssSha224))]
840    #[case("rsasignaturepsssha256", Some(KeyMechanism::RsaSignaturePssSha256))]
841    #[case("rsasignaturepsssha384", Some(KeyMechanism::RsaSignaturePssSha384))]
842    #[case("rsasignaturepsssha512", Some(KeyMechanism::RsaSignaturePssSha512))]
843    #[case("eddsasignature", Some(KeyMechanism::EdDsaSignature))]
844    #[case("ecdsasignature", Some(KeyMechanism::EcdsaSignature))]
845    #[case("aesencryptioncbc", Some(KeyMechanism::AesEncryptionCbc))]
846    #[case("aesdecryptioncbc", Some(KeyMechanism::AesDecryptionCbc))]
847    #[case("foo", None)]
848    fn keymechanism_fromstr(
849        #[case] input: &str,
850        #[case] expected: Option<KeyMechanism>,
851    ) -> TestResult {
852        if let Some(expected) = expected {
853            assert_eq!(KeyMechanism::from_str(input)?, expected);
854        } else {
855            assert!(KeyMechanism::from_str(input).is_err());
856        }
857        Ok(())
858    }
859
860    #[rstest]
861    #[case("rsa", Some(KeyType::Rsa))]
862    #[case("curve25519", Some(KeyType::Curve25519))]
863    #[case("ecp224", Some(KeyType::EcP224))]
864    #[case("ecp256", Some(KeyType::EcP256))]
865    #[case("ecp384", Some(KeyType::EcP384))]
866    #[case("ecp521", Some(KeyType::EcP521))]
867    #[case("generic", Some(KeyType::Generic))]
868    #[case("foo", None)]
869    fn keytype_fromstr(#[case] input: &str, #[case] expected: Option<KeyType>) -> TestResult {
870        if let Some(expected) = expected {
871            assert_eq!(KeyType::from_str(input)?, expected);
872        } else {
873            assert!(KeyType::from_str(input).is_err());
874        }
875        Ok(())
876    }
877
878    #[rstest]
879    #[case("ecdsap224", Some(SignatureType::EcdsaP224))]
880    #[case("ecdsap256", Some(SignatureType::EcdsaP256))]
881    #[case("ecdsap384", Some(SignatureType::EcdsaP384))]
882    #[case("ecdsap521", Some(SignatureType::EcdsaP521))]
883    #[case("eddsa", Some(SignatureType::EdDsa))]
884    #[case("pkcs1", Some(SignatureType::Pkcs1))]
885    #[case("pssmd5", Some(SignatureType::PssMd5))]
886    #[case("psssha1", Some(SignatureType::PssSha1))]
887    #[case("psssha224", Some(SignatureType::PssSha224))]
888    #[case("psssha256", Some(SignatureType::PssSha256))]
889    #[case("psssha384", Some(SignatureType::PssSha384))]
890    #[case("psssha512", Some(SignatureType::PssSha512))]
891    #[case("foo", None)]
892    fn signaturetype_fromstr(
893        #[case] input: &str,
894        #[case] expected: Option<SignatureType>,
895    ) -> TestResult {
896        if let Some(expected) = expected {
897            assert_eq!(SignatureType::from_str(input)?, expected);
898        } else {
899            assert!(SignatureType::from_str(input).is_err());
900        }
901        Ok(())
902    }
903
904    #[rstest]
905    #[case("rsa", Some(TlsKeyType::Rsa))]
906    #[case("curve25519", Some(TlsKeyType::Curve25519))]
907    #[case("ecp224", Some(TlsKeyType::EcP224))]
908    #[case("ecp256", Some(TlsKeyType::EcP256))]
909    #[case("ecp384", Some(TlsKeyType::EcP384))]
910    #[case("ecp521", Some(TlsKeyType::EcP521))]
911    #[case("foo", None)]
912    fn tlskeytype_fromstr(#[case] input: &str, #[case] expected: Option<TlsKeyType>) -> TestResult {
913        if let Some(expected) = expected {
914            assert_eq!(TlsKeyType::from_str(input)?, expected);
915        } else {
916            assert!(TlsKeyType::from_str(input).is_err());
917        }
918        Ok(())
919    }
920
921    #[rstest]
922    #[case("administrator", Some(UserRole::Administrator))]
923    #[case("backup", Some(UserRole::Backup))]
924    #[case("metrics", Some(UserRole::Metrics))]
925    #[case("operator", Some(UserRole::Operator))]
926    #[case("foo", None)]
927    fn userrole_fromstr(#[case] input: &str, #[case] expected: Option<UserRole>) -> TestResult {
928        if let Some(expected) = expected {
929            assert_eq!(UserRole::from_str(input)?, expected);
930        } else {
931            assert!(UserRole::from_str(input).is_err());
932        }
933        Ok(())
934    }
935}