os/security/crypto/weakcryptospi/source/asymmetric/dsakeys.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
sl@0
     1
/*
sl@0
     2
* Copyright (c) 2003-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 <asymmetrickeys.h>
sl@0
    20
#include <bigint.h>
sl@0
    21
#include <random.h>
sl@0
    22
#include <hash.h>
sl@0
    23
#include "../common/inlines.h"
sl@0
    24
#include "../bigint/mont.h"
sl@0
    25
#include "dsakeypairshim.h"
sl@0
    26
sl@0
    27
const TUint SHASIZE = 20;
sl@0
    28
const TUint KMinPrimeLength = 512;
sl@0
    29
const TUint KMaxPrimeLength = 1024;
sl@0
    30
const TUint KPrimeLengthMultiple = 64;
sl@0
    31
sl@0
    32
/* CDSAParameters */
sl@0
    33
sl@0
    34
EXPORT_C const TInteger& CDSAParameters::P(void) const
sl@0
    35
	{
sl@0
    36
	return iP;
sl@0
    37
	}
sl@0
    38
sl@0
    39
EXPORT_C const TInteger& CDSAParameters::Q(void) const
sl@0
    40
	{
sl@0
    41
	return iQ;
sl@0
    42
	}
sl@0
    43
sl@0
    44
EXPORT_C const TInteger& CDSAParameters::G(void) const
sl@0
    45
	{
sl@0
    46
	return iG;
sl@0
    47
	}
sl@0
    48
sl@0
    49
EXPORT_C CDSAParameters::~CDSAParameters(void)
sl@0
    50
	{
sl@0
    51
	iP.Close();
sl@0
    52
	iQ.Close();
sl@0
    53
	iG.Close();
sl@0
    54
	}
sl@0
    55
sl@0
    56
EXPORT_C CDSAParameters* CDSAParameters::NewL(RInteger& aP, RInteger& aQ, 
sl@0
    57
	RInteger& aG)
sl@0
    58
	{
sl@0
    59
	CDSAParameters* me = new (ELeave) CDSAParameters(aP, aQ, aG);
sl@0
    60
	return (me);
sl@0
    61
	}
sl@0
    62
sl@0
    63
EXPORT_C TBool CDSAParameters::ValidatePrimesL(const CDSAPrimeCertificate& aCert)
sl@0
    64
	const
sl@0
    65
	{
sl@0
    66
	TBool result = EFalse;
sl@0
    67
	RInteger p;
sl@0
    68
	RInteger q;
sl@0
    69
	//Regenerate primes using aCert's seed and counter
sl@0
    70
	TUint counter = aCert.Counter();
sl@0
    71
	if(!CDSAParameters::GeneratePrimesL(aCert.Seed(), counter, p, 
sl@0
    72
		P().BitCount(), q, ETrue))
sl@0
    73
		{
sl@0
    74
		return result;
sl@0
    75
		}
sl@0
    76
	//this doesn't leave, no need to push p and q
sl@0
    77
	if(p == P() && q == Q() && counter == aCert.Counter())
sl@0
    78
		{
sl@0
    79
		result = ETrue;
sl@0
    80
		}
sl@0
    81
	p.Close();
sl@0
    82
	q.Close();
sl@0
    83
	return result;
sl@0
    84
	}
sl@0
    85
sl@0
    86
EXPORT_C TBool CDSAParameters::ValidPrimeLength(TUint aPrimeBits)
sl@0
    87
	{
sl@0
    88
	return (aPrimeBits >= KMinPrimeLength &&
sl@0
    89
		aPrimeBits <= KMaxPrimeLength &&
sl@0
    90
		aPrimeBits % KPrimeLengthMultiple == 0);
sl@0
    91
	}
sl@0
    92
sl@0
    93
EXPORT_C CDSAParameters::CDSAParameters(RInteger& aP, RInteger& aQ, 	
sl@0
    94
	RInteger& aG) : iP(aP), iQ(aQ), iG(aG)
sl@0
    95
	{
sl@0
    96
	}
sl@0
    97
sl@0
    98
EXPORT_C CDSAParameters::CDSAParameters(void)
sl@0
    99
	{
sl@0
   100
	}
sl@0
   101
sl@0
   102
TBool CDSAParameters::GeneratePrimesL(const TDesC8& aSeed, TUint& aCounter, 
sl@0
   103
	RInteger& aP, TUint aL, RInteger& aQ, TBool aUseInputCounter)
