use std::fmt;
use std::cmp;
use std::ops::{BitAnd, BitOr};
#[derive(Clone)]
pub struct KeyFlags{
can_certify: bool,
can_sign: bool,
can_encrypt_for_transport: bool,
can_encrypt_at_rest: bool,
can_authenticate: bool,
is_split_key: bool,
is_group_key: bool,
unknown: Box<[u8]>,
}
impl Default for KeyFlags {
fn default() -> Self {
KeyFlags::new(&vec![0])
}
}
impl fmt::Debug for KeyFlags {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
if self.can_certify() {
f.write_str("C")?;
}
if self.can_sign() {
f.write_str("S")?;
}
if self.can_encrypt_for_transport() {
f.write_str("Et")?;
}
if self.can_encrypt_at_rest() {
f.write_str("Er")?;
}
if self.can_authenticate() {
f.write_str("A")?;
}
if self.is_split_key() {
f.write_str("S")?;
}
if self.is_group_key() {
f.write_str("G")?;
}
Ok(())
}
}
impl PartialEq for KeyFlags {
fn eq(&self, other: &Self) -> bool {
self.partial_cmp(other) == Some(cmp::Ordering::Equal)
}
}
impl Eq for KeyFlags {}
impl PartialOrd for KeyFlags {
fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
let mut a_bits = self.as_vec();
let mut b_bits = other.as_vec();
let len = cmp::max(a_bits.len(), b_bits.len());
while a_bits.len() < len { a_bits.push(0); }
while b_bits.len() < len { b_bits.push(0); }
if a_bits == b_bits {
Some(cmp::Ordering::Equal)
} else if a_bits.iter().zip(b_bits.iter()).all(|(a,b)| a & b == *a) {
Some(cmp::Ordering::Less)
} else if a_bits.iter().zip(b_bits.iter()).all(|(a,b)| a & b == *b) {
Some(cmp::Ordering::Greater)
} else {
None
}
}
}
impl BitAnd for &KeyFlags {
type Output = KeyFlags;
fn bitand(self, rhs: Self) -> KeyFlags {
let l = self.as_vec();
let r = rhs.as_vec();
let mut c = Vec::with_capacity(cmp::min(l.len(), r.len()));
for (l, r) in l.into_iter().zip(r.into_iter()) {
c.push(l & r);
}
KeyFlags::new(&c[..])
}
}
impl BitOr for &KeyFlags {
type Output = KeyFlags;
fn bitor(self, rhs: Self) -> KeyFlags {
let l = self.as_vec();
let r = rhs.as_vec();
let (mut l, r) = if l.len() > r.len() {
(l, r)
} else {
(r, l)
};
for (i, r) in r.into_iter().enumerate() {
l[i] = l[i] | r;
}
KeyFlags::new(&l[..])
}
}
impl KeyFlags {
pub fn new(bits: &[u8]) -> Self {
let can_certify = bits.get(0)
.map(|x| x & KEY_FLAG_CERTIFY != 0).unwrap_or(false);
let can_sign = bits.get(0)
.map(|x| x & KEY_FLAG_SIGN != 0).unwrap_or(false);
let can_encrypt_for_transport = bits.get(0)
.map(|x| x & KEY_FLAG_ENCRYPT_FOR_TRANSPORT != 0).unwrap_or(false);
let can_encrypt_at_rest = bits.get(0)
.map(|x| x & KEY_FLAG_ENCRYPT_AT_REST != 0).unwrap_or(false);
let can_authenticate = bits.get(0)
.map(|x| x & KEY_FLAG_AUTHENTICATE != 0).unwrap_or(false);
let is_split_key = bits.get(0)
.map(|x| x & KEY_FLAG_SPLIT_KEY != 0).unwrap_or(false);
let is_group_key = bits.get(0)
.map(|x| x & KEY_FLAG_GROUP_KEY != 0).unwrap_or(false);
let unk = if bits.is_empty() {
Box::default()
} else {
let mut cpy = Vec::from(bits);
cpy[0] &= (
KEY_FLAG_ENCRYPT_AT_REST | KEY_FLAG_ENCRYPT_FOR_TRANSPORT |
KEY_FLAG_SIGN | KEY_FLAG_CERTIFY | KEY_FLAG_AUTHENTICATE |
KEY_FLAG_GROUP_KEY | KEY_FLAG_SPLIT_KEY
) ^ 0xff;
while cpy.last().cloned() == Some(0) { cpy.pop(); }
cpy.into_boxed_slice()
};
KeyFlags{
can_certify, can_sign, can_encrypt_for_transport,
can_encrypt_at_rest, can_authenticate, is_split_key,
is_group_key, unknown: unk
}
}
pub fn empty() -> Self {
KeyFlags::default()
}
pub(crate) fn as_vec(&self) -> Vec<u8> {
let mut ret = if self.unknown.is_empty() {
vec![0]
} else {
self.unknown.clone().into()
};
if self.can_certify { ret[0] |= KEY_FLAG_CERTIFY; }
if self.can_sign { ret[0] |= KEY_FLAG_SIGN; }
if self.can_encrypt_for_transport { ret[0] |= KEY_FLAG_ENCRYPT_FOR_TRANSPORT; }
if self.can_encrypt_at_rest { ret[0] |= KEY_FLAG_ENCRYPT_AT_REST; }
if self.can_authenticate { ret[0] |= KEY_FLAG_AUTHENTICATE; }
if self.is_split_key { ret[0] |= KEY_FLAG_SPLIT_KEY; }
if self.is_group_key { ret[0] |= KEY_FLAG_GROUP_KEY }
ret
}
pub fn can_certify(&self) -> bool { self.can_certify }
pub fn set_certify(mut self, v: bool) -> Self {
self.can_certify = v;
self
}
pub fn can_sign(&self) -> bool { self.can_sign }
pub fn set_sign(mut self, v: bool) -> Self {
self.can_sign = v;
self
}
pub fn can_encrypt_for_transport(&self) -> bool {
self.can_encrypt_for_transport
}
pub fn set_encrypt_for_transport(mut self, v: bool) -> Self {
self.can_encrypt_for_transport = v;
self
}
pub fn can_encrypt_at_rest(&self) -> bool { self.can_encrypt_at_rest }
pub fn set_encrypt_at_rest(mut self, v: bool) -> Self {
self.can_encrypt_at_rest = v;
self
}
pub fn can_authenticate(&self) -> bool {
self.can_authenticate
}
pub fn set_authenticate(mut self, v: bool) -> Self {
self.can_authenticate = v;
self
}
pub fn is_split_key(&self) -> bool {
self.is_split_key
}
pub fn set_split_key(mut self, v: bool) -> Self {
self.is_split_key = v;
self
}
pub fn is_group_key(&self) -> bool {
self.is_group_key
}
pub fn set_group_key(mut self, v: bool) -> Self {
self.is_group_key = v;
self
}
pub fn is_empty(&self) -> bool {
self.as_vec().into_iter().all(|b| b == 0)
}
}
const KEY_FLAG_CERTIFY: u8 = 0x01;
const KEY_FLAG_SIGN: u8 = 0x02;
const KEY_FLAG_ENCRYPT_FOR_TRANSPORT: u8 = 0x04;
const KEY_FLAG_ENCRYPT_AT_REST: u8 = 0x08;
const KEY_FLAG_SPLIT_KEY: u8 = 0x10;
const KEY_FLAG_AUTHENTICATE: u8 = 0x20;
const KEY_FLAG_GROUP_KEY: u8 = 0x80;
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn ordering() {
let nothing = KeyFlags::default();
let enc = KeyFlags::default()
.set_encrypt_for_transport(true)
.set_encrypt_at_rest(true);
let sig = KeyFlags::default()
.set_sign(true);
let enc_and_auth = KeyFlags::default()
.set_encrypt_for_transport(true)
.set_encrypt_at_rest(true)
.set_authenticate(true);
assert!(nothing < enc);
assert!(sig >= nothing);
assert!(nothing <= enc);
assert!(enc < enc_and_auth);
assert!(enc_and_auth >= enc_and_auth);
assert!(enc <= enc_and_auth);
assert!(enc_and_auth >= enc);
assert!(!(enc < sig));
assert!(!(enc > sig));
}
}