cryptlib  3.4.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Macros
mech_pkwrap.c
Go to the documentation of this file.
1 /****************************************************************************
2 * *
3 * cryptlib PKC Key Wrap Mechanism Routines *
4 * Copyright Peter Gutmann 1992-2008 *
5 * *
6 ****************************************************************************/
7 
8 #ifdef INC_ALL
9  #include "crypt.h"
10  #include "mech_int.h"
11  #include "pgp.h"
12  #include "asn1.h"
13  #include "misc_rw.h"
14 #else
15  #include "crypt.h"
16  #include "mechs/mech_int.h"
17  #include "misc/pgp.h"
18  #include "enc_dec/asn1.h"
19  #include "enc_dec/misc_rw.h"
20 #endif /* Compiler-specific includes */
21 
22 /****************************************************************************
23 * *
24 * Utility Routines *
25 * *
26 ****************************************************************************/
27 
28 #if defined( USE_PGP ) || defined( USE_PGPKEYS )
29 
30 /* PGP checksums the PKCS #1 wrapped data even though this doesn't really
31  serve any purpose since any decryption error will corrupt the PKCS #1
32  padding, the following routine calculates this checksum and either
33  appends it to the data or checks it against the stored value */
34 
36 static int pgpGenerateChecksum( INOUT_BUFFER_FIXED( dataLength ) void *data,
38  const int dataLength,
39  IN_LENGTH_PKC const int keyDataLength )
40  {
41  STREAM stream;
42  BYTE *dataPtr = data;
43  int checksum = 0, i, status;
44 
45  assert( isWritePtr( data, dataLength ) );
46 
47  REQUIRES( dataLength > 0 && \
48  dataLength <= CRYPT_MAX_PKCSIZE + UINT16_SIZE );
49  REQUIRES( keyDataLength == dataLength - UINT16_SIZE );
50 
51  /* Calculate the checksum for the MPI */
52  for( i = 0; i < keyDataLength; i++ )
53  checksum += dataPtr[ i ];
54 
55  /* Append the checksum to the MPI data */
56  sMemOpen( &stream, dataPtr + keyDataLength, dataLength - keyDataLength );
57  status = writeUint16( &stream, checksum );
58  sMemDisconnect( &stream );
59 
60  return( status );
61  }
62 
64 static BOOLEAN pgpVerifyChecksum( IN_BUFFER( dataLength ) const void *data,
66  const int dataLength )
67  {
68  STREAM stream;
69  int checksum = 0, storedChecksum, i;
70 
71  assert( isReadPtr( data, dataLength ) );
72 
73  REQUIRES_B( dataLength > UINT16_SIZE && \
74  dataLength <= CRYPT_MAX_PKCSIZE + UINT16_SIZE );
75 
76  /* Calculate the checksum for the MPI and compare it to the appended
77  checksum. We don't have to check the return status of sgetc()
78  because an error status returned will cause the checksum comparison
79  to fail */
80  sMemConnect( &stream, data, dataLength );
81  for( i = 0; i < dataLength - UINT16_SIZE; i++ )
82  {
83  const int ch = sgetc( &stream );
84  if( cryptStatusError( ch ) )
85  {
86  sMemDisconnect( &stream );
87  return( FALSE );
88  }
89  checksum += ch;
90  }
91  storedChecksum = readUint16( &stream );
92  sMemDisconnect( &stream );
93 
94  return( storedChecksum == checksum );
95  }
96 
97 /* PGP includes the session key information alongside the encrypted key so
98  it's not really possible to import the key into a context in the
99  conventional sense. Instead, the import code has to create the context
100  as part of the import process and return it to the caller. This is ugly,
101  but less ugly than doing a raw import and handling the key directly in
102  the calling code */
103 
104 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
105 static int pgpExtractKey( OUT_HANDLE_OPT CRYPT_CONTEXT *iCryptContext,
106  IN_BUFFER( dataLength ) const BYTE *data,
107  IN_LENGTH_SHORT const int dataLength )
108  {
110  MESSAGE_CREATEOBJECT_INFO createInfo;
111  static const int mode = CRYPT_MODE_CFB; /* int vs.enum */
112  int status;
113 
114  assert( isWritePtr( iCryptContext, sizeof( CRYPT_CONTEXT ) ) );
115  assert( isReadPtr( data, dataLength ) );
116 
117  REQUIRES( dataLength >= MIN_KEYSIZE && dataLength <= CRYPT_MAX_PKCSIZE );
118 
119  /* Clear return value */
120  *iCryptContext = CRYPT_ERROR;
121 
122  /* Get the session key algorithm. We delay checking the algorithm ID
123  until after the checksum calculation to reduce the chance of being
124  used as an oracle */
125  status = pgpToCryptlibAlgo( data[ 0 ], PGP_ALGOCLASS_CRYPT, &cryptAlgo );
126 
127  /* Checksum the session key, skipping the algorithm ID at the start and
128  the checksum at the end. This is actually superfluous since any
129  decryption error will be caught by corrupted PKCS #1 padding with
130  vastly higher probability than this simple checksum but we do it
131  anyway because other PGP implementations do it too */
132  if( !pgpVerifyChecksum( data + 1, dataLength - 1 ) )
133  return( CRYPT_ERROR_BADDATA );
134 
135  /* Make sure that the algorithm ID is valid. We only perform the check
136  at this point because this returns a different error code than the
137  usual bad-data, we want to be absolutely sure that the problem really
138  is an unknown algorithm and not the result of scrambled decrypted
139  data */
140  if( cryptStatusError( status ) )
141  return( CRYPT_ERROR_NOTAVAIL );
142 
143  /* Create the context ready to have the key loaded into it */
144  setMessageCreateObjectInfo( &createInfo, cryptAlgo );
146  &createInfo, OBJECT_TYPE_CONTEXT );
147  if( cryptStatusError( status ) )
148  return( status );
149  status = krnlSendMessage( createInfo.cryptHandle, IMESSAGE_SETATTRIBUTE,
150  ( MESSAGE_CAST ) &mode, CRYPT_CTXINFO_MODE );
151  if( cryptStatusError( status ) )
153  else
154  *iCryptContext = createInfo.cryptHandle;
155 
156  return( CRYPT_OK );
157  }
158 #endif /* USE_PGP || USE_PGPKEYS */
159 
160 /****************************************************************************
161 * *
162 * Low-level Data Wrap/Unwrap Routines *
163 * *
164 ****************************************************************************/
165 
166 /* Wrap/unwrap data using a public/private-key context */
167 
169 static int pkcWrapData( INOUT MECHANISM_WRAP_INFO *mechanismInfo,
170  INOUT_BUFFER_FIXED( wrappedDataLength ) BYTE *wrappedData,
171  IN_LENGTH_PKC const int wrappedDataLength,
172  const BOOLEAN usePgpWrap, const BOOLEAN isDlpAlgo )
173  {
174  BYTE dataSample[ 16 + 8 ];
175  const void *samplePtr = wrappedData + ( wrappedDataLength / 2 );
176  int status;
177 
178  assert( isWritePtr( mechanismInfo, sizeof( MECHANISM_WRAP_INFO ) ) );
179  assert( isWritePtr( wrappedData, wrappedDataLength ) );
180 
181  REQUIRES( wrappedDataLength >= MIN_PKCSIZE && \
182  wrappedDataLength <= CRYPT_MAX_PKCSIZE );
183  REQUIRES( wrappedData[ 0 ] == 0x00 && \
184  ( wrappedData[ 1 ] == 0x01 || wrappedData[ 1 ] == 0x02 ) );
185 
186  /* Take a sample of the input for comparison with the output */
187  memcpy( dataSample, samplePtr, 16 );
188 
189  if( isDlpAlgo )
190  {
191  DLP_PARAMS dlpParams;
192 
193  /* For DLP-based PKC's the output length isn't the same as the key
194  size so we adjust the return length as required */
195  setDLPParams( &dlpParams, wrappedData, wrappedDataLength,
196  wrappedData, mechanismInfo->wrappedDataLength );
197  if( usePgpWrap )
198  dlpParams.formatType = CRYPT_FORMAT_PGP;
199  status = krnlSendMessage( mechanismInfo->wrapContext,
200  IMESSAGE_CTX_ENCRYPT, &dlpParams,
201  sizeof( DLP_PARAMS ) );
202  if( cryptStatusOK( status ) )
203  mechanismInfo->wrappedDataLength = dlpParams.outLen;
204  }
205  else
206  {
207  status = krnlSendMessage( mechanismInfo->wrapContext,
208  IMESSAGE_CTX_ENCRYPT, wrappedData,
209  wrappedDataLength );
210  if( cryptStatusOK( status ) )
211  mechanismInfo->wrappedDataLength = wrappedDataLength;
212  }
213  if( cryptStatusOK( status ) && !memcmp( dataSample, samplePtr, 16 ) )
214  {
215  /* The data to wrap is unchanged, there's been a catastrophic
216  failure of the encryption. We don't do a retIntError() at this
217  point because we want to at least continue and zeroise the data
218  first */
219  assert( FALSE );
220  status = CRYPT_ERROR_FAILED;
221  }
222  zeroise( dataSample, 16 );
223  if( cryptStatusError( status ) )
224  {
225  /* There was a problem with the wrapping, clear the output value */
226  zeroise( wrappedData, wrappedDataLength );
227  }
228 
229  return( status );
230  }
231 
233 static int pkcUnwrapData( MECHANISM_WRAP_INFO *mechanismInfo,
234  INOUT_BUFFER( dataMaxLength, *dataOutLength ) \
235  BYTE *data,
237  const int dataMaxLength,
238  OUT_LENGTH_PKC_Z int *dataOutLength,
240  const int dataInLength,
241  const BOOLEAN usePgpWrap,
242  const BOOLEAN isDlpAlgo )
243  {
244  int status;
245 
246  assert( isWritePtr( mechanismInfo, sizeof( MECHANISM_WRAP_INFO ) ) );
247  assert( isWritePtr( data, dataMaxLength ) );
248  assert( isWritePtr( dataOutLength, sizeof( int ) ) );
249 
250  REQUIRES( dataMaxLength >= MIN_PKCSIZE && \
251  dataMaxLength <= MAX_INTLENGTH_SHORT );
252  REQUIRES( dataInLength >= MIN_PKCSIZE && \
253  dataInLength <= dataMaxLength && \
254  dataInLength <= MAX_INTLENGTH_SHORT );
255 
256  /* Clear return values */
257  memset( data, 0, min( 16, dataMaxLength ) );
258  *dataOutLength = 0;
259 
260  if( isDlpAlgo )
261  {
262  DLP_PARAMS dlpParams;
263 
264  setDLPParams( &dlpParams, mechanismInfo->wrappedData,
265  mechanismInfo->wrappedDataLength, data,
266  dataMaxLength );
267  if( usePgpWrap )
268  dlpParams.formatType = CRYPT_FORMAT_PGP;
269  status = krnlSendMessage( mechanismInfo->wrapContext,
270  IMESSAGE_CTX_DECRYPT, &dlpParams,
271  sizeof( DLP_PARAMS ) );
272  if( cryptStatusOK( status ) )
273  {
274  *dataOutLength = dlpParams.outLen;
275  return( CRYPT_OK );
276  }
277  }
278  else
279  {
280  status = adjustPKCS1Data( data, dataMaxLength,
281  mechanismInfo->wrappedData,
282  mechanismInfo->wrappedDataLength,
283  dataInLength );
284  if( cryptStatusOK( status ) )
285  status = krnlSendMessage( mechanismInfo->wrapContext,
286  IMESSAGE_CTX_DECRYPT, data,
287  dataInLength );
288  if( cryptStatusOK( status ) )
289  {
290  *dataOutLength = dataInLength;
291  return( CRYPT_OK );
292  }
293  }
294 
295  /* There was a problem with the wrapping, clear the output value */
296  zeroise( data, dataMaxLength );
297  return( status );
298  }
299 
300 /****************************************************************************
301 * *
302 * PKCS #1 Wrap/Unwrap Mechanisms *
303 * *
304 ****************************************************************************/
305 
306 /* Generate/recover a PKCS #1 data block */
307 
309 static int generatePkcs1DataBlock( INOUT_BUFFER( dataMaxLen, *dataLength ) \
310  BYTE *data,
312  const int dataMaxLen,
313  OUT_LENGTH_SHORT_Z int *dataLength,
315  const int messageLen )
316  {
318  const int padSize = dataMaxLen - ( messageLen + 3 );
319  int status;
320 
321  assert( isWritePtr( data, dataMaxLen ) );
322  assert( isWritePtr( dataLength, sizeof( int ) ) );
323 
324  REQUIRES( dataMaxLen >= MIN_PKCSIZE && dataMaxLen < MAX_INTLENGTH_SHORT );
325  REQUIRES( messageLen >= MIN_KEYSIZE && messageLen < dataMaxLen && \
326  messageLen < MAX_INTLENGTH_SHORT );
327 
328  /* Clear return values */
329  memset( data, 0, min( 16, dataMaxLen ) );
330  *dataLength = 0;
331 
332  /* Determine PKCS #1 padding parameters and make sure that the key is
333  long enough to encrypt the payload. PKCS #1 requires that the
334  maximum payload size be 11 bytes less than the length to give a
335  minimum of 8 bytes of random padding */
336  if( messageLen > dataMaxLen - 11 )
337  return( CRYPT_ERROR_OVERFLOW );
338 
339  ENSURES( padSize >= 8 && messageLen + padSize + 3 <= dataMaxLen );
340 
341  /* Encode the payload using the PKCS #1 format:
342 
343  [ 0 ][ 2 ][ nonzero random padding ][ 0 ][ payload ]
344 
345  Note that the random padding is a nice place for a subliminal channel,
346  especially with the larger public key sizes where you can communicate
347  more information in the padding than you can in the payload */
348  data[ 0 ] = 0;
349  data[ 1 ] = 2;
350  setMessageData( &msgData, data + 2, padSize );
352  IMESSAGE_GETATTRIBUTE_S, &msgData,
353  CRYPT_IATTRIBUTE_RANDOM_NZ );
354  if( cryptStatusError( status ) )
355  {
356  zeroise( data, dataMaxLen );
357  return( status );
358  }
359  data[ 2 + padSize ] = 0;
360  *dataLength = 2 + padSize + 1;
361 
362  return( CRYPT_OK );
363  }
364 
365 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \
366 static int recoverPkcs1DataBlock( INOUT_BUFFER_FIXED( dataLength ) \
367  BYTE *data,
369  const int dataLength,
370  OUT_LENGTH_SHORT_Z int *padSize )
371  {
372  int ch, length;
373 
374  assert( isWritePtr( data, dataLength ) );
375  assert( isWritePtr( padSize, sizeof( int ) ) );
376 
377  REQUIRES( dataLength >= MIN_PKCSIZE && dataLength < MAX_INTLENGTH );
378 
379  /* Clear return value */
380  *padSize = 0;
381 
382  /* Undo the PKCS #1 padding:
383 
384  [ 0 ][ 2 ][ random nonzero padding ][ 0 ][ payload ]
385 
386  with a minimum of 8 bytes padding. Note that some implementations
387  may have bignum code that zero-truncates the result which will
388  produce a CRYPT_ERROR_BADDATA error when we undo the padding, it's
389  the responsibility of the lower-level crypto layer to reformat the
390  data to return a correctly-formatted result if necessary.
391 
392  In order to avoid being used as a decription timing oracle we bundle
393  all of the formatting checks into a single location and make the code
394  as simple and quick as possible. At best an attacker will get only a
395  few clock cycles of timing information, which should be lost in the
396  general noise */
397  if( dataLength < 11 + MIN_KEYSIZE )
398  {
399  /* PKCS #1 padding requires at least 11 (2 + 8 + 1) bytes of
400  padding data, if there isn't this much present then what we've
401  got can't be a valid payload */
402  return( CRYPT_ERROR_BADDATA );
403  }
404  if( data[ 0 ] != 0x00 || data[ 1 ] != 0x02 )
405  return( CRYPT_ERROR_BADDATA );
406  for( length = 2, ch = 0xFF;
407  length < dataLength - MIN_KEYSIZE && \
408  ( ch = byteToInt( data[ length ] ) ) != 0x00;
409  length++ );
410  if( ch != 0x00 || length < 11 )
411  return( CRYPT_ERROR_BADDATA );
412  length++; /* Skip the final 0x00 */
413 
414  /* Sanity check to make sure that the padding data looks OK. We only do
415  this in debug mode since it's a probabalistic test and we don't want
416  to bail out due to a false positive in production code */
417  assert( checkEntropy( data + 2, length - 1 ) );
418 
419  /* Make sure that there's enough room left after the remaining PKCS #1
420  padding to hold at least a minimum-length key */
421  if( dataLength - length < MIN_KEYSIZE )
422  return( CRYPT_ERROR_BADDATA );
423 
424  *padSize = length;
425 
426  return( CRYPT_OK );
427  }
428 
429 /* Perform PKCS #1 wrapping/unwrapping. There are several variations of
430  this that are handled through common PKCS #1 mechanism functions */
431 
434 
436 static int pkcs1Wrap( INOUT MECHANISM_WRAP_INFO *mechanismInfo,
437  IN_ENUM( PKCS1_WRAP ) const PKCS1_WRAP_TYPE type )
438  {
440  BYTE *wrappedData = mechanismInfo->wrappedData, *dataPtr;
441  int payloadSize, length, dataBlockSize, status;
442 #ifdef USE_PGP
443  int pgpAlgoID = DUMMY_INIT;
444 #endif /* USE_PGP */
445 
446  assert( isWritePtr( mechanismInfo, sizeof( MECHANISM_WRAP_INFO ) ) );
447 
448  REQUIRES( type > PKCS1_WRAP_NONE && type < PKCS1_WRAP_LAST );
449 
450  /* Clear return value */
451  if( mechanismInfo->wrappedData != NULL )
452  {
453  memset( mechanismInfo->wrappedData, 0,
454  mechanismInfo->wrappedDataLength );
455  }
456 
457  /* Get various algorithm parameters */
458  status = getPkcAlgoParams( mechanismInfo->wrapContext, &cryptAlgo,
459  &length );
460  if( cryptStatusError( status ) )
461  return( status );
462  ANALYSER_HINT( length > MIN_PKCSIZE && length <= CRYPT_MAX_PKCSIZE );
463 
464  /* If this is just a length check, we're done */
465  if( mechanismInfo->wrappedData == NULL )
466  {
467  /* Determine how long the encrypted value will be. In the case of
468  Elgamal it's just an estimate since it can change by up to two
469  bytes depending on whether the values have the high bit set or
470  not, which requires zero-padding of the ASN.1-encoded integers.
471  This is rather nasty because it means that we can't tell how
472  large an encrypted value will be without actually creating it.
473  The 10-byte length at the start is for the ASN.1 SEQUENCE (= 4)
474  and 2 * INTEGER (= 2*3) encoding */
475  mechanismInfo->wrappedDataLength = \
476  ( cryptAlgo == CRYPT_ALGO_ELGAMAL ) ? \
477  10 + ( 2 * ( length + 1 ) ) : length;
478  return( CRYPT_OK );
479  }
480 
481  /* Make sure that there's enough room for the wrapped key data */
482  if( length > mechanismInfo->wrappedDataLength )
483  return( CRYPT_ERROR_OVERFLOW );
484 
485  /* Get the payload details, either as data passed in by the caller or
486  from the key context */
487  if( type == PKCS1_WRAP_RAW )
488  payloadSize = mechanismInfo->keyDataLength;
489  else
490  {
491  status = krnlSendMessage( mechanismInfo->keyContext,
492  IMESSAGE_GETATTRIBUTE, &payloadSize,
494  if( cryptStatusError( status ) )
495  return( status );
496  }
497 #ifdef USE_PGP
498  if( type == PKCS1_WRAP_PGP )
499  {
500  int sessionKeyAlgo; /* int vs.enum */
501 
502  /* PGP includes an additional algorithm specifier and checksum with
503  the wrapped key so we adjust the length to take this into
504  account */
505  status = krnlSendMessage( mechanismInfo->keyContext,
506  IMESSAGE_GETATTRIBUTE, &sessionKeyAlgo,
508  if( cryptStatusOK( status ) )
509  status = cryptlibToPgpAlgo( sessionKeyAlgo, &pgpAlgoID );
510  if( cryptStatusError( status ) )
511  return( status );
512  payloadSize += 3; /* 1-byte algo ID + 2-byte checksum */
513  }
514 #endif /* USE_PGP */
515 
516  /* Perform a preliminary check for an excessively long payload to make
517  it explicit, however generatePkcs1DataBlock() will also perform a
518  more precise check when it performs the data formatting */
519  if( payloadSize >= length )
520  return( CRYPT_ERROR_OVERFLOW );
521 
522  /* Generate the PKCS #1 data block with room for the payload at the end */
523  status = generatePkcs1DataBlock( wrappedData, length, &dataBlockSize,
524  payloadSize );
525  if( cryptStatusError( status ) )
526  {
527  zeroise( wrappedData, length );
528  return( status );
529  }
530  ENSURES( dataBlockSize + payloadSize == length );
531 
532  /* Copy the payload in at the last possible moment, then encrypt it */
533  dataPtr = wrappedData + dataBlockSize;
534  switch( type )
535  {
536  case PKCS1_WRAP_NORMAL:
537  status = extractKeyData( mechanismInfo->keyContext, dataPtr,
538  payloadSize, "keydata", 7 );
539  break;
540 
541  case PKCS1_WRAP_RAW:
542  memcpy( dataPtr, mechanismInfo->keyData, payloadSize );
543  break;
544 
545 #ifdef USE_PGP
546  case PKCS1_WRAP_PGP:
547  *dataPtr++ = intToByte( pgpAlgoID );
548  status = extractKeyData( mechanismInfo->keyContext, dataPtr,
549  payloadSize - 3, "keydata", 7 );
550  if( cryptStatusOK( status ) )
551  {
552  status = pgpGenerateChecksum( dataPtr, payloadSize - 1,
553  payloadSize - ( 1 + UINT16_SIZE ) );
554  }
555  break;
556 #endif /* USE_PGP */
557 
558  default:
559  retIntError();
560  }
561  if( cryptStatusError( status ) )
562  {
563  zeroise( wrappedData, length );
564  return( status );
565  }
566 
567  /* Wrap the encoded data using the public key */
568  return( pkcWrapData( mechanismInfo, wrappedData, length,
569  ( type == PKCS1_WRAP_PGP ) ? TRUE : FALSE,
570  ( cryptAlgo == CRYPT_ALGO_ELGAMAL ) ? TRUE : FALSE ) );
571  }
572 
574 static int pkcs1Unwrap( INOUT MECHANISM_WRAP_INFO *mechanismInfo,
575  IN_ENUM( PKCS1_WRAP ) const PKCS1_WRAP_TYPE type )
576  {
579  BYTE decryptedData[ CRYPT_MAX_PKCSIZE + 8 ];
580  const BYTE *payloadPtr;
581  int length, dataBlockSize, status;
582 
583  assert( isWritePtr( mechanismInfo, sizeof( MECHANISM_WRAP_INFO ) ) );
584 
585  REQUIRES( type > PKCS1_WRAP_NONE && type < PKCS1_WRAP_LAST );
586 
587  /* Clear the return value if we're returning raw data */
588  if( type == PKCS1_WRAP_RAW )
589  memset( mechanismInfo->keyData, 0, mechanismInfo->keyDataLength );
590 
591  /* Get various algorithm parameters */
592  status = getPkcAlgoParams( mechanismInfo->wrapContext, &cryptAlgo,
593  &length );
594  if( cryptStatusError( status ) )
595  return( status );
596  ANALYSER_HINT( length > MIN_PKCSIZE && length <= CRYPT_MAX_PKCSIZE );
597 
598  /* Decrypt the data */
599  status = pkcUnwrapData( mechanismInfo, decryptedData, CRYPT_MAX_PKCSIZE,
600  &length, length,
601  ( type == PKCS1_WRAP_PGP ) ? TRUE : FALSE,
602  ( cryptAlgo == CRYPT_ALGO_ELGAMAL ) ? TRUE : FALSE );
603  if( cryptStatusError( status ) )
604  return( status );
605 
606  /* Recover the PKCS #1 data block, with the payload at the end */
607  status = recoverPkcs1DataBlock( decryptedData, length, &dataBlockSize );
608  if( cryptStatusError( status ) )
609  {
610  zeroise( decryptedData, CRYPT_MAX_PKCSIZE );
611  return( status );
612  }
613  payloadPtr = decryptedData + dataBlockSize;
614  length -= dataBlockSize;
615 
616  /* Return the result to the caller or load it into a context as a key */
617  switch( type )
618  {
619 #ifdef USE_PGP
620  case PKCS1_WRAP_PGP:
621  /* PGP includes extra wrapping around the key so we have to
622  process that before we can load it */
623  status = pgpExtractKey( &mechanismInfo->keyContext, payloadPtr,
624  length );
625  if( cryptStatusError( status ) )
626  break;
627  payloadPtr++; /* Skip algorithm ID */
628  length -= 3; /* Subtract extra wrapping length */
629  if( length < MIN_KEYSIZE )
630  return( CRYPT_ERROR_BADDATA );
631  /* Fall through */
632 #endif /* USE_PGP */
633 
634  case PKCS1_WRAP_NORMAL:
635  /* Load the decrypted keying information into the session key
636  context */
637  setMessageData( &msgData, ( MESSAGE_CAST ) payloadPtr, length );
638  status = krnlSendMessage( mechanismInfo->keyContext,
639  IMESSAGE_SETATTRIBUTE_S, &msgData,
641  if( cryptArgError( status ) )
642  {
643  /* If there was an error with the key value or size convert
644  the return value into something more appropriate */
645  status = CRYPT_ERROR_BADDATA;
646  }
647  break;
648 
649  case PKCS1_WRAP_RAW:
650  /* Return the result to the caller */
651  if( length > mechanismInfo->keyDataLength )
652  status = CRYPT_ERROR_OVERFLOW;
653  else
654  {
655  memcpy( mechanismInfo->keyData, payloadPtr, length );
656  mechanismInfo->keyDataLength = length;
657  }
658  break;
659 
660  default:
661  retIntError();
662  }
663  zeroise( decryptedData, CRYPT_MAX_PKCSIZE );
664 
665  return( status );
666  }
667 
669 int exportPKCS1( STDC_UNUSED void *dummy,
670  INOUT MECHANISM_WRAP_INFO *mechanismInfo )
671  {
672  UNUSED_ARG( dummy );
673 
674  assert( isWritePtr( mechanismInfo, sizeof( MECHANISM_WRAP_INFO ) ) );
675 
676  return( pkcs1Wrap( mechanismInfo,
677  ( mechanismInfo->keyContext == CRYPT_UNUSED ) ? \
679  }
680 
682 int importPKCS1( STDC_UNUSED void *dummy,
683  INOUT MECHANISM_WRAP_INFO *mechanismInfo )
684  {
685  UNUSED_ARG( dummy );
686 
687  assert( isWritePtr( mechanismInfo, sizeof( MECHANISM_WRAP_INFO ) ) );
688 
689  return( pkcs1Unwrap( mechanismInfo,
690  ( mechanismInfo->keyData != NULL ) ? \
692  }
693 
694 #ifdef USE_PGP
695 
697 int exportPKCS1PGP( STDC_UNUSED void *dummy,
698  INOUT MECHANISM_WRAP_INFO *mechanismInfo )
699  {
700  UNUSED_ARG( dummy );
701 
702  assert( isWritePtr( mechanismInfo, sizeof( MECHANISM_WRAP_INFO ) ) );
703 
704  return( pkcs1Wrap( mechanismInfo, PKCS1_WRAP_PGP ) );
705  }
706 
708 int importPKCS1PGP( STDC_UNUSED void *dummy,
709  INOUT MECHANISM_WRAP_INFO *mechanismInfo )
710  {
711  UNUSED_ARG( dummy );
712 
713  assert( isWritePtr( mechanismInfo, sizeof( MECHANISM_WRAP_INFO ) ) );
714 
715  return( pkcs1Unwrap( mechanismInfo, PKCS1_WRAP_PGP ) );
716  }
717 #endif /* USE_PGP */
718 
719 /****************************************************************************
720 * *
721 * OAEP Key Wrap/Unwrap Mechanisms *
722 * *
723 ****************************************************************************/
724 
725 #ifdef USE_OAEP
726 
727 /* Get the lHash value used for OAEP. In theory this should be a hash of a
728  label applied to the OAEP operation but this is never used so what ends
729  up being used is a fixed hash of an empty string. Since this is
730  constant we can use a pre-calculated value for each hash algorithm */
731 
732 typedef struct {
734  BUFFER_FIXED( lHashSize ) \
735  const BYTE FAR_BSS *lHash;
736  const int lHashSize;
737  } LHASH_INFO;
738 
739 static const LHASH_INFO FAR_BSS lHashInfo[] = {
740  { CRYPT_ALGO_SHA1, ( const BYTE * ) /* For pedantic compilers */
741  "\xDA\x39\xA3\xEE\x5E\x6B\x4B\x0D\x32\x55\xBF\xEF\x95\x60\x18\x90"
742  "\xAF\xD8\x07\x09", 20 },
743  { CRYPT_ALGO_SHA2, ( const BYTE * ) /* For pedantic compilers */
744  "\xE3\xB0\xC4\x42\x98\xFC\x1C\x14\x9A\xFB\xF4\xC8\x99\x6F\xB9\x24"
745  "\x27\xAE\x41\xE4\x64\x9B\x93\x4C\xA4\x95\x99\x1B\x78\x52\xB8\x55", 32 },
746 #ifdef USE_SHA2_EXT
747  /* SHA2-512 is only available on systems with 64-bit data type support */
748  { CRYPT_ALGO_SHA2, ( const BYTE * ) /* For pedantic compilers */
749  "\xCF\x83\xE1\x35\x7E\xEF\xB8\xBD\xF1\x54\x28\x50\xD6\x6D\x80\x07"
750  "\xD6\x20\xE4\x05\x0B\x57\x15\xDC\x83\xF4\xA9\x21\xD3\x6C\xE9\xCE"
751  "\x47\xD0\xD1\x3C\x5D\x85\xF2\xB0\xFF\x83\x18\xD2\x87\x7E\xEC\x2F"
752  "\x63\xB9\x31\xBD\x47\x41\x7A\x81\xA5\x38\x32\x7A\xF9\x27\xDA\x3E", 64 },
753 #endif /* USE_SHA2_EXT */
754  { CRYPT_ALGO_NONE, NULL, 0 }, { CRYPT_ALGO_NONE, NULL, 0 }
755  };
756 
758 static int getOaepHash( OUT_BUFFER_OPT( lHashMaxLen, *lHashLen ) void *lHash,
759  IN_LENGTH_SHORT_Z const int lHashMaxLen,
760  OUT_LENGTH_SHORT_Z int *lHashLen,
762  IN_INT_SHORT_Z const int hashParam )
763  {
764  int i;
765 
766  assert( ( lHash == NULL && lHashMaxLen == 0 ) || \
767  isWritePtr( lHash, lHashMaxLen ) );
768 
769  REQUIRES( ( lHash == NULL && lHashMaxLen == 0 ) || \
770  ( lHashMaxLen >= CRYPT_MAX_HASHSIZE && \
771  lHashMaxLen < MAX_INTLENGTH_SHORT ) );
772  REQUIRES( isHashAlgo( hashAlgo ) );
773 
774  /* Clear return value */
775  if( lHash != NULL )
776  zeroise( lHash, lHashMaxLen );
777  *lHashLen = 0;
778 
779  for( i = 0; lHashInfo[ i ].hashAlgo != CRYPT_ALGO_NONE && \
780  i < FAILSAFE_ARRAYSIZE( lHashInfo, LHASH_INFO ); i++ )
781  {
782  if( lHashInfo[ i ].hashAlgo != hashAlgo )
783  continue;
784  if( hashParam != 0 && lHashInfo[ i ].lHashSize != hashParam )
785  continue;
786  if( lHash != NULL )
787  memcpy( lHash, lHashInfo[ i ].lHash, lHashInfo[ i ].lHashSize );
788  *lHashLen = lHashInfo[ i ].lHashSize;
789 
790  return( CRYPT_OK );
791  }
792  ENSURES( i < FAILSAFE_ARRAYSIZE( lHashInfo, LHASH_INFO ) );
793  if( lHash != NULL )
794  zeroise( lHash, lHashMaxLen );
795 
796  return( CRYPT_ERROR_NOTAVAIL );
797  }
798 
799 #define getOaepHashSize( hashLen, hashAlgo, hashParam ) \
800  getOaepHash( NULL, 0, hashLen, hashAlgo, hashParam )
801 
802 /* OAEP mask generation function MGF1 */
803 
804 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \
805 static int mgf1( OUT_BUFFER_FIXED( maskLen ) void *mask,
806  IN_LENGTH_PKC const int maskLen,
807  IN_BUFFER( seedLen ) const void *seed,
808  IN_LENGTH_PKC const int seedLen,
809  IN_ALGO const CRYPT_ALGO_TYPE hashAlgo,
810  IN_INT_SHORT_Z const int hashParam )
811  {
813  HASHINFO hashInfo;
814  BYTE countBuffer[ 4 + 8 ], maskBuffer[ CRYPT_MAX_HASHSIZE + 8 ];
815  BYTE *maskOutPtr = mask;
816  int hashSize, maskIndex, blockCount = 0, iterationCount;
817 
818  assert( isWritePtr( mask, maskLen ) );
819  assert( isReadPtr( seed, seedLen ) );
820 
821  REQUIRES( maskLen >= 16 && maskLen <= CRYPT_MAX_PKCSIZE );
822  REQUIRES( seedLen >= 16 && seedLen <= CRYPT_MAX_PKCSIZE );
823  REQUIRES( isHashAlgo( hashAlgo ) );
824  REQUIRES( hashParam >= 0 && hashParam < MAX_INTLENGTH_SHORT );
825 
826  getHashParameters( hashAlgo, hashParam, &hashFunction, &hashSize );
827 
828  /* Set up the block counter buffer. This will never have more than the
829  last few bits set (8 bits = 5120 bytes of mask for the smallest hash,
830  SHA-1) so we only change the last byte */
831  memset( countBuffer, 0, 4 );
832 
833  /* Produce enough blocks of output to fill the mask */
834  for( maskIndex = 0, iterationCount = 0;
835  maskIndex < maskLen && iterationCount < FAILSAFE_ITERATIONS_MED;
836  maskIndex += hashSize, maskOutPtr += hashSize, iterationCount++ )
837  {
838  const int noMaskBytes = ( maskLen - maskIndex > hashSize ) ? \
839  hashSize : maskLen - maskIndex;
840 
841  /* Calculate hash( seed || counter ) */
842  countBuffer[ 3 ] = ( BYTE ) blockCount++;
843  hashFunction( hashInfo, NULL, 0, seed, seedLen, HASH_STATE_START );
844  hashFunction( hashInfo, maskBuffer, hashSize, countBuffer, 4,
845  HASH_STATE_END );
846  memcpy( maskOutPtr, maskBuffer, noMaskBytes );
847  }
848  ENSURES( iterationCount < FAILSAFE_ITERATIONS_MED );
849  zeroise( hashInfo, sizeof( HASHINFO ) );
850  zeroise( maskBuffer, CRYPT_MAX_HASHSIZE );
851 
852  return( CRYPT_OK );
853  }
854 
855 /* Generate/recover an OAEP data block:
856 
857  +----------+---------+-------+
858  DB = | lHash | PS | M |
859  +----------+---------+-------+
860  |
861  +----------+ V
862  | seed |--> MGF ---> xor
863  +----------+ |
864  | |
865  +--+ V |
866  |00| xor <----- MGF <-----|
867  +--+ | |
868  | | |
869  V V V
870  +--+----------+----------------------------+
871  EM = |00|maskedSeed| maskedDB |
872  +--+----------+----------------------------+
873  | |
874  V V
875  xor <----- MGF <-----|
876  | |
877  V |
878  +----------+ V
879  | seed |--> MGF ---> xor
880  +----------+ |
881  V
882  +----------+---------+-------+
883  DB = | lHash | PS | M |
884  +----------+---------+-------+ */
885 
886 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 5 ) ) \
887 static int generateOaepDataBlock( OUT_BUFFER_FIXED( dataMaxLen ) BYTE *data,
888  IN_LENGTH_PKC const int dataMaxLen,
889  IN_BUFFER( messageLen ) const void *message,
891  const int messageLen,
892  IN_BUFFER( seedLen ) const void *seed,
893  IN_LENGTH_PKC const int seedLen,
894  IN_ALGO const CRYPT_ALGO_TYPE hashAlgo,
895  IN_INT_SHORT_Z const int hashParam )
896  {
897  BYTE dbMask[ CRYPT_MAX_PKCSIZE + 8 ], seedMask[ CRYPT_MAX_HASHSIZE + 8 ];
898  BYTE *maskedSeed, *db;
899  int dbLen, i, length, status;
900 
901  assert( isWritePtr( data, dataMaxLen ) );
902  assert( isReadPtr( message, messageLen ) );
903  assert( isReadPtr( seed, seedLen ) );
904 
905  REQUIRES( dataMaxLen >= MIN_PKCSIZE && dataMaxLen <= CRYPT_MAX_PKCSIZE );
906  REQUIRES( messageLen >= MIN_KEYSIZE && messageLen <= dataMaxLen && \
907  messageLen <= CRYPT_MAX_KEYSIZE );
908  REQUIRES( seedLen >= 16 && seedLen <= dataMaxLen && \
909  seedLen <= CRYPT_MAX_PKCSIZE );
911  getOaepHashSize( &i, hashAlgo, hashParam ) ) && seedLen == i );
912  REQUIRES( isHashAlgo( hashAlgo ) );
913  REQUIRES( hashParam >= 0 && hashParam < MAX_INTLENGTH_SHORT );
914 
915  /* Make sure that the payload fits:
916 
917  <------------ dataMaxLen ----------->
918  +--+------+-------+----+--+---------+
919  |00| seed | lhash | PS |01| message |
920  +--+------+-------+----+--+---------+
921  1 hLen hLen 1 1 msgLen
922 
923  Although PS may have a length of zero bytes we require at least one
924  padding byte. In general the only case where we can ever run into
925  problems is if we try and use SHA2-512 with a 1024-bit key */
926  if( 1 + seedLen + seedLen + 1 + 1 + messageLen > dataMaxLen )
927  return( CRYPT_ERROR_OVERFLOW );
928 
929  /* Calculate the size and position of the various data quantities */
930  maskedSeed = data + 1;
931  db = maskedSeed + seedLen;
932  dbLen = dataMaxLen - ( 1 + seedLen );
933 
934  ENSURES( dbLen >= 16 && dbLen >= messageLen + 1 && \
935  1 + seedLen + dbLen <= dataMaxLen );
936 
937  /* db = lHash || zeroes || 0x01 || message */
938  memset( db, 0, dbLen );
939  status = getOaepHash( db, CRYPT_MAX_PKCSIZE, &length, hashAlgo,
940  hashParam );
941  if( cryptStatusError( status ) )
942  return( status );
943  db[ dbLen - messageLen - 1 ] = 0x01;
944  memcpy( db + dbLen - messageLen, message, messageLen );
945 
946  ENSURES( length == seedLen );
947 
948  /* dbMask = MGF1( seed, dbLen ) */
949  status = mgf1( dbMask, dbLen, seed, seedLen, hashAlgo, hashParam );
950  ENSURES( cryptStatusOK( status ) );
951 
952  /* maskedDB = db ^ dbMask */
953  for( i = 0; i < dbLen; i++ )
954  db[ i ] ^= dbMask[ i ];
955 
956  /* seedMask = MGF1( maskedDB, seedLen ) */
957  status = mgf1( seedMask, seedLen, db, dbLen, hashAlgo, hashParam );
958  ENSURES( cryptStatusOK( status ) );
959 
960  /* maskedSeed = seed ^ seedMask */
961  for( i = 0; i < seedLen; i++ )
962  {
963  maskedSeed[ i ] = \
964  intToByte( ( ( const BYTE * ) seed )[ i ] ^ seedMask[ i ] );
965  }
966 
967  /* data = 0x00 || maskedSeed || maskedDB */
968  data[ 0 ] = 0x00;
969 
970  zeroise( dbMask, CRYPT_MAX_PKCSIZE );
971  zeroise( seedMask, CRYPT_MAX_HASHSIZE );
972 
973  return( CRYPT_OK );
974  }
975 
976 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 4 ) ) \
977 static int recoverOaepDataBlock( OUT_BUFFER( messageMaxLen, *messageLen ) \
978  BYTE *message,
979  IN_LENGTH_PKC const int messageMaxLen,
980  OUT_LENGTH_PKC_Z int *messageLen,
981  IN_BUFFER( dataLen ) const void *data,
982  IN_LENGTH_PKC const int dataLen,
983  IN_ALGO const CRYPT_ALGO_TYPE hashAlgo,
984  IN_INT_SHORT_Z const int hashParam )
985  {
986  BYTE dbMask[ CRYPT_MAX_PKCSIZE + 8 ], seedMask[ CRYPT_MAX_HASHSIZE + 8 ];
987  BYTE dataBuffer[ CRYPT_MAX_PKCSIZE + 8 ];
988  BYTE *seed, *db;
989  int seedLen, dbLen, length, i, dummy, status;
990 
991  assert( isWritePtr( message, messageMaxLen ) );
992  assert( isWritePtr( messageLen, sizeof( int ) ) );
993  assert( isReadPtr( data, dataLen ) );
994 
995  REQUIRES( messageMaxLen >= MIN_PKCSIZE && \
996  messageMaxLen <= CRYPT_MAX_PKCSIZE );
997  REQUIRES( dataLen >= MIN_PKCSIZE && dataLen <= CRYPT_MAX_PKCSIZE );
998  REQUIRES( isHashAlgo( hashAlgo ) );
999  REQUIRES( hashParam >= 0 && hashParam < MAX_INTLENGTH_SHORT );
1000 
1001  /* Clear return value */
1002  memset( message, 0, min( 16, messageMaxLen ) );
1003  *messageLen = 0;
1004 
1005  /* Make sure that the MGF requirements are met. Note that this check
1006  has already been performed by the caller to avoid this being used as
1007  a timing oracle, this is merely here to make the fact that the check
1008  has been done explicit */
1009  status = getOaepHashSize( &seedLen, hashAlgo, hashParam );
1010  if( cryptStatusError( status ) )
1011  return( status );
1012 
1013  /* Take a local copy of the input data, since we're about to operate on
1014  it */
1015  memcpy( dataBuffer, data, dataLen );
1016 
1017  /* Calculate the size and position of the various data quantities */
1018  seed = dataBuffer + 1;
1019  db = seed + seedLen;
1020  dbLen = dataLen - ( 1 + seedLen );
1021 
1022  ENSURES( dbLen >= 16 && 1 + seedLen + dbLen <= dataLen );
1023 
1024  /* seedMask = MGF1( maskedDB, seedLen ) */
1025  status = mgf1( seedMask, seedLen, db, dbLen, hashAlgo, hashParam );
1026  ENSURES( cryptStatusOK( status ) ); /* Can only be an internal error */
1027 
1028  /* seed = maskedSeed ^ seedMask */
1029  for( i = 0; i < seedLen; i++ )
1030  seed[ i ] ^= seedMask[ i ];
1031 
1032  /* dbMask = MGF1( seed, dbLen ) */
1033  status = mgf1( dbMask, dbLen, seed, seedLen, hashAlgo, hashParam );
1034  ENSURES( cryptStatusOK( status ) ); /* Can only be an internal error */
1035 
1036  /* db = maskedDB ^ dbMask */
1037  for( i = 0; i < dbLen; i++ )
1038  db[ i ] ^= dbMask[ i ];
1039 
1040  /* Get the (constant) lHash value */
1041  status = getOaepHash( dbMask, CRYPT_MAX_PKCSIZE, &dummy, hashAlgo,
1042  hashParam );
1043  ENSURES( cryptStatusOK( status ) ); /* Can only be an internal error */
1044 
1045  /* Verify that:
1046 
1047  data = 0x00 || [seed] || db
1048  = 0x00 || [seed] || lHash || zeroes || 0x01 || message
1049 
1050  As before to be careful with the order of the checks, for example we
1051  could check for the leading 0x00 before performing the OAEP
1052  processing but this might allow an attacker to mount a timing attack,
1053  see "A chosen ciphertext attack on RSA optimal asymmetric encryption
1054  padding (OAEP)" by James Manger, Proceedings of Crypto'01, LNCS
1055  No.2139, p.230. To make this as hard as possible we cluster all of
1056  the format checks as close together as we can to try and produce a
1057  near-constant-time accept/reject decision (unfortunately the complex
1058  processing required by OAEP makes it more or less impossible to
1059  perform in a timing-independent manner, so the best that we can do
1060  is make it as hard as possible to get timing data) */
1061  if( 1 + seedLen + seedLen + 1 + 1 + MIN_KEYSIZE > dataLen )
1062  {
1063  /* Make sure that at least a minimum-length payload fits:
1064 
1065  <------------ dataMaxLen ----------->
1066  +--+------+-------+----+--+---------+
1067  |00| seed | lhash | PS |01| message |
1068  +--+------+-------+----+--+---------+
1069  1 hLen hLen 1 1 msgLen
1070 
1071  Again, we perform this check after all formatting operations have
1072  completed to try and avoid a timing attack */
1073  return( CRYPT_ERROR_BADDATA );
1074  }
1075  if( dataBuffer[ 0 ] != 0x00 || \
1076  !compareDataConstTime( db, dbMask, seedLen ) )
1077  return( CRYPT_ERROR_BADDATA );
1078  for( i = seedLen; i < dbLen && db[ i ] == 0x00; i++ );
1079  if( i <= seedLen || i >= dbLen || db[ i++ ] != 0x01 )
1080  return( CRYPT_ERROR_BADDATA );
1081  length = dbLen - i;
1082  if( length < MIN_KEYSIZE )
1083  return( CRYPT_ERROR_UNDERFLOW );
1084  if( length > messageMaxLen )
1085  return( CRYPT_ERROR_OVERFLOW );
1086 
1087  /* Return the recovered message to the caller */
1088  memcpy( message, db + i, length );
1089  *messageLen = length;
1090 
1091  zeroise( dbMask, CRYPT_MAX_PKCSIZE );
1092  zeroise( seedMask, CRYPT_MAX_HASHSIZE );
1093  zeroise( dataBuffer, CRYPT_MAX_PKCSIZE );
1094 
1095  return( CRYPT_OK );
1096  }
1097 
1098 /* Perform OAEP wrapping/unwrapping */
1099 
1100 CHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \
1101 int exportOAEP( STDC_UNUSED void *dummy,
1102  INOUT MECHANISM_WRAP_INFO *mechanismInfo )
1103  {
1105  BYTE payload[ CRYPT_MAX_KEYSIZE + 8 ], seed[ CRYPT_MAX_HASHSIZE + 8 ];
1106  int seedLen, payloadSize, length, status;
1107 
1108  UNUSED_ARG( dummy );
1109  assert( isWritePtr( mechanismInfo, sizeof( MECHANISM_WRAP_INFO ) ) );
1110 
1111  /* Clear return value */
1112  if( mechanismInfo->wrappedData != NULL )
1113  {
1114  memset( mechanismInfo->wrappedData, 0,
1115  mechanismInfo->wrappedDataLength );
1116  }
1117 
1118  /* Make sure that the OAEP auxiliary algorithm requirements are met */
1119  status = getOaepHashSize( &seedLen, mechanismInfo->auxInfo, 0 );
1120  if( cryptStatusError( status ) )
1121  return( status );
1122 
1123  /* Get various algorithm parameters */
1124  status = getPkcAlgoParams( mechanismInfo->wrapContext, &cryptAlgo,
1125  &length );
1126  if( cryptStatusError( status ) )
1127  return( status );
1128  ANALYSER_HINT( length > MIN_PKCSIZE && length <= CRYPT_MAX_PKCSIZE );
1129 
1130  /* If this is just a length check, we're done */
1131  if( mechanismInfo->wrappedData == NULL )
1132  {
1133  /* Determine how long the encrypted value will be. In the case of
1134  Elgamal it's just an estimate since it can change by up to two
1135  bytes depending on whether the values have the high bit set or
1136  not, which requires zero-padding of the ASN.1-encoded integers.
1137  This is rather nasty because it means that we can't tell how
1138  large an encrypted value will be without actually creating it.
1139  The 10-byte length at the start is for the ASN.1 SEQUENCE (= 4)
1140  and 2 * INTEGER (= 2*3) encoding */
1141  mechanismInfo->wrappedDataLength = \
1142  ( cryptAlgo == CRYPT_ALGO_ELGAMAL ) ? \
1143  10 + ( 2 * ( length + 1 ) ) : length;
1144 
1145  return( CRYPT_OK );
1146  }
1147 
1148  /* Get the payload details from the key context and generate the OAEP
1149  random seed value */
1150  status = krnlSendMessage( mechanismInfo->keyContext,
1151  IMESSAGE_GETATTRIBUTE, &payloadSize,
1153  if( cryptStatusOK( status ) )
1154  {
1156 
1157  setMessageData( &msgData, seed, seedLen );
1159  IMESSAGE_GETATTRIBUTE_S, &msgData,
1160  CRYPT_IATTRIBUTE_RANDOM );
1161  }
1162  if( cryptStatusError( status ) )
1163  return( status );
1164 
1165  /* Extract the key data and process it into an OAEP data block */
1166  status = extractKeyData( mechanismInfo->keyContext, payload, payloadSize,
1167  "keydata", 7 );
1168  if( cryptStatusOK( status ) )
1169  {
1170  status = generateOaepDataBlock( mechanismInfo->wrappedData, length,
1171  payload, payloadSize, seed, seedLen,
1172  mechanismInfo->auxInfo, 0 );
1173  }
1174  zeroise( payload, bitsToBytes( CRYPT_MAX_KEYSIZE ) );
1175  zeroise( seed, CRYPT_MAX_HASHSIZE );
1176  if( cryptStatusError( status ) )
1177  return( status );
1178 
1179  /* Wrap the encoded data using the public key */
1180  return( pkcWrapData( mechanismInfo, mechanismInfo->wrappedData, length,
1181  FALSE, ( cryptAlgo == CRYPT_ALGO_ELGAMAL ) ? \
1182  TRUE : FALSE ) );
1183  }
1184 
1185 CHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \
1186 int importOAEP( STDC_UNUSED void *dummy,
1187  INOUT MECHANISM_WRAP_INFO *mechanismInfo )
1188  {
1191  BYTE decryptedData[ CRYPT_MAX_PKCSIZE + 8 ];
1192  BYTE message[ CRYPT_MAX_PKCSIZE + 8 ];
1193  int length, messageLen, status;
1194 
1195  UNUSED_ARG( dummy );
1196  assert( isWritePtr( mechanismInfo, sizeof( MECHANISM_WRAP_INFO ) ) );
1197 
1198  /* Get various algorithm parameters */
1199  status = getPkcAlgoParams( mechanismInfo->wrapContext, &cryptAlgo,
1200  &length );
1201  if( cryptStatusError( status ) )
1202  return( status );
1203  ANALYSER_HINT( length > MIN_PKCSIZE && length <= CRYPT_MAX_PKCSIZE );
1204 
1205  /* Make sure that the MGF requirements are met. This check isn't
1206  actually needed until the recoverOaepDataBlock() call but we perform
1207  it here before the decrypt to avoid being used as a timing oracle
1208  since feeding in a non-usable hash function that causes the
1209  processing to bail out right after the decrypt provides a reasonably
1210  precise timer for the decryption */
1211  status = getOaepHashSize( &length, mechanismInfo->auxInfo, 0 );
1212  if( cryptStatusError( status ) )
1213  return( status );
1214 
1215  /* Decrypt the data */
1216  status = pkcUnwrapData( mechanismInfo, decryptedData, CRYPT_MAX_PKCSIZE,
1217  &length, length, FALSE,
1218  ( cryptAlgo == CRYPT_ALGO_ELGAMAL ) ? TRUE : FALSE );
1219  if( cryptStatusError( status ) )
1220  return( status );
1221 
1222  /* Recover the payload from the OAEP data block */
1223  status = recoverOaepDataBlock( message, CRYPT_MAX_PKCSIZE, &messageLen,
1224  decryptedData, length,
1225  mechanismInfo->auxInfo, 0 );
1226  zeroise( decryptedData, CRYPT_MAX_PKCSIZE );
1227  if( cryptStatusError( status ) )
1228  {
1229  zeroise( message, CRYPT_MAX_PKCSIZE );
1230  return( status );
1231  }
1232 
1233  /* Load the decrypted keying information into the session key context */
1234  setMessageData( &msgData, message, messageLen );
1235  status = krnlSendMessage( mechanismInfo->keyContext,
1236  IMESSAGE_SETATTRIBUTE_S, &msgData,
1238  if( cryptArgError( status ) )
1239  {
1240  /* If there was an error with the key value or size, convert the
1241  return value into something more appropriate */
1242  status = CRYPT_ERROR_BADDATA;
1243  }
1244  zeroise( message, CRYPT_MAX_PKCSIZE );
1245 
1246  return( status );
1247  }
1248 
1249 #if 0
1250 
1251 void testOAEP( void )
1252  {
1253  const BYTE seed[] = { 0xaa, 0xfd, 0x12, 0xf6, 0x59, 0xca, 0xe6, 0x34,
1254  0x89, 0xb4, 0x79, 0xe5, 0x07, 0x6d, 0xde, 0xc2,
1255  0xf0, 0x6c, 0xb5, 0x8f };
1256  const BYTE message[] = { 0xd4, 0x36, 0xe9, 0x95, 0x69, 0xfd, 0x32, 0xa7,
1257  0xc8, 0xa0, 0x5b, 0xbc, 0x90, 0xd3, 0x2c, 0x49 };
1258  BYTE buffer[ 1024 ], outMessage[ 128 ];
1259  int seedLen, outLen, status;
1260 
1261  status = getOaepHashSize( &seedLen, CRYPT_ALGO_SHA1, 0 );
1262 
1263  memset( buffer, '*', 1024 );
1264 
1265  status = generateOaepDataBlock( buffer, 128, message, 16, seed, seedLen,
1266  CRYPT_ALGO_SHA1, 0 );
1267  status = recoverOaepDataBlock( outMessage, 128, &outLen, buffer, 128,
1268  CRYPT_ALGO_SHA1, 0 );
1269  if( outLen != 16 || memcmp( message, outMessage, outLen ) )
1270  puts( "Bang." );
1271  puts( "Done." );
1272  }
1273 #endif /* 0 */
1274 
1275 #endif /* USE_OAEP */