Skip to main content

Module cpace

Module cpace 

Source
Expand description

The CPace exchange that hands the credentials of an enrolled device to a new one, reverse engineered from 1Password’s WASM module: the local crypto, and the requests that carry it.

The new device proves it knows the verification code the user reads off the enrolled device, and both sides end up with the same key to move the credential bundle through the server.

StructsΒ§

Ad πŸ”’
The associated data of a CPace message.
MsgA πŸ”’
The first CPace message, from the enrolled device.

ConstantsΒ§

CREDENTIAL_BUNDLE_AAD πŸ”’
EXCHANGE_KEY_INFO πŸ”’
PADDING_LENGTH πŸ”’
Pads the second hash input through the passcode hash to one 128 byte SHA-512 block.
PASSCODE_ITERATIONS πŸ”’
TRANSPORT_KEY_ID πŸ”’
The key id of the exchange key, which also keys the first step of deriving it.

FunctionsΒ§

calculate_auth_a_hash πŸ”’
The point both sides agree on: ya times the client scalar.
calculate_auth_b_hash πŸ”’
The session secret, hashed over the whole transcript.
calculate_auth_b_tag_b πŸ”’
Calculates the shared secret authB and the tagb that proves knowing it.
calculate_first_hash πŸ”’
Binds the exchange to the user, the sign-in address and the enrollment.
calculate_msg_b πŸ”’
Calculates msgb, the new device’s answer to msga.
calculate_passcode_hash πŸ”’
Stretches the verification code, salted by the enrolled device.
calculate_second_hash πŸ”’
The input of the CPace generator, which binds the passcode to the first hash and the session.
calculate_tag_b πŸ”’
The MAC of msgb under a key derived from authB.
cpace_endpoint πŸ”’
The CPace endpoints, under the enrollment’s cpace prefix.
decompress_point πŸ”’
Fails for anything but the canonical encoding of a point.
decrypt_credentials πŸ”’
Decrypts the credential bundle the enrolled device shared.
derive_exchange_key πŸ”’
Derives the key that encrypts the credential bundle in transit from authB.
enrollment_endpoint πŸ”’
v3/device/enrollments/{enrollmentUuid}/{method}
expect_success πŸ”’
The server confirms each CPace message with success: 1.
get_tag_a πŸ”’
Waits for the enrolled device’s taga, which only verify_tag_a looks at.
hmac_sha384 πŸ”’
hmac_sha512 πŸ”’
leb128_prefixed πŸ”’
Prefixes every field with its length as LEB128, and concatenates them.
multiply_by_client_scalar πŸ”’
Multiplies by the scalar the client secret reduces to, and compresses the result.
parse_msg_a πŸ”’
Parses the JSON of msga, after its base64 layer is removed.
perform_cpace πŸ”’
Runs the whole exchange over rest with a fresh random client secret and returns the credentials the enrolled device shared.
perform_cpace_with_client_secret πŸ”’
The CPace exchange with the client secret injected so the test vectors can pin it.
post_json_until_result πŸ”’
POSTs until the endpoint answers a body instead of the empty 200 it sends while the enrolled device has not replied yet. The web frontend retries the same way.
request_encrypted_credentials πŸ”’
Waits for the credential bundle, still encrypted for the exchange key and so invisible to the server that relays it.
request_msg_a πŸ”’
Fetches and parses the enrolled device’s first message.
send_msg_b πŸ”’
Replies with msgb and expects the server to accept it.
send_tag_b πŸ”’
Replies with tagb and expects the server to accept it.
sha512 πŸ”’
sign_in_body πŸ”’
The body every CPace request carries besides the messages themselves.
verify_tag_a πŸ”’
Would check taga, which proves the enrolled device knows the verification code too.
write_leb128_prefixed πŸ”’
Writes data after its length, as the little endian base 128 varint the WASM module uses.