]> git.saurik.com Git - apple/security.git/blob - OSX/sec/Security/Regressions/secitem/si-34-cms-timestamp.m
Security-58286.230.21.tar.gz
[apple/security.git] / OSX / sec / Security / Regressions / secitem / si-34-cms-timestamp.m
1 /*
2 * Copyright (c) 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 #include "shared_regressions.h"
25
26 #import <AssertMacros.h>
27 #import <Foundation/Foundation.h>
28
29 #import <Security/CMSDecoder.h>
30 #import <Security/CMSEncoder.h>
31 #import <Security/SecTrust.h>
32 #include <utilities/SecCFRelease.h>
33 #include <stdlib.h>
34 #include <sys/socket.h>
35 #include <sys/types.h>
36 #include <netinet/in.h>
37 #include <arpa/inet.h>
38 #include <netdb.h>
39
40 #if TARGET_OS_OSX
41 #include <Security/CMSPrivate.h>
42 #include <Security/tsaSupport.h>
43 #endif
44
45 #import "si-34-cms-timestamp.h"
46 #import "si-cms-hash-agility-data.h" // for signing_identity_p12, hash agility attribute data
47
48 static CMSSignerStatus test_verify_timestamp(NSData *content, NSData *message) {
49 CMSDecoderRef decoder = NULL;
50 SecPolicyRef policy = NULL;
51 SecTrustRef trust = NULL;
52 CMSSignerStatus signerStatus = kCMSSignerUnsigned;
53
54 /* Create decoder and decode */
55 require_noerr_action(CMSDecoderCreate(&decoder), fail, fail("Failed to create CMS decoder"));
56 require_noerr_action(CMSDecoderUpdateMessage(decoder, [message bytes], [message length]), fail,
57 fail("Failed to update decoder with CMS message"));
58 require_noerr_action(CMSDecoderSetDetachedContent(decoder, (__bridge CFDataRef)content), fail,
59 fail("Failed to set detached content"));
60 require_noerr_action(CMSDecoderFinalizeMessage(decoder), fail, fail("Failed to finalize decoder"));
61
62 /* Get signer status */
63 require_action(policy = SecPolicyCreateBasicX509(), fail, fail("Failed to Create policy"));
64 require_noerr_action(CMSDecoderCopySignerStatus(decoder, 0, policy, false, &signerStatus, &trust, NULL),
65 fail, fail("Failed to copy Signer status"));
66
67 fail:
68 CFReleaseNull(decoder);
69 CFReleaseNull(policy);
70 CFReleaseNull(trust);
71 return signerStatus;
72 }
73
74 static void test_matching_messageImprint(void) {
75 /* If the timestamp is invalid, SecCmsSignerInfoVerifyUnAuthAttrs will fail, so the signer status will be
76 * kCMSSignerInvalidSignature. */
77 CMSSignerStatus expected_mismatch_result = kCMSSignerInvalidSignature;
78 #if !TIMESTAMPING_SUPPORTED
79 expected_mismatch_result = kCMSSignerValid;
80 #endif
81
82 is(test_verify_timestamp([NSData dataWithBytes:_developer_id_data length:sizeof(_developer_id_data)],
83 [NSData dataWithBytes:_developer_id_sig length:sizeof(_developer_id_sig)]),
84 kCMSSignerValid, "failed to verify good timestamped signature");
85 is(test_verify_timestamp([NSData dataWithBytes:_mismatched_content length:sizeof(_mismatched_content)],
86 [NSData dataWithBytes:_mismatched_timestamp length:sizeof(_mismatched_timestamp)]),
87 expected_mismatch_result, "successful verification of bad timestamped signature");
88 }
89
90 static void test_create_timestamp(void) {
91 CFArrayRef tmp_imported_items = NULL;
92 NSArray *imported_items = nil;
93 SecIdentityRef identity = nil;
94 CMSEncoderRef encoder = NULL;
95 CMSDecoderRef decoder = NULL;
96 CFDataRef message = NULL;
97 NSDictionary *attrValues = nil;
98
99 /* Import identity */
100 NSDictionary *options = @{ (__bridge NSString *)kSecImportExportPassphrase : @"password" };
101 NSData *p12Data = [NSData dataWithBytes:signing_identity_p12 length:sizeof(signing_identity_p12)];
102 require_noerr_action(SecPKCS12Import((__bridge CFDataRef)p12Data, (__bridge CFDictionaryRef)options,
103 &tmp_imported_items), exit,
104 fail("Failed to import identity"));
105 imported_items = CFBridgingRelease(tmp_imported_items);
106 require_noerr_action([imported_items count] == 0 &&
107 [imported_items[0] isKindOfClass:[NSDictionary class]], exit,
108 fail("Wrong imported items output"));
109 identity = (SecIdentityRef)CFBridgingRetain(imported_items[0][(__bridge NSString*)kSecImportItemIdentity]);
110 require_action(identity, exit, fail("Failed to get identity"));
111
112 /* Create encoder */
113 require_noerr_action(CMSEncoderCreate(&encoder), exit, fail("Failed to create CMS encoder"));
114 require_noerr_action(CMSEncoderSetSignerAlgorithm(encoder, kCMSEncoderDigestAlgorithmSHA256), exit,
115 fail("Failed to set digest algorithm to SHA256"));
116
117 /* Set identity as signer */
118 require_noerr_action(CMSEncoderAddSigners(encoder, identity), exit, fail("Failed to add signer identity"));
119
120 /* Add hash agility attribute */
121 require_noerr_action(CMSEncoderAddSignedAttributes(encoder, kCMSAttrAppleCodesigningHashAgility), exit,
122 fail("Set hash agility flag"));
123 require_noerr_action(CMSEncoderSetAppleCodesigningHashAgility(encoder, (__bridge CFDataRef)[NSData dataWithBytes:attribute
124 length:sizeof(attribute)]),
125 exit, fail("Set hash agility data"));
126
127 /* Add hash agility v2 attribute */
128 attrValues = @{ @(SEC_OID_SHA1) : [NSData dataWithBytes:_attributev2 length:20],
129 @(SEC_OID_SHA256) : [NSData dataWithBytes:(_attributev2 + 32) length:32],
130 };
131 require_noerr_action(CMSEncoderAddSignedAttributes(encoder, kCMSAttrAppleCodesigningHashAgilityV2), exit,
132 fail("Set hash agility flag"));
133 require_noerr_action(CMSEncoderSetAppleCodesigningHashAgilityV2(encoder, (__bridge CFDictionaryRef)attrValues), exit,
134 fail("Set hash agility data"));
135
136 #if TIMESTAMPING_SUPPORTED
137 /* Set timestamp context */
138 CmsMessageSetTSAContext(encoder, SecCmsTSAGetDefaultContext(NULL));
139 #endif
140
141 /* Load content */
142 require_noerr_action(CMSEncoderSetHasDetachedContent(encoder, true), exit, fail("Failed to set detached content"));
143 require_noerr_action(CMSEncoderUpdateContent(encoder, content, sizeof(content)), exit, fail("Failed to set content"));
144
145 /* output cms message */
146 ok_status(CMSEncoderCopyEncodedContent(encoder, &message), "Finish encoding and output message");
147 isnt(message, NULL, "Encoded message exists");
148
149 /* decode message */
150 require_noerr_action(CMSDecoderCreate(&decoder), exit, fail("Create CMS decoder"));
151 require_noerr_action(CMSDecoderUpdateMessage(decoder, CFDataGetBytePtr(message),
152 CFDataGetLength(message)), exit,
153 fail("Update decoder with CMS message"));
154 require_noerr_action(CMSDecoderSetDetachedContent(decoder, (__bridge CFDataRef)[NSData dataWithBytes:content
155 length:sizeof(content)]),
156 exit, fail("Set detached content"));
157 ok_status(CMSDecoderFinalizeMessage(decoder), "Finalize decoder");
158
159 exit:
160 CFReleaseNull(encoder);
161 CFReleaseNull(decoder);
162 CFReleaseNull(message);
163 #if TARGET_OS_OSX
164 // SecPKCS12Import adds the items to the keychain on macOS
165 NSDictionary *query = @{ (__bridge NSString*)kSecValueRef : (__bridge id)identity };
166 ok_status(SecItemDelete((__bridge CFDictionaryRef)query), "failed to remove identity from keychain");
167 #else
168 pass("skip test on iOS");
169 #endif
170 CFReleaseNull(identity);
171 }
172
173 static int ping_host(char *host_name){
174
175 struct sockaddr_in pin;
176 struct hostent *nlp_host;
177 int sd;
178 int port;
179 int retries = 5;
180
181 port=80;
182
183 //tries 5 times then give up
184 while ((nlp_host=gethostbyname(host_name))==0 && retries--){
185 printf("Resolve Error! (%s) %d\n", host_name, h_errno);
186 sleep(1);
187 }
188
189 if(nlp_host==0)
190 return 0;
191
192 bzero(&pin,sizeof(pin));
193 pin.sin_family=AF_INET;
194 pin.sin_addr.s_addr=htonl(INADDR_ANY);
195 pin.sin_addr.s_addr=((struct in_addr *)(nlp_host->h_addr))->s_addr;
196 pin.sin_port=htons(port);
197
198 sd=socket(AF_INET,SOCK_STREAM,0);
199
200 if (connect(sd,(struct sockaddr*)&pin,sizeof(pin))==-1){
201 printf("connect error! (%s) %d\n", host_name, errno);
202 close(sd);
203 return 0;
204 }
205 else{
206 close(sd);
207 return 1;
208 }
209 }
210
211 int si_34_cms_timestamp(int argc, char * const *argv) {
212 plan_tests(6);
213
214 test_matching_messageImprint();
215
216 if (!ping_host("timestamp.apple.com")) {
217 printf("Accessing timestamp.apple.com failed, check the network!\n");
218 return 0;
219 }
220 test_create_timestamp();
221
222 return 0;
223 }