sl@0
   104
	{
sl@0
   105
	//This follows the steps in FIPS 186-2 
sl@0
   106
	//See DSS Appendix 2.2
sl@0
   107
	//Note. Step 1 is performed prior to calling GeneratePrimesL, so that this
sl@0
   108
	//routine can be used for both generation and validation.
sl@0
   109
	//Step 1.  Choose an arbitrary sequence of at least 160 bits and call it
sl@0
   110
	//SEED.  Let g be the length of SEED in bits.
sl@0
   111
sl@0
   112
	if(!CDSAParameters::ValidPrimeLength(aL))
sl@0
   113
		{
sl@0
   114
		User::Leave(KErrNotSupported);
sl@0
   115
		}
sl@0
   116
	
sl@0
   117
	CSHA1* sha1 = CSHA1::NewL();
sl@0
   118
	CleanupStack::PushL(sha1);
sl@0
   119
sl@0
   120
	HBufC8* seedBuf = aSeed.AllocLC();
sl@0
   121
	TPtr8 seed = seedBuf->Des();
sl@0
   122
	TUint gBytes = aSeed.Size();
sl@0
   123
	//Note that the DSS's g = BytesToBits(gBytes) ie. the number of random bits
sl@0
   124
	//in the seed.  
sl@0
   125
	//This function has made the assumption (for ease of computation) that g%8
sl@0
   126
	//is 0.  Ie the seed is a whole number of random bytes.
sl@0
   127
	TBuf8<SHASIZE> U; 
sl@0
   128
	TBuf8<SHASIZE> temp; 
sl@0
   129
	const TUint n = (aL-1)/160;
sl@0
   130
	const TUint b = (aL-1)%160;
sl@0
   131
	HBufC8* Wbuf = HBufC8::NewMaxLC((n+1) * SHASIZE);
sl@0
   132
	TUint8* W = const_cast<TUint8*>(Wbuf->Ptr());
sl@0
   133
sl@0
   134
	U.Copy(sha1->Final(seed));
sl@0
   135
	
sl@0
   136
	//Step 2. U = SHA-1[SEED] XOR SHA-1[(SEED+1) mod 2^g]
sl@0
   137
	for(TInt i=gBytes - 1, carry=ETrue; i>=0 && carry; i--)
sl@0
   138
		{
sl@0
   139
		//!++(TUint) adds one to the current word which if it overflows to zero
sl@0
   140
		//sets carry to 1 thus letting the loop continue.  It's a poor man's
sl@0
   141
		//multi-word addition.  Swift eh?
sl@0
   142
		carry = !++(seed[i]);
sl@0
   143
		}
sl@0
   144
sl@0
   145
	temp.Copy(sha1->Final(seed));
sl@0
   146
	XorBuf(const_cast<TUint8*>(U.Ptr()), temp.Ptr(), SHASIZE);
sl@0
   147
sl@0
   148
	//Step 3. Form q from U by setting the most significant bit (2^159)
sl@0
   149
	//and the least significant bit to 1.
sl@0
   150
	U[0] |= 0x80;
sl@0
   151
	U[SHASIZE-1] |= 1;
sl@0
   152
sl@0
   153
	aQ = RInteger::NewL(U);
sl@0
   154
	CleanupStack::PushL(aQ);
sl@0
   155
sl@0
   156
	//Step 4. Use a robust primality testing algo to test if q is prime
sl@0
   157
	//The robust part is the calling codes problem.  This will use whatever
sl@0
   158
	//random number generator you set for the thread.  To attempt FIPS 186-2
sl@0
   159
	//compliance, set a FIPS 186-2 compliant RNG.
sl@0
   160
	if( !aQ.IsPrimeL() )
sl@0
   161
		{
sl@0
   162
		//Step 5. If not exit and get a new seed
sl@0
   163
		CleanupStack::PopAndDestroy(&aQ);
sl@0
   164
		CleanupStack::PopAndDestroy(Wbuf);
sl@0
   165
		CleanupStack::PopAndDestroy(seedBuf);
sl@0
   166
		CleanupStack::PopAndDestroy(sha1);
sl@0
   167
		return EFalse;
sl@0
   168
		}
sl@0
   169
	
sl@0
   170
	TUint counterEnd = aUseInputCounter ? aCounter+1 : 4096;
sl@0
   171
	
sl@0
   172
	//Step 6. Let counter = 0 and offset = 2
sl@0
   173
	//Note 1. that the DSS speaks of SEED + offset + k because they always
sl@0
   174
	//refer to a constant SEED.  We update our seed as we go so the offset
sl@0
   175
	//variable has already been added to seed in the previous iterations.
sl@0
   176
	//Note 2. We've already added 1 to our seed, so the first time through this
sl@0
   177
	//the offset in DSS speak will be 2.
sl@0
   178
	for(TUint counter=0; counter < counterEnd; counter++)
sl@0
   179
		{
sl@0
   180
		//Step 7. For k=0, ..., n let
sl@0
   181
		// Vk = SHA-1[(SEED + offset + k) mod 2^g]
sl@0
   182
		//I'm storing the Vk's inside of a big W buffer.
sl@0
   183
		for(TUint k=0; k<=n; k++)
sl@0
   184
			{
sl@0
   185
			for(TInt i=gBytes-1, carry=ETrue; i>=0 && carry; i--)
sl@0
   186
				{
sl@0
   187
				carry = !++(seed[i]);
sl@0
   188
				}
sl@0
   189
			if(!aUseInputCounter || counter == aCounter)
sl@0
   190
				{
sl@0
   191
				TPtr8 Wptr(W+(n-k)*SHASIZE, gBytes);
sl@0
   192
				Wptr.Copy(sha1->Final(seed));
sl@0
   193
				}
sl@0
   194
			}
sl@0
   195
		if(!aUseInputCounter || counter == aCounter)
sl@0
   196
			{
sl@0
   197
			//Step 8. Let W be the integer...  and let X = W + 2^(L-1)
sl@0
   198
			const_cast<TUint8&>((*Wbuf)[SHASIZE - 1 - b/8]) |= 0x80;
sl@0
   199
			TPtr8 Wptr(W + SHASIZE - 1 - b/8, aL/8, aL/8);
sl@0
   200
			RInteger X = RInteger::NewL(Wptr);
sl@0
   201
			CleanupStack::PushL(X);
sl@0
   202
			//Step 9. Let c = X mod 2q and set p = X - (c-1)
sl@0
   203
			RInteger twoQ = aQ.TimesL(TInteger::Two());
sl@0
   204
			CleanupStack::PushL(twoQ);
sl@0
   205
			RInteger c = X.ModuloL(twoQ);
sl@0
   206
			CleanupStack::PushL(c);
sl@0
   207
			--c;
sl@0
   208
			aP = X.MinusL(c);
sl@0
   209
			CleanupStack::PopAndDestroy(3, &X); //twoQ, c, X
sl@0
   210
			CleanupStack::PushL(aP);
sl@0
   211
			
sl@0
   212
			//Step 10 and 11: if p >= 2^(L-1) and p is prime
sl@0
   213
			if( aP.Bit(aL-1) && aP.IsPrimeL() )
sl@0
   214
				{
sl@0
   215
				aCounter = counter;
sl@0
   216
				CleanupStack::Pop(&aP);
sl@0
   217
				CleanupStack::Pop(&aQ);
sl@0
   218
				CleanupStack::PopAndDestroy(Wbuf);
sl@0
   219
				CleanupStack::PopAndDestroy(seedBuf);
sl@0
   220
				CleanupStack::PopAndDestroy(sha1);
sl@0
   221
				return ETrue;
sl@0
   222
				}
sl@0
   223
			CleanupStack::PopAndDestroy(&aP);
sl@0
   224
			}
sl@0
   225
		}
sl@0
   226
	CleanupStack::PopAndDestroy(&aQ);
sl@0
   227
	CleanupStack::PopAndDestroy(Wbuf);
sl@0
   228
	CleanupStack::PopAndDestroy(seedBuf);
sl@0
   229
	CleanupStack::PopAndDestroy(sha1);
sl@0
   230
	return EFalse;
sl@0
   231
	}
