Cleanup Tlv, Tag, Value:
- Make Tlv/Tag fields private. - Rename TlvEntry to Value. - impl TryFrom<&[u8]> for Tlv
This commit is contained in:
parent
821b5f0dae
commit
c25c8b55b8
6 changed files with 153 additions and 146 deletions
|
@ -17,7 +17,7 @@ use crate::crypto_data::{
|
|||
CardUploadableKey, Cryptogram, EccType, Hash, PublicKeyMaterial,
|
||||
};
|
||||
use crate::errors::OpenpgpCardError;
|
||||
use crate::tlv::{tag::Tag, Tlv, TlvEntry};
|
||||
use crate::tlv::{tag::Tag, Tlv, Value};
|
||||
use crate::{apdu, keys, CardCaps, CardClientBox, KeyType};
|
||||
|
||||
/// Low-level access to OpenPGP card functionality.
|
||||
|
@ -103,11 +103,11 @@ impl CardApp {
|
|||
pub fn get_app_data(&mut self) -> Result<ApplicationRelatedData> {
|
||||
let ad = commands::get_application_data();
|
||||
let resp = apdu::send_command(&mut self.card_client, ad, true)?;
|
||||
let entry = TlvEntry::from(resp.data()?, true)?;
|
||||
let value = Value::from(resp.data()?, true)?;
|
||||
|
||||
log::debug!(" App data TlvEntry: {:x?}", entry);
|
||||
log::debug!(" App data Value: {:x?}", value);
|
||||
|
||||
Ok(ApplicationRelatedData(Tlv(Tag::from([0x6E]), entry)))
|
||||
Ok(ApplicationRelatedData(Tlv::new(Tag::from([0x6E]), value)))
|
||||
}
|
||||
|
||||
/// Get data from "private use" DO.
|
||||
|
@ -180,11 +180,11 @@ impl CardApp {
|
|||
resp.check_ok()?;
|
||||
|
||||
let tlv = Tlv::try_from(resp.data()?)?;
|
||||
let res = tlv.find(&Tag::from([0x93])).ok_or_else(|| {
|
||||
let res = tlv.find(&[0x93].into()).ok_or_else(|| {
|
||||
anyhow!("Couldn't get SecuritySupportTemplate DO")
|
||||
})?;
|
||||
|
||||
if let TlvEntry::S(data) = res {
|
||||
if let Value::S(data) = res {
|
||||
let mut data = data.to_vec();
|
||||
assert_eq!(data.len(), 3);
|
||||
|
||||
|
@ -227,9 +227,9 @@ impl CardApp {
|
|||
num: u8,
|
||||
tag: &[u8],
|
||||
) -> Result<Response, OpenpgpCardError> {
|
||||
let tlv = Tlv(
|
||||
Tag(vec![0x60]),
|
||||
TlvEntry::C(vec![Tlv(Tag(vec![0x5c]), TlvEntry::S(tag.to_vec()))]),
|
||||
let tlv = Tlv::new(
|
||||
[0x60],
|
||||
Value::C(vec![Tlv::new([0x5c], Value::S(tag.to_vec()))]),
|
||||
);
|
||||
|
||||
let data = tlv.serialize();
|
||||
|
@ -342,13 +342,13 @@ impl CardApp {
|
|||
}
|
||||
Cryptogram::ECDH(eph) => {
|
||||
// External Public Key
|
||||
let epk = Tlv(Tag(vec![0x86]), TlvEntry::S(eph.to_vec()));
|
||||
let epk = Tlv::new([0x86], Value::S(eph.to_vec()));
|
||||
|
||||
// Public Key DO
|
||||
let pkdo = Tlv(Tag(vec![0x7f, 0x49]), TlvEntry::C(vec![epk]));
|
||||
let pkdo = Tlv::new([0x7f, 0x49], Value::C(vec![epk]));
|
||||
|
||||
// Cipher DO
|
||||
let cdo = Tlv(Tag(vec![0xa6]), TlvEntry::C(vec![pkdo]));
|
||||
let cdo = Tlv::new([0xa6], Value::C(vec![pkdo]));
|
||||
|
||||
self.pso_decipher(cdo.serialize())
|
||||
}
|
||||
|
@ -378,24 +378,21 @@ impl CardApp {
|
|||
) -> Result<Vec<u8>, OpenpgpCardError> {
|
||||
let data = match hash {
|
||||
Hash::SHA256(_) | Hash::SHA384(_) | Hash::SHA512(_) => {
|
||||
let tlv = Tlv(
|
||||
Tag(vec![0x30]),
|
||||
TlvEntry::C(vec![
|
||||
Tlv(
|
||||
Tag(vec![0x30]),
|
||||
TlvEntry::C(vec![
|
||||
Tlv(
|
||||
Tag(vec![0x06]),
|
||||
let tlv = Tlv::new(
|
||||
[0x30],
|
||||
Value::C(vec![
|
||||
Tlv::new(
|
||||
[0x30],
|
||||
Value::C(vec![
|
||||
Tlv::new(
|
||||
[0x06],
|
||||
// unwrapping is ok, for SHA*
|
||||
TlvEntry::S(hash.oid().unwrap().to_vec()),
|
||||
Value::S(hash.oid().unwrap().to_vec()),
|
||||
),
|
||||
Tlv(Tag(vec![0x05]), TlvEntry::S(vec![])),
|
||||
Tlv::new([0x05], Value::S(vec![])),
|
||||
]),
|
||||
),
|
||||
Tlv(
|
||||
Tag(vec![0x04]),
|
||||
TlvEntry::S(hash.digest().to_vec()),
|
||||
),
|
||||
Tlv::new([0x04], Value::S(hash.digest().to_vec())),
|
||||
]),
|
||||
);
|
||||
|
||||
|
|
|
@ -6,8 +6,7 @@ use std::convert::TryFrom;
|
|||
use anyhow::Result;
|
||||
|
||||
use crate::card_do::{Cardholder, Sex};
|
||||
use crate::tlv::tag::Tag;
|
||||
use crate::tlv::{Tlv, TlvEntry};
|
||||
use crate::tlv::{Tlv, Value};
|
||||
|
||||
impl Cardholder {
|
||||
pub fn name(&self) -> Option<&str> {
|
||||
|
@ -27,15 +26,15 @@ impl TryFrom<&[u8]> for Cardholder {
|
|||
type Error = anyhow::Error;
|
||||
|
||||
fn try_from(data: &[u8]) -> Result<Self> {
|
||||
let entry = TlvEntry::from(data, true)?;
|
||||
let tlv = Tlv(Tag(vec![0x65]), entry);
|
||||
let value = Value::from(data, true)?;
|
||||
let tlv = Tlv::new([0x65], value);
|
||||
|
||||
let name: Option<String> = tlv
|
||||
.find(&Tag::from(&[0x5b][..]))
|
||||
.find(&[0x5b].into())
|
||||
.map(|v| String::from_utf8_lossy(&v.serialize()).to_string());
|
||||
|
||||
let lang: Option<Vec<[char; 2]>> =
|
||||
tlv.find(&Tag::from(&[0x5f, 0x2d][..])).map(|v| {
|
||||
tlv.find(&[0x5f, 0x2d].into()).map(|v| {
|
||||
v.serialize()
|
||||
.chunks(2)
|
||||
.map(|c| [c[0] as char, c[1] as char])
|
||||
|
@ -43,7 +42,7 @@ impl TryFrom<&[u8]> for Cardholder {
|
|||
});
|
||||
|
||||
let sex = tlv
|
||||
.find(&Tag::from(&[0x5f, 0x35][..]))
|
||||
.find(&[0x5f, 0x35].into())
|
||||
.map(|v| v.serialize())
|
||||
.filter(|v| v.len() == 1)
|
||||
.map(|v| Sex::from(v[0]));
|
||||
|
|
|
@ -10,7 +10,7 @@ use std::convert::TryInto;
|
|||
|
||||
use crate::algorithm::Algo;
|
||||
use crate::errors::OpenpgpCardError;
|
||||
use crate::tlv::{tag::Tag, Tlv};
|
||||
use crate::tlv::Tlv;
|
||||
use crate::KeyType;
|
||||
|
||||
mod algo_attrs;
|
||||
|
@ -38,7 +38,7 @@ impl ApplicationRelatedData {
|
|||
/// Application identifier (AID), ISO 7816-4
|
||||
pub fn get_aid(&self) -> Result<ApplicationId, OpenpgpCardError> {
|
||||
// get from cached "application related data"
|
||||
let aid = self.0.find(&Tag::from([0x4F]));
|
||||
let aid = self.0.find(&[0x4f].into());
|
||||
|
||||
if let Some(aid) = aid {
|
||||
Ok(ApplicationId::try_from(&aid.serialize()[..])?)
|
||||
|
@ -50,7 +50,7 @@ impl ApplicationRelatedData {
|
|||
/// Historical bytes
|
||||
pub fn get_historical(&self) -> Result<Historical, OpenpgpCardError> {
|
||||
// get from cached "application related data"
|
||||
let hist = self.0.find(&Tag::from([0x5F, 0x52]));
|
||||
let hist = self.0.find(&[0x5f, 0x52].into());
|
||||
|
||||
if let Some(hist) = hist {
|
||||
log::debug!("Historical bytes: {:x?}", hist);
|
||||
|
@ -66,7 +66,7 @@ impl ApplicationRelatedData {
|
|||
&self,
|
||||
) -> Result<Option<ExtendedLengthInfo>> {
|
||||
// get from cached "application related data"
|
||||
let eli = self.0.find(&Tag::from([0x7F, 0x66]));
|
||||
let eli = self.0.find(&[0x7f, 0x66].into());
|
||||
|
||||
log::debug!("Extended length information: {:x?}", eli);
|
||||
|
||||
|
@ -92,7 +92,7 @@ impl ApplicationRelatedData {
|
|||
&self,
|
||||
) -> Result<ExtendedCap, OpenpgpCardError> {
|
||||
// get from cached "application related data"
|
||||
let ecap = self.0.find(&Tag::from([0xc0]));
|
||||
let ecap = self.0.find(&[0xc0].into());
|
||||
|
||||
if let Some(ecap) = ecap {
|
||||
Ok(ExtendedCap::try_from(&ecap.serialize()[..])?)
|
||||
|
@ -104,7 +104,7 @@ impl ApplicationRelatedData {
|
|||
/// Algorithm attributes (for each key type)
|
||||
pub fn get_algorithm_attributes(&self, key_type: KeyType) -> Result<Algo> {
|
||||
// get from cached "application related data"
|
||||
let aa = self.0.find(&Tag::from([key_type.get_algorithm_tag()]));
|
||||
let aa = self.0.find(&[key_type.get_algorithm_tag()].into());
|
||||
|
||||
if let Some(aa) = aa {
|
||||
Algo::try_from(&aa.serialize()[..])
|
||||
|
@ -119,7 +119,7 @@ impl ApplicationRelatedData {
|
|||
/// PW status Bytes
|
||||
pub fn get_pw_status_bytes(&self) -> Result<PWStatus> {
|
||||
// get from cached "application related data"
|
||||
let psb = self.0.find(&Tag::from([0xc4]));
|
||||
let psb = self.0.find(&[0xc4].into());
|
||||
|
||||
if let Some(psb) = psb {
|
||||
let pws = PWStatus::try_from(&psb.serialize())?;
|
||||
|
@ -138,7 +138,7 @@ impl ApplicationRelatedData {
|
|||
&self,
|
||||
) -> Result<KeySet<Fingerprint>, OpenpgpCardError> {
|
||||
// Get from cached "application related data"
|
||||
let fp = self.0.find(&Tag::from([0xc5]));
|
||||
let fp = self.0.find(&[0xc5].into());
|
||||
|
||||
if let Some(fp) = fp {
|
||||
let fp = fingerprint::to_keyset(&fp.serialize())?;
|
||||
|
@ -155,7 +155,7 @@ impl ApplicationRelatedData {
|
|||
pub fn get_key_generation_times(
|
||||
&self,
|
||||
) -> Result<KeySet<KeyGenerationTime>, OpenpgpCardError> {
|
||||
let kg = self.0.find(&Tag::from([0xCD]));
|
||||
let kg = self.0.find(&[0xcd].into());
|
||||
|
||||
if let Some(kg) = kg {
|
||||
let kg = key_generation_times::from(&kg.serialize())?;
|
||||
|
|
|
@ -17,7 +17,7 @@ use crate::crypto_data::{
|
|||
RSAKey, RSAPub,
|
||||
};
|
||||
use crate::errors::OpenpgpCardError;
|
||||
use crate::tlv::{tag::Tag, Tlv, TlvEntry};
|
||||
use crate::tlv::{Tlv, Value};
|
||||
use crate::{apdu, tlv, KeyType};
|
||||
|
||||
/// `gen_key_with_metadata` calculates the fingerprint for a public key
|
||||
|
@ -70,10 +70,10 @@ pub(crate) fn gen_key_with_metadata(
|
|||
}
|
||||
|
||||
fn tlv_to_pubkey(tlv: &Tlv, algo: &Algo) -> Result<PublicKeyMaterial> {
|
||||
let n = tlv.find(&Tag::new(vec![0x81]));
|
||||
let v = tlv.find(&Tag::new(vec![0x82]));
|
||||
let n = tlv.find(&[0x81].into());
|
||||
let v = tlv.find(&[0x82].into());
|
||||
|
||||
let ec = tlv.find(&Tag::new(vec![0x86]));
|
||||
let ec = tlv.find(&[0x86].into());
|
||||
|
||||
match (n, v, ec) {
|
||||
(Some(n), Some(v), None) => {
|
||||
|
@ -303,13 +303,13 @@ fn ecc_key_cmd(
|
|||
let crt = get_crt(key_type)?;
|
||||
|
||||
// 2) "Cardholder private key template" (7F48)
|
||||
let cpkt = Tlv(Tag(vec![0x7F, 0x48]), TlvEntry::S(vec![0x92, scalar_len]));
|
||||
let cpkt = Tlv::new([0x7F, 0x48], Value::S(vec![0x92, scalar_len]));
|
||||
|
||||
// 3) "Cardholder private key" (5F48)
|
||||
let cpk = Tlv(Tag(vec![0x5F, 0x48]), TlvEntry::S(scalar_data.to_vec()));
|
||||
let cpk = Tlv::new([0x5F, 0x48], Value::S(scalar_data.to_vec()));
|
||||
|
||||
// "Extended header list (DO 4D)" (contains the three inner TLV)
|
||||
let ehl = Tlv(Tag(vec![0x4d]), TlvEntry::C(vec![crt, cpkt, cpk]));
|
||||
let ehl = Tlv::new([0x4d], Value::C(vec![crt, cpkt, cpk]));
|
||||
|
||||
// key import command
|
||||
Ok(commands::key_import(ehl.serialize().to_vec()))
|
||||
|
@ -327,7 +327,7 @@ fn get_crt(key_type: KeyType) -> Result<Tlv, OpenpgpCardError> {
|
|||
)))
|
||||
}
|
||||
};
|
||||
Ok(Tlv(Tag(vec![tag]), TlvEntry::S(vec![])))
|
||||
Ok(Tlv::new([tag], Value::S(vec![])))
|
||||
}
|
||||
|
||||
fn rsa_key_cmd(
|
||||
|
@ -366,7 +366,7 @@ fn rsa_key_cmd(
|
|||
// len q in bytes, TLV-encoded
|
||||
value.extend_from_slice(&tlv::tlv_encode_length(len_q_bytes));
|
||||
|
||||
let cpkt = Tlv(Tag(vec![0x7F, 0x48]), TlvEntry::S(value));
|
||||
let cpkt = Tlv::new([0x7F, 0x48], Value::S(value));
|
||||
|
||||
// 3) "Cardholder private key" (5F48)
|
||||
//
|
||||
|
@ -387,10 +387,10 @@ fn rsa_key_cmd(
|
|||
keydata.extend(rsa_key.get_p().iter());
|
||||
keydata.extend(rsa_key.get_q().iter());
|
||||
|
||||
let cpk = Tlv(Tag(vec![0x5F, 0x48]), TlvEntry::S(keydata));
|
||||
let cpk = Tlv::new([0x5F, 0x48], Value::S(keydata));
|
||||
|
||||
// "Extended header list (DO 4D)"
|
||||
let ehl = Tlv(Tag(vec![0x4d]), TlvEntry::C(vec![crt, cpkt, cpk]));
|
||||
let ehl = Tlv::new([0x4d], Value::C(vec![crt, cpkt, cpk]));
|
||||
|
||||
// key import command
|
||||
Ok(commands::key_import(ehl.serialize().to_vec()))
|
||||
|
|
|
@ -1,29 +1,38 @@
|
|||
// SPDX-FileCopyrightText: 2021 Heiko Schaefer <heiko@schaefer.name>
|
||||
// SPDX-License-Identifier: MIT OR Apache-2.0
|
||||
|
||||
use anyhow::Result;
|
||||
use nom::{bytes::complete as bytes, combinator};
|
||||
|
||||
// mod value;
|
||||
pub mod length;
|
||||
pub mod tag;
|
||||
|
||||
use crate::card_do::complete;
|
||||
use tag::Tag;
|
||||
use anyhow::Result;
|
||||
use nom::{bytes::complete as bytes, combinator};
|
||||
use std::convert::TryFrom;
|
||||
|
||||
use crate::card_do::complete;
|
||||
use crate::tlv::tag::Tag;
|
||||
|
||||
/// TLV (Tag-Length-Value)
|
||||
#[derive(Debug, Eq, PartialEq)]
|
||||
pub struct Tlv(pub Tag, pub TlvEntry);
|
||||
pub struct Tlv {
|
||||
tag: Tag,
|
||||
value: Value,
|
||||
}
|
||||
|
||||
impl Tlv {
|
||||
pub fn find(&self, tag: &Tag) -> Option<&TlvEntry> {
|
||||
if &self.0 == tag {
|
||||
Some(&self.1)
|
||||
pub fn new<T: Into<Tag>>(tag: T, value: Value) -> Self {
|
||||
let tag = tag.into();
|
||||
Self { tag, value }
|
||||
}
|
||||
|
||||
/// Find the first occurrence of `tag` and return its value (if any)
|
||||
pub fn find(&self, tag: &Tag) -> Option<&Value> {
|
||||
if &self.tag == tag {
|
||||
Some(&self.value)
|
||||
} else {
|
||||
if let TlvEntry::C(inner) = &self.1 {
|
||||
if let Value::C(inner) = &self.value {
|
||||
for tlv in inner {
|
||||
let found = tlv.find(tag);
|
||||
if found.is_some() {
|
||||
return found;
|
||||
if let Some(found) = tlv.find(tag) {
|
||||
return Some(found);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -32,11 +41,11 @@ impl Tlv {
|
|||
}
|
||||
|
||||
pub fn serialize(&self) -> Vec<u8> {
|
||||
let value = self.1.serialize();
|
||||
let value = self.value.serialize();
|
||||
let length = crate::tlv::tlv_encode_length(value.len() as u16);
|
||||
|
||||
let mut ser = Vec::new();
|
||||
ser.extend(self.0 .0.iter());
|
||||
ser.extend(self.tag.get().iter());
|
||||
ser.extend(length.iter());
|
||||
ser.extend(value.iter());
|
||||
ser
|
||||
|
@ -49,12 +58,16 @@ impl Tlv {
|
|||
let (input, value) =
|
||||
combinator::flat_map(length::length, bytes::take)(input)?;
|
||||
|
||||
let (_, entry) = TlvEntry::parse(value, tag.is_constructed())?;
|
||||
let (_, v) = Value::parse(value, tag.is_constructed())?;
|
||||
|
||||
Ok((input, Self(tag, entry)))
|
||||
Ok((input, Self::new(tag, v)))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn try_from(input: &[u8]) -> Result<Self> {
|
||||
impl TryFrom<&[u8]> for Tlv {
|
||||
type Error = anyhow::Error;
|
||||
|
||||
fn try_from(input: &[u8]) -> Result<Self, Self::Error> {
|
||||
complete(Tlv::parse(input))
|
||||
}
|
||||
}
|
||||
|
@ -69,16 +82,20 @@ pub fn tlv_encode_length(len: u16) -> Vec<u8> {
|
|||
}
|
||||
}
|
||||
|
||||
/// A TLV "value"
|
||||
#[derive(Debug, Eq, PartialEq)]
|
||||
pub enum TlvEntry {
|
||||
pub enum Value {
|
||||
/// A "constructed" value, consisting of a list of Tlv
|
||||
C(Vec<Tlv>),
|
||||
|
||||
/// A "simple" value, consisting of binary data
|
||||
S(Vec<u8>),
|
||||
}
|
||||
|
||||
impl TlvEntry {
|
||||
pub fn parse(data: &[u8], constructed: bool) -> nom::IResult<&[u8], Self> {
|
||||
impl Value {
|
||||
fn parse(data: &[u8], constructed: bool) -> nom::IResult<&[u8], Self> {
|
||||
match constructed {
|
||||
false => Ok((&[], TlvEntry::S(data.to_vec()))),
|
||||
false => Ok((&[], Value::S(data.to_vec()))),
|
||||
true => {
|
||||
let mut c = vec![];
|
||||
let mut input = data;
|
||||
|
@ -89,7 +106,7 @@ impl TlvEntry {
|
|||
c.push(tlv);
|
||||
}
|
||||
|
||||
Ok((&[], TlvEntry::C(c)))
|
||||
Ok((&[], Value::C(c)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -100,8 +117,8 @@ impl TlvEntry {
|
|||
|
||||
pub fn serialize(&self) -> Vec<u8> {
|
||||
match self {
|
||||
TlvEntry::S(data) => data.clone(),
|
||||
TlvEntry::C(data) => {
|
||||
Value::S(data) => data.clone(),
|
||||
Value::C(data) => {
|
||||
let mut s = vec![];
|
||||
for t in data {
|
||||
s.extend(&t.serialize());
|
||||
|
@ -114,16 +131,17 @@ impl TlvEntry {
|
|||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::{Tag, Tlv};
|
||||
use crate::tlv::TlvEntry;
|
||||
use anyhow::Result;
|
||||
use hex_literal::hex;
|
||||
use std::convert::TryFrom;
|
||||
|
||||
use super::{Tlv, Value};
|
||||
|
||||
#[test]
|
||||
fn test_tlv0() {
|
||||
let cpkt = Tlv(
|
||||
Tag(vec![0x7F, 0x48]),
|
||||
TlvEntry::S(vec![
|
||||
let cpkt = Tlv::new(
|
||||
[0x7F, 0x48],
|
||||
Value::S(vec![
|
||||
0x91, 0x03, 0x92, 0x82, 0x01, 0x00, 0x93, 0x82, 0x01, 0x00,
|
||||
]),
|
||||
);
|
||||
|
@ -146,9 +164,9 @@ mod test {
|
|||
|
||||
assert_eq!(
|
||||
tlv,
|
||||
Tlv(
|
||||
Tag::from([0x5b]),
|
||||
TlvEntry::S(hex!("546573743C3C5465737469").to_vec())
|
||||
Tlv::new(
|
||||
[0x5b],
|
||||
Value::S(hex!("546573743C3C5465737469").to_vec())
|
||||
)
|
||||
);
|
||||
|
||||
|
@ -156,15 +174,12 @@ mod test {
|
|||
|
||||
assert_eq!(
|
||||
tlv,
|
||||
Tlv(Tag::from([0x5f, 0x2d]), TlvEntry::S(hex!("6465").to_vec()))
|
||||
Tlv::new([0x5f, 0x2d], Value::S(hex!("6465").to_vec()))
|
||||
);
|
||||
|
||||
let (input, tlv) = Tlv::parse(input).unwrap();
|
||||
|
||||
assert_eq!(
|
||||
tlv,
|
||||
Tlv(Tag::from([0x5f, 0x35]), TlvEntry::S(hex!("31").to_vec()))
|
||||
);
|
||||
assert_eq!(tlv, Tlv::new([0x5f, 0x35], Value::S(hex!("31").to_vec())));
|
||||
|
||||
assert!(input.is_empty());
|
||||
|
||||
|
@ -178,76 +193,76 @@ mod test {
|
|||
let tlv = Tlv::try_from(&data[..])?;
|
||||
|
||||
// outermost layer contains all bytes as value
|
||||
let entry = tlv.find(&Tag::from([0x6e])).unwrap();
|
||||
assert_eq!(entry.serialize(),
|
||||
let value = tlv.find(&[0x6e].into()).unwrap();
|
||||
assert_eq!(value.serialize(),
|
||||
hex!("4f10d27600012401030400061601918000005f520800730000e00590007f740381012073820110c00a7d000bfe080000ff0000c106010800001100c206010800001100c306010800001100da06010800001100c407ff7f7f7f030003c5500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c6500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cd1000000000000000000000000000000000de0801000200030081027f660802020bfe02020bfed6020020d7020020d8020020d9020020"));
|
||||
|
||||
// get and verify data for ecap tag
|
||||
let entry = tlv.find(&Tag::from([0xc0])).unwrap();
|
||||
assert_eq!(entry.serialize(), hex!("7d000bfe080000ff0000"));
|
||||
let value = tlv.find(&[0xc0].into()).unwrap();
|
||||
assert_eq!(value.serialize(), hex!("7d000bfe080000ff0000"));
|
||||
|
||||
let entry = tlv.find(&Tag::from([0x4f])).unwrap();
|
||||
let value = tlv.find(&[0x4f].into()).unwrap();
|
||||
assert_eq!(
|
||||
entry.serialize(),
|
||||
value.serialize(),
|
||||
hex!("d2760001240103040006160191800000")
|
||||
);
|
||||
|
||||
let entry = tlv.find(&Tag::from([0x5f, 0x52])).unwrap();
|
||||
assert_eq!(entry.serialize(), hex!("00730000e0059000"));
|
||||
let value = tlv.find(&[0x5f, 0x52].into()).unwrap();
|
||||
assert_eq!(value.serialize(), hex!("00730000e0059000"));
|
||||
|
||||
let entry = tlv.find(&Tag::from([0x7f, 0x74])).unwrap();
|
||||
assert_eq!(entry.serialize(), hex!("810120"));
|
||||
let value = tlv.find(&[0x7f, 0x74].into()).unwrap();
|
||||
assert_eq!(value.serialize(), hex!("810120"));
|
||||
|
||||
let entry = tlv.find(&Tag::from([0x73])).unwrap();
|
||||
assert_eq!(entry.serialize(), hex!("c00a7d000bfe080000ff0000c106010800001100c206010800001100c306010800001100da06010800001100c407ff7f7f7f030003c5500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c6500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cd1000000000000000000000000000000000de0801000200030081027f660802020bfe02020bfed6020020d7020020d8020020d9020020"));
|
||||
let value = tlv.find(&[0x73].into()).unwrap();
|
||||
assert_eq!(value.serialize(), hex!("c00a7d000bfe080000ff0000c106010800001100c206010800001100c306010800001100da06010800001100c407ff7f7f7f030003c5500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c6500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cd1000000000000000000000000000000000de0801000200030081027f660802020bfe02020bfed6020020d7020020d8020020d9020020"));
|
||||
|
||||
let entry = tlv.find(&Tag::from([0xc0])).unwrap();
|
||||
assert_eq!(entry.serialize(), hex!("7d000bfe080000ff0000"));
|
||||
let value = tlv.find(&[0xc0].into()).unwrap();
|
||||
assert_eq!(value.serialize(), hex!("7d000bfe080000ff0000"));
|
||||
|
||||
let entry = tlv.find(&Tag::from([0xc1])).unwrap();
|
||||
assert_eq!(entry.serialize(), hex!("010800001100"));
|
||||
let value = tlv.find(&[0xc1].into()).unwrap();
|
||||
assert_eq!(value.serialize(), hex!("010800001100"));
|
||||
|
||||
let entry = tlv.find(&Tag::from([0xc2])).unwrap();
|
||||
assert_eq!(entry.serialize(), hex!("010800001100"));
|
||||
let value = tlv.find(&[0xc2].into()).unwrap();
|
||||
assert_eq!(value.serialize(), hex!("010800001100"));
|
||||
|
||||
let entry = tlv.find(&Tag::from([0xc3])).unwrap();
|
||||
assert_eq!(entry.serialize(), hex!("010800001100"));
|
||||
let value = tlv.find(&[0xc3].into()).unwrap();
|
||||
assert_eq!(value.serialize(), hex!("010800001100"));
|
||||
|
||||
let entry = tlv.find(&Tag::from([0xda])).unwrap();
|
||||
assert_eq!(entry.serialize(), hex!("010800001100"));
|
||||
let value = tlv.find(&[0xda].into()).unwrap();
|
||||
assert_eq!(value.serialize(), hex!("010800001100"));
|
||||
|
||||
let entry = tlv.find(&Tag::from([0xc4])).unwrap();
|
||||
assert_eq!(entry.serialize(), hex!("ff7f7f7f030003"));
|
||||
let value = tlv.find(&[0xc4].into()).unwrap();
|
||||
assert_eq!(value.serialize(), hex!("ff7f7f7f030003"));
|
||||
|
||||
let entry = tlv.find(&Tag::from([0xc5])).unwrap();
|
||||
assert_eq!(entry.serialize(), hex!("0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"));
|
||||
let value = tlv.find(&[0xc5].into()).unwrap();
|
||||
assert_eq!(value.serialize(), hex!("0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"));
|
||||
|
||||
let entry = tlv.find(&Tag::from([0xc6])).unwrap();
|
||||
assert_eq!(entry.serialize(), hex!("0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"));
|
||||
let value = tlv.find(&[0xc6].into()).unwrap();
|
||||
assert_eq!(value.serialize(), hex!("0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"));
|
||||
|
||||
let entry = tlv.find(&Tag::from([0xcd])).unwrap();
|
||||
let value = tlv.find(&[0xcd].into()).unwrap();
|
||||
assert_eq!(
|
||||
entry.serialize(),
|
||||
value.serialize(),
|
||||
hex!("00000000000000000000000000000000")
|
||||
);
|
||||
|
||||
let entry = tlv.find(&Tag::from([0xde])).unwrap();
|
||||
assert_eq!(entry.serialize(), hex!("0100020003008102"));
|
||||
let value = tlv.find(&[0xde].into()).unwrap();
|
||||
assert_eq!(value.serialize(), hex!("0100020003008102"));
|
||||
|
||||
let entry = tlv.find(&Tag::from([0x7f, 0x66])).unwrap();
|
||||
assert_eq!(entry.serialize(), hex!("02020bfe02020bfe"));
|
||||
let value = tlv.find(&[0x7f, 0x66].into()).unwrap();
|
||||
assert_eq!(value.serialize(), hex!("02020bfe02020bfe"));
|
||||
|
||||
let entry = tlv.find(&Tag::from([0xd6])).unwrap();
|
||||
assert_eq!(entry.serialize(), hex!("0020"));
|
||||
let value = tlv.find(&[0xd6].into()).unwrap();
|
||||
assert_eq!(value.serialize(), hex!("0020"));
|
||||
|
||||
let entry = tlv.find(&Tag::from([0xd7])).unwrap();
|
||||
assert_eq!(entry.serialize(), hex!("0020"));
|
||||
let value = tlv.find(&[0xd7].into()).unwrap();
|
||||
assert_eq!(value.serialize(), hex!("0020"));
|
||||
|
||||
let entry = tlv.find(&Tag::from([0xd8])).unwrap();
|
||||
assert_eq!(entry.serialize(), hex!("0020"));
|
||||
let value = tlv.find(&[0xd8].into()).unwrap();
|
||||
assert_eq!(value.serialize(), hex!("0020"));
|
||||
|
||||
let entry = tlv.find(&Tag::from([0xd9])).unwrap();
|
||||
assert_eq!(entry.serialize(), hex!("0020"));
|
||||
let value = tlv.find(&[0xd9].into()).unwrap();
|
||||
assert_eq!(value.serialize(), hex!("0020"));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -258,15 +273,11 @@ mod test {
|
|||
// but has been abridged and changed. It does not represent a
|
||||
// complete valid OpenPGP card DO!
|
||||
|
||||
let a =
|
||||
Tlv(Tag::from(&[0x7F, 0x48][..]), TlvEntry::S(vec![0x92, 0x03]));
|
||||
let a = Tlv::new([0x7F, 0x48], Value::S(vec![0x92, 0x03]));
|
||||
|
||||
let b = Tlv(
|
||||
Tag::from(&[0x5F, 0x48][..]),
|
||||
TlvEntry::S(vec![0x1, 0x2, 0x3]),
|
||||
);
|
||||
let b = Tlv::new([0x5F, 0x48], Value::S(vec![0x1, 0x2, 0x3]));
|
||||
|
||||
let tlv = Tlv(Tag::from(&[0x4d][..]), TlvEntry::C(vec![a, b]));
|
||||
let tlv = Tlv::new([0x4d], Value::C(vec![a, b]));
|
||||
|
||||
assert_eq!(
|
||||
tlv.serialize(),
|
||||
|
|
|
@ -7,13 +7,9 @@ use nom::{
|
|||
};
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
pub struct Tag(pub Vec<u8>);
|
||||
pub struct Tag(Vec<u8>);
|
||||
|
||||
impl Tag {
|
||||
pub fn new(t: Vec<u8>) -> Self {
|
||||
Self(t)
|
||||
}
|
||||
|
||||
pub fn is_constructed(&self) -> bool {
|
||||
if self.0.is_empty() {
|
||||
false
|
||||
|
@ -21,6 +17,10 @@ impl Tag {
|
|||
self.0[0] & 0x20 != 0
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get(&self) -> &[u8] {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&[u8]> for Tag {
|
||||
|
|
Loading…
Reference in a new issue