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