diff --git a/openpgp-card/src/card_app.rs b/openpgp-card/src/card_app.rs index 5d7b34f..ecb17a0 100644 --- a/openpgp-card/src/card_app.rs +++ b/openpgp-card/src/card_app.rs @@ -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 { 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 { - 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, 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())), ]), ); diff --git a/openpgp-card/src/card_do/cardholder.rs b/openpgp-card/src/card_do/cardholder.rs index 2e6b0a4..9d599f2 100644 --- a/openpgp-card/src/card_do/cardholder.rs +++ b/openpgp-card/src/card_do/cardholder.rs @@ -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 { - 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 = tlv - .find(&Tag::from(&[0x5b][..])) + .find(&[0x5b].into()) .map(|v| String::from_utf8_lossy(&v.serialize()).to_string()); let lang: Option> = - 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])); diff --git a/openpgp-card/src/card_do/mod.rs b/openpgp-card/src/card_do/mod.rs index 9a83f2f..1ab47fe 100644 --- a/openpgp-card/src/card_do/mod.rs +++ b/openpgp-card/src/card_do/mod.rs @@ -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 { // 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 { // 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> { // 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 { // 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 { // 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 { // 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, 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, 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())?; diff --git a/openpgp-card/src/keys.rs b/openpgp-card/src/keys.rs index 4bdee13..3c5b6e5 100644 --- a/openpgp-card/src/keys.rs +++ b/openpgp-card/src/keys.rs @@ -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 { - 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 { ))) } }; - 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())) diff --git a/openpgp-card/src/tlv/mod.rs b/openpgp-card/src/tlv/mod.rs index d061aaa..f854eb6 100644 --- a/openpgp-card/src/tlv/mod.rs +++ b/openpgp-card/src/tlv/mod.rs @@ -1,29 +1,38 @@ // SPDX-FileCopyrightText: 2021 Heiko Schaefer // 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>(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 { - 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 { +impl TryFrom<&[u8]> for Tlv { + type Error = anyhow::Error; + + fn try_from(input: &[u8]) -> Result { complete(Tlv::parse(input)) } } @@ -69,16 +82,20 @@ pub fn tlv_encode_length(len: u16) -> Vec { } } +/// A TLV "value" #[derive(Debug, Eq, PartialEq)] -pub enum TlvEntry { +pub enum Value { + /// A "constructed" value, consisting of a list of Tlv C(Vec), + + /// A "simple" value, consisting of binary data S(Vec), } -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 { 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(), diff --git a/openpgp-card/src/tlv/tag.rs b/openpgp-card/src/tlv/tag.rs index 3fea8a9..4247b61 100644 --- a/openpgp-card/src/tlv/tag.rs +++ b/openpgp-card/src/tlv/tag.rs @@ -7,13 +7,9 @@ use nom::{ }; #[derive(Clone, Debug, Eq, PartialEq)] -pub struct Tag(pub Vec); +pub struct Tag(Vec); impl Tag { - pub fn new(t: Vec) -> 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 {