Pad private key scalars of ECC keys.
MPIs can have leading zeros stripped, in OpenPGP, however, e.g. the floss34 card requires the NIST scalar in its non-stripped form.
This commit is contained in:
parent
c73a4fa2f8
commit
1ce74ab8c6
3 changed files with 37 additions and 30 deletions
|
@ -20,6 +20,9 @@ use openpgp_card::crypto_data::{
|
||||||
CardUploadableKey, EccKey, EccType, PrivateKeyMaterial, RSAKey,
|
CardUploadableKey, EccKey, EccType, PrivateKeyMaterial, RSAKey,
|
||||||
};
|
};
|
||||||
use openpgp_card::Error;
|
use openpgp_card::Error;
|
||||||
|
use sequoia_openpgp::types::Curve;
|
||||||
|
|
||||||
|
use crate::util;
|
||||||
|
|
||||||
/// A SequoiaKey represents the private cryptographic key material of an
|
/// A SequoiaKey represents the private cryptographic key material of an
|
||||||
/// OpenPGP (sub)key to be uploaded to an OpenPGP card.
|
/// OpenPGP (sub)key to be uploaded to an OpenPGP card.
|
||||||
|
@ -83,12 +86,7 @@ impl CardUploadableKey for SequoiaKey {
|
||||||
mpi::PublicKey::ECDH { curve, q, .. },
|
mpi::PublicKey::ECDH { curve, q, .. },
|
||||||
mpi::SecretKeyMaterial::ECDH { scalar },
|
mpi::SecretKeyMaterial::ECDH { scalar },
|
||||||
) => {
|
) => {
|
||||||
let sq_ecc = SqEccKey::new(
|
let sq_ecc = SqEccKey::new(curve, scalar, q, EccType::ECDH);
|
||||||
curve.oid().to_vec(),
|
|
||||||
scalar,
|
|
||||||
q,
|
|
||||||
EccType::ECDH,
|
|
||||||
);
|
|
||||||
|
|
||||||
Ok(PrivateKeyMaterial::E(Box::new(sq_ecc)))
|
Ok(PrivateKeyMaterial::E(Box::new(sq_ecc)))
|
||||||
}
|
}
|
||||||
|
@ -96,12 +94,7 @@ impl CardUploadableKey for SequoiaKey {
|
||||||
mpi::PublicKey::ECDSA { curve, q, .. },
|
mpi::PublicKey::ECDSA { curve, q, .. },
|
||||||
mpi::SecretKeyMaterial::ECDSA { scalar },
|
mpi::SecretKeyMaterial::ECDSA { scalar },
|
||||||
) => {
|
) => {
|
||||||
let sq_ecc = SqEccKey::new(
|
let sq_ecc = SqEccKey::new(curve, scalar, q, EccType::ECDSA);
|
||||||
curve.oid().to_vec(),
|
|
||||||
scalar,
|
|
||||||
q,
|
|
||||||
EccType::ECDSA,
|
|
||||||
);
|
|
||||||
|
|
||||||
Ok(PrivateKeyMaterial::E(Box::new(sq_ecc)))
|
Ok(PrivateKeyMaterial::E(Box::new(sq_ecc)))
|
||||||
}
|
}
|
||||||
|
@ -109,19 +102,13 @@ impl CardUploadableKey for SequoiaKey {
|
||||||
mpi::PublicKey::EdDSA { curve, q, .. },
|
mpi::PublicKey::EdDSA { curve, q, .. },
|
||||||
mpi::SecretKeyMaterial::EdDSA { scalar },
|
mpi::SecretKeyMaterial::EdDSA { scalar },
|
||||||
) => {
|
) => {
|
||||||
let sq_ecc = SqEccKey::new(
|
let sq_ecc = SqEccKey::new(curve, scalar, q, EccType::EdDSA);
|
||||||
curve.oid().to_vec(),
|
|
||||||
scalar,
|
|
||||||
q,
|
|
||||||
EccType::EdDSA,
|
|
||||||
);
|
|
||||||
|
|
||||||
Ok(PrivateKeyMaterial::E(Box::new(sq_ecc)))
|
Ok(PrivateKeyMaterial::E(Box::new(sq_ecc)))
|
||||||
}
|
}
|
||||||
(p, s) => {
|
(p, s) => {
|
||||||
unimplemented!(
|
unimplemented!(
|
||||||
"Unexpected algorithms: public {:?}, \
|
"Unexpected algorithms: public {:?}, secret {:?}",
|
||||||
secret {:?}",
|
|
||||||
p,
|
p,
|
||||||
s
|
s
|
||||||
);
|
);
|
||||||
|
@ -208,7 +195,7 @@ impl RSAKey for SqRSA {
|
||||||
/// ECC-specific data-structure to hold private (sub)key material for upload
|
/// ECC-specific data-structure to hold private (sub)key material for upload
|
||||||
/// with the `openpgp-card` crate.
|
/// with the `openpgp-card` crate.
|
||||||
struct SqEccKey {
|
struct SqEccKey {
|
||||||
oid: Vec<u8>,
|
curve: Curve,
|
||||||
private: ProtectedMPI,
|
private: ProtectedMPI,
|
||||||
public: MPI,
|
public: MPI,
|
||||||
ecc_type: EccType,
|
ecc_type: EccType,
|
||||||
|
@ -216,13 +203,13 @@ struct SqEccKey {
|
||||||
|
|
||||||
impl SqEccKey {
|
impl SqEccKey {
|
||||||
fn new(
|
fn new(
|
||||||
oid: Vec<u8>,
|
curve: Curve,
|
||||||
private: ProtectedMPI,
|
private: ProtectedMPI,
|
||||||
public: MPI,
|
public: MPI,
|
||||||
ecc_type: EccType,
|
ecc_type: EccType,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
SqEccKey {
|
SqEccKey {
|
||||||
oid,
|
curve,
|
||||||
private,
|
private,
|
||||||
public,
|
public,
|
||||||
ecc_type,
|
ecc_type,
|
||||||
|
@ -232,15 +219,22 @@ impl SqEccKey {
|
||||||
|
|
||||||
impl EccKey for SqEccKey {
|
impl EccKey for SqEccKey {
|
||||||
fn get_oid(&self) -> &[u8] {
|
fn get_oid(&self) -> &[u8] {
|
||||||
&self.oid
|
self.curve.oid()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_private(&self) -> &[u8] {
|
fn get_private(&self) -> Vec<u8> {
|
||||||
self.private.value()
|
// FIXME: padding for 25519?
|
||||||
|
match self.curve {
|
||||||
|
Curve::NistP256 => util::left_zero_pad(self.private.value(), 0x20),
|
||||||
|
Curve::NistP384 => util::left_zero_pad(self.private.value(), 0x30),
|
||||||
|
Curve::NistP521 => util::left_zero_pad(self.private.value(), 0x42),
|
||||||
|
_ => self.private.value().to_vec(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_public(&self) -> &[u8] {
|
fn get_public(&self) -> Vec<u8> {
|
||||||
self.public.value()
|
// FIXME: padding?
|
||||||
|
self.public.value().to_vec()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_type(&self) -> EccType {
|
fn get_type(&self) -> EccType {
|
||||||
|
|
|
@ -305,3 +305,16 @@ pub fn decrypt(
|
||||||
|
|
||||||
Ok(decrypted)
|
Ok(decrypted)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// This fn prepends zeros to `value` so that the resulting Vec<u8> has
|
||||||
|
/// len `size`.
|
||||||
|
///
|
||||||
|
/// (Leading zero-bytes may be stripped from MPIs, this fn is a helper for
|
||||||
|
/// re-creating the non-stripped representation of an MPI)
|
||||||
|
pub(crate) fn left_zero_pad(value: &[u8], size: usize) -> Vec<u8> {
|
||||||
|
let pad = size - value.len();
|
||||||
|
let mut res = vec![0; pad];
|
||||||
|
res.extend_from_slice(value);
|
||||||
|
|
||||||
|
res
|
||||||
|
}
|
||||||
|
|
|
@ -100,8 +100,8 @@ pub trait RSAKey {
|
||||||
/// card.
|
/// card.
|
||||||
pub trait EccKey {
|
pub trait EccKey {
|
||||||
fn get_oid(&self) -> &[u8];
|
fn get_oid(&self) -> &[u8];
|
||||||
fn get_private(&self) -> &[u8];
|
fn get_private(&self) -> Vec<u8>;
|
||||||
fn get_public(&self) -> &[u8];
|
fn get_public(&self) -> Vec<u8>;
|
||||||
fn get_type(&self) -> EccType;
|
fn get_type(&self) -> EccType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue