os/security/cryptoservices/certificateandkeymgmt/x509/x509keysRSA.cpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
sl@0
     1
/*
sl@0
     2
* Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies).
sl@0
     3
* All rights reserved.
sl@0
     4
* This component and the accompanying materials are made available
sl@0
     5
* under the terms of the License "Eclipse Public License v1.0"
sl@0
     6
* which accompanies this distribution, and is available
sl@0
     7
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
sl@0
     8
*
sl@0
     9
* Initial Contributors:
sl@0
    10
* Nokia Corporation - initial contribution.
sl@0
    11
*
sl@0
    12
* Contributors:
sl@0
    13
*
sl@0
    14
* Description: 
sl@0
    15
*
sl@0
    16
*/
sl@0
    17
sl@0
    18
sl@0
    19
#include <x509keys.h>
sl@0
    20
#include <asn1dec.h>
sl@0
    21
#include <asn1enc.h>
sl@0
    22
#include <x509cert.h>
sl@0
    23
#include "x509keyencoder.h"
sl@0
    24
sl@0
    25
CX509RSAPublicKey::CX509RSAPublicKey()
sl@0
    26
{}
sl@0
    27
sl@0
    28
//RSA public key
sl@0
    29
EXPORT_C CX509RSAPublicKey* CX509RSAPublicKey::NewL(const TDesC8& aBinaryData)
sl@0
    30
	{
sl@0
    31
	TInt pos = 0;
sl@0
    32
	return CX509RSAPublicKey::NewL(aBinaryData, pos);
sl@0
    33
	}
sl@0
    34
sl@0
    35
EXPORT_C CX509RSAPublicKey* CX509RSAPublicKey::NewLC(const TDesC8& aBinaryData)
sl@0
    36
	{
sl@0
    37
	TInt pos = 0;
sl@0
    38
	return CX509RSAPublicKey::NewLC(aBinaryData, pos);
sl@0
    39
	}
sl@0
    40
sl@0
    41
EXPORT_C CX509RSAPublicKey* CX509RSAPublicKey::NewL(const TDesC8& aBinaryData, TInt& aPos)
sl@0
    42
	{
sl@0
    43
	CX509RSAPublicKey* self = CX509RSAPublicKey::NewLC(aBinaryData, aPos);
sl@0
    44
	CleanupStack::Pop();
sl@0
    45
	return self;
sl@0
    46
	}
sl@0
    47
sl@0
    48
EXPORT_C CX509RSAPublicKey* CX509RSAPublicKey::NewLC(const TDesC8& aBinaryData, TInt& aPos)
sl@0
    49
	{
sl@0
    50
	CX509RSAPublicKey* self = new(ELeave) CX509RSAPublicKey();
sl@0
    51
	CleanupStack::PushL(self);
sl@0
    52
	self->ConstructL(aBinaryData, aPos);
sl@0
    53
	return self;
sl@0
    54
	}
sl@0
    55
sl@0
    56
void CX509RSAPublicKey::ConstructL(const TDesC8& aBinaryData, TInt& aPos)
sl@0
    57
	{
sl@0
    58
	TASN1DecGeneric gen(aBinaryData.Right(aBinaryData.Length() - aPos));
sl@0
    59
	gen.InitL();
sl@0
    60
	TInt end = aPos + gen.LengthDER();
sl@0
    61
	aPos += gen.LengthDERHeader();
sl@0
    62
	if (gen.Tag() != EASN1Sequence)
sl@0
    63
		{
sl@0
    64
		User::Leave(KErrArgument);
sl@0
    65
		}
sl@0
    66
	TASN1DecInteger encInt;
sl@0
    67
	iN = encInt.DecodeDERLongL(aBinaryData, aPos);
sl@0
    68
	iE = encInt.DecodeDERLongL(aBinaryData, aPos);
sl@0
    69
sl@0
    70
	// RSA Public keys, modulus and exponent must be positive integers
sl@0
    71
	if(!iN.IsPositive() || !iE.IsPositive())
sl@0
    72
		{
sl@0
    73
		User::Leave(KErrArgument);
sl@0
    74
		}
sl@0
    75
	if (aPos != end)
sl@0
    76
		{
sl@0
    77
		User::Leave(KErrArgument);
sl@0
    78
		}
sl@0
    79
	}
sl@0
    80
sl@0
    81
