u2fd: make util::VectorToObject safer

This would prevent potential stack overflow issue.

BUG=b:173403271
TEST=check power button key work on DUT
TEST=CQ

Change-Id: I6ed587f8917dc94433f0e52aae8b9752a973660d
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform2/+/2546672
Tested-by: John L Chen <zuan@chromium.org>
Tested-by: Leo Lai <cylai@google.com>
Reviewed-by: joe Chou <yich@google.com>
Reviewed-by: Leo Lai <cylai@google.com>
Commit-Queue: Leo Lai <cylai@google.com>
diff --git a/u2fd/u2f_msg_handler.cc b/u2fd/u2f_msg_handler.cc
index 7f460c7..6c350fc 100644
--- a/u2fd/u2f_msg_handler.cc
+++ b/u2fd/u2f_msg_handler.cc
@@ -296,8 +296,14 @@
   struct u2f_generate_req generate_req = {
       .flags = U2F_AUTH_ENFORCE  // Require user presence, consume.
   };
-  util::VectorToObject(app_id, generate_req.appId);
-  util::VectorToObject(*user_secret, generate_req.userSecret);
+  if (!util::VectorToObject(app_id, generate_req.appId,
+                            sizeof(generate_req.appId))) {
+    return Cr50CmdStatus::kInvalidState;
+  }
+  if (!util::VectorToObject(*user_secret, generate_req.userSecret,
+                            sizeof(generate_req.userSecret))) {
+    return Cr50CmdStatus::kInvalidState;
+  }
 
   struct u2f_generate_resp generate_resp = {};
   Cr50CmdStatus generate_status = static_cast<Cr50CmdStatus>(
@@ -332,10 +338,20 @@
   };
   if (allow_legacy_kh_sign_)
     sign_req.flags |= SIGN_LEGACY_KH;
-  util::VectorToObject(app_id, sign_req.appId);
-  util::VectorToObject(*user_secret, sign_req.userSecret);
-  util::VectorToObject(key_handle, &sign_req.keyHandle);
-  util::VectorToObject(hash, sign_req.hash);
+  if (!util::VectorToObject(app_id, sign_req.appId, sizeof(sign_req.appId))) {
+    return Cr50CmdStatus::kInvalidState;
+  }
+  if (!util::VectorToObject(*user_secret, sign_req.userSecret,
+                            sizeof(sign_req.userSecret))) {
+    return Cr50CmdStatus::kInvalidState;
+  }
+  if (!util::VectorToObject(key_handle, &sign_req.keyHandle,
+                            sizeof(sign_req.keyHandle))) {
+    return Cr50CmdStatus::kInvalidState;
+  }
+  if (!util::VectorToObject(hash, sign_req.hash, sizeof(sign_req.hash))) {
+    return Cr50CmdStatus::kInvalidState;
+  }
 
   struct u2f_sign_resp sign_resp = {};
   Cr50CmdStatus sign_status =
@@ -371,9 +387,17 @@
   struct u2f_sign_req sign_req = {
       .flags = U2F_AUTH_CHECK_ONLY  // No user presence required, no consume.
   };
-  util::VectorToObject(app_id, sign_req.appId);
-  util::VectorToObject(*user_secret, sign_req.userSecret);
-  util::VectorToObject(key_handle, &sign_req.keyHandle);
+  if (!util::VectorToObject(app_id, sign_req.appId, sizeof(sign_req.appId))) {
+    return Cr50CmdStatus::kInvalidState;
+  }
+  if (!util::VectorToObject(*user_secret, sign_req.userSecret,
+                            sizeof(sign_req.userSecret))) {
+    return Cr50CmdStatus::kInvalidState;
+  }
+  if (!util::VectorToObject(key_handle, &sign_req.keyHandle,
+                            sizeof(sign_req.keyHandle))) {
+    return Cr50CmdStatus::kInvalidState;
+  }
 
   Cr50CmdStatus sign_status =
       static_cast<Cr50CmdStatus>(proxy_->SendU2fSign(sign_req, nullptr));
@@ -395,10 +419,13 @@
 
   struct u2f_attest_req attest_req = {
       .format = format, .dataLen = static_cast<uint8_t>(data.size())};
