feat: v1.11.0, remove swiftc dependency
This commit is contained in:
@@ -1,11 +1,7 @@
|
||||
use crate::ecdsautil;
|
||||
use crate::keyutil::{parse_key_uri, KeyUri};
|
||||
use clap::{App, Arg, ArgMatches, SubCommand};
|
||||
use p256::elliptic_curve::sec1::FromEncodedPoint;
|
||||
use p256::{EncodedPoint, PublicKey};
|
||||
use rust_util::util_clap::{Command, CommandError};
|
||||
use rust_util::util_msg;
|
||||
use spki::EncodePublicKey;
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
pub struct CommandImpl;
|
||||
|
||||
@@ -31,7 +31,7 @@ impl Command for CommandImpl {
|
||||
}
|
||||
|
||||
let ciphertext = sub_arg_matches.value_of("ciphertext").unwrap();
|
||||
let plaintext = hmacutil::hmac_decrypt_to_string(&ciphertext)?;
|
||||
let plaintext = hmacutil::hmac_decrypt_to_string(ciphertext)?;
|
||||
|
||||
if json_output {
|
||||
let mut json = BTreeMap::<&'_ str, String>::new();
|
||||
|
||||
@@ -8,8 +8,6 @@ use rust_util::util_msg;
|
||||
use crate::ecdsautil::parse_ecdsa_r_and_s;
|
||||
use crate::util::try_decode;
|
||||
|
||||
const SEPARATOR: &str = ".";
|
||||
|
||||
pub struct CommandImpl;
|
||||
|
||||
impl Command for CommandImpl {
|
||||
|
||||
@@ -50,8 +50,7 @@ impl Command for CommandImpl {
|
||||
let KeyUri::SecureEnclaveKey(se_key_uri) = parse_key_uri(key)?;
|
||||
debugging!("Secure enclave key URI: {:?}", se_key_uri);
|
||||
|
||||
let ephemeral_public_key_der_bytes;
|
||||
if epk.starts_with("04") {
|
||||
let ephemeral_public_key_der_bytes = if epk.starts_with("04") {
|
||||
let ephemeral_public_key_point_bytes = opt_result!(
|
||||
hex::decode(epk),
|
||||
"Decode public key point from hex failed: {}"
|
||||
@@ -65,11 +64,10 @@ impl Command for CommandImpl {
|
||||
return simple_error!("Parse public key failed.");
|
||||
}
|
||||
let public_key = public_key_opt.unwrap();
|
||||
ephemeral_public_key_der_bytes = public_key.to_public_key_der()?.as_bytes().to_vec();
|
||||
public_key.to_public_key_der()?.as_bytes().to_vec()
|
||||
} else {
|
||||
ephemeral_public_key_der_bytes =
|
||||
opt_result!(hex::decode(epk), "Decode public key from hex failed: {}");
|
||||
}
|
||||
opt_result!(hex::decode(epk), "Decode public key from hex failed: {}")
|
||||
};
|
||||
|
||||
let dh = seutil::secure_enclave_p256_dh(
|
||||
&se_key_uri.private_key,
|
||||
|
||||
@@ -7,11 +7,8 @@ use jwt::{AlgorithmType, Header, ToBase64};
|
||||
use rust_util::util_clap::{Command, CommandError};
|
||||
use rust_util::{util_msg, util_time, XResult};
|
||||
use serde_json::{Map, Number, Value};
|
||||
use yubikey::piv::{sign_data, AlgorithmId, SlotId};
|
||||
use yubikey::{Certificate, YubiKey};
|
||||
|
||||
use crate::ecdsautil::parse_ecdsa_to_rs;
|
||||
use crate::{cmd_signjwt, digest, ecdsautil, hmacutil, pivutil, rsautil, util};
|
||||
use crate::{cmd_signjwt, digest, ecdsautil, hmacutil, rsautil, util};
|
||||
|
||||
const SEPARATOR: &str = ".";
|
||||
|
||||
|
||||
@@ -22,8 +22,8 @@ pub fn parse_ecdsa_to_rs(signature_der: &[u8]) -> XResult<Vec<u8>> {
|
||||
}
|
||||
|
||||
pub fn parse_ecdsa_r_and_s(signature_der: &[u8]) -> XResult<(Vec<u8>, Vec<u8>)> {
|
||||
let mut vec_r: Vec<u8> = Vec::new();
|
||||
let mut vec_s: Vec<u8> = Vec::new();
|
||||
let vec_r: Vec<u8>;
|
||||
let vec_s: Vec<u8>;
|
||||
let (_, parsed_signature) = opt_result!(der_parser::parse_der(signature_der), "Parse signature failed: {}");
|
||||
match parsed_signature.content {
|
||||
BerObjectContent::Sequence(seq) => {
|
||||
@@ -73,7 +73,6 @@ pub fn generate_p384_keypair() -> XResult<(String, String, String)> {
|
||||
|
||||
macro_rules! parse_ecdsa_private_key {
|
||||
($algo: tt, $parse_ecdsa_private_key: tt) => ({
|
||||
use $algo::ecdsa::{SigningKey};
|
||||
use $algo::pkcs8::DecodePrivateKey;
|
||||
use $algo::SecretKey;
|
||||
|
||||
@@ -103,7 +102,7 @@ pub fn sign_p256_rs(private_key_d: &[u8], pre_hash: &[u8]) -> XResult<Vec<u8>> {
|
||||
use p256::ecdsa::{SigningKey, Signature};
|
||||
use p256::ecdsa::signature::hazmat::PrehashSigner;
|
||||
|
||||
let signing_key = SigningKey::from_slice(&private_key_d)?;
|
||||
let signing_key = SigningKey::from_slice(private_key_d)?;
|
||||
let signature: Signature = signing_key.sign_prehash(pre_hash)?;
|
||||
|
||||
Ok(signature.to_bytes().to_vec())
|
||||
@@ -113,7 +112,7 @@ pub fn sign_p384_rs(private_key_d: &[u8], pre_hash: &[u8]) -> XResult<Vec<u8>> {
|
||||
use p384::ecdsa::{SigningKey, Signature};
|
||||
use p384::ecdsa::signature::hazmat::PrehashSigner;
|
||||
|
||||
let signing_key = SigningKey::from_slice(&private_key_d)?;
|
||||
let signing_key = SigningKey::from_slice(private_key_d)?;
|
||||
let signature: Signature = signing_key.sign_prehash(pre_hash)?;
|
||||
|
||||
Ok(signature.to_bytes().to_vec())
|
||||
|
||||
@@ -8,7 +8,7 @@ use yubico_manager::config::{Config, Mode, Slot};
|
||||
use yubico_manager::hmacmode::HmacKey;
|
||||
use yubico_manager::sec::hmac_sha1;
|
||||
use yubico_manager::Yubico;
|
||||
use crate::digest::{copy_sha256, sha256, sha256_bytes};
|
||||
use crate::digest::{copy_sha256, sha256_bytes};
|
||||
use crate::util::{base64_decode, base64_encode};
|
||||
|
||||
const HMAC_ENC_PREFIX: &str = "hmac_enc:";
|
||||
@@ -33,8 +33,8 @@ pub fn hmac_encrypt(plaintext: &[u8]) -> XResult<String> {
|
||||
|
||||
Ok(format!("{}{}:{}:{}",
|
||||
HMAC_ENC_PREFIX,
|
||||
hex::encode(&hmac_nonce),
|
||||
hex::encode(&aes_gcm_nonce),
|
||||
hex::encode(hmac_nonce),
|
||||
hex::encode(aes_gcm_nonce),
|
||||
base64_encode(&ciphertext)
|
||||
))
|
||||
}
|
||||
@@ -92,7 +92,7 @@ pub fn compute_yubikey_hmac(challenge_bytes: &[u8]) -> XResult<Vec<u8>> {
|
||||
.set_mode(Mode::Sha1)
|
||||
.set_slot(Slot::Slot2);
|
||||
|
||||
let hmac_result = opt_result!(yubi.challenge_response_hmac(&challenge_bytes, config), "Challenge HMAC failed: {}");
|
||||
let hmac_result = opt_result!(yubi.challenge_response_hmac(challenge_bytes, config), "Challenge HMAC failed: {}");
|
||||
Ok(hmac_result.deref().to_vec())
|
||||
}
|
||||
|
||||
|
||||
13
src/main.rs
13
src/main.rs
@@ -33,15 +33,10 @@ mod cmd_pivverify;
|
||||
mod cmd_rsadecrypt;
|
||||
mod cmd_rsaencrypt;
|
||||
mod cmd_rsaverify;
|
||||
#[cfg(feature = "with-secure-enclave")]
|
||||
mod cmd_se;
|
||||
#[cfg(feature = "with-secure-enclave")]
|
||||
mod cmd_se_ecdh;
|
||||
#[cfg(feature = "with-secure-enclave")]
|
||||
mod cmd_se_ecsign;
|
||||
#[cfg(feature = "with-secure-enclave")]
|
||||
mod cmd_se_generate;
|
||||
#[cfg(feature = "with-secure-enclave")]
|
||||
mod cmd_se_recover;
|
||||
mod cmd_signfile;
|
||||
mod cmd_signjwt;
|
||||
@@ -68,7 +63,6 @@ mod pinutil;
|
||||
mod pivutil;
|
||||
mod pkiutil;
|
||||
mod rsautil;
|
||||
#[cfg(feature = "with-secure-enclave")]
|
||||
mod seutil;
|
||||
mod signfile;
|
||||
mod sshutil;
|
||||
@@ -139,15 +133,10 @@ fn inner_main() -> CommandError {
|
||||
Box::new(cmd_signjwtsoft::CommandImpl),
|
||||
Box::new(cmd_signfile::CommandImpl),
|
||||
Box::new(cmd_verifyfile::CommandImpl),
|
||||
#[cfg(feature = "with-secure-enclave")]
|
||||
Box::new(cmd_se::CommandImpl),
|
||||
#[cfg(feature = "with-secure-enclave")]
|
||||
Box::new(cmd_se_generate::CommandImpl),
|
||||
#[cfg(feature = "with-secure-enclave")]
|
||||
Box::new(cmd_se_recover::CommandImpl),
|
||||
#[cfg(feature = "with-secure-enclave")]
|
||||
Box::new(cmd_se_ecsign::CommandImpl),
|
||||
#[cfg(feature = "with-secure-enclave")]
|
||||
Box::new(cmd_se_ecdh::CommandImpl),
|
||||
Box::new(cmd_ecverify::CommandImpl),
|
||||
Box::new(cmd_parseecdsasignature::CommandImpl),
|
||||
@@ -159,8 +148,6 @@ fn inner_main() -> CommandError {
|
||||
let mut features: Vec<&str> = vec![];
|
||||
#[cfg(feature = "with-sequoia-openpgp")]
|
||||
features.push("sequoia-openpgp");
|
||||
#[cfg(feature = "with-secure-enclave")]
|
||||
features.push("secure-enclave");
|
||||
features
|
||||
};
|
||||
let about = format!(
|
||||
|
||||
126
src/seutil.rs
126
src/seutil.rs
@@ -1,113 +1,63 @@
|
||||
use crate::util::{base64_decode, base64_encode};
|
||||
use base64::engine::general_purpose::STANDARD;
|
||||
use base64::Engine;
|
||||
use rust_util::XResult;
|
||||
use swift_rs::swift;
|
||||
use swift_rs::{Bool, SRString};
|
||||
|
||||
swift!(fn is_support_secure_enclave() -> Bool);
|
||||
swift!(fn generate_secure_enclave_p256_ecdh_keypair() -> SRString);
|
||||
swift!(fn generate_secure_enclave_p256_ecsign_keypair() -> SRString);
|
||||
swift!(fn compute_secure_enclave_p256_ecdh(private_key_base64: SRString, ephemera_public_key_base64: SRString) -> SRString);
|
||||
swift!(fn compute_secure_enclave_p256_ecsign(private_key_base64: SRString, content: SRString) -> SRString);
|
||||
swift!(fn recover_secure_enclave_p256_ecsign_public_key(private_key_base64: SRString) -> SRString);
|
||||
swift!(fn recover_secure_enclave_p256_ecdh_public_key(private_key_base64: SRString) -> SRString);
|
||||
use swift_secure_enclave_tool_rs::KeyPurpose;
|
||||
|
||||
pub fn is_support_se() -> bool {
|
||||
unsafe { is_support_secure_enclave() }
|
||||
swift_secure_enclave_tool_rs::is_secure_enclave_supported().unwrap_or(false)
|
||||
}
|
||||
|
||||
pub fn generate_secure_enclave_p256_keypair(sign: bool) -> XResult<(Vec<u8>, Vec<u8>, String)> {
|
||||
let p256_keypair_result = if sign {
|
||||
unsafe { generate_secure_enclave_p256_ecsign_keypair() }
|
||||
let key_material = if sign {
|
||||
swift_secure_enclave_tool_rs::generate_ecdsa_keypair(KeyPurpose::Signing, true)?
|
||||
} else {
|
||||
unsafe { generate_secure_enclave_p256_ecdh_keypair() }
|
||||
swift_secure_enclave_tool_rs::generate_ecdsa_keypair(KeyPurpose::KeyAgreement, true)?
|
||||
};
|
||||
parse_p256_keypair_result(p256_keypair_result.as_str())
|
||||
Ok((
|
||||
key_material.public_key_point,
|
||||
key_material.public_key_der,
|
||||
STANDARD.encode(&key_material.private_key_representation),
|
||||
))
|
||||
}
|
||||
|
||||
pub fn recover_secure_enclave_p256_public_key(
|
||||
private_key: &str,
|
||||
sign: bool,
|
||||
) -> XResult<(Vec<u8>, Vec<u8>, String)> {
|
||||
let p256_keypair_result = if sign {
|
||||
unsafe { recover_secure_enclave_p256_ecsign_public_key(SRString::from(private_key)) }
|
||||
let private_key_representation = STANDARD.decode(private_key)?;
|
||||
let key_material = if sign {
|
||||
swift_secure_enclave_tool_rs::recover_ecdsa_keypair(
|
||||
KeyPurpose::Signing,
|
||||
&private_key_representation,
|
||||
)
|
||||
} else {
|
||||
unsafe { recover_secure_enclave_p256_ecdh_public_key(SRString::from(private_key)) }
|
||||
};
|
||||
parse_p256_keypair_result(p256_keypair_result.as_str())
|
||||
swift_secure_enclave_tool_rs::recover_ecdsa_keypair(
|
||||
KeyPurpose::KeyAgreement,
|
||||
&private_key_representation,
|
||||
)
|
||||
}?;
|
||||
Ok((
|
||||
key_material.public_key_point,
|
||||
key_material.public_key_der,
|
||||
STANDARD.encode(&key_material.private_key_representation),
|
||||
))
|
||||
}
|
||||
|
||||
pub fn secure_enclave_p256_dh(
|
||||
private_key: &str,
|
||||
ephemeral_public_key_bytes: &[u8],
|
||||
) -> XResult<Vec<u8>> {
|
||||
let dh_result = unsafe {
|
||||
compute_secure_enclave_p256_ecdh(
|
||||
SRString::from(private_key),
|
||||
SRString::from(base64_encode(ephemeral_public_key_bytes).as_str()),
|
||||
)
|
||||
};
|
||||
let dh_result_str = dh_result.as_str();
|
||||
debugging!("DH result: {}", &dh_result_str);
|
||||
if !dh_result_str.starts_with("ok:SharedSecret:") {
|
||||
return simple_error!("ECDH P256 in secure enclave failed: {}", dh_result_str);
|
||||
}
|
||||
|
||||
let shared_secret_hex = dh_result_str
|
||||
.chars()
|
||||
.skip("ok:SharedSecret:".len())
|
||||
.collect::<String>();
|
||||
let shared_secret_hex = shared_secret_hex.trim();
|
||||
|
||||
Ok(opt_result!(
|
||||
hex::decode(shared_secret_hex),
|
||||
"Decrypt shared secret hex: {}, failed: {}",
|
||||
shared_secret_hex
|
||||
))
|
||||
let private_key_representation = STANDARD.decode(private_key)?;
|
||||
let shared_secret = swift_secure_enclave_tool_rs::private_key_ecdh(
|
||||
&private_key_representation,
|
||||
ephemeral_public_key_bytes,
|
||||
)?;
|
||||
Ok(shared_secret)
|
||||
}
|
||||
|
||||
pub fn secure_enclave_p256_sign(private_key: &str, content: &[u8]) -> XResult<Vec<u8>> {
|
||||
let signature_result = unsafe {
|
||||
compute_secure_enclave_p256_ecsign(
|
||||
SRString::from(private_key),
|
||||
SRString::from(base64_encode(content).as_str()),
|
||||
)
|
||||
};
|
||||
let signature_result_str = signature_result.as_str();
|
||||
debugging!("Signature result: {}", &signature_result_str);
|
||||
if !signature_result_str.starts_with("ok:") {
|
||||
return simple_error!(
|
||||
"Sign P256 in secure enclave failed: {}",
|
||||
signature_result_str
|
||||
);
|
||||
}
|
||||
let signature = signature_result_str.chars().skip(3).collect::<String>();
|
||||
debugging!("Signature: {}", &signature);
|
||||
Ok(base64_decode(&signature)?)
|
||||
}
|
||||
|
||||
fn parse_p256_keypair_result(p256_keypair_result_str: &str) -> XResult<(Vec<u8>, Vec<u8>, String)> {
|
||||
if !p256_keypair_result_str.starts_with("ok:") {
|
||||
return simple_error!(
|
||||
"Generate P256 in secure enclave failed: {}",
|
||||
p256_keypair_result_str
|
||||
);
|
||||
}
|
||||
let public_key_and_private_key = p256_keypair_result_str.chars().skip(3).collect::<String>();
|
||||
let public_key_and_private_keys = public_key_and_private_key.split(',').collect::<Vec<_>>();
|
||||
if public_key_and_private_keys.len() != 3 {
|
||||
return simple_error!(
|
||||
"Generate P256 in secure enclave result is bad: {}",
|
||||
public_key_and_private_key
|
||||
);
|
||||
}
|
||||
let public_key_point = opt_result!(
|
||||
base64_decode(public_key_and_private_keys[0]),
|
||||
"Public key point is not base64 encoded: {}"
|
||||
);
|
||||
let public_key_der = opt_result!(
|
||||
base64_decode(public_key_and_private_keys[1]),
|
||||
"Public key der is not base64 encoded: {}"
|
||||
);
|
||||
let private_key = public_key_and_private_keys[2].to_string();
|
||||
Ok((public_key_point, public_key_der, private_key))
|
||||
let private_key_representation = STANDARD.decode(private_key)?;
|
||||
let signature =
|
||||
swift_secure_enclave_tool_rs::private_key_ecdsa_sign(&private_key_representation, content)?;
|
||||
Ok(signature)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user