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

Some error improvements #155

Merged
merged 2 commits into from
Feb 1, 2021
Merged
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
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,4 @@ tempfile = "3.0.4"
tokio = {version = "0.2", features = ["full"]}
tokio-io = "0.1"
tss-esapi = "4.0.10-alpha.2"
thiserror = "1.0"
76 changes: 11 additions & 65 deletions src/crypto.rs
Original file line number Diff line number Diff line change
@@ -1,29 +1,28 @@
// use super::*;
use hex;
use openssl::error::ErrorStack;
use openssl::hash::MessageDigest;
use openssl::pkcs5;
use openssl::pkey::{PKey, Private, Public};
use openssl::rsa::{Padding, Rsa};
use openssl::sign::Signer;
use std::error::Error;
use std::fmt;
use std::fs::File;
use std::io::Error as StdIOError;
use std::io::Read;
use std::string::String;

use crate::Result;

/*
* Inputs: secret key
* message to sign
* Output: signed HMAC result
*
* Sign message and return HMAC result string
*/
pub fn do_hmac(
pub(crate) fn do_hmac(
input_key: String,
input_message: String,
) -> Result<String, KeylimeCryptoError> {
) -> Result<String> {
let key = PKey::hmac(input_key.as_bytes())?;
let message = input_message.as_bytes();
let mut signer = Signer::new(MessageDigest::sha384(), &key)?;
Expand All @@ -39,9 +38,9 @@ pub fn do_hmac(
* Import a PEM-encoded RSA public key and return a callable OpenSSL RSA key
* object.
*/
pub fn rsa_import_pubkey(
pub(crate) fn rsa_import_pubkey(
input_key_path: String,
) -> Result<Rsa<Public>, KeylimeCryptoError> {
) -> Result<Rsa<Public>> {
let mut key_buffer = vec![0; 1];
let mut input_key = File::open(input_key_path)?;
input_key.read_to_end(&mut key_buffer)?;
Expand All @@ -54,9 +53,7 @@ pub fn rsa_import_pubkey(
*
* Randomly generate a callable OpenSSL RSA key object with desired key size.
*/
pub fn rsa_generate(
key_size: u32,
) -> Result<Rsa<Private>, KeylimeCryptoError> {
pub(crate) fn rsa_generate(key_size: u32) -> Result<Rsa<Private>> {
Ok(Rsa::generate(key_size)?)
}

Expand All @@ -68,10 +65,10 @@ pub fn rsa_generate(
* Take in an RSA-encrypted ciphertext and an RSA private key and decrypt the
* ciphertext based on PKCS1 OAEP. Parameters match that of Python-Keylime.
*/
pub fn rsa_decrypt(
pub(crate) fn rsa_decrypt(
private_key: Rsa<Private>,
ciphertext: String,
) -> Result<String, KeylimeCryptoError> {
) -> Result<String> {
let mut dec_result = vec![0; private_key.size() as usize];
let dec_len = private_key.private_decrypt(
ciphertext.as_bytes(),
Expand All @@ -95,10 +92,10 @@ pub fn rsa_decrypt(
* PBKDF2 function defaults to SHA-1 unless otherwise specified, and
* Python-Keylime uses this default.
*/
pub fn kdf(
pub(crate) fn kdf(
input_password: String,
input_salt: String,
) -> Result<String, KeylimeCryptoError> {
) -> Result<String> {
let password = input_password.as_bytes();
let salt = input_salt.as_bytes();
let count = 2000;
Expand Down Expand Up @@ -128,57 +125,6 @@ fn to_hex_string(bytes: Vec<u8>) -> String {
strs.join("")
}

/*
* KeylimeCryptoError: Custom error type to be thrown by functions in
* crypto.rs. Wraps I/O errors and OpenSSL ErrorStack structs together into
* one thing.
*/
#[derive(Debug)]
pub enum KeylimeCryptoError {
IOError { details: String },
OpenSSLError { stack: ErrorStack },
}

impl fmt::Display for KeylimeCryptoError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
KeylimeCryptoError::IOError { ref details } => {
f.write_str(&format!("{:?}", details))
}
KeylimeCryptoError::OpenSSLError { ref stack } => {
f.write_str(&format!("{:?}", stack))
}
}
}
}

impl Error for KeylimeCryptoError {
fn description(&self) -> &str {
match *self {
KeylimeCryptoError::IOError { ref details } => {
("Error reading file")
}
KeylimeCryptoError::OpenSSLError { ref stack } => {
("OpenSSL library error")
}
}
}
}

impl From<ErrorStack> for KeylimeCryptoError {
fn from(e: ErrorStack) -> Self {
KeylimeCryptoError::OpenSSLError { stack: e }
}
}

impl From<StdIOError> for KeylimeCryptoError {
fn from(e: StdIOError) -> Self {
KeylimeCryptoError::IOError {
details: format!("{:?}", e),
}
}
}

// Unit Testing
#[cfg(test)]
mod tests {
Expand Down
44 changes: 24 additions & 20 deletions src/error.rs
Original file line number Diff line number Diff line change
@@ -1,39 +1,37 @@
use std::fmt;

#[derive(Debug)]
use thiserror::Error;

#[derive(Error, Debug)]
pub(crate) enum Error {
#[error("HttpServer error: {0}")]
ActixWeb(actix_web::Error),
#[error("TPM Error: {0}")]
TPM(tss_esapi::Error),
#[error("Invalid request")]
InvalidRequest,
#[error("Configuration loading error: {0}")]
Ini(ini::ini::Error),
#[error("Configuration error: {0}")]
Configuration(String),
#[error("Serialization/deserialization error: {0}")]
Serde(serde_json::Error),
#[error("Permission error")]
Permission,
#[error("IO error: {0}")]
IO(std::io::Error),
#[error("Text decoding error: {0}")]
Utf8(std::string::FromUtf8Error),
#[error("Secure Mount error")]
SecureMount,
#[error("TPM in use")]
TPMInUse,
#[error("Execution error: {0:?}, {1}")]
Execution(Option<i32>, String),
#[error("Number parsing error: {0}")]
NumParse(std::num::ParseIntError),
}

impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Error::Ini(err) => {
write!(f, "Error loading configuration: {}", err)
}
Error::TPM(err) => write!(f, "TPM Error encountered: {}", err),
Error::ActixWeb(err) => write!(f, "HttpServer({})", err),
anything => write!(f, "Another error: {:?}", anything),
}
}
}

impl std::error::Error for Error {
fn description(&self) -> &str {
"Keylime Error"
}
#[error("Crypto error: {0}")]
OpenSSLError(openssl::error::ErrorStack),
}

impl From<tss_esapi::Error> for Error {
Expand Down Expand Up @@ -78,4 +76,10 @@ impl From<std::num::ParseIntError> for Error {
}
}

impl From<openssl::error::ErrorStack> for Error {
fn from(err: openssl::error::ErrorStack) -> Self {
Error::OpenSSLError(err)
}
}

pub(crate) type Result<T> = std::result::Result<T, Error>;