Use byte-array data types for url, name, lang in openpgp-card.

This commit is contained in:
Heiko Schaefer 2022-02-15 15:30:28 +01:00
parent 80af7000e0
commit 574d7be765
No known key found for this signature in database
GPG key ID: 4A849A1904CCBD7D
6 changed files with 42 additions and 40 deletions

View file

@ -331,29 +331,29 @@ pub fn test_set_user_data(
card_client.verify_pw3("12345678")?; card_client.verify_pw3("12345678")?;
// name // name
card_client.set_name("Bar<<Foo")?; card_client.set_name(b"Bar<<Foo")?;
// lang // lang
card_client.set_lang("deen")?; card_client.set_lang(b"deen")?;
// sex // sex
card_client.set_sex(Sex::Female)?; card_client.set_sex(Sex::Female)?;
// url // url
card_client.set_url("https://duckduckgo.com/")?; card_client.set_url(b"https://duckduckgo.com/")?;
// read all the fields back again, expect equal data // read all the fields back again, expect equal data
let ch = card_client.cardholder_related_data()?; let ch = card_client.cardholder_related_data()?;
assert_eq!(ch.name(), Some("Bar<<Foo")); assert_eq!(ch.name().as_deref(), Some("Bar<<Foo".as_bytes()));
assert_eq!( assert_eq!(
ch.lang().expect("Language setting is None"), ch.lang().expect("Language setting is None"),
&[['d', 'e'], ['e', 'n']] &[[b'd', b'e'], [b'e', b'n']]
); );
assert_eq!(ch.sex(), Some(Sex::Female)); assert_eq!(ch.sex(), Some(Sex::Female));
let url = card_client.url()?; let url = card_client.url()?;
assert_eq!(url, "https://duckduckgo.com/".to_string()); assert_eq!(&url, b"https://duckduckgo.com/");
Ok(vec![]) Ok(vec![])
} }
@ -498,7 +498,7 @@ pub fn test_verify(
let mut out = vec![]; let mut out = vec![];
// try to set name without verify, assert result is not ok! // try to set name without verify, assert result is not ok!
let res = card_client.set_name("Notverified<<Hello"); let res = card_client.set_name("Notverified<<Hello".as_bytes());
if let Err(Error::CardStatus(s)) = res { if let Err(Error::CardStatus(s)) = res {
assert_eq!(s, StatusBytes::SecurityStatusNotSatisfied); assert_eq!(s, StatusBytes::SecurityStatusNotSatisfied);
@ -519,10 +519,13 @@ pub fn test_verify(
Ok(_) => out.push(TestResult::StatusOk), Ok(_) => out.push(TestResult::StatusOk),
} }
card_client.set_name("Admin<<Hello")?; card_client.set_name(b"Admin<<Hello")?;
let cardholder = card_client.cardholder_related_data()?; let cardholder = card_client.cardholder_related_data()?;
assert_eq!(cardholder.name(), Some("Admin<<Hello")); assert_eq!(
cardholder.name().as_deref(),
Some("Admin<<Hello".as_bytes())
);
card_client.verify_pw1("123456")?; card_client.verify_pw1("123456")?;
@ -537,10 +540,10 @@ pub fn test_verify(
Ok(_) => out.push(TestResult::StatusOk), Ok(_) => out.push(TestResult::StatusOk),
} }
card_client.set_name("There<<Hello")?; card_client.set_name(b"There<<Hello")?;
let cardholder = card_client.cardholder_related_data()?; let cardholder = card_client.cardholder_related_data()?;
assert_eq!(cardholder.name(), Some("There<<Hello")); assert_eq!(cardholder.name(), Some("There<<Hello".as_bytes()));
Ok(out) Ok(out)
} }

View file

@ -296,7 +296,7 @@ impl<'a> Open<'a> {
// --- URL (5f50) --- // --- URL (5f50) ---
pub fn url(&mut self) -> Result<String> { pub fn url(&mut self) -> Result<String> {
self.card_client.url() Ok(String::from_utf8_lossy(&self.card_client.url()?).to_string())
} }
// --- cardholder related data (65) --- // --- cardholder related data (65) ---
@ -408,7 +408,7 @@ impl Admin<'_, '_> {
return Err(anyhow!("Invalid char in name").into()); return Err(anyhow!("Invalid char in name").into());
}; };
self.oc.card_client.set_name(name) self.oc.card_client.set_name(name.as_bytes())
} }
pub fn set_lang(&mut self, lang: &str) -> Result<Response, Error> { pub fn set_lang(&mut self, lang: &str) -> Result<Response, Error> {
@ -416,7 +416,7 @@ impl Admin<'_, '_> {
return Err(anyhow!("lang too long").into()); return Err(anyhow!("lang too long").into());
} }
self.oc.card_client.set_lang(lang) self.oc.card_client.set_lang(lang.as_bytes())
} }
pub fn set_sex(&mut self, sex: Sex) -> Result<Response, Error> { pub fn set_sex(&mut self, sex: Sex) -> Result<Response, Error> {
@ -438,7 +438,7 @@ impl Admin<'_, '_> {
// or if it's within the acceptable length: // or if it's within the acceptable length:
// send the url update to the card. // send the url update to the card.
self.oc.card_client.set_url(url) self.oc.card_client.set_url(url.as_bytes())
} else { } else {
Err(anyhow!("URL too long").into()) Err(anyhow!("URL too long").into())
} }

View file

@ -284,8 +284,8 @@ pub struct ExtendedLengthInfo {
/// Cardholder Related Data (see spec pg. 22) /// Cardholder Related Data (see spec pg. 22)
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq)]
pub struct CardholderRelatedData { pub struct CardholderRelatedData {
name: Option<String>, name: Option<Vec<u8>>,
lang: Option<Vec<[char; 2]>>, lang: Option<Vec<[u8; 2]>>,
sex: Option<Sex>, sex: Option<Sex>,
} }

