Skip to content
This repository has been archived by the owner on Sep 4, 2024. It is now read-only.

Utilize a pin code for Windows Hello #48

Merged
merged 2 commits into from
Apr 11, 2024
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 .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ Cargo.lock
# MSVC Windows builds of rustc generate these, which store debugging information
*.pdb

tags

# Added by cargo

Expand Down
4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]
name = "msal"
description = "Microsoft Authentication Library for Rust"
version = "0.1.15"
version = "0.1.16"
edition = "2021"
authors = [
"David Mulder <dmulder@suse.com>"
Expand Down Expand Up @@ -30,7 +30,7 @@ uuid = { version = "^1.4.1", features = [ "v4", "serde" ] }
os-release = "^0.1.0"
hostname = "^0.3.1"
openssl = "^0.10.55"
compact_jwt = { version = "0.3.5", optional = true }
compact_jwt = { version = "0.4.0-dev", optional = true }
kanidm-hsm-crypto = { version = "^0.2.0", optional = true }
regex = "^1.10.3"
zeroize = { version = "^1.7.0", features = ["zeroize_derive"] }
Expand Down
70 changes: 49 additions & 21 deletions src/auth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ use compact_jwt::traits::JwsSignable;
use compact_jwt::Jws;
#[cfg(feature = "broker")]
use kanidm_hsm_crypto::{
BoxedDynTpm, IdentityKey, KeyAlgorithm, LoadableIdentityKey, MachineKey, SealedData, Tpm,
BoxedDynTpm, IdentityKey, KeyAlgorithm, LoadableIdentityKey, MachineKey, PinValue, SealedData,
Tpm,
};
#[cfg(feature = "broker")]
use kanidm_hsm_crypto::{LoadableMsOapxbcRsaKey, MsOapxbcRsaKey};
Expand Down Expand Up @@ -1904,7 +1905,7 @@ impl BrokerClientApplication {
) -> Result<IdentityKey, MsalError> {
match &self.cert_key {
Some(cert_key) => {
let cert_key = tpm.identity_key_load(machine_key, cert_key)
let cert_key = tpm.identity_key_load(machine_key, None, cert_key)
.map_err(|e| {
MsalError::TPMFail(format!("Failed to load IdentityKey: {:?}", e))
})?;
Expand Down Expand Up @@ -1956,7 +1957,7 @@ impl BrokerClientApplication {
.await?;
// Create the transport and cert keys
let loadable_cert_key = tpm
.identity_key_create(machine_key, KeyAlgorithm::Rsa2048)
.identity_key_create(machine_key, None, KeyAlgorithm::Rsa2048)
.map_err(|e| MsalError::TPMFail(format!("Failed creating certificate key: {:?}", e)))?;
let loadable_transport_key = tpm
.msoapxbc_rsa_key_create(machine_key)
Expand All @@ -1966,6 +1967,7 @@ impl BrokerClientApplication {
// Create the CSR
let csr_der = match tpm.identity_key_certificate_request(
machine_key,
None,
&loadable_cert_key,
"7E980AD9-B86D-4306-9425-9AC066FB014A",
) {
Expand Down Expand Up @@ -2009,6 +2011,7 @@ impl BrokerClientApplication {

let new_loadable_cert_key = match tpm.identity_key_associate_certificate(
machine_key,
None,
&loadable_cert_key,
&cert
.to_der()
Expand Down Expand Up @@ -2801,24 +2804,26 @@ impl BrokerClientApplication {
/// acquire_token_by_username_password_for_device_enrollment
/// or acquire_token_by_device_flow.
///
/// * `key` - An optional existing LoadableIdentityKey, if not provided
/// one will be created.
///
/// * `tpm` - The tpm object.
///
/// * `machine_key` - The TPM MachineKey associated with this application.
///
/// * `pin` - The PIN code which will be used to unlock the key.
///
/// # Returns
/// * Success: Either the existing LoadableIdentityKey, or a new created
/// key if none was provided.
/// * Failure: An MsalError, indicating the failure.
pub async fn provision_hello_for_business_key(
&self,
token: &UserToken,
key: Option<LoadableIdentityKey>,
tpm: &mut BoxedDynTpm,
machine_key: &MachineKey,
pin: &str,
) -> Result<LoadableIdentityKey, MsalError> {
let pin = PinValue::new(pin)
.map_err(|e| MsalError::TPMFail(format!("Failed setting pin value: {:?}", e)))?;

// Discover the KeyProvisioningService
let access_token = match &token.access_token {
Some(access_token) => access_token.clone(),
Expand Down Expand Up @@ -2864,17 +2869,14 @@ impl BrokerClientApplication {
)
.await?;

// Use an existing key, or create a new hello key (using the TPM)
let loadable_win_hello_key = match key {
Some(loadable_win_hello_key) => loadable_win_hello_key,
None => tpm
.identity_key_create(machine_key, KeyAlgorithm::Rsa2048)
.map_err(|e| {
MsalError::TPMFail(format!("Failed creating Windows Hello Key: {:?}", e))
})?,
};
// Create a new hello key (using the TPM)
let loadable_win_hello_key = tpm
.identity_key_create(machine_key, Some(&pin), KeyAlgorithm::Rsa2048)
.map_err(|e| {
MsalError::TPMFail(format!("Failed creating Windows Hello Key: {:?}", e))
})?;
let win_hello_key = tpm
.identity_key_load(machine_key, &loadable_win_hello_key)
.identity_key_load(machine_key, Some(&pin), &loadable_win_hello_key)
.map_err(|e| {
MsalError::TPMFail(format!("Failed loading Windows Hello Key: {:?}", e))
})?;
Expand Down Expand Up @@ -2946,6 +2948,8 @@ impl BrokerClientApplication {
///
/// * `machine_key` - The TPM MachineKey associated with this application.
///
/// * `pin` - The PIN code required to unlock the key.
///
/// # Returns
/// * Success: A UserToken containing an access_token.
/// * Failure: An MsalError, indicating the failure.
Expand All @@ -2956,9 +2960,19 @@ impl BrokerClientApplication {
scopes: Vec<&str>,
tpm: &mut BoxedDynTpm,
machine_key: &MachineKey,
pin: &str,
) -> Result<UserToken, MsalError> {
let pin = PinValue::new(pin)
.map_err(|e| MsalError::TPMFail(format!("Failed setting pin value: {:?}", e)))?;

let prt = self
.acquire_user_prt_by_hello_for_business_key_internal(username, key, tpm, machine_key)
.acquire_user_prt_by_hello_for_business_key_internal(
username,
key,
tpm,
machine_key,
&pin,
)
.await?;
let transport_key = self.transport_key(tpm, machine_key)?;
let session_key = prt.session_key()?;
Expand All @@ -2984,10 +2998,11 @@ impl BrokerClientApplication {
loadable_key: &LoadableIdentityKey,
tpm: &mut BoxedDynTpm,
machine_key: &MachineKey,
pin: &PinValue,
) -> Result<Jws, MsalError> {
let nonce = self.request_nonce().await?;
let key = tpm
.identity_key_load(machine_key, loadable_key)
.identity_key_load(machine_key, Some(pin), loadable_key)
.map_err(|e| MsalError::TPMFail(format!("{:?}", e)))?;
let win_hello_pub_der = tpm.identity_key_public_as_der(&key).map_err(|e| {
MsalError::TPMFail(format!("Failed getting Windows Hello Key as der: {:?}", e))
Expand Down Expand Up @@ -3056,9 +3071,10 @@ impl BrokerClientApplication {
key: &LoadableIdentityKey,
tpm: &mut BoxedDynTpm,
machine_key: &MachineKey,
pin: &PinValue,
) -> Result<PrimaryRefreshToken, MsalError> {
let jwt = self
.build_jwt_by_hello_for_business_key(username, key, tpm, machine_key)
.build_jwt_by_hello_for_business_key(username, key, tpm, machine_key, pin)
.await?;
let signed_jwt = self.sign_jwt(&jwt, tpm, machine_key).await?;

Expand All @@ -3078,6 +3094,8 @@ impl BrokerClientApplication {
///
/// * `machine_key` - The TPM MachineKey associated with this application.
///
/// * `pin` - The PIN code required to unlock the key.
///
/// # Returns
/// * Success: An encrypted PrimaryRefreshToken, containing a refresh_token and tgt.
/// * Failure: An MsalError, indicating the failure.
Expand All @@ -3087,9 +3105,19 @@ impl BrokerClientApplication {
key: &LoadableIdentityKey,
tpm: &mut BoxedDynTpm,
machine_key: &MachineKey,
pin: &str,
) -> Result<SealedData, MsalError> {
let pin = PinValue::new(pin)
.map_err(|e| MsalError::TPMFail(format!("Failed setting pin value: {:?}", e)))?;

let prt = self
.acquire_user_prt_by_hello_for_business_key_internal(username, key, tpm, machine_key)
.acquire_user_prt_by_hello_for_business_key_internal(
username,
key,
tpm,
machine_key,
&pin,
)
.await?;
let transport_key = self.transport_key(tpm, machine_key)?;
self.seal_user_prt(&prt, tpm, &transport_key)
Expand Down