sl@0
   232
sl@0
   233
/* CDSAPublicKey */
sl@0
   234
sl@0
   235
EXPORT_C CDSAPublicKey* CDSAPublicKey::NewL(RInteger& aP, RInteger& aQ, 
sl@0
   236
	RInteger& aG, RInteger& aY)
sl@0
   237
	{
sl@0
   238
	CDSAPublicKey* self = new(ELeave) CDSAPublicKey(aP, aQ, aG, aY);
sl@0
   239
	return self;
sl@0
   240
	}
sl@0
   241
sl@0
   242
EXPORT_C CDSAPublicKey* CDSAPublicKey::NewLC(RInteger& aP, RInteger& aQ, 
sl@0
   243
	RInteger& aG, RInteger& aY)
sl@0
   244
	{
sl@0
   245
	CDSAPublicKey* self = NewL(aP, aQ, aG, aY);
sl@0
   246
	CleanupStack::PushL(self);
sl@0
   247
	return self;
sl@0
   248
	}
sl@0
   249
sl@0
   250
EXPORT_C const TInteger& CDSAPublicKey::Y(void) const
sl@0
   251
	{
sl@0
   252
	return iY;
sl@0
   253
	}
sl@0
   254
sl@0
   255
EXPORT_C CDSAPublicKey::CDSAPublicKey(void)
sl@0
   256
	{
sl@0
   257
	} 
