First public contribution.
2 * Copyright (c) 2002-2009 Nokia Corporation and/or its subsidiary(-ies).
4 * This component and the accompanying materials are made available
5 * under the terms of the License "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".
9 * Initial Contributors:
10 * Nokia Corporation - initial contribution.
15 * Implements PKCS#10 certificate request class.
27 #include <pkcs10attr.h>
28 #include "keyhelper.h"
29 #include <mctkeystoreuids.h>
31 void Panic(TInt aError)
33 _LIT(KCategory, "PKCS10");
34 User::Panic(KCategory, aError);
37 // CPKCS10Request Class Implementation
39 CPKCS10Request::CPKCS10Request(const CX500DistinguishedName* aDN,
40 const CCTKeyInfo* aKeyInfo,
41 CPKCS10Attributes* aAttr) :
42 CActive(EPriorityNormal),
48 CActiveScheduler::Add(this);
51 EXPORT_C CPKCS10Request* CPKCS10Request::NewLC(const CX500DistinguishedName& aDN,
52 const CCTKeyInfo& aKeyInfo,
53 CPKCS10Attributes* aAttr/* = NULL*/)
55 // Sanity Check the input parameters
58 User::Leave(KErrArgument);
61 if (&aKeyInfo == NULL)
63 User::Leave(KErrArgument);
66 CPKCS10Request* self = new (ELeave) CPKCS10Request(&aDN, &aKeyInfo, aAttr);
67 CleanupStack::PushL(self);
71 EXPORT_C CPKCS10Request* CPKCS10Request::NewL(const CX500DistinguishedName& aDN,
72 const CCTKeyInfo& aKeyInfo,
73 CPKCS10Attributes* aAttr/* = NULL*/)
75 CPKCS10Request* self = NewLC(aDN, aKeyInfo, aAttr);
76 CleanupStack::Pop(self);
80 EXPORT_C CPKCS10Request::~CPKCS10Request()
87 void CPKCS10Request::Reset()
103 EXPORT_C void CPKCS10Request::SetDistinguishedNameL(const CX500DistinguishedName& aDN)
108 User::Leave(KErrArgument);
113 EXPORT_C void CPKCS10Request::SetKeyInfoL(const CCTKeyInfo& aKeyInfo)
116 if (&aKeyInfo == NULL)
118 User::Leave(KErrArgument);
120 iKeyInfo = &aKeyInfo;
123 EXPORT_C void CPKCS10Request::SetAttributes(CPKCS10Attributes* aAttr)
129 EXPORT_C void CPKCS10Request::SetDigestAlgL(TAlgorithmId aDigestId)
131 if (aDigestId != EMD2 && aDigestId != EMD5 && aDigestId != ESHA1)
133 User::Leave(KErrArgument);
135 if (iKeyInfo->Algorithm() == CCTKeyInfo::EDSA && aDigestId != ESHA1)
137 User::Leave(KErrArgument);
139 iDigestId = aDigestId;
142 EXPORT_C void CPKCS10Request::CreateEncoding(HBufC8*& aResult, TRequestStatus& aStatus)
144 ASSERT(iState == EIdle);
145 iClientStatus = &aStatus;
148 aStatus = KRequestPending;
149 iState = EInitialize;
151 TRequestStatus* status = &iStatus;
152 User::RequestComplete(status, KErrNone);
155 TInt CPKCS10Request::RunError(TInt aErr)
157 User::RequestComplete(iClientStatus, aErr);
162 void CPKCS10Request::DoCancel()
167 iKeyInfo->Token().CancelGetInterface();
171 iKeyStore->CancelExportPublic();
175 iKeyHelper->CancelOpenSigner();
179 iKeyHelper->CancelSignDigest();
183 // do nothing, keep compiler happy
188 User::RequestComplete(iClientStatus, KErrCancel);
193 void CPKCS10Request::RunL()
195 User::LeaveIfError(iStatus.Int());
200 // Get keystore interface
203 iKeyStore->Release();
206 iKeyInfo->Token().GetInterface(TUid::Uid(KInterfaceKeyStore),
207 *reinterpret_cast<MCTTokenInterface**>(&iKeyStore),
209 iState = EGetKeyStore;
214 // Fetch the public key
216 iKeyStore->ExportPublic(*iKeyInfo, iExportedKey, iStatus);
217 iState = EGetPublicKey;
222 // Create key helper object
224 iKeyHelper = CPKCS10KeyHelper::CreateKeyHelperL(*iKeyStore, *iKeyInfo, *iExportedKey, iDigestId);
227 // Open signing object
228 iKeyHelper->OpenSigner(iStatus);
229 iState = EOpenSigner;
236 CMessageDigest* digest = NULL;
240 digest = CMD2::NewL();
243 digest = CMD5::NewL();
246 digest = CSHA1::NewL();
251 CleanupStack::PushL(digest);
253 // Hash data and sign
254 digest->Update(*iTBSData);
256 iKeyHelper->SignDigestL(digest->Final(), iStatus);
257 CleanupStack::PopAndDestroy(digest); // keystore copies data to be signed
264 CreateFinalEncodingL();
273 CASN1EncBase* CPKCS10Request::MakeAttrEncLC()
277 CASN1EncBase* result = iAttributes->TakeEncodingLC();
284 CASN1EncSequence* contextSpecific = CASN1EncSequence::NewLC();
285 contextSpecific->SetTag(0);
286 return contextSpecific;
290 CASN1EncSequence* CPKCS10Request::MakeCertRequestInfoEncLC()
292 // Top-level sequence contains distinguished name and other
293 // stuff. This is what gets signed with the entity's private key.
294 CASN1EncSequence* certRequestInfo = CASN1EncSequence::NewLC();
296 // Encode version number, which is 0.
297 CASN1EncInt* version = CASN1EncInt::NewLC(0);
298 certRequestInfo->AddAndPopChildL(version);
300 // Encode distinguished name.
301 CASN1EncBase* distinguishedName = iDN->EncodeASN1LC();
302 certRequestInfo->AddAndPopChildL(distinguishedName);
304 // Encode SubjectPublicKeyInfo.
305 CASN1EncBase* subjectPubKeyInfo = iKeyHelper->EncodeKeyLC();
306 certRequestInfo->AddAndPopChildL(subjectPubKeyInfo);
308 // Encode attributes, if any.
309 CASN1EncBase* attr = MakeAttrEncLC();
310 certRequestInfo->AddAndPopChildL(attr);
312 return certRequestInfo;
315 void CPKCS10Request::EncodeTBSDataL()
317 // The data we provide for signing is the certRequestInfo object.
318 CASN1EncBase* certRequestInfo = MakeCertRequestInfoEncLC();
319 // Write DER of it to the buffer.
321 iTBSData = HBufC8::NewMaxL(certRequestInfo->LengthDER());
322 TPtr8 dataPtr = iTBSData->Des();
324 certRequestInfo->WriteDERL(dataPtr, pos);
325 CleanupStack::PopAndDestroy(certRequestInfo);
328 void CPKCS10Request::CreateFinalEncodingL()
330 // the root sequence contains all other components of a X509 signed object
331 CASN1EncSequence* root = CASN1EncSequence::NewLC();
333 // wrap data to be signed in a sequence and add it to the root
334 CASN1EncEncoding* encenc = CASN1EncEncoding::NewLC(*iTBSData);
335 root->AddAndPopChildL(encenc);
337 // encode signature algorithm and parameters and add them to the root
338 CASN1EncSequence* sigalg = iKeyHelper->EncodeSignatureAlgorithmLC();
339 root->AddAndPopChildL(sigalg);
341 // Create ASN.1 bit string from the signature
342 CASN1EncBitString* encSig = iKeyHelper->EncodeSignatureLC();
343 root->AddAndPopChildL(encSig);
345 // encode the object in a DER encoding
346 HBufC8* der = HBufC8::NewMaxLC(root->LengthDER());
347 TPtr8 pder(der->Des());
349 root->WriteDERL(pder, pos);
350 CleanupStack::Pop(der);
351 CleanupStack::PopAndDestroy(root);
354 User::RequestComplete(iClientStatus, KErrNone);