-
Notifications
You must be signed in to change notification settings - Fork 22
fix(security): bound panics on hostile authenticator inputs #203
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
d60303e
4da3fff
99cb6f4
62e75ca
9236103
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -359,6 +359,22 @@ where | |
| let uv_auth_token = | ||
| uv_proto.decrypt(&shared_secret, &encrypted_pin_uv_auth_token)?; | ||
|
|
||
| // pinUvAuthToken is 16 bytes for PUAP1 and 32 bytes for PUAP2. | ||
| // Reject a shorter token before it is used as a key downstream. | ||
| let min_token_len = match uv_proto.version() { | ||
| Ctap2PinUvAuthProtocol::One => 16, | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not entirely sure this logic is correct. Under section PUAP1, the spec says:
while under PUAP2, it says:
This code would allow under PUAP1 a token of 20 bytes length. I think it has to check for 32 bytes equality always and optionally for 16 bytes, if we are doing PUAP1. |
||
| Ctap2PinUvAuthProtocol::Two => 32, | ||
| }; | ||
| if uv_auth_token.len() < min_token_len { | ||
| error!( | ||
| protocol = ?uv_proto.version(), | ||
| token_len = uv_auth_token.len(), | ||
| min_expected = min_token_len, | ||
| "Decrypted pinUvAuthToken is shorter than required" | ||
| ); | ||
| return Err(Error::Ctap(CtapError::Other)); | ||
| } | ||
|
|
||
| let token_identifier = Ctap2AuthTokenPermission::new( | ||
| uv_proto.version(), | ||
| ctap2_request.permissions(), | ||
|
|
@@ -838,7 +854,7 @@ mod test { | |
| .unwrap(); | ||
| // We do here what the device would need to do, i.e. generate a new random | ||
| // pinUvAuthToken (here all 5's), then encrypt it using the shared_secret. | ||
| let token = [5; 32]; | ||
| let token = [5; 16]; | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. While puap1 would allow for 32 as well, it is probably not a bad idea to go for 16 here, just to test that both lengths works. |
||
| let encrypted_token = pin_protocol.encrypt(&shared_secret, &token).unwrap(); | ||
| let pin_resp = CborResponse::new_success_from_slice( | ||
| to_vec(&Ctap2ClientPinResponse { | ||
|
|
@@ -1182,7 +1198,7 @@ mod test { | |
| .unwrap(); | ||
| // We do here what the device would need to do, i.e. generate a new random | ||
| // pinUvAuthToken (here all 5's), then encrypt it using the shared_secret. | ||
| let token = [5; 32]; | ||
| let token = [5; 16]; | ||
| let encrypted_token = pin_protocol.encrypt(&shared_secret, &token).unwrap(); | ||
| let pin_resp = CborResponse::new_success_from_slice( | ||
| to_vec(&Ctap2ClientPinResponse { | ||
|
|
@@ -1322,7 +1338,7 @@ mod test { | |
| .unwrap(); | ||
| // We do here what the device would need to do, i.e. generate a new random | ||
| // pinUvAuthToken (here all 5's), then encrypt it using the shared_secret. | ||
| let token = [5; 32]; | ||
| let token = [5; 16]; | ||
| let encrypted_token = pin_protocol.encrypt(&shared_secret, &token).unwrap(); | ||
| let pin_resp = CborResponse::new_success_from_slice( | ||
| to_vec(&Ctap2ClientPinResponse { | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I had to read this sentence like 4 times 😂
(No need to change it, though. It was just funny to me.)