diff --git a/README.md b/README.md index 68f33e9..2a69f60 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,8 @@ The `cryptoki` crate provides an idiomatic interface to the PKCS #11 API. The `cryptoki-sys` crate provides the direct FFI bindings. +Check the `cryptoki` [README file](cryptoki/README.md) to get started! + # Community Come and ask questions or talk with the Parsec Community in our Slack channel or biweekly meetings. diff --git a/cryptoki/README.md b/cryptoki/README.md index 76c0bcc..0e1c136 100644 --- a/cryptoki/README.md +++ b/cryptoki/README.md @@ -11,9 +11,26 @@ The items in this crate only expose idiomatic and safe Rust types and functions to interface with the PKCS11 API. All the PKCS11 items might not be implemented but everything that is implemented is safe. +## Prerequisites + +In order to use this crate you will need to have access to a PKCS11 dynamic library to load, to use your HSM. +To develop locally on this crate and in the CI we use [SoftHSM version 2](https://github.com/softhsm/SoftHSMv2). You can also use that if you want to run the example below. + +You can follow the installation steps directly in the repository's README but here are instructions proven to work on Ubuntu 24.01: + +```bash +sudo apt install libsofthsm2 +mkdir /tmp/tokens +echo "directories.tokendir = /tmp/tokens" > /tmp/softhsm2.conf +export PKCS11_SOFTHSM2_MODULE="/usr/lib/softhsm/libsofthsm2.so" +export SOFTHSM2_CONF="/tmp/softhsm2.conf" +cargo run --example generate_key_pair +``` + ## Example The following example initializes an empty token and generates a new RSA key. +You can find it in the `examples` folder and run it with `cargo run --example generate_key_pair`. ```rust # fn main() -> testresult::TestResult { @@ -22,9 +39,13 @@ use cryptoki::context::{CInitializeArgs, Pkcs11}; use cryptoki::session::UserType; use cryptoki::types::AuthPin; use cryptoki::mechanism::Mechanism; +use std::env; // initialize a new Pkcs11 object using the module from the env variable -let pkcs11 = Pkcs11::new(std::env::var("PKCS11_SOFTHSM2_MODULE")?)?; +let pkcs11 = Pkcs11::new( + env::var("PKCS11_SOFTHSM2_MODULE") + .unwrap_or_else(|_| "/usr/local/lib/softhsm/libsofthsm2.so".to_string()), +)?; pkcs11.initialize(CInitializeArgs::OsThreads)?; @@ -62,6 +83,10 @@ let (public, private) = session.generate_key_pair(&Mechanism::RsaPkcsKeyPairGen, # Ok(()) } ``` +## See also + +* Session Pool Management based on `r2d2`: + ## Conformance Notes Throughout this crate, many functions and other items include additional diff --git a/cryptoki/examples/generate_key_pair.rs b/cryptoki/examples/generate_key_pair.rs new file mode 100644 index 0000000..6c0b785 --- /dev/null +++ b/cryptoki/examples/generate_key_pair.rs @@ -0,0 +1,60 @@ +// Copyright 2024 Contributors to the Parsec project. +// SPDX-License-Identifier: Apache-2.0 +use cryptoki::context::{CInitializeArgs, Pkcs11}; +use cryptoki::mechanism::Mechanism; +use cryptoki::object::Attribute; +use cryptoki::session::UserType; +use cryptoki::types::AuthPin; +use std::env; + +// The default user pin +pub static USER_PIN: &str = "fedcba"; +// The default SO pin +pub static SO_PIN: &str = "abcdef"; + +fn main() -> testresult::TestResult { + // initialize a new Pkcs11 object using the module from the env variable + let pkcs11 = Pkcs11::new( + env::var("PKCS11_SOFTHSM2_MODULE") + .unwrap_or_else(|_| "/usr/local/lib/softhsm/libsofthsm2.so".to_string()), + )?; + + pkcs11.initialize(CInitializeArgs::OsThreads)?; + + let slot = pkcs11.get_slots_with_token()?[0]; + + // initialize a test token + let so_pin = AuthPin::new("abcdef".into()); + pkcs11.init_token(slot, &so_pin, "Test Token")?; + + let user_pin = AuthPin::new("fedcba".into()); + + // initialize user PIN + { + let session = pkcs11.open_rw_session(slot)?; + session.login(UserType::So, Some(&so_pin))?; + session.init_pin(&user_pin)?; + } + + // login as a user, the token has to be already initialized + let session = pkcs11.open_rw_session(slot)?; + session.login(UserType::User, Some(&user_pin))?; + + // template of the public key + let pub_key_template = vec![ + Attribute::Token(true), + Attribute::Private(false), + Attribute::PublicExponent(vec![0x01, 0x00, 0x01]), + Attribute::ModulusBits(1024.into()), + ]; + + let priv_key_template = vec![Attribute::Token(true)]; + + // generate an RSA key according to passed templates + let (_public, _private) = session.generate_key_pair( + &Mechanism::RsaPkcsKeyPairGen, + &pub_key_template, + &priv_key_template, + )?; + Ok(()) +}