cryptlib  3.4.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Macros
ctx_elg.c
Go to the documentation of this file.
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 
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/*2*/, "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 \
178 static int selfTest( void )
179  {
180  CONTEXT_INFO contextInfo;
181  PKC_INFO contextData, *pkcInfo = &contextData;
182  int status;
183 
184  /* Initialise the key components */
185  status = staticInitContext( &contextInfo, CONTEXT_PKC,
186  getElgamalCapability(), &contextData,
187  sizeof( PKC_INFO ), NULL );
188  if( cryptStatusError( status ) )
189  return( CRYPT_ERROR_FAILED );
190  status = importBignum( &pkcInfo->dlpParam_p, dlpTestKey.p,
191  dlpTestKey.pLen, DLPPARAM_MIN_P,
193  if( cryptStatusOK( status ) )
194  status = importBignum( &pkcInfo->dlpParam_g, dlpTestKey.g,
195  dlpTestKey.gLen, DLPPARAM_MIN_G,
196  DLPPARAM_MAX_G, &pkcInfo->dlpParam_p,
198  if( cryptStatusOK( status ) )
199  status = importBignum( &pkcInfo->dlpParam_q, dlpTestKey.q,
200  dlpTestKey.qLen, DLPPARAM_MIN_Q,
201  DLPPARAM_MAX_Q, &pkcInfo->dlpParam_p,
203  if( cryptStatusOK( status ) )
204  status = importBignum( &pkcInfo->dlpParam_y, dlpTestKey.y,
205  dlpTestKey.yLen, DLPPARAM_MIN_Y,
206  DLPPARAM_MAX_Y, &pkcInfo->dlpParam_p,
208  if( cryptStatusOK( status ) )
209  status = importBignum( &pkcInfo->dlpParam_x, dlpTestKey.x,
210  dlpTestKey.xLen, DLPPARAM_MIN_X,
211  DLPPARAM_MAX_X, &pkcInfo->dlpParam_p,
213  if( cryptStatusError( status ) )
214  {
215  staticDestroyContext( &contextInfo );
216  retIntError();
217  }
218 
219  /* Perform a test a sig generation/check and test en/decryption */
220 #if 0 /* See comment in sig.code */
221  memset( buffer, '*', 20 );
222  status = capabilityInfoPtr->signFunction( &contextInfoPtr, buffer, -1 );
223  if( !cryptStatusError( status ) )
224  {
225  memmove( buffer + 20, buffer, status );
226  memset( buffer, '*', 20 );
227  status = capabilityInfoPtr->sigCheckFunction( &contextInfoPtr,
228  buffer, 20 + status );
229  }
230  if( status != CRYPT_OK )
231  status = CRYPT_ERROR_FAILED;
232 #endif /* 0 */
233  status = contextInfo.capabilityInfo->initKeyFunction( &contextInfo, NULL, 0 );
234  if( cryptStatusOK( status ) && \
235  !pairwiseConsistencyTest( &contextInfo, FALSE ) )
236  status = CRYPT_ERROR_FAILED;
237 
238  /* Clean up */
239  staticDestroyContext( &contextInfo );
240 
241  return( status );
242  }
243 #else
244  #define selfTest NULL
245 #endif /* !CONFIG_NO_SELFTEST */
246 
247 /****************************************************************************
248 * *
249 * Create/Check a Signature *
250 * *
251 ****************************************************************************/
252 
253 /* Elgamal signatures have potential security problems (although this isn't
254  an issue when they're used in a PKCS #1 manner, OTOH nothing apart from
255  cryptlib uses them like this) while the equivalent DSA signatures don't
256  (or at least have less than Elgamal). In addition since nothing uses
257  them anyway this code, while fully functional, is disabled (there's no
258  benefit to having it present and active) */
259 
260 #if 0
261 
262 /* Since Elgamal signature generation produces two values and the
263  cryptEncrypt() model only provides for passing a byte string in and out
264  (or, more specifically, the internal bignum data can't be exported to the
265  outside world), we need to encode the resulting data into a flat format.
266  This is done by encoding the output as an Elgamal-Sig record:
267 
268  Elgamal-Sig ::= SEQUENCE {
269  r INTEGER,
270  s INTEGER
271  }
272 
273  The input is the 160-bit hash, usually SHA but possibly also RIPEMD-160 */
274 
275 /* The size of the Elgamal signature hash component is 160 bits */
276 
277 #define ELGAMAL_SIGPART_SIZE 20
278 
279 /* Sign a single block of data */
280 
281 static int sign( CONTEXT_INFO *contextInfoPtr, BYTE *buffer, int noBytes )
282  {
283  PKC_INFO *pkcInfo = &contextInfoPtr->ctxPKC;
284  BIGNUM *p = &pkcInfo->dlpParam_p, *g = &pkcInfo->dlpParam_g;
285  BIGNUM *x = &pkcInfo->dlpParam_x;
286  BIGNUM *tmp = &pkcInfo->tmp1, *k = &pkcInfo->tmp2, *kInv = &pkcInfo->tmp3;
287  BIGNUM *r = &pkcInfo->dlpTmp1, *s = &pkcInfo->dlpTmp2;
288  BIGNUM *phi_p = &pkcInfo->dlpTmp3;
289  BYTE *bufPtr = buffer;
290  int length, status = CRYPT_OK;
291 
292  assert( noBytes == ELGAMAL_SIGPART_SIZE || noBytes == -1 );
293 
294  /* Generate the secret random value k. During the initial self-test
295  the random data pool may not exist yet, and may in fact never exist in
296  a satisfactory condition if there isn't enough randomness present in
297  the system to generate cryptographically strong random numbers. To
298  bypass this problem, if the caller passes in a noBytes value that
299  can't be passed in via a call to cryptEncrypt() we know it's an
300  internal self-test call and use a fixed bit pattern for k that avoids
301  having to call generateBignum(). This is a somewhat ugly use of
302  'magic numbers', but it's safe because cryptEncrypt() won't allow any
303  such value for noBytes so there's no way an external caller can pass
304  in a value like this */
305  if( noBytes == -1 )
306  {
307  status = importBignum( k, ( BYTE * ) kVal, ELGAMAL_SIGPART_SIZE,
308  ELGAMAL_SIGPART_SIZE, ELGAMAL_SIGPART_SIZE,
309  q, KEYSIZE_CHECK_NONE );
310  }
311  else
312  {
313  status = generateBignum( k, bytesToBits( ELGAMAL_SIGPART_SIZE + \
315  0x80, 0, FALSE );
316  }
317  if( cryptStatusError( status ) )
318  return( status );
319 
320  /* Generate phi( p ) and use it to get k, k < p-1 and k relatively prime
321  to p-1. Since (p-1)/2 is prime, the initial choice for k will be
322  divisible by (p-1)/2 with probability 2/(p-1), so we'll do at most two
323  gcd operations with very high probability. A k of (p-3)/2 will be
324  chosen with probability 3/(p-1), and all other numbers from 1 to p-1
325  will be chosen with probability 2/(p-1), giving a nearly uniform
326  distribution of exponents */
327  BN_copy( phi_p, p );
328  BN_sub_word( phi_p, 1 ); /* phi( p ) = p - 1 */
329  BN_mod( k, k, phi_p, /* Reduce k to the correct range */
330  pkcInfo->bnCTX );
331  BN_gcd( r, k, phi_p, pkcInfo->bnCTX );
332  while( !BN_is_one( r ) )
333  {
334  BN_sub_word( k, 1 );
335  BN_gcd( r, k, phi_p, pkcInfo->bnCTX );
336  }
337 
338  /* Move the data from the buffer into a bignum */
339  status = importBignum( s, bufPtr, ELGAMAL_SIGPART_SIZE, q,
341  if( cryptStatusError( status ) )
342  return( status );
343 
344  /* r = g^k mod p */
345  BN_mod_exp_mont( r, g, k, p, pkcInfo->bnCTX, &pkcInfo->dlpParam_mont_p );
346  /* r = g^k mod p */
347 
348  /* s = ( k^-1 * ( hash - x * r ) ) mod phi( p ) */
349  kInv = BN_mod_inverse( k, phi_p, /* k = ( k^-1 ) mod phi( p ) */
350  pkcInfo->bnCTX );
351  BN_mod_mul( tmp, x, r, phi_p, /* tmp = ( x * r ) mod phi( p ) */
352  pkcInfo->bnCTX );
353  if( BN_cmp( s, tmp ) < 0 ) /* if hash < x * r */
354  BN_add( s, s, phi_p ); /* hash = hash + phi( p ) (fast mod) */
355  BN_sub( s, s, tmp ); /* s = hash - x * r */
356  BN_mod_mul( s, s, kInv, phi_p, /* s = ( s * k^-1 ) mod phi( p ) */
357  pkcInfo->bnCTX );
358 
359  /* Encode the result as a DL data block */
360  length = encodeDLValues( buffer, r, s );
361 
362  return( ( status == -1 ) ? CRYPT_ERROR_FAILED : length );
363  }
364 
365 /* Signature check a single block of data */
366 
367 static int sigCheck( CONTEXT_INFO *contextInfoPtr, BYTE *buffer, int noBytes )
368  {
369  PKC_INFO *pkcInfo = &contextInfoPtr->ctxPKC;
370  BIGNUM *p = &pkcInfo->dlpParam_p, *g = &pkcInfo->dlpParam_g;
371  BIGNUM *y = &pkcInfo->dlpParam_y;
372  BIGNUM *r = &pkcInfo->tmp1, *s = &pkcInfo->tmp1;
373  int status;
374 
375  /* Decode the values from a DL data block and make sure that r and s are
376  valid */
377  status = decodeDLValues( buffer + ELGAMAL_SIGPART_SIZE, noBytes, &r, &s );
378  if( cryptStatusError( status ) )
379  return( status );
380 
381  /* Verify that 0 < r < p. If this check isn't done, an adversary can
382  forge signatures given one existing valid signature for a key */
383  if( BN_is_zero( r ) || BN_cmp( r, p ) >= 0 )
384  status = CRYPT_ERROR_SIGNATURE;
385  else
386  {
387  BIGNUM *hash, *u1, *u2;
388 
389  hash = BN_new();
390  u1 = BN_new();
391  u2 = BN_new();
392 
393  status = importBignum( hash, buffer, ELGAMAL_SIGPART_SIZE,
394  &pkcInfo->dlpParam_p, KEYSIZE_CHECK_NONE );
395  if( cryptStatusError( status ) )
396  return( status );
397 
398  /* u1 = ( y^r * r^s ) mod p */
399  BN_mod_exp_mont( u1, y, r, p, /* y' = ( y^r ) mod p */
400  pkcInfo->bnCTX, &pkcInfo->dlpParam_mont_p );
401  BN_mod_exp_mont( r, r, s, p, /* r' = ( r^s ) mod p */
402  pkcInfo->bnCTX, &pkcInfo->dlpParam_mont_p );
403  BN_mod_mul_mont( u1, u1, r, p, /* u1 = ( y' * r' ) mod p */
404  pkcInfo->bnCTX, &pkcInfo->dlpParam_mont_p );
405 
406  /* u2 = g^hash mod p */
407  BN_mod_exp_mont( u2, g, hash, p, pkcInfo->bnCTX,
408  &pkcInfo->dlpParam_mont_p );
409 
410  /* if u1 == u2, signature is good */
411  if( BN_cmp( u1, u2 ) && cryptStatusOK( status ) )
412  status = CRYPT_ERROR_SIGNATURE;
413 
414  BN_clear_free( hash );
415  BN_clear_free( u2 );
416  BN_clear_free( u1 );
417  }
418 
419  return( status );
420  }
421 #endif /* 0 */
422 
423 /****************************************************************************
424 * *
425 * Encrypt/Decrypt a Data Block *
426 * *
427 ****************************************************************************/
428 
429 /* Encrypt a single block of data. We have to append the distinguisher 'Fn'
430  to the name since some systems already have 'encrypt' and 'decrypt' in
431  their standard headers */
432 
433 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
434 static int encryptFn( INOUT CONTEXT_INFO *contextInfoPtr,
435  INOUT_BUFFER_FIXED( noBytes ) BYTE *buffer,
436  IN_LENGTH_FIXED( sizeof( DLP_PARAMS ) ) int noBytes )
437  {
438  PKC_INFO *pkcInfo = contextInfoPtr->ctxPKC;
439  DLP_PARAMS *dlpParams = ( DLP_PARAMS * ) buffer;
440  BIGNUM *p = &pkcInfo->dlpParam_p, *g = &pkcInfo->dlpParam_g;
441  BIGNUM *y = &pkcInfo->dlpParam_y;
442  BIGNUM *tmp = &pkcInfo->tmp1, *k = &pkcInfo->tmp2;
443  BIGNUM *r = &pkcInfo->tmp3, *s = &pkcInfo->dlpTmp1;
444  BIGNUM *phi_p = &pkcInfo->dlpTmp2;
445  const int length = bitsToBytes( pkcInfo->keySizeBits );
446  int i, bnStatus = BN_STATUS, status;
447 
448  assert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );
449  assert( isWritePtr( dlpParams, sizeof( DLP_PARAMS ) ) );
450  assert( isReadPtr( dlpParams->inParam1, dlpParams->inLen1 ) );
451  assert( isWritePtr( dlpParams->outParam, dlpParams->outLen ) );
452 
453  REQUIRES( noBytes == sizeof( DLP_PARAMS ) );
454  REQUIRES( dlpParams->inLen1 == length );
455  REQUIRES( dlpParams->inParam2 == NULL && \
456  ( dlpParams->inLen2 == 0 || dlpParams->inLen2 == -999 ) );
457  REQUIRES( dlpParams->outLen >= ( 2 + length ) * 2 && \
458  dlpParams->outLen < MAX_INTLENGTH_SHORT );
459 
460  /* Make sure that we're not being fed suspiciously short data
461  quantities. importBignum() performs a more rigorous check, but we
462  use this as a lint filter before performing the relatively expensive
463  random bignum generation and preprocessing */
464  for( i = 0; i < length; i++ )
465  {
466  if( buffer[ i ] != 0 )
467  break;
468  }
469  if( length - i < MIN_PKCSIZE - 8 )
470  return( CRYPT_ERROR_BADDATA );
471 
472  /* Generate the secret random value k. During the initial self-test
473  the random data pool may not exist yet, and may in fact never exist in
474  a satisfactory condition if there isn't enough randomness present in
475  the system to generate cryptographically strong random numbers. To
476  bypass this problem, if the caller passes in a second length parameter
477  of -999, we know that it's an internal self-test call and use a fixed
478  bit pattern for k that avoids having to call generateBignum(). This
479  is a somewhat ugly use of 'magic numbers', but it's safe because this
480  function can only be called internally, so all we need to trap is
481  accidental use of the parameter which is normally unused */
482  if( dlpParams->inLen2 == -999 )
483  {
484  status = importBignum( k, ( BYTE * ) kRandomVal, length,
485  length, length, NULL, KEYSIZE_CHECK_NONE );
486  }
487  else
488  {
489  /* Generate the random value k, with the same 32-bit adjustment used
490  in the DSA code to avoid bias in the output (the only real
491  difference is that we eventually reduce it mode phi(p) rather than
492  mod q) */
493  status = generateBignum( k, bytesToBits( length + \
494  DLP_OVERFLOW_SIZE ), 0x80, 0 );
495  }
496  if( cryptStatusError( status ) )
497  return( status );
498 
499  /* Generate phi( p ) and use it to get k, k < p-1 and k relatively prime
500  to p-1. Since (p-1)/2 is prime, the initial choice for k will be
501  divisible by (p-1)/2 with probability 2/(p-1), so we'll do at most two
502  gcd operations with very high probability. A k of (p-3)/2 will be
503  chosen with probability 3/(p-1), and all other numbers from 1 to p-1
504  will be chosen with probability 2/(p-1), giving a nearly uniform
505  distribution of exponents */
506  CKPTR( BN_copy( phi_p, p ) );
507  CK( BN_sub_word( phi_p, 1 ) ); /* phi( p ) = p - 1 */
508  CK( BN_mod( k, k, phi_p, /* Reduce k to the correct range */
509  pkcInfo->bnCTX ) );
510  CK( BN_gcd( s, k, phi_p, pkcInfo->bnCTX ) );
511  while( bnStatusOK( bnStatus ) && !BN_is_one( s ) )
512  {
513  CK( BN_sub_word( k, 1 ) );
514  CK( BN_gcd( s, k, phi_p, pkcInfo->bnCTX ) );
515  }
516  if( bnStatusError( bnStatus ) )
517  return( getBnStatus( bnStatus ) );
518 
519  /* Move the input data into a bignum */
520  status = importBignum( tmp, ( BYTE * ) dlpParams->inParam1, length,
523  if( cryptStatusError( status ) )
524  return( status );
525 
526  /* s = ( y^k * M ) mod p */
527  CK( BN_mod_exp_mont( r, y, k, p, /* y' = y^k mod p */
528  pkcInfo->bnCTX, &pkcInfo->dlpParam_mont_p ) );
529  CK( BN_mod_mul( s, r, tmp, p, /* s = y'M mod p */
530  pkcInfo->bnCTX ) );
531  if( bnStatusError( bnStatus ) )
532  return( getBnStatus( bnStatus ) );
533 
534  /* r = g^k mod p */
535  CK( BN_mod_exp_mont( r, g, k, p, pkcInfo->bnCTX,
536  &pkcInfo->dlpParam_mont_p ) );
537  if( bnStatusError( bnStatus ) )
538  return( getBnStatus( bnStatus ) );
539 
540  /* Encode the result as a DL data block */
541  status = pkcInfo->encodeDLValuesFunction( dlpParams->outParam,
542  dlpParams->outLen, &dlpParams->outLen,
543  r, s, dlpParams->formatType );
544  if( cryptStatusError( status ) )
545  return( status );
546 
547  /* Perform side-channel attack checks if necessary */
548  if( ( contextInfoPtr->flags & CONTEXT_FLAG_SIDECHANNELPROTECTION ) && \
549  cryptStatusError( calculateBignumChecksum( pkcInfo,
550  CRYPT_ALGO_ELGAMAL ) ) )
551  {
552  return( CRYPT_ERROR_FAILED );
553  }
554  return( CRYPT_OK );
555  }
556 
557 /* Decrypt a single block of data */
558 
559 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
560 static int decryptFn( INOUT CONTEXT_INFO *contextInfoPtr,
561  INOUT_BUFFER_FIXED( noBytes ) BYTE *buffer,
562  IN_LENGTH_FIXED( sizeof( DLP_PARAMS ) ) int noBytes )
563  {
564  PKC_INFO *pkcInfo = contextInfoPtr->ctxPKC;
565  DLP_PARAMS *dlpParams = ( DLP_PARAMS * ) buffer;
566  BIGNUM *p = &pkcInfo->dlpParam_p, *x = &pkcInfo->dlpParam_x;
567  BIGNUM *r = &pkcInfo->tmp1, *s = &pkcInfo->tmp2, *tmp = &pkcInfo->tmp3;
568  const int length = bitsToBytes( pkcInfo->keySizeBits );
569  int offset, dummy, bnStatus = BN_STATUS, status;
570 
571  assert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );
572  assert( isWritePtr( dlpParams, sizeof( DLP_PARAMS ) ) );
573  assert( isReadPtr( dlpParams->inParam1, dlpParams->inLen1 ) );
574  assert( isWritePtr( dlpParams->outParam, dlpParams->outLen ) );
575 
576  REQUIRES( noBytes == sizeof( DLP_PARAMS ) );
577  REQUIRES( dlpParams->inLen1 >= ( 2 + ( length - 2 ) ) * 2 && \
578  dlpParams->inLen1 < MAX_INTLENGTH_SHORT );
579  REQUIRES( dlpParams->inParam2 == NULL && dlpParams->inLen2 == 0 );
580  REQUIRES( dlpParams->outLen >= length && \
581  dlpParams->outLen < MAX_INTLENGTH_SHORT );
582 
583  /* Decode the values from a DL data block and make sure that r and s are
584  valid, i.e. r, s = [1...p-1] */
585  status = pkcInfo->decodeDLValuesFunction( dlpParams->inParam1,
586  dlpParams->inLen1, r, s, p,
587  dlpParams->formatType );
588  if( cryptStatusError( status ) )
589  return( status );
590 
591  /* M = ( s / ( r^x ) ) mod p */
592  CK( BN_mod_exp_mont( r, r, x, p, /* r' = r^x */
593  pkcInfo->bnCTX, &pkcInfo->dlpParam_mont_p ) );
594  CKPTR( BN_mod_inverse( tmp, r, p, /* r'' = r'^-1 */
595  pkcInfo->bnCTX ) );
596  CK( BN_mod_mul( s, s, tmp, p, /* s = s * r'^-1 mod p */
597  pkcInfo->bnCTX ) );
598  if( bnStatusError( bnStatus ) )
599  return( getBnStatus( bnStatus ) );
600 
601  /* Copy the result to the output. Since the bignum code performs
602  leading-zero truncation, we have to adjust where we copy the
603  result to in the buffer to take into account extra zero bytes
604  that aren't extracted from the bignum. In addition we can't use
605  the length returned from exportBignum() because this is the length
606  of the zero-truncated result, not the full length */
607  offset = length - BN_num_bytes( s );
608  if( offset > 0 )
609  memset( dlpParams->outParam, 0, offset );
610  dlpParams->outLen = length;
611  status = exportBignum( dlpParams->outParam + offset,
612  dlpParams->outLen - offset, &dummy, s );
613  if( cryptStatusError( status ) )
614  return( status );
615 
616  /* Perform side-channel attack checks if necessary */
617  if( ( contextInfoPtr->flags & CONTEXT_FLAG_SIDECHANNELPROTECTION ) && \
618  cryptStatusError( calculateBignumChecksum( pkcInfo,
619  CRYPT_ALGO_ELGAMAL ) ) )
620  {
621  return( CRYPT_ERROR_FAILED );
622  }
623  return( CRYPT_OK );
624  }
625 
626 /****************************************************************************
627 * *
628 * Key Management *
629 * *
630 ****************************************************************************/
631 
632 /* Load key components into an encryption context */
633 
635 static int initKey( INOUT CONTEXT_INFO *contextInfoPtr,
636  IN_BUFFER_OPT( keyLength ) const void *key,
637  IN_LENGTH_SHORT_OPT const int keyLength )
638  {
639  PKC_INFO *pkcInfo = contextInfoPtr->ctxPKC;
640 
641  assert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );
642  assert( ( key == NULL && keyLength == 0 ) || \
643  ( isReadPtr( key, keyLength ) && \
644  keyLength == sizeof( CRYPT_PKCINFO_DLP ) ) );
645 
646  REQUIRES( ( key == NULL && keyLength == 0 ) || \
647  ( key != NULL && keyLength == sizeof( CRYPT_PKCINFO_DLP ) ) );
648 
649 #ifndef USE_FIPS140
650  /* Load the key component from the external representation into the
651  internal bignums unless we're doing an internal load */
652  if( key != NULL )
653  {
654  const CRYPT_PKCINFO_DLP *egKey = ( CRYPT_PKCINFO_DLP * ) key;
655  int status;
656 
657  /* Load the key components into the bignums */
658  contextInfoPtr->flags |= ( egKey->isPublicKey ) ? \
660  status = importBignum( &pkcInfo->dlpParam_p, egKey->p,
661  bitsToBytes( egKey->pLen ),
664  if( cryptStatusOK( status ) )
665  status = importBignum( &pkcInfo->dlpParam_g, egKey->g,
666  bitsToBytes( egKey->gLen ),
668  &pkcInfo->dlpParam_p,
670  if( cryptStatusOK( status ) )
671  status = importBignum( &pkcInfo->dlpParam_q, egKey->q,
672  bitsToBytes( egKey->qLen ),
674  &pkcInfo->dlpParam_p,
676  if( cryptStatusOK( status ) )
677  status = importBignum( &pkcInfo->dlpParam_y, egKey->y,
678  bitsToBytes( egKey->yLen ),
680  &pkcInfo->dlpParam_p,
682  if( cryptStatusOK( status ) && !egKey->isPublicKey )
683  status = importBignum( &pkcInfo->dlpParam_x, egKey->x,
684  bitsToBytes( egKey->xLen ),
686  &pkcInfo->dlpParam_p,
688  contextInfoPtr->flags |= CONTEXT_FLAG_PBO;
689  if( cryptStatusError( status ) )
690  return( status );
691  }
692 #endif /* USE_FIPS140 */
693 
694  /* Complete the key checking and setup. PGP Elgamal keys don't follow
695  X9.42 and are effectively PKCS #3 keys so if the key is being
696  instantiated from PGP key data and doesn't have a q parameter we mark
697  it as a PKCS #3 key to ensure that it doesn't fail the validity check
698  for q != 0 */
699  if( key == NULL && \
700  ( contextInfoPtr->flags & CONTEXT_FLAG_OPENPGPKEYID_SET ) && \
701  BN_is_zero( &pkcInfo->dlpParam_q ) )
702  {
703  /* It's a PGP Elgamal key, treat it as a PKCS #3 key for checking
704  purposes */
705  return( initCheckDLPkey( contextInfoPtr, FALSE, TRUE ) );
706  }
707  return( initCheckDLPkey( contextInfoPtr, FALSE, FALSE ) );
708  }
709 
710 /* Generate a key into an encryption context */
711 
713 static int generateKey( INOUT CONTEXT_INFO *contextInfoPtr,
715  const int keySizeBits )
716  {
717  int status;
718 
719  assert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );
720 
721  REQUIRES( keySizeBits >= bytesToBits( MIN_PKCSIZE ) && \
722  keySizeBits <= bytesToBits( CRYPT_MAX_PKCSIZE ) );
723 
724  status = generateDLPkey( contextInfoPtr, keySizeBits );
725  if( cryptStatusOK( status ) &&
726 #ifndef USE_FIPS140
727  ( contextInfoPtr->flags & CONTEXT_FLAG_SIDECHANNELPROTECTION ) &&
728 #endif /* USE_FIPS140 */
729  !pairwiseConsistencyTest( contextInfoPtr, TRUE ) )
730  {
731  DEBUG_DIAG(( "Consistency check of freshly-generated Elgamal key "
732  "failed" ));
733  assert( DEBUG_WARN );
734  status = CRYPT_ERROR_FAILED;
735  }
736  return( status );
737  }
738 
739 /****************************************************************************
740 * *
741 * Capability Access Routines *
742 * *
743 ****************************************************************************/
744 
745 static const CAPABILITY_INFO FAR_BSS capabilityInfo = {
746  CRYPT_ALGO_ELGAMAL, bitsToBytes( 0 ), "Elgamal", 7,
748  selfTest, getDefaultInfo, NULL, NULL, initKey, generateKey, encryptFn, decryptFn
749  };
750 
752  {
753  return( &capabilityInfo );
754  }
755 
756 #endif /* USE_ELGAMAL */