/ OSX / libsecurity_ocspd / common / ocspExtensions.cpp
ocspExtensions.cpp
  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   */
 42  OCSPExtension *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   */
 62  OCSPExtension::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   */ 
 86  OCSPExtension::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  
105  OCSPExtension::~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   */
115  OCSPNonce::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() */
130  OCSPNonce::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  
139  OCSPNonce::~OCSPNonce()
140  {
141  	/* nothing for now, need a virtual function for dynamic casts */
142  }
143  
144  #pragma mark ----- Extensions array -----
145  
146  OCSPExtensions::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  
178  OCSPExtensions::~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 */
189  OCSPExtension *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