2 * Copyright (c) 2008-2009,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 * SecOCSPRequest.c - Trust policies dealing with certificate revocation.
28 #include "trust/trustd/SecOCSPRequest.h"
29 #include <Security/SecCertificateInternal.h>
30 #include <AssertMacros.h>
31 #include <utilities/debugging.h>
32 #include <security_asn1/SecAsn1Coder.h>
33 #include <security_asn1/ocspTemplates.h>
34 #include <security_asn1/oidsalg.h>
35 #include <CommonCrypto/CommonDigest.h>
37 #include "SecInternal.h"
40 OCSPRequest ::= SEQUENCE {
41 tbsRequest TBSRequest,
42 optionalSignature [0] EXPLICIT Signature OPTIONAL }
44 TBSRequest ::= SEQUENCE {
45 version [0] EXPLICIT Version DEFAULT v1,
46 requestorName [1] EXPLICIT GeneralName OPTIONAL,
47 requestList SEQUENCE OF Request,
48 requestExtensions [2] EXPLICIT Extensions OPTIONAL }
50 Signature ::= SEQUENCE {
51 signatureAlgorithm AlgorithmIdentifier,
53 certs [0] EXPLICIT SEQUENCE OF Certificate
56 Version ::= INTEGER { v1(0) }
58 Request ::= SEQUENCE {
60 singleRequestExtensions [0] EXPLICIT Extensions OPTIONAL }
63 hashAlgorithm AlgorithmIdentifier,
64 issuerNameHash OCTET STRING, -- Hash of Issuer's DN
65 issuerKeyHash OCTET STRING, -- Hash of Issuers public key
66 serialNumber CertificateSerialNumber }
68 static CFDataRef
_SecOCSPRequestCopyDEREncoding(SecOCSPRequestRef
this) {
69 /* fields obtained from issuer */
70 SecAsn1OCSPSignedRequest signedReq
= {};
71 SecAsn1OCSPTbsRequest
*tbs
= &signedReq
.tbsRequest
;
72 SecAsn1OCSPRequest singleReq
= {};
73 SecAsn1OCSPCertID
*certId
= &singleReq
.reqCert
;
74 SecAsn1OCSPRequest
*reqArray
[2] = { &singleReq
, NULL
};
76 SecAsn1Item vers
= {1, &version
};
78 SecAsn1CoderRef coder
= NULL
;
79 CFDataRef issuerNameDigest
;
81 CFDataRef issuerPubKeyDigest
;
84 /* algId refers to the hash we'll perform in issuer name and key */
85 certId
->algId
.algorithm
= CSSMOID_SHA1
;
86 /* preencoded DER NULL */
87 static uint8_t nullParam
[2] = {5, 0};
88 certId
->algId
.parameters
.Data
= nullParam
;
89 certId
->algId
.parameters
.Length
= sizeof(nullParam
);
91 /* @@@ Change this from using SecCertificateCopyIssuerSHA1Digest() /
92 SecCertificateCopyPublicKeySHA1Digest() to
93 SecCertificateCopyIssuerSequence() / SecCertificateGetPublicKeyData()
94 and call SecDigestCreate here instead. */
95 issuerNameDigest
= SecCertificateCopyIssuerSHA1Digest(this->certificate
);
96 issuerPubKeyDigest
= SecCertificateCopyPublicKeySHA1Digest(this->issuer
);
97 serial
= SecCertificateCopySerialNumberData(this->certificate
, NULL
);
99 /* build the CertID from those components */
100 certId
->issuerNameHash
.Length
= CC_SHA1_DIGEST_LENGTH
;
101 certId
->issuerNameHash
.Data
= (uint8_t *)CFDataGetBytePtr(issuerNameDigest
);
102 certId
->issuerPubKeyHash
.Length
= CC_SHA1_DIGEST_LENGTH
;
103 certId
->issuerPubKeyHash
.Data
= (uint8_t *)CFDataGetBytePtr(issuerPubKeyDigest
);
104 certId
->serialNumber
.Length
= CFDataGetLength(serial
);
105 certId
->serialNumber
.Data
= (uint8_t *)CFDataGetBytePtr(serial
);
107 /* Build top level request with one entry in requestList, no signature,
108 and no optional extensions. */
109 tbs
->version
= &vers
;
110 tbs
->requestList
= reqArray
;
112 /* Encode the request. */
113 require_noerr(SecAsn1CoderCreate(&coder
), errOut
);
115 require_noerr(SecAsn1EncodeItem(coder
, &signedReq
,
116 kSecAsn1OCSPSignedRequestTemplate
, &encoded
), errOut
);
117 der
= CFDataCreate(kCFAllocatorDefault
, encoded
.Data
,
122 SecAsn1CoderRelease(coder
);
123 CFReleaseSafe(issuerNameDigest
);
124 CFReleaseSafe(serial
);
125 CFReleaseSafe(issuerPubKeyDigest
);
130 SecOCSPRequestRef
SecOCSPRequestCreate(SecCertificateRef certificate
,
131 SecCertificateRef issuer
) {
132 SecOCSPRequestRef
this;
133 require(this = (SecOCSPRequestRef
)calloc(1, sizeof(struct __SecOCSPRequest
)),
135 this->certificate
= certificate
;
136 this->issuer
= issuer
;
141 SecOCSPRequestFinalize(this);
146 CFDataRef
SecOCSPRequestGetDER(SecOCSPRequestRef
this) {
147 if (!this) { return NULL
; }
148 CFDataRef der
= this->der
;
150 this->der
= der
= _SecOCSPRequestCopyDEREncoding(this);
155 void SecOCSPRequestFinalize(SecOCSPRequestRef
this) {
156 CFReleaseSafe(this->der
);