vpnengine/utlpkcs10/src/pkcs10.cpp
changeset 0 33413c0669b9
child 10 68dc8923de26
equal deleted inserted replaced
-1:000000000000 0:33413c0669b9
       
     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 }