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