View file

@ -11,11 +11,11 @@ use crate::card_do::{CardholderRelatedData, Sex};
use crate::tlv::{value::Value, Tlv}; use crate::tlv::{value::Value, Tlv};
impl CardholderRelatedData { impl CardholderRelatedData {
pub fn name(&self) -> Option<&str> { pub fn name(&self) -> Option<&[u8]> {
self.name.as_deref() self.name.as_deref()
} }
pub fn lang(&self) -> Option<&[[char; 2]]> { pub fn lang(&self) -> Option<&[[u8; 2]]> {
self.lang.as_deref() self.lang.as_deref()
} }
@ -31,17 +31,12 @@ impl TryFrom<&[u8]> for CardholderRelatedData {
let value = Value::from(data, true)?; let value = Value::from(data, true)?;
let tlv = Tlv::new([0x65], value); let tlv = Tlv::new([0x65], value);
let name: Option<String> = tlv let name: Option<Vec<u8>> =
.find(&[0x5b].into()) tlv.find(&[0x5b].into()).map(|v| v.serialize().to_vec());
.map(|v| String::from_utf8_lossy(&v.serialize()).to_string());
let lang: Option<Vec<[char; 2]>> = let lang: Option<Vec<[u8; 2]>> = tlv
tlv.find(&[0x5f, 0x2d].into()).map(|v| { .find(&[0x5f, 0x2d].into())
v.serialize() .map(|v| v.serialize().chunks(2).map(|c| [c[0], c[1]]).collect());
.chunks(2)
.map(|c| [c[0] as char, c[1] as char])
.collect()
});
let sex = tlv let sex = tlv
.find(&[0x5f, 0x35].into()) .find(&[0x5f, 0x35].into())
@ -70,8 +65,8 @@ mod test {
assert_eq!( assert_eq!(
ch, ch,
CardholderRelatedData { CardholderRelatedData {
name: Some("Bar<<Foo".to_string()), name: Some("Bar<<Foo".as_bytes().to_vec()),
lang: Some(vec![['d', 'e'], ['e', 'n']]), lang: Some(vec![[b'd', b'e'], [b'e', b'n']]),
sex: Some(Sex::Female) sex: Some(Sex::Female)
} }
); );

View file

@ -247,10 +247,10 @@ impl<'a> dyn CardClient + 'a {
// --- login data (5e) --- // --- login data (5e) ---
/// Get URL (5f50) /// Get URL (5f50)
pub fn url(&mut self) -> Result<String> { pub fn url(&mut self) -> Result<Vec<u8>> {
let resp = apdu::send_command(self, commands::url(), true)?; let resp = apdu::send_command(self, commands::url(), true)?;
Ok(String::from_utf8_lossy(resp.data()?).to_string()) Ok(resp.data()?.to_vec())
} }
/// Get cardholder related data (65) /// Get cardholder related data (65)
@ -749,13 +749,13 @@ impl<'a> dyn CardClient + 'a {
// --- admin --- // --- admin ---
pub fn set_name(&mut self, name: &str) -> Result<Response, Error> { pub fn set_name(&mut self, name: &[u8]) -> Result<Response, Error> {
let put_name = commands::put_name(name.as_bytes().to_vec()); let put_name = commands::put_name(name.to_vec());
apdu::send_command(self, put_name, false)?.try_into() apdu::send_command(self, put_name, false)?.try_into()
} }
pub fn set_lang(&mut self, lang: &str) -> Result<Response, Error> { pub fn set_lang(&mut self, lang: &[u8]) -> Result<Response, Error> {
let put_lang = commands::put_lang(lang.as_bytes().to_vec()); let put_lang = commands::put_lang(lang.to_vec());
apdu::send_command(self, put_lang, false)?.try_into() apdu::send_command(self, put_lang, false)?.try_into()
} }
@ -764,8 +764,8 @@ impl<'a> dyn CardClient + 'a {
apdu::send_command(self, put_sex, false)?.try_into() apdu::send_command(self, put_sex, false)?.try_into()
} }
pub fn set_url(&mut self, url: &str) -> Result<Response, Error> { pub fn set_url(&mut self, url: &[u8]) -> Result<Response, Error> {
let put_url = commands::put_url(url.as_bytes().to_vec()); let put_url = commands::put_url(url.to_vec());
apdu::send_command(self, put_url, false)?.try_into() apdu::send_command(self, put_url, false)?.try_into()
} }

View file

@ -189,6 +189,8 @@ fn print_status(ident: Option<String>, verbose: bool) -> Result<()> {
let crd = open.cardholder_related_data()?; let crd = open.cardholder_related_data()?;
if let Some(name) = crd.name() { if let Some(name) = crd.name() {
let name = String::from_utf8_lossy(name).to_string();
print!("Cardholder: "); print!("Cardholder: ");
// This field is silly, maybe ignore it?! // This field is silly, maybe ignore it?!
@ -215,7 +217,9 @@ fn print_status(ident: Option<String>, verbose: bool) -> Result<()> {
if let Some(lang) = crd.lang() { if let Some(lang) = crd.lang() {
let lang = lang let lang = lang
.iter() .iter()
.map(|lang| lang.iter().collect::<String>()) .map(|lang| {
lang.iter().map(|&u| char::from(u)).collect::<String>()
})
.collect::<Vec<_>>() .collect::<Vec<_>>()
.join(", "); .join(", ");
println!("Language preferences '{}'", lang); println!("Language preferences '{}'", lang);