]> git.saurik.com Git - apple/security.git/blob - SecurityTests/clxutils/ocspTool/ocspRequest.cpp
Security-57031.1.35.tar.gz
[apple/security.git] / SecurityTests / clxutils / ocspTool / ocspRequest.cpp
1 /*
2 * Copyright (c) 2004-2005 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 <clAppUtils/CertParser.h>
30 #include <security_cdsa_utils/cuCdsaUtils.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.
51 */
52 OCSPRequest::OCSPRequest(
53 CertParser &subject,
54 CertParser &issuer,
55 bool genNonce)
56 : mCoder(NULL),
57 mSubject(subject),
58 mIssuer(issuer),
59 mGenNonce(genNonce),
60 mCertID(NULL)
61 {
62 SecAsn1CoderCreate(&mCoder);
63 mNonce.Data = NULL;
64 mNonce.Length = 0;
65 mEncoded.Data = NULL;
66 mEncoded.Length = 0;
67 }
68
69 OCSPRequest::~OCSPRequest()
70 {
71 delete mCertID;
72 if(mCoder) {
73 SecAsn1CoderRelease(mCoder);
74 }
75 }
76
77 const CSSM_DATA *OCSPRequest::encode()
78 {
79 /* fields obtained from issuer */
80 CSSM_DATA issuerName;
81 CSSM_DATA issuerKey;
82 CSSM_KEY_PTR issuerPubKey;
83 /* from subject */
84 CSSM_DATA subjectSerial;
85
86 CSSM_RETURN crtn = CSSM_OK;
87 uint8 issuerNameHash[CC_SHA1_DIGEST_LENGTH];
88 uint8 pubKeyHash[CC_SHA1_DIGEST_LENGTH];
89 SecAsn1OCSPRequest singleReq;
90 SecAsn1OCSPCertID &certId = singleReq.reqCert;
91 SecAsn1OCSPSignedRequest signedReq;
92 SecAsn1OCSPRequest *reqArray[2] = { &singleReq, NULL };
93 SecAsn1OCSPTbsRequest &tbs = signedReq.tbsRequest;
94 uint8 version = 0;
95 CSSM_DATA vers = {1, &version};
96 uint8 nonceBytes[OCSP_NONCE_SIZE];
97 CSSM_DATA nonceData = {OCSP_NONCE_SIZE, nonceBytes};
98 OCSPNonce *nonce = NULL;
99 NSS_CertExtension *extenArray[2] = {NULL, NULL};
100
101 if(mEncoded.Data) {
102 /* already done */
103 return &mEncoded;
104 }
105
106 /*
107 * One single request, no extensions
108 */
109 memset(&singleReq, 0, sizeof(singleReq));
110
111 /* algId refers to the hash we'll perform in issuer name and key */
112 certId.algId.algorithm = CSSMOID_SHA1;
113 certId.algId.parameters.Data = nullParam;
114 certId.algId.parameters.Length = sizeof(nullParam);
115
116 /* gather fields from two certs */
117 issuerName.Length = 0; // don't check
118 issuerName.Data = (uint8 *)mSubject.fieldForOid(CSSMOID_X509V1IssuerNameStd,
119 issuerName.Length);
120 issuerKey.Length = sizeof(CSSM_KEY);
121 issuerKey.Data = (uint8 *)mIssuer.fieldForOid(CSSMOID_CSSMKeyStruct,
122 issuerKey.Length);
123 subjectSerial.Length = 0;
124 subjectSerial.Data = (uint8 *)mSubject.fieldForOid(CSSMOID_X509V1SerialNumber,
125 subjectSerial.Length);
126
127 /* SHA1(issuerName) */
128 ocspdSha1(issuerName.Data, issuerName.Length, issuerNameHash);
129
130 /* SHA1(issuer public key) */
131 issuerPubKey = (CSSM_KEY_PTR)issuerKey.Data;
132 ocspdSha1(issuerPubKey->KeyData.Data, issuerPubKey->KeyData.Length, pubKeyHash);
133
134 /* build the CertID from those components */
135 certId.issuerNameHash.Data = issuerNameHash;
136 certId.issuerNameHash.Length = CC_SHA1_DIGEST_LENGTH;
137 certId.issuerPubKeyHash.Data = pubKeyHash;
138 certId.issuerPubKeyHash.Length = CC_SHA1_DIGEST_LENGTH;
139 certId.serialNumber = subjectSerial;
140
141 /*
142 * Build top level request with one entry in requestList, no signature,
143 * one optional extension (a nonce)
144 */
145 memset(&signedReq, 0, sizeof(signedReq));
146 tbs.version = &vers;
147 tbs.requestList = reqArray;
148
149 /* one extension - the nonce */
150 if(mGenNonce) {
151 DevRandomGenerator drg;
152 drg.random(nonceBytes, OCSP_NONCE_SIZE);
153 nonce = new OCSPNonce(mCoder, false, nonceData);
154 extenArray[0] = nonce->nssExt();
155 tbs.requestExtensions = extenArray;
156 SecAsn1AllocCopyItem(mCoder, &nonceData, &mNonce);
157 }
158
159 /* Encode */
160 if(SecAsn1EncodeItem(mCoder, &signedReq, kSecAsn1OCSPSignedRequestTemplate,
161 &mEncoded)) {
162 printf("OCSPRequest::encode: error encoding OCSP req\n");
163 crtn = CSSMERR_TP_INTERNAL_ERROR;
164 goto errOut;
165 }
166 /* save a copy of the CertID */
167 mCertID = new OCSPClientCertID(issuerName, issuerPubKey->KeyData, subjectSerial);
168
169 errOut:
170 if(nonce) {
171 delete nonce;
172 }
173 if(crtn) {
174 CssmError::throwMe(crtn);
175 }
176 return &mEncoded;
177 }
178
179 const CSSM_DATA *OCSPRequest::nonce()
180 {
181 /* not legal before encode() called */
182 assert(mEncoded.Data != NULL);
183 if(mNonce.Data) {
184 return &mNonce;
185 }
186 else {
187 return NULL;
188 }
189 }
190
191 OCSPClientCertID *OCSPRequest::certID()
192 {
193 encode();
194 return mCertID;
195 }
196