]>
Commit | Line | Data |
---|---|---|
b1ab9ed8 | 1 | /* |
d8f41ccd | 2 | * Copyright (c) 2004-2005 Apple Computer, Inc. All Rights Reserved. |
b1ab9ed8 A |
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" | |
d8f41ccd A |
29 | #include <clAppUtils/CertParser.h> |
30 | #include <security_cdsa_utils/cuCdsaUtils.h> | |
b1ab9ed8 A |
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 | /* | |
d8f41ccd | 50 | * The only constructor. |
b1ab9ed8 | 51 | */ |
d8f41ccd A |
52 | OCSPRequest::OCSPRequest( |
53 | CertParser &subject, | |
54 | CertParser &issuer, | |
b1ab9ed8 A |
55 | bool genNonce) |
56 | : mCoder(NULL), | |
d8f41ccd | 57 | mSubject(subject), |
b1ab9ed8 A |
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 */ | |
d8f41ccd A |
80 | CSSM_DATA issuerName; |
81 | CSSM_DATA issuerKey; | |
b1ab9ed8 A |
82 | CSSM_KEY_PTR issuerPubKey; |
83 | /* from subject */ | |
d8f41ccd | 84 | CSSM_DATA subjectSerial; |
b1ab9ed8 | 85 | |
d8f41ccd | 86 | CSSM_RETURN crtn = CSSM_OK; |
b1ab9ed8 A |
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 */ | |
d8f41ccd A |
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); | |
b1ab9ed8 A |
126 | |
127 | /* SHA1(issuerName) */ | |
d8f41ccd | 128 | ocspdSha1(issuerName.Data, issuerName.Length, issuerNameHash); |
b1ab9ed8 A |
129 | |
130 | /* SHA1(issuer public key) */ | |
d8f41ccd A |
131 | issuerPubKey = (CSSM_KEY_PTR)issuerKey.Data; |
132 | ocspdSha1(issuerPubKey->KeyData.Data, issuerPubKey->KeyData.Length, pubKeyHash); | |
b1ab9ed8 A |
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; | |
d8f41ccd | 139 | certId.serialNumber = subjectSerial; |
b1ab9ed8 A |
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)) { | |
d8f41ccd | 162 | printf("OCSPRequest::encode: error encoding OCSP req\n"); |
b1ab9ed8 A |
163 | crtn = CSSMERR_TP_INTERNAL_ERROR; |
164 | goto errOut; | |
165 | } | |
166 | /* save a copy of the CertID */ | |
d8f41ccd | 167 | mCertID = new OCSPClientCertID(issuerName, issuerPubKey->KeyData, subjectSerial); |
b1ab9ed8 A |
168 | |
169 | errOut: | |
b1ab9ed8 A |
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 |