Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
O
OpenSK
Manage
Activity
Members
Code
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Locked files
Deploy
Releases
Model registry
Analyze
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
GitLab community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
This is an archived project. Repository and other project resources are read-only.
Show more breadcrumbs
koenigl2
OpenSK
Commits
ca6f910c
Commit
ca6f910c
authored
May 13, 2020
by
Julien Cretin
Browse files
Options
Downloads
Patches
Plain Diff
Remove unknown fields
parent
479de32a
Branches
Branches containing commit
No related tags found
No related merge requests found
Changes
4
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
libraries/cbor/src/macros.rs
+7
-18
7 additions, 18 deletions
libraries/cbor/src/macros.rs
src/ctap/data_formats.rs
+40
-49
40 additions, 49 deletions
src/ctap/data_formats.rs
src/ctap/mod.rs
+0
-4
0 additions, 4 deletions
src/ctap/mod.rs
src/ctap/storage.rs
+2
-4
2 additions, 4 deletions
src/ctap/storage.rs
with
49 additions
and
75 deletions
libraries/cbor/src/macros.rs
+
7
−
18
View file @
ca6f910c
...
...
@@ -41,31 +41,20 @@ macro_rules! cbor_map_options {
};
(
$
(
$key:expr
=>
$value:expr
),
*
)
=>
{
{
let
mut
_map
=
::
alloc
::
collections
::
BTreeMap
::
<
_
,
$crate
::
values
::
Value
>
::
new
();
extend_cbor_map_options!
(
&
mut
_map
,
$
(
$key
=>
$value
,
)
*
);
$crate
::
values
::
Value
::
Map
(
_map
)
}
};
}
#[macro_export]
macro_rules!
extend_cbor_map_options
{
// Add trailing comma if missing.
(
&
mut
$map:expr
,
$
(
$key:expr
=>
$value:expr
),
+
)
=>
{
extend_cbor_map_options!
(
&
mut
$map
,
$
(
$key
=>
$value
,)
+
)
};
(
&
mut
$map:expr
,
$
(
$key:expr
=>
$value:expr
,
)
*
)
=>
{
{
// The import is unused if the list is empty.
#[allow(unused_imports)]
use
$crate
::
values
::{
IntoCborKey
,
IntoCborValueOption
};
let
mut
_map
=
::
alloc
::
collections
::
BTreeMap
::
<
_
,
$crate
::
values
::
Value
>
::
new
();
$
(
if
let
Some
(
val
)
=
$value
.into_cbor_value_option
()
{
$map
.insert
(
$key
.into_cbor_key
(),
val
);
{
let
opt
:
Option
<
$crate
::
values
::
Value
>
=
$value
.into_cbor_value_option
();
if
let
Some
(
val
)
=
opt
{
_map
.insert
(
$key
.into_cbor_key
(),
val
);
}
}
)
*
$crate
::
values
::
Value
::
Map
(
_map
)
}
};
}
...
...
This diff is collapsed.
Click to expand it.
src/ctap/data_formats.rs
+
40
−
49
View file @
ca6f910c
...
...
@@ -433,6 +433,9 @@ impl TryFrom<&cbor::Value> for SignatureAlgorithm {
}
// https://www.w3.org/TR/webauthn/#public-key-credential-source
//
// Note that we only use the WebAuthn definition as an example. This data-structure is not specified
// by FIDO. In particular we may choose how we serialize and deserialize it.
#[derive(Clone)]
#[cfg_attr(test,
derive(PartialEq))]
#[cfg_attr(any(test,
feature
=
"debug_ctap"
),
derive(Debug))]
...
...
@@ -445,18 +448,10 @@ pub struct PublicKeyCredentialSource {
pub
user_handle
:
Vec
<
u8
>
,
// not optional, but nullable
pub
other_ui
:
Option
<
String
>
,
pub
cred_random
:
Option
<
Vec
<
u8
>>
,
/// Contains the unknown fields when parsing a CBOR value.
///
/// Those fields could either be deleted fields from older versions (they should have reserved
/// tags) or fields from newer versions (the tags should not be reserved). If this is empty,
/// then the parsed credential is probably from the same version (but not necessarily).
pub
unknown_fields
:
BTreeMap
<
cbor
::
KeyType
,
cbor
::
Value
>
,
}
// We serialize credentials for the persistent storage using CBOR maps. Each field of a credential
// is associated with a unique tag, implemented with a CBOR unsigned key.
#[repr(u64)]
enum
PublicKeyCredentialSourceField
{
CredentialId
=
0
,
PrivateKey
=
1
,
...
...
@@ -480,50 +475,48 @@ impl From<PublicKeyCredentialSource> for cbor::Value {
use
PublicKeyCredentialSourceField
::
*
;
let
mut
private_key
=
[
0
;
32
];
credential
.private_key
.to_bytes
(
&
mut
private_key
);
let
mut
result
=
credential
.unknown_fields
;
extend_cbor_map_options!
{
&
mut
result
,
cbor_map_options!
{
CredentialId
=>
Some
(
credential
.credential_id
),
PrivateKey
=>
Some
(
private_key
.to_vec
()),
RpId
=>
Some
(
credential
.rp_id
),
UserHandle
=>
Some
(
credential
.user_handle
),
OtherUi
=>
credential
.other_ui
,
CredRandom
=>
credential
.cred_random
};
cbor
::
Value
::
Map
(
result
)
}
}
}
impl
PublicKeyCredentialSource
{
pub
fn
parse_cbor
(
cbor_value
:
cbor
::
Value
)
->
Option
<
PublicKeyCredentialSource
>
{
use
PublicKeyCredentialSourceField
::
*
;
let
mut
map
=
match
cbor_value
{
cbor
::
Value
::
Map
(
x
)
=>
x
,
_
=>
return
None
,
};
impl
TryFrom
<&
cbor
::
Value
>
for
PublicKeyCredentialSource
{
type
Error
=
Ctap2StatusCode
;
let
credential_id
=
read_byte_string
(
&
map
.remove
(
&
CredentialId
.into
())
?
)
.ok
()
?
;
let
private_key
=
read_byte_string
(
&
map
.remove
(
&
PrivateKey
.into
())
?
)
.ok
()
?
;
fn
try_from
(
cbor_value
:
&
cbor
::
Value
)
->
Result
<
Self
,
Ctap2StatusCode
>
{
use
PublicKeyCredentialSourceField
::
*
;
let
map
=
read_map
(
cbor_value
)
?
;
let
credential_id
=
read_byte_string
(
ok_or_missing
(
map
.get
(
&
CredentialId
.into
()))
?
)
?
;
let
private_key
=
read_byte_string
(
ok_or_missing
(
map
.get
(
&
PrivateKey
.into
()))
?
)
?
;
if
private_key
.len
()
!=
32
{
return
None
;
}
let
private_key
=
ecdsa
::
SecKey
::
from_bytes
(
array_ref!
(
private_key
,
0
,
32
))
?
;
let
rp_id
=
read_text_string
(
&
map
.remove
(
&
RpId
.into
())
?
)
.ok
()
?
;
let
user_handle
=
read_byte_string
(
&
map
.remove
(
&
UserHandle
.into
())
?
)
.ok
()
?
;
let
other_ui
=
map
.remove
(
&
OtherUi
.into
())
.as_ref
()
.map
(
read_text_string
)
.transpose
()
.ok
()
?
;
return
Err
(
Ctap2StatusCode
::
CTAP2_ERR_INVALID_CBOR
);
}
let
private_key
=
ecdsa
::
SecKey
::
from_bytes
(
array_ref!
(
private_key
,
0
,
32
))
.ok_or
(
Ctap2StatusCode
::
CTAP2_ERR_INVALID_CBOR
)
?
;
let
rp_id
=
read_text_string
(
ok_or_missing
(
map
.get
(
&
RpId
.into
()))
?
)
?
;
let
user_handle
=
read_byte_string
(
ok_or_missing
(
map
.get
(
&
UserHandle
.into
()))
?
)
?
;
let
other_ui
=
map
.get
(
&
OtherUi
.into
())
.map
(
read_text_string
)
.transpose
()
?
;
let
cred_random
=
map
.remove
(
&
CredRandom
.into
())
.as_ref
()
.get
(
&
CredRandom
.into
())
.map
(
read_byte_string
)
.transpose
()
.ok
()
?
;
let
unknown_fields
=
map
;
Some
(
PublicKeyCredentialSource
{
.transpose
()
?
;
// We don't return whether there were unknown fields in the CBOR value. This means that
// deserialization is not injective. In particular deserialization is only an inverse of
// serialization at a given version of OpenSK. This is not a problem because:
// 1. When a field is deprecated, its tag is reserved and never reused in future versions,
// including to be reintroduced with the same semantics. In other words, removing a field
// is permanent.
// 2. OpenSK is never used with a more recent version of the storage. In particular, OpenSK
// is never rolled-back.
// As a consequence, the unknown fields are only reserved fields and don't need to be
// preserved.
Ok
(
PublicKeyCredentialSource
{
key_type
:
PublicKeyCredentialType
::
PublicKey
,
credential_id
,
private_key
,
...
...
@@ -531,7 +524,6 @@ impl PublicKeyCredentialSource {
user_handle
,
other_ui
,
cred_random
,
unknown_fields
,
})
}
}
...
...
@@ -1245,12 +1237,11 @@ mod test {
user_handle
:
b"foo"
.to_vec
(),
other_ui
:
None
,
cred_random
:
None
,
unknown_fields
:
BTreeMap
::
new
(),
};
assert_eq!
(
PublicKeyCredentialSource
::
parse_cbor
(
cbor
::
Value
::
from
(
credential
.clone
())),
Some
(
credential
.clone
())
PublicKeyCredentialSource
::
try_from
(
&
cbor
::
Value
::
from
(
credential
.clone
())),
Ok
(
credential
.clone
())
);
let
credential
=
PublicKeyCredentialSource
{
...
...
@@ -1259,8 +1250,8 @@ mod test {
};
assert_eq!
(
PublicKeyCredentialSource
::
parse_cbor
(
cbor
::
Value
::
from
(
credential
.clone
())),
Some
(
credential
.clone
())
PublicKeyCredentialSource
::
try_from
(
&
cbor
::
Value
::
from
(
credential
.clone
())),
Ok
(
credential
.clone
())
);
let
credential
=
PublicKeyCredentialSource
{
...
...
@@ -1269,15 +1260,15 @@ mod test {
};
assert_eq!
(
PublicKeyCredentialSource
::
parse_cbor
(
cbor
::
Value
::
from
(
credential
.clone
())),
Some
(
credential
)
PublicKeyCredentialSource
::
try_from
(
&
cbor
::
Value
::
from
(
credential
.clone
())),
Ok
(
credential
)
);
}
#[test]
fn
test_credential_source_invalid_cbor
()
{
assert!
(
PublicKeyCredentialSource
::
parse_cbor
(
cbor_false!
())
.is_
none
());
assert!
(
PublicKeyCredentialSource
::
parse_cbor
(
cbor_array!
(
false
))
.is_
none
());
assert!
(
PublicKeyCredentialSource
::
parse_cbor
(
cbor_array!
(
b"foo"
.to_vec
()))
.is_
none
());
assert!
(
PublicKeyCredentialSource
::
try_from
(
&
cbor_false!
())
.is_
err
());
assert!
(
PublicKeyCredentialSource
::
try_from
(
&
cbor_array!
(
false
))
.is_
err
());
assert!
(
PublicKeyCredentialSource
::
try_from
(
&
cbor_array!
(
b"foo"
.to_vec
()))
.is_
err
());
}
}
This diff is collapsed.
Click to expand it.
src/ctap/mod.rs
+
0
−
4
View file @
ca6f910c
...
...
@@ -335,7 +335,6 @@ where
user_handle
:
vec!
[],
other_ui
:
None
,
cred_random
:
None
,
unknown_fields
:
BTreeMap
::
new
(),
})
}
...
...
@@ -502,7 +501,6 @@ where
.user_display_name
.map
(|
s
|
truncate_to_char_boundary
(
&
s
,
64
)
.to_string
()),
cred_random
,
unknown_fields
:
BTreeMap
::
new
(),
};
self
.persistent_store
.store_credential
(
credential_source
)
?
;
random_id
...
...
@@ -1281,7 +1279,6 @@ mod test {
user_handle
:
vec!
[],
other_ui
:
None
,
cred_random
:
None
,
unknown_fields
:
BTreeMap
::
new
(),
};
assert!
(
ctap_state
.persistent_store
...
...
@@ -1479,7 +1476,6 @@ mod test {
user_handle
:
vec!
[],
other_ui
:
None
,
cred_random
:
None
,
unknown_fields
:
BTreeMap
::
new
(),
};
assert!
(
ctap_state
.persistent_store
...
...
This diff is collapsed.
Click to expand it.
src/ctap/storage.rs
+
2
−
4
View file @
ca6f910c
...
...
@@ -16,9 +16,9 @@ use crate::crypto::rng256::Rng256;
use
crate
::
ctap
::
data_formats
::
PublicKeyCredentialSource
;
use
crate
::
ctap
::
status_code
::
Ctap2StatusCode
;
use
crate
::
ctap
::
PIN_AUTH_LENGTH
;
use
alloc
::
collections
::
BTreeMap
;
use
alloc
::
string
::
String
;
use
alloc
::
vec
::
Vec
;
use
core
::
convert
::
TryFrom
;
use
ctap2
::
embedded_flash
::{
self
,
StoreConfig
,
StoreEntry
,
StoreError
,
StoreIndex
};
#[cfg(any(test,
feature
=
"ram_storage"
))]
...
...
@@ -420,7 +420,7 @@ impl From<StoreError> for Ctap2StatusCode {
}
fn
deserialize_credential
(
data
:
&
[
u8
])
->
Option
<
PublicKeyCredentialSource
>
{
PublicKeyCredentialSource
::
parse_cbor
(
cbor
::
read
(
data
)
.ok
()
?
)
PublicKeyCredentialSource
::
try_from
(
&
cbor
::
read
(
data
)
.ok
()
?
)
.ok
()
}
fn
serialize_credential
(
credential
:
PublicKeyCredentialSource
)
->
Result
<
Vec
<
u8
>
,
Ctap2StatusCode
>
{
...
...
@@ -453,7 +453,6 @@ mod test {
user_handle
,
other_ui
:
None
,
cred_random
:
None
,
unknown_fields
:
BTreeMap
::
new
(),
}
}
...
...
@@ -623,7 +622,6 @@ mod test {
user_handle
:
vec!
[
0x00
],
other_ui
:
None
,
cred_random
:
None
,
unknown_fields
:
BTreeMap
::
new
(),
};
assert_eq!
(
found_credential
,
Some
(
expected_credential
));
}
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment