Skip to content

Commit

Permalink
Merge branch 'mathias-CRP-1814-add-pks-and-sks-contains-to-vault-api'…
Browse files Browse the repository at this point in the history
… into 'master'

feat(crypto) CRP-1814 Adding pks_and_sks_contains to CSP vault API

Adding a new `pks_and_sks_contains` function to the CSP vault API, as well as implementation for the local vault. The new functionality is not yet called at the IDKM layer, and the soon-to-be-removed helper methods and `pks_contains` method is still there, to facilitate initial reviewing. 

See merge request dfinity-lab/public/ic!9604
  • Loading branch information
mbjorkqvist committed Jan 19, 2023
2 parents 22dc01c + 05b8a83 commit 8cb7789
Show file tree
Hide file tree
Showing 25 changed files with 1,909 additions and 164 deletions.
Expand Up @@ -30,9 +30,17 @@ impl TryFrom<PublicKeyProto> for CspFsEncryptionPublicKey {
type Error = MalformedFsEncryptionPublicKeyError;

fn try_from(pk_proto: PublicKeyProto) -> Result<Self, MalformedFsEncryptionPublicKeyError> {
Self::try_from(&pk_proto)
}
}

impl TryFrom<&PublicKeyProto> for CspFsEncryptionPublicKey {
type Error = MalformedFsEncryptionPublicKeyError;

fn try_from(pk_proto: &PublicKeyProto) -> Result<Self, MalformedFsEncryptionPublicKeyError> {
if pk_proto.algorithm != AlgorithmIdProto::Groth20Bls12381 as i32 {
return Err(MalformedFsEncryptionPublicKeyError {
key_bytes: pk_proto.key_value,
key_bytes: pk_proto.clone().key_value,
internal_error: format!("Unknown algorithm: {}", pk_proto.algorithm),
});
}
Expand Down
30 changes: 29 additions & 1 deletion rs/crypto/internal/crypto_service_provider/src/keygen/mod.rs
Expand Up @@ -71,7 +71,7 @@ impl CspSecretKeyStoreChecker for Csp {
/// Some key related utils
pub mod utils {
use crate::types::{CspPop, CspPublicKey};
use ic_crypto_internal_threshold_sig_ecdsa::MEGaPublicKey;
use ic_crypto_internal_threshold_sig_ecdsa::{EccCurveType, MEGaPublicKey};
use ic_crypto_internal_types::encrypt::forward_secure::{
CspFsEncryptionPop, CspFsEncryptionPublicKey,
};
Expand Down Expand Up @@ -138,4 +138,32 @@ pub mod utils {
timestamp: None,
}
}

#[derive(Clone, Debug, PartialEq, Eq)]
pub enum MEGaPublicKeyFromProtoError {
UnsupportedAlgorithm {
algorithm_id: Option<AlgorithmIdProto>,
},
MalformedPublicKey {
key_bytes: Vec<u8>,
},
}

/// Deserialize a Protobuf public key to a MEGaPublicKey.
pub fn mega_public_key_from_proto(
proto: &PublicKeyProto,
) -> Result<MEGaPublicKey, MEGaPublicKeyFromProtoError> {
let curve_type = match AlgorithmIdProto::from_i32(proto.algorithm) {
Some(AlgorithmIdProto::MegaSecp256k1) => Ok(EccCurveType::K256),
alg_id => Err(MEGaPublicKeyFromProtoError::UnsupportedAlgorithm {
algorithm_id: alg_id,
}),
}?;

MEGaPublicKey::deserialize(curve_type, &proto.key_value).map_err(|_| {
MEGaPublicKeyFromProtoError::MalformedPublicKey {
key_bytes: proto.key_value.clone(),
}
})
}
}
6 changes: 3 additions & 3 deletions rs/crypto/internal/crypto_service_provider/src/lib.rs
Expand Up @@ -26,15 +26,15 @@ use crate::vault::remote_csp_vault::RemoteCspVault;
use crate::api::{
CspIDkgProtocol, CspKeyGenerator, CspSecretKeyStoreChecker, CspSigVerifier, CspSigner,
CspThresholdEcdsaSigVerifier, CspThresholdEcdsaSigner, CspTlsHandshakeSignerProvider,
NiDkgCspClient, NodePublicKeyData, ThresholdSignatureCspClient,
DkgDealingEncryptionKeyIdRetrievalError, NiDkgCspClient, NodePublicKeyData,
NodePublicKeyDataError, ThresholdSignatureCspClient,
};
use crate::api::{DkgDealingEncryptionKeyIdRetrievalError, NodePublicKeyDataError};
use crate::public_key_store::proto_pubkey_store::ProtoPublicKeyStore;
use crate::public_key_store::temp_pubkey_store::TempPublicKeyStore;
use crate::public_key_store::PublicKeyStore;
use crate::secret_key_store::temp_secret_key_store::TempSecretKeyStore;
use crate::secret_key_store::SecretKeyStore;
use crate::types::CspPublicKey;
use crate::types::{CspPublicKey, ExternalPublicKeys};
use crate::vault::api::{CspPublicKeyStoreError, CspVault};
use ic_config::crypto::{CryptoConfig, CspVaultType};
use ic_crypto_internal_logmon::metrics::CryptoMetrics;
Expand Down
10 changes: 10 additions & 0 deletions rs/crypto/internal/crypto_service_provider/src/types.rs
Expand Up @@ -17,6 +17,7 @@ use ic_crypto_internal_threshold_sig_bls12381::types as threshold_types;
#[cfg(test)]
use ic_crypto_internal_threshold_sig_ecdsa::EccScalarBytes;
use ic_crypto_internal_threshold_sig_ecdsa::{CommitmentOpeningBytes, MEGaKeySetK256Bytes};
use ic_protobuf::registry::crypto::v1::{PublicKey, X509PublicKeyCert};
use ic_types::crypto::AlgorithmId;
use serde::{Deserialize, Serialize};
use strum_macros::{EnumCount, IntoStaticStr};
Expand Down Expand Up @@ -268,3 +269,12 @@ impl CspSignature {
pub struct SigConverter {
target_algorithm: AlgorithmId,
}

#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct ExternalPublicKeys {
pub node_signing_public_key: PublicKey,
pub committee_signing_public_key: PublicKey,
pub tls_certificate: X509PublicKeyCert,
pub dkg_dealing_encryption_public_key: PublicKey,
pub idkg_dealing_encryption_public_key: PublicKey,
}
Expand Up @@ -61,10 +61,17 @@ impl TryFrom<PublicKeyProto> for CspPublicKey {
// TODO (CRP-540): move the key bytes from pk_proto.key_value to the
// resulting csp_pk (instead of copying/cloning them).
fn try_from(pk_proto: PublicKeyProto) -> Result<Self, Self::Error> {
Self::try_from(&pk_proto)
}
}

impl TryFrom<&PublicKeyProto> for CspPublicKey {
type Error = CryptoError;
fn try_from(pk_proto: &PublicKeyProto) -> Result<Self, Self::Error> {
match AlgorithmId::from(pk_proto.algorithm) {
AlgorithmId::Ed25519 => {
let public_key_bytes =
ed25519_types::PublicKeyBytes::try_from(&pk_proto).map_err(|e| {
ed25519_types::PublicKeyBytes::try_from(pk_proto).map_err(|e| {
CryptoError::MalformedPublicKey {
algorithm: AlgorithmId::Ed25519,
key_bytes: Some(e.key_bytes),
Expand All @@ -75,7 +82,7 @@ impl TryFrom<PublicKeyProto> for CspPublicKey {
}
AlgorithmId::MultiBls12_381 => {
let public_key_bytes =
multi_types::PublicKeyBytes::try_from(&pk_proto).map_err(|e| {
multi_types::PublicKeyBytes::try_from(pk_proto).map_err(|e| {
CryptoError::MalformedPublicKey {
algorithm: AlgorithmId::MultiBls12_381,
key_bytes: Some(e.key_bytes),
Expand Down
71 changes: 71 additions & 0 deletions rs/crypto/internal/crypto_service_provider/src/vault/api.rs
Expand Up @@ -2,6 +2,7 @@ use crate::api::{CspCreateMEGaKeyError, CspThresholdSignError};
use crate::key_id::KeyId;
use crate::types::CspPublicCoefficients;
use crate::types::{CspPop, CspPublicKey, CspSignature};
use crate::ExternalPublicKeys;
use ic_crypto_internal_seed::Seed;
use ic_crypto_internal_threshold_sig_bls12381::api::ni_dkg_errors;
use ic_crypto_internal_threshold_sig_ecdsa::{
Expand Down Expand Up @@ -147,6 +148,50 @@ pub enum CspTlsSignError {
},
}

#[derive(Clone, Debug, Default, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct NodeKeysErrors {
pub node_signing_key_error: Option<NodeKeysError>,
pub committee_signing_key_error: Option<NodeKeysError>,
pub tls_certificate_error: Option<NodeKeysError>,
pub dkg_dealing_encryption_key_error: Option<NodeKeysError>,
pub idkg_dealing_encryption_key_error: Option<NodeKeysError>,
}

#[derive(Clone, Debug, Default, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct NodeKeysError {
pub external_public_key_error: Option<ExternalPublicKeyError>,
pub local_public_key_error: Option<LocalPublicKeyError>,
pub secret_key_error: Option<SecretKeyError>,
}

#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct ExternalPublicKeyError(pub Box<String>);

#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum LocalPublicKeyError {
/// No local public key exists.
NotFound,
/// A local public key exists, but it is not the same as the external key passed in.
Mismatch,
}

#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum SecretKeyError {
/// Unable to compute the key ID using the externally provided public key.
CannotComputeKeyId,
/// A local secret key matching the externally provided public key does not exist
NotFound,
}

#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum PksAndSksContainsErrors {
/// If one or more keys were missing, or were malformed, or did not match the corresponding
/// external public key.
NodeKeysErrors(NodeKeysErrors),
/// If a transient internal error occurs, e.g., an RPC error communicating with the remote vault
TransientInternalError(String),
}

/// `CspVault` offers a selection of operations that involve
/// secret keys managed by the vault.
pub trait CspVault:
Expand All @@ -159,6 +204,7 @@ pub trait CspVault:
+ SecretKeyStoreCspVault
+ TlsHandshakeCspVault
+ PublicRandomSeedGenerator
+ PublicAndSecretKeyStoreCspVault
+ PublicKeyStoreCspVault
{
}
Expand All @@ -175,6 +221,7 @@ impl<T> CspVault for T where
+ SecretKeyStoreCspVault
+ TlsHandshakeCspVault
+ PublicRandomSeedGenerator
+ PublicAndSecretKeyStoreCspVault
+ PublicKeyStoreCspVault
{
}
Expand Down Expand Up @@ -478,6 +525,30 @@ pub trait PublicKeyStoreCspVault {
fn idkg_dealing_encryption_pubkeys_count(&self) -> Result<usize, CspPublicKeyStoreError>;
}

/// Operations of `CspVault` related to querying both the public and private key stores.
pub trait PublicAndSecretKeyStoreCspVault {
/// Checks whether the keys corresponding to the provided external public keys exist locally.
/// In particular, this means the provided public keys themselves are stored locally, as well
/// as the corresponding secret keys. Key comparisons will not take timestamps into account.
///
/// # Parameters
/// The current external node public keys and TLS certificate.
///
/// # Returns
/// An empty result if all the external public keys, and the corresponding secret keys, were
/// all found locally.
///
/// # Errors
/// * `PksAndSksContainsErrors::NodeKeysErrors` if local public or secret keys were not
/// consistent with the provided external keys.
/// * `PksAndSksContainsErrors::TransientInternalError` if a transient internal error, e.g., an RPC
/// error, occurred.
fn pks_and_sks_contains(
&self,
external_public_keys: ExternalPublicKeys,
) -> Result<(), PksAndSksContainsErrors>;
}

/// Operations of `CspVault` related to TLS handshakes.
pub trait TlsHandshakeCspVault: Send + Sync {
/// Generates TLS key material for node with ID `node_id`.
Expand Down
Expand Up @@ -2,6 +2,7 @@ mod basic_sig;
mod idkg;
mod multi_sig;
mod ni_dkg;
mod public_and_secret_key_store;
mod public_key_store;
mod public_seed;
mod secret_key_store;
Expand Down Expand Up @@ -240,6 +241,16 @@ impl<R: Rng + CryptoRng, S: SecretKeyStore, C: SecretKeyStore, P: PublicKeyStore
(sks_write_lock, pks_write_lock)
}

/// Acquires read locks for both the node secret key store and the public key store.
///
/// The locks are acquired according to the total resource order defined in the
/// section on deadlock prevention in the documentation of the `LocalCspVault`.
fn sks_and_pks_read_locks(&self) -> (RwLockReadGuard<'_, S>, RwLockReadGuard<'_, P>) {
let sks_read_lock = self.node_secret_key_store.read();
let pks_read_lock = self.public_key_store.read();
(sks_read_lock, pks_read_lock)
}

fn sks_read_lock(&self) -> RwLockReadGuard<'_, S> {
self.node_secret_key_store.read()
}
Expand Down

0 comments on commit 8cb7789

Please sign in to comment.