1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/ossrv/ssl/libcrypto/src/crypto/certretriever/createx509.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,474 @@
1.4 +/*
1.5 +Copyright (c) 2009-2010 Nokia Corporation and/or its subsidiary(-ies). All rights reserved.
1.6 +
1.7 +Redistribution and use in source and binary forms, with or without
1.8 +modification, are permitted provided that the following conditions are met:
1.9 +
1.10 +* Redistributions of source code must retain the above copyright notice, this
1.11 + list of conditions and the following disclaimer.
1.12 +* Redistributions in binary form must reproduce the above copyright notice,
1.13 + this list of conditions and the following disclaimer in the documentation
1.14 + and/or other materials provided with the distribution.
1.15 +* Neither the name of Nokia Corporation nor the names of its contributors
1.16 + may be used to endorse or promote products derived from this software
1.17 + without specific prior written permission.
1.18 +
1.19 +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
1.20 +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1.21 +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
1.22 +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
1.23 +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1.24 +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
1.25 +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
1.26 +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
1.27 +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
1.28 +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1.29 +
1.30 +Description:
1.31 +*/
1.32 +
1.33 +
1.34 +#include "createx509.h"
1.35 +
1.36 +
1.37 +X509* CX509_Initializer::CreateX509L(CX509Certificate* X509Cert)
1.38 +{
1.39 + X509* ret = X509_new();
1.40 + TBool serail = ETrue;
1.41 +
1.42 + if(ret != NULL)
1.43 + {
1.44 +
1.45 +//validity
1.46 + X509_VAL_free(ret->cert_info->validity);
1.47 + ret->cert_info->validity = CreateX509_VAL(X509Cert);
1.48 +
1.49 +//issuer
1.50 + const CX500DistinguishedName& IssName = X509Cert->IssuerName();
1.51 + X509_NAME_free(ret->cert_info->issuer);
1.52 + ret->cert_info->issuer = CreateX509_NAMEL(IssName);
1.53 +
1.54 +//subject
1.55 + const CX500DistinguishedName& SubName = X509Cert->SubjectName();
1.56 + X509_NAME_free(ret->cert_info->subject);
1.57 + ret->cert_info->subject = CreateX509_NAMEL(SubName);
1.58 + // const HBufC * name = SubName.DisplayNameL();
1.59 +
1.60 +//signature
1.61 + const TPtrC8* sig_alg_ptr = X509Cert->DataElementEncoding(CX509Certificate::EAlgorithmId);
1.62 + X509_ALGOR_free(ret->cert_info->signature);
1.63 + ret->cert_info->signature = CreateX509_ALGORL(sig_alg_ptr);
1.64 +
1.65 +//serialnumber
1.66 + const TPtrC8 sernum = X509Cert->SerialNumber();
1.67 + ASN1_INTEGER_free(ret->cert_info->serialNumber);
1.68 + ret->cert_info->serialNumber = CreateASN1_STRING(sernum.Length(),V_ASN1_INTEGER,(unsigned char *)sernum.Ptr(),0);
1.69 + if((sernum.Length()== 1) && sernum[0]==0)
1.70 + serail = EFalse;
1.71 +
1.72 +//version
1.73 +
1.74 + TInt ver = X509Cert->Version();
1.75 + unsigned char verVal = (unsigned char)(ver-1);
1.76 + ASN1_INTEGER_free(ret->cert_info->version);
1.77 + if( (verVal) || (!serail))// for X509 V1 certificates, version is null if any serial number present.
1.78 + ret->cert_info->version = CreateASN1_STRING(1,V_ASN1_INTEGER,&verVal,0);
1.79 +
1.80 +
1.81 +//issuerUID
1.82 + const TPtrC8* issUID_enc = X509Cert->DataElementEncoding(CX509Certificate::EIssuerUID);
1.83 + if(issUID_enc)
1.84 + ret->cert_info->issuerUID = CreateASN1_STRING(issUID_enc->Length(),V_ASN1_BIT_STRING,(unsigned char *)issUID_enc->Ptr(),0);
1.85 +
1.86 +
1.87 +//subjectUID
1.88 + const TPtrC8* subUID_enc = X509Cert->DataElementEncoding(CX509Certificate::ESubjectUID);
1.89 + if(subUID_enc)
1.90 + ret->cert_info->subjectUID = CreateASN1_STRING(subUID_enc->Length(),V_ASN1_BIT_STRING,(unsigned char *)subUID_enc->Ptr(),0);
1.91 +
1.92 +//key
1.93 + X509_PUBKEY_free(ret->cert_info->key);
1.94 + ret->cert_info->key = CreateX509_PUBKEYL(X509Cert);
1.95 +
1.96 +
1.97 +//extension
1.98 +
1.99 +
1.100 + ret->cert_info->extensions = CreateSTACKOF_X509_EXTENSIONL(X509Cert);
1.101 +
1.102 +
1.103 +//name
1.104 + ret->name = X509_NAME_oneline(ret->cert_info->subject, NULL, 0);
1.105 +
1.106 +//sig_alg
1.107 + X509_ALGOR_free(ret->sig_alg);
1.108 + ret->sig_alg = CreateX509_ALGORL(sig_alg_ptr);
1.109 +
1.110 +//signature
1.111 + const TPtrC8 sig = X509Cert->Signature();
1.112 + ASN1_STRING_free(ret->signature);
1.113 + ret->signature = CreateASN1_STRING(sig.Length(), V_ASN1_BIT_STRING, (unsigned char *)sig.Ptr(), ASN1_STRING_FLAG_BITS_LEFT);
1.114 + }
1.115 +
1.116 + return ret;
1.117 +}
1.118 +
1.119 +
1.120 +X509_ALGOR* CX509_Initializer::CreateX509_ALGORL(const TPtrC8* ptr)
1.121 +{
1.122 + X509_ALGOR* ret = X509_ALGOR_new();
1.123 +
1.124 + TASN1DecGeneric dec((TDesC8 &)*ptr);
1.125 + dec.InitL();
1.126 +
1.127 + TASN1DecSequence encSeq;
1.128 + CArrayPtrFlat<TASN1DecGeneric>* seq = encSeq.DecodeDERLC(dec);
1.129 +
1.130 + TASN1DecGeneric& AlgorEncSeq = *(seq->At(0));
1.131 +
1.132 + if (dec.LengthDERContent() > AlgorEncSeq.LengthDER()) // can also check for (seq->Count() > 1) alternatively
1.133 + {
1.134 + // parameter part is present in the encoding.
1.135 + TASN1DecGeneric& ParameterEncSeq = *(seq->At(1));
1.136 +
1.137 + // if param = 5, ie. ASN1 type NULL, then create a NULL ASN1 STRING
1.138 + ret->parameter = ASN1_TYPE_new();
1.139 + ret->parameter->type = (TInt)ParameterEncSeq.Encoding()[0];
1.140 +
1.141 + if(ret->parameter->type != V_ASN1_NULL)
1.142 + {
1.143 + // we have some parameter
1.144 + // add code to fill this stuff
1.145 + }
1.146 + }
1.147 + else
1.148 + {
1.149 + //encoding does not contain parameter at all
1.150 + //ret->parameter is anyway NULL when X509_ALGOR is created
1.151 + //Not sure if we need to create a NULL ASN1 string or just leave parameter = NULL
1.152 + }
1.153 +
1.154 +
1.155 + const TDesC8& algor_data = AlgorEncSeq.GetContentDER();
1.156 + char * ch_algor_data = (char *)algor_data.Ptr();
1.157 +
1.158 + ret->algorithm = ASN1_OBJECT_new();
1.159 + ret->algorithm->length = AlgorEncSeq.LengthDERContent();
1.160 + ret->algorithm->data = (unsigned char *)OPENSSL_malloc(ret->algorithm->length);
1.161 + if(ret->algorithm->data)
1.162 + memcpy(ret->algorithm->data, ch_algor_data, ret->algorithm->length);
1.163 + //else log error- cannot malloc
1.164 +
1.165 + ret->algorithm->flags |= ASN1_OBJECT_FLAG_DYNAMIC_DATA; // so that X509_ALGOR_free() frees all internally allocated data
1.166 +
1.167 + CleanupStack::PopAndDestroy(); //seq
1.168 +
1.169 + return ret;
1.170 +}
1.171 +
1.172 +
1.173 +
1.174 +X509_NAME* CX509_Initializer::CreateX509_NAMEL(const CX500DistinguishedName& DistName)
1.175 +{
1.176 + X509_NAME* ret = X509_NAME_new();
1.177 +
1.178 + CASN1EncSequence * Asn1Seq = DistName.EncodeASN1LC();
1.179 +
1.180 + HBufC8* octetData = HBufC8::NewMaxLC(5000);
1.181 + TPtr8 oct(octetData->Des());
1.182 + oct.FillZ();
1.183 + oct.SetLength(KMaxNameLength);
1.184 + TUint writePos = 0;
1.185 + Asn1Seq->WriteDERL(oct, writePos);
1.186 +
1.187 + TInt len = Fill_X509_NAME_ENTRYL(ret, octetData->Des());
1.188 +
1.189 + char *p = (char *)oct.PtrZ();
1.190 +
1.191 + ret->bytes->data = (char *)OPENSSL_malloc(len); // no need to free this. BUF_MEM_free will free if not NULL
1.192 + if(ret->bytes->data)
1.193 + memcpy(ret->bytes->data, p, len);
1.194 + //else log error- cannot malloc
1.195 +
1.196 + ret->bytes->length = len;
1.197 + ret->bytes->max = len;
1.198 +
1.199 + ret->hash = 0; // for now filling zero. Not sure.
1.200 +
1.201 + CleanupStack::PopAndDestroy(2); // Asn1Seq, octetData
1.202 +
1.203 + return ret;
1.204 +}
1.205 +
1.206 +
1.207 +// return the length of the encoded sequence
1.208 +TInt CX509_Initializer::Fill_X509_NAME_ENTRYL(X509_NAME * name, const TDesC8& aBinaryData)
1.209 +{
1.210 + TInt aPos = 0;
1.211 + TASN1DecGeneric dec(aBinaryData.Right(aBinaryData.Length() - aPos));
1.212 + dec.InitL();
1.213 +
1.214 + TInt end = aPos + dec.LengthDER();
1.215 + aPos += dec.LengthDERHeader();
1.216 +
1.217 + if (dec.Tag() != EASN1Sequence)
1.218 + {
1.219 + User::Leave(KErrArgument);
1.220 + }
1.221 + while (aPos < end)
1.222 + {
1.223 + TASN1DecGeneric rdn(aBinaryData.Right(aBinaryData.Length() - aPos));
1.224 + rdn.InitL();
1.225 + if (rdn.Tag() != EASN1Set)
1.226 + {
1.227 + User::Leave(KErrArgument);
1.228 + }
1.229 + TInt rdnEnd = rdn.LengthDER();
1.230 + TInt rdnPos = rdn.LengthDERHeader();//add on header
1.231 + while (rdnPos < rdnEnd)
1.232 + {
1.233 + const TDesC8& TypeValEnc = rdn.Encoding();
1.234 +
1.235 + TASN1DecGeneric dec(TypeValEnc.Right(TypeValEnc.Length() - rdnPos));
1.236 + dec.InitL();
1.237 + TInt tvend = rdnPos + dec.LengthDER();
1.238 + rdnPos += dec.LengthDERHeader();
1.239 +
1.240 + //first element must be the id
1.241 + TASN1DecObjectIdentifier encOID;
1.242 + //iType = encOID.DecodeDERL(TypeValEnc, rdnPos);
1.243 + TASN1DecGeneric first(TypeValEnc.Right(TypeValEnc.Length() - rdnPos));
1.244 + first.InitL();
1.245 + rdnPos += first.LengthDER();
1.246 + if (first.Tag() != EASN1ObjectIdentifier)
1.247 + {
1.248 + User::Leave(KErrArgument);
1.249 + }
1.250 +
1.251 + const TDesC8& type = first.GetContentDER();
1.252 + char * ch_type = (char *)type.Ptr();
1.253 +
1.254 + //second is the data
1.255 + TASN1DecGeneric second(TypeValEnc.Right(TypeValEnc.Length() - rdnPos));
1.256 + second.InitL();
1.257 + rdnPos += second.LengthDER();
1.258 +
1.259 + const TDesC8& value = second.GetContentDER();
1.260 + char * ch_value = (char *)value.Ptr();
1.261 +
1.262 + X509_NAME_ENTRY* new_entry = CreateX509_NAME_ENTRY(ch_type,first.LengthDERContent(), ch_value, second.LengthDERContent(), second.Tag());
1.263 +
1.264 + X509_NAME_add_entry(name, new_entry, -1, 0);
1.265 +
1.266 + //we can free this, since add_entry makes a copy and adds
1.267 + X509_NAME_ENTRY_free(new_entry);
1.268 + //
1.269 +
1.270 + if (rdnPos != tvend)
1.271 + {
1.272 + User::Leave(KErrArgument);
1.273 + }
1.274 +
1.275 + }
1.276 + aPos += rdnEnd;
1.277 + }
1.278 + if (aPos != end)
1.279 + {
1.280 + User::Leave(KErrArgument);
1.281 + }
1.282 + return end;
1.283 +}
1.284 +
1.285 +
1.286 +X509_NAME_ENTRY * CX509_Initializer::CreateX509_NAME_ENTRY(char* type, int typeLen, char * value, int valueLen, int stringType)
1.287 +{
1.288 + X509_NAME_ENTRY * newEntry = X509_NAME_ENTRY_new();
1.289 +
1.290 + newEntry->object->length = typeLen;
1.291 + newEntry->object->data = (unsigned char *)OPENSSL_malloc(typeLen);
1.292 + if(newEntry->object->data)
1.293 + memcpy(newEntry->object->data, type, typeLen);
1.294 + //else log error- cannot malloc
1.295 +
1.296 + ASN1_STRING_free(newEntry->value);
1.297 + newEntry->value = CreateASN1_STRING(valueLen, stringType, (unsigned char* )value, 0);
1.298 +
1.299 + newEntry->object->flags |= ASN1_OBJECT_FLAG_DYNAMIC_DATA; // so that X509_NAME_ENTRY_free() frees all internally allocated data
1.300 +
1.301 + return newEntry;
1.302 +
1.303 +}
1.304 +
1.305 +
1.306 +X509_VAL * CX509_Initializer::CreateX509_VAL(CX509Certificate* X509Cert)
1.307 +{
1.308 + X509_VAL * ret = X509_VAL_new();
1.309 +
1.310 + const CValidityPeriod& val = X509Cert->ValidityPeriod();
1.311 +
1.312 + TBuf8<KCertMaxBuffer> numBuffer8;
1.313 + char* numPtr = (char*)numBuffer8.PtrZ();
1.314 +
1.315 + //start date (notBefore)
1.316 + TDateTime dt = val.Start().DateTime();
1.317 +
1.318 + numBuffer8.AppendNum(dt.Year());
1.319 + if(numBuffer8.Length() > 2)
1.320 + numBuffer8.Delete(0, numBuffer8.Length() - 2);
1.321 +
1.322 + _LIT8(KCertTimeStampFormat, "%02d%02d%02d%02d%02dZ");
1.323 + numBuffer8.AppendFormat(KCertTimeStampFormat,dt.Month()+1,dt.Day()+1,dt.Hour(),dt.Minute(),dt.Second()); //Month and Day - offset from zero, so add 1
1.324 + numPtr[13]='\0';
1.325 +
1.326 + ASN1_STRING_free(ret->notBefore);
1.327 + ret->notBefore = CreateASN1_STRING(13,V_ASN1_UTCTIME,(unsigned char *)numPtr,0);
1.328 +
1.329 + //finish date (notAfter)
1.330 + dt = val.Finish().DateTime();
1.331 +
1.332 + numBuffer8.Zero();
1.333 + numBuffer8.AppendNum(dt.Year());
1.334 + if(numBuffer8.Length() > 2)
1.335 + numBuffer8.Delete(0, numBuffer8.Length() - 2);
1.336 +
1.337 + numBuffer8.AppendFormat(KCertTimeStampFormat,dt.Month()+1,dt.Day()+1,dt.Hour(),dt.Minute(),dt.Second()); //Month and Day - offset from zero, so add 1
1.338 + numPtr[13]='\0';
1.339 +
1.340 + ASN1_STRING_free(ret->notAfter);
1.341 + ret->notAfter = CreateASN1_STRING(13,V_ASN1_UTCTIME,(unsigned char *)numPtr,0);
1.342 +
1.343 + return ret;
1.344 +
1.345 +}
1.346 +
1.347 +
1.348 +
1.349 +ASN1_STRING* CX509_Initializer::CreateASN1_STRING(int len, int type, unsigned char* data, long flags)
1.350 +{
1.351 + ASN1_STRING* ret = ASN1_STRING_new();
1.352 + ret->length = len;
1.353 + ret->type = type;
1.354 + if(data!=NULL)
1.355 + {
1.356 + ret->data = (unsigned char *)OPENSSL_malloc(len);
1.357 + if(ret->data)
1.358 + memcpy(ret->data,data,len);
1.359 + //else log error- cannot malloc
1.360 + }
1.361 + else
1.362 + ret->data = NULL;
1.363 +
1.364 + ret->flags |= flags;
1.365 + return ret;
1.366 +}
1.367 +
1.368 +
1.369 +
1.370 +X509_PUBKEY* CX509_Initializer::CreateX509_PUBKEYL(CX509Certificate* X509Cert)
1.371 +{
1.372 + X509_PUBKEY* ret = X509_PUBKEY_new();
1.373 +
1.374 +//algor
1.375 + const TPtrC8* ptr = X509Cert->DataElementEncoding(CX509Certificate::ESubjectPublicKeyInfo);
1.376 +
1.377 + TInt aPos = 0;
1.378 + TASN1DecGeneric dec(ptr->Right(ptr->Length() - aPos));
1.379 + dec.InitL();
1.380 +
1.381 + TInt end = aPos + dec.LengthDER();
1.382 + aPos += dec.LengthDERHeader();
1.383 +
1.384 + if (dec.Tag() != EASN1Sequence)
1.385 + User::Leave(KErrArgument);
1.386 +
1.387 + if (aPos < end)
1.388 + {
1.389 + TASN1DecGeneric rdn(ptr->Right(ptr->Length() - aPos));
1.390 + rdn.InitL();
1.391 + TPtrC8 newPtr = rdn.Encoding();
1.392 +
1.393 + X509_ALGOR_free(ret->algor); // free the one allocated by X509_PUBKEY_new
1.394 + ret->algor = CreateX509_ALGORL(&newPtr);
1.395 + }
1.396 +
1.397 +//public_key
1.398 + const CSubjectPublicKeyInfo& pubkey = X509Cert->PublicKey();
1.399 + const TPtrC8 keyDat = pubkey.KeyData();
1.400 +
1.401 + ASN1_BIT_STRING_free(ret->public_key);
1.402 + ret->public_key = CreateASN1_STRING(keyDat.Size(),V_ASN1_BIT_STRING,(unsigned char*)keyDat.Ptr(),0);
1.403 +
1.404 +//pkey
1.405 + ret->pkey = NULL; // we need not create this. Will be created later. Used to cache the computed data
1.406 +
1.407 + return ret;
1.408 +}
1.409 +
1.410 +
1.411 +
1.412 +
1.413 +STACK_OF(X509_EXTENSION)* CX509_Initializer::CreateSTACKOF_X509_EXTENSIONL(CX509Certificate* X509Cert)
1.414 +{
1.415 + //STACK_OF(X509_EXTENSION) * ret = sk_X509_EXTENSION_new_null();
1.416 + STACK_OF(X509_EXTENSION) * ret = NULL;
1.417 +
1.418 + const TPtrC8* ptr = X509Cert->DataElementEncoding(CX509Certificate::EExtensionList);
1.419 +
1.420 + const CArrayPtrFlat<CX509CertExtension>& extlist = X509Cert->Extensions();
1.421 +
1.422 + TASN1DecSequence encSeq;
1.423 + TInt pos = 0;
1.424 +
1.425 + if(ptr != NULL) //There is an extension list
1.426 + {
1.427 + TASN1DecGeneric dec((TDesC8 &)*ptr);
1.428 + ret = sk_X509_EXTENSION_new_null();
1.429 + dec.InitL();
1.430 +
1.431 + CArrayPtrFlat<TASN1DecGeneric>* seq = encSeq.DecodeDERLC( dec.GetContentDER(), pos);
1.432 +
1.433 + TInt count = seq->Count(); // no of extensions in the ext list
1.434 + for (TInt i = 0; i < count; i++)
1.435 + {
1.436 +
1.437 + X509_EXTENSION* ext = X509_EXTENSION_new();
1.438 +
1.439 + ext->object = ASN1_OBJECT_new();
1.440 +
1.441 + TASN1DecGeneric* gen = seq->At(i);
1.442 + TASN1DecGeneric oid(seq->At(i)->GetContentDER());
1.443 + oid.InitL();
1.444 +
1.445 + const TDesC8& ext_obj_data = oid.GetContentDER();
1.446 + char * ch_ext_obj_data = (char *)ext_obj_data.Ptr();
1.447 +
1.448 + ext->object->length = oid.LengthDERContent();
1.449 + ext->object->data = (unsigned char *)OPENSSL_malloc(ext->object->length);
1.450 + if(ext->object->data)
1.451 + memcpy(ext->object->data, ch_ext_obj_data, ext->object->length);
1.452 + //else log error- cannot malloc
1.453 +
1.454 + ext->object->flags |= ASN1_OBJECT_FLAG_DYNAMIC_DATA; // so that X509_free() frees all internally allocated data
1.455 +
1.456 + if(extlist.At(i)->Critical())
1.457 + ext->critical = extlist.At(i)->Critical();
1.458 +
1.459 + const TPtrC8 data = extlist.At(i)->Data();
1.460 + TASN1DecGeneric value(data);
1.461 + value.InitL();
1.462 +
1.463 + const TDesC8& ext_value = value.GetContentDER();
1.464 + char * ch_ext_value = (char *)ext_value.Ptr();
1.465 + ASN1_STRING_free(ext->value);
1.466 + ext->value = CreateASN1_STRING(value.LengthDERContent(), V_ASN1_OCTET_STRING, (unsigned char *)ch_ext_value, 0);
1.467 +
1.468 + sk_X509_EXTENSION_push(ret,ext);
1.469 +
1.470 + }
1.471 +
1.472 + CleanupStack::PopAndDestroy();// seq
1.473 + }
1.474 +
1.475 + return ret;
1.476 +}
1.477 +