1/* 2 * Copyright (c) 2004,2011-2012,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 * ocspRequest.cpp - OCSP Request class 26 */ 27 28#include "ocspRequest.h" 29#include "certGroupUtils.h" 30#include "tpdebugging.h" 31#include <security_ocspd/ocspResponse.h> 32#include <security_ocspd/ocspExtensions.h> 33#include <security_ocspd/ocspdUtils.h> 34#include <assert.h> 35#include <string.h> 36#include <Security/oidsalg.h> 37#include <Security/oidscert.h> 38#include <Security/ocspTemplates.h> 39#include <security_utilities/devrandom.h> 40#include <CommonCrypto/CommonDigest.h> 41#include <security_cdsa_utilities/cssmerrors.h> 42 43/* preencoded DER NULL */ 44static uint8 nullParam[2] = {5, 0}; 45 46/* size of nonce we generate, in bytes */ 47#define OCSP_NONCE_SIZE 8 48 49/* 50 * The only constructor. Subject and issuer must remain valid for the 51 * lifetime of this object (they are not refcounted). 52 */ 53OCSPRequest::OCSPRequest( 54 TPCertInfo &subject, 55 TPCertInfo &issuer, 56 bool genNonce) 57 : mCoder(NULL), 58 mSubject(subject), 59 mIssuer(issuer), 60 mGenNonce(genNonce), 61 mCertID(NULL) 62{ 63 SecAsn1CoderCreate(&mCoder); 64 mNonce.Data = NULL; 65 mNonce.Length = 0; 66 mEncoded.Data = NULL; 67 mEncoded.Length = 0; 68} 69 70OCSPRequest::~OCSPRequest() 71{ 72 delete mCertID; 73 if(mCoder) { 74 SecAsn1CoderRelease(mCoder); 75 } 76} 77 78const CSSM_DATA *OCSPRequest::encode() 79{ 80 /* fields obtained from issuer */ 81 CSSM_DATA_PTR issuerName; 82 CSSM_DATA_PTR issuerKey; 83 CSSM_KEY_PTR issuerPubKey; 84 /* from subject */ 85 CSSM_DATA_PTR subjectSerial=NULL; 86 87 CSSM_RETURN crtn; 88 uint8 issuerNameHash[CC_SHA1_DIGEST_LENGTH]; 89 uint8 pubKeyHash[CC_SHA1_DIGEST_LENGTH]; 90 SecAsn1OCSPRequest singleReq; 91 SecAsn1OCSPCertID &certId = singleReq.reqCert; 92 SecAsn1OCSPSignedRequest signedReq; 93 SecAsn1OCSPRequest *reqArray[2] = { &singleReq, NULL }; 94 SecAsn1OCSPTbsRequest &tbs = signedReq.tbsRequest; 95 uint8 version = 0; 96 CSSM_DATA vers = {1, &version}; 97 uint8 nonceBytes[OCSP_NONCE_SIZE]; 98 CSSM_DATA nonceData = {OCSP_NONCE_SIZE, nonceBytes}; 99 OCSPNonce *nonce = NULL; 100 NSS_CertExtension *extenArray[2] = {NULL, NULL}; 101 102 if(mEncoded.Data) { 103 /* already done */ 104 return &mEncoded; 105 } 106 107 /* 108 * One single request, no extensions 109 */ 110 memset(&singleReq, 0, sizeof(singleReq)); 111 112 /* algId refers to the hash we'll perform in issuer name and key */ 113 certId.algId.algorithm = CSSMOID_SHA1; 114 certId.algId.parameters.Data = nullParam; 115 certId.algId.parameters.Length = sizeof(nullParam); 116 117 /* gather fields from two certs */ 118 crtn = mSubject.fetchField(&CSSMOID_X509V1IssuerNameStd, &issuerName); 119 if(crtn) { 120 CssmError::throwMe(crtn); 121 } 122 crtn = mIssuer.fetchField(&CSSMOID_CSSMKeyStruct, &issuerKey); 123 if(crtn) { 124 goto errOut; 125 } 126 crtn = mSubject.fetchField(&CSSMOID_X509V1SerialNumber, &subjectSerial); 127 if(crtn) { 128 goto errOut; 129 } 130 131 /* SHA1(issuerName) */ 132 ocspdSha1(issuerName->Data, (CC_LONG)issuerName->Length, issuerNameHash); 133 134 /* SHA1(issuer public key) */ 135 if(issuerKey->Length != sizeof(CSSM_KEY)) { 136 tpErrorLog("OCSPRequest::encode: malformed issuer key\n"); 137 crtn = CSSMERR_TP_INTERNAL_ERROR; 138 goto errOut; 139 } 140 issuerPubKey = (CSSM_KEY_PTR)issuerKey->Data; 141 ocspdSha1(issuerPubKey->KeyData.Data, (CC_LONG)issuerPubKey->KeyData.Length, pubKeyHash); 142 143 /* build the CertID from those components */ 144 certId.issuerNameHash.Data = issuerNameHash; 145 certId.issuerNameHash.Length = CC_SHA1_DIGEST_LENGTH; 146 certId.issuerPubKeyHash.Data = pubKeyHash; 147 certId.issuerPubKeyHash.Length = CC_SHA1_DIGEST_LENGTH; 148 certId.serialNumber = *subjectSerial; 149 150 /* 151 * Build top level request with one entry in requestList, no signature, 152 * one optional extension (a nonce) 153 */ 154 memset(&signedReq, 0, sizeof(signedReq)); 155 tbs.version = &vers; 156 tbs.requestList = reqArray; 157 158 /* one extension - the nonce */ 159 if(mGenNonce) { 160 DevRandomGenerator drg; 161 drg.random(nonceBytes, OCSP_NONCE_SIZE); 162 nonce = new OCSPNonce(mCoder, false, nonceData); 163 extenArray[0] = nonce->nssExt(); 164 tbs.requestExtensions = extenArray; 165 SecAsn1AllocCopyItem(mCoder, &nonceData, &mNonce); 166 } 167 168 /* Encode */ 169 if(SecAsn1EncodeItem(mCoder, &signedReq, kSecAsn1OCSPSignedRequestTemplate, 170 &mEncoded)) { 171 tpErrorLog("OCSPRequest::encode: error encoding OCSP req\n"); 172 crtn = CSSMERR_TP_INTERNAL_ERROR; 173 goto errOut; 174 } 175 /* save a copy of the CertID */ 176 mCertID = new OCSPClientCertID(*issuerName, issuerPubKey->KeyData, *subjectSerial); 177 178errOut: 179 if(issuerName) { 180 mIssuer.freeField(&CSSMOID_X509V1IssuerNameStd, issuerName); 181 } 182 if(issuerKey) { 183 mIssuer.freeField(&CSSMOID_CSSMKeyStruct, issuerKey); 184 } 185 if(subjectSerial) { 186 mSubject.freeField(&CSSMOID_X509V1SerialNumber, subjectSerial); 187 } 188 if(nonce) { 189 delete nonce; 190 } 191 if(crtn) { 192 CssmError::throwMe(crtn); 193 } 194 return &mEncoded; 195} 196 197const CSSM_DATA *OCSPRequest::nonce() 198{ 199 /* not legal before encode() called */ 200 assert(mEncoded.Data != NULL); 201 if(mNonce.Data) { 202 return &mNonce; 203 } 204 else { 205 return NULL; 206 } 207} 208 209OCSPClientCertID *OCSPRequest::certID() 210{ 211 encode(); 212 return mCertID; 213} 214 215