1/*
2 * Copyright (c) 2004,2011,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/*
25 * ocspExtensions.cpp - OCSP Extension support.
26 */
27
28#include "ocspExtensions.h"
29#include "ocspdDebug.h"
30#include "ocspdUtils.h"
31#include <Security/oidscrl.h>
32#include <Security/cssmapple.h>
33#include <strings.h>
34#include "ocspdDebug.h"
35#include <security_cdsa_utilities/cssmerrors.h>
36
37#pragma mark ----- base class : OCSCExtension -----
38
39/*
40 * Public means to vend a subclass of this object while decoding.
41 */
42OCSPExtension *OCSPExtension::createFromNSS(
43	SecAsn1CoderRef		coder,
44	const NSS_CertExtension	&nssExt)
45{
46	const CSSM_OID *extnId = &nssExt.extnId;
47	if(ocspdCompareCssmData(extnId, &CSSMOID_PKIX_OCSP_NONCE)) {
48		return new OCSPNonce(coder, nssExt);
49	}
50	/* more here */
51	else {
52		return new OCSPExtension(coder, nssExt, OET_Unknown);
53	}
54}
55
56/*
57 * Called in two circumstances:
58 *
59 * -- from subclass-specific constructor during decode
60 * -- from createFromNSS (during decode) when we don't recognize the extension ID
61 */
62OCSPExtension::OCSPExtension(
63	SecAsn1CoderRef			coder,
64	const NSS_CertExtension	&nssExt,
65	OCSPExtensionTag		tag)
66		: mNssExt(const_cast<NSS_CertExtension *>(&nssExt)),
67		  mCoder(coder),
68		  mTag(tag),
69		  mUnrecognizedCritical(false)
70{
71	if((nssExt.critical.Data != NULL) && (*nssExt.critical.Data != 0)) {
72		mCritical = true;
73	}
74	else {
75		mCritical = false;
76	}
77	if(mCritical && (tag == OET_Unknown)) {
78		mUnrecognizedCritical = true;
79	}
80}
81
82/*
83 * Constructor during encode, called from subclass-specific constructor�(which
84 * always has all of the subclass-specific arguments).
85 */
86OCSPExtension::OCSPExtension(
87	SecAsn1CoderRef			coder,			// passed to subclass constructor
88	const CSSM_OID			&extnId,		// subclass knows this
89	OCSPExtensionTag		tag,			// subclass knows this
90	bool					critical)		// passed to subclass constructor
91		: mNssExt(NULL),					// we'll cook this up
92		  mCoder(coder),
93		  mCritical(critical),
94		  mTag(tag),
95		  mUnrecognizedCritical(false)		// this is a tautology
96{
97	mNssExt = (NSS_CertExtension *)SecAsn1Malloc(coder, sizeof(NSS_CertExtension));
98	memset(mNssExt, 0, sizeof(NSS_CertExtension));
99	SecAsn1AllocCopyItem(coder, &extnId, &mNssExt->extnId);
100	/* alloc one byte for critical flag */
101	SecAsn1AllocItem(coder, &mNssExt->critical, 1);
102	mNssExt->critical.Data[0] = critical ? 0xff : 0;
103}
104
105OCSPExtension::~OCSPExtension()
106{
107	/* nothing for now, need a virtual function for dynamic casts */
108}
109
110#pragma mark ---- Nonce -----
111
112/*
113 * Public constructor on encode
114 */
115OCSPNonce::OCSPNonce(
116	SecAsn1CoderRef		coder,
117	bool				critical,
118	const CSSM_DATA		&nonce)
119		: OCSPExtension(coder, CSSMOID_PKIX_OCSP_NONCE, OET_Nonce, critical)
120{
121	/*
122	 * They don't get much simpler than this: the nonce is the literal value
123	 * of NSS_CertExtension.value.
124	 */
125	SecAsn1AllocCopyItem(coder, &nonce, &mNonce);
126	setDerValue(mNonce);
127}
128
129/* construct during decode, called only by OCSPExtension::createFromNSS() */
130OCSPNonce::OCSPNonce(
131	SecAsn1CoderRef		coder,
132	const NSS_CertExtension &nssExt)
133		: OCSPExtension(coder, nssExt, OET_Nonce)
134{
135	/* only subclass-specific stuff is the nonce, no further processing needed */
136	SecAsn1AllocCopyItem(coder, &nssExt.value, &mNonce);
137}
138
139OCSPNonce::~OCSPNonce()
140{
141	/* nothing for now, need a virtual function for dynamic casts */
142}
143
144#pragma mark ----- Extensions array -----
145
146OCSPExtensions::OCSPExtensions(
147	NSS_CertExtension **nssExts)
148		: mCoder(NULL), mNumExtensions(0), mExtensions(NULL)
149{
150	SecAsn1CoderCreate(&mCoder);
151	mNumExtensions = ocspdArraySize((const void **)nssExts);
152	if(mNumExtensions == 0) {
153		return;
154	}
155
156	mExtensions = (OCSPExtension **)SecAsn1Malloc(mCoder,
157		(mNumExtensions * sizeof(OCSPExtension *)));
158	for(unsigned dex=0; dex<mNumExtensions; dex++) {
159		try {
160			mExtensions[dex] =
161				OCSPExtension::createFromNSS(mCoder, *nssExts[dex]);
162			if(mExtensions[dex] == NULL) {
163				ocspdErrorLog("OCSPExtensions: extension failure (NULL) dex %u\n", dex);
164				CssmError::throwMe(CSSMERR_APPLETP_OCSP_BAD_RESPONSE);
165			}
166			if(mExtensions[dex]->unrecognizedCritical()) {
167				ocspdErrorLog("OCSPExtensions: unrecognized critical extension\n");
168				CssmError::throwMe(CSSMERR_APPLETP_OCSP_BAD_RESPONSE);
169			}
170		}
171		catch (...) {
172			ocspdErrorLog("OCSPExtensions: extension failure dex %u\n", dex);
173			CssmError::throwMe(CSSMERR_APPLETP_OCSP_BAD_RESPONSE);
174		}
175	}
176}
177
178OCSPExtensions::~OCSPExtensions()
179{
180	for(unsigned dex=0; dex<mNumExtensions; dex++) {
181		delete mExtensions[dex];
182	}
183	if(mCoder) {
184		SecAsn1CoderRelease(mCoder);
185	}
186}
187
188/* find parsed extension in mExtensions with specified OID */
189OCSPExtension *OCSPExtensions::findExtension(
190	const CSSM_OID &oid)
191{
192	for(unsigned dex=0; dex<mNumExtensions; dex++) {
193		const CSSM_OID &extnId = mExtensions[dex]->extnId();
194		if(ocspdCompareCssmData(&oid, &extnId)) {
195			return mExtensions[dex];
196		}
197	}
198	return NULL;
199}
200
201