1use std::{
7 self,
8 fmt::{self, Debug, Formatter},
9 result::Result,
10};
11
12use openssl::{hash, pkey, rsa, sign};
13
14use opcua_types::status_code::StatusCode;
15use openssl::sign::RsaPssSaltlen;
16
17#[derive(Copy, Clone, Debug, PartialEq)]
18pub enum RsaPadding {
19 Pkcs1,
20 OaepSha1,
21 OaepSha256,
22 Pkcs1Pss,
23}
24
25impl Into<rsa::Padding> for RsaPadding {
26 fn into(self) -> rsa::Padding {
27 match self {
28 RsaPadding::Pkcs1 => rsa::Padding::PKCS1,
29 RsaPadding::OaepSha1 => rsa::Padding::PKCS1_OAEP,
30 RsaPadding::Pkcs1Pss => rsa::Padding::PKCS1_PSS,
31 RsaPadding::OaepSha256 => rsa::Padding::PKCS1_OAEP,
33 }
34 }
35}
36
37#[derive(Debug)]
38pub struct PKeyError;
39
40impl fmt::Display for PKeyError {
41 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
42 write!(f, "PKeyError")
43 }
44}
45
46impl std::error::Error for PKeyError {}
47
48pub struct PKey<T> {
51 pub(crate) value: pkey::PKey<T>,
52}
53
54pub type PublicKey = PKey<pkey::Public>;
56pub type PrivateKey = PKey<pkey::Private>;
58
59impl<T> Debug for PKey<T> {
60 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
61 write!(f, "[pkey]")
64 }
65}
66
67pub trait KeySize {
68 fn bit_length(&self) -> usize;
69
70 fn size(&self) -> usize {
71 self.bit_length() / 8
72 }
73
74 fn calculate_cipher_text_size(&self, data_size: usize, padding: RsaPadding) -> usize {
75 let plain_text_block_size = self.plain_text_block_size(padding);
76 let block_count = if data_size % plain_text_block_size == 0 {
77 data_size / plain_text_block_size
78 } else {
79 (data_size / plain_text_block_size) + 1
80 };
81 block_count * self.cipher_text_block_size()
82 }
83
84 fn plain_text_block_size(&self, padding: RsaPadding) -> usize {
85 match padding {
89 RsaPadding::Pkcs1 => self.size() - 11,
90 RsaPadding::OaepSha1 => self.size() - 42,
91 RsaPadding::OaepSha256 => self.size() - 66,
92 _ => panic!("Unsupported padding"),
93 }
94 }
95
96 fn cipher_text_block_size(&self) -> usize {
97 self.size()
98 }
99}
100
101impl KeySize for PrivateKey {
102 fn bit_length(&self) -> usize {
104 self.value.bits() as usize
105 }
106}
107
108impl PrivateKey {
109 pub fn new(bit_length: u32) -> PrivateKey {
110 PKey {
111 value: {
112 let rsa = rsa::Rsa::generate(bit_length).unwrap();
113 pkey::PKey::from_rsa(rsa).unwrap()
114 },
115 }
116 }
117
118 pub fn wrap_private_key(pkey: pkey::PKey<pkey::Private>) -> PrivateKey {
119 PrivateKey { value: pkey }
120 }
121
122 pub fn from_pem(pem: &[u8]) -> Result<PrivateKey, PKeyError> {
123 pkey::PKey::private_key_from_pem(pem)
124 .map(|value| PKey { value })
125 .map_err(|_| {
126 error!("Cannot produce a private key from the data supplied");
127 PKeyError
128 })
129 }
130
131 pub fn private_key_to_pem(&self) -> Result<Vec<u8>, PKeyError> {
132 self.value.private_key_to_pem_pkcs8().map_err(|_| {
133 error!("Cannot turn private key to PEM");
134 PKeyError
135 })
136 }
137
138 fn sign(
140 &self,
141 message_digest: hash::MessageDigest,
142 data: &[u8],
143 signature: &mut [u8],
144 padding: RsaPadding,
145 ) -> Result<usize, StatusCode> {
146 trace!("RSA signing");
147 if let Ok(mut signer) = sign::Signer::new(message_digest, &self.value) {
148 let _ = signer.set_rsa_padding(padding.into());
149 let _ = signer.set_rsa_pss_saltlen(RsaPssSaltlen::DIGEST_LENGTH);
150 if signer.update(data).is_ok() {
151 return signer
152 .sign_to_vec()
153 .map(|result| {
154 trace!(
155 "Signature result, len {} = {:?}, copying to signature len {}",
156 result.len(),
157 result,
158 signature.len()
159 );
160 signature.copy_from_slice(&result);
161 result.len()
162 })
163 .map_err(|err| {
164 debug!("Cannot sign data - error = {:?}", err);
165 StatusCode::BadUnexpectedError
166 });
167 }
168 }
169 Err(StatusCode::BadUnexpectedError)
170 }
171
172 pub fn sign_sha1(&self, data: &[u8], signature: &mut [u8]) -> Result<usize, StatusCode> {
174 self.sign(
175 hash::MessageDigest::sha1(),
176 data,
177 signature,
178 RsaPadding::Pkcs1,
179 )
180 }
181
182 pub fn sign_sha256(&self, data: &[u8], signature: &mut [u8]) -> Result<usize, StatusCode> {
184 self.sign(
185 hash::MessageDigest::sha256(),
186 data,
187 signature,
188 RsaPadding::Pkcs1,
189 )
190 }
191
192 pub fn sign_sha256_pss(&self, data: &[u8], signature: &mut [u8]) -> Result<usize, StatusCode> {
194 self.sign(
195 hash::MessageDigest::sha256(),
196 data,
197 signature,
198 RsaPadding::Pkcs1Pss,
199 )
200 }
201
202 pub fn private_decrypt(
205 &self,
206 src: &[u8],
207 dst: &mut [u8],
208 padding: RsaPadding,
209 ) -> Result<usize, PKeyError> {
210 let cipher_text_block_size = self.cipher_text_block_size();
212 let rsa = self.value.rsa().unwrap();
213 let is_oaep_sha256 = padding == RsaPadding::OaepSha256;
214 let rsa_padding: rsa::Padding = padding.into();
215
216 let mut src_idx = 0;
218 let mut dst_idx = 0;
219
220 let src_len = src.len();
221 while src_idx < src_len {
222 dst_idx += {
224 let src = &src[src_idx..(src_idx + cipher_text_block_size)];
225 let dst = &mut dst[dst_idx..(dst_idx + cipher_text_block_size)];
226
227 if is_oaep_sha256 {
228 oaep_sha256::decrypt(&rsa, src, dst)
229 } else {
230 rsa.private_decrypt(src, dst, rsa_padding)
231 }.map_err(|err| {
232 error!("Decryption failed for key size {}, src idx {}, dst idx {}, padding {:?}, error - {:?}", cipher_text_block_size, src_idx, dst_idx, padding, err);
233 PKeyError
234 })?
235 };
236 src_idx += cipher_text_block_size;
237 }
238 Ok(dst_idx)
239 }
240}
241
242impl KeySize for PublicKey {
243 fn bit_length(&self) -> usize {
245 self.value.bits() as usize
246 }
247}
248
249impl PublicKey {
250 pub fn wrap_public_key(pkey: pkey::PKey<pkey::Public>) -> PublicKey {
251 PublicKey { value: pkey }
252 }
253
254 fn verify(
256 &self,
257 message_digest: hash::MessageDigest,
258 data: &[u8],
259 signature: &[u8],
260 padding: RsaPadding,
261 ) -> Result<bool, StatusCode> {
262 trace!(
263 "RSA verifying, against signature {:?}, len {}",
264 signature,
265 signature.len()
266 );
267 if let Ok(mut verifier) = sign::Verifier::new(message_digest, &self.value) {
268 let _ = verifier.set_rsa_padding(padding.into());
269 let _ = verifier.set_rsa_pss_saltlen(RsaPssSaltlen::DIGEST_LENGTH);
270 if verifier.update(data).is_ok() {
271 return verifier
272 .verify(signature)
273 .map(|result| {
274 trace!("Key verified = {:?}", result);
275 result
276 })
277 .map_err(|err| {
278 debug!("Cannot verify key - error = {:?}", err);
279 StatusCode::BadUnexpectedError
280 });
281 }
282 }
283 Err(StatusCode::BadUnexpectedError)
284 }
285
286 pub fn verify_sha1(&self, data: &[u8], signature: &[u8]) -> Result<bool, StatusCode> {
288 self.verify(
289 hash::MessageDigest::sha1(),
290 data,
291 signature,
292 RsaPadding::Pkcs1,
293 )
294 }
295
296 pub fn verify_sha256(&self, data: &[u8], signature: &[u8]) -> Result<bool, StatusCode> {
298 self.verify(
299 hash::MessageDigest::sha256(),
300 data,
301 signature,
302 RsaPadding::Pkcs1,
303 )
304 }
305
306 pub fn verify_sha256_pss(&self, data: &[u8], signature: &[u8]) -> Result<bool, StatusCode> {
308 self.verify(
309 hash::MessageDigest::sha256(),
310 data,
311 signature,
312 RsaPadding::Pkcs1Pss,
313 )
314 }
315
316 pub fn public_encrypt(
319 &self,
320 src: &[u8],
321 dst: &mut [u8],
322 padding: RsaPadding,
323 ) -> Result<usize, PKeyError> {
324 let cipher_text_block_size = self.cipher_text_block_size();
325 let plain_text_block_size = self.plain_text_block_size(padding);
326
327 let rsa = self.value.rsa().unwrap();
331 let is_oaep_sha256 = padding == RsaPadding::OaepSha256;
332 let padding: rsa::Padding = padding.into();
333
334 let mut src_idx = 0;
336 let mut dst_idx = 0;
337
338 let src_len = src.len();
339 while src_idx < src_len {
340 let bytes_to_encrypt = if src_len < plain_text_block_size {
341 src_len
342 } else if (src_len - src_idx) < plain_text_block_size {
343 src_len - src_idx
344 } else {
345 plain_text_block_size
346 };
347
348 dst_idx += {
350 let src = &src[src_idx..(src_idx + bytes_to_encrypt)];
351 let dst = &mut dst[dst_idx..(dst_idx + cipher_text_block_size)];
352
353 if is_oaep_sha256 {
354 oaep_sha256::encrypt(&rsa, src, dst)
355 } else {
356 rsa.public_encrypt(src, dst, padding)
357 }.map_err(|err| {
358 error!("Encryption failed for bytes_to_encrypt {}, src len {}, src_idx {}, dst len {}, dst_idx {}, cipher_text_block_size {}, plain_text_block_size {}, error - {:?}",
359 bytes_to_encrypt, src.len(), src_idx, dst.len(), dst_idx, cipher_text_block_size, plain_text_block_size, err);
360 PKeyError
361 })?
362 };
363
364 src_idx += bytes_to_encrypt;
366 }
367
368 Ok(dst_idx)
369 }
370}
371
372mod oaep_sha256 {
376 use std::ptr;
377
378 use foreign_types::ForeignType;
379 use libc::*;
380 use openssl::{
381 error,
382 pkey::{Private, Public},
383 rsa::{self, Rsa},
384 };
385 use openssl_sys::*;
386
387 unsafe fn set_evp_ctrl_oaep_sha256(ctx: *mut EVP_PKEY_CTX) {
389 EVP_PKEY_CTX_set_rsa_padding(ctx, rsa::Padding::PKCS1_OAEP.as_raw());
390 let md = EVP_sha256() as *mut EVP_MD;
391 EVP_PKEY_CTX_set_rsa_mgf1_md(ctx, md);
392 const EVP_PKEY_CTRL_RSA_OAEP_MD: c_int = EVP_PKEY_ALG_CTRL + 9;
394 EVP_PKEY_CTX_ctrl(
395 ctx,
396 EVP_PKEY_RSA,
397 EVP_PKEY_OP_TYPE_CRYPT,
398 EVP_PKEY_CTRL_RSA_OAEP_MD,
399 0,
400 md as *mut c_void,
401 );
402 }
403
404 pub fn decrypt(
406 pkey: &Rsa<Private>,
407 from: &[u8],
408 to: &mut [u8],
409 ) -> Result<usize, error::ErrorStack> {
410 let result;
411 unsafe {
412 let priv_key = EVP_PKEY_new();
413 if !priv_key.is_null() {
414 EVP_PKEY_set1_RSA(priv_key, pkey.as_ptr());
415 let ctx = EVP_PKEY_CTX_new(priv_key, ptr::null_mut());
416 EVP_PKEY_free(priv_key);
417
418 if !ctx.is_null() {
419 let _ret = EVP_PKEY_decrypt_init(ctx);
420 set_evp_ctrl_oaep_sha256(ctx);
421
422 let mut out_len: size_t = to.len();
423 let ret = EVP_PKEY_decrypt(
424 ctx,
425 to.as_mut_ptr(),
426 &mut out_len,
427 from.as_ptr(),
428 from.len(),
429 );
430 if ret > 0 && out_len > 0 {
431 result = Ok(out_len as usize);
432 } else {
433 trace!(
434 "oaep_sha256::decrypt EVP_PKEY_decrypt, ret = {}, out_len = {}",
435 ret,
436 out_len
437 );
438 result = Err(error::ErrorStack::get());
439 }
440 EVP_PKEY_CTX_free(ctx);
441 } else {
442 trace!("oaep_sha256::decrypt EVP_PKEY_CTX_new");
443 result = Err(error::ErrorStack::get());
444 }
445 } else {
446 trace!(
447 "oaep_sha256::decrypt EVP_PKEY_new failed, err {}",
448 ERR_get_error()
449 );
450 result = Err(error::ErrorStack::get());
451 }
452 }
453
454 result
455 }
456
457 pub fn encrypt(
459 pkey: &Rsa<Public>,
460 from: &[u8],
461 to: &mut [u8],
462 ) -> Result<usize, error::ErrorStack> {
463 let result;
464 unsafe {
465 let pub_key = EVP_PKEY_new();
466 if !pub_key.is_null() {
467 EVP_PKEY_set1_RSA(pub_key, pkey.as_ptr());
468 let ctx = EVP_PKEY_CTX_new(pub_key, ptr::null_mut());
469 EVP_PKEY_free(pub_key);
470
471 if !ctx.is_null() {
472 let _ret = EVP_PKEY_encrypt_init(ctx);
473 set_evp_ctrl_oaep_sha256(ctx);
474
475 let mut out_len: size_t = to.len();
476 let ret = EVP_PKEY_encrypt(
477 ctx,
478 to.as_mut_ptr(),
479 &mut out_len,
480 from.as_ptr(),
481 from.len(),
482 );
483 if ret > 0 && out_len > 0 {
484 result = Ok(out_len as usize);
485 } else {
486 trace!(
487 "oaep_sha256::encrypt EVP_PKEY_encrypt, ret = {}, out_len = {}",
488 ret,
489 out_len
490 );
491 result = Err(error::ErrorStack::get());
492 }
493 EVP_PKEY_CTX_free(ctx);
494 } else {
495 trace!("oaep_sha256::encrypt EVP_PKEY_CTX_new");
496 result = Err(error::ErrorStack::get());
497 }
498 } else {
499 trace!(
500 "oaep_sha256::encrypt EVP_PKEY_new failed, err {}",
501 ERR_get_error()
502 );
503 result = Err(error::ErrorStack::get());
504 }
505 }
506 result
507 }
508}