]>
Commit | Line | Data |
---|---|---|
b1ab9ed8 | 1 | /* |
d8f41ccd | 2 | * Copyright (c) 2004,2011-2012,2014 Apple Inc. All Rights Reserved. |
949d2ff0 | 3 | * |
b1ab9ed8 | 4 | * @APPLE_LICENSE_HEADER_START@ |
949d2ff0 | 5 | * |
b1ab9ed8 A |
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. | |
949d2ff0 | 12 | * |
b1ab9ed8 A |
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. | |
949d2ff0 | 20 | * |
b1ab9ed8 A |
21 | * @APPLE_LICENSE_HEADER_END@ |
22 | */ | |
23 | ||
24 | /* | |
25 | * ocspRequest.cpp - OCSP Request class | |
26 | */ | |
949d2ff0 | 27 | |
b1ab9ed8 A |
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 | /* | |
949d2ff0 A |
50 | * The only constructor. Subject and issuer must remain valid for the |
51 | * lifetime of this object (they are not refcounted). | |
b1ab9ed8 A |
52 | */ |
53 | OCSPRequest::OCSPRequest( | |
54 | TPCertInfo &subject, | |
55 | TPCertInfo &issuer, | |
56 | bool genNonce) | |
57 | : mCoder(NULL), | |
949d2ff0 | 58 | mSubject(subject), |
b1ab9ed8 A |
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; | |
949d2ff0 | 84 | CSSM_DATA issuerPubKeyBytes; |
b1ab9ed8 | 85 | /* from subject */ |
427c49bc | 86 | CSSM_DATA_PTR subjectSerial=NULL; |
b1ab9ed8 A |
87 | |
88 | CSSM_RETURN crtn; | |
89 | uint8 issuerNameHash[CC_SHA1_DIGEST_LENGTH]; | |
90 | uint8 pubKeyHash[CC_SHA1_DIGEST_LENGTH]; | |
91 | SecAsn1OCSPRequest singleReq; | |
92 | SecAsn1OCSPCertID &certId = singleReq.reqCert; | |
93 | SecAsn1OCSPSignedRequest signedReq; | |
94 | SecAsn1OCSPRequest *reqArray[2] = { &singleReq, NULL }; | |
95 | SecAsn1OCSPTbsRequest &tbs = signedReq.tbsRequest; | |
96 | uint8 version = 0; | |
97 | CSSM_DATA vers = {1, &version}; | |
98 | uint8 nonceBytes[OCSP_NONCE_SIZE]; | |
99 | CSSM_DATA nonceData = {OCSP_NONCE_SIZE, nonceBytes}; | |
100 | OCSPNonce *nonce = NULL; | |
101 | NSS_CertExtension *extenArray[2] = {NULL, NULL}; | |
949d2ff0 | 102 | |
b1ab9ed8 A |
103 | if(mEncoded.Data) { |
104 | /* already done */ | |
105 | return &mEncoded; | |
106 | } | |
107 | ||
949d2ff0 | 108 | /* |
b1ab9ed8 A |
109 | * One single request, no extensions |
110 | */ | |
111 | memset(&singleReq, 0, sizeof(singleReq)); | |
949d2ff0 | 112 | |
b1ab9ed8 A |
113 | /* algId refers to the hash we'll perform in issuer name and key */ |
114 | certId.algId.algorithm = CSSMOID_SHA1; | |
115 | certId.algId.parameters.Data = nullParam; | |
116 | certId.algId.parameters.Length = sizeof(nullParam); | |
117 | ||
118 | /* gather fields from two certs */ | |
119 | crtn = mSubject.fetchField(&CSSMOID_X509V1IssuerNameStd, &issuerName); | |
120 | if(crtn) { | |
121 | CssmError::throwMe(crtn); | |
122 | } | |
123 | crtn = mIssuer.fetchField(&CSSMOID_CSSMKeyStruct, &issuerKey); | |
124 | if(crtn) { | |
125 | goto errOut; | |
126 | } | |
127 | crtn = mSubject.fetchField(&CSSMOID_X509V1SerialNumber, &subjectSerial); | |
128 | if(crtn) { | |
129 | goto errOut; | |
130 | } | |
131 | ||
132 | /* SHA1(issuerName) */ | |
427c49bc | 133 | ocspdSha1(issuerName->Data, (CC_LONG)issuerName->Length, issuerNameHash); |
b1ab9ed8 A |
134 | |
135 | /* SHA1(issuer public key) */ | |
136 | if(issuerKey->Length != sizeof(CSSM_KEY)) { | |
137 | tpErrorLog("OCSPRequest::encode: malformed issuer key\n"); | |
138 | crtn = CSSMERR_TP_INTERNAL_ERROR; | |
139 | goto errOut; | |
140 | } | |
141 | issuerPubKey = (CSSM_KEY_PTR)issuerKey->Data; | |
949d2ff0 A |
142 | ocspdGetPublicKeyBytes(mCoder, issuerPubKey, issuerPubKeyBytes); |
143 | ocspdSha1(issuerPubKeyBytes.Data, (CC_LONG)issuerPubKeyBytes.Length, pubKeyHash); | |
144 | ||
b1ab9ed8 A |
145 | /* build the CertID from those components */ |
146 | certId.issuerNameHash.Data = issuerNameHash; | |
147 | certId.issuerNameHash.Length = CC_SHA1_DIGEST_LENGTH; | |
148 | certId.issuerPubKeyHash.Data = pubKeyHash; | |
949d2ff0 | 149 | certId.issuerPubKeyHash.Length = CC_SHA1_DIGEST_LENGTH; |
b1ab9ed8 A |
150 | certId.serialNumber = *subjectSerial; |
151 | ||
949d2ff0 | 152 | /* |
b1ab9ed8 A |
153 | * Build top level request with one entry in requestList, no signature, |
154 | * one optional extension (a nonce) | |
155 | */ | |
156 | memset(&signedReq, 0, sizeof(signedReq)); | |
157 | tbs.version = &vers; | |
158 | tbs.requestList = reqArray; | |
159 | ||
160 | /* one extension - the nonce */ | |
161 | if(mGenNonce) { | |
162 | DevRandomGenerator drg; | |
163 | drg.random(nonceBytes, OCSP_NONCE_SIZE); | |
164 | nonce = new OCSPNonce(mCoder, false, nonceData); | |
165 | extenArray[0] = nonce->nssExt(); | |
166 | tbs.requestExtensions = extenArray; | |
167 | SecAsn1AllocCopyItem(mCoder, &nonceData, &mNonce); | |
168 | } | |
949d2ff0 | 169 | |
b1ab9ed8 | 170 | /* Encode */ |
949d2ff0 | 171 | if(SecAsn1EncodeItem(mCoder, &signedReq, kSecAsn1OCSPSignedRequestTemplate, |
b1ab9ed8 A |
172 | &mEncoded)) { |
173 | tpErrorLog("OCSPRequest::encode: error encoding OCSP req\n"); | |
174 | crtn = CSSMERR_TP_INTERNAL_ERROR; | |
175 | goto errOut; | |
176 | } | |
177 | /* save a copy of the CertID */ | |
949d2ff0 A |
178 | mCertID = new OCSPClientCertID(*issuerName, issuerPubKeyBytes, *subjectSerial); |
179 | ||
b1ab9ed8 A |
180 | errOut: |
181 | if(issuerName) { | |
182 | mIssuer.freeField(&CSSMOID_X509V1IssuerNameStd, issuerName); | |
183 | } | |
184 | if(issuerKey) { | |
185 | mIssuer.freeField(&CSSMOID_CSSMKeyStruct, issuerKey); | |
186 | } | |
187 | if(subjectSerial) { | |
188 | mSubject.freeField(&CSSMOID_X509V1SerialNumber, subjectSerial); | |
189 | } | |
190 | if(nonce) { | |
191 | delete nonce; | |
192 | } | |
193 | if(crtn) { | |
194 | CssmError::throwMe(crtn); | |
195 | } | |
196 | return &mEncoded; | |
197 | } | |
198 | ||
199 | const CSSM_DATA *OCSPRequest::nonce() | |
200 | { | |
201 | /* not legal before encode() called */ | |
202 | assert(mEncoded.Data != NULL); | |
203 | if(mNonce.Data) { | |
204 | return &mNonce; | |
205 | } | |
206 | else { | |
207 | return NULL; | |
208 | } | |
209 | } | |
210 | ||
211 | OCSPClientCertID *OCSPRequest::certID() | |
212 | { | |
213 | encode(); | |
214 | return mCertID; | |
215 | } | |
216 |