2 * Copyright (c) 2011-2012 Apple Inc. All Rights Reserved.
4 * @APPLE_LICENSE_HEADER_START@
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
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.
21 * @APPLE_LICENSE_HEADER_END@
25 // xar++ - interface to XAR-format archive files
28 #include "notarization.h"
29 #include <security_utilities/cfutilities.h>
30 #include <Security/Security.h>
34 namespace CodeSigning
{
37 Xar::Xar(const char *path
)
46 void Xar::open(const char *path
)
48 if ((mXar
= ::xar_open(path
, READ
)) == NULL
)
51 mPath
= std::string(path
);
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) {
59 } else if (strcmp(type
, "RSA") == 0) {
62 sig
= ::xar_signature_next(sig
);
72 static CFArrayRef
copyCertChainFromSignature(xar_signature_t sig
)
74 unsigned count
= xar_signature_get_x509certificate_count(sig
);
75 CFRef
<CFMutableArrayRef
> certs
= makeCFMutableArray(0);
76 for (unsigned ix
= 0; ix
< count
; ix
++) {
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());
88 CFArrayRef
Xar::copyCertChain()
91 return copyCertChainFromSignature(mSigCMS
);
93 return copyCertChainFromSignature(mSigClassic
);
97 void Xar::registerStapledNotarization()
99 registerStapledTicketInPackage(mPath
);
102 CFDataRef
Xar::createPackageChecksum()
104 xar_signature_t sig
= NULL
;
106 // Always prefer a CMS signature to a class signature and return early
107 // if no appropriate signature has been found.
110 } else if (mSigClassic
) {
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
;
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());
125 // xar_signature_copy_signed_data returns malloc'd data that can be used without copying
126 // but must be free'd properly later.
127 return makeCFDataMalloc(data
, length
);
130 SecCSDigestAlgorithm
Xar::checksumDigestAlgorithm()
133 const char* value
= NULL
;
134 unsigned long size
= 0;
137 secerror("Evaluating checksum digest on bad xar: %s", mPath
.c_str());
138 return kSecCodeSignatureNoHash
;
141 error
= xar_prop_get((xar_file_t
)mXar
, "checksum/size", &value
);
143 secerror("Unable to extract package checksum size: %s", mPath
.c_str());
144 return kSecCodeSignatureNoHash
;
147 size
= strtoul(value
, NULL
, 10);
149 case CC_SHA1_DIGEST_LENGTH
:
150 return kSecCodeSignatureHashSHA1
;
151 case CC_SHA256_DIGEST_LENGTH
:
152 return kSecCodeSignatureHashSHA256
;
153 case CC_SHA512_DIGEST_LENGTH
:
154 return kSecCodeSignatureHashSHA512
;
155 case CC_MD5_DIGEST_LENGTH
:
157 return kSecCodeSignatureNoHash
;
161 } // end namespace CodeSigning
162 } // end namespace Security