|
1 /* |
|
2 * Copyright (c) 2003 - 2007 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: Pkcs10 certificate request. |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 |
|
20 #include <eikenv.h> |
|
21 #include <asn1cons.h> |
|
22 #include <asn1enc.h> |
|
23 #include <x520ava.h> |
|
24 |
|
25 #include "pkcs10.h" |
|
26 #include "base64.h" |
|
27 #include "pkidefs.h" |
|
28 #include "utlcrypto.h" |
|
29 |
|
30 ////////////////////////////////////////////////////////////////////////////// |
|
31 // Destructor |
|
32 ////////////////////////////////////////////////////////////////////////////// |
|
33 EXPORT_C CPkcs10Req::~CPkcs10Req() |
|
34 { |
|
35 delete iDNDerBuf; |
|
36 } |
|
37 |
|
38 ////////////////////////////////////////////////////////////////////////////// |
|
39 // Set distinguished name parameter, Only CommonName given |
|
40 ////////////////////////////////////////////////////////////////////////////// |
|
41 EXPORT_C TInt CPkcs10Req::SetDistinguishedName(const TDesC8 &aDistinguishedName) |
|
42 { |
|
43 TInt status = KErrNone; |
|
44 |
|
45 // Set distiguished name |
|
46 if(aDistinguishedName.Length() > 0) |
|
47 { |
|
48 iDistinguishedName.Set(aDistinguishedName); |
|
49 iUseExtendedDistinguishedName = EFalse; |
|
50 } |
|
51 else |
|
52 status = KErrArgument; |
|
53 |
|
54 return (status); |
|
55 } |
|
56 |
|
57 ////////////////////////////////////////////////////////////////////////////// |
|
58 // SetDistinguishedNameExtended |
|
59 ////////////////////////////////////////////////////////////////////////////// |
|
60 // Set distinguished name parameter. Complete distinguished name in format |
|
61 // CN=xxx,O=abc,OU=def or CN=xxx/O=abc/OU=def |
|
62 // OIds and corresponding texts (case insensitive): |
|
63 // KX520CountryName "2.5.4.6" "c" {0x55, 0x04, 0x06} |
|
64 // KX520OrganizationName "2.5.4.10" "o" {0x55, 0x04, 0x0a} |
|
65 // KX520OrganizationalUnitName "2.5.4.11" "ou" {0x55, 0x04, 0x0b} |
|
66 // KX520LocalityName "2.5.4.7" "l" {0x55, 0x04, 0x07} |
|
67 // KX520StateOrProvinceName "2.5.4.8" "st" {0x55, 0x04, 0x08} |
|
68 // KX520Title "2.5.4.12" "title" {0x55, 0x04, 0x0c} |
|
69 // KX520CommonName "2.5.4.3" "cn" {0x55, 0x04, 0x03} |
|
70 // KX520GivenName "2.5.4.42" "GivenName" {0x55, 0x04, 0x2a} |
|
71 // KX520Surname "2.5.4.4" "sn" {0x55, 0x04, 0x04} |
|
72 // KX520Initials "2.5.4.43" "initials" {0x55, 0x04, 0x2b} |
|
73 // KX520GenerationQualifier "2.5.4.44" "generationQualifier" {0x55, 0x04, 0x2c} |
|
74 // KX520DNQualifier "2.5.4.46" "dnQualifier" {0x55, 0x04, 0x2e} |
|
75 // KX520SerialNumber "2.5.4.5" "serialNumber" {0x55, 0x04, 0x05} |
|
76 //////////////////////////////////////////////////////////////////////////////////////// |
|
77 EXPORT_C TInt CPkcs10Req::SetDistinguishedNameExtendedL(const TDesC8 &aDistinguishedName) |
|
78 { |
|
79 TInt status = KErrNone; |
|
80 |
|
81 // Set distiguished name |
|
82 if(aDistinguishedName.Length() > 0) |
|
83 { |
|
84 delete iDNDerBuf; // delete possible old buffer |
|
85 iDNDerBuf = NULL; |
|
86 TRAPD(status, BuildDistinguishedNameDerFromTextL(iDNDerBuf, aDistinguishedName, EFalse, KCountryName())); |
|
87 if(status == KErrNone) |
|
88 { |
|
89 iUseExtendedDistinguishedName = ETrue; |
|
90 } |
|
91 } |
|
92 else |
|
93 status = KErrArgument; |
|
94 |
|
95 return (status); |
|
96 } |
|
97 |
|
98 ////////////////////////////////////////////////////////////////////////////// |
|
99 // BuildDistinguishedNameDerFromText |
|
100 ////////////////////////////////////////////////////////////////////////////// |
|
101 EXPORT_C void CPkcs10Req::BuildDistinguishedNameDerFromTextL( |
|
102 HBufC8 *&derBuffer, |
|
103 const TDesC8 &aDistinguishedName, |
|
104 TBool aByPass, |
|
105 const TDesC8 &aByPassType |
|
106 ) |
|
107 { |
|
108 HBufC8 *shrinkedBuffer; |
|
109 |
|
110 CArrayFixFlat<TIndexPair> *valueIndexArray = |
|
111 new (ELeave) CArrayFixFlat<TIndexPair>(1); |
|
112 |
|
113 CleanupStack::PushL(valueIndexArray); |
|
114 |
|
115 CArrayFixFlat<TIndexPair> *typeIndexArray = |
|
116 new (ELeave) CArrayFixFlat<TIndexPair>(1); |
|
117 |
|
118 CleanupStack::PushL(typeIndexArray); |
|
119 |
|
120 CArrayFixFlat<TPtr8> *valuePtrArray = |
|
121 new (ELeave) CArrayFixFlat<TPtr8>(1); |
|
122 |
|
123 CleanupStack::PushL(valuePtrArray); |
|
124 |
|
125 CArrayFixFlat<TPtr8> *typePtrArray = |
|
126 new (ELeave) CArrayFixFlat<TPtr8>(1); |
|
127 |
|
128 CleanupStack::PushL(typePtrArray); |
|
129 |
|
130 // Scan input and build index arrays for types and values |
|
131 CPkcs10Req::BuildIndexPairsLC( |
|
132 shrinkedBuffer, |
|
133 aDistinguishedName, |
|
134 typeIndexArray, |
|
135 valueIndexArray |
|
136 ); |
|
137 |
|
138 CPkcs10Req::BuildDerL( |
|
139 shrinkedBuffer, |
|
140 derBuffer, |
|
141 typeIndexArray, |
|
142 valueIndexArray, |
|
143 typePtrArray, |
|
144 valuePtrArray, |
|
145 aByPass, |
|
146 aByPassType |
|
147 ); |
|
148 |
|
149 CleanupStack::PopAndDestroy(5); |
|
150 } |
|
151 |
|
152 ////////////////////////////////////////////////////////////////////////////// |
|
153 // AttributeTypeOidToText |
|
154 ////////////////////////////////////////////////////////////////////////////// |
|
155 EXPORT_C TPtrC8 CPkcs10Req::AttributeTypeOidToText(const TDesC &aType) |
|
156 { |
|
157 TPtrC8 temp; |
|
158 |
|
159 if(aType.Compare(KX520CountryName) == 0) |
|
160 temp.Set(KCountryName); |
|
161 else if(aType.Compare(KX520OrganizationName) == 0) |
|
162 temp.Set(KOrganizationName); |
|
163 else if(aType.Compare(KX520OrganizationalUnitName) == 0) |
|
164 temp.Set(KOrganizationalUnitName); |
|
165 else if(aType.Compare(KX520LocalityName) == 0) |
|
166 temp.Set(KLocalityName); |
|
167 else if(aType.Compare(KX520StateOrProvinceName) == 0) |
|
168 temp.Set(KStateOrProvinceName); |
|
169 else if(aType.Compare(KX520Title) == 0) |
|
170 temp.Set(KTitle); |
|
171 else if(aType.Compare(KX520CommonName) == 0) |
|
172 temp.Set(KCommonName); |
|
173 else if(aType.Compare(KX520GivenName) == 0) |
|
174 temp.Set(KGivenName); |
|
175 else if(aType.Compare(KX520Surname) == 0) |
|
176 temp.Set(KSurname); |
|
177 else if(aType.Compare(KX520Initials) == 0) |
|
178 temp.Set(KInitials); |
|
179 else if(aType.Compare(KX520GenerationQualifier) == 0) |
|
180 temp.Set(KGenerationQualifier); |
|
181 else if(aType.Compare(KX520DNQualifier) == 0) |
|
182 temp.Set(KDNQualifier); |
|
183 else if(aType.Compare(KX520SerialNumber) == 0) |
|
184 temp.Set(KSerialNumber); |
|
185 else if(aType.Compare(KRFC2247DomainComponent) == 0) |
|
186 temp.Set(KDomainComponent); |
|
187 else |
|
188 { |
|
189 // Return dotted oid, length = 0 |
|
190 } |
|
191 |
|
192 return temp; |
|
193 } |
|
194 |
|
195 ////////////////////////////////////////////////////////////////////////////// |
|
196 // BuildIndexPairsLC |
|
197 ////////////////////////////////////////////////////////////////////////////// |
|
198 void CPkcs10Req::BuildIndexPairsLC( |
|
199 HBufC8 *&buffer, |
|
200 const TDesC8 &aDistinguishedName, |
|
201 CArrayFixFlat<TIndexPair> *aTypePairArray, |
|
202 CArrayFixFlat<TIndexPair> *aValuePairArray |
|
203 ) |
|
204 { |
|
205 // Some rules: |
|
206 // 1) Separator: ',' |
|
207 // 2) Escape character '\' |
|
208 // 3) Value may be quoted. Then separator in value is allowed |
|
209 // (without preceding escape char) |
|
210 |
|
211 HBufC8 *sourceBuffer; |
|
212 HBufC8 *targetBuffer; |
|
213 TUint i, j; |
|
214 targetBuffer = HBufC8::NewLC(aDistinguishedName.Length()); |
|
215 targetBuffer->Des().SetLength(aDistinguishedName.Length()); |
|
216 sourceBuffer = HBufC8::NewLC(aDistinguishedName.Length()); |
|
217 sourceBuffer->Des().Copy(aDistinguishedName); |
|
218 TPtr8 sourcePointer = sourceBuffer->Des(); |
|
219 TPtr8 targetPointer = targetBuffer->Des(); |
|
220 TBool insideQuotes = EFalse; |
|
221 TIndexPair pair; |
|
222 TUint elementStartPosition = 0; |
|
223 TUint elementEndPosition = 0; |
|
224 |
|
225 // Delete leading and trailing spaces |
|
226 sourcePointer.Trim(); |
|
227 |
|
228 // Scan text in order to collect name value pairs |
|
229 for(i = 0, j = 0; (TInt)i < sourcePointer.Length(); i++) |
|
230 { |
|
231 if(sourcePointer[i] == '"') |
|
232 { |
|
233 // Toggle quote state |
|
234 // Don't ignore quotes in order to ease trimming. |
|
235 // (Spaces inside quotes are meaningful) |
|
236 insideQuotes = !insideQuotes; |
|
237 targetPointer[j] = sourcePointer[i]; |
|
238 j++; |
|
239 continue; |
|
240 } |
|
241 |
|
242 if(insideQuotes) |
|
243 { |
|
244 // Allow any character |
|
245 // Check for escape |
|
246 if(sourcePointer[i] == '\\') |
|
247 { |
|
248 if((TInt)i < sourcePointer.Length() - 1) |
|
249 { |
|
250 targetPointer[j] = sourcePointer[i + 1]; |
|
251 j++; |
|
252 i++; // skip char |
|
253 } |
|
254 else |
|
255 User::Leave(KErrArgument); |
|
256 } |
|
257 else |
|
258 { |
|
259 targetPointer[j] = sourcePointer[i]; |
|
260 j++; |
|
261 } |
|
262 continue; |
|
263 } |
|
264 |
|
265 // Check for escape |
|
266 if(sourcePointer[i] == '\\') |
|
267 { |
|
268 if((TInt)i < sourcePointer.Length() - 1) |
|
269 { |
|
270 targetPointer[j] = sourcePointer[i + 1]; |
|
271 j++; |
|
272 i++; // skip char |
|
273 } |
|
274 else |
|
275 User::Leave(KErrArgument); |
|
276 |
|
277 continue; |
|
278 } |
|
279 |
|
280 // Check for pair separator |
|
281 if(sourcePointer[i] == ',') |
|
282 { |
|
283 // End of type/value pair |
|
284 elementEndPosition = j; |
|
285 pair.startIndex = elementStartPosition; |
|
286 pair.endIndex = elementEndPosition; |
|
287 aValuePairArray->AppendL(pair); |
|
288 elementStartPosition = j; |
|
289 } |
|
290 // Check for type/value separator |
|
291 else if(sourcePointer[i] == '=') |
|
292 { |
|
293 elementEndPosition = j; |
|
294 pair.startIndex = elementStartPosition; |
|
295 pair.endIndex = elementEndPosition; |
|
296 aTypePairArray->AppendL(pair); |
|
297 elementStartPosition = j; |
|
298 } |
|
299 else |
|
300 { |
|
301 // Plain copy |
|
302 targetPointer[j] = sourcePointer[i]; |
|
303 j++; |
|
304 } |
|
305 } |
|
306 |
|
307 // Append final value |
|
308 elementEndPosition = j; |
|
309 pair.startIndex = elementStartPosition; |
|
310 pair.endIndex = elementEndPosition; |
|
311 aValuePairArray->AppendL(pair); |
|
312 |
|
313 // Ensure we have consistent type/value pairs |
|
314 if(aTypePairArray->Count() != aValuePairArray->Count()) |
|
315 { |
|
316 User::Leave(KErrArgument); |
|
317 } |
|
318 |
|
319 CleanupStack::PopAndDestroy(1); // source |
|
320 // Return allocated shrinked buffer and OK status |
|
321 targetBuffer->Des().SetLength(j); |
|
322 buffer = targetBuffer; |
|
323 } |
|
324 |
|
325 ////////////////////////////////////////////////////////////////////////////// |
|
326 // BuildDerLC |
|
327 ////////////////////////////////////////////////////////////////////////////// |
|
328 void CPkcs10Req::BuildDerL( |
|
329 HBufC8 *aSource, |
|
330 HBufC8 *&derBuffer, |
|
331 CArrayFixFlat<TIndexPair> *aTypeIndexArray, |
|
332 CArrayFixFlat<TIndexPair> *aValueIndexArray, |
|
333 CArrayFixFlat<TPtr8> *aTypePtrArray, |
|
334 CArrayFixFlat<TPtr8> *aValuePtrArray, |
|
335 TBool aByPass, |
|
336 const TDesC8 &aByPassType |
|
337 ) |
|
338 { |
|
339 TUint i; |
|
340 // trim types and values and count required der length |
|
341 TUint elementLength = 0; |
|
342 TUint totalLength = 0; |
|
343 TUint wholeLength = 0; |
|
344 TUint setLength = 0; |
|
345 TUint seqLength = 0; |
|
346 TUint oidLength = COMMON_NAME_OID_LTH; |
|
347 TUint stringLength = 0; |
|
348 TUint contentLength = 0; |
|
349 TUint oidIndex = 0; |
|
350 TBuf8<32> dottedOidDer; |
|
351 |
|
352 CArrayFixFlat<HBufC8 *> *elementArray = |
|
353 new (ELeave) CArrayFixFlat<HBufC8 *>(1); |
|
354 |
|
355 CleanupStack::PushL(elementArray); |
|
356 |
|
357 for(i = 0; (TInt)i < aTypeIndexArray->Count(); i++) // counts are equal |
|
358 { |
|
359 TPtr8 tempPtr( |
|
360 CONST_CAST(TUint8*, aSource->Des().Ptr()) + aTypeIndexArray->At(i).startIndex, |
|
361 aTypeIndexArray->At(i).endIndex - aTypeIndexArray->At(i).startIndex |
|
362 ); |
|
363 |
|
364 tempPtr.SetLength( |
|
365 aTypeIndexArray->At(i).endIndex - aTypeIndexArray->At(i).startIndex |
|
366 ); |
|
367 |
|
368 aTypePtrArray->AppendL(tempPtr); |
|
369 |
|
370 tempPtr.Set( |
|
371 CONST_CAST(TUint8*, aSource->Des().Ptr()) + aValueIndexArray->At(i).startIndex, |
|
372 aValueIndexArray->At(i).endIndex - aValueIndexArray->At(i).startIndex, |
|
373 aValueIndexArray->At(i).endIndex - aValueIndexArray->At(i).startIndex |
|
374 ); |
|
375 |
|
376 tempPtr.SetLength(aValueIndexArray->At(i).endIndex - aValueIndexArray->At(i).startIndex); |
|
377 |
|
378 tempPtr.Trim(); |
|
379 |
|
380 if(0 == tempPtr.Length()) |
|
381 { |
|
382 User::Leave(KErrArgument); |
|
383 } |
|
384 |
|
385 // Remove quotes. Spaces inside quotes are meaningful, |
|
386 // so Trim must be called before this operation |
|
387 if(tempPtr[0] == '"') |
|
388 { |
|
389 if(tempPtr[tempPtr.Length() -1 ] != '"') |
|
390 { |
|
391 User::Leave(KErrArgument); |
|
392 } |
|
393 else |
|
394 { |
|
395 TInt tempLength = tempPtr.Length() - 2; |
|
396 tempPtr.Set(CONST_CAST(TUint8*, tempPtr.Ptr() + 1), tempLength, tempLength); |
|
397 tempPtr.SetLength(tempLength); |
|
398 } |
|
399 } |
|
400 |
|
401 if(0 == tempPtr.Length()) |
|
402 { |
|
403 User::Leave(KErrArgument); |
|
404 } |
|
405 |
|
406 aValuePtrArray->AppendL(tempPtr); |
|
407 |
|
408 aTypePtrArray->At(i).Trim(); |
|
409 aTypePtrArray->At(i).UpperCase(); |
|
410 |
|
411 // Check if type is supported, it is ignored if not |
|
412 if(CPkcs10Req::OidExistsL(aTypePtrArray->At(i), oidIndex, dottedOidDer)) |
|
413 { |
|
414 if(KNullAttributeIndex == oidIndex) |
|
415 { |
|
416 oidLength = dottedOidDer.Length() - ASN1_SHORT_TAG_HDR_LTH; |
|
417 } |
|
418 else if(KDomainComponentIndex == oidIndex) |
|
419 { |
|
420 oidLength = DC_OID_LTH; |
|
421 } |
|
422 else |
|
423 { |
|
424 oidLength = COMMON_NAME_OID_LTH; |
|
425 } |
|
426 |
|
427 if(!(aByPass && aTypePtrArray->At(i).Compare(aByPassType) == 0)) |
|
428 { |
|
429 // Printable string |
|
430 elementLength = aValuePtrArray->At(i).Length(); |
|
431 stringLength = elementLength; |
|
432 if(elementLength > 127) |
|
433 elementLength++; |
|
434 if(elementLength > 255) |
|
435 elementLength++; |
|
436 elementLength += ASN1_SHORT_TAG_HDR_LTH; |
|
437 |
|
438 elementLength += oidLength; // Oid |
|
439 elementLength += ASN1_SHORT_TAG_HDR_LTH; |
|
440 seqLength = elementLength; |
|
441 if(elementLength > 127) |
|
442 elementLength++; |
|
443 if(elementLength > 255) |
|
444 elementLength++; |
|
445 elementLength += ASN1_SHORT_TAG_HDR_LTH; // Sequence |
|
446 setLength = elementLength; |
|
447 if(elementLength > 127) |
|
448 elementLength++; |
|
449 if(elementLength > 255) |
|
450 elementLength++; |
|
451 elementLength += ASN1_SHORT_TAG_HDR_LTH; // Set |
|
452 wholeLength = elementLength; |
|
453 |
|
454 // Build one element |
|
455 CPkcs10Req::BuildElementDerLC( |
|
456 elementArray, |
|
457 wholeLength, |
|
458 setLength, |
|
459 seqLength, |
|
460 oidLength, |
|
461 stringLength, |
|
462 oidIndex, |
|
463 dottedOidDer, |
|
464 aValuePtrArray->At(i) |
|
465 ); |
|
466 |
|
467 totalLength += elementLength; |
|
468 } |
|
469 } |
|
470 } |
|
471 |
|
472 if( 0 == totalLength ) |
|
473 { |
|
474 User::Leave(KErrArgument); |
|
475 } |
|
476 |
|
477 contentLength = totalLength; |
|
478 if(totalLength > 127) // Sequence |
|
479 totalLength++; |
|
480 if(totalLength > 255) |
|
481 totalLength++; |
|
482 |
|
483 totalLength += ASN1_SHORT_TAG_HDR_LTH; |
|
484 |
|
485 // Allocate buffer |
|
486 derBuffer = HBufC8::NewL(totalLength); |
|
487 derBuffer->Des().SetLength(totalLength); |
|
488 TUint8 *derBufferPtr = (TUint8 *)derBuffer->Ptr(); |
|
489 derBufferPtr+= CPkcs10Req::DERSetTag(derBufferPtr, (EASN1Sequence | ASN1_CONSTRUCTED)); |
|
490 derBufferPtr+= CPkcs10Req::DERSetLength(derBufferPtr, contentLength); |
|
491 |
|
492 for(i = 0; (TInt)i < elementArray->Count(); i++) |
|
493 { |
|
494 derBufferPtr+= CPkcs10Req::ASNCopy( |
|
495 derBufferPtr, |
|
496 CONST_CAST(unsigned char *, elementArray->At(i)->Des().Ptr()), |
|
497 elementArray->At(i)->Length() |
|
498 ); |
|
499 } |
|
500 |
|
501 CleanupStack::PopAndDestroy(elementArray->Count()); |
|
502 CleanupStack::PopAndDestroy(elementArray); |
|
503 } |
|
504 |
|
505 ////////////////////////////////////////////////////////////////////////////// |
|
506 // OidExistsLC |
|
507 /////////////////////////////////////////////////////////////////////////////// |
|
508 TBool CPkcs10Req::OidExistsL( |
|
509 TPtr8 &aTypePtrArray, |
|
510 TUint &aIndex, |
|
511 TBuf8<32> &aDottedOidDer |
|
512 ) |
|
513 { |
|
514 TBool validOId = EFalse; |
|
515 |
|
516 aIndex = KNullAttributeIndex; |
|
517 |
|
518 if(aTypePtrArray.Compare(KCountryName) == 0) |
|
519 aIndex = KCountryNameIndex; |
|
520 else if(aTypePtrArray.Compare(KOrganizationName) == 0) |
|
521 aIndex = KOrganizationNameIndex; |
|
522 else if(aTypePtrArray.Compare(KOrganizationalUnitName) == 0) |
|
523 aIndex = KOrganizationalUnitNameIndex; |
|
524 else if(aTypePtrArray.Compare(KLocalityName) == 0) |
|
525 aIndex = KLocalityNameIndex; |
|
526 else if(aTypePtrArray.Compare(KStateOrProvinceName) == 0) |
|
527 aIndex = KStateOrProvinceNameIndex; |
|
528 else if(aTypePtrArray.Compare(KTitle) == 0) |
|
529 aIndex = KTitleIndex; |
|
530 else if(aTypePtrArray.Compare(KCommonName) == 0) |
|
531 aIndex = KCommonNameIndex; |
|
532 else if(aTypePtrArray.Compare(KGivenName) == 0) |
|
533 aIndex = KGivenNameIndex; |
|
534 else if(aTypePtrArray.Compare(KSurname) == 0) |
|
535 aIndex = KSurnameIndex; |
|
536 else if(aTypePtrArray.Compare(KInitials) == 0) |
|
537 aIndex = KInitialsIndex; |
|
538 else if(aTypePtrArray.Compare(KGenerationQualifier) == 0) |
|
539 aIndex = KGenerationQualifierIndex; |
|
540 else if(aTypePtrArray.Compare(KDNQualifier) == 0) |
|
541 aIndex = KDNQualifierIndex; |
|
542 else if(aTypePtrArray.Compare(KSerialNumber) == 0) |
|
543 aIndex = KSerialNumberIndex; |
|
544 else if(aTypePtrArray.Compare(KDomainComponent) == 0) |
|
545 aIndex = KDomainComponentIndex; |
|
546 |
|
547 if(KNullAttributeIndex != aIndex) |
|
548 { |
|
549 validOId = ETrue; |
|
550 } |
|
551 else |
|
552 { |
|
553 if(aTypePtrArray.Find(KDot) != KErrNotFound) |
|
554 { |
|
555 // Dotted oid notation |
|
556 TUint offset = 0; |
|
557 TBuf<32> tempOidBuf; |
|
558 tempOidBuf.Copy(aTypePtrArray); |
|
559 |
|
560 CASN1EncObjectIdentifier *oidIdentifier = |
|
561 CASN1EncObjectIdentifier::NewLC(tempOidBuf); |
|
562 |
|
563 // WriteDERL uses Length() instead of MaxLength() ? |
|
564 aDottedOidDer.SetLength(32); |
|
565 oidIdentifier->WriteDERL(aDottedOidDer, offset); |
|
566 aDottedOidDer.SetLength(oidIdentifier->LengthDER()); |
|
567 CleanupStack::PopAndDestroy(); // oidIdentifier |
|
568 validOId = ETrue; |
|
569 } |
|
570 } |
|
571 |
|
572 return validOId; |
|
573 } |
|
574 |
|
575 //////////////////////////////////////////////////////////////////////////////////////// |
|
576 // GetOid |
|
577 //////////////////////////////////////////////////////////////////////////////////////// |
|
578 TInt CPkcs10Req::GetOid(TUint aIndex, const TUint8 *&aValue) |
|
579 { |
|
580 switch(aIndex) |
|
581 { |
|
582 case KCountryNameIndex: |
|
583 aValue = KCountryNameOid; |
|
584 break; |
|
585 case KOrganizationNameIndex: |
|
586 aValue = KOrganizationNameOid; |
|
587 break; |
|
588 case KOrganizationalUnitNameIndex: |
|
589 aValue = KOrganizationalUnitNameOid; |
|
590 break; |
|
591 case KLocalityNameIndex: |
|
592 aValue = KLocalityNameOid; |
|
593 break; |
|
594 case KStateOrProvinceNameIndex: |
|
595 aValue = KStateOrProvinceNameOid; |
|
596 break; |
|
597 case KTitleIndex: |
|
598 aValue = KTitleOid; |
|
599 break; |
|
600 case KCommonNameIndex: |
|
601 aValue = KCommonNOid; |
|
602 break; |
|
603 case KGivenNameIndex: |
|
604 aValue = KGivenNameOid; |
|
605 break; |
|
606 case KSurnameIndex: |
|
607 aValue = KSurnameOid; |
|
608 break; |
|
609 case KInitialsIndex: |
|
610 aValue = KInitialsOid; |
|
611 break; |
|
612 case KGenerationQualifierIndex: |
|
613 aValue = KGenerationQualifierOid; |
|
614 break; |
|
615 case KDNQualifierIndex: |
|
616 aValue = KDNQualifierOid; |
|
617 break; |
|
618 case KSerialNumberIndex: |
|
619 aValue = KSerialNumberOid; |
|
620 break; |
|
621 case KDomainComponentIndex: |
|
622 aValue = KDomainComponentOid; |
|
623 break; |
|
624 default: |
|
625 return KErrArgument; |
|
626 } |
|
627 |
|
628 return KErrNone; |
|
629 } |
|
630 |
|
631 //////////////////////////////////////////////////////////////////////////////////////// |
|
632 // FillDer |
|
633 //////////////////////////////////////////////////////////////////////////////////////// |
|
634 void CPkcs10Req::BuildElementDerLC(CArrayFixFlat<HBufC8 *> *aElementArray, TUint aWholeLength, TUint aSetLength, TUint aSeqLength, TUint aOidLength, TUint aStringLength, TUint aOidIndex, TBuf8<32> &aDottedOidDer, TPtr8 &aValuePtr) |
|
635 { |
|
636 HBufC8 *elementBuffer = HBufC8::NewLC(aWholeLength); |
|
637 elementBuffer->Des().SetLength(aWholeLength); |
|
638 TUint8 *elementBufferPtr = (TUint8 *)elementBuffer->Ptr(); |
|
639 const TUint8 *oidPtr; |
|
640 |
|
641 elementBufferPtr+= CPkcs10Req::DERSetTag(elementBufferPtr, (EASN1Set | ASN1_CONSTRUCTED)); |
|
642 elementBufferPtr+= CPkcs10Req::DERSetLength(elementBufferPtr, aSetLength); |
|
643 elementBufferPtr+= CPkcs10Req::DERSetTag(elementBufferPtr, (EASN1Sequence | ASN1_CONSTRUCTED)); |
|
644 elementBufferPtr+= CPkcs10Req::DERSetLength(elementBufferPtr, aSeqLength); |
|
645 if(aOidIndex != 0) |
|
646 { |
|
647 GetOid(aOidIndex, oidPtr); |
|
648 elementBufferPtr+= CPkcs10Req::DERSetTag(elementBufferPtr, EASN1ObjectIdentifier); |
|
649 elementBufferPtr+= CPkcs10Req::DERSetLength(elementBufferPtr, aOidLength); |
|
650 elementBufferPtr+= CPkcs10Req::DERSetOid(elementBufferPtr, oidPtr, aOidLength); |
|
651 } |
|
652 else |
|
653 { |
|
654 // Dotted oid representation |
|
655 elementBufferPtr+= CPkcs10Req::ASNCopy(elementBufferPtr, CONST_CAST(unsigned char *, aDottedOidDer.Ptr()), aDottedOidDer.Length()); |
|
656 } |
|
657 elementBufferPtr+= CPkcs10Req::DERSetTag(elementBufferPtr, EASN1UTF8String); |
|
658 elementBufferPtr+= CPkcs10Req::DERSetLength(elementBufferPtr, aStringLength); |
|
659 elementBufferPtr+= CPkcs10Req::ASNCopy(elementBufferPtr, CONST_CAST(unsigned char *, aValuePtr.Ptr()), aValuePtr.Length()); |
|
660 |
|
661 aElementArray->AppendL(elementBuffer); |
|
662 } |
|
663 |
|
664 //////////////////////////////////////////////////////////////////////////////////////// |
|
665 // Set subject alt name extension, email |
|
666 //////////////////////////////////////////////////////////////////////////////////////// |
|
667 EXPORT_C TInt CPkcs10Req::SetSubjectAltNameRfc822(const TDesC8 &aSubjectAltNameRfc822) |
|
668 { |
|
669 TInt status = KErrNone; |
|
670 |
|
671 // Set subject alt name |
|
672 if(aSubjectAltNameRfc822.Length() > 0) |
|
673 iSubjectAltName.Set(aSubjectAltNameRfc822); |
|
674 |
|
675 return (status); |
|
676 } |
|
677 |
|
678 //////////////////////////////////////////////////////////////////////////////////////// |
|
679 // Set DNSname extension |
|
680 //////////////////////////////////////////////////////////////////////////////////////// |
|
681 EXPORT_C TInt CPkcs10Req::SetDNSName(const TDesC8 &aDNSName) |
|
682 { |
|
683 TInt status = KErrNone; |
|
684 |
|
685 // Set subject alt name |
|
686 if(aDNSName.Length() > 0) |
|
687 iDNSName.Set(aDNSName); |
|
688 |
|
689 return (status); // DNS name is optional |
|
690 } |
|
691 |
|
692 //////////////////////////////////////////////////////////////////////////////////////// |
|
693 // Set challenge password extension |
|
694 //////////////////////////////////////////////////////////////////////////////////////// |
|
695 EXPORT_C TInt CPkcs10Req::SetChallengePw(const TDesC8 &aChallengePw) |
|
696 { |
|
697 // Set challenge password |
|
698 if(aChallengePw.Length() > 0) |
|
699 iChallengePW.Set(aChallengePw); |
|
700 |
|
701 return KErrNone; // ChallengePw is optional |
|
702 } |
|
703 |
|
704 //////////////////////////////////////////////////////////////////////////////////////// |
|
705 // Set public key and key type (only RSA supported!) |
|
706 //////////////////////////////////////////////////////////////////////////////////////// |
|
707 EXPORT_C TInt CPkcs10Req::SetPublicKey(const TDesC8 &aPublicKeyBits) |
|
708 { |
|
709 TInt status = KErrNone; |
|
710 |
|
711 // Build public key DER |
|
712 if(aPublicKeyBits.Length() > 0 ) |
|
713 { |
|
714 iPublicKey.Set(aPublicKeyBits); |
|
715 } |
|
716 else |
|
717 { |
|
718 status = KErrArgument; |
|
719 } |
|
720 |
|
721 return (status); |
|
722 } |
|
723 |
|
724 //////////////////////////////////////////////////////////////////////////////////////// |
|
725 // Create the request |
|
726 // |
|
727 // In: THashType aSignatureAlgorithmId, MD5 os SHA1 |
|
728 // const TDesC& aPrivateKeyFilename, keyid used in kmdserver |
|
729 // TBool doPEM, set ETrue if PEM encoding requested, otherwise out format is DER |
|
730 // TSignCallback aSignCallBackL, signing callback function address, defined in pkcs10.h |
|
731 // Out: HBufC8 * containing the request. Remember to pop it out of the cleanupstack and delete it when not needed anymore. |
|
732 // |
|
733 // Output format is either der (in example below, ASN1 decoding done) |
|
734 // |
|
735 // 0:d=0 hl=4 l= 431 cons: SEQUENCE |
|
736 // 4:d=1 hl=4 l= 281 cons: SEQUENCE |
|
737 // 8:d=2 hl=2 l= 1 prim: INTEGER :00 |
|
738 // 11:d=2 hl=2 l= 52 cons: SEQUENCE : Distinguished name |
|
739 // 13:d=3 hl=2 l= 16 cons: SET |
|
740 // 15:d=4 hl=2 l= 14 cons: SEQUENCE |
|
741 // 17:d=5 hl=2 l= 3 prim: OBJECT :commonName |
|
742 // 22:d=5 hl=2 l= 7 prim: PRINTABLESTRING :subject |
|
743 // 31:d=3 hl=2 l= 32 cons: SET // |
|
744 // 33:d=4 hl=2 l= 30 cons: SEQUENCE |
|
745 // 35:d=5 hl=2 l= 9 prim: OBJECT :emailAddress |
|
746 // 46:d=5 hl=2 l= 17 prim: IA5STRING |
|
747 // 65:d=2 hl=3 l= 138 cons: SEQUENCE |
|
748 // 68:d=3 hl=2 l= 13 cons: SEQUENCE |
|
749 // 70:d=4 hl=2 l= 9 prim: OBJECT :rsaEncryption |
|
750 // 81:d=4 hl=2 l= 0 prim: NULL |
|
751 // 83:d=3 hl=2 l= 121 prim: BIT STRING |
|
752 // 206:d=2 hl=2 l= 81 cons: cont [ 0 ] |
|
753 // 208:d=3 hl=2 l= 26 cons: SEQUENCE |
|
754 // 210:d=4 hl=2 l= 9 prim: OBJECT :challengePassword |
|
755 // 221:d=4 hl=2 l= 13 cons: SET |
|
756 // 223:d=5 hl=2 l= 11 prim: PRINTABLESTRING :challengepw |
|
757 // 236:d=3 hl=2 l= 51 cons: SEQUENCE |
|
758 // 238:d=4 hl=2 l= 9 prim: OBJECT :Extension Request |
|
759 // 249:d=4 hl=2 l= 38 cons: SET |
|
760 // 251:d=5 hl=2 l= 36 cons: SEQUENCE |
|
761 // 253:d=6 hl=2 l= 34 cons: SEQUENCE |
|
762 // 255:d=7 hl=2 l= 9 prim: OBJECT :emailAddress |
|
763 // 266:d=7 hl=2 l= 21 prim: OCTET STRING |
|
764 // 289:d=1 hl=2 l= 13 cons: SEQUENCE |
|
765 // 291:d=2 hl=2 l= 9 prim: OBJECT :sha1WithRSAEncryption |
|
766 // 302:d=2 hl=2 l= 0 prim: NULL |
|
767 // 304:d=1 hl=3 l= 129 prim: BIT STRING |
|
768 // |
|
769 // or PEM, which looks like this |
|
770 // -----BEGIN NEW CERTIFICATE REQUEST----- |
|
771 // MIIBqDCCARECAQAwFjEUMBIGA1UEAxMLa3Vra3VsdXVydXUwgZ8wDQYJKoZIhvcN |
|
772 // AQEBBQADgY0AMIGJAoGBALCCSQ305j5l/qh4TeIJeaLdLEtKe9IpAPTCvZqZhIv/ |
|
773 // VpVRw3fdq2qgBMe6zsO0kctBYkvdZ67Yq3Gdmzx1Ofx4S0F4BUDT6TGH2uP3zi04 |
|
774 // zMb3IoDxF9BAp9drc6BKzMnhN5HBIV0RUoTLhQ8HKbFcwmqIAo0uJkUx2gbr+aOD |
|
775 // AgMBAAGgUjAXBgkqhkiG9w0BCQcxChMIcGFzc3dvcmQwNwYJKoZIhvcNAQkOMSow |
|
776 // KDAmBgNVHREEHzAdggtrdWtrdWx1dXJ1dYEOanVraUBub2tpYS5jb20wDQYJKoZI |
|
777 // hvcNAQEEBQADgYEAbltAG0DNe2NuyMHoJPg4QQExhUb9rep6eSJvrACbyT2qVgJe |
|
778 // vrdpOesdw7//MsOhgTP+MU36DlTVRbpoUJ8xO1wM10ljrxkWcwNfdEU4kf3NOiWB |
|
779 // 4i+V99jPK2nbK/ofNpJU7m2nMvi4Z66WlM/kDEwVJe5GWwIzOIyOlfkiyc8= |
|
780 // -----END NEW CERTIFICATE REQUEST----- |
|
781 // |
|
782 /////////////////////////////////////////////////////////////////////////////// |
|
783 EXPORT_C HBufC8* CPkcs10Req::CreateCertificateRequestLC( |
|
784 THashType aSignatureAlgorithmId, |
|
785 const TPKIKeyIdentifier& aPrivateKeyFilename, |
|
786 TBool aDoBase64, |
|
787 TBool aDoPEM, |
|
788 TSignCallback aSignCallBackL, |
|
789 TAny* aSignCallBackContext) |
|
790 { |
|
791 // Build certificate request |
|
792 HBufC8 *CRInfoBuffer = NULL; |
|
793 HBufC8 *CRBuffer = NULL; |
|
794 TBuf8<SHA1_HASH_LTH> hash; |
|
795 TBase64Codec base64Codec; |
|
796 HBufC8 *encodedCRBuffer = NULL; |
|
797 HBufC8 *tempBuffer = NULL; |
|
798 TBuf8<MAX_SIGNATURE_LENGTH> signature; |
|
799 |
|
800 // Create CertificationRequestInfo consisting |
|
801 // |
|
802 // - subject distinguished name |
|
803 // - public key |
|
804 // - Attributes |
|
805 // -Subject alt name Rfc822 |
|
806 // -Challenge PW |
|
807 |
|
808 CRInfoBuffer = ASNEncodeCertificationRequestInfoLC(); |
|
809 if(CRInfoBuffer) |
|
810 { |
|
811 // Sign CertificationRequestInfo |
|
812 // |
|
813 // - create hash using the defined signature algorithm |
|
814 // - create digital signature of the hash by calling the given callback function |
|
815 |
|
816 DigestL(CRInfoBuffer->Des(), hash, aSignatureAlgorithmId); |
|
817 |
|
818 // Capsulate hash in digest info |
|
819 TUint digestInfoLength = hash.Length() + 5 * ASN1_SHORT_TAG_HDR_LTH + MD5SIGNATURE_OID_LTH; |
|
820 HBufC8 *digestInfo = HBufC8::NewLC(digestInfoLength); |
|
821 |
|
822 digestInfo->Des().SetLength(digestInfoLength); |
|
823 TUint8 *digestInfoPtr = (TUint8*)digestInfo->Ptr(); |
|
824 digestInfoPtr+= CPkcs10Req::DERSetTag(digestInfoPtr, (EASN1Sequence | ASN1_CONSTRUCTED)); |
|
825 digestInfoPtr+= CPkcs10Req::DERSetLength(digestInfoPtr, digestInfoLength - ASN1_SHORT_TAG_HDR_LTH); |
|
826 digestInfoPtr+= CPkcs10Req::DERSetTag(digestInfoPtr, (EASN1Sequence | ASN1_CONSTRUCTED)); |
|
827 digestInfoPtr+= CPkcs10Req::DERSetLength(digestInfoPtr, MD5SIGNATURE_OID_LTH + 2 * ASN1_SHORT_TAG_HDR_LTH); |
|
828 digestInfoPtr+= CPkcs10Req::DERSetTag(digestInfoPtr, EASN1ObjectIdentifier); |
|
829 digestInfoPtr+= CPkcs10Req::DERSetLength(digestInfoPtr, MD5SIGNATURE_OID_LTH); |
|
830 digestInfoPtr+= CPkcs10Req::DERSetOid(digestInfoPtr, (TUint8*)KMd5SignatureOid, MD5SIGNATURE_OID_LTH); |
|
831 digestInfoPtr+= CPkcs10Req::DERSetTag(digestInfoPtr, EASN1Null); |
|
832 digestInfoPtr+= CPkcs10Req::DERSetLength(digestInfoPtr, 0); |
|
833 digestInfoPtr+= CPkcs10Req::DERSetTag(digestInfoPtr, EASN1OctetString); |
|
834 digestInfoPtr+= CPkcs10Req::DERSetLength(digestInfoPtr, hash.Length()); |
|
835 digestInfoPtr+= CPkcs10Req::ASNCopy(digestInfoPtr, CONST_CAST(TUint8 *, hash.Ptr()), hash.Length()); |
|
836 |
|
837 // Sign it |
|
838 // Only RSA supported by now |
|
839 iSignatureAlgorithmId = aSignatureAlgorithmId; |
|
840 aSignCallBackL( |
|
841 *digestInfo, |
|
842 signature, |
|
843 aPrivateKeyFilename, |
|
844 aSignCallBackContext); |
|
845 CleanupStack::PopAndDestroy( digestInfo ); |
|
846 |
|
847 // Collect CertificationRequestInfo, signature algoritm identifier (NO OPTIONS) |
|
848 // and signature into PKCS#10 CertificationRequest |
|
849 |
|
850 CRBuffer = ASNEncodeCertificationRequestLC(CRInfoBuffer->Des(), signature); |
|
851 if(CRBuffer) |
|
852 { |
|
853 if(aDoBase64) |
|
854 { |
|
855 // Base64 encode the CertificationRequest |
|
856 tempBuffer = base64Codec.Base64EncodeLC(CRBuffer->Des()); |
|
857 if(tempBuffer != NULL) |
|
858 { |
|
859 // Append PEM header and trailer |
|
860 encodedCRBuffer = HBufC8::NewL(tempBuffer->Length() + HEADERLENGTH + TRAILERLENGTH + 1); |
|
861 TPtr8 encodedCRBufferPtr = encodedCRBuffer->Des(); |
|
862 if(aDoPEM) |
|
863 { |
|
864 encodedCRBufferPtr.Copy(HEADER); |
|
865 encodedCRBufferPtr.Append(tempBuffer->Des()); |
|
866 encodedCRBufferPtr.Append(TRAILER); |
|
867 } |
|
868 else |
|
869 encodedCRBufferPtr.Copy(tempBuffer->Des()); |
|
870 |
|
871 CleanupStack::PopAndDestroy(3); //tempBuffer, CRInfoBuffer, CRBuffer |
|
872 CleanupStack::PushL(encodedCRBuffer); |
|
873 } |
|
874 else |
|
875 CleanupStack::PopAndDestroy(2); //CRInfoBuffer, CRBuffer |
|
876 } |
|
877 else |
|
878 { |
|
879 CleanupStack::Pop(1); |
|
880 CleanupStack::PopAndDestroy(1); //CRInfoBuffer |
|
881 CleanupStack::PushL(CRBuffer); |
|
882 return (CRBuffer); |
|
883 } |
|
884 } |
|
885 else |
|
886 CleanupStack::PopAndDestroy(1); //CRInfoBuffer |
|
887 } |
|
888 |
|
889 return (encodedCRBuffer); |
|
890 } |
|
891 |
|
892 |
|
893 //////////////////////////////////////////////////////////////////////////////////////// |
|
894 // MD5 hash function |
|
895 //////////////////////////////////////////////////////////////////////////////////////// |
|
896 void CPkcs10Req::MD5_HashL(const TDesC8 &aInData, TDes8& aOutData) |
|
897 { |
|
898 CUtlMessageDigest* md5 = TUtlCrypto::MakeMessageDigesterL(TUtlCrypto::EUtlMessageDigestMd5); |
|
899 aOutData.Copy(md5->Final(aInData)); |
|
900 delete md5; |
|
901 } |
|
902 |
|
903 //////////////////////////////////////////////////////////////////////////////////////// |
|
904 // SHA1 hash function |
|
905 //////////////////////////////////////////////////////////////////////////////////////// |
|
906 void CPkcs10Req::SHA1_HashL(const TDesC8 &aInData, TDes8& aOutData) |
|
907 { |
|
908 CUtlMessageDigest* sha1 = TUtlCrypto::MakeMessageDigesterL(TUtlCrypto::EUtlMessageDigestSha1); |
|
909 aOutData.Copy(sha1->Final(aInData)); |
|
910 delete sha1; |
|
911 } |
|
912 |
|
913 //////////////////////////////////////////////////////////////////////////////////////// |
|
914 // Digest function, calling either MD5 or SHA1 hash |
|
915 //////////////////////////////////////////////////////////////////////////////////////// |
|
916 void CPkcs10Req::DigestL(const TDesC8& aData, TDes8& aDigest, THashType aHashType) |
|
917 { |
|
918 if (aHashType == HASH_TYPE_MD5) |
|
919 MD5_HashL(aData, aDigest); |
|
920 else |
|
921 SHA1_HashL(aData, aDigest); |
|
922 } |
|
923 |
|
924 |
|
925 //////////////////////////////////////////////////////////////////////////// |
|
926 // |
|
927 // ASN1 related operations |
|
928 // |
|
929 /////////////////////////////////////////////////////////////////////////// |
|
930 //////////////////////////////////////////////////////////////////////////////////////// |
|
931 // Set ASN1 length |
|
932 //////////////////////////////////////////////////////////////////////////////////////// |
|
933 TInt CPkcs10Req::DERSetLength(TUint8 *p, TInt aLen) |
|
934 { |
|
935 /*------------------------------------------------------ |
|
936 * |
|
937 * Encode length value (max value supported 65535) |
|
938 * |
|
939 *------------------------------------------------------*/ |
|
940 TInt CodingLth; |
|
941 aLen &= ASN1_MAX_LENGTH; |
|
942 if ( aLen > 127 ) |
|
943 { |
|
944 if ( aLen < 256 ) |
|
945 { |
|
946 *p = 0x81; |
|
947 CodingLth = 2; |
|
948 } |
|
949 else |
|
950 { |
|
951 *p = 0x82; |
|
952 p ++; |
|
953 *p = (TUint8)((aLen >> 8) & 0xff); |
|
954 CodingLth = 3; |
|
955 } |
|
956 p ++; |
|
957 } |
|
958 else |
|
959 { |
|
960 CodingLth = 1; |
|
961 } |
|
962 *p = (TUint8)(aLen & 0xff); |
|
963 |
|
964 return CodingLth; |
|
965 } |
|
966 |
|
967 //////////////////////////////////////////////////////////////////////////////////////// |
|
968 // Set ASN1 integer |
|
969 //////////////////////////////////////////////////////////////////////////////////////// |
|
970 TInt CPkcs10Req::DERSetInteger(TUint8 *p, TInt aValue) |
|
971 { |
|
972 /*------------------------------------------------------ |
|
973 * |
|
974 * Encode Integer value (max value supported 65535) |
|
975 * |
|
976 *------------------------------------------------------*/ |
|
977 TInt CodingLth; |
|
978 aValue &= ASN1_MAX_INTEGER; |
|
979 if ( aValue > 255 ) |
|
980 CodingLth = CPkcs10Req::DERSetLength(p, 2); |
|
981 else CodingLth = CPkcs10Req::DERSetLength(p, 1); |
|
982 |
|
983 p += CodingLth; //skip length |
|
984 if ( aValue > 255 ) { |
|
985 *p = (TUint8)((aValue >> 8) & 0xff); |
|
986 p ++; |
|
987 CodingLth ++; |
|
988 } |
|
989 *p = (TUint8)(aValue & 0xff); |
|
990 CodingLth ++; |
|
991 |
|
992 return CodingLth; |
|
993 } |
|
994 |
|
995 |
|
996 //////////////////////////////////////////////////////////////////////////////////////// |
|
997 // Encode Certification Request Info |
|
998 //////////////////////////////////////////////////////////////////////////////////////// |
|
999 HBufC8* CPkcs10Req::ASNEncodeCertificationRequestInfoLC() |
|
1000 { |
|
1001 // Build certificate request info |
|
1002 HBufC8 *CRInfoBuffer = NULL; |
|
1003 TUint8 *CRInfoPtr; |
|
1004 TUint requestInfoLength; |
|
1005 TUint coverSeqHeaderLength = 2; |
|
1006 |
|
1007 HBufC8 *commonAttributes; |
|
1008 HBufC8 *pkiInfo; |
|
1009 HBufC8 *extendedAttributes; |
|
1010 |
|
1011 // Build components |
|
1012 // Encode common attributes |
|
1013 commonAttributes = ASNEncodeCommonAttributesLC(); |
|
1014 // Encode private key |
|
1015 pkiInfo = ASNEncodePKIinfoLC(); |
|
1016 // Encode common attributes |
|
1017 extendedAttributes = ASNEncodeExtendedAttributesLC(); |
|
1018 |
|
1019 requestInfoLength = commonAttributes->Length() + pkiInfo->Length() + extendedAttributes->Length() + ASN1_SHORT_TAG_HDR_LTH + 1; // Fixed one byte version number! |
|
1020 |
|
1021 if(requestInfoLength > 127) |
|
1022 coverSeqHeaderLength++; |
|
1023 if(requestInfoLength > 255) |
|
1024 coverSeqHeaderLength++; |
|
1025 |
|
1026 requestInfoLength = requestInfoLength + coverSeqHeaderLength; |
|
1027 |
|
1028 if(requestInfoLength > 0) |
|
1029 { |
|
1030 CRInfoBuffer = HBufC8::NewL(requestInfoLength); |
|
1031 CRInfoBuffer->Des().SetLength(requestInfoLength); |
|
1032 CRInfoPtr = (TUint8*)CRInfoBuffer->Ptr(); |
|
1033 |
|
1034 // Build header |
|
1035 CRInfoPtr += CPkcs10Req::DERSetTag(CRInfoPtr, (EASN1Sequence | ASN1_CONSTRUCTED)); |
|
1036 CRInfoPtr += CPkcs10Req::DERSetLength(CRInfoPtr, requestInfoLength - coverSeqHeaderLength); |
|
1037 CRInfoPtr += CPkcs10Req::DERSetTag(CRInfoPtr, EASN1Integer); |
|
1038 CRInfoPtr += DERSetInteger(CRInfoPtr, 0); // version |
|
1039 |
|
1040 // Copy component ders |
|
1041 if(commonAttributes != NULL && commonAttributes->Length() > 0) |
|
1042 CRInfoPtr += CPkcs10Req::ASNCopy(CRInfoPtr, CONST_CAST(TUint8 *, commonAttributes->Ptr()), commonAttributes->Length()); |
|
1043 |
|
1044 if(pkiInfo != NULL && pkiInfo->Length() > 0) |
|
1045 CRInfoPtr += CPkcs10Req::ASNCopy(CRInfoPtr, CONST_CAST(TUint8 *, pkiInfo->Ptr()), pkiInfo->Length()); |
|
1046 |
|
1047 if(extendedAttributes != NULL && extendedAttributes->Length() > 0) |
|
1048 CRInfoPtr += CPkcs10Req::ASNCopy(CRInfoPtr, CONST_CAST(TUint8 *, extendedAttributes->Ptr()), extendedAttributes->Length()); |
|
1049 } |
|
1050 |
|
1051 if(extendedAttributes != NULL) |
|
1052 { |
|
1053 delete extendedAttributes; |
|
1054 CleanupStack::Pop(1); |
|
1055 } |
|
1056 if(pkiInfo != NULL) |
|
1057 { |
|
1058 delete pkiInfo; |
|
1059 CleanupStack::Pop(1); |
|
1060 } |
|
1061 if(commonAttributes != NULL) |
|
1062 { |
|
1063 delete commonAttributes; |
|
1064 CleanupStack::Pop(1); |
|
1065 } |
|
1066 if(CRInfoBuffer != NULL) |
|
1067 CleanupStack::PushL(CRInfoBuffer); // to be destroyed by the caller |
|
1068 |
|
1069 return (CRInfoBuffer); |
|
1070 } |
|
1071 |
|
1072 //////////////////////////////////////////////////////////////////////////////////////// |
|
1073 // Encode Certification Request |
|
1074 //////////////////////////////////////////////////////////////////////////////////////// |
|
1075 HBufC8* CPkcs10Req::ASNEncodeCertificationRequestLC(const TDes8 &CRInfoBuffer, const TDes8 &signature) |
|
1076 { |
|
1077 HBufC8 *CRBuffer = NULL; |
|
1078 TUint8 *CRPtr; |
|
1079 TUint requestLength; |
|
1080 TUint coverSeqHeaderLength = 2; |
|
1081 TUint signatureLength = 0; |
|
1082 |
|
1083 if(CRInfoBuffer.Length() > 0 && signature.Length() > 0) |
|
1084 { |
|
1085 signatureLength = signature.Length() + 1; // No padding zero added |
|
1086 if(signatureLength > 127) |
|
1087 signatureLength++; |
|
1088 if(signatureLength > 255) |
|
1089 signatureLength++; |
|
1090 |
|
1091 if(iSignatureAlgorithmId == HASH_TYPE_MD5) |
|
1092 requestLength = CRInfoBuffer.Length() + signatureLength + 4 * ASN1_SHORT_TAG_HDR_LTH + MD5WITHRSA_OID_LTH; |
|
1093 else |
|
1094 requestLength = CRInfoBuffer.Length() + signatureLength + 4 * ASN1_SHORT_TAG_HDR_LTH + SHA1WITHRSA_OID_LTH; |
|
1095 |
|
1096 if(requestLength > 127) |
|
1097 coverSeqHeaderLength++; |
|
1098 if(requestLength > 255) |
|
1099 coverSeqHeaderLength++; |
|
1100 |
|
1101 requestLength = requestLength + coverSeqHeaderLength; |
|
1102 |
|
1103 CRBuffer = HBufC8::NewL(requestLength); |
|
1104 CRBuffer->Des().SetLength(requestLength); |
|
1105 CRPtr = (TUint8*)CRBuffer->Ptr(); |
|
1106 |
|
1107 CRPtr += CPkcs10Req::DERSetTag(CRPtr, (EASN1Sequence | ASN1_CONSTRUCTED)); |
|
1108 CRPtr += CPkcs10Req::DERSetLength(CRPtr, requestLength - coverSeqHeaderLength); |
|
1109 |
|
1110 // Copy Certificate request info |
|
1111 CRPtr += CPkcs10Req::ASNCopy(CRPtr, CONST_CAST(TUint8 *, CRInfoBuffer.Ptr()), CRInfoBuffer.Length()); |
|
1112 CRPtr += CPkcs10Req::DERSetTag(CRPtr, (EASN1Sequence | ASN1_CONSTRUCTED)); |
|
1113 CRPtr += CPkcs10Req::DERSetLength(CRPtr, MD5WITHRSA_OID_LTH + 2 * ASN1_SHORT_TAG_HDR_LTH); // null included! |
|
1114 // Set algorithm identifier |
|
1115 CRPtr += CPkcs10Req::DERSetTag(CRPtr, EASN1ObjectIdentifier); |
|
1116 if(iSignatureAlgorithmId == HASH_TYPE_MD5) |
|
1117 { |
|
1118 CRPtr += CPkcs10Req::DERSetLength(CRPtr, MD5WITHRSA_OID_LTH); |
|
1119 CRPtr += CPkcs10Req::DERSetOid(CRPtr, (TUint8*)KMd5WithRSAEncryptionOid, MD5WITHRSA_OID_LTH); |
|
1120 } |
|
1121 else |
|
1122 { |
|
1123 CRPtr += CPkcs10Req::DERSetLength(CRPtr, SHA1WITHRSA_OID_LTH); |
|
1124 CRPtr += CPkcs10Req::DERSetOid(CRPtr, (TUint8*)KSha1WithRSAEncryptionOid, SHA1WITHRSA_OID_LTH); |
|
1125 } |
|
1126 |
|
1127 CRPtr += CPkcs10Req::DERSetTag(CRPtr, EASN1Null); |
|
1128 CRPtr += CPkcs10Req::DERSetLength(CRPtr, 0); |
|
1129 // Copy signature |
|
1130 CRPtr += CPkcs10Req::DERSetTag(CRPtr, EASN1BitString); |
|
1131 CRPtr += CPkcs10Req::DERSetLength(CRPtr, signature.Length() + 1); |
|
1132 CRPtr += CPkcs10Req::DERSetLength(CRPtr, 0); // add 0, no padding |
|
1133 CRPtr += CPkcs10Req::ASNCopy(CRPtr, CONST_CAST(TUint8 *, signature.Ptr()), signature.Length()); |
|
1134 |
|
1135 CleanupStack::PushL(CRBuffer); // to be destroyed by the caller |
|
1136 } |
|
1137 return (CRBuffer); |
|
1138 } |
|
1139 |
|
1140 //////////////////////////////////////////////////////////////////////////////////////// |
|
1141 // Encode common attributes |
|
1142 //////////////////////////////////////////////////////////////////////////////////////// |
|
1143 HBufC8* CPkcs10Req::ASNEncodeCommonAttributesLC() |
|
1144 { |
|
1145 HBufC8 *commonAttributesBuffer = NULL; |
|
1146 TUint8 *commonAttributesPtr; |
|
1147 TUint distinguishedNameAttrLength; |
|
1148 TUint totalLength = 0; |
|
1149 TUint coverSeqHeaderLength = 2; |
|
1150 |
|
1151 if(iUseExtendedDistinguishedName) |
|
1152 { |
|
1153 if(iDNDerBuf != NULL && iDNDerBuf->Des().Length() > 0) |
|
1154 commonAttributesBuffer = iDNDerBuf->Des().AllocLC(); |
|
1155 return (commonAttributesBuffer); |
|
1156 } |
|
1157 if(iDistinguishedName.Length() == 0) |
|
1158 distinguishedNameAttrLength = 0; |
|
1159 else |
|
1160 distinguishedNameAttrLength = 4 * ASN1_SHORT_TAG_HDR_LTH + COMMON_NAME_OID_LTH + iDistinguishedName.Length(); |
|
1161 |
|
1162 totalLength = distinguishedNameAttrLength; |
|
1163 if(totalLength > 127) |
|
1164 coverSeqHeaderLength++; |
|
1165 if(totalLength > 255) |
|
1166 coverSeqHeaderLength++; |
|
1167 |
|
1168 totalLength = totalLength + coverSeqHeaderLength; |
|
1169 |
|
1170 if(totalLength > 0) |
|
1171 { |
|
1172 commonAttributesBuffer = HBufC8::NewL(totalLength); |
|
1173 commonAttributesBuffer->Des().SetLength(totalLength); |
|
1174 commonAttributesPtr = (TUint8*)commonAttributesBuffer->Ptr(); |
|
1175 |
|
1176 commonAttributesPtr+= CPkcs10Req::DERSetTag(commonAttributesPtr, (EASN1Sequence | ASN1_CONSTRUCTED)); |
|
1177 commonAttributesPtr+= CPkcs10Req::DERSetLength(commonAttributesPtr, totalLength - coverSeqHeaderLength); |
|
1178 |
|
1179 if(iDistinguishedName.Length() > 0) |
|
1180 { |
|
1181 // Encode common name |
|
1182 commonAttributesPtr+= CPkcs10Req::DERSetTag(commonAttributesPtr, (EASN1Set | ASN1_CONSTRUCTED)); |
|
1183 commonAttributesPtr+= CPkcs10Req::DERSetLength(commonAttributesPtr, distinguishedNameAttrLength - ASN1_SHORT_TAG_HDR_LTH); |
|
1184 commonAttributesPtr+= CPkcs10Req::DERSetTag(commonAttributesPtr, (EASN1Sequence | ASN1_CONSTRUCTED)); |
|
1185 commonAttributesPtr+= CPkcs10Req::DERSetLength(commonAttributesPtr, distinguishedNameAttrLength - 2 * ASN1_SHORT_TAG_HDR_LTH); |
|
1186 commonAttributesPtr+= CPkcs10Req::DERSetTag(commonAttributesPtr, EASN1ObjectIdentifier); |
|
1187 commonAttributesPtr+= CPkcs10Req::DERSetLength(commonAttributesPtr, COMMON_NAME_OID_LTH); |
|
1188 commonAttributesPtr+= CPkcs10Req::DERSetOid(commonAttributesPtr, (TUint8*)KCommonNameOid, COMMON_NAME_OID_LTH); |
|
1189 commonAttributesPtr+= CPkcs10Req::DERSetTag(commonAttributesPtr, EASN1UTF8String); |
|
1190 commonAttributesPtr+= CPkcs10Req::DERSetLength(commonAttributesPtr, iDistinguishedName.Length()); |
|
1191 commonAttributesPtr+= CPkcs10Req::ASNCopy(commonAttributesPtr, CONST_CAST(TUint8 *, iDistinguishedName.Ptr()), iDistinguishedName.Length()); |
|
1192 } |
|
1193 CleanupStack::PushL(commonAttributesBuffer); |
|
1194 } |
|
1195 return (commonAttributesBuffer); |
|
1196 } |
|
1197 |
|
1198 //////////////////////////////////////////////////////////////////////////////////////// |
|
1199 // Encode Private key information |
|
1200 //////////////////////////////////////////////////////////////////////////////////////// |
|
1201 HBufC8* CPkcs10Req::ASNEncodePKIinfoLC() |
|
1202 { |
|
1203 HBufC8 *pkiInfoBuffer = NULL; |
|
1204 TUint8 *pkiInfoPtr; |
|
1205 TUint entityLength; |
|
1206 TUint bitStringHeaderLength = 2; |
|
1207 TUint coverSeqHeaderLength = 2; |
|
1208 |
|
1209 if(iPublicKey.Length() == 0) |
|
1210 entityLength = 0; |
|
1211 else |
|
1212 { |
|
1213 entityLength = iPublicKey.Length() + 1; // Add 1 for padding indicator byte |
|
1214 if(entityLength > 127) |
|
1215 bitStringHeaderLength++; |
|
1216 if(entityLength > 255) |
|
1217 bitStringHeaderLength++; |
|
1218 |
|
1219 entityLength = entityLength + bitStringHeaderLength + 3 * ASN1_SHORT_TAG_HDR_LTH + KEY_TYPE_RSA_OID_LTH; |
|
1220 |
|
1221 if(entityLength > 127) |
|
1222 coverSeqHeaderLength++; |
|
1223 if(entityLength > 255) |
|
1224 coverSeqHeaderLength++; |
|
1225 |
|
1226 entityLength = entityLength + coverSeqHeaderLength; |
|
1227 } |
|
1228 |
|
1229 if(entityLength > 0) |
|
1230 { |
|
1231 pkiInfoBuffer = HBufC8::NewL(entityLength); |
|
1232 pkiInfoBuffer->Des().SetLength(entityLength); |
|
1233 pkiInfoPtr = (TUint8*)pkiInfoBuffer->Ptr(); |
|
1234 |
|
1235 pkiInfoPtr+= CPkcs10Req::DERSetTag(pkiInfoPtr, (EASN1Sequence | ASN1_CONSTRUCTED)); |
|
1236 pkiInfoPtr+= CPkcs10Req::DERSetLength(pkiInfoPtr, entityLength - coverSeqHeaderLength); |
|
1237 pkiInfoPtr+= CPkcs10Req::DERSetTag(pkiInfoPtr, (EASN1Sequence | ASN1_CONSTRUCTED)); |
|
1238 pkiInfoPtr+= CPkcs10Req::DERSetLength(pkiInfoPtr, KEY_TYPE_RSA_OID_LTH + ASN1_SHORT_TAG_HDR_LTH + ASN1_NULL_LTH); |
|
1239 // Only RSA key supported |
|
1240 pkiInfoPtr+= CPkcs10Req::DERSetTag(pkiInfoPtr, EASN1ObjectIdentifier); |
|
1241 pkiInfoPtr+= CPkcs10Req::DERSetLength(pkiInfoPtr, KEY_TYPE_RSA_OID_LTH); |
|
1242 pkiInfoPtr+= CPkcs10Req::DERSetOid(pkiInfoPtr, (TUint8*)KKeyTypeRSAOid, KEY_TYPE_RSA_OID_LTH); |
|
1243 pkiInfoPtr+= CPkcs10Req::DERSetTag(pkiInfoPtr, EASN1Null); |
|
1244 pkiInfoPtr+= CPkcs10Req::DERSetLength(pkiInfoPtr, 0); |
|
1245 pkiInfoPtr+= CPkcs10Req::DERSetTag(pkiInfoPtr, EASN1BitString); |
|
1246 pkiInfoPtr+= CPkcs10Req::DERSetLength(pkiInfoPtr, iPublicKey.Length() + 1); |
|
1247 pkiInfoPtr+= CPkcs10Req::DERSetLength(pkiInfoPtr, 0); // add 0, no padding |
|
1248 pkiInfoPtr+= CPkcs10Req::ASNCopy(pkiInfoPtr, CONST_CAST(TUint8 *, iPublicKey.Ptr()), iPublicKey.Length()); |
|
1249 |
|
1250 CleanupStack::PushL(pkiInfoBuffer); |
|
1251 } |
|
1252 return (pkiInfoBuffer); |
|
1253 } |
|
1254 |
|
1255 //////////////////////////////////////////////////////////////////////////////////////// |
|
1256 // Encode Extended attributes |
|
1257 //////////////////////////////////////////////////////////////////////////////////////// |
|
1258 HBufC8* CPkcs10Req::ASNEncodeExtendedAttributesLC() |
|
1259 { |
|
1260 HBufC8 *extendedAttributesBuffer = NULL; |
|
1261 TUint8 *extendedAttributesPtr; |
|
1262 TUint challengePWLength; |
|
1263 TUint DNSLength; |
|
1264 TUint SubAltNLength; |
|
1265 TUint emailExtensionLength; |
|
1266 TUint totalLength; |
|
1267 TUint tempLength; |
|
1268 TUint coverTagLength = 2; |
|
1269 |
|
1270 if(iChallengePW.Length() == 0) |
|
1271 challengePWLength = 0; |
|
1272 else |
|
1273 challengePWLength = 4 * ASN1_SHORT_TAG_HDR_LTH + CHALLENGEPW_OID_LTH + iChallengePW.Length(); |
|
1274 |
|
1275 if((iSubjectAltName.Length() == 0) && (iDNSName.Length() == 0)) |
|
1276 emailExtensionLength = 0; |
|
1277 else |
|
1278 // Header part |
|
1279 emailExtensionLength = 8 * ASN1_SHORT_TAG_HDR_LTH + SUBJECTALTNAME_OID_LTH + PKCS10_EXTENSION_OID_LTH; |
|
1280 |
|
1281 if(iSubjectAltName.Length() == 0) |
|
1282 SubAltNLength = 0; |
|
1283 else |
|
1284 SubAltNLength = ASN1_SHORT_TAG_HDR_LTH + iSubjectAltName.Length(); |
|
1285 |
|
1286 emailExtensionLength = emailExtensionLength + SubAltNLength; |
|
1287 |
|
1288 if(iDNSName.Length() == 0) |
|
1289 DNSLength = 0; |
|
1290 else |
|
1291 DNSLength = ASN1_SHORT_TAG_HDR_LTH + iDNSName.Length(); |
|
1292 |
|
1293 emailExtensionLength = emailExtensionLength + DNSLength; |
|
1294 totalLength = challengePWLength + emailExtensionLength; |
|
1295 |
|
1296 if(totalLength > 127) |
|
1297 coverTagLength++; |
|
1298 |
|
1299 totalLength = totalLength + coverTagLength; |
|
1300 |
|
1301 if(totalLength > 0) |
|
1302 { |
|
1303 extendedAttributesBuffer = HBufC8::NewL(totalLength); |
|
1304 extendedAttributesBuffer->Des().SetLength(totalLength); |
|
1305 extendedAttributesPtr = (TUint8*)extendedAttributesBuffer->Ptr(); |
|
1306 |
|
1307 extendedAttributesPtr+= CPkcs10Req::DERSetTag(extendedAttributesPtr, (EASN1EOC | ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED)); |
|
1308 extendedAttributesPtr+= CPkcs10Req::DERSetLength(extendedAttributesPtr, totalLength - coverTagLength); |
|
1309 |
|
1310 if(challengePWLength > 0) |
|
1311 { |
|
1312 // Challenge password |
|
1313 extendedAttributesPtr+= CPkcs10Req::DERSetTag(extendedAttributesPtr, (EASN1Sequence | ASN1_CONSTRUCTED)); |
|
1314 extendedAttributesPtr+= CPkcs10Req::DERSetLength(extendedAttributesPtr, challengePWLength - ASN1_SHORT_TAG_HDR_LTH ); |
|
1315 extendedAttributesPtr+= CPkcs10Req::DERSetTag(extendedAttributesPtr, EASN1ObjectIdentifier); |
|
1316 extendedAttributesPtr+= CPkcs10Req::DERSetLength(extendedAttributesPtr, CHALLENGEPW_OID_LTH); |
|
1317 extendedAttributesPtr+= CPkcs10Req::DERSetOid(extendedAttributesPtr, (TUint8*)KChallengePWOid, CHALLENGEPW_OID_LTH); |
|
1318 extendedAttributesPtr+= CPkcs10Req::DERSetTag(extendedAttributesPtr, (EASN1Set | ASN1_CONSTRUCTED)); |
|
1319 extendedAttributesPtr+= CPkcs10Req::DERSetLength(extendedAttributesPtr, iChallengePW.Length() + ASN1_SHORT_TAG_HDR_LTH ); |
|
1320 extendedAttributesPtr+= CPkcs10Req::DERSetTag(extendedAttributesPtr, (EASN1PrintableString)); |
|
1321 extendedAttributesPtr+= CPkcs10Req::DERSetLength(extendedAttributesPtr, iChallengePW.Length()); |
|
1322 extendedAttributesPtr+= CPkcs10Req::ASNCopy(extendedAttributesPtr, CONST_CAST(TUint8 *, iChallengePW.Ptr()), iChallengePW.Length()); |
|
1323 } |
|
1324 |
|
1325 if(emailExtensionLength > 0) |
|
1326 { |
|
1327 // SubjectAltName.Email assumed to be less than 97 bytes |
|
1328 extendedAttributesPtr+= CPkcs10Req::DERSetTag(extendedAttributesPtr, (EASN1Sequence | ASN1_CONSTRUCTED)); |
|
1329 extendedAttributesPtr+= CPkcs10Req::DERSetLength(extendedAttributesPtr, emailExtensionLength - ASN1_SHORT_TAG_HDR_LTH ); |
|
1330 extendedAttributesPtr+= CPkcs10Req::DERSetTag(extendedAttributesPtr, EASN1ObjectIdentifier); |
|
1331 extendedAttributesPtr+= CPkcs10Req::DERSetLength(extendedAttributesPtr, PKCS10_EXTENSION_OID_LTH); |
|
1332 extendedAttributesPtr+= CPkcs10Req::DERSetOid(extendedAttributesPtr, (TUint8*)KPkcs10ExtensionOid, PKCS10_EXTENSION_OID_LTH); |
|
1333 extendedAttributesPtr+= CPkcs10Req::DERSetTag(extendedAttributesPtr, (EASN1Set | ASN1_CONSTRUCTED)); |
|
1334 tempLength = SUBJECTALTNAME_OID_LTH + 5 * ASN1_SHORT_TAG_HDR_LTH + DNSLength + SubAltNLength; |
|
1335 extendedAttributesPtr+= CPkcs10Req::DERSetLength(extendedAttributesPtr, tempLength); |
|
1336 extendedAttributesPtr+= CPkcs10Req::DERSetTag(extendedAttributesPtr, (EASN1Sequence | ASN1_CONSTRUCTED)); |
|
1337 extendedAttributesPtr+= CPkcs10Req::DERSetLength(extendedAttributesPtr, tempLength - ASN1_SHORT_TAG_HDR_LTH ); |
|
1338 extendedAttributesPtr+= CPkcs10Req::DERSetTag(extendedAttributesPtr, (EASN1Sequence | ASN1_CONSTRUCTED)); |
|
1339 extendedAttributesPtr+= CPkcs10Req::DERSetLength(extendedAttributesPtr, tempLength - 2 * ASN1_SHORT_TAG_HDR_LTH); |
|
1340 extendedAttributesPtr+= CPkcs10Req::DERSetTag(extendedAttributesPtr, EASN1ObjectIdentifier); |
|
1341 extendedAttributesPtr+= CPkcs10Req::DERSetLength(extendedAttributesPtr, SUBJECTALTNAME_OID_LTH); |
|
1342 extendedAttributesPtr+= CPkcs10Req::DERSetOid(extendedAttributesPtr, (TUint8*)KSubjectAltNameOid, SUBJECTALTNAME_OID_LTH); |
|
1343 extendedAttributesPtr+= CPkcs10Req::DERSetTag(extendedAttributesPtr, EASN1OctetString); |
|
1344 extendedAttributesPtr+= CPkcs10Req::DERSetLength(extendedAttributesPtr, ASN1_SHORT_TAG_HDR_LTH + DNSLength + SubAltNLength); |
|
1345 extendedAttributesPtr+= CPkcs10Req::DERSetTag(extendedAttributesPtr, (EASN1Sequence | ASN1_CONSTRUCTED)); |
|
1346 extendedAttributesPtr+= CPkcs10Req::DERSetLength(extendedAttributesPtr, DNSLength + SubAltNLength); |
|
1347 |
|
1348 if(SubAltNLength > 0) |
|
1349 { |
|
1350 extendedAttributesPtr+= CPkcs10Req::DERSetTag(extendedAttributesPtr, (EASN1EOC | ASN1_CONTEXT_SPECIFIC | 0x1)); // context specific 1 |
|
1351 extendedAttributesPtr+= CPkcs10Req::DERSetLength(extendedAttributesPtr, iSubjectAltName.Length()); |
|
1352 extendedAttributesPtr+= CPkcs10Req::ASNCopy(extendedAttributesPtr, CONST_CAST(TUint8 *, iSubjectAltName.Ptr()), iSubjectAltName.Length()); |
|
1353 } |
|
1354 |
|
1355 if(DNSLength > 0) |
|
1356 { |
|
1357 extendedAttributesPtr+= CPkcs10Req::DERSetTag(extendedAttributesPtr, (EASN1EOC | ASN1_CONTEXT_SPECIFIC | 0x2)); // context specific 2 |
|
1358 extendedAttributesPtr+= CPkcs10Req::DERSetLength(extendedAttributesPtr, iDNSName.Length()); |
|
1359 extendedAttributesPtr+= CPkcs10Req::ASNCopy(extendedAttributesPtr, CONST_CAST(TUint8 *, iDNSName.Ptr()), iDNSName.Length()); |
|
1360 } |
|
1361 } |
|
1362 CleanupStack::PushL(extendedAttributesBuffer); |
|
1363 } |
|
1364 |
|
1365 return (extendedAttributesBuffer); |
|
1366 } |
|
1367 |
|
1368 //////////////////////////////////////////////////////////////////////////////////////// |
|
1369 // ASN1 copy |
|
1370 //////////////////////////////////////////////////////////////////////////////////////// |
|
1371 TInt CPkcs10Req::ASNCopy(TUint8 *dataPtr, TUint8 *valuePtr, TInt length) |
|
1372 { |
|
1373 Mem::Copy(dataPtr, valuePtr, length); |
|
1374 return (length); |
|
1375 } |