Skip to content

Expose vendor defined error code #300

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

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
41 changes: 36 additions & 5 deletions cryptoki/src/error/rv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@
// SPDX-License-Identifier: Apache-2.0
//! Function types
use crate::context::Function;
use crate::{context::Function, MAX_CK_ULONG};

use super::{Error, Result, RvError};
use cryptoki_sys::*;
use log::error;

#[derive(Copy, Clone, Debug)]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
/// Return value of a PKCS11 function
pub enum Rv {
/// The function exited successfully
Expand Down Expand Up @@ -116,13 +116,14 @@ impl From<CK_RV> for Rv {
CKR_PIN_TOO_WEAK => Rv::Error(RvError::PinTooWeak),
CKR_PUBLIC_KEY_INVALID => Rv::Error(RvError::PublicKeyInvalid),
CKR_FUNCTION_REJECTED => Rv::Error(RvError::FunctionRejected),
CKR_VENDOR_DEFINED => Rv::Error(RvError::VendorDefined),
// Section 3.6 of v3.1: "Return values CKR_VENDOR_DEFINED and above are permanently reserved for token vendors."
CKR_VENDOR_DEFINED..=MAX_CK_ULONG => Rv::Error(RvError::VendorDefined(ck_rv)),
other => {
error!(
"Can not find a corresponding error for {}, converting to GeneralError.",
"Can not find a corresponding error for {}, converting to UnknownErrorCode.",
other
);
Rv::Error(RvError::GeneralError)
Rv::Error(RvError::UnknownErrorCode(other))
}
}
}
Expand All @@ -137,3 +138,33 @@ impl Rv {
}
}
}

#[cfg(test)]
mod test {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the tests!

use super::{Rv, RvError};
use cryptoki_sys::*;

#[test]
fn vendor_defined_exact() {
let code = CKR_VENDOR_DEFINED;
let actual = Rv::from(code);
let expected = Rv::Error(RvError::VendorDefined(code));
assert_eq!(actual, expected);
}

#[test]
fn vendor_defined_higher() {
let code = CKR_VENDOR_DEFINED + 42;
let actual = Rv::from(code);
let expected = Rv::Error(RvError::VendorDefined(code));
assert_eq!(actual, expected);
}

#[test]
fn unknown_code() {
let code = CKR_VENDOR_DEFINED - 42;
let actual = Rv::from(code);
let expected = Rv::Error(RvError::UnknownErrorCode(code));
assert_eq!(actual, expected);
}
}
10 changes: 7 additions & 3 deletions cryptoki/src/error/rv_error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// SPDX-License-Identifier: Apache-2.0
//! Function types
use cryptoki_sys::CK_RV;
use std::fmt;

#[derive(Debug, Copy, Clone, PartialEq, Eq)]
Expand Down Expand Up @@ -193,8 +194,10 @@ pub enum RvError {
PublicKeyInvalid,
/// The signature request is rejected by the user.
FunctionRejected,
/// CKR_VENDOR_DEFINED
VendorDefined,
/// A vendor defined error code, CKR_VENDOR_DEFINED and above.
VendorDefined(CK_RV),
/// An unknown error code
UnknownErrorCode(CK_RV),
}

impl fmt::Display for RvError {
Expand Down Expand Up @@ -293,7 +296,8 @@ impl fmt::Display for RvError {
RvError::PinTooWeak => write!(f, "The specified PIN is too weak so that it could be easy to guess. If the PIN is too short, CKR_PIN_LEN_RANGE should be returned instead. This return code only applies to functions which attempt to set a PIN."),
RvError::PublicKeyInvalid => write!(f, "The public key fails a public key validation. For example, an EC public key fails the public key validation specified in Section 5.2.2 of ANSI X9.62. This error code may be returned by C_CreateObject, when the public key is created, or by C_VerifyInit or C_VerifyRecoverInit, when the public key is used. It may also be returned by C_DeriveKey, in preference to CKR_MECHANISM_PARAM_INVALID, if the other party's public key specified in the mechanism's parameters is invalid."),
RvError::FunctionRejected => write!(f, "The signature request is rejected by the user."),
RvError::VendorDefined => write!(f, "CKR_VENDOR_DEFINED"),
RvError::VendorDefined(code) => write!(f, "CKR_VENDOR_DEFINED({code:#x})",),
RvError::UnknownErrorCode(code) => write!(f, "Unknown error code: {code:#x}"),
}
}
}
2 changes: 2 additions & 0 deletions cryptoki/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ pub mod types;

