]> git.saurik.com Git - apple/security.git/blob - libsecurity_apple_x509_tp/lib/ocspRequest.cpp
Security-55471.tar.gz
[apple/security.git] / libsecurity_apple_x509_tp / lib / ocspRequest.cpp
1 /*
2 * Copyright (c) 2004 Apple Computer, 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 */
44 static 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 */
53 OCSPRequest::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
70 OCSPRequest::~OCSPRequest()
71 {
72 delete mCertID;
73 if(mCoder) {
74 SecAsn1CoderRelease(mCoder);
75 }
76 }
77
78 const 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
178 errOut:
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
197 const 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
209 OCSPClientCertID *OCSPRequest::certID()
210 {
211 encode();
212 return mCertID;
213 }
214