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

Use rust's own bool type in abstraction crate #61

Merged
merged 2 commits into from
Nov 5, 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
117 changes: 71 additions & 46 deletions cryptoki/src/object.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

use crate::error::{Error, Result};
use crate::mechanism::MechanismType;
use crate::types::{Bbool, Date, Ulong};
use crate::types::{Date, Ulong};
use cryptoki_sys::*;
use log::error;
use std::convert::TryFrom;
Expand Down Expand Up @@ -412,9 +412,9 @@ pub enum Attribute {
/// List of mechanisms allowed to be used with the key
AllowedMechanisms(Vec<MechanismType>),
/// Indicates that the user has to supply the PIN for each use with the key
AlwaysAuthenticate(Bbool),
AlwaysAuthenticate(bool),
/// Indicates if the key has always had the Sensitive attribute set to true
AlwaysSensitive(Bbool),
AlwaysSensitive(bool),
/// Description of the application that manages the object
Application(Vec<u8>),
/// BER-encoding of a sequence of object identifier values
Expand All @@ -430,27 +430,27 @@ pub enum Attribute {
/// The CRT coefficient `iqmp` of an RSA private key
Coefficient(Vec<u8>),
/// Determines if an object can be copied
Copyable(Bbool),
Copyable(bool),
/// Determines if a key supports decryption
Decrypt(Bbool),
Decrypt(bool),
/// Determines if it is possible to derive other keys from the key
Derive(Bbool),
Derive(bool),
/// Determines if it is possible to destroy an object
Destroyable(Bbool),
Destroyable(bool),
/// Parameters describing an elliptic curve
EcParams(Vec<u8>),
/// Elliptic Curve point
EcPoint(Vec<u8>),
/// Determines if a key supports encryption
Encrypt(Bbool),
Encrypt(bool),
/// The end date of the object
EndDate(Date),
/// The private exponent `dmp1` of an RSA private key
Exponent1(Vec<u8>),
/// The private exponent `dmq1` of an RSA private key
Exponent2(Vec<u8>),
/// Determines if a key is extractable and can be wrapped
Extractable(Bbool),
Extractable(bool),
/// Hash of issuer public key
HashOfIssuerPublicKey(Vec<u8>),
/// Hash of subject public key
Expand All @@ -466,15 +466,15 @@ pub enum Attribute {
/// Description of the object
Label(Vec<u8>),
/// Indicates if the key was generated locally or copied from a locally created object
Local(Bbool),
Local(bool),
/// Determines if the object can be modified
Modifiable(Bbool),
Modifiable(bool),
/// Modulus value of a key
Modulus(Vec<u8>),
/// Length in bits of the modulus of a key
ModulusBits(Ulong),
/// Indicates if the key has never had the Extractable attribute set to true
NeverExtractable(Bbool),
NeverExtractable(bool),
/// Object ID
ObjectId(Vec<u8>),
/// DER encoding of the attribute certificate's subject field
Expand All @@ -486,45 +486,45 @@ pub enum Attribute {
/// The prime `q` of an RSA private key
Prime2(Vec<u8>),
/// Determines if the object is private
Private(Bbool),
Private(bool),
/// The private exponent `d`
PrivateExponent(Vec<u8>),
/// Public exponent value of a key
PublicExponent(Vec<u8>),
/// DER-encoding of the SubjectPublicKeyInfo
PublicKeyInfo(Vec<u8>),
/// Determines if the key is sensitive
Sensitive(Bbool),
Sensitive(bool),
/// DER encoding of the certificate serial number
SerialNumber(Vec<u8>),
/// Determines if a key supports signing
Sign(Bbool),
Sign(bool),
/// Determines if a key supports signing where the data can be recovered from the signature
SignRecover(Bbool),
SignRecover(bool),
/// The start date of the object
StartDate(Date),
/// DER-encoding of certificate subject name
Subject(Vec<u8>),
/// Determines if the object is a token object
Token(Bbool),
Token(bool),
/// Determines if an object is trusted
Trusted(Bbool),
Trusted(bool),
/// Determines if a key supports unwrapping
Unwrap(Bbool),
Unwrap(bool),
/// Gives the URL where the complete certificate can ber obtained
Url(Vec<u8>),
/// Value of the object
Value(Vec<u8>),
/// Length in bytes of the value
ValueLen(Ulong),
/// Determines if a key supports verifying
Verify(Bbool),
Verify(bool),
/// Determines if a key supports verifying where the data can be recovered from the signature
VerifyRecover(Bbool),
VerifyRecover(bool),
/// Determines if a key supports wrapping
Wrap(Bbool),
Wrap(bool),
/// Indicates that the key can only be wrapped with a wrapping key that has the Trusted attribute
WrapWithTrusted(Bbool),
WrapWithTrusted(bool),
}

impl Attribute {
Expand Down Expand Up @@ -617,7 +617,7 @@ impl Attribute {
| Attribute::Verify(_)
| Attribute::VerifyRecover(_)
| Attribute::Wrap(_)
| Attribute::WrapWithTrusted(_) => 1,
| Attribute::WrapWithTrusted(_) => std::mem::size_of::<bool>(),
Copy link
Collaborator

Choose a reason for hiding this comment

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

Extreme corner case -> CK_BBOOL is defined as an unsigned char. What if the architecture defines a char to not be 8-bits (e.g. not POSIX compliant).

Googling this question turns up two TI DSPs that if someone implemented a cryptoki token on I'd question their sanity.

I think this is fine, but just wanted to pose the question.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good catch. It may be possible at an architectural level, but the standard itself excludes that possibility by explicitly saying "unsigned 8-bit value".

At this particular location, the type being sized is exactly the type that the raw pointer points to. So if, say, CK_BBOOL somehow gets bigger because of a weird backing c_uchar, the ptr and len calls still match each other. And the provider should return CKR_BUFFER_TOO_SMALL or some other error code.

Attribute::Base(_) => 1,
Attribute::Application(bytes) | Attribute::Label(bytes) | Attribute::Url(bytes) => {
std::mem::size_of::<CK_UTF8CHAR>() * bytes.len()
Expand Down Expand Up @@ -669,6 +669,10 @@ impl Attribute {
/// will not use Attribute parameters but return them
/// directly to the caller.
fn ptr(&self) -> *mut c_void {
// Note: bools in Rust are guaranteed to occupy a byte, so
// &mut bool as a raw pointer will provide the same space
// needed for CK_BBOOL types. See also:
// https://doc.rust-lang.org/reference/type-layout.html#primitive-data-layout
match self {
// CK_BBOOL
Attribute::AlwaysAuthenticate(b)
Expand Down Expand Up @@ -755,6 +759,19 @@ impl From<&Attribute> for CK_ATTRIBUTE {
}
}

/// Private function standing in for TryInto<bool> for &[u8]
/// which can't be implemented through the actual trait because
/// it and both types are external to this crate.
/// NB from the specification: "In Cryptoki, the CK_BBOOL data type
/// is a Boolean type that can be true or false. A zero value means
/// false, and a nonzero value means true." so there is no invalid
/// byte value.
fn try_u8_into_bool(slice: &[u8]) -> Result<bool> {
let as_array: [u8; std::mem::size_of::<CK_BBOOL>()] = slice.try_into()?;
let as_byte = CK_BBOOL::from_ne_bytes(as_array);
Ok(!matches!(as_byte, 0u8))
}

impl TryFrom<CK_ATTRIBUTE> for Attribute {
type Error = Error;

Expand All @@ -769,28 +786,36 @@ impl TryFrom<CK_ATTRIBUTE> for Attribute {
};
match attr_type {
// CK_BBOOL
AttributeType::AlwaysAuthenticate => Ok(Attribute::AlwaysAuthenticate(val.try_into()?)),
AttributeType::AlwaysSensitive => Ok(Attribute::AlwaysSensitive(val.try_into()?)),
AttributeType::Copyable => Ok(Attribute::Copyable(val.try_into()?)),
AttributeType::Decrypt => Ok(Attribute::Decrypt(val.try_into()?)),
AttributeType::Derive => Ok(Attribute::Derive(val.try_into()?)),
AttributeType::Destroyable => Ok(Attribute::Destroyable(val.try_into()?)),
AttributeType::Encrypt => Ok(Attribute::Encrypt(val.try_into()?)),
AttributeType::Extractable => Ok(Attribute::Extractable(val.try_into()?)),
AttributeType::Local => Ok(Attribute::Local(val.try_into()?)),
AttributeType::Modifiable => Ok(Attribute::Modifiable(val.try_into()?)),
AttributeType::NeverExtractable => Ok(Attribute::NeverExtractable(val.try_into()?)),
AttributeType::Private => Ok(Attribute::Private(val.try_into()?)),
AttributeType::Sensitive => Ok(Attribute::Sensitive(val.try_into()?)),
AttributeType::Sign => Ok(Attribute::Sign(val.try_into()?)),
AttributeType::SignRecover => Ok(Attribute::SignRecover(val.try_into()?)),
AttributeType::Token => Ok(Attribute::Token(val.try_into()?)),
AttributeType::Trusted => Ok(Attribute::Trusted(val.try_into()?)),
AttributeType::Unwrap => Ok(Attribute::Unwrap(val.try_into()?)),
AttributeType::Verify => Ok(Attribute::Verify(val.try_into()?)),
AttributeType::VerifyRecover => Ok(Attribute::VerifyRecover(val.try_into()?)),
AttributeType::Wrap => Ok(Attribute::Wrap(val.try_into()?)),
AttributeType::WrapWithTrusted => Ok(Attribute::WrapWithTrusted(val.try_into()?)),
AttributeType::AlwaysAuthenticate => {
Ok(Attribute::AlwaysAuthenticate(try_u8_into_bool(val)?))
}
AttributeType::AlwaysSensitive => {
Ok(Attribute::AlwaysSensitive(try_u8_into_bool(val)?))
}
AttributeType::Copyable => Ok(Attribute::Copyable(try_u8_into_bool(val)?)),
AttributeType::Decrypt => Ok(Attribute::Decrypt(try_u8_into_bool(val)?)),
AttributeType::Derive => Ok(Attribute::Derive(try_u8_into_bool(val)?)),
AttributeType::Destroyable => Ok(Attribute::Destroyable(try_u8_into_bool(val)?)),
AttributeType::Encrypt => Ok(Attribute::Encrypt(try_u8_into_bool(val)?)),
AttributeType::Extractable => Ok(Attribute::Extractable(try_u8_into_bool(val)?)),
AttributeType::Local => Ok(Attribute::Local(try_u8_into_bool(val)?)),
AttributeType::Modifiable => Ok(Attribute::Modifiable(try_u8_into_bool(val)?)),
AttributeType::NeverExtractable => {
Ok(Attribute::NeverExtractable(try_u8_into_bool(val)?))
}
AttributeType::Private => Ok(Attribute::Private(try_u8_into_bool(val)?)),
AttributeType::Sensitive => Ok(Attribute::Sensitive(try_u8_into_bool(val)?)),
AttributeType::Sign => Ok(Attribute::Sign(try_u8_into_bool(val)?)),
AttributeType::SignRecover => Ok(Attribute::SignRecover(try_u8_into_bool(val)?)),
AttributeType::Token => Ok(Attribute::Token(try_u8_into_bool(val)?)),
AttributeType::Trusted => Ok(Attribute::Trusted(try_u8_into_bool(val)?)),
AttributeType::Unwrap => Ok(Attribute::Unwrap(try_u8_into_bool(val)?)),
AttributeType::Verify => Ok(Attribute::Verify(try_u8_into_bool(val)?)),
AttributeType::VerifyRecover => Ok(Attribute::VerifyRecover(try_u8_into_bool(val)?)),
AttributeType::Wrap => Ok(Attribute::Wrap(try_u8_into_bool(val)?)),
AttributeType::WrapWithTrusted => {
Ok(Attribute::WrapWithTrusted(try_u8_into_bool(val)?))
}
// CK_ULONG
AttributeType::ModulusBits => Ok(Attribute::ModulusBits(
CK_ULONG::from_ne_bytes(val.try_into()?).try_into()?,
Expand Down
59 changes: 0 additions & 59 deletions cryptoki/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

use crate::error::{Error, Result};
use cryptoki_sys::*;
use log::error;
use std::convert::TryFrom;
use std::convert::TryInto;
use std::fmt::Formatter;
Expand Down Expand Up @@ -36,64 +35,6 @@ pub(crate) trait Flags: std::fmt::Display {
}
}

#[repr(u8)]
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
/// Byte-sized boolean
pub enum Bbool {
/// False value
False = 0,
/// True value
True = 1,
}

impl TryFrom<&[u8]> for Bbool {
type Error = Error;

fn try_from(slice: &[u8]) -> Result<Self> {
CK_BBOOL::from_ne_bytes(slice.try_into()?).try_into()
}
}

impl From<Bbool> for CK_BBOOL {
fn from(bbool: Bbool) -> Self {
bbool as CK_BBOOL
}
}

impl From<bool> for Bbool {
fn from(val: bool) -> Self {
if val {
Bbool::True
} else {
Bbool::False
}
}
}

impl From<Bbool> for bool {
fn from(val: Bbool) -> Self {
match val {
Bbool::False => false,
Bbool::True => true,
}
}
}

impl TryFrom<CK_BBOOL> for Bbool {
type Error = Error;

fn try_from(bbool: CK_BBOOL) -> Result<Self> {
match bbool {
CK_FALSE => Ok(Bbool::False),
CK_TRUE => Ok(Bbool::True),
other => {
error!("Bbool value {} is invalid.", other);
Err(Error::InvalidValue)
}
}
}
}

#[derive(Debug, Copy, Clone)]
#[repr(transparent)]
/// Value that represents a date
Expand Down
Loading