sl@0
   258
sl@0
   259
EXPORT_C CDSAPublicKey::CDSAPublicKey(RInteger& aP, RInteger& aQ, RInteger& aG, 
sl@0
   260
	RInteger& aY) : CDSAParameters(aP, aQ, aG), iY(aY)
sl@0
   261
	{
sl@0
   262
	}
sl@0
   263
sl@0
   264
EXPORT_C CDSAPublicKey::~CDSAPublicKey(void)
sl@0
   265
	{
sl@0
   266
	iY.Close();
sl@0
   267
	}
sl@0
   268
sl@0
   269
/* CDSAPrivateKey */
sl@0
   270
sl@0
   271
EXPORT_C CDSAPrivateKey* CDSAPrivateKey::NewL(RInteger& aP, RInteger& aQ, 
sl@0
   272
	RInteger& aG, RInteger& aX)
sl@0
   273
	{
sl@0
   274
	CDSAPrivateKey* self = new(ELeave) CDSAPrivateKey(aP, aQ, aG, aX);
sl@0
   275
	return self;
sl@0
   276
	}
sl@0
   277
sl@0
   278
EXPORT_C CDSAPrivateKey* CDSAPrivateKey::NewLC(RInteger& aP, RInteger& aQ, 
sl@0
   279
	RInteger& aG, RInteger& aX)
sl@0
   280
	{
sl@0
   281
	CDSAPrivateKey* self = NewL(aP, aQ, aG, aX);
sl@0
   282
	CleanupStack::PushL(self);
sl@0
   283
	return self;
sl@0
   284
	}
sl@0
   285
sl@0
   286
EXPORT_C const TInteger& CDSAPrivateKey::X(void) const
sl@0
   287
	{
sl@0
   288
	return iX;
sl@0
   289
	}
sl@0
   290
sl@0
   291
EXPORT_C CDSAPrivateKey::CDSAPrivateKey(RInteger& aP, RInteger& aQ, RInteger& aG, 
sl@0
   292
	RInteger& aX) : CDSAParameters(aP, aQ, aG), iX(aX)
sl@0
   293
	{
sl@0
   294
	}
sl@0
   295
sl@0
   296
EXPORT_C CDSAPrivateKey::~CDSAPrivateKey(void)
sl@0
   297
	{
sl@0
   298
	iX.Close();
sl@0
   299
	}
sl@0
   300
sl@0
   301
/* CDSAKeyPair */
sl@0
   302
sl@0
   303
EXPORT_C CDSAKeyPair* CDSAKeyPair::NewL(TUint aKeyBits)
sl@0
   304
	{
sl@0
   305
 	CDSAKeyPairShim* self = CDSAKeyPairShim::NewLC(aKeyBits);
sl@0
   306
 	CleanupStack::Pop();
sl@0
   307
 	return self;
sl@0
   308
	}
sl@0
   309
sl@0
   310
EXPORT_C CDSAKeyPair* CDSAKeyPair::NewLC(TUint aKeyBits)
sl@0
   311
	{
sl@0
   312
 	CDSAKeyPairShim* self = CDSAKeyPairShim::NewLC(aKeyBits);
sl@0
   313
 	return self;
sl@0
   314
	}
sl@0
   315
sl@0
   316
