]> git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_codesigning/lib/xar++.cpp
Security-58286.260.20.tar.gz
[apple/security.git] / OSX / libsecurity_codesigning / lib / xar++.cpp
1 /*
2 * Copyright (c) 2011-2012 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 //
25 // xar++ - interface to XAR-format archive files
26 //
27 #include "xar++.h"
28 #include "notarization.h"
29 #include <security_utilities/cfutilities.h>
30 #include <Security/Security.h>
31
32
33 namespace Security {
34 namespace CodeSigning {
35
36
37 Xar::Xar(const char *path)
38 {
39 mXar = 0;
40 mSigCMS = 0;
41 mSigClassic = 0;
42 if (path)
43 open(path);
44 }
45
46 void Xar::open(const char *path)
47 {
48 if ((mXar = ::xar_open(path, READ)) == NULL)
49 return;
50
51 mPath = std::string(path);
52
53 xar_signature_t sig = ::xar_signature_first(mXar);
54 // read signatures until we find a CMS signature
55 while (sig && mSigCMS == NULL) {
56 const char *type = ::xar_signature_type(sig);
57 if (strcmp(type, "CMS") == 0) {
58 mSigCMS = sig;
59 } else if (strcmp(type, "RSA") == 0) {
60 mSigClassic = sig;
61 }
62 sig = ::xar_signature_next(sig);
63 }
64 }
65
66 Xar::~Xar()
67 {
68 if (mXar)
69 ::xar_close(mXar);
70 }
71
72 static CFArrayRef copyCertChainFromSignature(xar_signature_t sig)
73 {
74 unsigned count = xar_signature_get_x509certificate_count(sig);
75 CFRef<CFMutableArrayRef> certs = makeCFMutableArray(0);
76 for (unsigned ix = 0; ix < count; ix++) {
77 const uint8_t *data;
78 uint32_t length;
79 if (xar_signature_get_x509certificate_data(sig, ix, &data, &length) == 0) {
80 CFTempData cdata(data, length);
81 CFRef<SecCertificateRef> cert = SecCertificateCreateWithData(NULL, cdata);
82 CFArrayAppendValue(certs, cert.get());
83 }
84 }
85 return certs.yield();
86 }
87
88 CFArrayRef Xar::copyCertChain()
89 {
90 if (mSigCMS)
91 return copyCertChainFromSignature(mSigCMS);
92 else if (mSigClassic)
93 return copyCertChainFromSignature(mSigClassic);
94 return NULL;
95 }
96
97 void Xar::registerStapledNotarization()
98 {
99 registerStapledTicketInPackage(mPath);
100 }
101
102 CFDataRef Xar::createPackageChecksum()
103 {
104 xar_signature_t sig = NULL;
105
106 // Always prefer a CMS signature to a class signature and return early
107 // if no appropriate signature has been found.
108 if (mSigCMS) {
109 sig = mSigCMS;
110 } else if (mSigClassic) {
111 sig = mSigClassic;
112 } else {
113 return NULL;
114 }
115
116 // Extract the signed data from the xar, which is actually just the checksum
117 // we use as an identifying hash.
118 uint8_t *data = NULL;
119 uint32_t length;
120 if (xar_signature_copy_signed_data(sig, &data, &length, NULL, NULL, NULL) != 0) {
121 secerror("Unable to extract package hash for package: %s", mPath.c_str());
122 return NULL;
123 }
124
125 return makeCFData(data, length);
126 }
127
128 SecCSDigestAlgorithm Xar::checksumDigestAlgorithm()
129 {
130 int32_t error = 0;
131 const char* value = NULL;
132 unsigned long size = 0;
133
134 if (mXar == NULL) {
135 secerror("Evaluating checksum digest on bad xar: %s", mPath.c_str());
136 return kSecCodeSignatureNoHash;
137 }
138
139 error = xar_prop_get((xar_file_t)mXar, "checksum/size", &value);
140 if (error == -1) {
141 secerror("Unable to extract package checksum size: %s", mPath.c_str());
142 return kSecCodeSignatureNoHash;
143 }
144
145 size = strtoul(value, NULL, 10);
146 switch (size) {
147 case CC_SHA1_DIGEST_LENGTH:
148 return kSecCodeSignatureHashSHA1;
149 case CC_SHA256_DIGEST_LENGTH:
150 return kSecCodeSignatureHashSHA256;
151 case CC_SHA512_DIGEST_LENGTH:
152 return kSecCodeSignatureHashSHA512;
153 case CC_MD5_DIGEST_LENGTH:
154 default:
155 return kSecCodeSignatureNoHash;
156 }
157 }
158
159 } // end namespace CodeSigning
160 } // end namespace Security