Use byte-array data types for url, name, lang in openpgp-card.
This commit is contained in:
parent
80af7000e0
commit
574d7be765
6 changed files with 42 additions and 40 deletions
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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())
|
||||||
}
|
}
|
||||||
|
|
|
@ -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>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
|
@ -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()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in a new issue