|
1 | 1 | use crate::{ |
2 | 2 | crypto::{PinUvAuthParam, PinUvAuthToken}, |
3 | 3 | ctap2::server::UserVerificationRequirement, |
4 | | - errors::AuthenticatorError, |
| 4 | + errors::{AuthenticatorError, UnsupportedOption}, |
5 | 5 | transport::errors::HIDError, |
6 | 6 | FidoDevice, |
7 | 7 | }; |
@@ -69,6 +69,10 @@ impl PinUvAuthCommand for LargeBlobs { |
69 | 69 | fn get_rp_id(&self) -> Option<&String> { |
70 | 70 | None |
71 | 71 | } |
| 72 | + |
| 73 | + fn hmac_requested(&self) -> bool { |
| 74 | + false |
| 75 | + } |
72 | 76 | } |
73 | 77 |
|
74 | 78 | impl Serialize for LargeBlobs { |
@@ -132,16 +136,17 @@ impl RequestCtap2 for LargeBlobs { |
132 | 136 | } |
133 | 137 |
|
134 | 138 | let status: StatusCode = input[0].into(); |
135 | | - let payload = &input[1..]; |
136 | 139 | if status.is_ok() { |
137 | | - if payload.len() > 1 { |
| 140 | + if input.len() > 1 { |
| 141 | + let payload = &input[1..]; |
138 | 142 | Ok(payload.to_vec()) |
139 | 143 | } else { |
140 | 144 | // Some subcommands return only an OK-status without any data |
141 | 145 | Ok(Vec::new()) |
142 | 146 | } |
143 | 147 | } else { |
144 | 148 | let data: Option<Value> = if input.len() > 1 { |
| 149 | + let payload = &input[1..]; |
145 | 150 | Some(from_slice(payload).map_err(CommandError::Deserializing)?) |
146 | 151 | } else { |
147 | 152 | None |
@@ -314,7 +319,7 @@ impl<'de> Deserialize<'de> for LargeBlobsResponse { |
314 | 319 |
|
315 | 320 | let byte_len = large_blob.len() as u64; |
316 | 321 | let large_blob_array: Vec<LargeBlobArrayElement> = |
317 | | - from_slice(large_blob).unwrap(); |
| 322 | + from_slice(large_blob).map_err(M::Error::custom)?; |
318 | 323 | let mut hash = [0u8; 16]; |
319 | 324 | hash.copy_from_slice(hash_slice); |
320 | 325 | response = Some(LargeBlobsResponse { |
@@ -354,11 +359,18 @@ where |
354 | 359 | // Spec: |
355 | 360 | // A per-authenticator constant, maxFragmentLength, is here defined as the value of maxMsgSize (from the authenticatorGetInfo response) minus 64. |
356 | 361 | // If no maxMsgSize is given in the authenticatorGetInfo response) then it defaults to 1024, leaving maxFragmentLength to default to 960. |
357 | | - let max_fragment_length = dev |
| 362 | + // |
| 363 | + // In the highly unlikely case of a max_msg_size smaller than 65 (leaving zero-byte fragment-length), we error out, saying that largeBlobs is unsupported. |
| 364 | + let max_msg_size = dev |
358 | 365 | .get_authenticator_info() |
359 | 366 | .and_then(|i| i.max_msg_size) |
360 | | - .unwrap_or(1024) |
361 | | - - 64; |
| 367 | + .unwrap_or(1024); |
| 368 | + if max_msg_size <= 64 { |
| 369 | + return Err(AuthenticatorError::UnsupportedOption( |
| 370 | + UnsupportedOption::LargeBlobs, |
| 371 | + )); |
| 372 | + } |
| 373 | + let max_fragment_length = max_msg_size - 64; |
362 | 374 | let mut bytes = vec![]; |
363 | 375 | let mut offset = 0; |
364 | 376 | loop { |
@@ -404,11 +416,18 @@ where |
404 | 416 | // Spec: |
405 | 417 | // A per-authenticator constant, maxFragmentLength, is here defined as the value of maxMsgSize (from the authenticatorGetInfo response) minus 64. |
406 | 418 | // If no maxMsgSize is given in the authenticatorGetInfo response) then it defaults to 1024, leaving maxFragmentLength to default to 960. |
407 | | - let max_fragment_length = dev |
| 419 | + // |
| 420 | + // In the highly unlikely case of a max_msg_size smaller than 65 (leaving zero-byte fragment-length), we error out, saying that largeBlobs is unsupported. |
| 421 | + let max_msg_size = dev |
408 | 422 | .get_authenticator_info() |
409 | 423 | .and_then(|i| i.max_msg_size) |
410 | | - .unwrap_or(1024) |
411 | | - - 64; |
| 424 | + .unwrap_or(1024); |
| 425 | + if max_msg_size <= 64 { |
| 426 | + return Err(AuthenticatorError::UnsupportedOption( |
| 427 | + UnsupportedOption::LargeBlobs, |
| 428 | + )); |
| 429 | + } |
| 430 | + let max_fragment_length = max_msg_size - 64; |
412 | 431 | let total_length = bytes.len(); |
413 | 432 | let mut offset = initial_offset; |
414 | 433 | for chunk in bytes.chunks(max_fragment_length) { |
|
0 commit comments