parsec_interface/operations_protobuf/
convert_psa_asymmetric_encrypt.rs

1// Copyright 2020 Contributors to the Parsec project.
2// SPDX-License-Identifier: Apache-2.0
3use super::generated_ops::psa_asymmetric_encrypt::{
4    Operation as OperationProto, Result as ResultProto,
5};
6use crate::operations::psa_asymmetric_encrypt::{Operation, Result};
7use crate::requests::ResponseStatus;
8use log::error;
9use std::convert::{TryFrom, TryInto};
10use zeroize::Zeroizing;
11
12impl TryFrom<OperationProto> for Operation {
13    type Error = ResponseStatus;
14
15    fn try_from(proto_op: OperationProto) -> std::result::Result<Self, Self::Error> {
16        let salt = match proto_op.salt.len() {
17            0 => None,
18            _ => Some(Zeroizing::new(proto_op.salt)),
19        };
20
21        Ok(Operation {
22            key_name: proto_op.key_name,
23            alg: proto_op
24                .alg
25                .ok_or_else(|| {
26                    error!("The alg field of PsaAsymmetricEncrypt::Operation message is not set (mandatory field).");
27                    ResponseStatus::InvalidEncoding
28                })?
29                .try_into()?,
30            plaintext: proto_op.plaintext.into(),
31            salt,
32        })
33    }
34}
35
36impl TryFrom<Operation> for OperationProto {
37    type Error = ResponseStatus;
38
39    fn try_from(op: Operation) -> std::result::Result<Self, Self::Error> {
40        let alg = Some(op.alg.try_into()?);
41        let salt = match op.salt {
42            Some(salt) => salt.to_vec(),
43            None => vec![],
44        };
45        Ok(OperationProto {
46            key_name: op.key_name,
47            alg,
48            plaintext: op.plaintext.to_vec(),
49            salt,
50        })
51    }
52}
53
54impl TryFrom<ResultProto> for Result {
55    type Error = ResponseStatus;
56
57    fn try_from(proto_result: ResultProto) -> std::result::Result<Self, Self::Error> {
58        Ok(Result {
59            ciphertext: proto_result.ciphertext.into(),
60        })
61    }
62}
63
64impl TryFrom<Result> for ResultProto {
65    type Error = ResponseStatus;
66
67    fn try_from(result: Result) -> std::result::Result<Self, Self::Error> {
68        Ok(ResultProto {
69            ciphertext: result.ciphertext.to_vec(),
70        })
71    }
72}
73
74#[cfg(test)]
75mod test {
76    use super::super::generated_ops::psa_algorithm as algorithm_proto;
77    use super::super::generated_ops::psa_asymmetric_encrypt::{
78        Operation as OperationProto, Result as ResultProto,
79    };
80    use super::super::{Convert, ProtobufConverter};
81    use crate::operations::psa_algorithm::AsymmetricEncryption;
82    use crate::operations::psa_asymmetric_encrypt::{Operation, Result};
83    use std::convert::TryInto;
84    static CONVERTER: ProtobufConverter = ProtobufConverter {};
85    use crate::operations::{NativeOperation, NativeResult};
86    use crate::requests::{request::RequestBody, response::ResponseBody, Opcode};
87
88    #[test]
89    fn asym_proto_to_op() {
90        let mut proto: OperationProto = Default::default();
91        let message = vec![0x11, 0x22, 0x33];
92        let key_name = "test name".to_string();
93        let salt: Vec<u8> = vec![];
94        proto.plaintext = message.clone();
95        proto.alg = Some(algorithm_proto::algorithm::AsymmetricEncryption {
96            variant: Some(
97                algorithm_proto::algorithm::asymmetric_encryption::Variant::RsaPkcs1v15Crypt(
98                    algorithm_proto::algorithm::asymmetric_encryption::RsaPkcs1v15Crypt {},
99                ),
100            ),
101        });
102        proto.key_name = key_name.clone();
103        proto.salt = salt;
104
105        let op: Operation = proto.try_into().expect("Failed to convert");
106
107        assert_eq!(*op.plaintext, message);
108        assert_eq!(op.key_name, key_name);
109        assert_eq!(op.salt, None);
110    }
111
112    #[test]
113    fn asym_op_to_proto() {
114        let message = vec![0x11, 0x22, 0x33];
115        let key_name = "test name".to_string();
116
117        let op = Operation {
118            plaintext: message.clone().into(),
119            alg: AsymmetricEncryption::RsaPkcs1v15Crypt,
120            key_name: key_name.clone(),
121            salt: None,
122        };
123
124        let proto: OperationProto = op.try_into().expect("Failed to convert");
125
126        assert_eq!(proto.plaintext, message);
127        assert_eq!(proto.key_name, key_name);
128        assert_eq!(proto.salt, vec![]);
129    }
130
131    #[test]
132    fn asym_proto_to_resp() {
133        let mut proto: ResultProto = Default::default();
134        let ciphertext = vec![0x11, 0x22, 0x33];
135        proto.ciphertext = ciphertext.clone();
136
137        let result: Result = proto.try_into().expect("Failed to convert");
138
139        assert_eq!(*result.ciphertext, ciphertext);
140    }
141
142    #[test]
143    fn asym_resp_to_proto() {
144        let ciphertext = vec![0x11, 0x22, 0x33];
145        let result = Result {
146            ciphertext: ciphertext.clone().into(),
147        };
148
149        let proto: ResultProto = result.try_into().expect("Failed to convert");
150
151        assert_eq!(proto.ciphertext, ciphertext);
152    }
153
154    #[test]
155    fn psa_encrypt_message_op_e2e() {
156        let name = "test name".to_string();
157        let op = Operation {
158            key_name: name,
159            alg: AsymmetricEncryption::RsaPkcs1v15Crypt,
160            plaintext: vec![0x11, 0x22, 0x33].into(),
161            salt: None,
162        };
163
164        let body = CONVERTER
165            .operation_to_body(NativeOperation::PsaAsymmetricEncrypt(op))
166            .expect("Failed to convert to body");
167
168        let _ = CONVERTER
169            .body_to_operation(body, Opcode::PsaAsymmetricEncrypt)
170            .expect("Failed to convert to operation");
171    }
172
173    #[test]
174    fn resp_asym_encrypt_e2e() {
175        let result = Result {
176            ciphertext: vec![0x11, 0x22, 0x33].into(),
177        };
178        let body = CONVERTER
179            .result_to_body(NativeResult::PsaAsymmetricEncrypt(result))
180            .expect("Failed to convert request");
181
182        assert!(CONVERTER
183            .body_to_result(body, Opcode::PsaAsymmetricEncrypt)
184            .is_ok());
185    }
186
187    #[test]
188    fn result_from_mangled_resp_body() {
189        let resp_body =
190            ResponseBody::from_bytes(vec![0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88]);
191        assert!(CONVERTER
192            .body_to_result(resp_body, Opcode::PsaAsymmetricEncrypt)
193            .is_err());
194    }
195
196    #[test]
197    fn op_from_mangled_req_body() {
198        let req_body =
199            RequestBody::from_bytes(vec![0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88]);
200
201        assert!(CONVERTER
202            .body_to_operation(req_body, Opcode::PsaAsymmetricEncrypt)
203            .is_err());
204    }
205}