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