|
@@ -1,3 +1,5 @@
|
|
|
|
+use crate::error::{DisplayErr, StringError};
|
|
|
|
+
|
|
use super::*;
|
|
use super::*;
|
|
|
|
|
|
use btserde::read_from;
|
|
use btserde::read_from;
|
|
@@ -50,23 +52,17 @@ use zeroize::Zeroizing;
|
|
impl From<tss_esapi::Error> for Error {
|
|
impl From<tss_esapi::Error> for Error {
|
|
fn from(err: tss_esapi::Error) -> Self {
|
|
fn from(err: tss_esapi::Error) -> Self {
|
|
match err {
|
|
match err {
|
|
- tss_esapi::Error::WrapperError(err) => Error::custom(err),
|
|
|
|
|
|
+ tss_esapi::Error::WrapperError(err) => Error::library(err),
|
|
tss_esapi::Error::Tss2Error(err) => {
|
|
tss_esapi::Error::Tss2Error(err) => {
|
|
let rc = err.tss2_rc();
|
|
let rc = err.tss2_rc();
|
|
let text = tss2_rc_decode(err);
|
|
let text = tss2_rc_decode(err);
|
|
let string = format!("response code: {rc}, response text: {text}");
|
|
let string = format!("response code: {rc}, response text: {text}");
|
|
- Error::custom(string)
|
|
|
|
|
|
+ Error::library(StringError::new(string))
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
-impl<Guard> From<std::sync::PoisonError<Guard>> for Error {
|
|
|
|
- fn from(error: std::sync::PoisonError<Guard>) -> Self {
|
|
|
|
- Error::custom(error.to_string())
|
|
|
|
- }
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
/// Trait which extends the `tss_esapi::Context`.
|
|
/// Trait which extends the `tss_esapi::Context`.
|
|
trait ContextExt {
|
|
trait ContextExt {
|
|
fn persistent_handles(&mut self) -> Result<Vec<PersistentTpmHandle>>;
|
|
fn persistent_handles(&mut self) -> Result<Vec<PersistentTpmHandle>>;
|
|
@@ -123,10 +119,10 @@ impl ContextExt for Context {
|
|
let list = match handles {
|
|
let list = match handles {
|
|
CapabilityData::Handles(list) => list.into_inner(),
|
|
CapabilityData::Handles(list) => list.into_inner(),
|
|
_ => {
|
|
_ => {
|
|
- return Err(Error::custom(format!(
|
|
|
|
|
|
+ return Err(bterr!(
|
|
"Unexpected capability type returned by TPM: {:?}",
|
|
"Unexpected capability type returned by TPM: {:?}",
|
|
handles
|
|
handles
|
|
- )))
|
|
|
|
|
|
+ ))
|
|
}
|
|
}
|
|
};
|
|
};
|
|
all_handles.reserve(list.len());
|
|
all_handles.reserve(list.len());
|
|
@@ -138,7 +134,7 @@ impl ContextExt for Context {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if more {
|
|
if more {
|
|
- return Err(Error::custom(
|
|
|
|
|
|
+ return Err(bterr!(
|
|
"hit iteration limit before retrieving all persistent handles from the TPM",
|
|
"hit iteration limit before retrieving all persistent handles from the TPM",
|
|
));
|
|
));
|
|
}
|
|
}
|
|
@@ -175,7 +171,7 @@ impl ContextExt for Context {
|
|
}
|
|
}
|
|
match unused {
|
|
match unused {
|
|
Some(unused) => Ok(Persistent::Persistent(unused)),
|
|
Some(unused) => Ok(Persistent::Persistent(unused)),
|
|
- None => Err(Error::custom("failed to find an unused persistent handle")),
|
|
|
|
|
|
+ None => Err(bterr!("failed to find an unused persistent handle")),
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -204,7 +200,7 @@ impl ContextExt for Context {
|
|
}
|
|
}
|
|
match persistent {
|
|
match persistent {
|
|
Some(Persistent::Persistent(inner)) => Ok(inner.into()),
|
|
Some(Persistent::Persistent(inner)) => Ok(inner.into()),
|
|
- None => Err(Error::custom("retry limit reached")),
|
|
|
|
|
|
+ None => Err(bterr!("retry limit reached")),
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -238,7 +234,7 @@ impl ContextExt for Context {
|
|
SymmetricDefinition::AES_256_CFB,
|
|
SymmetricDefinition::AES_256_CFB,
|
|
HashingAlgorithm::Sha256,
|
|
HashingAlgorithm::Sha256,
|
|
)?
|
|
)?
|
|
- .ok_or_else(|| Error::custom("empty session handle received from TPM"))?;
|
|
|
|
|
|
+ .ok_or_else(|| bterr!("empty session handle received from TPM"))?;
|
|
self.set_encrypt_decrypt(session)?;
|
|
self.set_encrypt_decrypt(session)?;
|
|
Ok(session)
|
|
Ok(session)
|
|
}
|
|
}
|
|
@@ -253,7 +249,7 @@ impl ContextExt for Context {
|
|
SymmetricDefinition::AES_256_CFB,
|
|
SymmetricDefinition::AES_256_CFB,
|
|
HashingAlgorithm::Sha256,
|
|
HashingAlgorithm::Sha256,
|
|
)?
|
|
)?
|
|
- .ok_or_else(|| Error::custom("empty session handle received from TPM"))?;
|
|
|
|
|
|
+ .ok_or_else(|| bterr!("empty session handle received from TPM"))?;
|
|
self.set_encrypt_decrypt(session)?;
|
|
self.set_encrypt_decrypt(session)?;
|
|
Ok(session.try_into()?)
|
|
Ok(session.try_into()?)
|
|
}
|
|
}
|
|
@@ -595,7 +591,8 @@ impl From<HashKind> for HashingAlgorithm {
|
|
}
|
|
}
|
|
|
|
|
|
impl TryInto<RsaScheme> for SchemeKind {
|
|
impl TryInto<RsaScheme> for SchemeKind {
|
|
- type Error = Error;
|
|
|
|
|
|
+ type Error = crate::Error;
|
|
|
|
+
|
|
fn try_into(self) -> Result<RsaScheme> {
|
|
fn try_into(self) -> Result<RsaScheme> {
|
|
match self {
|
|
match self {
|
|
SchemeKind::Sign(sign) => match sign {
|
|
SchemeKind::Sign(sign) => match sign {
|
|
@@ -613,14 +610,14 @@ impl TryInto<RsaScheme> for SchemeKind {
|
|
}
|
|
}
|
|
|
|
|
|
impl TryFrom<KeyLen> for RsaKeyBits {
|
|
impl TryFrom<KeyLen> for RsaKeyBits {
|
|
- type Error = Error;
|
|
|
|
|
|
+ type Error = crate::Error;
|
|
|
|
|
|
fn try_from(len: KeyLen) -> Result<RsaKeyBits> {
|
|
fn try_from(len: KeyLen) -> Result<RsaKeyBits> {
|
|
match len {
|
|
match len {
|
|
KeyLen::Bits2048 => Ok(RsaKeyBits::Rsa2048),
|
|
KeyLen::Bits2048 => Ok(RsaKeyBits::Rsa2048),
|
|
KeyLen::Bits3072 => Ok(RsaKeyBits::Rsa3072),
|
|
KeyLen::Bits3072 => Ok(RsaKeyBits::Rsa3072),
|
|
KeyLen::Bits4096 => Ok(RsaKeyBits::Rsa4096),
|
|
KeyLen::Bits4096 => Ok(RsaKeyBits::Rsa4096),
|
|
- _ => Err(Error::custom(format!("unsupported key len: {len}"))),
|
|
|
|
|
|
+ _ => Err(bterr!("unsupported key len: {len}")),
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -863,7 +860,7 @@ impl TpmCredStore {
|
|
let cookie = storage.cookie.clone();
|
|
let cookie = storage.cookie.clone();
|
|
let state = Arc::new(RwLock::new(State::new(context, storage)?));
|
|
let state = Arc::new(RwLock::new(State::new(context, storage)?));
|
|
{
|
|
{
|
|
- let mut guard = state.write()?;
|
|
|
|
|
|
+ let mut guard = state.write().display_err()?;
|
|
guard.init_node_creds(&state)?;
|
|
guard.init_node_creds(&state)?;
|
|
}
|
|
}
|
|
Ok(TpmCredStore {
|
|
Ok(TpmCredStore {
|
|
@@ -886,7 +883,7 @@ impl TpmCredStore {
|
|
creds: &TpmCreds,
|
|
creds: &TpmCreds,
|
|
update_storage: F,
|
|
update_storage: F,
|
|
) -> Result<()> {
|
|
) -> Result<()> {
|
|
- let mut guard = self.state.write()?;
|
|
|
|
|
|
+ let mut guard = self.state.write().display_err()?;
|
|
let sign_handle = guard.context.persist_key(creds.sign.private)?;
|
|
let sign_handle = guard.context.persist_key(creds.sign.private)?;
|
|
let enc_handle = match guard.context.persist_key(creds.enc.private) {
|
|
let enc_handle = match guard.context.persist_key(creds.enc.private) {
|
|
Ok(handle) => handle,
|
|
Ok(handle) => handle,
|
|
@@ -923,14 +920,14 @@ impl TpmCredStore {
|
|
|
|
|
|
fn get_or_init_storage_key(&self) -> Result<KeyPair<Encrypt>> {
|
|
fn get_or_init_storage_key(&self) -> Result<KeyPair<Encrypt>> {
|
|
{
|
|
{
|
|
- let guard = self.state.read()?;
|
|
|
|
|
|
+ let guard = self.state.read().display_err()?;
|
|
if let Some(storage_key) = &guard.storage_key {
|
|
if let Some(storage_key) = &guard.storage_key {
|
|
// We take this path if the storage key was generated and loaded.
|
|
// We take this path if the storage key was generated and loaded.
|
|
return Ok(storage_key.clone());
|
|
return Ok(storage_key.clone());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
{
|
|
{
|
|
- let mut guard = self.state.write()?;
|
|
|
|
|
|
+ let mut guard = self.state.write().display_err()?;
|
|
if let Some(storage_key) = guard.storage.storage_key.take() {
|
|
if let Some(storage_key) = guard.storage.storage_key.take() {
|
|
let result = KeyPair::from_stored(&mut guard.context, &storage_key);
|
|
let result = KeyPair::from_stored(&mut guard.context, &storage_key);
|
|
guard.storage.storage_key = Some(storage_key);
|
|
guard.storage.storage_key = Some(storage_key);
|
|
@@ -941,7 +938,7 @@ impl TpmCredStore {
|
|
let params = KeyBuilder::for_storage_key(Self::ENCRYPT_SCHEME, self.cookie.as_slice())
|
|
let params = KeyBuilder::for_storage_key(Self::ENCRYPT_SCHEME, self.cookie.as_slice())
|
|
.with_parent(Parent::Seed(Hierarchy::Owner))
|
|
.with_parent(Parent::Seed(Hierarchy::Owner))
|
|
.with_auth(self.cookie.auth());
|
|
.with_auth(self.cookie.auth());
|
|
- let mut guard = self.state.write()?;
|
|
|
|
|
|
+ let mut guard = self.state.write().display_err()?;
|
|
let storage_key = params.build(&mut guard.context)?;
|
|
let storage_key = params.build(&mut guard.context)?;
|
|
guard.storage_key = Some(storage_key.clone());
|
|
guard.storage_key = Some(storage_key.clone());
|
|
let tpm_handle = guard.context.persist_key(storage_key.private)?;
|
|
let tpm_handle = guard.context.persist_key(storage_key.private)?;
|
|
@@ -958,7 +955,7 @@ impl TpmCredStore {
|
|
}
|
|
}
|
|
|
|
|
|
fn gen_key<S: Scheme>(&self, params: KeyBuilder<S>) -> Result<KeyPair<S>> {
|
|
fn gen_key<S: Scheme>(&self, params: KeyBuilder<S>) -> Result<KeyPair<S>> {
|
|
- let mut guard = self.state.write()?;
|
|
|
|
|
|
+ let mut guard = self.state.write().display_err()?;
|
|
params.build(&mut guard.context)
|
|
params.build(&mut guard.context)
|
|
}
|
|
}
|
|
|
|
|
|
@@ -1062,7 +1059,7 @@ impl CredStore for TpmCredStore {
|
|
|
|
|
|
fn node_creds(&self) -> Result<TpmCreds> {
|
|
fn node_creds(&self) -> Result<TpmCreds> {
|
|
{
|
|
{
|
|
- let guard = self.state.read()?;
|
|
|
|
|
|
+ let guard = self.state.read().display_err()?;
|
|
if let Some(creds) = &guard.node_creds {
|
|
if let Some(creds) = &guard.node_creds {
|
|
return Ok(creds.clone());
|
|
return Ok(creds.clone());
|
|
}
|
|
}
|
|
@@ -1072,15 +1069,15 @@ impl CredStore for TpmCredStore {
|
|
|
|
|
|
fn root_creds(&self, password: &str) -> Result<Self::CredHandle> {
|
|
fn root_creds(&self, password: &str) -> Result<Self::CredHandle> {
|
|
let root_handles = {
|
|
let root_handles = {
|
|
- let guard = self.state.read()?;
|
|
|
|
|
|
+ let guard = self.state.read().display_err()?;
|
|
guard
|
|
guard
|
|
.storage
|
|
.storage
|
|
.root
|
|
.root
|
|
.as_ref()
|
|
.as_ref()
|
|
- .ok_or_else(|| Error::custom("root creds have not yet been generated"))?
|
|
|
|
|
|
+ .ok_or_else(|| bterr!("root creds have not yet been generated"))?
|
|
.clone()
|
|
.clone()
|
|
};
|
|
};
|
|
- let mut guard = self.state.write()?;
|
|
|
|
|
|
+ let mut guard = self.state.write().display_err()?;
|
|
let key_handles = root_handles.to_cred_data(&mut guard.context)?;
|
|
let key_handles = root_handles.to_cred_data(&mut guard.context)?;
|
|
guard.context.set_auth(&key_handles, password)?;
|
|
guard.context.set_auth(&key_handles, password)?;
|
|
Ok(TpmCreds::new(key_handles, &self.state))
|
|
Ok(TpmCreds::new(key_handles, &self.state))
|
|
@@ -1088,13 +1085,13 @@ impl CredStore for TpmCredStore {
|
|
|
|
|
|
fn gen_root_creds(&self, password: &str) -> Result<Self::CredHandle> {
|
|
fn gen_root_creds(&self, password: &str) -> Result<Self::CredHandle> {
|
|
{
|
|
{
|
|
- let guard = self.state.read()?;
|
|
|
|
|
|
+ let guard = self.state.read().display_err()?;
|
|
if guard.storage.root.is_some() {
|
|
if guard.storage.root.is_some() {
|
|
- return Err(Error::custom("root creds have already been generated"));
|
|
|
|
|
|
+ return Err(bterr!("root creds have already been generated"));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
let policy = {
|
|
let policy = {
|
|
- let mut guard = self.state.write()?;
|
|
|
|
|
|
+ let mut guard = self.state.write().display_err()?;
|
|
guard.context.dup_with_password_policy()?
|
|
guard.context.dup_with_password_policy()?
|
|
};
|
|
};
|
|
let sign = self.gen_root_sign_key(password, policy.clone())?;
|
|
let sign = self.gen_root_sign_key(password, policy.clone())?;
|
|
@@ -1105,7 +1102,7 @@ impl CredStore for TpmCredStore {
|
|
writecap: None,
|
|
writecap: None,
|
|
};
|
|
};
|
|
{
|
|
{
|
|
- let mut guard = self.state.write()?;
|
|
|
|
|
|
+ let mut guard = self.state.write().display_err()?;
|
|
guard.context.set_auth(&cred_data, password)?;
|
|
guard.context.set_auth(&cred_data, password)?;
|
|
}
|
|
}
|
|
let mut creds = TpmCreds::new(cred_data, &self.state);
|
|
let mut creds = TpmCreds::new(cred_data, &self.state);
|
|
@@ -1128,7 +1125,7 @@ impl CredStore for TpmCredStore {
|
|
let params = DerivationParams::new()?;
|
|
let params = DerivationParams::new()?;
|
|
let aead_key = params.derive_key(password)?;
|
|
let aead_key = params.derive_key(password)?;
|
|
let new_parent = new_parent.storage_key_public()?;
|
|
let new_parent = new_parent.storage_key_public()?;
|
|
- let mut guard = self.state.write()?;
|
|
|
|
|
|
+ let mut guard = self.state.write().display_err()?;
|
|
if let Some(storage_key) = guard.storage_key.take() {
|
|
if let Some(storage_key) = guard.storage_key.take() {
|
|
// Save memory by flushing the storage key from the TPM's RAM.
|
|
// Save memory by flushing the storage key from the TPM's RAM.
|
|
guard.context.flush_context(storage_key.private.into())?;
|
|
guard.context.flush_context(storage_key.private.into())?;
|
|
@@ -1165,7 +1162,7 @@ impl CredStore for TpmCredStore {
|
|
let auth = Auth::try_from(password.as_bytes())?;
|
|
let auth = Auth::try_from(password.as_bytes())?;
|
|
let storage_key = self.get_or_init_storage_key()?;
|
|
let storage_key = self.get_or_init_storage_key()?;
|
|
let creds = {
|
|
let creds = {
|
|
- let mut guard = self.state.write()?;
|
|
|
|
|
|
+ let mut guard = self.state.write().display_err()?;
|
|
let sign = guard.context.import_key(
|
|
let sign = guard.context.import_key(
|
|
exported.sign,
|
|
exported.sign,
|
|
storage_key.private,
|
|
storage_key.private,
|
|
@@ -1193,7 +1190,7 @@ impl CredStore for TpmCredStore {
|
|
writecap: Writecap,
|
|
writecap: Writecap,
|
|
) -> Result<()> {
|
|
) -> Result<()> {
|
|
handle.writecap = Some(writecap.clone());
|
|
handle.writecap = Some(writecap.clone());
|
|
- let mut state = self.state.write()?;
|
|
|
|
|
|
+ let mut state = self.state.write().display_err()?;
|
|
if let Some(creds) = state.node_creds.as_mut() {
|
|
if let Some(creds) = state.node_creds.as_mut() {
|
|
creds.writecap = Some(writecap.clone());
|
|
creds.writecap = Some(writecap.clone());
|
|
}
|
|
}
|
|
@@ -1217,7 +1214,7 @@ impl<S: Scheme> AsymKeyPub<S> {
|
|
let pkey = PKey::from_rsa(rsa)?.conv_pub();
|
|
let pkey = PKey::from_rsa(rsa)?.conv_pub();
|
|
Ok(AsymKey { pkey, scheme })
|
|
Ok(AsymKey { pkey, scheme })
|
|
}
|
|
}
|
|
- _ => Err(Error::custom("Unsupported key type returned by TPM")),
|
|
|
|
|
|
+ key => Err(bterr!("Unsupported key type returned by TPM: {:?}", key)),
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -1260,7 +1257,7 @@ impl BigNumRefExt for &BigNumRef {
|
|
fn try_into_u32(self) -> Result<u32> {
|
|
fn try_into_u32(self) -> Result<u32> {
|
|
let data = self.to_vec();
|
|
let data = self.to_vec();
|
|
if data.len() > 4 {
|
|
if data.len() > 4 {
|
|
- return Err(Error::custom(format!("data was too long: {}", data.len())));
|
|
|
|
|
|
+ return Err(bterr!("data was too long: {}", data.len()));
|
|
}
|
|
}
|
|
let mut buf = [0u8; 4];
|
|
let mut buf = [0u8; 4];
|
|
// Note that BigNum data is stored in big endian format, so padding zeros go at the
|
|
// Note that BigNum data is stored in big endian format, so padding zeros go at the
|
|
@@ -1297,10 +1294,7 @@ impl MessageDigestExt for MessageDigest {
|
|
} else if Nid::sha3_512() == nid {
|
|
} else if Nid::sha3_512() == nid {
|
|
HashingAlgorithm::Sha3_512
|
|
HashingAlgorithm::Sha3_512
|
|
} else {
|
|
} else {
|
|
- return Err(Error::custom(format!(
|
|
|
|
- "Unsupported hash algorithm with NID: {:?}",
|
|
|
|
- nid
|
|
|
|
- )));
|
|
|
|
|
|
+ return Err(bterr!("Unsupported hash algorithm with NID: {:?}", nid));
|
|
};
|
|
};
|
|
Ok(algo)
|
|
Ok(algo)
|
|
}
|
|
}
|
|
@@ -1405,7 +1399,7 @@ impl<'a> Op for TpmSignOp<'a> {
|
|
let scheme = SignatureScheme::Null;
|
|
let scheme = SignatureScheme::Null;
|
|
|
|
|
|
let sig = {
|
|
let sig = {
|
|
- let mut guard = self.creds.state.write()?;
|
|
|
|
|
|
+ let mut guard = self.creds.state.write().display_err()?;
|
|
guard
|
|
guard
|
|
.context
|
|
.context
|
|
.sign(self.creds.sign.private, digest, scheme, validation)?
|
|
.sign(self.creds.sign.private, digest, scheme, validation)?
|
|
@@ -1413,19 +1407,14 @@ impl<'a> Op for TpmSignOp<'a> {
|
|
let slice: &[u8] = match &sig {
|
|
let slice: &[u8] = match &sig {
|
|
tss_esapi::structures::Signature::RsaSsa(inner) => inner.signature(),
|
|
tss_esapi::structures::Signature::RsaSsa(inner) => inner.signature(),
|
|
tss_esapi::structures::Signature::RsaPss(inner) => inner.signature(),
|
|
tss_esapi::structures::Signature::RsaPss(inner) => inner.signature(),
|
|
- _ => {
|
|
|
|
- return Err(Error::custom(format!(
|
|
|
|
- "Unexpected signature type: {:?}",
|
|
|
|
- sig.algorithm()
|
|
|
|
- )))
|
|
|
|
- }
|
|
|
|
|
|
+ _ => return Err(bterr!("Unexpected signature type: {:?}", sig.algorithm())),
|
|
};
|
|
};
|
|
|
|
|
|
if buf.len() < slice.len() {
|
|
if buf.len() < slice.len() {
|
|
- return Err(Error::IncorrectSize {
|
|
|
|
|
|
+ return Err(bterr!(Error::IncorrectSize {
|
|
expected: slice.len(),
|
|
expected: slice.len(),
|
|
actual: buf.len(),
|
|
actual: buf.len(),
|
|
- });
|
|
|
|
|
|
+ }));
|
|
}
|
|
}
|
|
buf.copy_from_slice(slice);
|
|
buf.copy_from_slice(slice);
|
|
Ok(slice.len())
|
|
Ok(slice.len())
|
|
@@ -1462,7 +1451,7 @@ impl Decrypter for TpmCreds {
|
|
let empty = [0u8; 0];
|
|
let empty = [0u8; 0];
|
|
let label = Data::try_from(empty.as_slice())?;
|
|
let label = Data::try_from(empty.as_slice())?;
|
|
let plain_text = {
|
|
let plain_text = {
|
|
- let mut guard = self.state.write()?;
|
|
|
|
|
|
+ let mut guard = self.state.write().display_err()?;
|
|
guard
|
|
guard
|
|
.context
|
|
.context
|
|
.rsa_decrypt(self.enc.private, cipher_text, in_scheme, label)?
|
|
.rsa_decrypt(self.enc.private, cipher_text, in_scheme, label)?
|
|
@@ -1706,7 +1695,7 @@ mod test {
|
|
if expected.as_slice() == actual {
|
|
if expected.as_slice() == actual {
|
|
Ok(())
|
|
Ok(())
|
|
} else {
|
|
} else {
|
|
- Err(Error::custom("decrypted data did not match input"))
|
|
|
|
|
|
+ Err(bterr!("decrypted data did not match input"))
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -1745,7 +1734,7 @@ mod test {
|
|
let cookie = Cookie::random()?;
|
|
let cookie = Cookie::random()?;
|
|
let params = KeyBuilder::new(Sign::RSA_PSS_3072_SHA_256, cookie.as_slice());
|
|
let params = KeyBuilder::new(Sign::RSA_PSS_3072_SHA_256, cookie.as_slice());
|
|
let pair = store.gen_key(params)?;
|
|
let pair = store.gen_key(params)?;
|
|
- let mut guard = store.state.write()?;
|
|
|
|
|
|
+ let mut guard = store.state.write().display_err()?;
|
|
guard.context.persist_key(pair.private)?;
|
|
guard.context.persist_key(pair.private)?;
|
|
Ok(())
|
|
Ok(())
|
|
}
|
|
}
|