1/*
2 * Copyright (c) 2002-2004,2011,2013-2014 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 <Security/SecCertificateRequest.h>
25
26#include "SecBridge.h"
27#include "CertificateRequest.h"
28#include "SecImportExport.h"
29#include "SecCertificate.h"
30
31CFTypeID
32SecCertificateRequestGetTypeID(void)
33{
34	BEGIN_SECAPI
35
36	return gTypes().CertificateRequest.typeID;
37
38	END_SECAPI1(_kCFRuntimeNotATypeID)
39}
40
41
42OSStatus SecCertificateRequestCreate(
43        const CSSM_OID *policy,
44        CSSM_CERT_TYPE certificateType,
45        CSSM_TP_AUTHORITY_REQUEST_TYPE requestType,
46	    SecKeyRef privateKeyItemRef,
47	    SecKeyRef publicKeyItemRef,
48	    const SecCertificateRequestAttributeList* attributeList,
49        SecCertificateRequestRef* certRequest)
50{
51	BEGIN_SECAPI
52	Required(certRequest);
53	Required(policy);
54	*certRequest = (new CertificateRequest(*policy, certificateType, requestType,
55		privateKeyItemRef, publicKeyItemRef, attributeList))->handle();
56	END_SECAPI
57}
58
59
60OSStatus SecCertificateRequestSubmit(
61        SecCertificateRequestRef certRequest,
62        sint32* estimatedTime)
63{
64	BEGIN_SECAPI
65
66	CertificateRequest::required(certRequest)->submit(estimatedTime);
67
68	END_SECAPI
69}
70
71
72OSStatus SecCertificateRequestGetType(
73        SecCertificateRequestRef certRequestRef,
74        CSSM_TP_AUTHORITY_REQUEST_TYPE *requestType)
75{
76	BEGIN_SECAPI
77
78	Required(requestType);
79	*requestType = CertificateRequest::required(certRequestRef)->reqType();
80
81	END_SECAPI
82}
83
84OSStatus SecCertificateRequestGetResult(
85        SecCertificateRequestRef certRequestRef,
86        SecKeychainRef keychain,
87        sint32 *estimatedTime,
88        SecCertificateRef *certificateRef)
89{
90	BEGIN_SECAPI
91
92	CssmData certData;
93	*certificateRef = NULL;
94	CertificateRequest::required(certRequestRef)->getResult(estimatedTime, certData);
95	if(certData.data() != NULL) {
96		/*
97		 * Convert to SecCertifcateRef, optionally import.
98		 */
99		CFDataRef cfCert = CFDataCreate(NULL, (UInt8 *)certData.data(), certData.Length);
100		SecExternalItemType itemType = kSecItemTypeCertificate;
101		CFArrayRef outItems = NULL;
102		bool freeKcRef = false;
103		OSStatus ortn;
104
105		if(keychain == NULL) {
106			/*
107			 * Unlike most Sec* calls, if the keychain argument to SecKeychainItemImport()
108			 * is NULL, the item is not imported to the default keychain. At our
109			 * interface, however, a NULL keychain means "import to the default
110			 * keychain".
111			 */
112			ortn = SecKeychainCopyDefault(&keychain);
113			if(ortn) {
114				certReqDbg("GetResult: SecKeychainCopyDefault failure");
115				/* oh well, there's nothing we can do about this */
116			}
117			else {
118				freeKcRef = true;
119			}
120		}
121		ortn = SecKeychainItemImport(cfCert, NULL,
122			NULL,			// format, don't care
123			&itemType,
124			0,				// flags
125			NULL,			// keyParams
126			keychain,		// optional, like ours
127			&outItems);
128		CFRelease(cfCert);
129		if(freeKcRef) {
130			CFRelease(keychain);
131		}
132		if(ortn) {
133			certReqDbg("SecCertificateRequestGetResult: SecKeychainItemImport failure");
134			MacOSError::throwMe(ortn);
135		}
136		CFIndex numItems = CFArrayGetCount(outItems);
137		switch(numItems) {
138			case 0:
139				certReqDbg("SecCertificateRequestGetResult: import zero items");
140				MacOSError::throwMe(errSecInternalComponent);
141			default:
142				certReqDbg("SecCertificateRequestGetResult: import %d items",
143					(int)numItems);
144				/* but drop thru anyway, take the first one */
145			case 1:
146				SecCertificateRef certRef =
147					(SecCertificateRef)(CFArrayGetValueAtIndex(outItems, 0));
148				if(CFGetTypeID(certRef) != SecCertificateGetTypeID()) {
149					certReqDbg("SecCertificateRequestGetResult: bad type");
150				}
151				else {
152					CFRetain(certRef);
153					*certificateRef = certRef;
154				}
155		}
156		CFRelease(outItems);
157	}
158	END_SECAPI
159}
160
161OSStatus SecCertificateFindRequest(
162        const CSSM_OID *policy,
163        CSSM_CERT_TYPE certificateType,
164        CSSM_TP_AUTHORITY_REQUEST_TYPE requestType,
165		SecKeyRef publicKeyItemRef,
166		SecKeyRef privateKeyItemRef,
167		const SecCertificateRequestAttributeList* attributeList,
168        SecCertificateRequestRef* certRequest)
169{
170	BEGIN_SECAPI
171
172	Required(certRequest);
173	Required(policy);
174	*certRequest = (new CertificateRequest(*policy, certificateType, requestType,
175		privateKeyItemRef, publicKeyItemRef, attributeList, false))->handle();
176	END_SECAPI
177}
178
179
180OSStatus SecCertificateRequestGetData(
181	SecCertificateRequestRef	certRequestRef,
182	CSSM_DATA					*data)
183{
184	BEGIN_SECAPI
185
186	Required(data);
187	CertificateRequest::required(certRequestRef)->getReturnData(CssmData::overlay(*data));
188
189	END_SECAPI
190}
191