1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/security/cryptoservices/asnpkcs/source/asnpkcs8enc.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,365 @@
1.4 +/*
1.5 +* Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies).
1.6 +* All rights reserved.
1.7 +* This component and the accompanying materials are made available
1.8 +* under the terms of the License "Eclipse Public License v1.0"
1.9 +* which accompanies this distribution, and is available
1.10 +* at the URL "http://www.eclipse.org/legal/epl-v10.html".
1.11 +*
1.12 +* Initial Contributors:
1.13 +* Nokia Corporation - initial contribution.
1.14 +*
1.15 +* Contributors:
1.16 +*
1.17 +* Description:
1.18 +*
1.19 +*/
1.20 +
1.21 +
1.22 +#include <asn1enc.h>
1.23 +#include <pbe.h>
1.24 +#include <asymmetrickeys.h>
1.25 +#include <bigint.h>
1.26 +#include "asnpkcs.h"
1.27 +
1.28 +const TInt KPkcs8Version = 0; // PKCS#8 version 0
1.29 +const TInt KPkcs8RSATwoPrime = 0; // We support only two-prime RSA.
1.30 +
1.31 +
1.32 +/*static*/ void TASN1EncPKCS8::AddAttributesL(CASN1EncSequence& aSeq, const TDesC8& aAttribute)
1.33 + {
1.34 + if (aAttribute != KNullDesC8)
1.35 + {
1.36 + CASN1EncEncoding* encoded = CASN1EncEncoding::NewLC(aAttribute);
1.37 + aSeq.AddAndPopChildL(encoded);
1.38 + }
1.39 + }
1.40 +
1.41 +/**
1.42 + * Given a ASN1 sequence representing a private key and a CPBEncryptor object,
1.43 + * it returns an ASN1 octet string containing the key sequence encrypted by
1.44 + * the given encryptor.
1.45 + *
1.46 + * @param aKeySeq The key sequence to be encrypted.
1.47 + * @param aEncryptor The CPBEncryptor object used to encrypt the given key.
1.48 + * @return An ASN1 octet string containing the encrypted key.
1.49 + */
1.50 +/*static*/ CASN1EncOctetString* TASN1EncPKCS8::EncryptKeySequenceL(CASN1EncSequence& aKeySeq, CPBEncryptor& aEncryptor)
1.51 + {
1.52 + // Make an octet string of the key sequence
1.53 + TUint seqLen = aKeySeq.LengthDER();
1.54 + HBufC8* octetData = HBufC8::NewMaxLC(seqLen);
1.55 + TPtr8 oct(octetData->Des());
1.56 + oct.FillZ();
1.57 + TUint writePos = 0;
1.58 + aKeySeq.WriteDERL(oct, writePos);
1.59 +
1.60 + // Encrypt it
1.61 + HBufC8* encryptedData = HBufC8::NewLC(aEncryptor.MaxFinalOutputLength(seqLen));
1.62 + TPtr8 encrypted(encryptedData->Des());
1.63 +
1.64 + aEncryptor.ProcessFinalL(*octetData, encrypted);
1.65 +
1.66 + CASN1EncOctetString* octet = CASN1EncOctetString::NewL(encrypted);
1.67 +
1.68 + CleanupStack::PopAndDestroy(2, octetData); // encryptedData, octetData
1.69 +
1.70 + return octet;
1.71 + }
1.72 +
1.73 +
1.74 +/*static*/ CASN1EncOctetString* TASN1EncPKCS8::ElementToOctetL(CASN1EncBase& aAsnElement)
1.75 + {
1.76 + // Make an octet string from the structure
1.77 + HBufC8* octetData = HBufC8::NewMaxLC(aAsnElement.LengthDER());
1.78 + TPtr8 oct(octetData->Des());
1.79 + oct.FillZ();
1.80 +
1.81 + TUint writePos = 0;
1.82 + aAsnElement.WriteDERL(oct, writePos);
1.83 +
1.84 + CASN1EncOctetString* octet = CASN1EncOctetString::NewL(oct);
1.85 + CleanupStack::PopAndDestroy(octetData);
1.86 + return octet;
1.87 + }
1.88 +
1.89 +
1.90 +/*static*/ CASN1EncSequence* TASN1EncPKCS8::EncryptedSequenceL(CASN1EncSequence& aPrivateKeySequence,
1.91 + CPBEncryptor& aEncryptor, CPBEncryptParms& aData)
1.92 + {
1.93 + // Main ASN1 sequence
1.94 + CASN1EncSequence* seq = CASN1EncSequence::NewLC();
1.95 +
1.96 + // PKCS#5 PBE sequence
1.97 + CASN1EncSequence* pkcs5Seq = TASN1EncPKCS5::EncodeDERL(aData);
1.98 +
1.99 + CleanupStack::PushL(pkcs5Seq);
1.100 + seq->AddAndPopChildL(pkcs5Seq);
1.101 +
1.102 + // Encrypt the Private Key Sequence
1.103 + CASN1EncOctetString* octet = EncryptKeySequenceL(aPrivateKeySequence, aEncryptor);
1.104 + CleanupStack::PushL(octet);
1.105 + seq->AddAndPopChildL(octet);
1.106 +
1.107 + CleanupStack::Pop(seq);
1.108 +
1.109 + return seq;
1.110 + }
1.111 +
1.112 +
1.113 +/*static*/ const RInteger TASN1EncPKCS8::CalculateRSAPrivExpL(const CRSAPrivateKeyCRT& aPrivateKey, const CRSAPublicKey& aPublicKey)
1.114 + {
1.115 + const TInteger& e = aPublicKey.E();
1.116 +
1.117 + RInteger pTemp = RInteger::NewL(aPrivateKey.P());
1.118 + CleanupStack::PushL(pTemp);
1.119 + RInteger qTemp = RInteger::NewL(aPrivateKey.Q());
1.120 + CleanupStack::PushL(qTemp);
1.121 +
1.122 + --pTemp;
1.123 + --qTemp;
1.124 +
1.125 + //phi = (p-1)(q-1)
1.126 + RInteger phi = pTemp.TimesL(qTemp);
1.127 +
1.128 + CleanupStack::PopAndDestroy(2, &pTemp); // qTemp, pTemp
1.129 + CleanupStack::PushL(phi);
1.130 +
1.131 + //d = e^(-1) mod ((p-1)(q-1))
1.132 + RInteger d = e.InverseModL(phi);
1.133 + CleanupStack::PopAndDestroy(&phi);
1.134 + return d;
1.135 + }
1.136 +
1.137 +/**
1.138 + * Encodes the given private key using the pkcs#8 standard.
1.139 + *
1.140 + * The returned ASN1 sequence respects the following grammar:
1.141 + *
1.142 + * PrivateKeyInfo ::= SEQUENCE {
1.143 + * version Version,
1.144 + * privateKeyAlgorithm PrivateKeyAlgorithmIdentifier,
1.145 + * privateKey PrivateKey,
1.146 + * attributes [0] IMPLICIT Attributes OPTIONAL }
1.147 + *
1.148 + * Version ::= INTEGER
1.149 + * PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier
1.150 + * PrivateKey ::= OCTET STRING
1.151 + * Attributes ::= SET OF Attribute
1.152 + *
1.153 + *
1.154 + * @param aKeyPair A key pair containing the private key we wish to encode.
1.155 + * @return A CASN1EncSequence encoding the private key. The sequence
1.156 + * follows the grammar specified above.
1.157 + * @internalComponent
1.158 + * @released
1.159 + */
1.160 +/*static*/ EXPORT_C CASN1EncSequence* TASN1EncPKCS8::EncodeL(const CRSAPrivateKeyCRT& aPrivateKey,
1.161 + const CRSAPublicKey& aPublicKey,
1.162 + const TDesC8& aAttributes)
1.163 + {
1.164 + // Main ASN1 sequence
1.165 + CASN1EncSequence* seq = CASN1EncSequence::NewLC();
1.166 +
1.167 + // Start with PKCS#8 header
1.168 + CASN1EncInt* version = CASN1EncInt::NewLC(KPkcs8Version);
1.169 + seq->AddAndPopChildL(version);
1.170 +
1.171 + // Algorithm sequence
1.172 + CASN1EncSequence* algSeq = CASN1EncSequence::NewLC();
1.173 +
1.174 + CASN1EncObjectIdentifier* oid = CASN1EncObjectIdentifier::NewLC(KRSA);
1.175 + algSeq->AddAndPopChildL(oid);
1.176 +
1.177 + // No other parameters
1.178 + CASN1EncNull* nullparams = CASN1EncNull::NewLC();
1.179 + algSeq->AddAndPopChildL(nullparams);
1.180 +
1.181 + seq->AddAndPopChildL(algSeq);
1.182 +
1.183 + // The actual private key sequence
1.184 + CASN1EncSequence* keySeq = CASN1EncSequence::NewLC();
1.185 +
1.186 + // TASN1DecGeneric* versionData = theData->operator[](seqIndex);
1.187 + CASN1EncInt* rsaVersion = CASN1EncInt::NewLC(KPkcs8RSATwoPrime);
1.188 + keySeq->AddAndPopChildL(rsaVersion);
1.189 +
1.190 + // The modulus
1.191 + const TInteger& modulus = aPrivateKey.N();
1.192 + CASN1EncBigInt* mod = CASN1EncBigInt::NewLC(modulus);
1.193 + keySeq->AddAndPopChildL(mod);
1.194 +
1.195 + // The public exponent
1.196 + const TInteger& e = aPublicKey.E();
1.197 + CASN1EncBigInt* publicExp = CASN1EncBigInt::NewLC(e);
1.198 + keySeq->AddAndPopChildL(publicExp);
1.199 +
1.200 + // The private exponent
1.201 + RInteger d = CalculateRSAPrivExpL(aPrivateKey, aPublicKey);
1.202 + CleanupStack::PushL(d);
1.203 +
1.204 + CASN1EncBigInt* privateExp = CASN1EncBigInt::NewLC(d);
1.205 +
1.206 + keySeq->AddAndPopChildL(privateExp);
1.207 + CleanupStack::PopAndDestroy(&d); // RSA Private Exponent
1.208 +
1.209 + // The prime1
1.210 + const TInteger& p = aPrivateKey.P();
1.211 + CASN1EncBigInt* prime1 = CASN1EncBigInt::NewLC(p);
1.212 + keySeq->AddAndPopChildL(prime1);
1.213 +
1.214 + // The prime2
1.215 + const TInteger& q = aPrivateKey.Q();
1.216 + CASN1EncBigInt* prime2 = CASN1EncBigInt::NewLC(q);
1.217 + keySeq->AddAndPopChildL(prime2);
1.218 +
1.219 + // The exponent 1
1.220 + const TInteger& dp = aPrivateKey.DP();
1.221 + CASN1EncBigInt* theExp1 = CASN1EncBigInt::NewLC(dp);
1.222 + keySeq->AddAndPopChildL(theExp1);
1.223 +
1.224 + // The exponent 2
1.225 + const TInteger& dq = aPrivateKey.DQ();
1.226 + CASN1EncBigInt* theExp2 = CASN1EncBigInt::NewLC(dq);
1.227 + keySeq->AddAndPopChildL(theExp2);
1.228 +
1.229 + // The coefficient
1.230 + const TInteger& coeff = aPrivateKey.QInv();
1.231 + CASN1EncBigInt* coefficient = CASN1EncBigInt::NewLC(coeff);
1.232 + keySeq->AddAndPopChildL(coefficient);
1.233 +
1.234 + CASN1EncOctetString* octet = ElementToOctetL(*keySeq);
1.235 + CleanupStack::PushL(octet);
1.236 +
1.237 + // Now add the octet of the key sequence to the sequence
1.238 + seq->AddAndPopChildL(octet);
1.239 +
1.240 + CleanupStack::PopAndDestroy(keySeq);
1.241 +
1.242 + AddAttributesL(*seq, aAttributes);
1.243 +
1.244 + CleanupStack::Pop(seq);
1.245 +
1.246 + return seq;
1.247 + }
1.248 +
1.249 +/**
1.250 + * Encodes an RSA key in encrypted format.
1.251 + *
1.252 + * @param aPrivateKey The private key to be encoded (must be in CRT format)
1.253 + * @param aPublicKey The corresponding public key.
1.254 + * @param aEncryptor The object used to encrypt the data.
1.255 + * @param aData The encryption parameters of the given encryptor.
1.256 + * These parameters are stored in the resulting sequence.
1.257 + *
1.258 + * @return An ASN1 Sequence encoding the encrypted key.
1.259 + */
1.260 +/*static*/ EXPORT_C CASN1EncSequence* TASN1EncPKCS8::EncodeEncryptedL(const CRSAPrivateKeyCRT& aPrivateKey, const CRSAPublicKey& aPublicKey,
1.261 + CPBEncryptor& aEncryptor, CPBEncryptParms& aData, const TDesC8& aAttributes)
1.262 + {
1.263 + // Now generate a PrivateKeyInfo type
1.264 + CASN1EncSequence* privKeySeq = EncodeL(aPrivateKey, aPublicKey, aAttributes);
1.265 + CleanupStack::PushL(privKeySeq);
1.266 +
1.267 + CASN1EncSequence* seq = EncryptedSequenceL(*privKeySeq, aEncryptor, aData);
1.268 +
1.269 + CleanupStack::PopAndDestroy(privKeySeq);
1.270 +
1.271 + return seq;
1.272 + }
1.273 +
1.274 +
1.275 +/**
1.276 + * Return the ASN1 PKCS#8 encoding of a DSA private key.
1.277 + *
1.278 + * The private key syntax for this key type is defined in
1.279 + * the PKCS#11 document.
1.280 + *
1.281 + * @param aPrivateKey The private key to be encoded (must be in CRT format)
1.282 + *
1.283 + * @return An ASN1 Sequence encoding the key.
1.284 + */
1.285 +/*static*/ EXPORT_C CASN1EncSequence* TASN1EncPKCS8::EncodeL(const CDSAPrivateKey& aPrivateKey,
1.286 + const TDesC8& aAttributes)
1.287 + {
1.288 + // Main ASN1 sequence
1.289 + CASN1EncSequence* seq = CASN1EncSequence::NewLC();
1.290 +
1.291 + // version
1.292 + CASN1EncInt* version = CASN1EncInt::NewLC(KPkcs8Version);
1.293 + seq->AddAndPopChildL(version);
1.294 +
1.295 + // Algorithm sequence
1.296 + CASN1EncSequence* algSeq = CASN1EncSequence::NewLC();
1.297 +
1.298 + CASN1EncObjectIdentifier* oid = CASN1EncObjectIdentifier::NewLC(KDSA);
1.299 + algSeq->AddAndPopChildL(oid);
1.300 +
1.301 + seq->AddAndPopChildL(algSeq);
1.302 +
1.303 + // DSA Parameters
1.304 + CASN1EncSequence* keySeq = CASN1EncSequence::NewLC();
1.305 +
1.306 + // The modulus P
1.307 + const TInteger& modulus1 = aPrivateKey.P();
1.308 +
1.309 + CASN1EncBigInt* mod = CASN1EncBigInt::NewLC(modulus1);
1.310 + keySeq->AddAndPopChildL(mod);
1.311 +
1.312 + // The modulus Q
1.313 + const TInteger& modulus2 = aPrivateKey.Q();
1.314 +
1.315 + CASN1EncBigInt* mod2 = CASN1EncBigInt::NewLC(modulus2);
1.316 + keySeq->AddAndPopChildL(mod2);
1.317 +
1.318 + // The base G
1.319 + const TInteger& base = aPrivateKey.G();
1.320 +
1.321 + CASN1EncBigInt* b = CASN1EncBigInt::NewLC(base);
1.322 + keySeq->AddAndPopChildL(b);
1.323 +
1.324 + algSeq->AddAndPopChildL(keySeq);
1.325 +
1.326 + // The private key X
1.327 + const TInteger& priv = aPrivateKey.X();
1.328 + CASN1EncBigInt* x = CASN1EncBigInt::NewLC(priv);
1.329 +
1.330 + CASN1EncOctetString* octet = ElementToOctetL(*x);
1.331 +
1.332 + CleanupStack::PopAndDestroy(x);
1.333 + CleanupStack::PushL(octet);
1.334 +
1.335 + seq->AddAndPopChildL(octet);
1.336 +
1.337 + AddAttributesL(*seq, aAttributes);
1.338 +
1.339 + CleanupStack::Pop(seq);
1.340 +
1.341 + return seq;
1.342 + }
1.343 +
1.344 +
1.345 +/**
1.346 + * Encodes a DSA key in encrypted format.
1.347 + *
1.348 + * @param aPrivateKey The private key to be encoded.
1.349 + * @param aEncryptor The object used to encrypt the data.
1.350 + * @param aData The encryption parameters of the given encryptor.
1.351 + * These parameters are stored in the resulting sequence.
1.352 + *
1.353 + * @return An ASN1 Sequence encoding the encrypted key.
1.354 + */
1.355 +/*static*/ EXPORT_C CASN1EncSequence* TASN1EncPKCS8::EncodeEncryptedL(const CDSAPrivateKey& aPrivateKey, CPBEncryptor& aEncryptor,
1.356 + CPBEncryptParms& aData, const TDesC8& aAttributes)
1.357 + {
1.358 + // Now generate a PrivateKeyInfo type
1.359 + CASN1EncSequence* privKeySeq = EncodeL(aPrivateKey, aAttributes);
1.360 + CleanupStack::PushL(privKeySeq);
1.361 +
1.362 + CASN1EncSequence* seq = EncryptedSequenceL(*privKeySeq, aEncryptor, aData);
1.363 +
1.364 + CleanupStack::PopAndDestroy(privKeySeq);
1.365 +
1.366 + return seq;
1.367 + }
1.368 +