// Encodes public key to DER
sl@0
    82
EXPORT_C HBufC8* TASN1EncRSAPublicKey::EncodeDERL(const CRSAPublicKey& aKey) const
sl@0
    83
	{
sl@0
    84
	CASN1EncSequence* sequence = CASN1EncSequence::NewLC();
sl@0
    85
	CASN1EncBigInt* encModulus = CASN1EncBigInt::NewLC(aKey.N());
sl@0
    86
	sequence->AddAndPopChildL(encModulus);
sl@0
    87
	CASN1EncBigInt* encPublicExponent = CASN1EncBigInt::NewLC(aKey.E());
sl@0
    88
	sequence->AddAndPopChildL(encPublicExponent);
sl@0
    89
	HBufC8* der = HBufC8::NewMaxLC(sequence->LengthDER());
sl@0
    90
	TUint pos = 0;
sl@0
    91
	TPtr8 derptr(der->Des());
sl@0
    92
	sequence->WriteDERL(derptr, pos);
sl@0
    93
	CleanupStack::Pop(der);
sl@0
    94
	CleanupStack::PopAndDestroy(sequence);
sl@0
    95
	return der;
sl@0
    96
	}
sl@0
    97
sl@0
    98
// Decodes public key from DER
sl@0
    99
EXPORT_C CRSAPublicKey* TASN1DecRSAPublicKey::DecodeDERL(const TDesC8& aDER, 
sl@0
   100
														 TInt& aPos) const
sl@0
   101
	{
sl@0
   102
	// Enter into the containing SEQUENCE and verify if it is indeed there
sl@0
   103
	TASN1DecGeneric gen(aDER.Right(aDER.Length() - aPos));
sl@0
   104
	gen.InitL();
sl@0
   105
	TInt end = aPos + gen.LengthDER();
sl@0
   106
	aPos += gen.LengthDERHeader();
sl@0
   107
	if (gen.Tag() != EASN1Sequence)
sl@0
   108
		User::Leave(KErrArgument);
sl@0
   109
sl@0
   110
	// Decode modulus and public exponent (two large integers)
sl@0
   111
	TASN1DecInteger encInt;
sl@0
   112
	RInteger modulus = encInt.DecodeDERLongL(aDER, aPos);
sl@0
   113
	CleanupStack::PushL(modulus);
sl@0
   114
	RInteger publicExponent = encInt.DecodeDERLongL(aDER, aPos);
sl@0
   115
	CleanupStack::PushL(publicExponent);
sl@0
   116
	if (aPos != end)
sl@0
   117
		User::Leave(KErrArgument);
sl@0
   118
sl@0
   119
	// Construct a new key without copying
sl@0
   120
	CRSAPublicKey* key = CRSAPublicKey::NewL(modulus, publicExponent);
sl@0
   121
	CleanupStack::Pop(2); // modulus, publicExponent - owned by public key
sl@0
   122
	return key;
sl@0
   123
	}
sl@0
   124
sl@0
   125
// Decodes RSA key pair from DER-encoded buffer
sl@0
   126
EXPORT_C void TASN1DecRSAKeyPair::DecodeDERL(const TDesC8& aDER, 
sl@0
   127
												TInt& aPos, 
sl@0
   128
												CRSAPublicKey*& aPublicKey,
sl@0
   129
												CRSAPrivateKey*& aPrivateKey,
sl@0
   130
												TRSAPrivateKeyType aKeyType /*=EStandardCRT*/)
