virtual_ctap2_device.h 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344
  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. #ifndef DEVICE_FIDO_VIRTUAL_CTAP2_DEVICE_H_
  5. #define DEVICE_FIDO_VIRTUAL_CTAP2_DEVICE_H_
  6. #include <stdint.h>
  7. #include <list>
  8. #include <memory>
  9. #include <vector>
  10. #include "base/component_export.h"
  11. #include "base/containers/span.h"
  12. #include "base/memory/scoped_refptr.h"
  13. #include "components/cbor/values.h"
  14. #include "device/fido/attested_credential_data.h"
  15. #include "device/fido/authenticator_data.h"
  16. #include "device/fido/authenticator_supported_options.h"
  17. #include "device/fido/ctap_get_assertion_request.h"
  18. #include "device/fido/ctap_make_credential_request.h"
  19. #include "device/fido/fido_constants.h"
  20. #include "device/fido/fido_types.h"
  21. #include "device/fido/virtual_fido_device.h"
  22. #include "third_party/abseil-cpp/absl/types/optional.h"
  23. namespace device {
  24. class VirtualU2fDevice;
  25. class COMPONENT_EXPORT(DEVICE_FIDO) VirtualCtap2Device
  26. : public VirtualFidoDevice {
  27. public:
  28. struct COMPONENT_EXPORT(DEVICE_FIDO) Config {
  29. // IncludeCredential enumerates possible behaviours when deciding whether to
  30. // return credential information in an assertion response.
  31. enum class IncludeCredential {
  32. // ONLY_IF_NEEDED causes the credential information to be included when
  33. // the
  34. // allowlist has zero or several entries.
  35. ONLY_IF_NEEDED,
  36. // ALWAYS causes credential information to always be returned. This is
  37. // a valid behaviour per the CTAP2 spec.
  38. ALWAYS,
  39. // NEVER causes credential information to never be returned. This is
  40. // invalid behaviour whenever the allowlist is not of length one.
  41. NEVER,
  42. };
  43. Config();
  44. Config(const Config&);
  45. Config& operator=(const Config&);
  46. ~Config();
  47. base::flat_set<Ctap2Version> ctap2_versions = {
  48. std::begin(kCtap2Versions2_0), std::end(kCtap2Versions2_0)};
  49. // u2f_support, if true, makes this device a dual-protocol (i.e. CTAP2 and
  50. // U2F) device.
  51. bool u2f_support = false;
  52. bool pin_support = false;
  53. bool is_platform_authenticator = false;
  54. bool internal_uv_support = false;
  55. bool pin_uv_auth_token_support = false;
  56. bool resident_key_support = false;
  57. bool credential_management_support = false;
  58. bool bio_enrollment_support = false;
  59. bool bio_enrollment_preview_support = false;
  60. uint8_t bio_enrollment_capacity = 10;
  61. uint8_t bio_enrollment_samples_required = 4;
  62. bool cred_protect_support = false;
  63. bool hmac_secret_support = false;
  64. bool large_blob_support = false;
  65. // Support for setting a min PIN length and forcing pin change.
  66. bool min_pin_length_support = false;
  67. // min_pin_length_extension_support, if true, enables support for the
  68. // minPinLength extension. See
  69. // https://fidoalliance.org/specs/fido-v2.1-ps-20210615/fido-client-to-authenticator-protocol-v2.1-ps-20210615.html#sctn-minpinlength-extension
  70. bool min_pin_length_extension_support = false;
  71. bool always_uv = false;
  72. // The space available to store a large blob. In real authenticators this
  73. // may change depending on the number of resident credentials. We treat this
  74. // as a fixed size area for the large blob.
  75. size_t available_large_blob_storage = 1024;
  76. bool cred_blob_support = false;
  77. // include_transports_in_attestation_certificate controls whether a
  78. // transports extension will be included in the attestation certificate
  79. // returned from a makeCredential operation.
  80. bool include_transports_in_attestation_certificate = true;
  81. // transports_in_get_info, if not empty, contains the transports that will
  82. // be reported via getInfo.
  83. std::vector<FidoTransportProtocol> transports_in_get_info;
  84. IncludeCredential include_credential_in_assertion_response =
  85. IncludeCredential::ONLY_IF_NEEDED;
  86. // force_cred_protect, if set and if |cred_protect_support| is true, is a
  87. // credProtect level that will be forced for all registrations. This
  88. // overrides any level requested in the makeCredential.
  89. absl::optional<device::CredProtect> force_cred_protect;
  90. // default_cred_protect, if |cred_protect_support| is true, is the
  91. // credProtect level that will be set for makeCredential requests that do
  92. // not specify one.
  93. device::CredProtect default_cred_protect = device::CredProtect::kUVOptional;
  94. // max_credential_count_in_list, if non-zero, is the value to return for
  95. // maxCredentialCountInList in the authenticatorGetInfo reponse.
  96. // CTAP2_ERR_LIMIT_EXCEEDED will be returned for requests with an allow or
  97. // exclude list exceeding this limit. Note that the request handler
  98. // implementations require maxCredentialIdLength be set in order for
  99. // maxCredentialCountInList to be respected.
  100. uint32_t max_credential_count_in_list = 0;
  101. // max_credential_id_length, if non-zero, is the value to return for
  102. // maxCredentialIdLength in the authenticatorGetInfo reponse.
  103. // CTAP2_ERR_LIMIT_EXCEEDED will be returned for requests with an allow or
  104. // exclude list containing a credential ID exceeding this limit.
  105. uint32_t max_credential_id_length = 0;
  106. // resident_credential_storage is the number of resident credentials that
  107. // the device will store before returning KEY_STORE_FULL.
  108. size_t resident_credential_storage = 3;
  109. // return_immediate_invalid_credential_error causes an INVALID_CREDENTIAL
  110. // error to be returned from GetAssertion, before getting a touch, when no
  111. // credentials are recognised. This behaviour is exhibited by some CTAP2
  112. // authenticators in the wild.
  113. bool return_immediate_invalid_credential_error = false;
  114. // return_attested_cred_data_in_get_assertion_response causes
  115. // attestedCredentialData to be included in the authenticator data of an
  116. // GetAssertion response.
  117. bool return_attested_cred_data_in_get_assertion_response = false;
  118. // reject_large_allow_and_exclude_lists causes the authenticator to respond
  119. // with an error if an allowList or an excludeList contains more than one
  120. // credential ID. This can be used to simulate errors with oversized
  121. // credential lists in an authenticator that does not support batching (i.e.
  122. // maxCredentialCountInList and maxCredentialIdSize).
  123. bool reject_large_allow_and_exclude_lists = false;
  124. // reject_silent_authenticator_requests causes the authenticator to return
  125. // an error if a up=false assertion request is received.
  126. bool reject_silent_authentication_requests = false;
  127. // Whether internal user verification should succeed or not.
  128. bool user_verification_succeeds = true;
  129. // allow_invalid_utf8_in_credential_entities indicates whether
  130. // InjectResidentKey() may be called with a PublicKeyCredentialRpEntity and
  131. // PublicKeyCredentialUserEntity containing a trailing partial UTF-8
  132. // sequence. This is used to simulate a security key that truncates strings
  133. // at a pre-defined byte length without concern for UTF-8 validity of the
  134. // result.
  135. bool allow_invalid_utf8_in_credential_entities = false;
  136. // add_extra_extension causes an unsolicited extension to be added in the
  137. // authenticator extensions output.
  138. bool add_extra_extension = false;
  139. // reject_all_extensions causes the authenticator to return a CTAP error if
  140. // a makeCredential or getAssertion request carries any extension.
  141. bool reject_all_extensions = false;
  142. // advertised_algorithms is the contents of the algorithms field in the
  143. // getInfo. If empty then no such field is reported. The virtual
  144. // authenticator only enables the algorithms listed here, unless the list is
  145. // empty in which case all algorithms except for |kInvalidForTesting| are
  146. // enabled.
  147. std::vector<device::CoseAlgorithmIdentifier> advertised_algorithms = {
  148. device::CoseAlgorithmIdentifier::kEs256,
  149. };
  150. // support_enterprise_attestation indicates whether enterprise attestation
  151. // support will be advertised in the getInfo response and whether requests
  152. // will be honored during makeCredential.
  153. bool support_enterprise_attestation = false;
  154. // always_return_enterprise_attestation causes the authenticator to,
  155. // invalidly, always signal that the returned attestation is an enterprise
  156. // attestation, even when it wasn't requested.
  157. bool always_return_enterprise_attestation = false;
  158. // enterprise_attestation_rps enumerates the RP IDs that will trigger
  159. // enterprise attestation when the platform requests ep=1.
  160. std::vector<std::string> enterprise_attestation_rps;
  161. // ignore_u2f_credentials causes credentials created over the
  162. // authenticator's U2F interface not to be available over CTAP2 for
  163. // assertions.
  164. bool ignore_u2f_credentials = false;
  165. // pin_protocol is the PIN protocol version that this authenticator supports
  166. // and reports in the pinProtocols field of the authenticatorGetInfo
  167. // response.
  168. PINUVAuthProtocol pin_protocol = PINUVAuthProtocol::kV1;
  169. // internal_account_chooser indicates that the authenticator has a screen
  170. // and thus presents the account chooser for discoverable credential
  171. // assertions itself. This causes userSelected to be asserted on those
  172. // responses.
  173. bool internal_account_chooser = false;
  174. // override_response_map allows overriding the response for a given command
  175. // with a given code. The actual command won't be executed.
  176. base::flat_map<CtapRequestCommand, CtapDeviceResponseCode>
  177. override_response_map;
  178. // allow_non_resident_credential_creation_without_uv corresponds to the
  179. // make_cred_uv_not_required field in AuthenticatorSupportedOptions.
  180. bool allow_non_resident_credential_creation_without_uv = false;
  181. };
  182. VirtualCtap2Device();
  183. VirtualCtap2Device(scoped_refptr<State> state, const Config& config);
  184. VirtualCtap2Device(const VirtualCtap2Device&) = delete;
  185. VirtualCtap2Device& operator=(const VirtualCtap2Device&) = delete;
  186. ~VirtualCtap2Device() override;
  187. // Configures and sets a PIN on the authenticator.
  188. void SetPin(std::string pin);
  189. // Sets whether to force a PIN change before accepting pinUvAuthToken
  190. // requests.
  191. void SetForcePinChange(bool force_pin_change);
  192. // Sets the minimum accepted PIN length.
  193. void SetMinPinLength(uint32_t min_pin_length);
  194. // FidoDevice:
  195. void Cancel(CancelToken) override;
  196. CancelToken DeviceTransact(std::vector<uint8_t> command,
  197. DeviceCallback cb) override;
  198. base::WeakPtr<FidoDevice> GetWeakPtr() override;
  199. private:
  200. // RequestState encapsulates state for what CTAP 2.1 calls "stateful commands"
  201. // (https://drafts.fidoalliance.org/fido-2/latest/fido-client-to-authenticator-protocol-v2.1-rd-20210308.html#authenticator-api).
  202. struct RequestState {
  203. RequestState();
  204. RequestState(RequestState&) = delete;
  205. RequestState& operator=(RequestState&) = delete;
  206. ~RequestState();
  207. // Reset should be called at the beginning of every authenticator operation
  208. // that is not a direct continuation of another stateful operation. CTAP 2.1
  209. // specifies that authenticators may assume that stateful commands are never
  210. // interleaved by other operations.
  211. void Reset() {
  212. pending_assertions.clear();
  213. pending_rps.clear();
  214. pending_registrations.clear();
  215. large_blob_buffer.clear();
  216. large_blob_expected_next_offset = 0;
  217. large_blob_expected_length = 0;
  218. }
  219. // pending_assertions contains the second and subsequent assertions
  220. // resulting from a GetAssertion call. These values are awaiting a
  221. // GetNextAssertion request.
  222. std::vector<std::vector<uint8_t>> pending_assertions;
  223. // pending_rps contains the remaining RPs to return from a previous
  224. // authenticatorCredentialManagement/enumerateRPs command.
  225. std::list<device::PublicKeyCredentialRpEntity> pending_rps;
  226. // pending_registrations contains the remaining |is_resident| registrations
  227. // to return from a previous
  228. // authenticatorCredentialManagement/enumerateCredentials command.
  229. std::list<cbor::Value::MapValue> pending_registrations;
  230. // Buffer that gets progressively filled with large blob fragments until
  231. // committed.
  232. std::vector<uint8_t> large_blob_buffer;
  233. uint64_t large_blob_expected_next_offset = 0;
  234. uint64_t large_blob_expected_length = 0;
  235. };
  236. // Init performs initialization that's common across the constructors.
  237. void Init(std::vector<ProtocolVersion> versions);
  238. // CheckUserVerification implements the first, common steps of
  239. // makeCredential and getAssertion from the CTAP2 spec.
  240. enum class CheckUserVerificationMode {
  241. kGetAssertion,
  242. kMakeCredential,
  243. kMakeCredentialUvNotRequired,
  244. };
  245. absl::optional<CtapDeviceResponseCode> CheckUserVerification(
  246. CheckUserVerificationMode mode,
  247. const AuthenticatorGetInfoResponse& authenticator_info,
  248. const std::string& rp_id,
  249. const absl::optional<std::vector<uint8_t>>& pin_auth,
  250. const absl::optional<PINUVAuthProtocol>& pin_protocol,
  251. base::span<const uint8_t> client_data_hash,
  252. UserVerificationRequirement user_verification,
  253. bool user_presence_required,
  254. bool* out_user_verified);
  255. absl::optional<CtapDeviceResponseCode> OnMakeCredential(
  256. base::span<const uint8_t> request,
  257. std::vector<uint8_t>* response);
  258. absl::optional<CtapDeviceResponseCode> OnGetAssertion(
  259. base::span<const uint8_t> request,
  260. std::vector<uint8_t>* response);
  261. CtapDeviceResponseCode OnGetNextAssertion(base::span<const uint8_t> request,
  262. std::vector<uint8_t>* response);
  263. absl::optional<CtapDeviceResponseCode> OnPINCommand(
  264. base::span<const uint8_t> request,
  265. std::vector<uint8_t>* response);
  266. CtapDeviceResponseCode OnCredentialManagement(
  267. base::span<const uint8_t> request,
  268. std::vector<uint8_t>* response);
  269. CtapDeviceResponseCode OnBioEnrollment(base::span<const uint8_t> request,
  270. std::vector<uint8_t>* response);
  271. CtapDeviceResponseCode OnLargeBlobs(base::span<const uint8_t> request,
  272. std::vector<uint8_t>* response);
  273. CtapDeviceResponseCode OnAuthenticatorGetInfo(
  274. std::vector<uint8_t>* response) const;
  275. void InitPendingRPs();
  276. void GetNextRP(cbor::Value::MapValue* response_map);
  277. void InitPendingRegistrations(base::span<const uint8_t> rp_id_hash);
  278. void RegenerateKeyAgreementKey();
  279. AttestedCredentialData ConstructAttestedCredentialData(
  280. base::span<const uint8_t> key_handle,
  281. std::unique_ptr<PublicKey> public_key);
  282. size_t remaining_resident_credentials() const;
  283. bool SupportsAtLeast(Ctap2Version ctap2_version) const;
  284. std::unique_ptr<VirtualU2fDevice> u2f_device_;
  285. const Config config_;
  286. RequestState request_state_;
  287. base::WeakPtrFactory<FidoDevice> weak_factory_{this};
  288. };
  289. } // namespace device
  290. #endif // DEVICE_FIDO_VIRTUAL_CTAP2_DEVICE_H_