diff options
author | Igor <igorcov@chromium.org> | 2018-06-21 16:39:57 +0200 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2018-11-07 11:40:45 -0800 |
commit | a771ac1213c4b0066d81ded4b8132f9506d7634d (patch) | |
tree | 892bfd2b0a654fef263d055cb54d95f70435a6a2 /include | |
parent | 8d48f6e390823d2a89808ea6f9dc8c7348134440 (diff) | |
download | chrome-ec-a771ac1213c4b0066d81ded4b8132f9506d7634d.tar.gz |
Cr50: Add valid PCR value for pinweaver
In order to bind the PIN authentication to PCR4, required for
additional security, a set of valid PCR criteria is added as metadata
in the leaf of the tree. Each criteria has a bitmask of PCR indexes
and the digest sha256 that should be obtained from concatenation of
PCR values for the respective indexes. Pinweaver will handle
both types of requests, in old and the new format.
For migration of old leaves that don't have the new field, the
process expects cryptohome to detect that the leaf needs migration
based on protocol used, leaf version and if the list of PCR
criteria is empty. In case the leaf needs migration, cryptohome
should insert a new leaf with the same data and remove the old one.
The PCR criteria set is created on Chrome OS side. Details of that
implementation is in
https://chromium-review.googlesource.com/c/chromiumos/platform2/+/1124856
BRANCH=none
BUG=chromium:812165
TEST=sudo V=1 make run-pinweaver -j
pinweaver_client selftest
Deploy old image on a device and create an account setting a PIN code
as well. Deploy the new image and new CR50 build. Login and check that the
migration works well. Also try to put device to sleep and unlock. Check
that a new credential creation with new version works as well and sleep +
unlock work as expected. Extend PCR4 on device and check that login/unlock
works only for the user which obfuscated_username was used to extend the
PCR. Also check that authentication works with cases when old cryptohome
and new pinweaver is deployed, or old pinweaver and new cryptohome.
CQ-DEPEND=CL:1124856
Change-Id: If778c4e46b9945afadfd2af7d58353005624d668
Signed-off-by: igorcov@chromium.org
Reviewed-on: https://chromium-review.googlesource.com/1112014
Commit-Ready: Igor <igorcov@chromium.org>
Tested-by: Igor <igorcov@chromium.org>
Reviewed-by: Igor <igorcov@chromium.org>
Reviewed-by: Randall Spangler <rspangler@chromium.org>
Reviewed-by: Andrey Pronin <apronin@chromium.org>
Diffstat (limited to 'include')
-rw-r--r-- | include/pinweaver.h | 14 | ||||
-rw-r--r-- | include/pinweaver_tpm_imports.h | 6 | ||||
-rw-r--r-- | include/pinweaver_types.h | 73 |
3 files changed, 75 insertions, 18 deletions
diff --git a/include/pinweaver.h b/include/pinweaver.h index 7c7a8fb1cb..1f373ba582 100644 --- a/include/pinweaver.h +++ b/include/pinweaver.h @@ -65,18 +65,6 @@ struct PW_PACKED pw_log_storage_t { }; /* Do not remove fields within the same PW_LEAF_MAJOR_VERSION. */ -/* Unencrypted part of the leaf data. - */ -struct PW_PACKED leaf_public_data_t { - struct label_t label; - struct delay_schedule_entry_t delay_schedule[PW_SCHED_COUNT]; - - /* State used to rate limit. */ - struct pw_timestamp_t timestamp; - struct attempt_count_t attempt_count; -}; - -/* Do not remove fields within the same PW_LEAF_MAJOR_VERSION. */ /* Encrypted part of the leaf data. */ struct PW_PACKED PW_ALIGN_TO_BLK leaf_sensitive_data_t { @@ -142,7 +130,7 @@ void pinweaver_init(void); * merkle_tree->root needs to be updated with new_root outside of this function. */ int pw_handle_request(struct merkle_tree_t *merkle_tree, - const struct pw_request_t *request, + struct pw_request_t *request, struct pw_response_t *response); /******************************************************************************/ diff --git a/include/pinweaver_tpm_imports.h b/include/pinweaver_tpm_imports.h index 7dad418910..879bb6bbb8 100644 --- a/include/pinweaver_tpm_imports.h +++ b/include/pinweaver_tpm_imports.h @@ -22,4 +22,10 @@ */ void get_storage_seed(void *buf, size_t *len); +/* Reads PCR values for indexes from bitmask and computes sha256 digest of + * concatenated values. Populates the digest in |sha256_of_selected_pcr|. + */ +uint8_t get_current_pcr_digest(const uint8_t bitmask[2], + uint8_t sha256_of_selected_pcr[32]); + #endif /* __CROS_EC_INCLUDE_PINWEAVER_TPM_IMPORTS_H */ diff --git a/include/pinweaver_types.h b/include/pinweaver_types.h index 4200082696..cc4b5832b3 100644 --- a/include/pinweaver_types.h +++ b/include/pinweaver_types.h @@ -12,9 +12,10 @@ #define PW_PACKED __packed -#define PW_PROTOCOL_VERSION 0 +#define PW_PROTOCOL_VERSION 1 #define PW_LEAF_MAJOR_VERSION 0 -#define PW_LEAF_MINOR_VERSION 0 +/* The change from version zero is the addition of valid_pcr_value metadata */ +#define PW_LEAF_MINOR_VERSION 1 #define PW_MAX_MESSAGE_SIZE (2048 - 12 /* sizeof(struct tpm_cmd_header) */) @@ -45,6 +46,7 @@ enum pw_error_codes_enum { PW_ERR_NV_EMPTY, PW_ERR_NV_LENGTH_MISMATCH, PW_ERR_NV_VERSION_MISMATCH, + PW_ERR_PCR_NOT_MATCH, }; /* Represents the log2(fan out) of a tree. */ @@ -105,11 +107,26 @@ struct PW_PACKED delay_schedule_entry_t { struct time_diff_t time_diff; }; +/* Represents a set of PCR values hashed into a single digest. This is a + * criterion that can be added to a leaf. A leaf is valid only if at least one + * of the valid_pcr_value_t criteria it contains is satisfied. + */ +struct PW_PACKED valid_pcr_value_t { + /* The set of PCR indexes that have to pass the validation. */ + uint8_t bitmask[2]; + /* The hash digest of the PCR values contained in the bitmask */ + uint8_t digest[32]; +}; + /* Represents the number of entries in the delay schedule table which can be * used to determine the next time an authentication attempt can be made. */ #define PW_SCHED_COUNT 16 +/* Represents the maximum number of criteria for valid PCR values. + */ +#define PW_MAX_PCR_CRITERIA_COUNT 2 + /* Number of bytes required to store a secret. */ #define PW_SECRET_SIZE 32 @@ -143,6 +160,19 @@ struct PW_PACKED leaf_header_t { uint16_t sec_len; }; +/* Do not remove fields within the same PW_LEAF_MAJOR_VERSION. */ +/* Unencrypted part of the leaf data. + */ +struct PW_PACKED leaf_public_data_t { + struct label_t label; + struct delay_schedule_entry_t delay_schedule[PW_SCHED_COUNT]; + + /* State used to rate limit. */ + struct pw_timestamp_t timestamp; + struct attempt_count_t attempt_count; + struct valid_pcr_value_t valid_pcr_criteria[PW_MAX_PCR_CRITERIA_COUNT]; +}; + /* Represents a struct of unknown length to be imported to process a request. */ struct PW_PACKED unimported_leaf_data_t { /* This is first so that head.leaf_version will be the first field @@ -209,12 +239,30 @@ struct PW_PACKED pw_request_reset_tree_t { struct height_t height; }; +/* This is only used for parsing incoming data of version 0:0 */ +struct PW_PACKED pw_request_insert_leaf00_t { + struct label_t label; + struct delay_schedule_entry_t delay_schedule[PW_SCHED_COUNT]; + uint8_t low_entropy_secret[PW_SECRET_SIZE]; + uint8_t high_entropy_secret[PW_SECRET_SIZE]; + uint8_t reset_secret[PW_SECRET_SIZE]; + /* This is a variable length field because it size is determined at + * runtime based on the chosen tree parameters. Its size is treated as + * zero by the compiler so the computed size needs to be added to the + * size of this struct in order to determine the actual size. This field + * has the form: + * uint8_t path_hashes[get_path_auxiliary_hash_count(.)][PW_HASH_SIZE]; + */ + uint8_t path_hashes[][PW_HASH_SIZE]; +}; + struct PW_PACKED pw_request_insert_leaf_t { struct label_t label; struct delay_schedule_entry_t delay_schedule[PW_SCHED_COUNT]; uint8_t low_entropy_secret[PW_SECRET_SIZE]; uint8_t high_entropy_secret[PW_SECRET_SIZE]; uint8_t reset_secret[PW_SECRET_SIZE]; + struct valid_pcr_value_t valid_pcr_criteria[PW_MAX_PCR_CRITERIA_COUNT]; /* This is a variable length field because it size is determined at * runtime based on the chosen tree parameters. Its size is treated as * zero by the compiler so the computed size needs to be added to the @@ -241,11 +289,24 @@ struct PW_PACKED pw_request_try_auth_t { struct unimported_leaf_data_t unimported_leaf_data; }; +/* This is only used to send response data of version 0:0 */ +struct PW_PACKED pw_response_try_auth00_t { + /* Valid for the PW_ERR_RATE_LIMIT_REACHED return code only. */ + struct time_diff_t seconds_to_wait; + /* Valid for the EC_SUCCESS return code only. */ + uint8_t high_entropy_secret[PW_SECRET_SIZE]; + /* Valid for the PW_ERR_LOWENT_AUTH_FAILED and EC_SUCCESS return codes. + */ + struct unimported_leaf_data_t unimported_leaf_data; +}; + struct PW_PACKED pw_response_try_auth_t { /* Valid for the PW_ERR_RATE_LIMIT_REACHED return code only. */ struct time_diff_t seconds_to_wait; /* Valid for the EC_SUCCESS return code only. */ uint8_t high_entropy_secret[PW_SECRET_SIZE]; + /* Valid for the EC_SUCCESS return code only. */ + uint8_t reset_secret[PW_SECRET_SIZE]; /* Valid for the PW_ERR_LOWENT_AUTH_FAILED and EC_SUCCESS return codes. */ struct unimported_leaf_data_t unimported_leaf_data; @@ -312,6 +373,7 @@ struct PW_PACKED pw_request_t { struct pw_request_header_t header; union { struct pw_request_reset_tree_t reset_tree; + struct pw_request_insert_leaf00_t insert_leaf00; struct pw_request_insert_leaf_t insert_leaf; struct pw_request_remove_leaf_t remove_leaf; struct pw_request_try_auth_t try_auth; @@ -326,6 +388,7 @@ struct PW_PACKED pw_response_t { union { struct pw_response_insert_leaf_t insert_leaf; + struct pw_response_try_auth00_t try_auth00; struct pw_response_try_auth_t try_auth; struct pw_response_reset_auth_t reset_auth; /* An array with as many entries as are present in the log up to @@ -341,9 +404,9 @@ struct PW_PACKED pw_response_t { * defined so that meaningful parameter limits can be set to validate the tree * parameters. * - * 1536 was chosen because it is 3/4 of 2048 and allows for a maximum tree - * height of 16 for the default fan-out of 4. + * 1024 was chosen because it is 1/2 of 2048 and allows for a maximum tree + * height of 10 for the default fan-out of 4. */ -#define PW_MAX_PATH_SIZE 1536 +#define PW_MAX_PATH_SIZE 1024 #endif /* __CROS_EC_INCLUDE_PINWEAVER_TYPES_H */ |