pic_continuity/error.rs
1/*
2 * Copyright Nitro Agility S.r.l.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * https://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17//! Error types.
18//!
19//! [`RejectReason`] mirrors the individual checks of the Verifier procedure,
20//! so a rejection always says *which* check failed. [`ContinuityError`] wraps
21//! rejections together with encoding-level failures.
22
23use thiserror::Error;
24
25/// A semantic rejection: one of the Verifier or Prover checks failed.
26///
27/// Variants follow the settlement procedure of the Prover and Verifier
28/// specification (Section 3) so callers can map a rejection back to the
29/// exact spec check.
30#[derive(Debug, Clone, PartialEq, Eq, Error)]
31pub enum RejectReason {
32 // -- candidate shape (steps 1-5) --
33 /// The candidate could not be parsed into the expected artifact shape.
34 #[error("candidate is malformed: {0}")]
35 Malformed(String),
36 /// An artifact declares a profile other than the one this crate
37 /// implements ([`crate::PROFILE_0_2`]).
38 #[error("profile mismatch on {artifact}: expected {expected}, got {got}")]
39 ProfileMismatch {
40 /// Which artifact carried the mismatching profile.
41 artifact: &'static str,
42 /// The profile identifier this crate requires.
43 expected: String,
44 /// The profile identifier found in the artifact.
45 got: String,
46 },
47 /// A settled Continuity carried a non-null `transitions` member.
48 #[error("settled continuity must carry transitions = null")]
49 SettledCarriesTransitions,
50 /// A candidate Continuity carried a number of transitions other than
51 /// exactly one.
52 #[error("candidate continuity must carry exactly one transition, got {0}")]
53 TransitionCount(usize),
54
55 // -- proof of relationship (steps 6-11) --
56 /// `proof_of_relationship.type` is not the type the validator accepts.
57 #[error("proof_of_relationship.type not accepted: {0}")]
58 PorType(String),
59 /// The Proof of Relationship evidence failed validation.
60 #[error("proof of relationship rejected: {0}")]
61 PorRejected(String),
62 /// A workload signature over a candidate artifact did not verify.
63 #[error("workload signature invalid on {0}")]
64 WorkloadSignature(&'static str),
65
66 // -- checkpoint binding (steps 12-16) --
67 /// `root.pca` is not the exact bytes of a currently trusted checkpoint.
68 #[error("root.pca is not the currently trusted checkpoint")]
69 UntrustedCheckpoint,
70 /// The recomputed SHA-256 of `root.pca` differs from `root.pca_hash`.
71 #[error("root.pca_hash does not match SHA-256 of the exact root.pca bytes")]
72 PcaHashMismatch,
73 /// `predecessor.type` is not [`crate::PREDECESSOR_TYPE_PCA`].
74 #[error("predecessor.type must be \"pca\"")]
75 PredecessorType,
76 /// `predecessor.hash` does not match the trusted checkpoint bytes.
77 #[error("predecessor.hash does not match the trusted checkpoint bytes")]
78 PredecessorHashMismatch,
79 /// The proposed position is not exactly checkpoint position + 1.
80 #[error("transition.position must equal checkpoint position + 1")]
81 PositionProgression,
82 /// `previous_challenge` does not echo the checkpoint's `next_challenge`.
83 #[error("previous_challenge does not match the checkpoint next_challenge")]
84 ChallengeContinuity,
85 /// The proposed `next_challenge` is missing, empty, or not fresh.
86 #[error("next_challenge is missing or empty")]
87 NextChallengeInvalid,
88
89 // -- attenuation (step 17) --
90 /// A removal bitmap set a bit for an index the predecessor section does
91 /// not have.
92 #[error("remove bitmap references a nonexistent index in section {0}")]
93 BitmapIndexOutOfRange(&'static str),
94 /// A removal bitmap is empty or carries trailing zero bytes.
95 #[error("remove bitmap is not canonical (empty or trailing zero bytes)")]
96 BitmapNotCanonical,
97 /// Two execution-contract additions resolved to the same canonical key.
98 #[error("duplicate execution-contract addition key: {0}")]
99 DuplicateAdditionKey(String),
100 /// An authority value is empty or not a valid canonical tuple value.
101 #[error("invalid authority value for key {0}")]
102 InvalidAuthorityValue(String),
103 /// The execution contract would end up with no attributes.
104 #[error("execution contract must contain at least one attribute")]
105 EmptyExecutionContract,
106
107 // -- evidence and binding (step 18) --
108 /// Deployment-required request/execution binding failed.
109 #[error("request/execution binding rejected")]
110 RequestBinding,
111 /// Executor evidence or execution-contract conformance failed.
112 #[error("executor evidence / execution-contract conformance rejected")]
113 ContractConformance,
114
115 // -- non-expansion, revocation, policy (step 19) --
116 /// The materialized successor would carry authority its predecessor did
117 /// not have.
118 #[error("authority non-expansion violated")]
119 NonExpansion,
120 /// The continuity state is revoked.
121 #[error("continuity state is revoked")]
122 Revoked,
123 /// Local deployment policy denied the advancement.
124 #[error("local policy denied the advancement")]
125 PolicyDenied,
126
127 // -- settled-artifact verification --
128 /// A settlement-authority (realm) signature did not verify.
129 #[error("settlement-authority signature invalid on {0}")]
130 RealmSignature(&'static str),
131}
132
133/// Any failure while producing or validating continuity state.
134#[derive(Debug, Error)]
135pub enum ContinuityError {
136 /// A semantic Verifier or Prover check failed.
137 #[error(transparent)]
138 Reject(#[from] RejectReason),
139
140 /// A COSE envelope could not be built, parsed, or verified.
141 #[error("COSE error: {0}")]
142 Cose(#[from] crate::cose::CoseError),
143
144 /// CBOR (de)serialization of a payload failed.
145 #[error("CBOR encoding failed: {0}")]
146 Cbor(String),
147
148 /// JSON (de)serialization of a JSON protocol object failed.
149 #[error("JSON error: {0}")]
150 Json(String),
151
152 /// The JWS envelope of the PIC Token could not be built or parsed.
153 #[error("JWS error: {0}")]
154 Jws(String),
155}