use cryptoki_sys::CK_UTF8CHAR;

const MAX_CK_ULONG: cryptoki_sys::CK_ULONG = !0;

fn string_from_blank_padded(field: &[CK_UTF8CHAR]) -> String {
let decoded_str = String::from_utf8_lossy(field);
decoded_str.trim_end_matches(' ').to_string()
Expand Down
11 changes: 5 additions & 6 deletions cryptoki/src/object.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use crate::error::{Error, Result};
use crate::mechanism::MechanismType;
use crate::types::{Date, Ulong};
use crate::MAX_CK_ULONG;
use cryptoki_sys::*;
use log::error;
use std::convert::TryFrom;
Expand All @@ -14,8 +15,6 @@ use std::fmt::Formatter;
use std::mem::size_of;
use std::ops::Deref;

const MAX_CU_ULONG: CK_ULONG = !0;

#[derive(Debug, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
#[non_exhaustive]
/// Type of an attribute
Expand Down Expand Up @@ -261,7 +260,7 @@ impl AttributeType {
CKA_DERIVE_TEMPLATE => String::from(stringify!(CKA_DERIVE_TEMPLATE)),
CKA_ALLOWED_MECHANISMS => String::from(stringify!(CKA_ALLOWED_MECHANISMS)),
CKA_UNIQUE_ID => String::from(stringify!(CKA_UNIQUE_ID)),
CKA_VENDOR_DEFINED..=MAX_CU_ULONG => {
CKA_VENDOR_DEFINED..=MAX_CK_ULONG => {
format!("{}_{}", stringify!(CKA_VENDOR_DEFINED), val)
}
_ => format!("unknown ({val:08x})"),
Expand Down Expand Up @@ -409,7 +408,7 @@ impl TryFrom<CK_ATTRIBUTE_TYPE> for AttributeType {
CKA_VERIFY_RECOVER => Ok(AttributeType::VerifyRecover),
CKA_WRAP => Ok(AttributeType::Wrap),
CKA_WRAP_WITH_TRUSTED => Ok(AttributeType::WrapWithTrusted),
CKA_VENDOR_DEFINED..=MAX_CU_ULONG => Ok(AttributeType::VendorDefined(attribute_type)),
CKA_VENDOR_DEFINED..=MAX_CK_ULONG => Ok(AttributeType::VendorDefined(attribute_type)),
attr_type => {
error!("Attribute type {} not supported.", attr_type);
Err(Error::NotSupported)
Expand Down Expand Up @@ -1296,7 +1295,7 @@ impl KeyType {
CKK_EC_EDWARDS => String::from(stringify!(CKK_EC_EDWARDS)),
CKK_EC_MONTGOMERY => String::from(stringify!(CKK_EC_MONTGOMERY)),
CKK_HKDF => String::from(stringify!(CKK_HKDF)),
CKK_VENDOR_DEFINED..=MAX_CU_ULONG => String::from(stringify!(key_type)),
CKK_VENDOR_DEFINED..=MAX_CK_ULONG => String::from(stringify!(key_type)),
_ => format!("unknown ({key_type:08x})"),
}
}
Expand Down Expand Up @@ -1371,7 +1370,7 @@ impl TryFrom<CK_KEY_TYPE> for KeyType {
CKK_EC_EDWARDS => Ok(KeyType::EC_EDWARDS),
CKK_EC_MONTGOMERY => Ok(KeyType::EC_MONTGOMERY),
CKK_HKDF => Ok(KeyType::HKDF),
CKK_VENDOR_DEFINED..=MAX_CU_ULONG => KeyType::new_vendor_defined(key_type),
CKK_VENDOR_DEFINED..=MAX_CK_ULONG => KeyType::new_vendor_defined(key_type),
_ => {
error!("Key type {} is not supported.", key_type);
Err(Error::NotSupported)
Expand Down