apple_codesign/
error.rs

1// This Source Code Form is subject to the terms of the Mozilla Public
2// License, v. 2.0. If a copy of the MPL was not distributed with this
3// file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
5use {
6    crate::{macho_universal::UniversalMachOError, remote_signing::RemoteSignError},
7    cryptographic_message_syntax::CmsError,
8    std::path::PathBuf,
9    thiserror::Error,
10    x509_certificate::{KeyAlgorithm, X509CertificateError},
11};
12
13/// Unified error type for Apple code signing.
14#[derive(Debug, Error)]
15pub enum AppleCodesignError {
16    #[error("unknown command")]
17    CliUnknownCommand,
18
19    #[error("bad argument")]
20    CliBadArgument,
21
22    #[error("{0}")]
23    CliGeneralError(String),
24
25    #[error("I/O error: {0}")]
26    Io(#[from] std::io::Error),
27
28    #[error("CLI error: {0}")]
29    CliDialoguer(#[from] dialoguer::Error),
30
31    #[error("binary parsing error: {0}")]
32    Goblin(#[from] goblin::error::Error),
33
34    #[error("invalid Mach-O binary: {0}")]
35    InvalidBinary(String),
36
37    #[error("invalid binary index within Mach-O: {0}")]
38    InvalidMachOIndex(usize),
39
40    #[error("binary does not have code signature data")]
41    BinaryNoCodeSignature,
42
43    #[error("binary does not have code directory blob")]
44    BinaryNoCodeDirectory,
45
46    #[error("X.509 certificate handler error: {0}")]
47    X509(#[from] X509CertificateError),
48
49    #[error("CMS error: {0}")]
50    Cms(#[from] CmsError),
51
52    #[error("JSON serialization error: {0}")]
53    SerdeJson(#[from] serde_json::Error),
54
55    #[error("YAML serialization error: {0}")]
56    SerdeYaml(#[from] serde_yaml::Error),
57
58    #[error("glob error: {0}")]
59    GlobPattern(#[from] glob::PatternError),
60
61    #[error("problems reported during verification")]
62    VerificationProblems,
63
64    #[error("certificate error: {0}")]
65    CertificateGeneric(String),
66
67    #[error("certificate decode error: {0}")]
68    CertificateDecode(bcder::decode::DecodeError<std::convert::Infallible>),
69
70    #[error("PEM error: {0}")]
71    CertificatePem(pem::PemError),
72
73    #[error("X.509 certificate parsing error: {0}")]
74    X509Parse(String),
75
76    #[error("unsupported key algorithm in certificate: {0:?}")]
77    CertificateUnsupportedKeyAlgorithm(KeyAlgorithm),
78
79    #[error("unspecified cryptography error in certificate")]
80    CertificateRing(ring::error::Unspecified),
81
82    #[error("bad string value in certificate: {0:?}")]
83    CertificateCharset(bcder::string::CharSetError),
84
85    #[error("DER: {0}")]
86    Der(#[from] der::Error),
87
88    #[error("error parsing version string: {0}")]
89    VersionParse(#[from] semver::Error),
90
91    #[error("XAR error: {0}")]
92    Xar(#[from] apple_xar::Error),
93
94    #[error("Apple flat package error: {0}")]
95    FlatPackage(#[from] apple_flat_package::Error),
96
97    #[error("unable to locate __TEXT segment")]
98    MissingText,
99
100    #[error("unable to locate __LINKEDIT segment")]
101    MissingLinkedit,
102
103    #[error("bad header magic in {0}")]
104    BadMagic(&'static str),
105
106    #[error("data structure parse error: {0}")]
107    Scroll(#[from] scroll::Error),
108
109    #[error("error parsing plist XML: {0}")]
110    PlistParseXml(plist::Error),
111
112    #[error("error serializing plist to XML: {0}")]
113    PlistSerializeXml(plist::Error),
114
115    #[error("malformed identifier string in code directory")]
116    CodeDirectoryMalformedIdentifier,
117
118    #[error("malformed team name string in code directory")]
119    CodeDirectoryMalformedTeam,
120
121    #[error("plist error in code directory: {0}")]
122    CodeDirectoryPlist(plist::Error),
123
124    #[error("SuperBlob data is malformed")]
125    SuperblobMalformed,
126
127    #[error("specified path is not of a recognized type")]
128    UnrecognizedPathType,
129
130    #[error("functionality not implemented: {0}")]
131    Unimplemented(&'static str),
132
133    #[error("unknown code signature flag: {0}")]
134    CodeSignatureUnknownFlag(String),
135
136    #[error("entitlements data not valid UTF-8: {0}")]
137    EntitlementsBadUtf8(std::str::Utf8Error),
138
139    #[error("error with plist DER encoding: {0}")]
140    PlistDer(String),
141
142    #[error("unknown executable segment flag: {0}")]
143    ExecutableSegmentUnknownFlag(String),
144
145    #[error("unknown code requirement opcode: {0}")]
146    RequirementUnknownOpcode(u32),
147
148    #[error("unknown code requirement match expression: {0}")]
149    RequirementUnknownMatchExpression(u32),
150
151    #[error("code requirement data malformed: {0}")]
152    RequirementMalformed(&'static str),
153
154    #[error("plist error in code resources: {0}")]
155    ResourcesPlist(plist::Error),
156
157    #[error("base64 error in code resources: {0}")]
158    ResourcesBase64(base64::DecodeError),
159
160    #[error("plist parse error in code resources: {0}")]
161    ResourcesPlistParse(String),
162
163    #[error("bad regular expression in code resources: {0}; {1}")]
164    ResourcesBadRegex(String, regex::Error),
165
166    #[error("__LINKEDIT isn't final Mach-O segment")]
167    LinkeditNotLast,
168
169    #[error("__LINKEDIT segment contains data after signature")]
170    DataAfterSignature,
171
172    #[error("insufficient room to write code signature load command")]
173    LoadCommandNoRoom,
174
175    #[error("error writing Mach-O: {0}")]
176    MachOWrite(String),
177
178    #[error("no identifier string provided")]
179    NoIdentifier,
180
181    #[error("no signing certificate")]
182    NoSigningCertificate,
183
184    #[error("signature data too large (please report this issue)")]
185    SignatureDataTooLarge,
186
187    #[error("invalid builder operation: {0}")]
188    SignatureBuilder(&'static str),
189
190    #[error("HTTP error: {0}")]
191    Reqwest(#[from] reqwest::Error),
192
193    #[error("unknown digest algorithm")]
194    DigestUnknownAlgorithm,
195
196    #[error("unsupported digest algorithm")]
197    DigestUnsupportedAlgorithm,
198
199    #[error("unspecified digest error")]
200    DigestUnspecified,
201
202    #[error("deriving identifier from path: {0}")]
203    PathIdentifier(String),
204
205    #[error("error interfacing with directory-based bundle: {0}")]
206    DirectoryBundle(anyhow::Error),
207
208    #[error("nested bundle does not exist: {0}")]
209    BundleUnknown(String),
210
211    #[error("bundle Info.plist does not define CFBundleIdentifier: {0}")]
212    BundleNoIdentifier(PathBuf),
213
214    #[error("bundle Info.plist does not define CFBundleExecutable: {0}")]
215    BundleNoMainExecutable(PathBuf),
216
217    #[error(
218        "unexpected resource rule evaluation when signing nested bundle (please report this issue)"
219    )]
220    BundleUnexpectedResourceRuleResult,
221
222    #[error("unable to parse settings scope: {0}")]
223    ParseSettingsScope(String),
224
225    #[error("incorrect password given when decrypting PFX data")]
226    PfxBadPassword,
227
228    #[error("error parsing PFX data: {0}")]
229    PfxParseError(String),
230
231    #[cfg(target_os = "macos")]
232    #[error("SecurityFramework error: {0}")]
233    SecurityFramework(#[from] security_framework::base::Error),
234
235    #[error("error interfacing with macOS keychain: {0}")]
236    KeychainError(String),
237
238    #[error("error interfacing with Windows certificate store: {0}")]
239    WindowsStoreError(String),
240
241    #[error("failed to find certificate satisfying requirements: {0}")]
242    CertificateNotFound(String),
243
244    #[error("the given OID does not match a recognized Apple certificate authority extension")]
245    OidIsntCertificateAuthority,
246
247    #[error("the given OID does not match a recognized Apple extended key usage extension")]
248    OidIsntExtendedKeyUsage,
249
250    #[error("the given OID does not match a recognized Apple code signing extension")]
251    OidIsntCodeSigningExtension,
252
253    #[error("error building certificate: {0}")]
254    CertificateBuildError(String),
255
256    #[error("unknown certificate profile: {0}")]
257    UnknownCertificateProfile(String),
258
259    #[error("unknown code execution policy: {0}")]
260    UnknownPolicy(String),
261
262    #[error("unable to generate code requirement policy: {0}")]
263    PolicyFormulationError(String),
264
265    #[error("error producing universal Mach-O binary: {0}")]
266    UniversalMachO(#[from] UniversalMachOError),
267
268    #[error("walkdir error: {0}")]
269    WalkDir(#[from] walkdir::Error),
270
271    #[error("zip error: {0}")]
272    ZipError(#[from] zip::result::ZipError),
273
274    #[error("error writing app metadata XML: {0}")]
275    AppMetadataXml(xml::writer::Error),
276
277    #[error("error writing XML: {0}")]
278    XmlWrite(xml::writer::Error),
279
280    #[error("signing XAR archives requires a signing certificate")]
281    XarNoAdhoc,
282
283    #[error("App Store Connect API Key error: {0}")]
284    AppStoreConnectApiKey(String),
285
286    #[error("Could not find App Store Connect API key in default search locations")]
287    AppStoreConnectApiKeyNotFound,
288
289    #[error("signing settings are not compatible with notarization")]
290    ForNotarizationInvalidSettings,
291
292    #[error("do not know how to notarize {0}")]
293    NotarizeUnsupportedPath(PathBuf),
294
295    #[error("no authentication credentials to perform notarization request")]
296    NotarizeNoAuthCredentials,
297
298    #[error("reached time limit waiting for notarization to complete")]
299    NotarizeWaitLimitReached,
300
301    #[error("error interacting with Notary API")]
302    NotarizeServerError,
303
304    #[error("notarization rejected: StatusCode={0}; StatusMessage={1}")]
305    NotarizeRejected(i64, String),
306
307    #[error("notarization is incomplete (no status code and message)")]
308    NotarizeIncomplete,
309
310    #[error("notarization package is invalid")]
311    NotarizeInvalid,
312
313    #[error("notarization record not in response: {0}")]
314    NotarizationRecordNotInResponse(String),
315
316    #[error("signed ticket data not found in ticket lookup response (this should not happen)")]
317    NotarizationRecordNoSignedTicket,
318
319    #[error("signedTicket in notarization ticket lookup response is not BYTES: {0}")]
320    NotarizationRecordSignedTicketNotBytes(String),
321
322    #[error("notarization ticket lookup failure: {0}: {1}")]
323    NotarizationLookupFailure(String, String),
324
325    #[error("error decoding base64 in notarization ticket: {0}")]
326    NotarizationRecordDecodeFailure(base64::DecodeError),
327
328    #[error("unable to determine app platform from bundle")]
329    BundleUnknownAppPlatform,
330
331    #[error("do not support stapling {0:?} bundles")]
332    StapleUnsupportedBundleType(apple_bundles::BundlePackageType),
333
334    #[error("XAR file is malformed; cannot staple")]
335    StapleMalformedXar,
336
337    #[error("failed to find main executable in bundle")]
338    StapleMainExecutableNotFound,
339
340    #[error("do not know how to staple {0}")]
341    StapleUnsupportedPath(PathBuf),
342
343    #[error("bad header magic in DMG; not a DMG file?")]
344    DmgBadMagic,
345
346    #[error("cannot notarize DMG without an embedded signature")]
347    DmgNotarizeNoSignature,
348
349    #[error("cannot staple DMG without an embedded signature")]
350    DmgStapleNoSignature,
351
352    #[error("failed to find certificate in smartcard slot {0}")]
353    SmartcardNoCertificate(String),
354
355    #[error("failed to authenticate with smartcard device")]
356    SmartcardFailedAuthentication,
357
358    #[cfg(feature = "yubikey")]
359    #[error("YubiKey error: {0}")]
360    YubiKey(#[from] yubikey::Error),
361
362    #[error("poisoned lock")]
363    PoisonedLock,
364
365    #[error("internal API / logic error: {0}")]
366    LogicError(String),
367
368    #[error("zip structs error: {0}")]
369    ZipStructs(#[from] zip_structs::zip_error::ZipReadError),
370
371    #[error("remote signing error: {0}")]
372    RemoteSign(#[from] RemoteSignError),
373
374    #[cfg(feature = "notarize")]
375    #[error("bytestream creation error: {0}")]
376    AwsByteStream(#[from] aws_smithy_types::byte_stream::error::Error),
377
378    #[cfg(feature = "notarize")]
379    #[error("s3 upload error: {0}")]
380    AwsS3PutObject(
381        aws_smithy_types::error::display::DisplayErrorContext<
382            aws_sdk_s3::error::SdkError<aws_sdk_s3::operation::put_object::PutObjectError>,
383        >,
384    ),
385
386    #[error("bad time value")]
387    BadTime,
388
389    #[error("{0}")]
390    Anyhow(#[from] anyhow::Error),
391
392    #[error("plist: {0}")]
393    Plist(#[from] plist::Error),
394
395    #[error("config error: {0:?}")]
396    Figment(#[from] figment::Error),
397
398    #[error("environment constraints: {0}")]
399    EnvironmentConstraint(String),
400}
401
402/// Result type for this library.
403pub type Result<T, E = AppleCodesignError> = std::result::Result<T, E>;