Yicheng Li | 1090c90 | 2020-11-10 11:31:43 -0800 | [diff] [blame] | 1 | // Copyright 2020 The Chromium OS 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 | |
| 5 | #ifndef U2FD_WEBAUTHN_STORAGE_H_ |
| 6 | #define U2FD_WEBAUTHN_STORAGE_H_ |
| 7 | |
Yicheng Li | 30b6abc | 2020-11-13 14:51:15 -0800 | [diff] [blame] | 8 | #include <memory> |
Yicheng Li | 1090c90 | 2020-11-10 11:31:43 -0800 | [diff] [blame] | 9 | #include <string> |
| 10 | #include <vector> |
| 11 | |
| 12 | #include <base/files/file_path.h> |
| 13 | #include <base/optional.h> |
| 14 | #include <brillo/secure_blob.h> |
Yicheng Li | e7a2625 | 2021-02-03 12:18:37 -0800 | [diff] [blame] | 15 | #include <metrics/metrics_library.h> |
Yicheng Li | 1090c90 | 2020-11-10 11:31:43 -0800 | [diff] [blame] | 16 | |
| 17 | namespace u2f { |
| 18 | |
| 19 | constexpr int kCredentialSecretSize = 32; |
| 20 | |
| 21 | // Used to persist credentials as JSON in the user's cryptohome. |
| 22 | struct WebAuthnRecord { |
Yicheng Li | aeb3d68 | 2020-11-19 11:07:57 -0800 | [diff] [blame] | 23 | // Credential id in bytes. Will be hex-encoded. |
Yicheng Li | 1090c90 | 2020-11-10 11:31:43 -0800 | [diff] [blame] | 24 | std::string credential_id; |
Yicheng Li | aeb3d68 | 2020-11-19 11:07:57 -0800 | [diff] [blame] | 25 | // Secret to use for this credential in bytes. Will be base64-encoded. |
Yicheng Li | 4d27fa7 | 2020-12-10 11:09:21 -0800 | [diff] [blame] | 26 | // We do not use SecureBlob here because: 1. Loading many SecureBlobs in |
| 27 | // memory will hit RLIMIT_MEMLOCK. 2. With physical presence and auth-time |
| 28 | // secret, this per-credential secret is more like a salt. |
| 29 | brillo::Blob secret; |
Yicheng Li | aeb3d68 | 2020-11-19 11:07:57 -0800 | [diff] [blame] | 30 | // The relying party id. |
Yicheng Li | 1090c90 | 2020-11-10 11:31:43 -0800 | [diff] [blame] | 31 | std::string rp_id; |
Yicheng Li | d73908d | 2021-02-17 09:58:11 -0800 | [diff] [blame] | 32 | // The relying party display name. |
| 33 | std::string rp_display_name; |
Yicheng Li | aeb3d68 | 2020-11-19 11:07:57 -0800 | [diff] [blame] | 34 | // The PublicKeyCredentialUserEntity.id property in bytes. Will be |
| 35 | // hex-encoded. |
Yicheng Li | 1090c90 | 2020-11-10 11:31:43 -0800 | [diff] [blame] | 36 | std::string user_id; |
Yicheng Li | aeb3d68 | 2020-11-19 11:07:57 -0800 | [diff] [blame] | 37 | // The PublicKeyCredentialUserEntity.display_name property. |
| 38 | std::string user_display_name; |
| 39 | // Timestamp of record creation. |
Yicheng Li | 1090c90 | 2020-11-10 11:31:43 -0800 | [diff] [blame] | 40 | double timestamp; |
Yicheng Li | d73908d | 2021-02-17 09:58:11 -0800 | [diff] [blame] | 41 | // Whether this credential is a resident_key. |
| 42 | bool is_resident_key; |
Yicheng Li | 1090c90 | 2020-11-10 11:31:43 -0800 | [diff] [blame] | 43 | }; |
| 44 | |
| 45 | // WebAuthnStorage manages the WebAuthn credential id records for the current |
| 46 | // user. It supports CRUD operations on WebAuthn records. |
| 47 | // TODO(yichengli): Add support for deleting records. |
| 48 | class WebAuthnStorage { |
| 49 | public: |
| 50 | WebAuthnStorage(); |
| 51 | virtual ~WebAuthnStorage(); |
| 52 | |
| 53 | // Adds |record| to in-memory records and persist it on disk. |
| 54 | virtual bool WriteRecord(const WebAuthnRecord& record); |
| 55 | // Loads records for |sanitized_user| to memory. |
| 56 | virtual bool LoadRecords(); |
| 57 | |
Yicheng Li | e7a2625 | 2021-02-03 12:18:37 -0800 | [diff] [blame] | 58 | virtual bool SendRecordCountToUMA(MetricsLibraryInterface* metrics); |
| 59 | |
Yicheng Li | 1090c90 | 2020-11-10 11:31:43 -0800 | [diff] [blame] | 60 | // Clears in-memory records. |
| 61 | virtual void Reset(); |
| 62 | |
Yicheng Li | 4d27fa7 | 2020-12-10 11:09:21 -0800 | [diff] [blame] | 63 | virtual base::Optional<brillo::Blob> GetSecretByCredentialId( |
Yicheng Li | 1090c90 | 2020-11-10 11:31:43 -0800 | [diff] [blame] | 64 | const std::string& credential_id); |
| 65 | |
| 66 | virtual base::Optional<WebAuthnRecord> GetRecordByCredentialId( |
| 67 | const std::string& credential_id); |
| 68 | |
Yicheng Li | 30b6abc | 2020-11-13 14:51:15 -0800 | [diff] [blame] | 69 | // Writes auth-time secret hash to disk. |
| 70 | bool PersistAuthTimeSecretHash(const brillo::Blob& hash); |
| 71 | // Loads auth-time secret hash from disk. |
| 72 | std::unique_ptr<brillo::Blob> LoadAuthTimeSecretHash(); |
| 73 | |
Yicheng Li | 1090c90 | 2020-11-10 11:31:43 -0800 | [diff] [blame] | 74 | // Sets the |allow_access_| which determines whether the backing storage |
| 75 | // location can be accessed or not. |
| 76 | void set_allow_access(bool allow_access) { allow_access_ = allow_access; } |
| 77 | |
| 78 | void set_sanitized_user(const std::string& sanitized_user) { |
| 79 | sanitized_user_ = sanitized_user; |
| 80 | } |
| 81 | |
| 82 | void SetRootPathForTesting(const base::FilePath& root_path); |
| 83 | |
| 84 | private: |
| 85 | base::FilePath root_path_; |
| 86 | // Whether access to storage is allowed. |
| 87 | bool allow_access_ = false; |
| 88 | // The current user that we are reading/writing records for. |
| 89 | std::string sanitized_user_; |
| 90 | // All WebAuthn credential records for |sanitized_user_|. |
| 91 | std::vector<WebAuthnRecord> records_; |
| 92 | }; |
| 93 | |
| 94 | } // namespace u2f |
| 95 | |
| 96 | #endif // U2FD_WEBAUTHN_STORAGE_H_ |