2 * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved.
4 * The contents of this file constitute Original Code as defined in and are
5 * subject to the Apple Public Source License Version 1.2 (the 'License').
6 * You may not use this file except in compliance with the License. Please
7 * obtain a copy of the License at http://www.apple.com/publicsource and
8 * read it before using this file.
10 * This Original Code and all software distributed under the License are
11 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
12 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
13 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS
14 * FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please
15 * see the License for the specific language governing rights and
16 * limitations under the License.
23 Contains: Bridge between SecTrustGetCSSMAnchorCertificates() and
24 TP's internally cached tpRootCert array.
26 Written by: Doug Mitchell.
28 Copyright: Copyright 2002 by Apple Computer, Inc., all rights reserved.
32 #include "rootCerts.h"
34 #if TP_ROOT_CERT_ENABLE
36 #include "certGroupUtils.h"
37 #include "tpdebugging.h"
38 #include <Security/Trust.h>
39 #include <Security/TrustStore.h>
40 #include <Security/debugging.h>
41 #include <Security/oidscert.h>
43 /* static in TPRootStore */
44 ModuleNexus
<TPRootStore
> TPRootStore::tpGlobalRoots
;
46 TPRootStore::~TPRootStore()
49 * Technically this never gets called because the only instance
50 * of a TPRootStore is via tpGlobalRoots. Freeing mRootCerts
51 * here really doesn't accomplish anything.
55 const tpRootCert
*TPRootStore::rootCerts(
56 CSSM_CL_HANDLE clHand
,
57 unsigned &numRootCerts
)
59 StLock
<Mutex
> _(mLock
);
61 numRootCerts
= mNumRootCerts
;
65 CssmAllocator
&alloc(CssmAllocator::standard());
67 tpRootCert
*tpRoots
= NULL
; // copy to mRootCerts on success
68 unsigned numTpRoots
= 0;
71 /* Obtain system-wide root certs in blob format */
72 Security::KeychainCore::TrustStore
&trustStore
=
73 Security::KeychainCore::Trust::gStore();
74 trustStore
.getCssmRootCertificates(roots
);
75 if(roots
.type() != CSSM_CERTGROUP_DATA
) {
76 secdebug("tpAnchor", "Bad certGroup Type (%d)\n",
80 numTpRoots
= roots
.count();
82 secdebug("tpAnchor", "empty certGroup\n");
86 /* set up tpRoots array, one for each cert in the group */
88 (tpRootCert
*)alloc
.malloc(numTpRoots
* sizeof(tpRootCert
));
89 memset(tpRoots
, 0, numTpRoots
* sizeof(tpRootCert
));
90 for(uint32 certNum
=0; certNum
<numTpRoots
; certNum
++) {
91 tpRootCert
*tpRoot
= &tpRoots
[certNum
];
92 const CSSM_DATA
*certData
= &((roots
.blobCerts())[certNum
]);
94 /* extract normalized subject name */
96 CSSM_HANDLE ResultsHandle
;
99 crtn
= CSSM_CL_CertGetFirstFieldValue(
102 &CSSMOID_X509V1SubjectName
,
107 secdebug("tpAnchor", "GetFirstFieldValue error on cert %u",
111 CSSM_CL_CertAbortQuery(clHand
, ResultsHandle
);
112 tpCopyCssmData(alloc
, field
, &tpRoot
->subjectName
);
113 CSSM_CL_FreeFieldValue(clHand
, &CSSMOID_X509V1SubjectName
,
116 /* extract public key info - the blob and key size in bits */
118 crtn
= CSSM_CL_CertGetKeyInfo(clHand
, certData
, &key
);
120 secdebug("tpAnchor", "CSSM_CL_CertGetKeyInfo error on cert %u",
122 /* clear out this tpRoot? */
125 tpCopyCssmData(alloc
, &key
->KeyData
, &tpRoot
->publicKey
);
126 tpRoot
->keySize
= key
->KeyHeader
.LogicalKeySizeInBits
;
128 /* A hole in the CDSA API: there is no free function at the
129 * CL API for this key. It got mallocd with clHand's
132 CSSM_API_MEMORY_FUNCS memFuncs
;
133 crtn
= CSSM_GetAPIMemoryFunctions(clHand
, &memFuncs
);
135 secdebug("tpAnchor", "CSSM_GetAPIMemoryFunctions error");
139 memFuncs
.free_func(key
->KeyData
.Data
, memFuncs
.AllocRef
);
140 memFuncs
.free_func(key
, memFuncs
.AllocRef
);
147 mNumRootCerts
= numTpRoots
;
148 numRootCerts
= mNumRootCerts
;
149 mRootCerts
= tpRoots
;
154 * Compare a root cert to a list of known embedded roots.
156 CSSM_BOOL
tp_isKnownRootCert(
157 TPCertInfo
*rootCert
, // raw cert to compare
158 CSSM_CL_HANDLE clHand
)
160 const CSSM_DATA
*subjectName
= NULL
;
161 CSSM_DATA_PTR publicKey
= NULL
;
163 CSSM_BOOL brtn
= CSSM_FALSE
;
164 CSSM_DATA_PTR valToFree
= NULL
;
165 const tpRootCert
*roots
;
168 roots
= TPRootStore::tpGlobalRoots().rootCerts(clHand
, numRoots
);
170 subjectName
= rootCert
->subjectName();
171 publicKey
= tp_CertGetPublicKey(rootCert
, &valToFree
);
172 if(publicKey
== NULL
) {
173 tpPolicyError("tp_isKnownRootCert: error retrieving public "
179 * Grind thru the list of known certs, demanding perfect match of
182 for(dex
=0; dex
<numRoots
; dex
++) {
183 if(!tpCompareCssmData(subjectName
,
184 &roots
[dex
].subjectName
)) {
187 if(!tpCompareCssmData(publicKey
,
188 &roots
[dex
].publicKey
)) {
195 tp_CertFreePublicKey(rootCert
->clHand(), valToFree
);
200 * Attempt to verify specified cert (from the end of a chain) with one of
203 CSSM_BOOL
tp_verifyWithKnownRoots(
204 CSSM_CL_HANDLE clHand
,
205 CSSM_CSP_HANDLE cspHand
,
206 TPCertInfo
*certToVfy
) // last in chain, not root
208 CSSM_KEY rootKey
; // pub key manufactured from tpRootCert info
209 CSSM_CC_HANDLE ccHand
; // signature context
212 const tpRootCert
*rootInfo
;
213 CSSM_BOOL brtn
= CSSM_FALSE
;
214 CSSM_KEYHEADER
*hdr
= &rootKey
.KeyHeader
;
215 CSSM_X509_ALGORITHM_IDENTIFIER_PTR algId
;
216 CSSM_DATA_PTR valToFree
= NULL
;
217 CSSM_ALGORITHMS sigAlg
;
218 const tpRootCert
*rootCerts
= NULL
;
219 unsigned numRootCerts
= 0;
221 memset(&rootKey
, 0, sizeof(CSSM_KEY
));
224 * Get signature algorithm from subject key
226 algId
= tp_CertGetAlgId(certToVfy
, &valToFree
);
231 /* subsequest errors to errOut: */
233 /* map to key and signature algorithm */
234 sigAlg
= tpOidToAldId(&algId
->algorithm
, &hdr
->AlgorithmId
);
235 if(sigAlg
== CSSM_ALGID_NONE
) {
236 tpPolicyError("tp_verifyWithKnownRoots: unknown sig alg");
240 /* Set up other constant key fields */
241 hdr
->BlobType
= CSSM_KEYBLOB_RAW
;
242 switch(hdr
->AlgorithmId
) {
244 hdr
->Format
= CSSM_KEYBLOB_RAW_FORMAT_PKCS1
;
247 hdr
->Format
= CSSM_KEYBLOB_RAW_FORMAT_FIPS186
;
250 hdr
->Format
= CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING
;
254 hdr
->Format
= CSSM_KEYBLOB_RAW_FORMAT_NONE
;
256 hdr
->KeyClass
= CSSM_KEYCLASS_PUBLIC_KEY
;
257 hdr
->KeyAttr
= CSSM_KEYATTR_MODIFIABLE
| CSSM_KEYATTR_EXTRACTABLE
;
258 hdr
->KeyUsage
= CSSM_KEYUSE_VERIFY
;
260 rootCerts
= TPRootStore::tpGlobalRoots().rootCerts(clHand
, numRootCerts
);
261 for(dex
=0; dex
<numRootCerts
; dex
++) {
262 rootInfo
= &rootCerts
[dex
];
263 if(!tpCompareCssmData(&rootInfo
->subjectName
, certToVfy
->issuerName())) {
268 /* only variation in key in the loop - raw key bits and size */
269 rootKey
.KeyData
= rootInfo
->publicKey
;
270 hdr
->LogicalKeySizeInBits
= rootInfo
->keySize
;
271 crtn
= CSSM_CSP_CreateSignatureContext(cspHand
,
277 tpPolicyError("tp_verifyWithKnownRoots: "
278 "CSSM_CSP_CreateSignatureContext err");
279 CssmError::throwMe(CSSMERR_TP_INTERNAL_ERROR
);
281 crtn
= CSSM_CL_CertVerify(clHand
,
283 certToVfy
->itemData(),
284 NULL
, // no signer cert
287 CSSM_DeleteContext(ccHand
);
288 if(crtn
== CSSM_OK
) {
295 if(valToFree
!= NULL
) {
296 tp_CertFreeAlgId(clHand
, valToFree
);
301 #endif /* TP_ROOT_CERT_ENABLE */