|
1 // Copyright (c) 2003-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
2 // All rights reserved. |
|
3 // This component and the accompanying materials are made available |
|
4 // under the terms of "Eclipse Public License v1.0" |
|
5 // which accompanies this distribution, and is available |
|
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // Implementation for OCSP request encoder object |
|
15 // |
|
16 // |
|
17 |
|
18 #include "requestencoder.h" |
|
19 #include "certid.h" |
|
20 #include "oids.h" |
|
21 #include "ocsp.h" |
|
22 #include "panic.h" |
|
23 #include <asn1enc.h> |
|
24 |
|
25 COCSPRequestEncoder* COCSPRequestEncoder::NewL(const COCSPRequest& aRequest) |
|
26 { |
|
27 COCSPRequestEncoder* self = new (ELeave) COCSPRequestEncoder(); |
|
28 CleanupStack::PushL(self); |
|
29 self->ConstructL(aRequest); |
|
30 CleanupStack::Pop(self); |
|
31 return self; |
|
32 } |
|
33 |
|
34 |
|
35 COCSPRequestEncoder::COCSPRequestEncoder() |
|
36 { |
|
37 } |
|
38 |
|
39 |
|
40 COCSPRequestEncoder::~COCSPRequestEncoder() |
|
41 { |
|
42 delete iEncoding; |
|
43 } |
|
44 |
|
45 |
|
46 const TDesC8& COCSPRequestEncoder::Encoding() const |
|
47 { |
|
48 return *iEncoding; |
|
49 } |
|
50 |
|
51 |
|
52 void COCSPRequestEncoder::ConstructL(const COCSPRequest& aRequest) |
|
53 { |
|
54 // Get encoder |
|
55 CASN1EncBase* encoder = MakeOCSPRequestEncLC(aRequest); |
|
56 |
|
57 // Make buffer |
|
58 TUint length = encoder->LengthDER(); |
|
59 iEncoding = HBufC8::NewMaxL(length); |
|
60 TPtr8 buf = iEncoding->Des(); |
|
61 |
|
62 // Write data |
|
63 TUint position = 0; |
|
64 encoder->WriteDERL(buf, position); |
|
65 |
|
66 CleanupStack::PopAndDestroy(encoder); |
|
67 } |
|
68 |
|
69 |
|
70 // Static helper method - encapsulates a commonly-dupliciated peice of code |
|
71 void COCSPRequestEncoder::AddAndPopChildL(CASN1EncContainer& aParent, CASN1EncBase* aChild) |
|
72 { |
|
73 if (aChild) |
|
74 { |
|
75 aParent.AddChildL(aChild); |
|
76 CleanupStack::Pop(aChild); // Now owned by aParent |
|
77 } |
|
78 } |
|
79 |
|
80 |
|
81 CASN1EncBase* COCSPRequestEncoder::MakeOCSPRequestEncLC(const COCSPRequest& aRequest) |
|
82 { |
|
83 CASN1EncSequence* ocspRequest = CASN1EncSequence::NewLC(); |
|
84 |
|
85 CASN1EncBase* tbsRequest = MakeTBSRequestEncLC(aRequest); |
|
86 AddAndPopChildL(*ocspRequest, tbsRequest); |
|
87 |
|
88 return ocspRequest; |
|
89 } |
|
90 |
|
91 |
|
92 CASN1EncBase* COCSPRequestEncoder::MakeTBSRequestEncLC(const COCSPRequest& aRequest) |
|
93 { |
|
94 CASN1EncSequence* tbsRequest = CASN1EncSequence::NewLC(); |
|
95 |
|
96 // version - int 0, explicitly tagged as 0 |
|
97 // Excluded, since this is the default value, and we're using DER |
|
98 |
|
99 // Skip GeneralName - we don't support that, and it is optional |
|
100 |
|
101 // Cert requestList |
|
102 CASN1EncBase* requestList = MakeRequestListEncLC(aRequest); |
|
103 AddAndPopChildL(*tbsRequest, requestList); |
|
104 |
|
105 // Global request extensions - optional, explicitly tagged [2] |
|
106 CASN1EncBase* extensions = MakeRequestExtensionsEncLC(aRequest); |
|
107 if (extensions) |
|
108 { |
|
109 CleanupStack::Pop(extensions); // Will be owned by explicit tag |
|
110 CASN1EncExplicitTag* taggedExtensions = CASN1EncExplicitTag::NewLC(extensions, 2); |
|
111 AddAndPopChildL(*tbsRequest, taggedExtensions); |
|
112 } |
|
113 |
|
114 return tbsRequest; |
|
115 } |
|
116 |
|
117 |
|
118 CASN1EncBase* COCSPRequestEncoder::MakeRequestListEncLC(const COCSPRequest& aRequest) |
|
119 { |
|
120 CASN1EncSequence* requestList = CASN1EncSequence::NewLC(); |
|
121 |
|
122 // Request objects - one for each cert |
|
123 TUint numCerts = aRequest.CertCount(); |
|
124 ASSERT(numCerts > 0); |
|
125 |
|
126 for (TUint index = 0; index < numCerts; ++index) |
|
127 { |
|
128 const COCSPCertID& certId = aRequest.CertInfo(index).CertID(); |
|
129 CASN1EncBase* certEnc = MakeCertRequestEncLC(certId); |
|
130 AddAndPopChildL(*requestList, certEnc); |
|
131 } |
|
132 |
|
133 return requestList; |
|
134 } |
|
135 |
|
136 |
|
137 // Make encoder for the request object for a particular cert |
|
138 CASN1EncBase* COCSPRequestEncoder::MakeCertRequestEncLC(const COCSPCertID& aCertId) |
|
139 { |
|
140 CASN1EncSequence* request = CASN1EncSequence::NewLC(); |
|
141 |
|
142 // CertID |
|
143 CASN1EncBase* certIdEnc = aCertId.EncoderLC(); |
|
144 AddAndPopChildL(*request, certIdEnc); |
|
145 |
|
146 return request; |
|
147 } |
|
148 |
|
149 |
|
150 CASN1EncBase* COCSPRequestEncoder::MakeRequestExtensionsEncLC(const COCSPRequest& aRequest) |
|
151 { |
|
152 CASN1EncSequence* extns = CASN1EncSequence::NewLC(); |
|
153 |
|
154 // Nonce extension (if present) |
|
155 CASN1EncBase* nonceExtn = MakeNonceExtnEncLC(aRequest); |
|
156 AddAndPopChildL(*extns, nonceExtn); |
|
157 |
|
158 // Response type extentions |
|
159 CASN1EncBase* responseTypeExtn = MakeResponseTypeExtnEncLC(); |
|
160 AddAndPopChildL(*extns, responseTypeExtn); |
|
161 |
|
162 return extns; |
|
163 } |
|
164 |
|
165 |
|
166 // Response type. Is a sequence, with OID, default bool, and octet string |
|
167 // for contents. In this case the octet string contains a sequence |
|
168 // of OIDs specifying the acceptable response types. |
|
169 CASN1EncBase* COCSPRequestEncoder::MakeResponseTypeExtnEncLC() |
|
170 { |
|
171 CASN1EncSequence* extn = CASN1EncSequence::NewLC(); |
|
172 |
|
173 // OID |
|
174 CASN1EncObjectIdentifier* oid = CASN1EncObjectIdentifier::NewLC(KOCSPOidResponse); |
|
175 AddAndPopChildL(*extn, oid); |
|
176 |
|
177 // Skip Critical flag since we want default value FALSE and this is DER |
|
178 |
|
179 // Acceptable responses - takes a bit of work, so bear with it... |
|
180 |
|
181 // First, make sequence containing the OID for our response type |
|
182 CASN1EncSequence* responses = CASN1EncSequence::NewLC(); |
|
183 CASN1EncObjectIdentifier* basic = CASN1EncObjectIdentifier::NewLC(KOCSPOidBasic); |
|
184 AddAndPopChildL(*responses, basic); |
|
185 |
|
186 // Second, encode this into a descriptor |
|
187 TBuf8<KOCSPMaxOidEncodingLength> buf(responses->LengthDER()); |
|
188 TUint pos = 0; |
|
189 responses->WriteDERL(buf, pos); |
|
190 CleanupStack::PopAndDestroy(responses); // Finished with that now |
|
191 |
|
192 // Third, make Octet string encoder from this data + add to extn |
|
193 CASN1EncOctetString* value = CASN1EncOctetString::NewLC(buf); |
|
194 AddAndPopChildL(*extn, value); |
|
195 |
|
196 return extn; |
|
197 } |
|
198 |
|
199 |
|
200 CASN1EncBase* COCSPRequestEncoder::MakeNonceExtnEncLC(const COCSPRequest& aRequest) |
|
201 { |
|
202 CASN1EncSequence* extn = NULL; |
|
203 |
|
204 if (aRequest.Nonce()) |
|
205 { |
|
206 extn = CASN1EncSequence::NewLC(); |
|
207 |
|
208 // OID |
|
209 CASN1EncObjectIdentifier* oid = CASN1EncObjectIdentifier::NewLC(KOCSPOidNonce); |
|
210 AddAndPopChildL(*extn, oid); |
|
211 |
|
212 // Skip Critical flag since we want default value FALSE and this is DER |
|
213 |
|
214 // Place nonce into extension |
|
215 CASN1EncOctetString* value = CASN1EncOctetString::NewLC(*aRequest.Nonce()); |
|
216 AddAndPopChildL(*extn, value); |
|
217 } |
|
218 |
|
219 return extn; |
|
220 } |