use std::fmt;
use std::ops::{BitAnd, BitOr};
#[cfg(test)]
use quickcheck::{Arbitrary, Gen};
use crate::types::Bitfield;
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct KeyFlags(Bitfield);
assert_send_and_sync!(KeyFlags);
impl fmt::Debug for KeyFlags {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
if self.for_certification() {
f.write_str("C")?;
}
if self.for_signing() {
f.write_str("S")?;
}
if self.for_transport_encryption() {
f.write_str("Et")?;
}
if self.for_storage_encryption() {
f.write_str("Er")?;
}
if self.for_authentication() {
f.write_str("A")?;
}
if self.is_split_key() {
f.write_str("D")?;
}
if self.is_group_key() {
f.write_str("G")?;
}
let mut need_comma = false;
for i in self.0.iter_set() {
match i {
KEY_FLAG_CERTIFY
| KEY_FLAG_SIGN
| KEY_FLAG_ENCRYPT_FOR_TRANSPORT
| KEY_FLAG_ENCRYPT_AT_REST
| KEY_FLAG_SPLIT_KEY
| KEY_FLAG_AUTHENTICATE
| KEY_FLAG_GROUP_KEY
=> (),
i => {
if need_comma { f.write_str(", ")?; }
write!(f, "#{}", i)?;
need_comma = true;
},
}
}
if let Some(padding) = self.0.padding_bytes() {
if need_comma { f.write_str(", ")?; }
write!(f, "+padding({} bytes)", padding)?;
}
Ok(())
}
}
impl BitAnd for &KeyFlags {
type Output = KeyFlags;
fn bitand(self, rhs: Self) -> KeyFlags {
let l = self.as_bitfield().as_bytes();
let r = rhs.as_bitfield().as_bytes();
let mut c = Vec::with_capacity(std::cmp::min(l.len(), r.len()));
for (l, r) in l.iter().zip(r.iter()) {
c.push(l & r);
}
KeyFlags(c.into())
}
}
impl BitOr for &KeyFlags {
type Output = KeyFlags;
fn bitor(self, rhs: Self) -> KeyFlags {
let l = self.as_bitfield().as_bytes();
let r = rhs.as_bitfield().as_bytes();
let (l, r) = if l.len() > r.len() {
(l, r)
} else {
(r, l)
};
let mut l = l.to_vec();
for (i, r) in r.iter().enumerate() {
l[i] |= r;
}
KeyFlags(l.into())
}
}
impl AsRef<KeyFlags> for KeyFlags {
fn as_ref(&self) -> &KeyFlags {
self
}
}
impl KeyFlags {
pub fn new<B: AsRef<[u8]>>(bits: B) -> Self {
Self(bits.as_ref().to_vec().into())
}
pub fn empty() -> Self {
KeyFlags::new(&[])
}
pub fn as_bitfield(&self) -> &Bitfield {
&self.0
}
pub fn as_bitfield_mut(&mut self) -> &mut Bitfield {
&mut self.0
}
pub fn normalized_eq(&self, other: &Self) -> bool {
self.0.normalized_eq(&other.0)
}
pub fn get(&self, bit: usize) -> bool {
self.0.get(bit)
}
pub fn set(mut self, bit: usize) -> Self {
self.0.set(bit);
self.0.canonicalize();
self
}
pub fn clear(mut self, bit: usize) -> Self {
self.0.clear(bit);
self.0.canonicalize();
self
}
pub fn for_certification(&self) -> bool {
self.get(KEY_FLAG_CERTIFY)
}
pub fn certification() -> Self {
KeyFlags::empty().set_certification()
}
pub fn set_certification(self) -> Self {
self.set(KEY_FLAG_CERTIFY)
}
pub fn clear_certification(self) -> Self {
self.clear(KEY_FLAG_CERTIFY)
}
pub fn set_certification_to(self, value: bool) -> Self {
if value {
self.set(KEY_FLAG_CERTIFY)
} else {
self.clear(KEY_FLAG_CERTIFY)
}
}
pub fn for_signing(&self) -> bool {
self.get(KEY_FLAG_SIGN)
}
pub fn signing() -> Self {
KeyFlags::empty().set_signing()
}
pub fn set_signing(self) -> Self {
self.set(KEY_FLAG_SIGN)
}
pub fn clear_signing(self) -> Self {
self.clear(KEY_FLAG_SIGN)
}
pub fn set_signing_to(self, value: bool) -> Self {
if value {
self.set(KEY_FLAG_SIGN)
} else {
self.clear(KEY_FLAG_SIGN)
}
}
pub fn for_transport_encryption(&self) -> bool {
self.get(KEY_FLAG_ENCRYPT_FOR_TRANSPORT)
}
pub fn transport_encryption() -> Self {
KeyFlags::empty().set_transport_encryption()
}
pub fn set_transport_encryption(self) -> Self {
self.set(KEY_FLAG_ENCRYPT_FOR_TRANSPORT)
}
pub fn clear_transport_encryption(self) -> Self {
self.clear(KEY_FLAG_ENCRYPT_FOR_TRANSPORT)
}
pub fn set_transport_encryption_to(self, value: bool) -> Self {
if value {
self.set(KEY_FLAG_ENCRYPT_FOR_TRANSPORT)
} else {
self.clear(KEY_FLAG_ENCRYPT_FOR_TRANSPORT)
}
}
pub fn for_storage_encryption(&self) -> bool {
self.get(KEY_FLAG_ENCRYPT_AT_REST)
}
pub fn storage_encryption() -> Self {
KeyFlags::empty().set_storage_encryption()
}
pub fn set_storage_encryption(self) -> Self {
self.set(KEY_FLAG_ENCRYPT_AT_REST)
}
pub fn clear_storage_encryption(self) -> Self {
self.clear(KEY_FLAG_ENCRYPT_AT_REST)
}
pub fn set_storage_encryption_to(self, value: bool) -> Self {
if value {
self.set(KEY_FLAG_ENCRYPT_AT_REST)
} else {
self.clear(KEY_FLAG_ENCRYPT_AT_REST)
}
}
pub fn for_authentication(&self) -> bool {
self.get(KEY_FLAG_AUTHENTICATE)
}
pub fn authentication() -> Self {
KeyFlags::empty().set_authentication()
}
pub fn set_authentication(self) -> Self {
self.set(KEY_FLAG_AUTHENTICATE)
}
pub fn clear_authentication(self) -> Self {
self.clear(KEY_FLAG_AUTHENTICATE)
}
pub fn set_authentication_to(self, value: bool) -> Self {
if value {
self.set(KEY_FLAG_AUTHENTICATE)
} else {
self.clear(KEY_FLAG_AUTHENTICATE)
}
}
pub fn is_split_key(&self) -> bool {
self.get(KEY_FLAG_SPLIT_KEY)
}
pub fn split_key() -> Self {
KeyFlags::empty().set_split_key()
}
pub fn set_split_key(self) -> Self {
self.set(KEY_FLAG_SPLIT_KEY)
}
pub fn clear_split_key(self) -> Self {
self.clear(KEY_FLAG_SPLIT_KEY)
}
pub fn set_split_key_to(self, value: bool) -> Self {
if value {
self.set(KEY_FLAG_SPLIT_KEY)
} else {
self.clear(KEY_FLAG_SPLIT_KEY)
}
}
pub fn is_group_key(&self) -> bool {
self.get(KEY_FLAG_GROUP_KEY)
}
pub fn group_key() -> Self {
KeyFlags::empty().set_group_key()
}
pub fn set_group_key(self) -> Self {
self.set(KEY_FLAG_GROUP_KEY)
}
pub fn clear_group_key(self) -> Self {
self.clear(KEY_FLAG_GROUP_KEY)
}
pub fn set_group_key_to(self, value: bool) -> Self {
if value {
self.set(KEY_FLAG_GROUP_KEY)
} else {
self.clear(KEY_FLAG_GROUP_KEY)
}
}
pub fn is_empty(&self) -> bool {
self.as_bitfield().as_bytes().iter().all(|b| *b == 0)
}
}
const KEY_FLAG_CERTIFY: usize = 0;
const KEY_FLAG_SIGN: usize = 1;
const KEY_FLAG_ENCRYPT_FOR_TRANSPORT: usize = 2;
const KEY_FLAG_ENCRYPT_AT_REST: usize = 3;
const KEY_FLAG_SPLIT_KEY: usize = 4;
const KEY_FLAG_AUTHENTICATE: usize = 5;
const KEY_FLAG_GROUP_KEY: usize = 7;
#[cfg(test)]
impl Arbitrary for KeyFlags {
fn arbitrary(g: &mut Gen) -> Self {
Self::new(Vec::arbitrary(g))
}
}
#[cfg(test)]
mod tests {
use super::*;
quickcheck! {
fn roundtrip(val: KeyFlags) -> bool {
let mut q_bytes = val.as_bitfield().as_bytes().to_vec();
let q = KeyFlags::new(&q_bytes);
assert_eq!(val, q);
assert!(val.normalized_eq(&q));
q_bytes.push(0);
let q = KeyFlags::new(&q_bytes);
assert!(val != q);
assert!(val.normalized_eq(&q));
q_bytes.push(0);
let q = KeyFlags::new(&q_bytes);
assert!(val != q);
assert!(val.normalized_eq(&q));
true
}
}
#[test]
fn test_set_to() {
macro_rules! t {
($set:ident, $set2:ident) => {
assert_eq!(KeyFlags::empty().$set(),
KeyFlags::empty().$set2(true));
assert_eq!(KeyFlags::empty().$set2(false),
KeyFlags::empty());
assert_eq!(KeyFlags::empty().$set().$set2(false),
KeyFlags::empty());
}
}
t!(set_certification, set_certification_to);
t!(set_signing, set_signing_to);
t!(set_transport_encryption, set_transport_encryption_to);
t!(set_storage_encryption, set_storage_encryption_to);
t!(set_split_key, set_split_key_to);
t!(set_group_key, set_group_key_to);
}
}