Always insert attestation material in the store
This commit is contained in:
@@ -12,10 +12,13 @@
|
|||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
pub const AAGUID: &[u8; 16] = include_bytes!(concat!(env!("OUT_DIR"), "/opensk_aaguid.bin"));
|
pub const ATTESTATION_PRIVATE_KEY_LENGTH: usize = 32;
|
||||||
|
pub const AAGUID_LENGTH: usize = 16;
|
||||||
|
|
||||||
|
pub const AAGUID: &[u8; AAGUID_LENGTH] = include_bytes!(concat!(env!("OUT_DIR"), "/opensk_aaguid.bin"));
|
||||||
|
|
||||||
pub const ATTESTATION_CERTIFICATE: &[u8] =
|
pub const ATTESTATION_CERTIFICATE: &[u8] =
|
||||||
include_bytes!(concat!(env!("OUT_DIR"), "/opensk_cert.bin"));
|
include_bytes!(concat!(env!("OUT_DIR"), "/opensk_cert.bin"));
|
||||||
|
|
||||||
pub const ATTESTATION_PRIVATE_KEY: &[u8; 32] =
|
pub const ATTESTATION_PRIVATE_KEY: &[u8; ATTESTATION_PRIVATE_KEY_LENGTH] =
|
||||||
include_bytes!(concat!(env!("OUT_DIR"), "/opensk_pkey.bin"));
|
include_bytes!(concat!(env!("OUT_DIR"), "/opensk_pkey.bin"));
|
||||||
|
|||||||
@@ -15,9 +15,9 @@
|
|||||||
#[cfg(feature = "with_ctap2_1")]
|
#[cfg(feature = "with_ctap2_1")]
|
||||||
use crate::ctap::data_formats::{extract_array, extract_text_string};
|
use crate::ctap::data_formats::{extract_array, extract_text_string};
|
||||||
use crate::ctap::data_formats::{CredentialProtectionPolicy, PublicKeyCredentialSource};
|
use crate::ctap::data_formats::{CredentialProtectionPolicy, PublicKeyCredentialSource};
|
||||||
|
use crate::ctap::key_material;
|
||||||
use crate::ctap::pin_protocol_v1::PIN_AUTH_LENGTH;
|
use crate::ctap::pin_protocol_v1::PIN_AUTH_LENGTH;
|
||||||
use crate::ctap::status_code::Ctap2StatusCode;
|
use crate::ctap::status_code::Ctap2StatusCode;
|
||||||
use crate::ctap::{key_material, USE_BATCH_ATTESTATION};
|
|
||||||
use crate::embedded_flash::{self, StoreConfig, StoreEntry, StoreError};
|
use crate::embedded_flash::{self, StoreConfig, StoreEntry, StoreError};
|
||||||
use alloc::string::String;
|
use alloc::string::String;
|
||||||
#[cfg(any(test, feature = "ram_storage", feature = "with_ctap2_1"))]
|
#[cfg(any(test, feature = "ram_storage", feature = "with_ctap2_1"))]
|
||||||
@@ -76,8 +76,6 @@ const MIN_PIN_LENGTH_RP_IDS: usize = 9;
|
|||||||
const NUM_TAGS: usize = 10;
|
const NUM_TAGS: usize = 10;
|
||||||
|
|
||||||
const MAX_PIN_RETRIES: u8 = 8;
|
const MAX_PIN_RETRIES: u8 = 8;
|
||||||
const ATTESTATION_PRIVATE_KEY_LENGTH: usize = 32;
|
|
||||||
const AAGUID_LENGTH: usize = 16;
|
|
||||||
#[cfg(feature = "with_ctap2_1")]
|
#[cfg(feature = "with_ctap2_1")]
|
||||||
const DEFAULT_MIN_PIN_LENGTH: u8 = 4;
|
const DEFAULT_MIN_PIN_LENGTH: u8 = 4;
|
||||||
// TODO(kaczmarczyck) use this for the minPinLength extension
|
// TODO(kaczmarczyck) use this for the minPinLength extension
|
||||||
@@ -231,8 +229,7 @@ impl PersistentStore {
|
|||||||
})
|
})
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
// The following 3 entries are meant to be written by vendor-specific commands.
|
// The following 2 entries are meant to be written by vendor-specific commands.
|
||||||
if USE_BATCH_ATTESTATION {
|
|
||||||
if self.store.find_one(&Key::AttestationPrivateKey).is_none() {
|
if self.store.find_one(&Key::AttestationPrivateKey).is_none() {
|
||||||
self.set_attestation_private_key(key_material::ATTESTATION_PRIVATE_KEY)
|
self.set_attestation_private_key(key_material::ATTESTATION_PRIVATE_KEY)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
@@ -241,7 +238,7 @@ impl PersistentStore {
|
|||||||
self.set_attestation_certificate(key_material::ATTESTATION_CERTIFICATE)
|
self.set_attestation_certificate(key_material::ATTESTATION_CERTIFICATE)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if self.store.find_one(&Key::Aaguid).is_none() {
|
if self.store.find_one(&Key::Aaguid).is_none() {
|
||||||
self.set_aaguid(key_material::AAGUID).unwrap();
|
self.set_aaguid(key_material::AAGUID).unwrap();
|
||||||
}
|
}
|
||||||
@@ -525,20 +522,24 @@ impl PersistentStore {
|
|||||||
|
|
||||||
pub fn attestation_private_key(
|
pub fn attestation_private_key(
|
||||||
&self,
|
&self,
|
||||||
) -> Result<Option<&[u8; ATTESTATION_PRIVATE_KEY_LENGTH]>, Ctap2StatusCode> {
|
) -> Result<Option<&[u8; key_material::ATTESTATION_PRIVATE_KEY_LENGTH]>, Ctap2StatusCode> {
|
||||||
let data = match self.store.find_one(&Key::AttestationPrivateKey) {
|
let data = match self.store.find_one(&Key::AttestationPrivateKey) {
|
||||||
None => return Ok(None),
|
None => return Ok(None),
|
||||||
Some((_, entry)) => entry.data,
|
Some((_, entry)) => entry.data,
|
||||||
};
|
};
|
||||||
if data.len() != ATTESTATION_PRIVATE_KEY_LENGTH {
|
if data.len() != key_material::ATTESTATION_PRIVATE_KEY_LENGTH {
|
||||||
return Err(Ctap2StatusCode::CTAP2_ERR_VENDOR_INTERNAL_ERROR);
|
return Err(Ctap2StatusCode::CTAP2_ERR_VENDOR_INTERNAL_ERROR);
|
||||||
}
|
}
|
||||||
Ok(Some(array_ref!(data, 0, ATTESTATION_PRIVATE_KEY_LENGTH)))
|
Ok(Some(array_ref!(
|
||||||
|
data,
|
||||||
|
0,
|
||||||
|
key_material::ATTESTATION_PRIVATE_KEY_LENGTH
|
||||||
|
)))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_attestation_private_key(
|
pub fn set_attestation_private_key(
|
||||||
&mut self,
|
&mut self,
|
||||||
attestation_private_key: &[u8; ATTESTATION_PRIVATE_KEY_LENGTH],
|
attestation_private_key: &[u8; key_material::ATTESTATION_PRIVATE_KEY_LENGTH],
|
||||||
) -> Result<(), Ctap2StatusCode> {
|
) -> Result<(), Ctap2StatusCode> {
|
||||||
let entry = StoreEntry {
|
let entry = StoreEntry {
|
||||||
tag: ATTESTATION_PRIVATE_KEY,
|
tag: ATTESTATION_PRIVATE_KEY,
|
||||||
@@ -576,19 +577,22 @@ impl PersistentStore {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn aaguid(&self) -> Result<[u8; AAGUID_LENGTH], Ctap2StatusCode> {
|
pub fn aaguid(&self) -> Result<[u8; key_material::AAGUID_LENGTH], Ctap2StatusCode> {
|
||||||
let (_, entry) = self
|
let (_, entry) = self
|
||||||
.store
|
.store
|
||||||
.find_one(&Key::Aaguid)
|
.find_one(&Key::Aaguid)
|
||||||
.ok_or(Ctap2StatusCode::CTAP2_ERR_VENDOR_INTERNAL_ERROR)?;
|
.ok_or(Ctap2StatusCode::CTAP2_ERR_VENDOR_INTERNAL_ERROR)?;
|
||||||
let data = entry.data;
|
let data = entry.data;
|
||||||
if data.len() != AAGUID_LENGTH {
|
if data.len() != key_material::AAGUID_LENGTH {
|
||||||
return Err(Ctap2StatusCode::CTAP2_ERR_VENDOR_INTERNAL_ERROR);
|
return Err(Ctap2StatusCode::CTAP2_ERR_VENDOR_INTERNAL_ERROR);
|
||||||
}
|
}
|
||||||
Ok(*array_ref![data, 0, AAGUID_LENGTH])
|
Ok(*array_ref![data, 0, key_material::AAGUID_LENGTH])
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_aaguid(&mut self, aaguid: &[u8; AAGUID_LENGTH]) -> Result<(), Ctap2StatusCode> {
|
pub fn set_aaguid(
|
||||||
|
&mut self,
|
||||||
|
aaguid: &[u8; key_material::AAGUID_LENGTH],
|
||||||
|
) -> Result<(), Ctap2StatusCode> {
|
||||||
let entry = StoreEntry {
|
let entry = StoreEntry {
|
||||||
tag: AAGUID,
|
tag: AAGUID,
|
||||||
data: aaguid,
|
data: aaguid,
|
||||||
@@ -996,23 +1000,6 @@ mod test {
|
|||||||
let mut rng = ThreadRng256 {};
|
let mut rng = ThreadRng256 {};
|
||||||
let mut persistent_store = PersistentStore::new(&mut rng);
|
let mut persistent_store = PersistentStore::new(&mut rng);
|
||||||
|
|
||||||
// Make sure the attestation are absent. There is no batch attestation in tests.
|
|
||||||
assert!(persistent_store
|
|
||||||
.attestation_private_key()
|
|
||||||
.unwrap()
|
|
||||||
.is_none());
|
|
||||||
assert!(persistent_store
|
|
||||||
.attestation_certificate()
|
|
||||||
.unwrap()
|
|
||||||
.is_none());
|
|
||||||
|
|
||||||
// Make sure the persistent keys are initialized.
|
|
||||||
persistent_store
|
|
||||||
.set_attestation_private_key(key_material::ATTESTATION_PRIVATE_KEY)
|
|
||||||
.unwrap();
|
|
||||||
persistent_store
|
|
||||||
.set_attestation_certificate(key_material::ATTESTATION_CERTIFICATE)
|
|
||||||
.unwrap();
|
|
||||||
assert_eq!(&persistent_store.aaguid().unwrap(), key_material::AAGUID);
|
assert_eq!(&persistent_store.aaguid().unwrap(), key_material::AAGUID);
|
||||||
|
|
||||||
// The persistent keys stay initialized and preserve their value after a reset.
|
// The persistent keys stay initialized and preserve their value after a reset.
|
||||||
|
|||||||
Reference in New Issue
Block a user