1 /****************************************************************************
2 *																			*
3 *					  cryptlib Elgamal Encryption Routines					*
4 *						Copyright Peter Gutmann 1997-2005					*
5 *																			*
6 ****************************************************************************/
7 
8 #define PKC_CONTEXT		/* Indicate that we're working with PKC contexts */
9 #if defined( INC_ALL )
10   #include "crypt.h"
11   #include "context.h"
12 #else
13   #include "crypt.h"
14   #include "context/context.h"
15 #endif /* Compiler-specific includes */
16 
17 #ifdef USE_ELGAMAL
18 
19 /****************************************************************************
20 *																			*
21 *								Algorithm Self-test							*
22 *																			*
23 ****************************************************************************/
24 
25 /* Perform a pairwise consistency test on a public/private key pair */
26 
27 CHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \
pairwiseConsistencyTest(INOUT CONTEXT_INFO * contextInfoPtr,const BOOLEAN isGeneratedKey)28 static BOOLEAN pairwiseConsistencyTest( INOUT CONTEXT_INFO *contextInfoPtr,
29 										const BOOLEAN isGeneratedKey )
30 	{
31 	const CAPABILITY_INFO *capabilityInfoPtr = contextInfoPtr->capabilityInfo;
32 	DLP_PARAMS dlpParams;
33 	BYTE buffer[ ( CRYPT_MAX_PKCSIZE * 2 ) + 32 + 8 ];
34 	int encrSize, status;
35 
36 	assert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );
37 
38 	/* Encrypt with the public key.  We  */
39 	memset( buffer, 0, CRYPT_MAX_PKCSIZE );
40 	memcpy( buffer + 1, "abcde", 5 );
41 	setDLPParams( &dlpParams, buffer,
42 				  bitsToBytes( contextInfoPtr->ctxPKC->keySizeBits ),
43 				  buffer, ( CRYPT_MAX_PKCSIZE * 2 ) + 32 );
44 	if( !isGeneratedKey )
45 		{
46 		/* Force the use of a fixed k value for the encryption test to
47 		   avoid having to go via the RNG */
48 		dlpParams.inLen2 = -999;
49 		}
50 	status = capabilityInfoPtr->encryptFunction( contextInfoPtr,
51 						( BYTE * ) &dlpParams, sizeof( DLP_PARAMS ) );
52 	if( cryptStatusError( status ) )
53 		return( FALSE );
54 
55 	/* Decrypt with the private key */
56 	encrSize = dlpParams.outLen;
57 	setDLPParams( &dlpParams, buffer, encrSize,
58 				  buffer, ( CRYPT_MAX_PKCSIZE * 2 ) + 32 );
59 	status = capabilityInfoPtr->decryptFunction( contextInfoPtr,
60 						( BYTE * ) &dlpParams, sizeof( DLP_PARAMS ) );
61 	if( cryptStatusError( status ) )
62 		return( FALSE );
63 	return( !memcmp( buffer + 1, "abcde", 5 ) );
64 	}
65 
66 #ifndef CONFIG_NO_SELFTEST
67 
68 /* Test the Elgamal implementation using a sample key.  Because a lot of the
69    high-level encryption routines don't exist yet, we cheat a bit and set up
70    a dummy encryption context with just enough information for the following
71    code to work */
72 
73 typedef struct {
74 	const int pLen; const BYTE p[ 128 ];
75 	const int qLen; const BYTE q[ 20 ];
76 	const int gLen; const BYTE g[ 128 ];
77 	const int xLen; const BYTE x[ 20 ];
78 	const int yLen; const BYTE y[ 128 ];
79 	} DLP_KEY;
80 
81 static const DLP_KEY FAR_BSS dlpTestKey = {
82 	/* p */
83 	128,
84 	{ 0x04, 0x4C, 0xDD, 0x5D, 0xB6, 0xED, 0x23, 0xAE,
85 	  0xB2, 0xA7, 0x59, 0xE6, 0xF8, 0x3D, 0xA6, 0x27,
86 	  0x85, 0xF2, 0xFE, 0xE2, 0xE8, 0xF3, 0xDA, 0xA3,
87 	  0x7B, 0xD6, 0x48, 0xD4, 0x44, 0xCA, 0x6E, 0x10,
88 	  0x97, 0x6C, 0x1D, 0x6C, 0x39, 0xA7, 0x0C, 0x88,
89 	  0x8E, 0x1F, 0xDD, 0xF7, 0x59, 0x69, 0xDA, 0x36,
90 	  0xDD, 0xB8, 0x3E, 0x1A, 0xD2, 0x91, 0x3E, 0x30,
91 	  0xB1, 0xB5, 0xC2, 0xBC, 0xA9, 0xA3, 0xA5, 0xDE,
92 	  0xC7, 0xCF, 0x51, 0x2C, 0x1B, 0x89, 0xD0, 0x71,
93 	  0xE3, 0x71, 0xBB, 0x50, 0x86, 0x26, 0x32, 0x9F,
94 	  0xF5, 0x4A, 0x9C, 0xB1, 0x78, 0x7B, 0x47, 0x1F,
95 	  0x19, 0xC7, 0x26, 0x22, 0x15, 0x62, 0x71, 0xAB,
96 	  0xD7, 0x25, 0xA5, 0xE4, 0x68, 0x71, 0x93, 0x5D,
97 	  0x1F, 0x29, 0x01, 0x05, 0x9C, 0x57, 0x3A, 0x09,
98 	  0xB0, 0xB8, 0xE4, 0xD2, 0x37, 0x90, 0x36, 0x2F,
99 	  0xBF, 0x1E, 0x74, 0xB4, 0x6B, 0xE4, 0x66, 0x07 },
100 
101 	/* q */
102 	20,
103 	{ 0xFD, 0xD9, 0xC8, 0x5F, 0x73, 0x62, 0xC9, 0x79,
104 	  0xEF, 0xD5, 0x09, 0x07, 0x02, 0xE7, 0xF2, 0x90,
105 	  0x97, 0x13, 0x26, 0x1D },
106 
107 	/* g */
108 	128,
109 	{ 0x02, 0x4E, 0xDD, 0x0D, 0x7F, 0x4D, 0xB1, 0x42,
110 	  0x01, 0x50, 0xE7, 0x9A, 0x65, 0x73, 0x8B, 0x31,
111 	  0x24, 0x6B, 0xC6, 0x74, 0xA7, 0x68, 0x26, 0x11,
112 	  0x06, 0x3C, 0x96, 0xA9, 0xA6, 0x23, 0x12, 0x79,
113 	  0xC4, 0xEE, 0x21, 0x88, 0xDD, 0xE3, 0xF0, 0x37,
114 	  0xCE, 0x3E, 0x54, 0x53, 0x57, 0x03, 0x30, 0xE4,
115 	  0xD3, 0xAB, 0x39, 0x4E, 0x39, 0xDC, 0xA2, 0x88,
116 	  0x82, 0xF6, 0xE8, 0xBA, 0xAC, 0xF5, 0x7D, 0x2F,
117 	  0x23, 0x9A, 0x09, 0x94, 0xB2, 0x89, 0xA2, 0xC9,
118 	  0x7C, 0xBE, 0x4D, 0x48, 0x0E, 0x59, 0x51, 0xB8,
119 	  0x7D, 0x99, 0x88, 0x79, 0xA8, 0x13, 0x0E, 0x12,
120 	  0x56, 0x9D, 0x4B, 0x2E, 0xE0, 0xE1, 0x37, 0x78,
121 	  0x6F, 0xCC, 0x4D, 0x97, 0xA9, 0x02, 0x0E, 0xD2,
122 	  0x43, 0x83, 0xEC, 0x4F, 0xC2, 0x70, 0xEF, 0x16,
123 	  0xDE, 0xBF, 0xBA, 0xD1, 0x6C, 0x8A, 0x36, 0xEE,
124 	  0x42, 0x41, 0xE9, 0xE7, 0x66, 0xAE, 0x46, 0x3B },
125 
126 	/* x */
127 	20,
128 	{ 0xD9, 0x41, 0x29, 0xF7, 0x40, 0x32, 0x09, 0x71,
129 	  0xB8, 0xE2, 0xB8, 0xCB, 0x74, 0x46, 0x0B, 0xD4,
130 	  0xF2, 0xAB, 0x54, 0xA1 },
131 
132 	/* y */
133 	128,
134 	{ 0x01, 0x7E, 0x16, 0x5B, 0x65, 0x51, 0x0A, 0xDA,
135 	  0x82, 0x1A, 0xD9, 0xF4, 0x1E, 0x66, 0x6D, 0x7D,
136 	  0x23, 0xA6, 0x28, 0x2F, 0xE6, 0xC2, 0x03, 0x8E,
137 	  0x8C, 0xAB, 0xC2, 0x08, 0x87, 0xC9, 0xE8, 0x51,
138 	  0x0A, 0x37, 0x1E, 0xD4, 0x41, 0x7F, 0xA2, 0xC5,
139 	  0x48, 0x26, 0xB7, 0xF6, 0xC2, 0x6F, 0xB2, 0xF8,
140 	  0xF9, 0x43, 0x43, 0xF9, 0xDA, 0xAB, 0xA2, 0x59,
141 	  0x27, 0xBA, 0xC9, 0x1C, 0x8C, 0xAB, 0xC4, 0x90,
142 	  0x27, 0xE1, 0x10, 0x39, 0x6F, 0xD2, 0xCD, 0x7C,
143 	  0xD1, 0x0B, 0xFA, 0x28, 0xD2, 0x7A, 0x7B, 0x52,
144 	  0x8A, 0xA0, 0x5A, 0x0F, 0x10, 0xF7, 0xBA, 0xFD,
145 	  0x33, 0x0C, 0x3C, 0xCE, 0xE5, 0xF2, 0xF6, 0x92,
146 	  0xED, 0x04, 0xBF, 0xD3, 0xF8, 0x3D, 0x39, 0xCC,
147 	  0xAA, 0xCC, 0x0B, 0xB2, 0x6B, 0xD8, 0xB2, 0x8A,
148 	  0x5C, 0xCE, 0xDA, 0xF9, 0xE1, 0xA7, 0x23, 0x50,
149 	  0xDC, 0xCE, 0xA4, 0xD5, 0xA5, 0x4F, 0x08, 0x0F }
150 	};
151 
152 /* If we're doing a self-test we use the following fixed k (for the
153    signature) and kRandom (for the encryption) data rather than a randomly-
154    generated value.  The k value is the DSA one from FIPS 186, which seems as
155    good as any */
156 
157 #if 0	/* Only needed for Elgamal signing */
158 
159 static const BYTE FAR_BSS kVal[] = {
160 	0x35, 0x8D, 0xAD, 0x57, 0x14, 0x62, 0x71, 0x0F,
161 	0x50, 0xE2, 0x54, 0xCF, 0x1A, 0x37, 0x6B, 0x2B,
162 	0xDE, 0xAA, 0xDF, 0xBF
163 	};
164 #endif /* 0 */
165 
166 static const BYTE FAR_BSS kRandomVal[] = {
167 	0x2A, 0x7C, 0x01, 0xFD, 0x62, 0xF7, 0x43, 0x13,
168 	0x36, 0xFE, 0xE8, 0xF1, 0x68, 0xB2, 0xA2, 0x2F,
169 	0x76, 0x50, 0xA1, 0x2C, 0x3E, 0x64, 0x8E, 0xFE,
170 	0x04, 0x58, 0x7F, 0xDE, 0xC2, 0x34, 0xE5, 0x79,
171 	0xE9, 0x45, 0xB0, 0xDD, 0x5E, 0x56, 0xD7, 0x82,
172 	0xEF, 0x93, 0xEF, 0x5F, 0xD0, 0x71, 0x8B, 0xA1,
173 	0x3E, 0xA0, 0x55, 0x6A, 0xB9, 0x6E, 0x72, 0xFE,
174 	0x17, 0x03, 0x95, 0x50, 0xB7, 0xA1, 0x11, 0xBA,
175 	};
176 
177 CHECK_RETVAL \
selfTest(void)178 static int selfTest( void )
179 	{
180 	CONTEXT_INFO contextInfo;
181 	PKC_INFO contextData, *pkcInfo = &contextData;
182 	const CAPABILITY_INFO *capabilityInfoPtr;
183 	DLP_PARAMS dlpParams;
184 	BYTE buffer[ ( CRYPT_MAX_PKCSIZE * 2 ) + 32 + 8 ];
185 	int status;
186 
187 	/* Initialise the key components */
188 	status = staticInitContext( &contextInfo, CONTEXT_PKC,
189 								getElgamalCapability(), &contextData,
190 								sizeof( PKC_INFO ), NULL );
191 	if( cryptStatusError( status ) )
192 		return( status );
193 	status = importBignum( &pkcInfo->dlpParam_p, dlpTestKey.p,
194 						   dlpTestKey.pLen, DLPPARAM_MIN_P,
195 						   DLPPARAM_MAX_P, NULL, KEYSIZE_CHECK_PKC );
196 	if( cryptStatusOK( status ) )
197 		status = importBignum( &pkcInfo->dlpParam_g, dlpTestKey.g,
198 							   dlpTestKey.gLen, DLPPARAM_MIN_G,
199 							   DLPPARAM_MAX_G, &pkcInfo->dlpParam_p,
200 							   KEYSIZE_CHECK_NONE );
201 	if( cryptStatusOK( status ) )
202 		status = importBignum( &pkcInfo->dlpParam_q, dlpTestKey.q,
203 							   dlpTestKey.qLen, DLPPARAM_MIN_Q,
204 							   DLPPARAM_MAX_Q, &pkcInfo->dlpParam_p,
205 							   KEYSIZE_CHECK_NONE );
206 	if( cryptStatusOK( status ) )
207 		status = importBignum( &pkcInfo->dlpParam_y, dlpTestKey.y,
208 							   dlpTestKey.yLen, DLPPARAM_MIN_Y,
209 							   DLPPARAM_MAX_Y, &pkcInfo->dlpParam_p,
210 							   KEYSIZE_CHECK_NONE );
211 	if( cryptStatusOK( status ) )
212 		status = importBignum( &pkcInfo->dlpParam_x, dlpTestKey.x,
213 							   dlpTestKey.xLen, DLPPARAM_MIN_X,
214 							   DLPPARAM_MAX_X, &pkcInfo->dlpParam_p,
215 							   KEYSIZE_CHECK_NONE );
216 	if( cryptStatusError( status ) )
217 		{
218 		staticDestroyContext( &contextInfo );
219 		retIntError();
220 		}
221 	capabilityInfoPtr = contextInfo.capabilityInfo;
222 
223 	ENSURES( sanityCheckPKCInfo( pkcInfo ) );
224 
225 	/* Perform a test a sig generation/check and test en/decryption */
226 #if 0	/* See comment in sig.code */
227 	memset( buffer, '*', 20 );
228 	status = capabilityInfoPtr->signFunction( &contextInfoPtr, buffer, -1 );
229 	if( !cryptStatusError( status ) )
230 		{
231 		memmove( buffer + 20, buffer, status );
232 		memset( buffer, '*', 20 );
233 		status = capabilityInfoPtr->sigCheckFunction( &contextInfoPtr,
234 													  buffer, 20 + status );
235 		}
236 	if( status != CRYPT_OK )
237 		status = CRYPT_ERROR_FAILED;
238 #endif /* 0 */
239 	status = capabilityInfoPtr->initKeyFunction( &contextInfo, NULL, 0 );
240 	if( cryptStatusError( status ) || \
241 		!pairwiseConsistencyTest( &contextInfo, FALSE ) )
242 		{
243 		staticDestroyContext( &contextInfo );
244 		return( CRYPT_ERROR_FAILED );
245 		}
246 
247 	/* Finally, make sure that the memory fault-detection is working */
248 	pkcInfo->dlpParam_p.d[ 8 ] ^= 0x0011;
249 	memset( buffer, 0, CRYPT_MAX_PKCSIZE );
250 	memcpy( buffer + 1, "abcde", 5 );
251 	setDLPParams( &dlpParams, buffer,
252 				  bitsToBytes( contextInfo.ctxPKC->keySizeBits ),
253 				  buffer, ( CRYPT_MAX_PKCSIZE * 2 ) + 32 );
254 	status = capabilityInfoPtr->encryptFunction( &contextInfo,
255 							( BYTE * ) &dlpParams, sizeof( DLP_PARAMS ) );
256 	if( cryptStatusOK( status ) )
257 		{
258 		/* The fault-detection couldn't detect a bit-flip, there's a
259 		   problem */
260 		staticDestroyContext( &contextInfo );
261 		return( CRYPT_ERROR_FAILED );
262 		}
263 
264 	/* Clean up */
265 	staticDestroyContext( &contextInfo );
266 
267 	return( CRYPT_OK );
268 	}
269 #else
270 	#define selfTest	NULL
271 #endif /* !CONFIG_NO_SELFTEST */
272 
273 /****************************************************************************
274 *																			*
275 *							Create/Check a Signature						*
276 *																			*
277 ****************************************************************************/
278 
279 /* Elgamal signatures have potential security problems (although this isn't
280    an issue when they're used in a PKCS #1 manner, OTOH nothing apart from
281    cryptlib uses them like this) while the equivalent DSA signatures don't
282    (or at least have less than Elgamal).  In addition since nothing uses
283    them anyway this code, we don't support Elgamal signing */
284 
285 /****************************************************************************
286 *																			*
287 *						Encrypt/Decrypt a Data Block						*
288 *																			*
289 ****************************************************************************/
290 
291 /* Encrypt a single block of data.  We have to append the distinguisher 'Fn'
292    to the name since some systems already have 'encrypt' and 'decrypt' in
293    their standard headers */
294 
295 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
encryptFn(INOUT CONTEXT_INFO * contextInfoPtr,INOUT_BUFFER_FIXED (noBytes)BYTE * buffer,IN_LENGTH_FIXED (sizeof (DLP_PARAMS))int noBytes)296 static int encryptFn( INOUT CONTEXT_INFO *contextInfoPtr,
297 					  INOUT_BUFFER_FIXED( noBytes ) BYTE *buffer,
298 					  IN_LENGTH_FIXED( sizeof( DLP_PARAMS ) ) int noBytes )
299 	{
300 	PKC_INFO *pkcInfo = contextInfoPtr->ctxPKC;
301 	DLP_PARAMS *dlpParams = ( DLP_PARAMS * ) buffer;
302 	const PKC_ENCODEDLVALUES_FUNCTION encodeDLValuesFunction = \
303 					FNPTR_GET( pkcInfo->encodeDLValuesFunction );
304 	BIGNUM *p = &pkcInfo->dlpParam_p, *g = &pkcInfo->dlpParam_g;
305 	BIGNUM *y = &pkcInfo->dlpParam_y;
306 	BIGNUM *tmp = &pkcInfo->tmp1, *k = &pkcInfo->tmp2;
307 	BIGNUM *r = &pkcInfo->tmp3, *s = &pkcInfo->dlpTmp1;
308 	BIGNUM *phi_p = &pkcInfo->dlpTmp2;
309 	const int length = bitsToBytes( pkcInfo->keySizeBits );
310 	int i, iterationCount, bnStatus = BN_STATUS, status;
311 
312 	assert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );
313 	assert( isWritePtr( dlpParams, sizeof( DLP_PARAMS ) ) );
314 	assert( isReadPtr( dlpParams->inParam1, dlpParams->inLen1 ) );
315 	assert( isWritePtr( dlpParams->outParam, dlpParams->outLen ) );
316 
317 	REQUIRES( sanityCheckPKCInfo( pkcInfo ) );
318 	REQUIRES( noBytes == sizeof( DLP_PARAMS ) );
319 	REQUIRES( dlpParams->inLen1 == length );
320 	REQUIRES( dlpParams->inParam2 == NULL && \
321 			  ( dlpParams->inLen2 == 0 || dlpParams->inLen2 == -999 ) );
322 	REQUIRES( dlpParams->outLen >= ( 2 + length ) * 2 && \
323 			  dlpParams->outLen < MAX_INTLENGTH_SHORT );
324 	REQUIRES( encodeDLValuesFunction != NULL );
325 
326 	/* Perform side-channel attack checks */
327 	if( cryptStatusError( \
328 			checksumContextData( pkcInfo, CRYPT_ALGO_ELGAMAL,
329 					( contextInfoPtr->flags & CONTEXT_FLAG_ISPUBLICKEY ) ? \
330 					FALSE : TRUE ) ) )
331 		{
332 		DEBUG_DIAG(( "Elgamal key memory corruption detected" ));
333 		return( CRYPT_ERROR_FAILED );
334 		}
335 
336 	/* Make sure that we're not being fed suspiciously short data
337 	   quantities.  importBignum() performs a more rigorous check, but we
338 	   use this as a lint filter before performing the relatively expensive
339 	   random bignum generation and preprocessing */
340 	for( i = 0; i < length; i++ )
341 		{
342 		if( ( ( BYTE * ) dlpParams->inParam1 ) [ i ] != 0 )
343 			break;
344 		}
345 	if( length - i < MIN_PKCSIZE - 8 )
346 		return( CRYPT_ERROR_BADDATA );
347 
348 	/* Generate the secret random value k.  During the initial self-test
349 	   the random data pool may not exist yet, and may in fact never exist in
350 	   a satisfactory condition if there isn't enough randomness present in
351 	   the system to generate cryptographically strong random numbers.  To
352 	   bypass this problem, if the caller passes in a second length parameter
353 	   of -999, we know that it's an internal self-test call and use a fixed
354 	   bit pattern for k that avoids having to call generateBignum().  This
355 	   is a somewhat ugly use of 'magic numbers', but it's safe because this
356 	   function can only be called internally, so all we need to trap is
357 	   accidental use of the parameter which is normally unused */
358 	if( dlpParams->inLen2 == -999 )
359 		{
360 		status = importBignum( k, ( BYTE * ) kRandomVal, length,
361 							   length - 1, length, NULL, KEYSIZE_CHECK_NONE );
362 		}
363 	else
364 		{
365 		/* Generate the random value k, with the same 32-bit adjustment used
366 		   in the DSA code to avoid bias in the output (the only real
367 		   difference is that we eventually reduce it mode phi(p) rather than
368 		   mod q).
369 
370 		   We also add (meaning "mix in" rather than strictly
371 		   "arithmetically add") the data being encrypted to curtail
372 		   problems in the incredibly unlikely situation that the RNG value
373 		   repeats */
374 		status = generateBignum( k,
375 								 bytesToBits( length + DLP_OVERFLOW_SIZE ),
376 								 0x80, 0, dlpParams->inParam1,
377 								 dlpParams->inLen1 );
378 		}
379 	if( cryptStatusError( status ) )
380 		return( status );
381 
382 	/* Generate phi( p ) and use it to get k, k < p-1 and k relatively prime
383 	   to p-1.  Since (p-1)/2 is prime, the initial choice for k will be
384 	   divisible by (p-1)/2 with probability 2/(p-1), so we'll do at most two
385 	   gcd operations with very high probability.  A k of (p-3)/2 will be
386 	   chosen with probability 3/(p-1), and all other numbers from 1 to p-1
387 	   will be chosen with probability 2/(p-1), giving a nearly uniform
388 	   distribution of exponents */
389 	CKPTR( BN_copy( phi_p, p ) );
390 	CK( BN_sub_word( phi_p, 1 ) );		/* phi( p ) = p - 1 */
391 	CK( BN_mod( k, k, phi_p,			/* Reduce k to the correct range */
392 				&pkcInfo->bnCTX ) );
393 	CK( BN_gcd( s, k, phi_p, &pkcInfo->bnCTX ) );
394 	for( iterationCount = 0;
395 		 bnStatusOK( bnStatus ) && !BN_is_one( s ) && \
396 			iterationCount < FAILSAFE_ITERATIONS_SMALL;
397 		 iterationCount++ )
398 		{
399 		CK( BN_sub_word( k, 1 ) );
400 		CK( BN_gcd( s, k, phi_p, &pkcInfo->bnCTX ) );
401 		}
402 	ENSURES( iterationCount < FAILSAFE_ITERATIONS_SMALL );
403 	if( bnStatusError( bnStatus ) )
404 		return( getBnStatus( bnStatus ) );
405 
406 	/* Move the input data into a bignum */
407 	status = importBignum( tmp, ( BYTE * ) dlpParams->inParam1, length,
408 						   MIN_PKCSIZE - 8, CRYPT_MAX_PKCSIZE, p,
409 						   KEYSIZE_CHECK_NONE );
410 	if( cryptStatusError( status ) )
411 		return( status );
412 
413 	/* s = ( y^k * M ) mod p */
414 	CK( BN_mod_exp_mont( r, y, k, p,	/* y' = y^k mod p */
415 						 &pkcInfo->bnCTX, &pkcInfo->dlpParam_mont_p ) );
416 	CK( BN_mod_mul( s, r, tmp, p,		/* s = y'M mod p */
417 					&pkcInfo->bnCTX ) );
418 	if( bnStatusError( bnStatus ) )
419 		return( getBnStatus( bnStatus ) );
420 
421 	/* r = g^k mod p */
422 	CK( BN_mod_exp_mont( r, g, k, p, &pkcInfo->bnCTX,
423 						 &pkcInfo->dlpParam_mont_p ) );
424 	if( bnStatusError( bnStatus ) )
425 		return( getBnStatus( bnStatus ) );
426 
427 	/* Encode the result as a DL data block */
428 	status = encodeDLValuesFunction( dlpParams->outParam, dlpParams->outLen,
429 									 &dlpParams->outLen, r, s,
430 									 dlpParams->formatType );
431 	if( cryptStatusError( status ) )
432 		return( status );
433 
434 	/* Perform side-channel attack checks */
435 	if( cryptStatusError( \
436 			checksumContextData( pkcInfo, CRYPT_ALGO_ELGAMAL,
437 					( contextInfoPtr->flags & CONTEXT_FLAG_ISPUBLICKEY ) ? \
438 					FALSE : TRUE ) ) )
439 		{
440 		if( dlpParams->inLen2 != -999 )	/* Don't trigger on self-test */
441 			DEBUG_DIAG(( "Elgamal key memory corruption detected" ));
442 		return( CRYPT_ERROR_FAILED );
443 		}
444 
445 	ENSURES( sanityCheckPKCInfo( pkcInfo ) );
446 
447 	return( CRYPT_OK );
448 	}
449 
450 /* Decrypt a single block of data */
451 
452 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
decryptFn(INOUT CONTEXT_INFO * contextInfoPtr,INOUT_BUFFER_FIXED (noBytes)BYTE * buffer,IN_LENGTH_FIXED (sizeof (DLP_PARAMS))int noBytes)453 static int decryptFn( INOUT CONTEXT_INFO *contextInfoPtr,
454 					  INOUT_BUFFER_FIXED( noBytes ) BYTE *buffer,
455 					  IN_LENGTH_FIXED( sizeof( DLP_PARAMS ) ) int noBytes )
456 	{
457 	PKC_INFO *pkcInfo = contextInfoPtr->ctxPKC;
458 	DLP_PARAMS *dlpParams = ( DLP_PARAMS * ) buffer;
459 	const PKC_DECODEDLVALUES_FUNCTION decodeDLValuesFunction = \
460 					FNPTR_GET( pkcInfo->decodeDLValuesFunction );
461 	BIGNUM *p = &pkcInfo->dlpParam_p, *x = &pkcInfo->dlpParam_x;
462 	BIGNUM *r = &pkcInfo->tmp1, *s = &pkcInfo->tmp2, *tmp = &pkcInfo->tmp3;
463 	const int length = bitsToBytes( pkcInfo->keySizeBits );
464 	int offset, dummy, bnStatus = BN_STATUS, status;
465 
466 	assert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );
467 	assert( isWritePtr( dlpParams, sizeof( DLP_PARAMS ) ) );
468 	assert( isReadPtr( dlpParams->inParam1, dlpParams->inLen1 ) );
469 	assert( isWritePtr( dlpParams->outParam, dlpParams->outLen ) );
470 
471 	REQUIRES( sanityCheckPKCInfo( pkcInfo ) );
472 	REQUIRES( noBytes == sizeof( DLP_PARAMS ) );
473 	REQUIRES( dlpParams->inLen1 >= ( 2 + ( length - 2 ) ) * 2 && \
474 			  dlpParams->inLen1 < MAX_INTLENGTH_SHORT );
475 	REQUIRES( dlpParams->inParam2 == NULL && dlpParams->inLen2 == 0 );
476 	REQUIRES( dlpParams->outLen >= length && \
477 			  dlpParams->outLen < MAX_INTLENGTH_SHORT );
478 	REQUIRES( decodeDLValuesFunction != NULL );
479 
480 	/* Perform side-channel attack checks */
481 	if( cryptStatusError( \
482 			checksumContextData( pkcInfo, CRYPT_ALGO_ELGAMAL, TRUE ) ) )
483 		{
484 		DEBUG_DIAG(( "Elgamal key memory corruption detected" ));
485 		return( CRYPT_ERROR_FAILED );
486 		}
487 
488 	/* Decode the values from a DL data block and make sure that r and s are
489 	   valid, i.e. r, s = [1...p-1] */
490 	status = decodeDLValuesFunction( dlpParams->inParam1, dlpParams->inLen1,
491 									 r, s, p, dlpParams->formatType );
492 	if( cryptStatusError( status ) )
493 		return( status );
494 
495 	/* M = ( s / ( r^x ) ) mod p */
496 	CK( BN_mod_exp_mont( r, r, x, p,		/* r' = r^x */
497 						 &pkcInfo->bnCTX, &pkcInfo->dlpParam_mont_p ) );
498 	CKPTR( BN_mod_inverse( tmp, r, p,		/* r'' = r'^-1 */
499 						   &pkcInfo->bnCTX ) );
500 	CK( BN_mod_mul( s, s, tmp, p,			/* s = s * r'^-1 mod p */
501 					&pkcInfo->bnCTX ) );
502 	if( bnStatusError( bnStatus ) )
503 		return( getBnStatus( bnStatus ) );
504 
505 	/* Copy the result to the output.  Since the bignum code performs
506 	   leading-zero truncation, we have to adjust where we copy the
507 	   result to in the buffer to take into account extra zero bytes
508 	   that aren't extracted from the bignum.  In addition we can't use
509 	   the length returned from exportBignum() because this is the length
510 	   of the zero-truncated result, not the full length */
511 	offset = length - BN_num_bytes( s );
512 	ENSURES( offset >= 0 && offset <= length );
513 	if( offset > 0 )
514 		{
515 		/* If the resulting value has more than 128 bits of leading zeroes
516 		   then there's something wrong */
517 		if( offset > 16 )
518 			return( CRYPT_ERROR_BADDATA );
519 		memset( dlpParams->outParam, 0, offset );
520 		}
521 	dlpParams->outLen = length;
522 	status = exportBignum( dlpParams->outParam + offset,
523 						   dlpParams->outLen - offset, &dummy, s );
524 	if( cryptStatusError( status ) )
525 		return( status );
526 
527 	/* Perform side-channel attack checks */
528 	if( cryptStatusError( \
529 			checksumContextData( pkcInfo, CRYPT_ALGO_ELGAMAL, TRUE ) ) )
530 		{
531 		DEBUG_DIAG(( "Elgamal key memory corruption detected" ));
532 		return( CRYPT_ERROR_FAILED );
533 		}
534 
535 	ENSURES( sanityCheckPKCInfo( pkcInfo ) );
536 
537 	return( CRYPT_OK );
538 	}
539 
540 /****************************************************************************
541 *																			*
542 *								Key Management								*
543 *																			*
544 ****************************************************************************/
545 
546 /* Load key components into an encryption context */
547 
548 CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
initKey(INOUT CONTEXT_INFO * contextInfoPtr,IN_BUFFER_OPT (keyLength)const void * key,IN_LENGTH_SHORT_OPT const int keyLength)549 static int initKey( INOUT CONTEXT_INFO *contextInfoPtr,
550 					IN_BUFFER_OPT( keyLength ) const void *key,
551 					IN_LENGTH_SHORT_OPT const int keyLength )
552 	{
553 	PKC_INFO *pkcInfo = contextInfoPtr->ctxPKC;
554 
555 	assert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );
556 	assert( ( key == NULL && keyLength == 0 ) || \
557 			( isReadPtr( key, keyLength ) && \
558 			  keyLength == sizeof( CRYPT_PKCINFO_DLP ) ) );
559 
560 	REQUIRES( ( key == NULL && keyLength == 0 ) || \
561 			  ( key != NULL && keyLength == sizeof( CRYPT_PKCINFO_DLP ) ) );
562 
563 #ifndef USE_FIPS140
564 	/* Load the key component from the external representation into the
565 	   internal bignums unless we're doing an internal load */
566 	if( key != NULL )
567 		{
568 		const CRYPT_PKCINFO_DLP *egKey = ( CRYPT_PKCINFO_DLP * ) key;
569 		int status;
570 
571 		/* Load the key components into the bignums */
572 		contextInfoPtr->flags |= ( egKey->isPublicKey ) ? \
573 					CONTEXT_FLAG_ISPUBLICKEY : CONTEXT_FLAG_ISPRIVATEKEY;
574 		status = importBignum( &pkcInfo->dlpParam_p, egKey->p,
575 							   bitsToBytes( egKey->pLen ),
576 							   DLPPARAM_MIN_P, DLPPARAM_MAX_P, NULL,
577 							   KEYSIZE_CHECK_PKC );
578 		if( cryptStatusOK( status ) )
579 			status = importBignum( &pkcInfo->dlpParam_g, egKey->g,
580 								   bitsToBytes( egKey->gLen ),
581 								   DLPPARAM_MIN_G, DLPPARAM_MAX_G,
582 								   &pkcInfo->dlpParam_p,
583 								   KEYSIZE_CHECK_NONE );
584 		if( cryptStatusOK( status ) )
585 			status = importBignum( &pkcInfo->dlpParam_q, egKey->q,
586 								   bitsToBytes( egKey->qLen ),
587 								   DLPPARAM_MIN_Q, DLPPARAM_MAX_Q,
588 								   &pkcInfo->dlpParam_p,
589 								   KEYSIZE_CHECK_NONE );
590 		if( cryptStatusOK( status ) )
591 			status = importBignum( &pkcInfo->dlpParam_y, egKey->y,
592 								   bitsToBytes( egKey->yLen ),
593 								   DLPPARAM_MIN_Y, DLPPARAM_MAX_Y,
594 								   &pkcInfo->dlpParam_p,
595 								   KEYSIZE_CHECK_NONE );
596 		if( cryptStatusOK( status ) && !egKey->isPublicKey )
597 			status = importBignum( &pkcInfo->dlpParam_x, egKey->x,
598 								   bitsToBytes( egKey->xLen ),
599 								   DLPPARAM_MIN_X, DLPPARAM_MAX_X,
600 								   &pkcInfo->dlpParam_p,
601 								   KEYSIZE_CHECK_NONE );
602 		contextInfoPtr->flags |= CONTEXT_FLAG_PBO;
603 		if( cryptStatusError( status ) )
604 			return( status );
605 
606 		ENSURES( sanityCheckPKCInfo( pkcInfo ) );
607 		}
608 #endif /* USE_FIPS140 */
609 
610 	/* Complete the key checking and setup.  PGP Elgamal keys don't follow
611 	   X9.42 and are effectively PKCS #3 keys so if the key is being
612 	   instantiated from PGP key data and doesn't have a q parameter we mark
613 	   it as a PKCS #3 key to ensure that it doesn't fail the validity check
614 	   for q != 0 */
615 	if( key == NULL && \
616 		( contextInfoPtr->flags & CONTEXT_FLAG_OPENPGPKEYID_SET ) && \
617 		BN_is_zero( &pkcInfo->dlpParam_q ) )
618 		{
619 		/* It's a PGP Elgamal key, treat it as a PKCS #3 key for checking
620 		   purposes */
621 		return( initCheckDLPkey( contextInfoPtr, FALSE, TRUE ) );
622 		}
623 	return( initCheckDLPkey( contextInfoPtr, FALSE, FALSE ) );
624 	}
625 
626 /* Generate a key into an encryption context */
627 
628 CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
629 static int generateKey( INOUT CONTEXT_INFO *contextInfoPtr,
630 						IN_LENGTH_SHORT_MIN( MIN_PKCSIZE * 8 ) \
631 							const int keySizeBits )
632 	{
633 	int status;
634 
635 	assert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );
636 
637 	REQUIRES( keySizeBits >= bytesToBits( MIN_PKCSIZE ) && \
638 			  keySizeBits <= bytesToBits( CRYPT_MAX_PKCSIZE ) );
639 
640 	status = generateDLPkey( contextInfoPtr, keySizeBits );
641 	if( cryptStatusOK( status ) &&
642 #ifndef USE_FIPS140
643 		( contextInfoPtr->flags & CONTEXT_FLAG_SIDECHANNELPROTECTION ) &&
644 #endif /* USE_FIPS140 */
645 		!pairwiseConsistencyTest( contextInfoPtr, TRUE ) )
646 		{
647 		DEBUG_DIAG(( "Consistency check of freshly-generated Elgamal key "
648 					 "failed" ));
649 		assert( DEBUG_WARN );
650 		status = CRYPT_ERROR_FAILED;
651 		}
652 	return( cryptArgError( status ) ? CRYPT_ERROR_FAILED : status );
653 	}
654 
655 /****************************************************************************
656 *																			*
657 *						Capability Access Routines							*
658 *																			*
659 ****************************************************************************/
660 
661 static const CAPABILITY_INFO FAR_BSS capabilityInfo = {
662 	CRYPT_ALGO_ELGAMAL, bitsToBytes( 0 ), "Elgamal", 7,
663 	MIN_PKCSIZE, bitsToBytes( 1536 ), CRYPT_MAX_PKCSIZE,
664 	selfTest, getDefaultInfo, NULL, NULL, initKey, generateKey,
665 	encryptFn, decryptFn
666 	};
667 
getElgamalCapability(void)668 const CAPABILITY_INFO *getElgamalCapability( void )
669 	{
670 	return( &capabilityInfo );
671 	}
672 
673 #endif /* USE_ELGAMAL */
674