Skip to content

Commit 1a46528

Browse files
committed
[SignedArchive] Give the verifier the ability to check for the version number. Give resign the ability to resign more than one file. Move SIGArchiveCommon.m into the SignedArchive folder and add it to the project.
1 parent 2160084 commit 1a46528

File tree

8 files changed

+161
-60
lines changed

8 files changed

+161
-60
lines changed

SignedArchive/SignedArchive.xcodeproj/project.pbxproj

+24-16
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
53F5895321C9B527004A372B /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 53F5895221C9B527004A372B /* main.m */; };
1515
53F5895721C9B564004A372B /* libSignedArchive.a in Frameworks */ = {isa = PBXBuildFile; fileRef = A6BC8B2321C8D80D00796BF3 /* libSignedArchive.a */; };
1616
53F5895B21C9C1F2004A372B /* SIGVerificationAlgorithm.m in Sources */ = {isa = PBXBuildFile; fileRef = 53F5895A21C9C1F2004A372B /* SIGVerificationAlgorithm.m */; };
17+
A665C1C9243A4D8E00F623F0 /* SIGArchiveCommon.h in Headers */ = {isa = PBXBuildFile; fileRef = A665C1C8243A4D8E00F623F0 /* SIGArchiveCommon.h */; };
18+
A665C1CD243A4DF000F623F0 /* SIGArchiveCommon.m in Sources */ = {isa = PBXBuildFile; fileRef = A665C1CC243A4DF000F623F0 /* SIGArchiveCommon.m */; };
1719
A6BC8B1921C8D5B500796BF3 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = A6BC8B1821C8D5B500796BF3 /* main.m */; };
1820
A6BC8B2C21C8D81F00796BF3 /* SIGArchiveBuilder.m in Sources */ = {isa = PBXBuildFile; fileRef = A6BC8AEB21C78A3000796BF3 /* SIGArchiveBuilder.m */; };
1921
A6BC8B2D21C8D81F00796BF3 /* SIGArchiveChunk.m in Sources */ = {isa = PBXBuildFile; fileRef = A6BC8B0321C8B65900796BF3 /* SIGArchiveChunk.m */; };
@@ -117,6 +119,8 @@
117119
53F5895021C9B527004A372B /* extract */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = extract; sourceTree = BUILT_PRODUCTS_DIR; };
118120
53F5895221C9B527004A372B /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
119121
53F5895A21C9C1F2004A372B /* SIGVerificationAlgorithm.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SIGVerificationAlgorithm.m; sourceTree = "<group>"; };
122+
A665C1C8243A4D8E00F623F0 /* SIGArchiveCommon.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SIGArchiveCommon.h; sourceTree = "<group>"; };
123+
A665C1CC243A4DF000F623F0 /* SIGArchiveCommon.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SIGArchiveCommon.m; sourceTree = "<group>"; };
120124
A6BC8ADF21C789DA00796BF3 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
121125
A6BC8AEA21C78A3000796BF3 /* SIGArchiveBuilder.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SIGArchiveBuilder.h; sourceTree = "<group>"; };
122126
A6BC8AEB21C78A3000796BF3 /* SIGArchiveBuilder.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SIGArchiveBuilder.m; sourceTree = "<group>"; };
@@ -211,8 +215,8 @@
211215
A6BC8AD121C789DA00796BF3 = {
212216
isa = PBXGroup;
213217
children = (
214-
A6F5F3B122EE28010093FC81 /* resign */,
215218
A6BC8ADD21C789DA00796BF3 /* SignedArchive */,
219+
A6F5F3B122EE28010093FC81 /* resign */,
216220
A6BC8B1721C8D5B500796BF3 /* sign */,
217221
A6BC8B3C21C8E30600796BF3 /* verify */,
218222
53F5895121C9B527004A372B /* extract */,
@@ -236,37 +240,39 @@
236240
A6BC8ADD21C789DA00796BF3 /* SignedArchive */ = {
237241
isa = PBXGroup;
238242
children = (
243+
A6BC8ADF21C789DA00796BF3 /* Info.plist */,
239244
A6BC8AEA21C78A3000796BF3 /* SIGArchiveBuilder.h */,
245+
A6BC8AEB21C78A3000796BF3 /* SIGArchiveBuilder.m */,
240246
A6BC8B0221C8B65900796BF3 /* SIGArchiveChunk.h */,
247+
A6BC8B0321C8B65900796BF3 /* SIGArchiveChunk.m */,
248+
A665C1C8243A4D8E00F623F0 /* SIGArchiveCommon.h */,
249+
A665C1CC243A4DF000F623F0 /* SIGArchiveCommon.m */,
241250
A6BC8AFE21C79A8000796BF3 /* SIGArchiveReader.h */,
251+
A6BC8AFF21C79A8000796BF3 /* SIGArchiveReader.m */,
242252
A6BC8AFA21C7982800796BF3 /* SIGArchiveVerifier.h */,
253+
A6BC8AFB21C7982800796BF3 /* SIGArchiveVerifier.m */,
243254
A6BC8B0621C8BB3700796BF3 /* SIGCertificate.h */,
255+
A6BC8B0721C8BB3700796BF3 /* SIGCertificate.m */,
244256
A6BC8B4821C95F8900796BF3 /* SIGError.h */,
257+
A6BC8B4921C95F8900796BF3 /* SIGError.m */,
245258
A6BC8AEE21C78C1700796BF3 /* SIGIdentity.h */,
259+
A6BC8AEF21C78C1700796BF3 /* SIGIdentity.m */,
246260
A6BC8AF621C791A700796BF3 /* SIGKey.h */,
261+
A6BC8AF721C791A700796BF3 /* SIGKey.m */,
247262
A6BC8AF221C78C5E00796BF3 /* SIGKeychain.h */,
263+
A6BC8AF321C78C5E00796BF3 /* SIGKeychain.m */,
248264
A6BC8B0E21C8CE7600796BF3 /* SIGPartialInputStream.h */,
265+
A6BC8B0F21C8CE7600796BF3 /* SIGPartialInputStream.m */,
249266
53F5893C21C9AF38004A372B /* SIGPolicy.h */,
267+
53F5893D21C9AF38004A372B /* SIGPolicy.m */,
250268
A6BC8B5021C965C100796BF3 /* SIGSHA2SigningAlgorithm.h */,
269+
A6BC8B5121C965C100796BF3 /* SIGSHA2SigningAlgorithm.m */,
251270
A6BC8B5821C96E4200796BF3 /* SIGSHA2VerificationAlgorithm.h */,
271+
A6BC8B5921C96E4200796BF3 /* SIGSHA2VerificationAlgorithm.m */,
252272
A6BC8B4C21C9656100796BF3 /* SIGSigningAlgorithm.h */,
253273
A6BC8B0A21C8C67300796BF3 /* SIGTrust.h */,
254-
A6BC8B5421C96E0E00796BF3 /* SIGVerificationAlgorithm.h */,
255-
A6BC8AEB21C78A3000796BF3 /* SIGArchiveBuilder.m */,
256-
A6BC8B0321C8B65900796BF3 /* SIGArchiveChunk.m */,
257-
A6BC8AFF21C79A8000796BF3 /* SIGArchiveReader.m */,
258-
A6BC8AFB21C7982800796BF3 /* SIGArchiveVerifier.m */,
259-
A6BC8B0721C8BB3700796BF3 /* SIGCertificate.m */,
260-
A6BC8B4921C95F8900796BF3 /* SIGError.m */,
261-
A6BC8AEF21C78C1700796BF3 /* SIGIdentity.m */,
262-
A6BC8AF721C791A700796BF3 /* SIGKey.m */,
263-
A6BC8AF321C78C5E00796BF3 /* SIGKeychain.m */,
264-
A6BC8B0F21C8CE7600796BF3 /* SIGPartialInputStream.m */,
265-
53F5893D21C9AF38004A372B /* SIGPolicy.m */,
266-
A6BC8B5121C965C100796BF3 /* SIGSHA2SigningAlgorithm.m */,
267-
A6BC8B5921C96E4200796BF3 /* SIGSHA2VerificationAlgorithm.m */,
268274
A6BC8B0B21C8C67300796BF3 /* SIGTrust.m */,
269-
A6BC8ADF21C789DA00796BF3 /* Info.plist */,
275+
A6BC8B5421C96E0E00796BF3 /* SIGVerificationAlgorithm.h */,
270276
53F5895A21C9C1F2004A372B /* SIGVerificationAlgorithm.m */,
271277
);
272278
path = SignedArchive;
@@ -314,6 +320,7 @@
314320
A6BC8B4A21C95F8900796BF3 /* SIGError.h in Headers */,
315321
A6BC8B5621C96E0E00796BF3 /* SIGVerificationAlgorithm.h in Headers */,
316322
53F5893E21C9AF38004A372B /* SIGPolicy.h in Headers */,
323+
A665C1C9243A4D8E00F623F0 /* SIGArchiveCommon.h in Headers */,
317324
A6BC8B5A21C96E4200796BF3 /* SIGSHA2VerificationAlgorithm.h in Headers */,
318325
A6BC8B5221C965C100796BF3 /* SIGSHA2SigningAlgorithm.h in Headers */,
319326
A6BC8B4E21C9656100796BF3 /* SIGSigningAlgorithm.h in Headers */,
@@ -488,6 +495,7 @@
488495
A6BC8B4B21C95F8900796BF3 /* SIGError.m in Sources */,
489496
A6BC8B3221C8D81F00796BF3 /* SIGPartialInputStream.m in Sources */,
490497
A6BC8B3321C8D81F00796BF3 /* SIGKey.m in Sources */,
498+
A665C1CD243A4DF000F623F0 /* SIGArchiveCommon.m in Sources */,
491499
A6BC8B5321C965C100796BF3 /* SIGSHA2SigningAlgorithm.m in Sources */,
492500
A6BC8B5B21C96E4200796BF3 /* SIGSHA2VerificationAlgorithm.m in Sources */,
493501
A6BC8B3421C8D81F00796BF3 /* SIGKeychain.m in Sources */,

SignedArchive/SignedArchive/SIGArchiveVerifier.h

+1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ NS_ASSUME_NONNULL_BEGIN
1717
@property (nonatomic, readonly) NSURL *url;
1818
@property (nonatomic, readonly) BOOL verified;
1919
@property (nonatomic, readonly, nullable) SIGArchiveReader *reader;
20+
@property (nonatomic) NSInteger minimumVersion;
2021

2122
- (instancetype)initWithURL:(NSURL *)url NS_DESIGNATED_INITIALIZER;
2223
- (instancetype)init NS_UNAVAILABLE;

SignedArchive/SignedArchive/SIGArchiveVerifier.m

+7-2
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,11 @@ - (instancetype)initWithURL:(NSURL *)url {
4848
self = [super init];
4949
if (self) {
5050
_url = url;
51+
#if ENABLE_SIGARCHIVE_MIGRATION_VALIDATION
52+
_minimumVersion = 1;
53+
#else
54+
_minimumVersion = 2;
55+
#endif
5156
}
5257
return self;
5358
}
@@ -219,13 +224,13 @@ - (BOOL)verifyMetadata:(NSString *)metadata error:(out NSError **)error {
219224
}
220225
return NO;
221226
}
222-
if (version < SIGArchiveVerifiedLowestSupportedVersion) {
227+
if (version < SIGArchiveVerifiedLowestSupportedVersion || version < _minimumVersion) {
223228
if (error) {
224229
*error = [SIGError errorWithCode:SIGErrorCodeDeprecatedOldVersion];
225230
}
226231
return NO;
227232
}
228-
233+
229234
NSString *const digestType = dictionary[SIGArchiveMetadataKeyDigestType];
230235
if (!digestType) {
231236
if (error) {

SignedArchive/SignedArchive/SIGError.m

+2-2
Original file line numberDiff line numberDiff line change
@@ -68,11 +68,11 @@ + (NSString *)localizedDescriptionFcode:(SIGErrorCode)code {
6868
case SIGErrorCodeAlgorithmCreationFailed:
6969
return @"Could not create algorithm";
7070
case SIGErrorCodeVersionTooNew:
71-
return @"This file is from a newer version of this app and cannot be loaded. Please upgrade and try again.";
71+
return @"This file is from a newer version of this app and cannot be loaded. Please upgrade and try again";
7272
case SIGErrorCodeMalformedMetadata:
7373
return @"Metadata chunk malformed";
7474
case SIGErrorCodeDeprecatedOldVersion:
75-
return @"This file is in an older format that is no longer supported because its authenticity cannot be guaranteed. It cannot be opened by this version of the app.";
75+
return @"This file is in an older format that is no longer supported because its authenticity cannot be guaranteed. It cannot be opened by this version of the app";
7676
case SIGErrorCodeMalformedHeader:
7777
return @"Header chunk malformed";
7878
case SIGErrorCodeUnsupportedAlgorithm:

SignedArchive/resign/main.m

+113-33
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,18 @@
88

99
#import <Foundation/Foundation.h>
1010
#import "SIGArchiveBuilder.h"
11+
#import "SIGArchiveCommon.h"
1112
#import "SIGArchiveReader.h"
1213
#import "SIGCertificate.h"
1314
#import "SIGIdentity.h"
1415
#import <stdio.h>
1516

17+
typedef enum {
18+
SIGReSignModeError,
19+
SIGReSignModeMultiple,
20+
SIGReSignModeSingle
21+
} SIGReSignMode;
22+
1623
SIGIdentity *FindSigningIdentity(NSString *query) {
1724
for (SIGIdentity *identity in [SIGIdentity allSigningIdentities]) {
1825
if ([identity.signingCertificate.longDescription localizedCaseInsensitiveContainsString:query]) {
@@ -99,43 +106,116 @@
99106
return url;
100107
}
101108

109+
static BOOL ReSignExtracted(NSURL *oldArchiveURL,
110+
NSString *identityName,
111+
NSURL *outputURL,
112+
NSURL *payloadURL) {
113+
if (!payloadURL) {
114+
fprintf(stderr, "Could not extract from %s\n", oldArchiveURL.path.UTF8String);
115+
return NO;
116+
}
117+
SIGIdentity *identity = FindSigningIdentity(identityName);
118+
if (!identity) {
119+
fprintf(stderr, "No identity found\n");
120+
return NO;
121+
}
122+
SIGArchiveBuilder *builder = [[SIGArchiveBuilder alloc] initWithPayloadFileURL:payloadURL
123+
identity:identity];
102124

103-
int main(int argc, const char * argv[]) {
104-
if (argc != 4) {
105-
fprintf(stderr, "Usage: resign filename.in identity filename.out\n");
106-
return -1;
125+
NSError *error = nil;
126+
const BOOL ok = [builder writeToURL:outputURL error:&error];
127+
if (!ok) {
128+
fprintf(stderr, "Signing error: %s\n", error.localizedDescription.UTF8String);
129+
return NO;
107130
}
108131

109-
@autoreleasepool {
110-
NSURL *oldArchiveURL = [NSURL fileURLWithPath:[NSString stringWithUTF8String:argv[1]]];
111-
NSURL *payloadURL = TemporaryURLOfExtractedUnverifiedPayload(oldArchiveURL);
112-
do {
113-
if (!payloadURL) {
114-
fprintf(stderr, "Could not extract from %s\n", argv[1]);
115-
break;
116-
}
117-
SIGIdentity *identity = FindSigningIdentity([NSString stringWithUTF8String:argv[2]]);
118-
if (!identity) {
119-
fprintf(stderr, "No identity found\n");
120-
break;
121-
}
122-
SIGArchiveBuilder *builder = [[SIGArchiveBuilder alloc] initWithPayloadFileURL:payloadURL
123-
identity:identity];
124-
125-
NSError *error = nil;
126-
NSURL *outputURL = [NSURL fileURLWithPath:[NSString stringWithUTF8String:argv[3]]];
127-
const BOOL ok = [builder writeToURL:outputURL error:&error];
128-
if (!ok) {
129-
fprintf(stderr, "Signing error: %s\n", error.localizedDescription.UTF8String);
130-
break;
131-
}
132-
} while (0);
133-
134-
NSError *error = nil;
135-
[[NSFileManager defaultManager] removeItemAtURL:payloadURL error:&error];
136-
if (error) {
137-
fprintf(stderr, "While deleting temp file %s: %s\n", payloadURL.path.UTF8String, error.localizedDescription.UTF8String);
132+
return YES;
133+
}
134+
135+
static void DeleteTempFile(NSURL *payloadURL) {
136+
NSError *error = nil;
137+
[[NSFileManager defaultManager] removeItemAtURL:payloadURL error:&error];
138+
if (error) {
139+
fprintf(stderr, "Warning: While deleting temp file %s: %s\n",
140+
payloadURL.path.UTF8String, error.localizedDescription.UTF8String);
141+
}
142+
}
143+
144+
static BOOL ReSign(NSURL *oldArchiveURL,
145+
NSString *identityName,
146+
NSURL *outputURL) {
147+
NSURL *payloadURL = TemporaryURLOfExtractedUnverifiedPayload(oldArchiveURL);
148+
const BOOL ok = ReSignExtracted(oldArchiveURL, identityName, outputURL, payloadURL);
149+
DeleteTempFile(payloadURL);
150+
return ok;
151+
}
152+
153+
static void Move(NSURL *source, NSURL *dest) {
154+
NSError *error = nil;
155+
[[NSFileManager defaultManager] replaceItemAtURL:dest
156+
withItemAtURL:source
157+
backupItemName:nil
158+
options:0
159+
resultingItemURL:nil
160+
error:&error];
161+
if (error) {
162+
fprintf(stderr, "While moving temp file %s over input file %s: %s",
163+
source.path.UTF8String, dest.path.UTF8String, error.localizedDescription.UTF8String);
164+
}
165+
}
166+
167+
static int ResignMultiple(int argc, const char *argv[]) {
168+
NSInteger errorCount = 0;
169+
NSString *identityName = [NSString stringWithUTF8String:argv[2]];
170+
for (size_t i = 3; i < argc; i++) {
171+
NSURL *fileURL = [NSURL fileURLWithPath:[NSString stringWithUTF8String:argv[i]]];
172+
NSURL *temporaryFileURL = CreateTemporaryURL([NSURL fileURLWithPath:NSTemporaryDirectory()]);
173+
if (!ReSign(fileURL, identityName, temporaryFileURL)) {
174+
errorCount += 1;
138175
}
176+
Move(temporaryFileURL, fileURL);
177+
}
178+
return errorCount == 0 ? 0 : 1;
179+
}
180+
181+
static int ResignSingle(int argc, const char *argv[]) {
182+
NSURL *oldArchiveURL = [NSURL fileURLWithPath:[NSString stringWithUTF8String:argv[1]]];
183+
NSString *identityName = [NSString stringWithUTF8String:argv[2]];
184+
NSURL *outputURL = [NSURL fileURLWithPath:[NSString stringWithUTF8String:argv[3]]];
185+
if (!ReSign(oldArchiveURL, identityName, outputURL)) {
186+
return 1;
139187
}
140188
return 0;
141189
}
190+
191+
static void Usage(void) {
192+
fprintf(stderr, "Usage: resign filename.in identity filename.out\n");
193+
fprintf(stderr, " resign -m identity file [file...]\n");
194+
}
195+
196+
static SIGReSignMode CheckArgs(int argc, const char *argv[]) {
197+
if (argc < 4) {
198+
return SIGReSignModeError;
199+
}
200+
if (!strcmp(argv[1], "-m")) {
201+
return SIGReSignModeMultiple;
202+
}
203+
if (argc > 4) {
204+
return SIGReSignModeError;
205+
}
206+
return SIGReSignModeSingle;
207+
}
208+
209+
int main(int argc, const char * argv[]) {
210+
@autoreleasepool {
211+
switch (CheckArgs(argc, argv)) {
212+
case SIGReSignModeError:
213+
Usage();
214+
return 1;
215+
case SIGReSignModeSingle:
216+
return ResignSingle(argc, argv);
217+
case SIGReSignModeMultiple:
218+
return ResignMultiple(argc, argv);
219+
}
220+
}
221+
}

SignedArchive/verify/main.m

+9-2
Original file line numberDiff line numberDiff line change
@@ -48,13 +48,14 @@
4848
return [detailLines componentsJoinedByString:@"\n"];
4949
}
5050

51-
static NSError *Verify(NSString *path, NSString **detailsPtr) {
51+
static NSError *Verify(NSString *path, BOOL requireV2, NSString **detailsPtr) {
5252
SIGArchiveVerifier *verifier = [[SIGArchiveVerifier alloc] initWithURL:[NSURL fileURLWithPath:path]];
5353
__block BOOL result;
5454
__block NSError *errorResult = nil;
5555
dispatch_group_t group = dispatch_group_create();
5656
dispatch_group_enter(group);
5757
__block NSString *details;
58+
verifier.minimumVersion = requireV2 ? 2 : 1;
5859
[verifier verifyWithCompletion:^(BOOL ok, NSError *error) {
5960
details = Details(verifier);
6061
result = ok;
@@ -77,19 +78,25 @@
7778
int main(int argc, const char * argv[]) {
7879
@autoreleasepool {
7980
if (argc < 2) {
80-
fprintf(stderr, "Usage: verify [-v] file [file...]\n");
81+
fprintf(stderr, "Usage: verify [-v] [-2] file [file...]\n");
8182
return 1;
8283
}
8384
int errors = 0;
8485
int first = 1;
86+
BOOL requireV2 = NO;
8587
BOOL verbose = NO;
8688
if (argc > 1 && !strcmp(argv[1], "-v")) {
8789
verbose = YES;
8890
first++;
8991
}
92+
if (argc > first && !strcmp(argv[first], "-2")) {
93+
requireV2 = YES;
94+
first++;
95+
}
9096
for (int i = first; i < argc; i++) {
9197
NSString *details;
9298
NSError *error = Verify([NSString stringWithUTF8String:argv[i]],
99+
requireV2,
93100
verbose ? &details : NULL);
94101
if (error) {
95102
errors++;

0 commit comments

Comments
 (0)