-  util::VectorToObject(*user_secret, attest_req.userSecret);
-  // Only a programming error can cause this CHECK to fail.
-  CHECK_LE(data.size(), sizeof(attest_req.data));
-  util::VectorToObject(data, attest_req.data);
+  if (!util::VectorToObject(*user_secret, attest_req.userSecret,
+                            sizeof(attest_req.userSecret))) {
+    return Cr50CmdStatus::kInvalidState;
+  }
+  if (!util::VectorToObject(data, attest_req.data, sizeof(attest_req.data))) {
+    return Cr50CmdStatus::kInvalidState;
+  }
 
   struct u2f_attest_resp attest_resp = {};
   Cr50CmdStatus attest_status = static_cast<Cr50CmdStatus>(
diff --git a/u2fd/util.h b/u2fd/util.h
index 2c05bdc..66aa064 100644
--- a/u2fd/util.h
+++ b/u2fd/util.h
@@ -41,10 +41,14 @@
 // Utility function to copy bytes from a vector to an object. This is the
 // inverse of AppendToVector.
 template <typename VectorAllocator, typename ToType>
-void VectorToObject(const std::vector<uint8_t, VectorAllocator>& from,
-                    ToType* to) {
-  // TODO(louiscollard): This, but nicer/safer.
+bool VectorToObject(const std::vector<uint8_t, VectorAllocator>& from,
+                    ToType* to,
+                    const size_t size) {
+  if (size < from.size()) {
+    return false;
+  }
   memcpy(to, &from.front(), from.size());
+  return true;
 }
 
 // Utility function to copy part of a string to a vector.
diff --git a/u2fd/webauthn_handler.cc b/u2fd/webauthn_handler.cc
index 24b955e..f2fcdee 100644
--- a/u2fd/webauthn_handler.cc
+++ b/u2fd/webauthn_handler.cc
@@ -362,8 +362,14 @@
   struct u2f_generate_req generate_req = {
       .flags = U2F_AUTH_ENFORCE  // Require user presence, consume.
   };
-  util::VectorToObject(rp_id_hash, generate_req.appId);
-  util::VectorToObject(*user_secret, generate_req.userSecret);
+  if (!util::VectorToObject(rp_id_hash, generate_req.appId,
+                            sizeof(generate_req.appId))) {
+    return MakeCredentialResponse::INVALID_REQUEST;
+  }
+  if (!util::VectorToObject(*user_secret, generate_req.userSecret,
+                            sizeof(generate_req.userSecret))) {
+    return MakeCredentialResponse::INVALID_REQUEST;
+  }
 
   struct u2f_generate_resp generate_resp = {};
 
@@ -526,10 +532,22 @@
   struct u2f_sign_req sign_req = {
       .flags = U2F_AUTH_ENFORCE  // Require user presence, consume.
   };
-  util::VectorToObject(rp_id_hash, sign_req.appId);
-  util::VectorToObject(*user_secret, sign_req.userSecret);
-  util::VectorToObject(credential_id, &sign_req.keyHandle);
-  util::VectorToObject(hash_to_sign, sign_req.hash);
+  if (!util::VectorToObject(rp_id_hash, sign_req.appId,
+                            sizeof(sign_req.appId))) {
+    return GetAssertionResponse::INVALID_REQUEST;
+  }
+  if (!util::VectorToObject(*user_secret, sign_req.userSecret,
+                            sizeof(sign_req.userSecret))) {
+    return GetAssertionResponse::INVALID_REQUEST;
+  }
+  if (!util::VectorToObject(credential_id, &sign_req.keyHandle,
+                            sizeof(sign_req.keyHandle))) {
+    return GetAssertionResponse::INVALID_REQUEST;
+  }
+  if (!util::VectorToObject(hash_to_sign, sign_req.hash,
+                            sizeof(sign_req.hash))) {
+    return GetAssertionResponse::INVALID_REQUEST;
+  }
 
   struct u2f_sign_resp sign_resp = {};
 
@@ -595,9 +613,18 @@
   }
 
   struct u2f_sign_req sign_req = {.flags = U2F_AUTH_CHECK_ONLY};
-  util::VectorToObject(rp_id_hash, sign_req.appId);
-  util::VectorToObject(*user_secret, sign_req.userSecret);
-  util::VectorToObject(credential_id, &sign_req.keyHandle);
+  if (!util::VectorToObject(rp_id_hash, sign_req.appId,
+                            sizeof(sign_req.appId))) {
+    return HasCredentialsResponse::INVALID_REQUEST;
+  }
+  if (!util::VectorToObject(*user_secret, sign_req.userSecret,
+                            sizeof(sign_req.userSecret))) {
+    return HasCredentialsResponse::INVALID_REQUEST;
+  }
+  if (!util::VectorToObject(credential_id, &sign_req.keyHandle,
+                            sizeof(sign_req.keyHandle))) {
+    return HasCredentialsResponse::INVALID_REQUEST;
+  }
 
   struct u2f_sign_resp sign_resp;
   base::AutoLock(tpm_proxy_->GetLock());