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")?;
// name
card_client.set_name("Bar<<Foo")?;
card_client.set_name(b"Bar<<Foo")?;
// lang
card_client.set_lang("deen")?;
card_client.set_lang(b"deen")?;
// sex
card_client.set_sex(Sex::Female)?;
// 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
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!(
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));
let url = card_client.url()?;
assert_eq!(url, "https://duckduckgo.com/".to_string());
assert_eq!(&url, b"https://duckduckgo.com/");
Ok(vec![])
}
@ -498,7 +498,7 @@ pub fn test_verify(
let mut out = vec![];
// 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 {
assert_eq!(s, StatusBytes::SecurityStatusNotSatisfied);
@ -519,10 +519,13 @@ pub fn test_verify(
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()?;
assert_eq!(cardholder.name(), Some("Admin<<Hello"));
assert_eq!(
cardholder.name().as_deref(),
Some("Admin<<Hello".as_bytes())
);
card_client.verify_pw1("123456")?;
@ -537,10 +540,10 @@ pub fn test_verify(
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()?;
assert_eq!(cardholder.name(), Some("There<<Hello"));
assert_eq!(cardholder.name(), Some("There<<Hello".as_bytes()));
Ok(out)
}

View file

@ -296,7 +296,7 @@ impl<'a> Open<'a> {
// --- URL (5f50) ---
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) ---
@ -408,7 +408,7 @@ impl Admin<'_, '_> {
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> {
@ -416,7 +416,7 @@ impl Admin<'_, '_> {
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> {
@ -438,7 +438,7 @@ impl Admin<'_, '_> {
// or if it's within the acceptable length:
// send the url update to the card.
self.oc.card_client.set_url(url)
self.oc.card_client.set_url(url.as_bytes())
} else {
Err(anyhow!("URL too long").into())
}

View file

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

View file

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

View file

@ -247,10 +247,10 @@ impl<'a> dyn CardClient + 'a {
// --- login data (5e) ---
/// 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)?;
Ok(String::from_utf8_lossy(resp.data()?).to_string())
Ok(resp.data()?.to_vec())
}
/// Get cardholder related data (65)
@ -749,13 +749,13 @@ impl<'a> dyn CardClient + 'a {
// --- admin ---
pub fn set_name(&mut self, name: &str) -> Result<Response, Error> {
let put_name = commands::put_name(name.as_bytes().to_vec());
pub fn set_name(&mut self, name: &[u8]) -> Result<Response, Error> {
let put_name = commands::put_name(name.to_vec());
apdu::send_command(self, put_name, false)?.try_into()
}
pub fn set_lang(&mut self, lang: &str) -> Result<Response, Error> {
let put_lang = commands::put_lang(lang.as_bytes().to_vec());
pub fn set_lang(&mut self, lang: &[u8]) -> Result<Response, Error> {
let put_lang = commands::put_lang(lang.to_vec());
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()
}
pub fn set_url(&mut self, url: &str) -> Result<Response, Error> {
let put_url = commands::put_url(url.as_bytes().to_vec());
pub fn set_url(&mut self, url: &[u8]) -> Result<Response, Error> {
let put_url = commands::put_url(url.to_vec());
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()?;
if let Some(name) = crd.name() {
let name = String::from_utf8_lossy(name).to_string();
print!("Cardholder: ");
// 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() {
let lang = lang
.iter()
.map(|lang| lang.iter().collect::<String>())
.map(|lang| {
lang.iter().map(|&u| char::from(u)).collect::<String>()
})
.collect::<Vec<_>>()
.join(", ");
println!("Language preferences '{}'", lang);