Skip to main content

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}