use polyc_proto::proto::polychrome::state::v1 as pb;
use polyc_state::{
command::{CommandEnvelope, CommandMetadata, ResourceBounds},
digest::ContentDigest,
error::StateError,
id::{Audience, CommandId, NamespaceId, Purpose},
passkey::{
CredentialId, P256_KEY_BYTES, PasskeyCommand, PasskeyOperation, PasskeyPointer,
PasskeyRecord, PersonaId, passkey_scope,
},
revision::Revision,
versioned::{EntryExpectation, MAX_MUTATIONS_PER_TRANSACTION, MAX_TRANSACTION_PAYLOAD_BYTES},
};
use crate::wire::{fixed_bytes, malformed, required};
pub(crate) fn expected_to_wire(value: EntryExpectation) -> pb::StatePasskeyExpectedEntry {
use pb::__buffa::oneof::state_passkey_expected_entry::Expected;
let expected = match value {
EntryExpectation::Absent => Expected::from(pb::StatePasskeyExpectedAbsent {
__buffa_unknown_fields: buffa::UnknownFields::default(),
}),
EntryExpectation::Revision(revision) => Expected::from(pb::StatePasskeyExpectedRevision {
revision: revision.get(),
__buffa_unknown_fields: buffa::UnknownFields::default(),
}),
};
pb::StatePasskeyExpectedEntry {
expected: Some(expected),
__buffa_unknown_fields: buffa::UnknownFields::default(),
}
}
fn expected_from_wire(
value: pb::StatePasskeyExpectedEntry,
) -> Result<EntryExpectation, StateError> {
use pb::__buffa::oneof::state_passkey_expected_entry::Expected;
match value.expected {
Some(Expected::Absent(_)) => Ok(EntryExpectation::Absent),
Some(Expected::Revision(value)) => {
Ok(EntryExpectation::Revision(Revision::new(value.revision)))
}
None => Err(malformed(
"expected",
"a passkey operation declares its exact row premise",
)),
}
}
pub(crate) fn record_to_wire(value: &PasskeyRecord) -> pb::StatePasskey {
pb::StatePasskey {
credential_id: value.credential_id().as_bytes().to_vec(),
p256_public_key_sec1: value.p256_public_key_sec1().to_vec(),
rp_id: value.rp_id().to_owned(),
origin: value.origin().to_owned(),
created_at_ms: value.created_at_ms(),
revoked: value.is_revoked(),
revoked_at_ms: value.revoked_at_ms(),
__buffa_unknown_fields: buffa::UnknownFields::default(),
}
}
pub(crate) fn record_from_wire(value: pb::StatePasskey) -> Result<PasskeyRecord, StateError> {
let key = fixed_bytes::<P256_KEY_BYTES>("p256_public_key_sec1", &value.p256_public_key_sec1)?;
Ok(PasskeyRecord::from_parts(
CredentialId::new(value.credential_id),
key,
value.rp_id,
value.origin,
value.created_at_ms,
value.revoked,
value.revoked_at_ms,
))
}
pub(crate) fn pointer_to_wire(value: &PasskeyPointer) -> pb::StatePasskeyPointer {
pb::StatePasskeyPointer {
persona_id: value.persona().as_str().to_owned(),
claimed_at_ms: value.claimed_at_ms(),
__buffa_unknown_fields: buffa::UnknownFields::default(),
}
}
pub(crate) fn pointer_from_wire(value: pb::StatePasskeyPointer) -> PasskeyPointer {
PasskeyPointer::new(PersonaId::new(value.persona_id), value.claimed_at_ms)
}
pub(crate) fn operation_to_wire(value: &PasskeyOperation) -> pb::StatePasskeyOperation {
use pb::__buffa::oneof::state_passkey_operation::Operation;
let operation = match value {
PasskeyOperation::Enroll {
now_ms,
passkey,
pointer,
passkey_expected,
pointer_expected,
} => Operation::from(pb::StatePasskeyEnrollOperation {
now_ms: *now_ms,
passkey: buffa::MessageField::some(record_to_wire(passkey)),
pointer: buffa::MessageField::some(pointer_to_wire(pointer)),
passkey_expected: buffa::MessageField::some(expected_to_wire(*passkey_expected)),
pointer_expected: buffa::MessageField::some(expected_to_wire(*pointer_expected)),
__buffa_unknown_fields: buffa::UnknownFields::default(),
}),
PasskeyOperation::Revoke {
now_ms,
passkey,
passkey_expected,
} => Operation::from(pb::StatePasskeyRevokeOperation {
now_ms: *now_ms,
passkey: buffa::MessageField::some(record_to_wire(passkey)),
passkey_expected: buffa::MessageField::some(expected_to_wire(*passkey_expected)),
__buffa_unknown_fields: buffa::UnknownFields::default(),
}),
};
pb::StatePasskeyOperation {
operation: Some(operation),
__buffa_unknown_fields: buffa::UnknownFields::default(),
}
}
fn operation_from_wire(value: pb::StatePasskeyOperation) -> Result<PasskeyOperation, StateError> {
use pb::__buffa::oneof::state_passkey_operation::Operation;
match value.operation {
Some(Operation::Enroll(value)) => Ok(PasskeyOperation::Enroll {
now_ms: value.now_ms,
passkey: record_from_wire(required(
"passkey",
"an enrollment carries its result",
value.passkey,
)?)?,
pointer: pointer_from_wire(required(
"pointer",
"an enrollment carries its credential pointer",
value.pointer,
)?),
passkey_expected: expected_from_wire(required(
"passkey_expected",
"an enrollment carries its record premise",
value.passkey_expected,
)?)?,
pointer_expected: expected_from_wire(required(
"pointer_expected",
"an enrollment carries its pointer premise",
value.pointer_expected,
)?)?,
}),
Some(Operation::Revoke(value)) => Ok(PasskeyOperation::Revoke {
now_ms: value.now_ms,
passkey: record_from_wire(required(
"passkey",
"a revocation carries its result",
value.passkey,
)?)?,
passkey_expected: expected_from_wire(required(
"passkey_expected",
"a revocation carries its premise",
value.passkey_expected,
)?)?,
}),
None => Err(malformed(
"operation",
"a passkey command names one operation",
)),
}
}
pub(crate) fn metadata_to_wire(command: &PasskeyCommand) -> pb::StatePasskeyCommandMetadata {
let value = command.metadata();
pb::StatePasskeyCommandMetadata {
command_id: value.command_id().as_str().to_owned(),
namespace: value.scope().namespace().as_str().to_owned(),
purpose: value.envelope().purpose().as_str().to_owned(),
command_audience: value.envelope().audience().as_str().to_owned(),
digest: value.digest().as_bytes().to_vec(),
__buffa_unknown_fields: buffa::UnknownFields::default(),
}
}
pub(crate) fn command_from_wire(
metadata: pb::StatePasskeyCommandMetadata,
persona_id: String,
operation: pb::StatePasskeyOperation,
) -> Result<PasskeyCommand, StateError> {
let namespace = NamespaceId::new(metadata.namespace);
let digest = ContentDigest::from_bytes(fixed_bytes::<{ ContentDigest::LEN }>(
"digest",
&metadata.digest,
)?);
Ok(PasskeyCommand::new(
CommandMetadata::new(
CommandId::new(metadata.command_id),
polyc_state::passkey::family(),
digest,
passkey_scope(&namespace),
CommandEnvelope::new(
Purpose::new(metadata.purpose),
Audience::new(metadata.command_audience),
ResourceBounds::new(MAX_TRANSACTION_PAYLOAD_BYTES, MAX_MUTATIONS_PER_TRANSACTION),
),
),
PersonaId::new(persona_id),
operation_from_wire(operation)?,
))
}
#[cfg(test)]
mod tests {
use super::*;
const NOW: u64 = 1_700_000_000_000;
const fn key() -> [u8; P256_KEY_BYTES] {
[
0x04, 0x6b, 0x17, 0xd1, 0xf2, 0xe1, 0x2c, 0x42, 0x47, 0xf8, 0xbc, 0xe6, 0xe5, 0x63,
0xa4, 0x40, 0xf2, 0x77, 0x03, 0x7d, 0x81, 0x2d, 0xeb, 0x33, 0xa0, 0xf4, 0xa1, 0x39,
0x45, 0xd8, 0x98, 0xc2, 0x96, 0x4f, 0xe3, 0x42, 0xe2, 0xfe, 0x1a, 0x7f, 0x9b, 0x8e,
0xe7, 0xeb, 0x4a, 0x7c, 0x0f, 0x9e, 0x16, 0x2b, 0xce, 0x33, 0x57, 0x6b, 0x31, 0x5e,
0xce, 0xcb, 0xb6, 0x40, 0x68, 0x37, 0xbf, 0x51, 0xf5,
]
}
fn record() -> PasskeyRecord {
PasskeyRecord::from_parts(
CredentialId::new(b"cred".to_vec()),
key(),
"example.test".to_owned(),
"https://example.test".to_owned(),
NOW,
false,
0,
)
}
#[test]
fn every_operation_round_trips_through_the_wire() {
let operations = [
PasskeyOperation::Enroll {
now_ms: NOW,
passkey: record(),
pointer: PasskeyPointer::new(PersonaId::new("p-1"), NOW),
passkey_expected: EntryExpectation::Absent,
pointer_expected: EntryExpectation::Revision(Revision::new(9)),
},
PasskeyOperation::Revoke {
now_ms: NOW + 1,
passkey: record().revoking(NOW + 1),
passkey_expected: EntryExpectation::Revision(Revision::new(11)),
},
];
for operation in operations {
let restored = operation_from_wire(operation_to_wire(&operation))
.expect("an operation survives its own encoding");
assert_eq!(restored, operation);
}
}
#[test]
fn a_key_of_the_wrong_width_is_refused() {
let mut wire = record_to_wire(&record());
wire.p256_public_key_sec1.truncate(P256_KEY_BYTES - 1);
assert!(
record_from_wire(wire).is_err(),
"a truncated registered key was accepted"
);
let mut wire = record_to_wire(&record());
wire.p256_public_key_sec1.push(0);
assert!(
record_from_wire(wire).is_err(),
"an overlong registered key was accepted"
);
}
#[test]
fn the_rows_round_trip_through_the_wire() {
assert_eq!(
record_from_wire(record_to_wire(&record())).expect("record round trip"),
record()
);
let pointer = PasskeyPointer::new(PersonaId::new("p-1"), NOW);
assert_eq!(pointer_from_wire(pointer_to_wire(&pointer)), pointer);
}
#[test]
fn a_missing_oneof_and_a_missing_premise_fail_closed() {
assert!(
operation_from_wire(pb::StatePasskeyOperation::default()).is_err(),
"an operation with no variant was accepted"
);
assert!(
expected_from_wire(pb::StatePasskeyExpectedEntry::default()).is_err(),
"a premise with no variant was accepted"
);
let revoke = pb::StatePasskeyRevokeOperation {
now_ms: NOW,
passkey: buffa::MessageField::some(record_to_wire(&record())),
passkey_expected: buffa::MessageField::none(),
__buffa_unknown_fields: buffa::UnknownFields::default(),
};
assert!(
operation_from_wire(pb::StatePasskeyOperation {
operation: Some(
pb::__buffa::oneof::state_passkey_operation::Operation::from(revoke)
),
__buffa_unknown_fields: buffa::UnknownFields::default(),
})
.is_err(),
"a revocation with no premise was accepted"
);
}
}