]> git.saurik.com Git - apple/security.git/blob - OSX/sec/Security/Regressions/secitem/si-89-cms-hash-agility.m
Security-58286.230.21.tar.gz
[apple/security.git] / OSX / sec / Security / Regressions / secitem / si-89-cms-hash-agility.m
1 /*
2 * Copyright (c) 2015-2018 Apple Inc. All Rights Reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24 #import <AssertMacros.h>
25 #include <Foundation/Foundation.h>
26 #include <CoreFoundation/CoreFoundation.h>
27 #include <Security/Security.h>
28 #include <Security/SecCMS.h>
29 #include <Security/SecCmsBase.h>
30 #include <Security/CMSEncoder.h>
31 #include <Security/CMSDecoder.h>
32 #include <utilities/SecCFRelease.h>
33
34 #if TARGET_OS_OSX
35 #include <Security/CMSPrivate.h>
36 #endif
37
38 #include "shared_regressions.h"
39
40 #include "si-cms-hash-agility-data.h"
41
42 static void ios_shim_tests(void)
43 {
44 CFDataRef message = NULL, contentData = NULL, hashAgilityOid = NULL, hashAgilityValue = NULL;
45 SecPolicyRef policy = NULL;
46 SecTrustRef trust = NULL;
47 CFDictionaryRef attrs = NULL;
48 CFArrayRef attrValues = NULL;
49 CFDateRef signingTime = NULL, expectedTime = NULL;
50
51 ok(message = CFDataCreate(NULL, valid_message, valid_message_size), "Create valid message");
52 ok(contentData = CFDataCreate(NULL, content, content_size), "Create detached content");
53 ok(policy = SecPolicyCreateBasicX509(), "Create policy");
54
55 /* verify the valid message and copy out attributes */
56 is(SecCMSVerifyCopyDataAndAttributes(message, contentData, policy, &trust, NULL, &attrs),
57 errSecSuccess, "Verify valid CMS message and get attributes");
58 isnt(attrs, NULL, "Copy CMS attributes");
59 CFReleaseNull(trust);
60
61 /* verify we can get the parsed attribute */
62 uint8_t appleHashAgilityOid[] = { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x63, 0x64, 0x9, 0x1 };
63 ok(hashAgilityOid = CFDataCreate(NULL, appleHashAgilityOid, sizeof(appleHashAgilityOid)),
64 "Create oid data");
65 ok(attrValues = (CFArrayRef) CFDictionaryGetValue(attrs, hashAgilityOid),
66 "Get hash agility value array");
67 is(CFArrayGetCount(attrValues), 1, "One attribute value");
68 ok(hashAgilityValue = CFArrayGetValueAtIndex(attrValues, 0), "Get hash agility value");
69 is((size_t)CFDataGetLength(hashAgilityValue), sizeof(attribute), "Verify size of parsed hash agility value");
70 is(memcmp(attribute, CFDataGetBytePtr(hashAgilityValue), sizeof(attribute)), 0,
71 "Verify correct hash agility value");
72
73 /* verify we can get the "cooked" parsed attribute */
74 ok(hashAgilityValue = (CFDataRef)CFDictionaryGetValue(attrs, kSecCMSHashAgility), "Get cooked hash agility value");
75 is((size_t)CFDataGetLength(hashAgilityValue), sizeof(attribute), "Verify size of parsed hash agility value");
76 is(memcmp(attribute, CFDataGetBytePtr(hashAgilityValue), sizeof(attribute)), 0,
77 "Verify correct hash agility value");
78
79 attrValues = NULL;
80
81 /*verify we can get the signing time attribute */
82 ok(signingTime = (CFDateRef) CFDictionaryGetValue(attrs, kSecCMSSignDate), "Get signing time");
83 ok(expectedTime = CFDateCreate(NULL, 468295000.0), "Set expected signing time");
84 is(CFDateCompare(signingTime, expectedTime, NULL), 0, "Verify signing time");
85
86 CFReleaseNull(message);
87
88 /* verify the invalid message */
89 ok(message = CFDataCreate(NULL, invalid_message, invalid_message_size), "Create invalid message");
90 is(SecCMSVerify(message, contentData, policy, &trust, NULL), errSecAuthFailed,
91 "Verify invalid CMS message");
92
93 CFReleaseNull(message);
94 CFReleaseNull(trust);
95 CFReleaseNull(attrs);
96
97 /* verify the valid message with no hash agility attribute */
98 ok(message = CFDataCreate(NULL, valid_no_attr, valid_no_attr_size),
99 "Create valid message with no hash agility value");
100 is(SecCMSVerifyCopyDataAndAttributes(message, contentData, policy, &trust, NULL, &attrs),
101 errSecSuccess, "Verify 2nd valid CMS message and get attributes");
102 isnt(attrs, NULL, "Copy 2nd CMS attributes");
103
104 /* verify we can't get the hash agility attribute */
105 is((CFArrayRef) CFDictionaryGetValue(attrs, hashAgilityOid), NULL,
106 "Get hash agility value array");
107 is((CFDataRef) CFDictionaryGetValue(attrs, kSecCMSHashAgility), NULL,
108 "Get cooked hash agility value");
109
110
111 CFReleaseNull(message);
112 CFReleaseNull(contentData);
113 CFReleaseNull(hashAgilityOid);
114 CFReleaseNull(expectedTime);
115 CFReleaseNull(policy);
116 CFReleaseNull(trust);
117 CFReleaseNull(attrs);
118 }
119
120 /* MARK: macOS Shim tests */
121 /* encode test */
122 static void encode_test(SecIdentityRef identity)
123 {
124 CMSEncoderRef encoder = NULL;
125 CFDataRef attributeData = NULL, message = NULL;
126
127 /* Create encoder */
128 ok_status(CMSEncoderCreate(&encoder), "Create CMS encoder");
129 ok_status(CMSEncoderSetSignerAlgorithm(encoder, kCMSEncoderDigestAlgorithmSHA256),
130 "Set digest algorithm to SHA256");
131
132 /* Set identity as signer */
133 ok_status(CMSEncoderAddSigners(encoder, identity), "Set Signer identity");
134
135 /* Add signing time attribute for 3 November 2015 */
136 ok_status(CMSEncoderAddSignedAttributes(encoder, kCMSAttrSigningTime),
137 "Set signing time flag");
138 ok_status(CMSEncoderSetSigningTime(encoder, 468295000.0), "Set Signing time");
139
140 /* Add hash agility attribute */
141 ok_status(CMSEncoderAddSignedAttributes(encoder, kCMSAttrAppleCodesigningHashAgility),
142 "Set hash agility flag");
143 ok(attributeData = CFDataCreate(NULL, attribute, sizeof(attribute)),
144 "Create atttribute object");
145 ok_status(CMSEncoderSetAppleCodesigningHashAgility(encoder, attributeData),
146 "Set hash agility data");
147
148 /* Load content */
149 ok_status(CMSEncoderSetHasDetachedContent(encoder, true), "Set detached content");
150 ok_status(CMSEncoderUpdateContent(encoder, content, content_size), "Set content");
151
152 /* output cms message */
153 ok_status(CMSEncoderCopyEncodedContent(encoder, &message), "Finish encoding and output message");
154
155 /* decode message */
156 CMSDecoderRef decoder = NULL;
157 CFDataRef contentData = NULL;
158 isnt(message, NULL, "Encoded message exists");
159 ok_status(CMSDecoderCreate(&decoder), "Create CMS decoder");
160 ok_status(CMSDecoderUpdateMessage(decoder, CFDataGetBytePtr(message), CFDataGetLength(message)),
161 "Update decoder with CMS message");
162 ok(contentData = CFDataCreate(NULL, content, content_size), "Create detached content");
163 ok_status(CMSDecoderSetDetachedContent(decoder, contentData), "Set detached content");
164 ok_status(CMSDecoderFinalizeMessage(decoder), "Finalize decoder");
165
166 CFReleaseNull(encoder);
167 CFReleaseNull(attributeData);
168 CFReleaseNull(message);
169 CFReleaseNull(decoder);
170 CFReleaseNull(contentData);
171 }
172
173 static void decode_positive_test(void)
174 {
175 CMSDecoderRef decoder = NULL;
176 CFDataRef contentData = NULL, attrValue = NULL;
177 SecPolicyRef policy = NULL;
178 SecTrustRef trust = NULL;
179 CMSSignerStatus signerStatus;
180 CFAbsoluteTime signingTime = 0.0;
181
182 /* Create decoder and decode */
183 ok_status(CMSDecoderCreate(&decoder), "Create CMS decoder");
184 ok_status(CMSDecoderUpdateMessage(decoder, valid_message, valid_message_size),
185 "Update decoder with CMS message");
186 ok(contentData = CFDataCreate(NULL, content, content_size), "Create detached content");
187 ok_status(CMSDecoderSetDetachedContent(decoder, contentData), "Set detached content");
188 ok_status(CMSDecoderFinalizeMessage(decoder), "Finalize decoder");
189
190 /* Get signer status */
191 ok(policy = SecPolicyCreateBasicX509(), "Create policy");
192 ok_status(CMSDecoderCopySignerStatus(decoder, 0, policy, false, &signerStatus, &trust, NULL),
193 "Copy Signer status");
194 is(signerStatus, kCMSSignerValid, "Valid signature");
195
196 /* Get Hash Agility Attribute value */
197 ok_status(CMSDecoderCopySignerAppleCodesigningHashAgility(decoder, 0, &attrValue),
198 "Copy hash agility attribute value");
199 is((size_t)CFDataGetLength(attrValue), sizeof(attribute), "Decoded attribute size");
200 is(memcmp(attribute, CFDataGetBytePtr(attrValue), sizeof(attribute)), 0,
201 "Decoded value same as input value");
202
203 /* Get Signing Time Attribute value */
204 ok_status(CMSDecoderCopySignerSigningTime(decoder, 0, &signingTime),
205 "Copy signing time attribute value");
206 is(signingTime, 468295000.0, "Decoded date same as input date");
207
208 CFReleaseNull(decoder);
209 CFReleaseNull(contentData);
210 CFReleaseNull(policy);
211 CFReleaseNull(trust);
212 CFReleaseNull(attrValue);
213 }
214
215 static void decode_negative_test(void)
216 {
217 CMSDecoderRef decoder = NULL;
218 CFDataRef contentData = NULL;
219 SecPolicyRef policy = NULL;
220 SecTrustRef trust = NULL;
221 CMSSignerStatus signerStatus;
222
223 /* Create decoder and decode */
224 ok_status(CMSDecoderCreate(&decoder), "Create CMS decoder");
225 ok_status(CMSDecoderUpdateMessage(decoder, invalid_message, invalid_message_size),
226 "Update decoder with CMS message");
227 ok(contentData = CFDataCreate(NULL, content, content_size), "Create detached content");
228 ok_status(CMSDecoderSetDetachedContent(decoder, contentData), "Set detached content");
229 ok_status(CMSDecoderFinalizeMessage(decoder), "Finalize decoder");
230
231 /* Get signer status */
232 ok(policy = SecPolicyCreateBasicX509(), "Create policy");
233 ok_status(CMSDecoderCopySignerStatus(decoder, 0, policy, false, &signerStatus, &trust, NULL),
234 "Copy Signer status");
235 is(signerStatus, kCMSSignerInvalidSignature, "Invalid signature");
236
237 CFReleaseNull(decoder);
238 CFReleaseNull(contentData);
239 CFReleaseNull(policy);
240 CFReleaseNull(trust);
241 }
242
243 static void decode_no_attr_test(void)
244 {
245 CMSDecoderRef decoder = NULL;
246 CFDataRef contentData = NULL, attrValue = NULL;
247 SecPolicyRef policy = NULL;
248 SecTrustRef trust = NULL;
249 CMSSignerStatus signerStatus;
250
251 /* Create decoder and decode */
252 ok_status(CMSDecoderCreate(&decoder), "Create CMS decoder");
253 ok_status(CMSDecoderUpdateMessage(decoder, valid_no_attr, valid_no_attr_size),
254 "Update decoder with CMS message");
255 ok(contentData = CFDataCreate(NULL, content, content_size), "Create detached content");
256 ok_status(CMSDecoderSetDetachedContent(decoder, contentData), "Set detached content");
257 ok_status(CMSDecoderFinalizeMessage(decoder), "Finalize decoder");
258
259 /* Get signer status */
260 ok(policy = SecPolicyCreateBasicX509(), "Create policy");
261 ok_status(CMSDecoderCopySignerStatus(decoder, 0, policy, false, &signerStatus, &trust, NULL),
262 "Copy Signer status");
263 is(signerStatus, kCMSSignerValid, "Valid signature");
264
265 /* Get Hash Agility Attribute value */
266 ok_status(CMSDecoderCopySignerAppleCodesigningHashAgility(decoder, 0, &attrValue),
267 "Copy empty hash agility attribute value");
268 is(attrValue, NULL, "NULL attribute value");
269
270 CFReleaseNull(decoder);
271 CFReleaseNull(contentData);
272 CFReleaseNull(policy);
273 CFReleaseNull(trust);
274 CFReleaseNull(attrValue);
275 }
276
277 static void macos_shim_tests(SecIdentityRef identity) {
278 encode_test(identity);
279 decode_positive_test();
280 decode_negative_test();
281 decode_no_attr_test();
282 }
283
284 /* MARK: V2 Attribute testing */
285 static void ios_shim_V2_tests(void) {
286 SecPolicyRef policy = NULL;
287 SecTrustRef trust = NULL;
288 CFDictionaryRef tmpAttrs = NULL;
289 NSMutableData *message = nil;
290 NSData *contentData = nil, *hashAgilityV2Oid = nil;
291 NSDictionary *attrs = nil, *hashAgilityValue = nil;
292 NSArray *attrValues = nil;
293 NSDate *signingTime = nil;
294
295 message = [NSMutableData dataWithBytes:_V2_valid_message length:_V2_valid_message_size];
296 contentData = [NSData dataWithBytes:content length:content_size];
297 policy = SecPolicyCreateBasicX509();
298
299 /* verify the valid message and copy out attributes */
300 is(SecCMSVerifyCopyDataAndAttributes((__bridge CFDataRef)message, (__bridge CFDataRef)contentData, policy, &trust, NULL, &tmpAttrs),
301 errSecSuccess, "Verify valid CMS message and get attributes");
302 attrs = CFBridgingRelease(tmpAttrs);
303 require_action(attrs, exit, fail("Copy CMS attributes"));
304
305 /* verify we can get the parsed attribute */
306 uint8_t appleHashAgilityOid[] = { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x63, 0x64, 0x9, 0x2 };
307 hashAgilityV2Oid = [NSData dataWithBytes:appleHashAgilityOid length:sizeof(appleHashAgilityOid)];
308 attrValues = attrs[hashAgilityV2Oid];
309 is([attrValues count], (size_t)2, "Two attribute values");
310
311 /* verify we can get the "cooked" parsed attribute */
312 require_action(hashAgilityValue = (NSDictionary *)attrs[(__bridge NSString*)kSecCMSHashAgilityV2], exit,
313 fail("Get cooked hash agility value"));
314 ok([hashAgilityValue[@(SEC_OID_SHA1)] isEqualToData:[NSData dataWithBytes:_attributev2 length:20]],
315 "Got wrong SHA1 agility value");
316 ok([hashAgilityValue[@(SEC_OID_SHA256)] isEqualToData:[NSData dataWithBytes:(_attributev2+32) length:32]],
317 "Got wrong SHA256 agility value");
318
319 attrValues = NULL;
320
321 /*verify we can get the signing time attribute */
322 require_action(signingTime = attrs[(__bridge NSString*)kSecCMSSignDate], exit, fail("Failed to get signing time"));
323 ok([signingTime isEqualToDate:[NSDate dateWithTimeIntervalSinceReferenceDate:530700000.0]], "Got wrong signing time");
324
325 /* verify the invalid message */
326 message = [NSMutableData dataWithBytes:_V2_valid_message length:_V2_valid_message_size];
327 [message resetBytesInRange:NSMakeRange(2110, 1)]; /* reset byte in hash agility attribute */
328 is(SecCMSVerify((__bridge CFDataRef)message, (__bridge CFDataRef)contentData, policy, &trust, NULL), errSecAuthFailed,
329 "Verify invalid CMS message");
330
331 /* verify the valid message with no hash agility attribute */
332 message = [NSMutableData dataWithBytes:valid_no_attr length:valid_no_attr_size];
333 is(SecCMSVerifyCopyDataAndAttributes((__bridge CFDataRef)message, (__bridge CFDataRef)contentData, policy, &trust, NULL, &tmpAttrs),
334 errSecSuccess, "Verify 2nd valid CMS message and get attributes");
335 attrs = CFBridgingRelease(tmpAttrs);
336 isnt(attrs, NULL, "Copy 2nd CMS attributes");
337
338 /* verify we can't get the hash agility attribute */
339 is(attrs[hashAgilityV2Oid], NULL, "Got hash agility V2 attribute");
340 is(attrs[(__bridge NSString*)kSecCMSHashAgilityV2], NULL, "Got cooked hash agility V2 attribute");
341
342 exit:
343 CFReleaseNull(policy);
344 CFReleaseNull(trust);
345 }
346
347 /* macOS shim test - encode */
348 static void encode_V2_test(SecIdentityRef identity) {
349 CMSEncoderRef encoder = NULL;
350 CMSDecoderRef decoder = NULL;
351 CFDataRef message = NULL;
352 NSDictionary *attrValues = nil;
353
354 /* Create encoder */
355 require_noerr_action(CMSEncoderCreate(&encoder), exit, fail("Failed to create CMS encoder"));
356 require_noerr_action(CMSEncoderSetSignerAlgorithm(encoder, kCMSEncoderDigestAlgorithmSHA256), exit,
357 fail("Failed to set digest algorithm to SHA256"));
358
359 /* Set identity as signer */
360 require_noerr_action(CMSEncoderAddSigners(encoder, identity), exit, fail("Failed to add signer identity"));
361
362 /* Add signing time attribute for 26 October 2017 */
363 require_noerr_action(CMSEncoderAddSignedAttributes(encoder, kCMSAttrSigningTime), exit,
364 fail("Failed to set signing time flag"));
365 require_noerr_action(CMSEncoderSetSigningTime(encoder, 530700000.0), exit, fail("Failed to set signing time"));
366
367 /* Add hash agility attribute */
368 attrValues = @{ @(SEC_OID_SHA1) : [NSData dataWithBytes:_attributev2 length:20],
369 @(SEC_OID_SHA256) : [NSData dataWithBytes:(_attributev2 + 32) length:32],
370 };
371 ok_status(CMSEncoderAddSignedAttributes(encoder, kCMSAttrAppleCodesigningHashAgilityV2),
372 "Set hash agility flag");
373 ok_status(CMSEncoderSetAppleCodesigningHashAgilityV2(encoder, (__bridge CFDictionaryRef)attrValues),
374 "Set hash agility data");
375
376 /* Load content */
377 require_noerr_action(CMSEncoderSetHasDetachedContent(encoder, true), exit, fail("Failed to set detached content"));
378 require_noerr_action(CMSEncoderUpdateContent(encoder, content, content_size), exit, fail("Failed to set content"));
379
380 /* output cms message */
381 ok_status(CMSEncoderCopyEncodedContent(encoder, &message), "Finish encoding and output message");
382 isnt(message, NULL, "Encoded message exists");
383
384 /* decode message */
385 require_noerr_action(CMSDecoderCreate(&decoder), exit, fail("Create CMS decoder"));
386 require_noerr_action(CMSDecoderUpdateMessage(decoder, CFDataGetBytePtr(message),
387 CFDataGetLength(message)), exit,
388 fail("Update decoder with CMS message"));
389 require_noerr_action(CMSDecoderSetDetachedContent(decoder, (__bridge CFDataRef)[NSData dataWithBytes:content
390 length:content_size]),
391 exit, fail("Set detached content"));
392 ok_status(CMSDecoderFinalizeMessage(decoder), "Finalize decoder");
393
394 exit:
395 CFReleaseNull(encoder);
396 CFReleaseNull(message);
397 CFReleaseNull(decoder);
398 }
399
400 /* macOS shim test - decode positive */
401 static void decode_V2_positive_test(void) {
402 CMSDecoderRef decoder = NULL;
403 SecPolicyRef policy = NULL;
404 SecTrustRef trust = NULL;
405 CMSSignerStatus signerStatus;
406 NSData *contentData = nil;
407 CFDictionaryRef tmpAttrValue = NULL;
408 NSDictionary *attrValue = nil;
409
410 /* Create decoder and decode */
411 require_noerr_action(CMSDecoderCreate(&decoder), exit, fail("Failed to create CMS decoder"));
412 require_noerr_action(CMSDecoderUpdateMessage(decoder, _V2_valid_message, _V2_valid_message_size), exit,
413 fail("Failed to update decoder with CMS message"));
414 contentData = [NSData dataWithBytes:content length:content_size];
415 require_noerr_action(CMSDecoderSetDetachedContent(decoder, (__bridge CFDataRef)contentData), exit,
416 fail("Failed to set detached content"));
417 ok_status(CMSDecoderFinalizeMessage(decoder), "Finalize decoder");
418
419 /* Get signer status */
420 require_action(policy = SecPolicyCreateBasicX509(), exit, fail("Failed to Create policy"));
421 ok_status(CMSDecoderCopySignerStatus(decoder, 0, policy, false, &signerStatus, &trust, NULL),
422 "Copy Signer status");
423 is(signerStatus, kCMSSignerValid, "Valid signature");
424
425 /* Get Hash Agility Attribute value */
426 ok_status(CMSDecoderCopySignerAppleCodesigningHashAgilityV2(decoder, 0, &tmpAttrValue),
427 "Copy hash agility attribute value");
428 attrValue = CFBridgingRelease(tmpAttrValue);
429 ok([attrValue[@(SEC_OID_SHA1)] isEqualToData:[NSData dataWithBytes:_attributev2 length:20]],
430 "Got wrong SHA1 agility value");
431 ok([attrValue[@(SEC_OID_SHA256)] isEqualToData:[NSData dataWithBytes:(_attributev2+32) length:32]],
432 "Got wrong SHA256 agility value");
433
434 exit:
435 CFReleaseNull(decoder);
436 CFReleaseNull(policy);
437 CFReleaseNull(trust);
438 }
439
440 /* macOS shim test - decode negative */
441 static void decode_V2_negative_test(void) {
442 CMSDecoderRef decoder = NULL;
443 SecPolicyRef policy = NULL;
444 SecTrustRef trust = NULL;
445 CMSSignerStatus signerStatus;
446 NSData *contentData = nil;
447 NSMutableData *invalid_message = nil;
448
449 /* Create decoder and decode */
450 invalid_message = [NSMutableData dataWithBytes:_V2_valid_message length:_V2_valid_message_size];
451 [invalid_message resetBytesInRange:NSMakeRange(2110, 1)]; /* reset byte in hash agility attribute */
452 require_noerr_action(CMSDecoderCreate(&decoder), exit, fail("Failed to create CMS decoder"));
453 require_noerr_action(CMSDecoderUpdateMessage(decoder, [invalid_message bytes], [invalid_message length]), exit,
454 fail("Failed to update decoder with CMS message"));
455 contentData = [NSData dataWithBytes:content length:content_size];
456 require_noerr_action(CMSDecoderSetDetachedContent(decoder, (__bridge CFDataRef)contentData), exit,
457 fail("Failed to set detached content"));
458 ok_status(CMSDecoderFinalizeMessage(decoder), "Finalize decoder");
459
460 /* Get signer status */
461 require_action(policy = SecPolicyCreateBasicX509(), exit, fail("Failed to Create policy"));
462 ok_status(CMSDecoderCopySignerStatus(decoder, 0, policy, false, &signerStatus, &trust, NULL),
463 "Copy Signer status");
464 is(signerStatus, kCMSSignerInvalidSignature, "Valid signature");
465
466 exit:
467 CFReleaseNull(decoder);
468 CFReleaseNull(policy);
469 CFReleaseNull(trust);
470 }
471
472 /* macOS shim test - no attribute */
473 static void decodeV2_no_attr_test(void) {
474 CMSDecoderRef decoder = NULL;
475 SecPolicyRef policy = NULL;
476 SecTrustRef trust = NULL;
477 CMSSignerStatus signerStatus;
478 NSData *contentData = nil;
479 CFDictionaryRef attrValue = NULL;
480
481 /* Create decoder and decode */
482 require_noerr_action(CMSDecoderCreate(&decoder), exit, fail("Failed to create CMS decoder"));
483 require_noerr_action(CMSDecoderUpdateMessage(decoder, valid_message, valid_message_size), exit,
484 fail("Failed to update decoder with CMS message"));
485 contentData = [NSData dataWithBytes:content length:content_size];
486 require_noerr_action(CMSDecoderSetDetachedContent(decoder, (__bridge CFDataRef)contentData), exit,
487 fail("Failed to set detached content"));
488 ok_status(CMSDecoderFinalizeMessage(decoder), "Finalize decoder");
489
490 /* Get signer status */
491 require_action(policy = SecPolicyCreateBasicX509(), exit, fail("Failed to Create policy"));
492 ok_status(CMSDecoderCopySignerStatus(decoder, 0, policy, false, &signerStatus, &trust, NULL),
493 "Copy Signer status");
494 is(signerStatus, kCMSSignerValid, "Valid signature");
495
496 /* Get Hash Agility Attribute value */
497 ok_status(CMSDecoderCopySignerAppleCodesigningHashAgilityV2(decoder, 0, &attrValue),
498 "Copy hash agility attribute value");
499 is(attrValue, NULL, "NULL attribute value");
500
501 exit:
502 CFReleaseNull(decoder);
503 CFReleaseNull(policy);
504 CFReleaseNull(trust);
505 CFReleaseNull(attrValue);
506 }
507
508 static void macOS_shim_V2_tests(SecIdentityRef identity) {
509 encode_V2_test(identity);
510 decode_V2_positive_test();
511 decode_V2_negative_test();
512 decodeV2_no_attr_test();
513 }
514
515 static bool setup_keychain(const uint8_t *p12, size_t p12_len, SecIdentityRef *identity) {
516 CFArrayRef tmp_imported_items = NULL;
517 NSArray *imported_items = nil;
518
519 NSDictionary *options = @{ (__bridge NSString *)kSecImportExportPassphrase : @"password" };
520 NSData *p12Data = [NSData dataWithBytes:signing_identity_p12 length:sizeof(signing_identity_p12)];
521 require_noerr_action(SecPKCS12Import((__bridge CFDataRef)p12Data, (__bridge CFDictionaryRef)options,
522 &tmp_imported_items), exit,
523 fail("Failed to import identity"));
524 imported_items = CFBridgingRelease(tmp_imported_items);
525 require_noerr_action([imported_items count] == 0 &&
526 [imported_items[0] isKindOfClass:[NSDictionary class]], exit,
527 fail("Wrong imported items output"));
528 *identity = (SecIdentityRef)CFBridgingRetain(imported_items[0][(__bridge NSString*)kSecImportItemIdentity]);
529 require_action(*identity, exit, fail("Failed to get identity"));
530
531 return true;
532
533 exit:
534 return false;
535 }
536
537 static void cleanup_keychain(SecIdentityRef identity) {
538 #if TARGET_OS_OSX
539 // SecPKCS12Import adds the items to the keychain on macOS
540 NSDictionary *query = @{ (__bridge NSString*)kSecValueRef : (__bridge id)identity };
541 ok_status(SecItemDelete((__bridge CFDictionaryRef)query), "failed to remove identity from keychain");
542 #else
543 pass("skip test on iOS");
544 #endif
545 CFReleaseNull(identity);
546 }
547
548 int si_89_cms_hash_agility(int argc, char *const *argv)
549 {
550 plan_tests(102);
551
552 SecIdentityRef identity = NULL;
553
554 if (setup_keychain(signing_identity_p12 , sizeof(signing_identity_p12), &identity)) {
555 ios_shim_tests();
556 macos_shim_tests(identity);
557 ios_shim_V2_tests();
558 macOS_shim_V2_tests(identity);
559 }
560
561 cleanup_keychain(identity);
562
563 return 0;
564 }