virtual_u2f_device.cc 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  1. // Copyright 2018 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "device/fido/virtual_u2f_device.h"
  5. #include <memory>
  6. #include <string>
  7. #include <tuple>
  8. #include <utility>
  9. #include "base/bind.h"
  10. #include "base/check_op.h"
  11. #include "base/containers/contains.h"
  12. #include "base/location.h"
  13. #include "base/numerics/safe_conversions.h"
  14. #include "base/threading/thread_task_runner_handle.h"
  15. #include "components/apdu/apdu_command.h"
  16. #include "components/apdu/apdu_response.h"
  17. #include "components/cbor/reader.h"
  18. #include "components/cbor/values.h"
  19. #include "crypto/ec_private_key.h"
  20. #include "device/fido/fido_constants.h"
  21. #include "device/fido/fido_parsing_utils.h"
  22. #include "device/fido/public_key.h"
  23. namespace device {
  24. using fido_parsing_utils::Append;
  25. namespace {
  26. // First byte of registration response is 0x05 for historical reasons
  27. // not detailed in the spec.
  28. constexpr uint8_t kU2fRegistrationResponseHeader = 0x05;
  29. // Returns an error response with the given status.
  30. absl::optional<std::vector<uint8_t>> ErrorStatus(
  31. apdu::ApduResponse::Status status) {
  32. return apdu::ApduResponse(std::vector<uint8_t>(), status)
  33. .GetEncodedResponse();
  34. }
  35. } // namespace
  36. // VirtualU2fDevice ----------------------------------------------------------
  37. // static
  38. bool VirtualU2fDevice::IsTransportSupported(FidoTransportProtocol transport) {
  39. return base::Contains(base::flat_set<FidoTransportProtocol>(
  40. {FidoTransportProtocol::kUsbHumanInterfaceDevice,
  41. FidoTransportProtocol::kBluetoothLowEnergy,
  42. FidoTransportProtocol::kNearFieldCommunication}),
  43. transport);
  44. }
  45. VirtualU2fDevice::VirtualU2fDevice() : VirtualFidoDevice() {}
  46. VirtualU2fDevice::VirtualU2fDevice(scoped_refptr<State> state)
  47. : VirtualFidoDevice(std::move(state)) {
  48. DCHECK(IsTransportSupported(mutable_state()->transport));
  49. }
  50. VirtualU2fDevice::~VirtualU2fDevice() = default;
  51. // Cancel operation is not supported on U2F devices.
  52. void VirtualU2fDevice::Cancel(CancelToken) {}
  53. FidoDevice::CancelToken VirtualU2fDevice::DeviceTransact(
  54. std::vector<uint8_t> command,
  55. DeviceCallback cb) {
  56. // Note, here we are using the code-under-test in this fake.
  57. auto parsed_command = apdu::ApduCommand::CreateFromMessage(command);
  58. // If malformed U2F request is received, respond with error immediately.
  59. if (!parsed_command) {
  60. base::ThreadTaskRunnerHandle::Get()->PostTask(
  61. FROM_HERE,
  62. base::BindOnce(
  63. std::move(cb),
  64. ErrorStatus(apdu::ApduResponse::Status::SW_INS_NOT_SUPPORTED)));
  65. return 0;
  66. }
  67. if (mutable_state()->simulate_invalid_response) {
  68. std::vector<uint8_t> nonsense = {1, 2, 3};
  69. auto response = apdu::ApduResponse(std::move(nonsense),
  70. apdu::ApduResponse::Status::SW_NO_ERROR)
  71. .GetEncodedResponse();
  72. base::ThreadTaskRunnerHandle::Get()->PostTask(
  73. FROM_HERE, base::BindOnce(std::move(cb), std::move(response)));
  74. return 0;
  75. }
  76. absl::optional<std::vector<uint8_t>> response;
  77. switch (parsed_command->ins()) {
  78. // Version request is defined by the U2F spec, but is never used in
  79. // production code.
  80. case base::strict_cast<uint8_t>(U2fApduInstruction::kVersion):
  81. break;
  82. case base::strict_cast<uint8_t>(U2fApduInstruction::kRegister):
  83. response = DoRegister(parsed_command->ins(), parsed_command->p1(),
  84. parsed_command->p2(), parsed_command->data());
  85. break;
  86. case base::strict_cast<uint8_t>(U2fApduInstruction::kSign):
  87. response = DoSign(parsed_command->ins(), parsed_command->p1(),
  88. parsed_command->p2(), parsed_command->data());
  89. break;
  90. default:
  91. response = ErrorStatus(apdu::ApduResponse::Status::SW_INS_NOT_SUPPORTED);
  92. }
  93. if (response) {
  94. // Call |callback| via the |MessageLoop| because |AuthenticatorImpl| doesn't
  95. // support callback hairpinning.
  96. base::ThreadTaskRunnerHandle::Get()->PostTask(
  97. FROM_HERE, base::BindOnce(std::move(cb), std::move(response)));
  98. }
  99. return 0;
  100. }
  101. base::WeakPtr<FidoDevice> VirtualU2fDevice::GetWeakPtr() {
  102. return weak_factory_.GetWeakPtr();
  103. }
  104. absl::optional<std::vector<uint8_t>> VirtualU2fDevice::DoRegister(
  105. uint8_t ins,
  106. uint8_t p1,
  107. uint8_t p2,
  108. base::span<const uint8_t> data) {
  109. if (data.size() != 64) {
  110. return ErrorStatus(apdu::ApduResponse::Status::SW_WRONG_LENGTH);
  111. }
  112. if (!SimulatePress()) {
  113. return absl::nullopt;
  114. }
  115. auto challenge_param = data.first<32>();
  116. auto application_parameter = data.last<32>();
  117. // Create key to register.
  118. // Note: Non-deterministic, you need to mock this out if you rely on
  119. // deterministic behavior.
  120. std::unique_ptr<PrivateKey> private_key(PrivateKey::FreshP256Key());
  121. std::vector<uint8_t> x962 = private_key->GetX962PublicKey();
  122. if (mutable_state()->u2f_invalid_public_key) {
  123. // Flip a bit in the x-coordinate, which will push the point off the curve.
  124. x962[10] ^= 1;
  125. }
  126. // Our key handles are simple hashes of the public key.
  127. const auto key_handle = crypto::SHA256Hash(x962);
  128. // Data to be signed.
  129. std::vector<uint8_t> sign_buffer;
  130. sign_buffer.reserve(1 + application_parameter.size() +
  131. challenge_param.size() + key_handle.size() + x962.size());
  132. sign_buffer.push_back(0x00);
  133. Append(&sign_buffer, application_parameter);
  134. Append(&sign_buffer, challenge_param);
  135. Append(&sign_buffer, key_handle);
  136. Append(&sign_buffer, x962);
  137. // Sign with attestation key.
  138. // Note: Non-deterministic, you need to mock this out if you rely on
  139. // deterministic behavior.
  140. std::vector<uint8_t> sig;
  141. std::unique_ptr<crypto::ECPrivateKey> attestation_private_key =
  142. crypto::ECPrivateKey::CreateFromPrivateKeyInfo(GetAttestationKey());
  143. bool status = Sign(attestation_private_key.get(), sign_buffer, &sig);
  144. DCHECK(status);
  145. // The spec says that the other bits of P1 should be zero. However, Chrome
  146. // sends Test User Presence (0x03) so we ignore those bits.
  147. bool individual_attestation_requested = p1 & kP1IndividualAttestation;
  148. const auto attestation_cert = GenerateAttestationCertificate(
  149. individual_attestation_requested, /*include_transports=*/true);
  150. if (!attestation_cert)
  151. return ErrorStatus(apdu::ApduResponse::Status::SW_INS_NOT_SUPPORTED);
  152. // U2F response data.
  153. std::vector<uint8_t> response;
  154. response.reserve(1 + x962.size() + 1 + key_handle.size() +
  155. attestation_cert->size() + sig.size());
  156. response.push_back(kU2fRegistrationResponseHeader);
  157. Append(&response, base::as_bytes(base::make_span(x962)));
  158. response.push_back(key_handle.size());
  159. Append(&response, key_handle);
  160. Append(&response, *attestation_cert);
  161. Append(&response, sig);
  162. RegistrationData registration_data(
  163. std::move(private_key), application_parameter, 1 /* signature counter */);
  164. registration_data.is_u2f = true;
  165. StoreNewKey(key_handle, std::move(registration_data));
  166. return apdu::ApduResponse(std::move(response),
  167. apdu::ApduResponse::Status::SW_NO_ERROR)
  168. .GetEncodedResponse();
  169. }
  170. absl::optional<std::vector<uint8_t>> VirtualU2fDevice::DoSign(
  171. uint8_t ins,
  172. uint8_t p1,
  173. uint8_t p2,
  174. base::span<const uint8_t> data) {
  175. if (!(p1 == kP1CheckOnly || p1 == kP1TupRequiredConsumed ||
  176. p1 == kP1IndividualAttestation) ||
  177. p2 != 0) {
  178. return ErrorStatus(apdu::ApduResponse::Status::SW_WRONG_DATA);
  179. }
  180. if (!SimulatePress()) {
  181. return absl::nullopt;
  182. }
  183. if (data.size() < 32 + 32 + 1)
  184. return ErrorStatus(apdu::ApduResponse::Status::SW_WRONG_LENGTH);
  185. auto challenge_param = data.first<32>();
  186. auto application_parameter = data.subspan<32, 32>();
  187. size_t key_handle_length = data[64];
  188. if (data.size() != 32 + 32 + 1 + key_handle_length)
  189. return ErrorStatus(apdu::ApduResponse::Status::SW_WRONG_LENGTH);
  190. auto key_handle = data.last(key_handle_length);
  191. auto* registration = FindRegistrationData(key_handle, application_parameter);
  192. if (!registration)
  193. return ErrorStatus(apdu::ApduResponse::Status::SW_WRONG_DATA);
  194. ++registration->counter;
  195. // First create the part of the response that gets signed over.
  196. std::vector<uint8_t> response;
  197. response.push_back(0x01); // Always pretend we got a touch.
  198. response.push_back(registration->counter >> 24);
  199. response.push_back(registration->counter >> 16);
  200. response.push_back(registration->counter >> 8);
  201. response.push_back(registration->counter);
  202. std::vector<uint8_t> sign_buffer;
  203. sign_buffer.reserve(application_parameter.size() + response.size() +
  204. challenge_param.size());
  205. Append(&sign_buffer, application_parameter);
  206. Append(&sign_buffer, response);
  207. Append(&sign_buffer, challenge_param);
  208. // Sign with credential key.
  209. std::vector<uint8_t> sig = registration->private_key->Sign(sign_buffer);
  210. if (mutable_state()->u2f_invalid_signature) {
  211. // Flip a bit in the ASN.1 header to make the signature structurally
  212. // invalid.
  213. sig[0] ^= 1;
  214. }
  215. // Add signature for full response.
  216. Append(&response, sig);
  217. return apdu::ApduResponse(std::move(response),
  218. apdu::ApduResponse::Status::SW_NO_ERROR)
  219. .GetEncodedResponse();
  220. }
  221. } // namespace device