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