2 * Copyright (c) 2004,2011-2012,2014 Apple Inc. All Rights Reserved.
4 * @APPLE_LICENSE_HEADER_START@
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
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.
21 * @APPLE_LICENSE_HEADER_END@
25 * ocspRequest.cpp - OCSP Request class
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>
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>
43 /* preencoded DER NULL */
44 static uint8 nullParam
[2] = {5, 0};
46 /* size of nonce we generate, in bytes */
47 #define OCSP_NONCE_SIZE 8
50 * The only constructor. Subject and issuer must remain valid for the
51 * lifetime of this object (they are not refcounted).
53 OCSPRequest::OCSPRequest(
63 SecAsn1CoderCreate(&mCoder
);
70 OCSPRequest::~OCSPRequest()
74 SecAsn1CoderRelease(mCoder
);
78 const CSSM_DATA
*OCSPRequest::encode()
80 /* fields obtained from issuer */
81 CSSM_DATA_PTR issuerName
;
82 CSSM_DATA_PTR issuerKey
;
83 CSSM_KEY_PTR issuerPubKey
;
84 CSSM_DATA issuerPubKeyBytes
;
86 CSSM_DATA_PTR subjectSerial
=NULL
;
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
;
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
};
109 * One single request, no extensions
111 memset(&singleReq
, 0, sizeof(singleReq
));
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
);
118 /* gather fields from two certs */
119 crtn
= mSubject
.fetchField(&CSSMOID_X509V1IssuerNameStd
, &issuerName
);
121 CssmError::throwMe(crtn
);
123 crtn
= mIssuer
.fetchField(&CSSMOID_CSSMKeyStruct
, &issuerKey
);
127 crtn
= mSubject
.fetchField(&CSSMOID_X509V1SerialNumber
, &subjectSerial
);
132 /* SHA1(issuerName) */
133 ocspdSha1(issuerName
->Data
, (CC_LONG
)issuerName
->Length
, issuerNameHash
);
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
;
141 issuerPubKey
= (CSSM_KEY_PTR
)issuerKey
->Data
;
142 ocspdGetPublicKeyBytes(mCoder
, issuerPubKey
, issuerPubKeyBytes
);
143 ocspdSha1(issuerPubKeyBytes
.Data
, (CC_LONG
)issuerPubKeyBytes
.Length
, pubKeyHash
);
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
;
149 certId
.issuerPubKeyHash
.Length
= CC_SHA1_DIGEST_LENGTH
;
150 certId
.serialNumber
= *subjectSerial
;
153 * Build top level request with one entry in requestList, no signature,
154 * one optional extension (a nonce)
156 memset(&signedReq
, 0, sizeof(signedReq
));
158 tbs
.requestList
= reqArray
;
160 /* one extension - the nonce */
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
);
171 if(SecAsn1EncodeItem(mCoder
, &signedReq
, kSecAsn1OCSPSignedRequestTemplate
,
173 tpErrorLog("OCSPRequest::encode: error encoding OCSP req\n");
174 crtn
= CSSMERR_TP_INTERNAL_ERROR
;
177 /* save a copy of the CertID */
178 mCertID
= new OCSPClientCertID(*issuerName
, issuerPubKeyBytes
, *subjectSerial
);
182 mIssuer
.freeField(&CSSMOID_X509V1IssuerNameStd
, issuerName
);
185 mIssuer
.freeField(&CSSMOID_CSSMKeyStruct
, issuerKey
);
188 mSubject
.freeField(&CSSMOID_X509V1SerialNumber
, subjectSerial
);
194 CssmError::throwMe(crtn
);
199 const CSSM_DATA
*OCSPRequest::nonce()
201 /* not legal before encode() called */
202 assert(mEncoded
.Data
!= NULL
);
211 OCSPClientCertID
*OCSPRequest::certID()