sl@0
   131
{
sl@0
   132
	aPublicKey = NULL;
sl@0
   133
	aPrivateKey = NULL;
sl@0
   134
sl@0
   135
	// Enter into the containing SEQUENCE and verify if it is 
sl@0
   136
	// indeed there
sl@0
   137
	TASN1DecGeneric gen(aDER.Right(aDER.Length() - aPos));
sl@0
   138
	gen.InitL();
sl@0
   139
	TInt end = aPos + gen.LengthDER();
sl@0
   140
	aPos += gen.LengthDERHeader();
sl@0
   141
	if (gen.Tag() != EASN1Sequence)
sl@0
   142
		User::Leave(KErrArgument);
sl@0
   143
sl@0
   144
	TASN1DecInteger encInt;
sl@0
   145
	
sl@0
   146
	// Decode and discard version, which is an integer
sl@0
   147
	encInt.DecodeDERShortL(aDER, aPos);
sl@0
   148
sl@0
   149
	// Decode public key components
sl@0
   150
	
sl@0
   151
	// Decode modulus
sl@0
   152
	RInteger publicModulus = encInt.DecodeDERLongL(aDER, aPos);
sl@0
   153
	CleanupStack::PushL(publicModulus);
sl@0
   154
	
sl@0
   155
	// Decode public exponent
sl@0
   156
	RInteger publicExponent = encInt.DecodeDERLongL(aDER, aPos);
sl@0
   157
	CleanupStack::PushL(publicExponent);
sl@0
   158
sl@0
   159
	//	Construct public key
sl@0
   160
	CRSAPublicKey* publicKey = CRSAPublicKey::NewL(publicModulus, publicExponent);
sl@0
   161
	CleanupStack::Pop(2, &publicModulus); // Now owned by publicKey
sl@0
   162
	CleanupStack::PushL(publicKey);
sl@0
   163
sl@0
   164
	// Decode private key components
sl@0
   165
sl@0
   166
	// Copy modulus
sl@0
   167
	RInteger privateModulus = RInteger::NewL(publicKey->N());
sl@0
   168
	CleanupStack::PushL(privateModulus);					  
sl@0
   169
	// Decode private exponent
sl@0
   170
	RInteger privateExponent = encInt.DecodeDERLongL(aDER, aPos);
sl@0
   171
	CleanupStack::PushL(privateExponent);
sl@0
   172
	// Decode prime 1
sl@0
   173
	RInteger p = encInt.DecodeDERLongL(aDER, aPos);
sl@0
   174
	CleanupStack::PushL(p);
sl@0
   175
	// Decode prime 2
sl@0
   176
	RInteger q = encInt.DecodeDERLongL(aDER, aPos);
sl@0
   177
	CleanupStack::PushL(q);
sl@0
   178
	// Decode exponent 1
sl@0
   179
	RInteger dmp1 = encInt.DecodeDERLongL(aDER, aPos);
sl@0
   180
	CleanupStack::PushL(dmp1);
sl@0
   181
	// Decode exponent 2
sl@0
   182
	RInteger dmq1 = encInt.DecodeDERLongL(aDER, aPos);
sl@0
   183
	CleanupStack::PushL(dmq1);
sl@0
   184
	// Decode coefficient
sl@0
   185
	RInteger the_iqmp = encInt.DecodeDERLongL(aDER, aPos);
sl@0
   186
	CleanupStack::PushL(the_iqmp);
sl@0
   187
sl@0
   188
	// We now should be at the end of the encoding. If not, the 
sl@0
   189
	// input encoding contains extra fields, and they are not 
sl@0
   190
	// supported.
sl@0
   191
	if (aPos != end)
sl@0
   192
		User::Leave(KErrArgument);
sl@0
   193
	
sl@0
   194
//	Construct private key
sl@0
   195
	CRSAPrivateKey* privateKey = NULL;
sl@0
   196
	if (EStandardCRT==aKeyType)
sl@0
   197
	{
sl@0
   198
		privateKey = CRSAPrivateKeyCRT::NewL(privateModulus, p, q, dmp1, dmq1, the_iqmp);
sl@0
   199
	}
sl@0
   200
	else if (EStandard==aKeyType)
sl@0
   201
	{
sl@0
   202
		privateKey = CRSAPrivateKeyStandard::NewL(privateModulus, privateExponent);
sl@0
   203
	}
sl@0
   204
	else
sl@0
   205
		User::Leave(KErrNotSupported);
sl@0
   206
	
sl@0
   207
	CleanupStack::Pop(8,publicKey);	 // publicKey, privateModulus, privateExponent,
sl@0
   208
	                                 // p, q, dmp1, dmq1, iqmp
sl@0
   209
	
sl@0
   210
//	Cleanup the TIntegers not owned by private key objects
sl@0
   211
	if (EStandard==aKeyType)
sl@0
   212
	{
sl@0
   213
		p.Close();
sl@0
   214
		q.Close();
sl@0
   215
		dmp1.Close();
sl@0
   216
		dmq1.Close();
sl@0
   217
		the_iqmp.Close();
sl@0
   218
	}
sl@0
   219
	else
sl@0
   220
	{
sl@0
   221
		privateExponent.Close();
sl@0
   222
	}
sl@0
   223
sl@0
   224
	aPublicKey = publicKey;
sl@0
   225
	aPrivateKey = privateKey;	
sl@0
   226
}
sl@0
   227
