src/vtok_p11/src/lib.rs (209 lines of code) (raw):

// Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 extern crate lazy_static; #[macro_use] extern crate log; extern crate serde; extern crate serde_json; extern crate vtok_common; #[macro_use] mod util; mod api; mod backend; mod crypto; mod pkcs11; use crate::crypto::Error as CryptoError; use backend::token::Error as TokenError; /// Device, slot and token capabilities and information mod defs { use super::backend::mech::{MechDigest, Mechanism}; use super::pkcs11; use vtok_common::defs as comm_defs; pub const CRYPTOKI_VERSION: pkcs11::CK_VERSION = ck_version!( pkcs11::CRYPTOKI_VERSION_MAJOR as u8, pkcs11::CRYPTOKI_VERSION_MINOR as u8 ); pub const DEVICE_DESCRIPTION: &str = comm_defs::DEVICE_DESCRIPTION; pub const DEVICE_VERSION: pkcs11::CK_VERSION = ck_version!(0, 1); pub const DEVICE_MANUFACTURER: &str = comm_defs::MANUFACTURER; pub const SLOT_DESCRIPTION: &str = comm_defs::SLOT_DESCRIPTION; pub const SLOT_HARDWARE_VERSION: pkcs11::CK_VERSION = ck_version!(0, 1); pub const SLOT_FIRMWARE_VERSION: pkcs11::CK_VERSION = ck_version!(0, 1); pub const SLOT_MANUFACTURER: &str = comm_defs::MANUFACTURER; pub const MAX_SLOTS: usize = comm_defs::DEVICE_MAX_SLOTS; pub const TOKEN_MANUFACTURER: &str = comm_defs::MANUFACTURER; pub const TOKEN_MODEL: &str = comm_defs::TOKEN_MODEL; pub const TOKEN_MAX_SESSIONS: pkcs11::CK_ULONG = comm_defs::TOKEN_MAX_SESSIONS as pkcs11::CK_ULONG; pub const TOKEN_MAX_RW_SESSIONS: pkcs11::CK_ULONG = 0; pub const TOKEN_MAX_PIN_LEN: pkcs11::CK_ULONG = comm_defs::TOKEN_MIN_PIN_LEN as pkcs11::CK_ULONG; pub const TOKEN_MIN_PIN_LEN: pkcs11::CK_ULONG = comm_defs::TOKEN_MAX_PIN_LEN as pkcs11::CK_ULONG; pub const TOKEN_HARDWARE_VERSION: pkcs11::CK_VERSION = ck_version!(0, 1); pub const TOKEN_FIRMWARE_VERSION: pkcs11::CK_VERSION = ck_version!(0, 1); pub const TOKEN_UTC_TIME: &str = ""; pub const TOKEN_MECH_LIST: [Mechanism; 24] = [ Mechanism::Digest(MechDigest::Sha1), Mechanism::Digest(MechDigest::Sha224), Mechanism::Digest(MechDigest::Sha256), Mechanism::Digest(MechDigest::Sha384), Mechanism::Digest(MechDigest::Sha512), Mechanism::RsaPkcs(None), Mechanism::RsaPkcs(Some(MechDigest::Sha1)), Mechanism::RsaPkcs(Some(MechDigest::Sha224)), Mechanism::RsaPkcs(Some(MechDigest::Sha256)), Mechanism::RsaPkcs(Some(MechDigest::Sha384)), Mechanism::RsaPkcs(Some(MechDigest::Sha512)), Mechanism::RsaPkcsPss(None, None), Mechanism::RsaPkcsPss(Some(MechDigest::Sha1), None), Mechanism::RsaPkcsPss(Some(MechDigest::Sha224), None), Mechanism::RsaPkcsPss(Some(MechDigest::Sha256), None), Mechanism::RsaPkcsPss(Some(MechDigest::Sha384), None), Mechanism::RsaPkcsPss(Some(MechDigest::Sha512), None), Mechanism::RsaX509, Mechanism::Ecdsa(None), Mechanism::Ecdsa(Some(MechDigest::Sha1)), Mechanism::Ecdsa(Some(MechDigest::Sha224)), Mechanism::Ecdsa(Some(MechDigest::Sha256)), Mechanism::Ecdsa(Some(MechDigest::Sha384)), Mechanism::Ecdsa(Some(MechDigest::Sha512)), ]; } /// Helper for comparing Criptoki versions impl PartialEq for pkcs11::CK_VERSION { fn eq(&self, other: &Self) -> bool { self.major == other.major && self.minor == other.minor } } mod data { use lazy_static::lazy_static; use std::sync::{Arc, Mutex}; use super::api; use super::api::nyi; use super::backend::device::Device; use super::defs; use super::pkcs11::*; /// Supported Criptoki PKCS#11 functions. As per specification, /// all functions are exported but some return CKR_FUNCTION_NOT_SUPPORTED. pub static FN_LIST: CK_FUNCTION_LIST = CK_FUNCTION_LIST { version: defs::DEVICE_VERSION, C_Initialize: Some(api::C_Initialize), C_Finalize: Some(api::C_Finalize), C_GetInfo: Some(api::C_GetInfo), C_GetFunctionList: Some(api::C_GetFunctionList), C_GetSlotList: Some(api::token::C_GetSlotList), C_GetSlotInfo: Some(api::token::C_GetSlotInfo), C_GetTokenInfo: Some(api::token::C_GetTokenInfo), C_GetMechanismList: Some(api::token::C_GetMechanismList), C_GetMechanismInfo: Some(api::token::C_GetMechanismInfo), C_InitToken: Some(api::token::C_InitToken), C_InitPIN: Some(nyi::C_InitPIN), C_SetPIN: Some(nyi::C_SetPIN), C_OpenSession: Some(api::session::C_OpenSession), C_CloseSession: Some(api::session::C_CloseSession), C_CloseAllSessions: Some(api::session::C_CloseAllSessions), C_GetSessionInfo: Some(api::session::C_GetSessionInfo), C_GetOperationState: Some(nyi::C_GetOperationState), C_SetOperationState: Some(nyi::C_SetOperationState), C_Login: Some(api::token::C_Login), C_Logout: Some(api::token::C_Logout), C_CreateObject: Some(nyi::C_CreateObject), C_CopyObject: Some(nyi::C_CopyObject), C_DestroyObject: Some(nyi::C_DestroyObject), C_GetObjectSize: Some(api::object::C_GetObjectSize), C_GetAttributeValue: Some(api::object::C_GetAttributeValue), C_SetAttributeValue: Some(nyi::C_SetAttributeValue), C_FindObjectsInit: Some(api::object::C_FindObjectsInit), C_FindObjects: Some(api::object::C_FindObjects), C_FindObjectsFinal: Some(api::object::C_FindObjectsFinal), C_EncryptInit: Some(api::encrypt::C_EncryptInit), C_Encrypt: Some(api::encrypt::C_Encrypt), C_EncryptUpdate: Some(nyi::C_EncryptUpdate), C_EncryptFinal: Some(nyi::C_EncryptFinal), C_DecryptInit: Some(api::decrypt::C_DecryptInit), C_Decrypt: Some(api::decrypt::C_Decrypt), C_DecryptUpdate: Some(nyi::C_DecryptUpdate), C_DecryptFinal: Some(nyi::C_DecryptFinal), C_DigestInit: Some(api::digest::C_DigestInit), C_Digest: Some(api::digest::C_Digest), C_DigestUpdate: Some(api::digest::C_DigestUpdate), C_DigestKey: Some(nyi::C_DigestKey), C_DigestFinal: Some(api::digest::C_DigestFinal), C_SignInit: Some(api::sign::C_SignInit), C_Sign: Some(api::sign::C_Sign), C_SignUpdate: Some(api::sign::C_SignUpdate), C_SignFinal: Some(api::sign::C_SignFinal), C_SignRecoverInit: Some(nyi::C_SignRecoverInit), C_SignRecover: Some(nyi::C_SignRecover), C_VerifyInit: Some(api::verify::C_VerifyInit), C_Verify: Some(api::verify::C_Verify), C_VerifyUpdate: Some(api::verify::C_VerifyUpdate), C_VerifyFinal: Some(api::verify::C_VerifyFinal), C_VerifyRecoverInit: Some(nyi::C_VerifyRecoverInit), C_VerifyRecover: Some(nyi::C_VerifyRecover), C_DigestEncryptUpdate: Some(nyi::C_DigestEncryptUpdate), C_DecryptDigestUpdate: Some(nyi::C_DecryptDigestUpdate), C_SignEncryptUpdate: Some(nyi::C_SignEncryptUpdate), C_DecryptVerifyUpdate: Some(nyi::C_DecryptVerifyUpdate), C_GenerateKey: Some(nyi::C_GenerateKey), C_GenerateKeyPair: Some(nyi::C_GenerateKeyPair), C_WrapKey: Some(nyi::C_WrapKey), C_UnwrapKey: Some(nyi::C_UnwrapKey), C_DeriveKey: Some(nyi::C_DeriveKey), C_SeedRandom: Some(nyi::C_SeedRandom), C_GenerateRandom: Some(nyi::C_GenerateRandom), C_GetFunctionStatus: Some(api::session::C_GetFunctionStatus), C_CancelFunction: Some(api::session::C_CancelFunction), C_WaitForSlotEvent: Some(nyi::C_WaitForSlotEvent), }; lazy_static! { pub static ref DEVICE: Arc<Mutex<Option<Device>>> = Arc::new(Mutex::new(None)); } } #[derive(Clone, Copy, Debug)] pub enum Error { CkError(pkcs11::CK_RV), CryptoError(crypto::Error), KeyHandleInvalid, KeyTypeInconsistent, MechanismInvalid, OperationNotInitialized, SessionHandleInvalid, SessionLockPoisoned, SlotIdInvalid, UserNotLoggedIn, TokenError(TokenError), TokenNotPresent, TokenUninit, // TODO: implement proper error reporting GeneralError, } impl Error { pub fn ck_rv(&self) -> pkcs11::CK_RV { match self { Self::CkError(code) => *code, Self::CryptoError(CryptoError::DataMissing) => pkcs11::CKR_DATA_LEN_RANGE, Self::CryptoError(CryptoError::OperationActive) => pkcs11::CKR_OPERATION_ACTIVE, Self::CryptoError(CryptoError::DigestVerifyFinal) => pkcs11::CKR_SIGNATURE_INVALID, Self::CryptoError(CryptoError::DigestVerify) => pkcs11::CKR_SIGNATURE_INVALID, Self::CryptoError(CryptoError::DirectVerify) => pkcs11::CKR_SIGNATURE_INVALID, Self::KeyHandleInvalid => pkcs11::CKR_KEY_HANDLE_INVALID, Self::KeyTypeInconsistent => pkcs11::CKR_KEY_TYPE_INCONSISTENT, Self::MechanismInvalid => pkcs11::CKR_MECHANISM_INVALID, Self::OperationNotInitialized => pkcs11::CKR_OPERATION_NOT_INITIALIZED, Self::SessionHandleInvalid => pkcs11::CKR_SESSION_HANDLE_INVALID, Self::SlotIdInvalid => pkcs11::CKR_SLOT_ID_INVALID, Self::UserNotLoggedIn => pkcs11::CKR_USER_NOT_LOGGED_IN, Self::TokenNotPresent => pkcs11::CKR_TOKEN_NOT_PRESENT, Self::TokenError(TokenError::SessionCount) => pkcs11::CKR_SESSION_COUNT, Self::TokenError(TokenError::SessionHandleInvalid) => { pkcs11::CKR_SESSION_HANDLE_INVALID } Self::TokenError(TokenError::UserAlreadyLoggedIn) => pkcs11::CKR_USER_ALREADY_LOGGED_IN, Self::TokenError(TokenError::UserNotLoggedIn) => pkcs11::CKR_USER_NOT_LOGGED_IN, Self::TokenError(TokenError::MechNotFound) => pkcs11::CKR_MECHANISM_INVALID, Self::TokenError(TokenError::PinIncorrect) => pkcs11::CKR_PIN_INCORRECT, _ => pkcs11::CKR_GENERAL_ERROR, } } } impl From<Error> for pkcs11::CK_RV { fn from(src: Error) -> pkcs11::CK_RV { src.ck_rv() } } pub type Result<T> = std::result::Result<T, Error>;