cryptoki/mechanism/
rsa.rs

1// Copyright 2021 Contributors to the Parsec project.
2// SPDX-License-Identifier: Apache-2.0
3//! RSA mechanism types
4
5use super::{Mechanism, MechanismType};
6use crate::error::{Error, Result};
7use crate::types::Ulong;
8use cryptoki_sys::*;
9use log::error;
10use std::convert::{TryFrom, TryInto};
11use std::ffi::c_void;
12use std::marker::PhantomData;
13use std::ops::Deref;
14
15#[derive(Debug, Clone, Copy, PartialEq, Eq)]
16#[repr(transparent)]
17/// Message Generation Function (MGF) applied to a message block when formatting a message block
18/// for the PKCS #1 OAEP encryption scheme or the PKCS #1 PSS signature scheme.
19pub struct PkcsMgfType {
20    val: CK_RSA_PKCS_MGF_TYPE,
21}
22
23impl PkcsMgfType {
24    /// MGF1 SHA-1
25    pub const MGF1_SHA1: PkcsMgfType = PkcsMgfType { val: CKG_MGF1_SHA1 };
26    /// MGF1 SHA-224
27    pub const MGF1_SHA224: PkcsMgfType = PkcsMgfType {
28        val: CKG_MGF1_SHA224,
29    };
30    /// MGF1 SHA-256
31    pub const MGF1_SHA256: PkcsMgfType = PkcsMgfType {
32        val: CKG_MGF1_SHA256,
33    };
34    /// MGF1 SHA-384
35    pub const MGF1_SHA384: PkcsMgfType = PkcsMgfType {
36        val: CKG_MGF1_SHA384,
37    };
38    /// MGF1 SHA-512
39    pub const MGF1_SHA512: PkcsMgfType = PkcsMgfType {
40        val: CKG_MGF1_SHA512,
41    };
42}
43
44impl Deref for PkcsMgfType {
45    type Target = CK_RSA_PKCS_MGF_TYPE;
46
47    fn deref(&self) -> &Self::Target {
48        &self.val
49    }
50}
51
52impl From<PkcsMgfType> for CK_RSA_PKCS_MGF_TYPE {
53    fn from(mgf_type: PkcsMgfType) -> Self {
54        *mgf_type
55    }
56}
57
58impl TryFrom<CK_RSA_PKCS_MGF_TYPE> for PkcsMgfType {
59    type Error = Error;
60
61    fn try_from(mgf_type: CK_RSA_PKCS_MGF_TYPE) -> Result<Self> {
62        match mgf_type {
63            CKG_MGF1_SHA1 => Ok(PkcsMgfType::MGF1_SHA1),
64            CKG_MGF1_SHA224 => Ok(PkcsMgfType::MGF1_SHA224),
65            CKG_MGF1_SHA256 => Ok(PkcsMgfType::MGF1_SHA256),
66            CKG_MGF1_SHA384 => Ok(PkcsMgfType::MGF1_SHA384),
67            CKG_MGF1_SHA512 => Ok(PkcsMgfType::MGF1_SHA512),
68            other => {
69                error!(
70                    "Mask Generation Function type {} is not one of the valid values.",
71                    other
72                );
73                Err(Error::InvalidValue)
74            }
75        }
76    }
77}
78
79#[derive(Debug, Clone, Copy)]
80/// Source of the encoding parameter when formatting a message block for the PKCS #1 OAEP
81/// encryption scheme
82pub struct PkcsOaepSource<'a>(Option<&'a [u8]>);
83
84impl<'a> PkcsOaepSource<'a> {
85    /// Construct an empty encoding parameter.
86    ///
87    /// This is equivalent to `data_specified(&[])`.
88    pub fn empty() -> Self {
89        Self(None)
90    }
91
92    /// Construct an encoding parameter from an array of bytes.
93    pub fn data_specified(source_data: &'a [u8]) -> Self {
94        Self(Some(source_data))
95    }
96
97    pub(crate) fn source_ptr(&self) -> *const c_void {
98        if let Some(source_data) = self.0 {
99            source_data.as_ptr() as _
100        } else {
101            std::ptr::null()
102        }
103    }
104
105    pub(crate) fn source_len(&self) -> Ulong {
106        self.0
107            .unwrap_or_default()
108            .len()
109            .try_into()
110            .expect("usize can not fit in CK_ULONG")
111    }
112
113    pub(crate) fn source_type(&self) -> CK_RSA_PKCS_OAEP_SOURCE_TYPE {
114        CKZ_DATA_SPECIFIED
115    }
116}
117
118/// Parameters of the RsaPkcsPss mechanism
119#[derive(Copy, Debug, Clone)]
120#[repr(C)]
121pub struct PkcsPssParams {
122    /// hash algorithm used in the PSS encoding; if the signature mechanism does not include
123    /// message hashing, then this value must be the mechanism used by the application to generate
124    /// the message hash; if the signature mechanism includes hashing, then this value must match
125    /// the hash algorithm indicated by the signature mechanism
126    pub hash_alg: MechanismType,
127    /// mask generation function to use on the encoded block
128    pub mgf: PkcsMgfType,
129    /// length, in bytes, of the salt value used in the PSS encoding; typical values are the length
130    /// of the message hash and zero
131    pub s_len: Ulong,
132}
133
134/// Parameters of the RsaPkcsOaep mechanism
135#[derive(Copy, Debug, Clone)]
136#[repr(C)]
137#[cfg_attr(windows, repr(packed))]
138pub struct PkcsOaepParams<'a> {
139    /// mechanism ID of the message digest algorithm used to calculate the digest of the encoding
140    /// parameter
141    hash_alg: MechanismType,
142    /// mask generation function to use on the encoded block
143    mgf: PkcsMgfType,
144    /// source of the encoding parameter
145    source: CK_RSA_PKCS_OAEP_SOURCE_TYPE,
146    /// data used as the input for the encoding parameter source
147    source_data: *const c_void,
148    /// length of the encoding parameter source input
149    source_data_len: Ulong,
150    /// marker type to ensure we don't outlive the source_data
151    _marker: PhantomData<&'a [u8]>,
152}
153
154impl<'a> PkcsOaepParams<'a> {
155    /// Construct a new `PkcsOaepParams`.
156    ///
157    /// # Arguments
158    ///
159    /// * `hash_alg` - The message digest algorithm used to calculate
160    ///   a digest of the encoding parameter.
161    /// * `mgf` - The mask generation function to use on the encoded block.
162    /// * `encoding_parameter` - The encoding parameter, also known as the label.
163    pub fn new(
164        hash_alg: MechanismType,
165        mgf: PkcsMgfType,
166        encoding_parameter: PkcsOaepSource<'a>,
167    ) -> Self {
168        PkcsOaepParams {
169            hash_alg,
170            mgf,
171            source: encoding_parameter.source_type(),
172            source_data: encoding_parameter.source_ptr(),
173            source_data_len: encoding_parameter.source_len(),
174            _marker: PhantomData,
175        }
176    }
177
178    /// Get the message digest algorithm for the `PkcsOaepParams`.
179    pub fn hash_alg(&self) -> MechanismType {
180        self.hash_alg
181    }
182}
183
184impl<'a> From<PkcsOaepParams<'a>> for Mechanism<'a> {
185    fn from(pkcs_oaep_params: PkcsOaepParams<'a>) -> Self {
186        Mechanism::RsaPkcsOaep(pkcs_oaep_params)
187    }
188}