sl@0
   228
// TX509RSAKeyEncoder Class Implementation
sl@0
   229
sl@0
   230
EXPORT_C TX509RSAKeyEncoder::TX509RSAKeyEncoder(const CRSAPublicKey& aPublicKey, TAlgorithmId aDigestAlg)
sl@0
   231
	: TX509KeyEncoder(aDigestAlg),
sl@0
   232
	  iPublicKey(aPublicKey)
sl@0
   233
	{
sl@0
   234
	}
sl@0
   235
sl@0
   236
EXPORT_C CASN1EncBase* TX509RSAKeyEncoder::EncodeKeyLC() const
sl@0
   237
	{
sl@0
   238
	// Create higher-level sequence that will contain OID and the public key
sl@0
   239
	CASN1EncSequence* subjectPubKeyInfo = CASN1EncSequence::NewLC();
sl@0
   240
sl@0
   241
	// The next-level sequence will contain OID of the algorithm followed by NULL
sl@0
   242
	CASN1EncSequence* seq = CASN1EncSequence::NewLC();
sl@0
   243
	CASN1EncObjectIdentifier* oid = CASN1EncObjectIdentifier::NewLC(KRSA);
sl@0
   244
	seq->AddAndPopChildL(oid);
sl@0
   245
	CASN1EncNull* null = CASN1EncNull::NewLC();
sl@0
   246
	seq->AddAndPopChildL(null);
sl@0
   247
	subjectPubKeyInfo->AddAndPopChildL(seq);
sl@0
   248
	
sl@0
   249
	// Add the key itself to the higher-level sequence as a bit string
sl@0
   250
	// Obtain a copy of the entity's public key
sl@0
   251
	TASN1EncRSAPublicKey keyencoder;
sl@0
   252
	HBufC8* encoding = keyencoder.EncodeDERL(iPublicKey);
sl@0
   253
	CleanupStack::PushL(encoding);
sl@0
   254
	CASN1EncBitString* pubkeyenc = CASN1EncBitString::NewLC(*encoding);
sl@0
   255
	subjectPubKeyInfo->AddAndPopChildL(pubkeyenc);
sl@0
   256
	CleanupStack::PopAndDestroy(encoding);
sl@0
   257
	return subjectPubKeyInfo;
sl@0
   258
	}
sl@0
   259
sl@0
   260
// Returns ASN.1 sequence containing encoded signature algorithm.
sl@0
   261
EXPORT_C CASN1EncSequence* TX509RSAKeyEncoder::EncodeSignatureAlgorithmLC() const
sl@0
   262
	{
sl@0
   263
	CASN1EncSequence* seq = CASN1EncSequence::NewLC();
sl@0
   264
	CASN1EncObjectIdentifier* oid = NULL;
sl@0
   265
sl@0
   266
	// Determine OID string for the current combination of algorithms.
sl@0
   267
	switch(iDigestAlg)
sl@0
   268
		{
sl@0
   269
		default:
sl@0
   270
			User::Leave(KErrNotSupported);
sl@0
   271
			break;
sl@0
   272
sl@0
   273
		case EMD2:
sl@0
   274
			oid = CASN1EncObjectIdentifier::NewLC(KMD2WithRSA);
sl@0
   275
			break;
sl@0
   276
sl@0
   277
		case EMD5:
sl@0
   278
			oid = CASN1EncObjectIdentifier::NewLC(KMD5WithRSA);
sl@0
   279
			break;
sl@0
   280
sl@0
   281
		case ESHA1:
sl@0
   282
			oid = CASN1EncObjectIdentifier::NewLC(KSHA1WithRSA);
sl@0
   283
			break;
sl@0
   284
		}
sl@0
   285
sl@0
   286
	// Add algorithm OID to the sequence.
sl@0
   287
	seq->AddAndPopChildL(oid);
sl@0
   288
	// Add NULL after OID.
sl@0
   289
	CASN1EncNull* null = CASN1EncNull::NewLC();
sl@0
   290
	seq->AddAndPopChildL(null);
sl@0
   291
	
sl@0
   292
	return seq;
sl@0
   293
	}