https://github.com/trilemma-dev/required
Parser and evaluator for Apple's Code Signing Requirement Language
https://github.com/trilemma-dev/required
codesign csreq macos secrequirement security
Last synced: 7 months ago
JSON representation
Parser and evaluator for Apple's Code Signing Requirement Language
- Host: GitHub
- URL: https://github.com/trilemma-dev/required
- Owner: trilemma-dev
- Created: 2022-05-18T04:53:59.000Z (about 4 years ago)
- Default Branch: main
- Last Pushed: 2022-06-17T12:05:51.000Z (almost 4 years ago)
- Last Synced: 2025-10-21T10:53:58.185Z (7 months ago)
- Topics: codesign, csreq, macos, secrequirement, security
- Language: Swift
- Homepage:
- Size: 156 KB
- Stars: 8
- Watchers: 2
- Forks: 2
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# Required
Parse requirement and requirement sets into their abstract syntax tree form and then evaluate them.
Apple provides a compiler for their
[Code Signing Requirement Language](https://developer.apple.com/library/archive/documentation/Security/Conceptual/CodeSigningGuide/RequirementLang/RequirementLang.html)
in the form of
[`SecRequirementCreateWithString`](https://developer.apple.com/documentation/security/1394522-secrequirementcreatewithstring),
but does not expose a parser and its corresponding abstract syntax tree. This package does precisely that.
While Apple does provide an evaluator for a
[`SecRequirement`](https://developer.apple.com/documentation/security/secrequirement) in the form of
[`SecStaticCodeCheckValidity`](https://developer.apple.com/documentation/security/1395784-secstaticcodecheckvalidity),
there is no ability to see _why_ validation has failed. This package provides detailed explanations.
## Example
To see whether and how an application satisfies its designated requirement:
```swift
// Retrieve the designated requirement for Numbers
let url = URL(fileURLWithPath: "/Applications/Numbers.app")
var code: SecStaticCode?
SecStaticCodeCreateWithPath(url as CFURL, [], &code)
var requirement: SecRequirement?
SecCodeCopyDesignatedRequirement(code!, [], &requirement)
// See whether and how Numbers satisifies its designated requirement
let abstractRequirement = try Parser.parse(requirement: requirement!)
let evaluation = try abstractRequirement.evaluateForStaticCode(code!)
print("Does \(url.lastPathComponent) satisfy its designated requirement?")
print(evaluation.isSatisfied ? "Yes" : "No")
print("\nEvaluation tree:")
print(evaluation.prettyDescription)
```
Requirements can be provided either as `SecRequirement`s as shown in the above code snippet or as `String`s. Running
this example outputs:
```
Does Numbers.app satisfy its designated requirement?
Yes
Evaluation tree:
and {true}
|--() {true}
| \--or {true}
| |--and {true}
| | |--anchor apple generic {true}
| | \--certificate leaf[field.1.2.840.113635.100.6.1.9] {true}
| \--and {false}
| |--and {false}
| | |--and {false}
| | | |--anchor apple generic {true}
| | | \--certificate 1[field.1.2.840.113635.100.6.2.6] {false}¹
| | \--certificate leaf[field.1.2.840.113635.100.6.1.13] {false}²
| \--certificate leaf[subject.OU] = K36BKF7T3D {false}³
\--identifier "com.apple.iWork.Numbers" {true}
Constraints not satisfied:
1. The certificate does not contain OID 1.2.840.113635.100.6.2.6
2. The certificate does not contain OID 1.2.840.113635.100.6.1.13
3. The certificate does not contain element subject.OU
```
Each leaf node of the evaluation tree which was not satisfied is annotated with a superscript number. Those numbers are
then used at the bottom to provide explanations for why the leaf node was not satified.
See this package's DocC documentation for more details.
## Apple Resources
Apple has published several documents that discuss to varying degrees their requirements language:
- [Code Signing Requirement Language](https://developer.apple.com/library/archive/documentation/Security/Conceptual/CodeSigningGuide/RequirementLang/RequirementLang.html#//apple_ref/doc/uid/TP40005929-CH5-SW1)
- [TN2206: macOS Code Signing In Depth](https://developer.apple.com/library/archive/technotes/tn2206/_index.html)
- [TN3125: Inside Code Signing: Provisioning Profiles](https://developer.apple.com/documentation/technotes/tn3125-inside-code-signing-provisioning-profiles)
- [TN3126: Inside Code Signing: Hashes](https://developer.apple.com/documentation/technotes/tn3126-inside-code-signing-hashes)
- [TN3127: Inside Code Signing: Requirements](https://developer.apple.com/documentation/technotes/tn3127-inside-code-signing-requirements)