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