Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: Support Public Key Algorithms in Crypto Module #80

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,32 @@ use actix_web::http::StatusCode;

#[derive(Error, Debug)]
pub enum RvError {
#[error("EC key generation failed.")]
ErrCryptoPKeyECKeyGenFailed,
#[error("RSA key generation failed.")]
ErrCryptoPKeyRSAKeyGenFailed,
#[error("Public key encryption failed.")]
ErrCryptoPKeyEncFailed,
#[error("Public key decryption failed.")]
ErrCryptoPKeyDecFailed,
#[error("Public key encryption init failed.")]
ErrCryptoPKeyEncInitFailed,
#[error("Public key decryption init failed.")]
ErrCryptoPKeyDecInitFailed,
#[error("Crypro module internal error.")]
ErrCryptoPKeyInternalError,
#[error("Verification failed.")]
ErrCryptoPKeyVerifyFailed,
#[error("Verification initialization failed.")]
ErrCryptoPKeyVerifyInitFailed,
#[error("Signing failed.")]
ErrCryptoPKeySignFailed,
#[error("Signing initialization failed.")]
ErrCryptoPKeySignInitFailed,
#[error("Invalid RSA key size.")]
ErrCryptoPKeyInvalidRSASize,
#[error("Public key operation not supported.")]
ErrCryptoPKeyOPNotSupported,
#[error("Cipher operation update failed.")]
ErrCryptoCipherUpdateFailed,
#[error("Cipher operation finalization failed.")]
Expand Down
261 changes: 260 additions & 1 deletion src/modules/crypto/crypto_adaptors/openssl_adaptor.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,24 @@
//! This is the OpenSSL adaptor.

use crate::errors::RvError;
use crate::modules::crypto::{AEADCipher, AESKeySize, BlockCipher, CipherMode, AES};
use crate::modules::crypto::{
AEADCipher, AESKeySize, BlockCipher,
CipherMode, AES,
RSA, RSAKeySize,
PublicKey, PublicKeyType,
Signature, Encryption,
ECDSA, ECCurveName
};
use openssl::symm::{Cipher, Crypter, Mode, encrypt, encrypt_aead, decrypt, decrypt_aead};
use openssl::rand::rand_priv_bytes;
use openssl::rsa::{Rsa, Padding};
use openssl::pkey::{PKey, Private};
use openssl::pkey_ctx::PkeyCtx;
use crate::modules::crypto::crypto_adaptors::common;
use openssl::nid::Nid;
use openssl::ec::{EcGroup, EcKey};

use zeroize::{Zeroize, Zeroizing};

pub struct AdaptorCTX {
ctx: Crypter,
Expand Down Expand Up @@ -81,3 +95,248 @@ impl AEADCipher for AES {
common_aes_set_tag!(self, tag);
}
}

pub struct AdaptorPKeyCTX {
// The private key in OpenSSL context contains also the public key
private_key: PKey<Private>,
}

// Simply do nothing since OpenSSL will safely clean the memory of a PKEY object (Drop trait)
impl Zeroize for AdaptorPKeyCTX {
fn zeroize(&mut self) {}
}

impl RSA {
/// This function is the constructor of the RSA struct, it returns a new RSA object on success.
///
/// size: RSA key size. Valid options are RSA2048 (default), RSA3072, RSA4096, RSA8192.
/// prime: for multi-prime RSA usage (RFC 8017), default is 2.
pub fn new(
prime: Option<u8>,
size: Option<RSAKeySize>,
) -> Result<Self, RvError> {
return Ok(
RSA {
key_type: PublicKeyType::RSA,
prime: prime.unwrap_or(2),
size: size.unwrap_or(RSAKeySize::RSA2048),
ctx: None,
}
);
}
}

impl PublicKey for RSA {
fn keygen(&mut self) -> Result<(), RvError> {
let bits: u32;
match &self.size {
RSAKeySize::RSA2048 => bits = 2048,
RSAKeySize::RSA3072 => bits = 3072,
RSAKeySize::RSA4096 => bits = 4096,
RSAKeySize::RSA8192 => bits = 8192,
}

let rsa = match Rsa::generate(bits) {
Ok(r) => r,
Err(_e) => return Err(RvError::ErrCryptoPKeyRSAKeyGenFailed),
};

let pkey = match PKey::from_rsa(rsa) {
Ok(r) => r,
Err(_e) => return Err(RvError::ErrCryptoPKeyRSAKeyGenFailed),
};

let adaptor_ctx = AdaptorPKeyCTX { private_key: pkey };
self.ctx = Some(adaptor_ctx);

return Ok(());
}

fn get_key_type(&self) -> Result<&PublicKeyType, RvError> {
return Ok(&self.key_type);
}
}

impl Signature for RSA {
fn sign(&self, data: &Vec<u8>) -> Result<Vec<u8>, RvError> {
let key = &self.ctx.as_ref().unwrap().private_key;

let mut ctx = match PkeyCtx::new(&key) {
Ok(ctx) => ctx,
Err(_e) => return Err(RvError::ErrCryptoPKeyInternalError),
};

match ctx.sign_init() {
Ok(_ret) => {},
Err(_e) => return Err(RvError::ErrCryptoPKeySignInitFailed),
}

let mut signature: Vec<u8> = Vec::new();
match ctx.sign_to_vec(data, &mut signature) {
Ok(_ret) => {},
Err(_e) => return Err(RvError::ErrCryptoPKeySignFailed),
}

return Ok(signature);
}

fn verify(&self, data: &Vec<u8>, sig: &Vec<u8>) -> Result<bool, RvError> {
let key = &self.ctx.as_ref().unwrap().private_key;

let mut ctx = match PkeyCtx::new(&key) {
Ok(ctx) => ctx,
Err(_e) => return Err(RvError::ErrCryptoPKeyInternalError),
};

match ctx.verify_init() {
Ok(_ret) => {},
Err(_e) => return Err(RvError::ErrCryptoPKeyVerifyInitFailed),
}

let valid = match ctx.verify(data, sig) {
Ok(ret) => ret,
Err(_e) => return Err(RvError::ErrCryptoPKeyVerifyFailed),
};

return Ok(valid);
}
}

impl Encryption for RSA {
fn encrypt(&self, plaintext: &Vec<u8>) -> Result<Vec<u8>, RvError> {
let key = &self.ctx.as_ref().unwrap().private_key;

let mut ctx = match PkeyCtx::new(&key) {
Ok(ctx) => ctx,
Err(_e) => return Err(RvError::ErrCryptoPKeyInternalError),
};

match ctx.encrypt_init() {
Ok(_ret) => {},
Err(_e) => return Err(RvError::ErrCryptoPKeyEncInitFailed),
}

let mut ciphertext: Vec<u8> = Vec::new();
match ctx.encrypt_to_vec(plaintext, &mut ciphertext) {
Ok(_ret) => {},
Err(_e) => return Err(RvError::ErrCryptoPKeyEncFailed),
}

return Ok(ciphertext);
}

fn decrypt(&self, ciphertext: &Vec<u8>) -> Result<Vec<u8>, RvError> {
let key = &self.ctx.as_ref().unwrap().private_key;

let mut ctx = match PkeyCtx::new(&key) {
Ok(ctx) => ctx,
Err(_e) => return Err(RvError::ErrCryptoPKeyInternalError),
};

match ctx.decrypt_init() {
Ok(_ret) => {},
Err(_e) => return Err(RvError::ErrCryptoPKeyDecInitFailed),
}

let mut plaintext: Vec<u8> = Vec::new();
match ctx.decrypt_to_vec(ciphertext, &mut plaintext) {
Ok(_ret) => {},
Err(_e) => return Err(RvError::ErrCryptoPKeyDecFailed),
}

return Ok(plaintext);
}
}

impl ECDSA {
/// This function is the constructor of the ECDSA struct, it returns a new ECDSA object
/// on success.
///
/// curve: RSA key size. Valid options are RSA2048 (default), RSA3072, RSA4096, RSA8192.
/// prime: for multi-prime RSA usage (RFC 8017), default is 2.
pub fn new(
curve: Option<ECCurveName>,
) -> Result<Self, RvError> {
return Ok(
ECDSA {
key_type: PublicKeyType::ECDSA,
curve: curve.unwrap_or(ECCurveName::prime256v1),
ctx: None,
}
);
}
}

impl PublicKey for ECDSA {
fn keygen(&mut self) -> Result<(), RvError> {
let nid: Nid;
match &self.curve {
ECCurveName::prime256v1 => nid = Nid::X9_62_PRIME256V1,
}

let group = EcGroup::from_curve_name(nid)?;
let ec = match EcKey::generate(&group) {
Ok(r) => r,
Err(_e) => return Err(RvError::ErrCryptoPKeyECKeyGenFailed),
};

let pkey = match PKey::from_ec_key(ec) {
Ok(r) => r,
Err(_e) => return Err(RvError::ErrCryptoPKeyECKeyGenFailed),
};

let adaptor_ctx = AdaptorPKeyCTX { private_key: pkey };
self.ctx = Some(adaptor_ctx);

return Ok(());
}

fn get_key_type(&self) -> Result<&PublicKeyType, RvError> {
return Ok(&self.key_type);
}
}

impl Signature for ECDSA {
fn sign(&self, data: &Vec<u8>) -> Result<Vec<u8>, RvError> {
let key = &self.ctx.as_ref().unwrap().private_key;

let mut ctx = match PkeyCtx::new(&key) {
Ok(ctx) => ctx,
Err(_e) => return Err(RvError::ErrCryptoPKeyInternalError),
};

match ctx.sign_init() {
Ok(_ret) => {},
Err(_e) => return Err(RvError::ErrCryptoPKeySignInitFailed),
}

let mut signature: Vec<u8> = Vec::new();
match ctx.sign_to_vec(data, &mut signature) {
Ok(_ret) => {},
Err(_e) => return Err(RvError::ErrCryptoPKeySignFailed),
}

return Ok(signature);
}

fn verify(&self, data: &Vec<u8>, sig: &Vec<u8>) -> Result<bool, RvError> {
let key = &self.ctx.as_ref().unwrap().private_key;

let mut ctx = match PkeyCtx::new(&key) {
Ok(ctx) => ctx,
Err(_e) => return Err(RvError::ErrCryptoPKeyInternalError),
};

match ctx.verify_init() {
Ok(_ret) => {},
Err(_e) => return Err(RvError::ErrCryptoPKeyVerifyInitFailed),
}

let valid = match ctx.verify(data, sig) {
Ok(ret) => ret,
Err(_e) => return Err(RvError::ErrCryptoPKeyVerifyFailed),
};

return Ok(valid);
}
}
Loading
Loading