EXPORT_C const CDSAPublicKey& CDSAKeyPair::PublicKey(void) const
sl@0
   317
	{
sl@0
   318
	return *iPublic;
sl@0
   319
	}
sl@0
   320
	
sl@0
   321
EXPORT_C const CDSAPrivateKey& CDSAKeyPair::PrivateKey(void) const
sl@0
   322
	{
sl@0
   323
	return *iPrivate;
sl@0
   324
	}
sl@0
   325
sl@0
   326
EXPORT_C CDSAKeyPair::~CDSAKeyPair(void) 
sl@0
   327
	{
sl@0
   328
	delete iPublic;
sl@0
   329
	delete iPrivate;
sl@0
   330
	delete iPrimeCertificate;
sl@0
   331
	}
sl@0
   332
sl@0
   333
EXPORT_C CDSAKeyPair::CDSAKeyPair(void) 
sl@0
   334
	{
sl@0
   335
	}
sl@0
   336
sl@0
   337
EXPORT_C const CDSAPrimeCertificate& CDSAKeyPair::PrimeCertificate(void) const
sl@0
   338
	{
sl@0
   339
	return *iPrimeCertificate;
sl@0
   340
	}
sl@0
   341
sl@0
   342
/* CDSAPrimeCertificate */
sl@0
   343
sl@0
   344
EXPORT_C CDSAPrimeCertificate* CDSAPrimeCertificate::NewL(const TDesC8& aSeed,
sl@0
   345
	TUint aCounter)
sl@0
   346
	{
sl@0
   347
	CDSAPrimeCertificate* self = NewLC(aSeed, aCounter);
sl@0
   348
	CleanupStack::Pop();
sl@0
   349
	return self;
sl@0
   350
	}
sl@0
   351
sl@0
   352
EXPORT_C CDSAPrimeCertificate* CDSAPrimeCertificate::NewLC(const TDesC8& aSeed,
sl@0
   353
	TUint aCounter)
sl@0
   354
	{
sl@0
   355
	CDSAPrimeCertificate* self = new(ELeave) CDSAPrimeCertificate(aCounter);
sl@0
   356
	CleanupStack::PushL(self);
sl@0
   357
	self->ConstructL(aSeed);
sl@0
   358
	return self;
sl@0
   359
	}
sl@0
   360
sl@0
   361
EXPORT_C const TDesC8& CDSAPrimeCertificate::Seed(void) const
sl@0
   362
	{
sl@0
   363
	return *iSeed;
sl@0
   364
	}
sl@0
   365
sl@0
   366
EXPORT_C TUint CDSAPrimeCertificate::Counter(void) const
sl@0
   367
	{
sl@0
   368
	return iCounter;
sl@0
   369
	}
sl@0
   370
sl@0
   371
EXPORT_C CDSAPrimeCertificate::~CDSAPrimeCertificate(void) 
sl@0
   372
	{
sl@0
   373
	delete const_cast<HBufC8*>(iSeed);
sl@0
   374
	}
sl@0
   375
sl@0
   376
void CDSAPrimeCertificate::ConstructL(const TDesC8& aSeed)
sl@0
   377
	{
sl@0
   378
	iSeed = aSeed.AllocL();
sl@0
   379
	}
sl@0
   380
sl@0
   381
EXPORT_C CDSAPrimeCertificate::CDSAPrimeCertificate(TUint aCounter) 
sl@0
   382
	: iCounter(aCounter)
sl@0
   383
	{
sl@0
   384
	}
sl@0
   385
sl@0
   386
// Over taken by  shim version. so, exclude it from coverage.
sl@0
   387
#ifdef _BullseyeCoverage
sl@0
   388
#pragma suppress_warnings on
sl@0
   389
#pragma BullseyeCoverage off
sl@0
   390
#pragma suppress_warnings off
sl@0
   391
#endif
sl@0
   392
void CDSAKeyPair::ConstructL(TUint /*aPBits*/)
sl@0
   393
	{
sl@0
   394
	}
sl@0
   395
sl@0
   396
// Unused exported and protected method can be excluded from coverage.
sl@0
   397
EXPORT_C CDSAPrimeCertificate::CDSAPrimeCertificate(void) 
sl@0
   398
	{
sl@0
   399
	}
sl@0
   400
sl@0
   401
EXPORT_C CDSAPrivateKey::CDSAPrivateKey(void)
sl@0
   402
	{
sl@0
   403
	}