Skip to content
Open
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 .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
"cSpell.words": [
"actix",
"ascii",
"Byok",
"canonicalize",
"chacha",
"ciphertext",
Expand Down
9 changes: 6 additions & 3 deletions crate/cli/src/actions/kms/actions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ use super::configurable_kem::ConfigurableKemCommands;
use super::cover_crypt::CovercryptCommands;
use crate::{
actions::kms::{
access::AccessAction, attributes::AttributesCommands, azure::AzureCommands,
bench::BenchAction, certificates::CertificatesCommands, console::Stdout,
derive_key::DeriveKeyAction, elliptic_curves::EllipticCurveCommands,
access::AccessAction, attributes::AttributesCommands, aws::AwsCommands,
azure::AzureCommands, bench::BenchAction, certificates::CertificatesCommands,
console::Stdout, derive_key::DeriveKeyAction, elliptic_curves::EllipticCurveCommands,
google::GoogleCommands, hash::HashAction, login::LoginAction, mac::MacCommands,
opaque_object::OpaqueObjectCommands, rng::RngAction, rsa::RsaCommands,
secret_data::SecretDataCommands, shared::LocateObjectsAction, symmetric::SymmetricCommands,
Expand All @@ -30,6 +30,8 @@ pub enum KmsActions {
Attributes(AttributesCommands),
#[command(subcommand)]
Azure(AzureCommands),
#[command(subcommand)]
Aws(AwsCommands),
#[clap(hide = true)]
Bench(BenchAction),
#[cfg(feature = "non-fips")]
Expand Down Expand Up @@ -81,6 +83,7 @@ impl KmsActions {
match self {
Self::AccessRights(action) => Box::pin(action.process(kms_rest_client)).await?,
Self::Attributes(action) => Box::pin(action.process(kms_rest_client)).await?,
Self::Aws(action) => Box::pin(action.process(kms_rest_client)).await?,
Self::Azure(action) => Box::pin(action.process(kms_rest_client)).await?,
Self::Bench(action) => Box::pin(action.process(kms_rest_client)).await?,
#[cfg(feature = "non-fips")]
Expand Down
32 changes: 32 additions & 0 deletions crate/cli/src/actions/kms/aws/README.ms
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
## creating keys on amazon kms

https://docs.aws.amazon.com/kms/latest/developerguide/importing-keys-conceptual.html

"importing keys link"

https://docs.aws.amazon.com/kms/latest/developerguide/importing-keys.html


requirements for key material :
https://docs.aws.amazon.com/kms/latest/developerguide/importing-keys-conceptual.html#importing-keys-material-requirements


// TODO: export a file path, if specified
// test key : e8518bca-e1d0-4519-a915-d80da8e8f38a

// aws kms get-parameters-for-import \
// --key-id e8518bca-e1d0-4519-a915-d80da8e8f38a \
// --wrapping-algorithm RSA_AES_KEY_WRAP_SHA_256 \
// --wrapping-key-spec RSA_3072

// results :
// {
// "KeyId": "arn:aws:kms:eu-west-3:447182645454:key/e8518bca-e1d0-4519-a915-d80da8e8f38a",
// "ImportToken": "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",
// "PublicKey": "MIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEA020eGsIGUYdaNMP2Ty6b/YmpL+8eMopdaXg5I+x3TMzTT7QV7d3mfe5E/wgNRGDjYRdA74S8WwdwcSpfFpppVnDKX1dKIXS5woYa7hx/YAdY/3kv0VJKGKxt8Tf1Ajpekot0uVLbHOwR9DF8aBiDCtrZR7x94H1GPSXZ3VLZimBldcJ+Tszt4wITmwBjJxkPXJzkVa8zg2tnTKm/M5TwMDe5Q3DUOYKVgMKdcsJPX43q72radD1VdMazxzps+7wDT64AD5FZoXHcJH4ZytIMySbhlwsQntT5lNeyulg7kbFAFuSzGM7SipDwvVPzgxrDY1aw/VpJ9vuMqtO/V7TWwL8NSuoh/5bsVXCUFdSXHmz9oh/hj8zIPDLjHc/Z1guGanl+4/ZQbs4M4SgqN1KT/aayX+oDsvj6Q+GVzhCIpq7XQJekcOcRjCyYocCLfYOTv2N/vFMGxcKZZLM4LmCGMFsDEO1GaISPsv6mVUgewWMeBmzTBbyB6atA07Li9JMjAgMBAAE=",
// "ParametersValidTo": "2026-01-15T16:58:27.315000+01:00"
// }

// aws kms import-key-material --key-id e8518bca-e1d0-4519-a915-d80da8e8f38a \
// --encrypted-key-material fileb://EncryptedKeyMaterial.bin \
// --import-token fileb://ImportToken.bin
183 changes: 183 additions & 0 deletions crate/cli/src/actions/kms/aws/byok/export_key_material.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
use std::{fs, path::PathBuf};

use base64::Engine;
use clap::Parser;
use cosmian_kmip::{
kmip_0::kmip_types::{HashingAlgorithm, PaddingMethod},
kmip_2_1::{
kmip_data_structures::KeyValue,
kmip_types::{CryptographicAlgorithm, CryptographicParameters, Tag},
},
};
use cosmian_kms_client::{ExportObjectParams, KmsClient, export_object};
use cosmian_logger::warn;

use crate::{
actions::kms::{
attributes::get_attributes, aws::byok::wrapping_algorithms::AwsKmsWrappingAlgorithm,
console,
},
cli_bail,
error::{
KmsCliError,
result::{KmsCliResult, KmsCliResultHelper},
},
};

/// Wrap a KMS key with an AWS Key Encryption Key (KEK).
#[derive(Parser)]
#[clap(verbatim_doc_comment)]
pub struct ExportByokAction {
/// The unique ID of the KMS private key that will be wrapped and then exported
#[clap(required = true)]
pub(crate) key_id: String,

/// The AWS KEK ID in this KMS.
#[clap(required = true)]
pub(crate) kek_id: String,

/// The file path containing the import token previously generated when importing the KEK.
/// This file isn't red and neither used by the KMS, it's simply for providing copy-paste ready output for
/// aws cli users upon a successful key material wrapping
#[clap(required = false)]
pub(crate) token_file_path: Option<PathBuf>,

/// If not specified, a base64 encoded blob containing the key material will be printed to stdout. Can be piped to desired file or command.
#[clap(required = false)]
pub(crate) output_file_path: Option<PathBuf>,
}

impl ExportByokAction {
#[allow(clippy::print_stdout, clippy::or_fun_call)] // the kms console wrapper forces a println but this function does not want a line return for proper display
pub async fn run(&self, kms_client: KmsClient) -> KmsCliResult<String> {
// Recover the attributes of the KEK key
let (_kek_id, kek_attributes) =
get_attributes(&kms_client, &self.kek_id, &[Tag::Tag], &[]).await?;
let kek_tag_error = |msg: &str| -> String {
format!(
"The KEK is not an AWS Key Encryption Key: {msg}. Import it using the \
`cosmian kms aws byok import` command."
)
};

let tags: Vec<String> = serde_json::from_value(
kek_attributes
.get("Tag")
.context(&kek_tag_error("no tags"))?
.clone(),
)?;

if !tags.contains(&"aws".to_owned()) {
return Err(KmsCliError::InconsistentOperation(kek_tag_error(
"missing `aws` tag",
)));
}

let key_arn = tags.iter().find_map(|t| t.strip_prefix("key_arn:"));

let wrapping_algorithm_str = tags
.iter()
.find(|t| t.starts_with("wrapping_algorithm:"))
.context(&kek_tag_error("wrapping algorithm not found"))?
.strip_prefix("wrapping_algorithm:")
.ok_or(KmsCliError::Default(kek_tag_error(
"invalid wrapping algorithm tag",
)))?
.parse::<AwsKmsWrappingAlgorithm>()
.context(&kek_tag_error("invalid wrapping algorithm tag"))?;

let wrapping_cryptographic_parameters = Some(match wrapping_algorithm_str {
AwsKmsWrappingAlgorithm::RsaesOaepSha1 => CryptographicParameters {
cryptographic_algorithm: Some(CryptographicAlgorithm::RSA),
padding_method: Some(PaddingMethod::OAEP),
hashing_algorithm: Some(HashingAlgorithm::SHA1),
..CryptographicParameters::default()
},
AwsKmsWrappingAlgorithm::RsaesOaepSha256 => CryptographicParameters {
cryptographic_algorithm: Some(CryptographicAlgorithm::RSA),
padding_method: Some(PaddingMethod::OAEP),
hashing_algorithm: Some(HashingAlgorithm::SHA256),
..CryptographicParameters::default()
},
AwsKmsWrappingAlgorithm::RsaAesKeyWrapSha1 => CryptographicParameters {
cryptographic_algorithm: Some(CryptographicAlgorithm::RSA),
// Note: We use "None" padding to route toward RSA AES Key Wrap, this is not a mistake
// see: crate/crypto/src/crypto/wrap/unwrap_key.rs line 365
padding_method: Some(PaddingMethod::None),
hashing_algorithm: Some(HashingAlgorithm::SHA1),
..CryptographicParameters::default()
},
AwsKmsWrappingAlgorithm::RsaAesKeyWrapSha256 => CryptographicParameters {
cryptographic_algorithm: Some(CryptographicAlgorithm::RSA),
padding_method: Some(PaddingMethod::None),
hashing_algorithm: Some(HashingAlgorithm::SHA256),
..CryptographicParameters::default()
},
// SM2PKE: SM2 public key encryption (China Regions only)
// Supported for: RSA private keys, ECC private keys, SM2 private keys
// TODO: gate this
AwsKmsWrappingAlgorithm::Sm2Pke => {
warn!(
"This encrypted key material can only be imported into AWS KMS in China Regions."
);
CryptographicParameters {
cryptographic_algorithm: Some(CryptographicAlgorithm::SM2),
padding_method: None, // SM2 uses its own encryption scheme per GM/T 0003.4-2012
..CryptographicParameters::default()
}
}
});

// Export the key wrapped with the KEK
let export_params = ExportObjectParams {
unwrap: false,
wrapping_key_id: Some(&self.kek_id),
allow_revoked: false,
key_format_type: None,
encode_to_ttlv: false,
wrapping_cryptographic_parameters,
authenticated_encryption_additional_data: None,
};

let (_, object, _) = export_object(&kms_client, &self.key_id, export_params).await?;

// Recover the wrapped bytes from the KeyBlock
let key_block = object.key_block()?;
let Some(KeyValue::ByteString(wrapped_key)) = &key_block.key_value else {
cli_bail!("The wrapped key should be a byte string");
};
let b64_key = base64::engine::general_purpose::STANDARD.encode(wrapped_key);

if let Some(file_path) = &self.output_file_path {
fs::write(file_path, wrapped_key)?;

// Print all formatting and instructions to stderr to not interfere with pipes
eprint!("The encrypted key material was successfully written to ");
print!("{}", file_path.display());
eprintln!(
"{} for key {}.\n\n\
To import into AWS KMS using the API, run:\n\
aws kms import-key-material \\\n\
--key-id {} \\\n\
--encrypted-key-material fileb://{} \\\n\
--import-token fileb://{} \\\n\
--expiration-model KEY_MATERIAL_DOES_NOT_EXPIRE",
wrapped_key.len(),
self.key_id,
key_arn.unwrap_or("<AWS_KEY_ARN>"),
file_path.display(),
self.token_file_path.as_ref().map_or_else(
|| "<IMPORT_TOKEN_FILE>".to_owned(),
|p| { p.display().to_string() }
)
);
} else {
// Same as above: descriptive info to stderr...
eprintln!("Wrapped key material (base64-encoded):");
// And raw output goes to stdout (can be piped)
let stdout = console::Stdout::new(&b64_key);
stdout.write()?;
}
Ok(b64_key)
}
}
103 changes: 103 additions & 0 deletions crate/cli/src/actions/kms/aws/byok/import_kek.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
use std::path::PathBuf;

use crate::{
actions::kms::{
aws::byok::wrapping_algorithms::AwsKmsWrappingAlgorithm,
shared::ImportSecretDataOrKeyAction,
},
error::{KmsCliError, result::KmsCliResult},
};
use base64::{Engine, prelude::BASE64_STANDARD};
use clap::{ArgGroup, Parser};
use cosmian_kmip::kmip_2_1::kmip_types::UniqueIdentifier;
use cosmian_kms_client::{
KmsClient,
reexport::cosmian_kms_client_utils::import_utils::{ImportKeyFormat, KeyUsage},
};

/// Validate that the string is valid base64 and its decoded length is between 1 and 4096 bytes.
fn validate_kek_base64(s: &str) -> Result<String, String> {
let decoded = BASE64_STANDARD
.decode(s)
.map_err(|e| format!("Invalid base64 encoding: {e}"))?;

if decoded.is_empty() {
return Err("KEK decoded data is empty".to_owned());
}

if decoded.len() > 4096 {
return Err(format!(
"KEK decoded data exceeds maximum length of 4096 bytes (got {})",
decoded.len()
));
}
Ok(s.to_owned())
}

/// Import an AWS Key Encryption Key (KEK) into the KMS.
#[derive(Parser)]
#[clap(verbatim_doc_comment)]
#[clap(group(ArgGroup::new("kek_input").required(true).args(["kek_base64", "kek_file"])))] // At least one of kek_file or kek_blob must be provided
pub struct ImportKekAction {
/// The RSA Key Encryption public key (the KEK) as a base64-encoded string
#[clap(
short = 'b',
long,
value_parser = clap::builder::ValueParser::new(validate_kek_base64),
group = "kek_input"
)]
pub(crate) kek_base64: Option<String>,

/// In case of KEK provided as a file blob.
#[clap(short = 'f', long, group = "kek_input")]
pub(crate) kek_file: Option<PathBuf>,

#[clap(short = 'w', long, required = true)]
pub(crate) wrapping_algorithm: AwsKmsWrappingAlgorithm,

/// The Amazon Resource Name (key ARN) of the KMS key. It's recommended to provide it for an easier export later.
#[clap(short = 'a', long, required = false)]
pub(crate) key_arn: Option<String>,

/// The unique ID of the key in this KMS; a random UUID
/// is generated if not specified.
#[clap(short = 'i', long, required = false)]
pub(crate) key_id: Option<String>,
}

impl ImportKekAction {
pub async fn run(&self, kms_client: KmsClient) -> KmsCliResult<UniqueIdentifier> {
// build tags
let mut tags = vec![
"aws".to_owned(),
format!("wrapping_algorithm:{}", self.wrapping_algorithm),
];
if let Some(arn) = &self.key_arn {
tags.push(format!("key_arn:{arn}"));
}

let import_action = ImportSecretDataOrKeyAction {
key_file: match (&self.kek_file, &self.kek_base64) {
(Some(file), _) => file.clone(),
(None, Some(base64_str)) => {
let temp_path = std::env::temp_dir().join(format!("{}", uuid::Uuid::new_v4()));
std::fs::write(&temp_path, BASE64_STANDARD.decode(base64_str)?)?;
temp_path
}
(None, None) => {
return Err(KmsCliError::Default(
"KEK file or base64 data must be provided".to_owned(),
));
}
},
key_id: self.key_id.clone(),
key_format: ImportKeyFormat::Pkcs8Pub,
tags,
key_usage: Some(vec![KeyUsage::WrapKey, KeyUsage::Encrypt]),
replace_existing: true,
..Default::default()
};

import_action.run(kms_client).await
}
}
33 changes: 33 additions & 0 deletions crate/cli/src/actions/kms/aws/byok/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
pub mod export_key_material;
pub mod import_kek;
pub mod wrapping_algorithms;

use clap::Subcommand;
use cosmian_kms_client::KmsClient;

use crate::{
actions::kms::aws::byok::{export_key_material::ExportByokAction, import_kek::ImportKekAction},
error::result::KmsCliResult,
};

/// AWS BYOK support.
/// See: <https://docs.aws.amazon.com/kms/latest/developerguide/importing-keys-conceptual.html>
#[derive(Subcommand)]
pub enum ByokCommands {
Import(ImportKekAction),
Export(ExportByokAction),
}

impl ByokCommands {
pub async fn process(&self, kms_rest_client: KmsClient) -> KmsCliResult<()> {
match self {
Self::Import(action) => {
action.run(kms_rest_client).await?;
}
Self::Export(action) => {
action.run(kms_rest_client).await?;
}
}
Ok(())
}
}
Loading
Loading