cryptlib  3.4.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Macros
int_api.c
Go to the documentation of this file.
1 /****************************************************************************
2 * *
3 * cryptlib Internal API *
4 * Copyright Peter Gutmann 1992-2007 *
5 * *
6 ****************************************************************************/
7 
8 /* A generic module that implements a rug under which all problems not
9  solved elsewhere are swept */
10 
11 #if defined( INC_ALL )
12  #include "crypt.h"
13  #include "asn1.h"
14  #include "asn1_ext.h"
15  #include "stream.h"
16 #else
17  #include "crypt.h"
18  #include "enc_dec/asn1.h"
19  #include "enc_dec/asn1_ext.h"
20  #include "io/stream.h"
21 #endif /* Compiler-specific includes */
22 
23 /* Perform the FIPS-140 statistical checks that are feasible on a byte
24  string. The full suite of tests assumes that an infinite source of
25  values (and time) is available, the following is a scaled-down version
26  used to sanity-check keys and other short random data blocks. Note that
27  this check requires at least 64 bits of data in order to produce useful
28  results */
29 
31 BOOLEAN checkEntropy( IN_BUFFER( dataLength ) const BYTE *data,
33  {
34  const int delta = ( dataLength < 16 ) ? 1 : 0;
35  int bitCount[ 4 + 8 ] = { 0 }, noOnes, i;
36 
37  assert( isReadPtr( data, dataLength ) );
38 
39  REQUIRES_B( dataLength >= MIN_KEYSIZE && dataLength < MAX_INTLENGTH_SHORT );
40 
41  for( i = 0; i < dataLength; i++ )
42  {
43  const int value = data[ i ];
44 
45  bitCount[ value & 3 ]++;
46  bitCount[ ( value >> 2 ) & 3 ]++;
47  bitCount[ ( value >> 4 ) & 3 ]++;
48  bitCount[ ( value >> 6 ) & 3 ]++;
49  }
50 
51  /* Monobit test: Make sure that at least 1/4 of the bits are ones and 1/4
52  are zeroes */
53  noOnes = bitCount[ 1 ] + bitCount[ 2 ] + ( 2 * bitCount[ 3 ] );
54  if( noOnes < dataLength * 2 || noOnes > dataLength * 6 )
55  return( FALSE );
56 
57  /* Poker test (almost): Make sure that each bit pair is present at least
58  1/16 of the time. The FIPS 140 version uses 4-bit values but the
59  numer of samples available from the keys is far too small for this so
60  we can only use 2-bit values.
61 
62  This isn't precisely 1/16, for short samples (< 128 bits) we adjust
63  the count by one because of the small sample size and for odd-length
64  data we're getting four more samples so the actual figure is slightly
65  less than 1/16 */
66  if( ( bitCount[ 0 ] + delta < dataLength / 2 ) || \
67  ( bitCount[ 1 ] + delta < dataLength / 2 ) || \
68  ( bitCount[ 2 ] + delta < dataLength / 2 ) || \
69  ( bitCount[ 3 ] + delta < dataLength / 2 ) )
70  return( FALSE );
71 
72  return( TRUE );
73  }
74 
75 /* Copy a string attribute to external storage, with various range checks
76  to follow the cryptlib semantics (these will already have been done by
77  the caller, this is just a backup check). There are two forms for this
78  function, one that takes a MESSAGE_DATA parameter containing all of the
79  result parameters in one place and the other that takes distinct result
80  parameters, typically because they've been passed down through several
81  levels of function call beyond the point where they were in a
82  MESSAGE_DATA */
83 
85 int attributeCopyParams( OUT_BUFFER_OPT( destMaxLength, \
86  *destLength ) void *dest,
89  IN_BUFFER_OPT( sourceLength ) const void *source,
91  {
92  assert( ( dest == NULL && destMaxLength == 0 ) || \
93  ( isWritePtr( dest, destMaxLength ) ) );
94  assert( isWritePtr( destLength, sizeof( int ) ) );
95  assert( ( source == NULL && sourceLength == 0 ) || \
96  isReadPtr( source, sourceLength ) );
97 
98  REQUIRES( ( dest == NULL && destMaxLength == 0 ) || \
99  ( dest != NULL && \
100  destMaxLength > 0 && \
101  destMaxLength < MAX_INTLENGTH_SHORT ) );
102  REQUIRES( ( source == NULL && sourceLength == 0 ) || \
103  ( source != NULL && \
104  sourceLength > 0 && \
105  sourceLength < MAX_INTLENGTH_SHORT ) );
106 
107  /* Clear return value */
108  *destLength = 0;
109 
110  if( sourceLength <= 0 )
111  return( CRYPT_ERROR_NOTFOUND );
112  if( dest != NULL )
113  {
114  assert( isReadPtr( source, sourceLength ) );
115 
116  if( sourceLength > destMaxLength || \
117  !isWritePtr( dest, sourceLength ) )
118  return( CRYPT_ERROR_OVERFLOW );
119  memcpy( dest, source, sourceLength );
120  }
121  *destLength = sourceLength;
122 
123  return( CRYPT_OK );
124  }
125 
127 int attributeCopy( INOUT MESSAGE_DATA *msgData,
128  IN_BUFFER( attributeLength ) const void *attribute,
130  {
131  assert( isWritePtr( msgData, sizeof( MESSAGE_DATA ) ) );
132  assert( attributeLength == 0 || \
133  isReadPtr( attribute, attributeLength ) );
134 
135  REQUIRES( attributeLength >= 0 && \
136  attributeLength < MAX_INTLENGTH_SHORT );
137 
138  return( attributeCopyParams( msgData->data, msgData->length,
139  &msgData->length, attribute,
140  attributeLength ) );
141  }
142 
143 /* Check whether a given algorithm is available */
144 
145 CHECK_RETVAL_BOOL \
147  {
149 
150  REQUIRES_B( cryptAlgo > CRYPT_ALGO_NONE && \
151  cryptAlgo < CRYPT_ALGO_LAST );
152 
153  /* Short-circuit check for always-available algorithms. The kernel
154  won't initialise without the first two being present (and SHA-1
155  implies HMAC-SHA1) so it's safe to hardcode them in here */
156  if( cryptAlgo == CRYPT_ALGO_3DES || \
157  cryptAlgo == CRYPT_ALGO_SHA1 || \
158  cryptAlgo == CRYPT_ALGO_HMAC_SHA1 || \
159  cryptAlgo == CRYPT_ALGO_RSA )
160  return( TRUE );
161 
163  IMESSAGE_DEV_QUERYCAPABILITY, &queryInfo,
164  cryptAlgo ) ) ? TRUE : FALSE );
165  }
166 
167 /* For a given algorithm pair, check whether the first is stronger than the
168  second. For hashes the order is:
169 
170  SHA2 > RIPEMD160 > SHA-1 > all others */
171 
172 CHECK_RETVAL_BOOL \
173 BOOLEAN isStrongerHash( IN_ALGO const CRYPT_ALGO_TYPE algorithm1,
174  IN_ALGO const CRYPT_ALGO_TYPE algorithm2 )
175  {
176  static const CRYPT_ALGO_TYPE algoPrecedence[] = {
178  CRYPT_ALGO_SHA1, CRYPT_ALGO_NONE, CRYPT_ALGO_NONE };
179  int algo1index, algo2index;
180 
181  REQUIRES_B( isHashAlgo( algorithm1 ) );
182  REQUIRES_B( isHashAlgo( algorithm2 ) );
183 
184  /* Find the relative positions on the scale of the two algorithms */
185  for( algo1index = 0;
186  algoPrecedence[ algo1index ] != algorithm1 && \
187  algo1index < FAILSAFE_ARRAYSIZE( algoPrecedence, CRYPT_ALGO_TYPE );
188  algo1index++ )
189  {
190  /* If we've reached an unrated algorithm, it can't be stronger than
191  the other one */
192  if( algoPrecedence[ algo1index ] == CRYPT_ALGO_NONE )
193  return( FALSE );
194  }
195  ENSURES_B( algo1index < FAILSAFE_ARRAYSIZE( algoPrecedence, \
196  CRYPT_ALGO_TYPE ) );
197  for( algo2index = 0;
198  algoPrecedence[ algo2index ] != algorithm2 && \
199  algo2index < FAILSAFE_ARRAYSIZE( algoPrecedence, CRYPT_ALGO_TYPE );
200  algo2index++ )
201  {
202  /* If we've reached an unrated algorithm, it's weaker than the other
203  one */
204  if( algoPrecedence[ algo2index ] == CRYPT_ALGO_NONE )
205  return( TRUE );
206  }
207  ENSURES_B( algo2index < FAILSAFE_ARRAYSIZE( algoPrecedence, \
208  CRYPT_ALGO_TYPE ) );
209 
210  /* If the first algorithm has a smaller index than the second, it's a
211  stronger algorithm */
212  return( ( algo1index < algo2index ) ? TRUE : FALSE );
213  }
214 
215 /* Return a random small integer. This is used to perform lightweight
216  randomisation of various algorithms in order to make DoS attacks harder.
217  Because of this the values don't have to be cryptographically strong, so
218  all that we do is cache the data from CRYPT_IATTRIBUTE_RANDOM_NONCE and
219  pull out a small integer's worth on each call */
220 
221 #define RANDOM_BUFFER_SIZE 8
222 
223 CHECK_RETVAL_RANGE( 0, 32767 ) \
224 int getRandomInteger( void )
225  {
226  static BYTE nonceData[ RANDOM_BUFFER_SIZE + 8 ];
227  static int nonceIndex = 0;
228  int returnValue, status;
229 
230  /* Initialise/reinitialise the nonce data if necessary. See the long
231  coment for getNonce() in system.c for the reason why we don't bail
232  out on error but continue with a lower-quality generator */
233  if( nonceIndex <= 0 )
234  {
236 
237  setMessageData( &msgData, nonceData, RANDOM_BUFFER_SIZE );
239  IMESSAGE_GETATTRIBUTE_S, &msgData,
240  CRYPT_IATTRIBUTE_RANDOM_NONCE );
241  if( cryptStatusError( status ) )
242  return( ( int ) getTime() & 0x7FFF );
243  }
244 
245  /* Extract the next random integer value from the buffered data */
246  returnValue = ( nonceData[ nonceIndex ] << 8 ) | \
247  nonceData[ nonceIndex + 1 ];
248  nonceIndex = ( nonceIndex + 2 ) % RANDOM_BUFFER_SIZE;
249  ENSURES( nonceIndex >= 0 && nonceIndex < RANDOM_BUFFER_SIZE );
250 
251  /* Return the value constrained to lie within the range 0...32767 */
252  return( returnValue & 0x7FFF );
253  }
254 
255 /* Map one value to another, used to map values from one representation
256  (e.g. PGP algorithms or HMAC algorithms) to another (cryptlib algorithms
257  or the underlying hash used for the HMAC algorithm) */
258 
260 int mapValue( IN_INT_SHORT_Z const int srcValue,
262  IN_ARRAY( mapTblSize ) const MAP_TABLE *mapTbl,
263  IN_LENGTH_SHORT const int mapTblSize )
264  {
265  int i;
266 
267  assert( isWritePtr( destValue, sizeof( int ) ) );
268  assert( isReadPtr( mapTbl, mapTblSize * sizeof( MAP_TABLE ) ) );
269 
270  REQUIRES( srcValue >= 0 && srcValue < MAX_INTLENGTH_SHORT );
271  REQUIRES( mapTblSize > 0 && mapTblSize < 100 );
272  REQUIRES( mapTbl[ mapTblSize ].source == CRYPT_ERROR );
273 
274  /* Clear return value */
275  *destValue = 0;
276 
277  /* Convert the hash algorithm into the equivalent HMAC algorithm */
278  for( i = 0; i < mapTblSize && mapTbl[ i ].source != CRYPT_ERROR && \
279  i < FAILSAFE_ITERATIONS_LARGE; i++ )
280  {
281  if( mapTbl[ i ].source == srcValue )
282  {
283  *destValue = mapTbl[ i ].destination;
284 
285  return( CRYPT_OK );
286  }
287  }
288  ENSURES( i < mapTblSize );
289 
290  return( CRYPT_ERROR_NOTAVAIL );
291  }
292 
293 /****************************************************************************
294 * *
295 * Checksum/Hash Functions *
296 * *
297 ****************************************************************************/
298 
299 /* Calculate a 16-bit Fletcher-like checksum of a block of data. This isn't
300  quite a pure Fletcher checksum because we don't bother keeping the
301  accumulators at 8 bits and also don't need to set the initial value to
302  nonzero since we'll never see a sequence of zero bytes. This isn't a big
303  deal since all we need is consistent results for identical data, the
304  value itself is never communicated externally. In addition we don't
305  bother with masking to 16 bits during the calculation process (although
306  we mask at the end to avoid potential problems with sign bits) since it's
307  not being used as a true checksum */
308 
310 int checksumData( IN_BUFFER( dataLength ) const void *data,
312  {
313  const BYTE *dataPtr = data;
314  int sum1 = 0, sum2 = 0, i;
315 
316  assert( isReadPtr( data, dataLength ) );
317 
318  REQUIRES( data != NULL );
319  REQUIRES( dataLength > 0 && dataLength < MAX_INTLENGTH )
320 
321  for( i = 0; i < dataLength; i++ )
322  {
323  sum1 += dataPtr[ i ];
324  sum2 += sum1;
325  }
326 
327  return( sum2 & 0xFFFF );
328  }
329 
330 /* Calculate the hash of a block of data. We use SHA-1 because it's the
331  built-in default, but any algorithm will do since we're only using it
332  to transform a variable-length value to a fixed-length one for easy
333  comparison purposes */
334 
335 STDC_NONNULL_ARG( ( 1, 3 ) ) \
336 void hashData( OUT_BUFFER_FIXED( hashMaxLength ) BYTE *hash,
337  IN_LENGTH_HASH const int hashMaxLength,
338  IN_BUFFER( dataLength ) const void *data,
339  IN_LENGTH const int dataLength )
340  {
341  static HASHFUNCTION_ATOMIC hashFunctionAtomic = NULL;
342  static int hashSize;
343  BYTE hashBuffer[ CRYPT_MAX_HASHSIZE + 8 ];
344 
345  assert( isWritePtr( hash, hashMaxLength ) );
346  assert( hashMaxLength >= 16 && \
347  hashMaxLength <= CRYPT_MAX_HASHSIZE );
348  assert( isReadPtr( data, dataLength ) );
349  assert( dataLength > 0 && dataLength < MAX_INTLENGTH );
350 
351  /* Get the hash algorithm information if necessary */
352  if( hashFunctionAtomic == NULL )
353  {
354  getHashAtomicParameters( CRYPT_ALGO_SHA1, 0, &hashFunctionAtomic,
355  &hashSize );
356  }
357 
358  /* Error handling: If there's a problem, return a zero hash. We use
359  this strategy since this is a void function and so the usual
360  REQUIRES() predicate won't be effective. Note that this can lead to
361  a false-positive match if we're called multiple times with invalid
362  input, in theory we could fill the return buffer with nonce data to
363  ensure that we never get a false-positive match but since this is a
364  should-never-occur condition anyway it's not certain whether forcing
365  a match or forcing a non-match is the preferred behaviour */
366  if( data == NULL || dataLength <= 0 || dataLength >= MAX_INTLENGTH || \
367  hashMaxLength < 16 || hashMaxLength > hashSize || \
368  hashMaxLength > CRYPT_MAX_HASHSIZE || hashFunctionAtomic == NULL )
369  {
370  memset( hash, 0, hashMaxLength );
372  }
373 
374  /* Hash the data and copy as many bytes as the caller has requested to
375  the output. Typically they'll require only a subset of the full
376  amount since all that we're doing is transforming a variable-length
377  value to a fixed-length value for easy comparison purposes */
378  hashFunctionAtomic( hashBuffer, 20, data, dataLength );
379  memcpy( hash, hashBuffer, hashMaxLength );
380  zeroise( hashBuffer, 20 );
381  }
382 
383 /* Compare two blocks of memory in a time-independent manner. This is used
384  to avoid potential timing attacks on memcmp(), which bails out as soon as
385  it finds a mismatch */
386 
388 BOOLEAN compareDataConstTime( IN_BUFFER( length ) const void *src,
389  IN_BUFFER( length ) const void *dest,
390  IN_LENGTH_SHORT const int length )
391  {
392  const BYTE *srcPtr = src, *destPtr = dest;
393  int value = 0, i;
394 
395  assert( isReadPtr( src, length ) );
396  assert( isReadPtr( dest, length ) );
397 
398  REQUIRES_B( length > 0 && length < MAX_INTLENGTH_SHORT );
399 
400  /* Compare the two values in a time-independent manner */
401  for( i = 0; i < length; i++ )
402  value |= srcPtr[ i ] ^ destPtr[ i ];
403 
404  return( !value );
405  }
406 
407 /****************************************************************************
408 * *
409 * Stream Export/Import Routines *
410 * *
411 ****************************************************************************/
412 
413 /* Export attribute or certificate data to a stream. In theory we would
414  have to export this via a dynbuf and then write it to the stream but we
415  can save some overhead by writing it directly to the stream's buffer.
416 
417  Some attributes have a user-defined size (e.g.
418  CRYPT_IATTRIBUTE_RANDOM_NONCE) so we allow the caller to specify an
419  optional length parameter indicating how much of the attribute should be
420  exported */
421 
423 static int exportAttr( INOUT STREAM *stream,
426  IN_LENGTH_INDEF const int length )
427  /* Declared as LENGTH_INDEF because SHORT_INDEF
428  doesn't make sense */
429  {
431  void *dataPtr = NULL;
432  int attrLength = 0, status;
433 
434  assert( isWritePtr( stream, sizeof( STREAM ) ) );
435  assert( sStatusOK( stream ) );
436 
437  REQUIRES( cryptHandle == SYSTEM_OBJECT_HANDLE || \
438  isHandleRangeValid( cryptHandle ) );
439  REQUIRES( isAttribute( attributeType ) || \
440  isInternalAttribute( attributeType ) );
441  REQUIRES( ( length == CRYPT_UNUSED ) || \
442  ( length >= 8 && length < MAX_INTLENGTH_SHORT ) );
443 
444  /* Get access to the stream buffer if required */
445  if( !sIsNullStream( stream ) )
446  {
447  if( length != CRYPT_UNUSED )
448  {
449  /* It's an explicit-length attribute, make sure that there's
450  enough room left in the stream for it */
451  attrLength = length;
452  status = sMemGetDataBlock( stream, &dataPtr, length );
453  }
454  else
455  {
456  /* It's an implicit-length attribute whose maximum length is
457  defined by the stream size */
458  status = sMemGetDataBlockRemaining( stream, &dataPtr,
459  &attrLength );
460  }
461  if( cryptStatusError( status ) )
462  return( status );
463  }
464 
465  /* Export the attribute directly into the stream buffer */
466  setMessageData( &msgData, dataPtr, attrLength );
468  &msgData, attributeType );
469  if( cryptStatusOK( status ) )
470  status = sSkip( stream, msgData.length );
471  return( status );
472  }
473 
475 int exportAttributeToStream( INOUT TYPECAST( STREAM * ) void *streamPtr,
476  IN_HANDLE const CRYPT_HANDLE cryptHandle,
477  IN_ATTRIBUTE \
478  const CRYPT_ATTRIBUTE_TYPE attributeType )
479  {
480  assert( isWritePtr( streamPtr, sizeof( STREAM ) ) );
481 
482  REQUIRES( isHandleRangeValid( cryptHandle ) );
483  REQUIRES( isAttribute( attributeType ) || \
484  isInternalAttribute( attributeType ) );
485 
486  return( exportAttr( streamPtr, cryptHandle, attributeType, \
487  CRYPT_UNUSED ) );
488  }
489 
491 int exportVarsizeAttributeToStream( INOUT TYPECAST( STREAM * ) void *streamPtr,
492  IN_HANDLE const CRYPT_HANDLE cryptHandle,
493  IN_LENGTH_FIXED( CRYPT_IATTRIBUTE_RANDOM_NONCE ) \
494  const CRYPT_ATTRIBUTE_TYPE attributeType,
495  IN_RANGE( 8, 1024 ) \
496  const int attributeDataLength )
497  {
498  assert( isWritePtr( streamPtr, sizeof( STREAM ) ) );
499 
500  REQUIRES( cryptHandle == SYSTEM_OBJECT_HANDLE );
501  REQUIRES( attributeType == CRYPT_IATTRIBUTE_RANDOM_NONCE );
502  REQUIRES( attributeDataLength >= 8 && attributeDataLength <= 1024 );
503 
504  return( exportAttr( streamPtr, cryptHandle, attributeType,
505  attributeDataLength ) );
506  }
507 
509 int exportCertToStream( INOUT TYPECAST( STREAM * ) void *streamPtr,
511  IN_ENUM( CRYPT_CERTFORMAT ) \
512  const CRYPT_CERTFORMAT_TYPE certFormatType )
513  {
515  STREAM *stream = streamPtr;
516  void *dataPtr = NULL;
517  int length = 0, status;
518 
519  assert( isWritePtr( stream, sizeof( STREAM ) ) );
520  assert( sStatusOK( stream ) );
521 
522  REQUIRES( isHandleRangeValid( cryptCertificate ) );
523  REQUIRES( certFormatType > CRYPT_CERTFORMAT_NONE && \
524  certFormatType < CRYPT_CERTFORMAT_LAST );
525 
526  /* Get access to the stream buffer if required */
527  if( !sIsNullStream( stream ) )
528  {
529  status = sMemGetDataBlockRemaining( stream, &dataPtr, &length );
530  if( cryptStatusError( status ) )
531  return( status );
532  }
533 
534  /* Export the cert directly into the stream buffer */
535  setMessageData( &msgData, dataPtr, length );
536  status = krnlSendMessage( cryptCertificate, IMESSAGE_CRT_EXPORT,
537  &msgData, certFormatType );
538  if( cryptStatusOK( status ) )
539  status = sSkip( stream, msgData.length );
540  return( status );
541  }
542 
543 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
544 int importCertFromStream( INOUT void *streamPtr,
545  OUT_HANDLE_OPT CRYPT_CERTIFICATE *cryptCertificate,
547  IN_ENUM( CRYPT_CERTTYPE ) \
550  const int certDataLength )
551  {
552  MESSAGE_CREATEOBJECT_INFO createInfo;
553  STREAM *stream = streamPtr;
554  void *dataPtr;
555  int status;
556 
557  assert( isWritePtr( stream, sizeof( STREAM ) ) );
558  assert( sStatusOK( stream ) );
559  assert( isWritePtr( cryptCertificate, sizeof( CRYPT_CERTIFICATE ) ) );
560 
561  REQUIRES( iCryptOwner == DEFAULTUSER_OBJECT_HANDLE || \
562  isHandleRangeValid( iCryptOwner ) );
563  REQUIRES( certType > CRYPT_CERTTYPE_NONE && \
564  certType < CRYPT_CERTTYPE_LAST );
565  REQUIRES( certDataLength >= MIN_CRYPT_OBJECTSIZE && \
566  certDataLength < MAX_INTLENGTH_SHORT );
567 
568  /* Clear return value */
569  *cryptCertificate = CRYPT_ERROR;
570 
571  /* Get access to the stream buffer and skip over the certificate data */
572  status = sMemGetDataBlock( stream, &dataPtr, certDataLength );
573  if( cryptStatusOK( status ) )
574  status = sSkip( stream, certDataLength );
575  if( cryptStatusError( status ) )
576  return( status );
577 
578  /* Import the cert directly from the stream buffer */
579  setMessageCreateObjectIndirectInfo( &createInfo, dataPtr,
580  certDataLength, certType );
581  createInfo.cryptOwner = iCryptOwner;
584  &createInfo, OBJECT_TYPE_CERTIFICATE );
585  if( cryptStatusError( status ) )
586  return( status );
587  *cryptCertificate = createInfo.cryptHandle;
588  return( CRYPT_OK );
589  }
590 
591 /****************************************************************************
592 * *
593 * Public-key Import Routines *
594 * *
595 ****************************************************************************/
596 
597 /* Read a public key from an X.509 SubjectPublicKeyInfo record, creating the
598  context necessary to contain it in the process. This is used by a variety
599  of modules including certificate-management, keyset, and crypto device.
600 
601  The use of the void * instead of STREAM * is necessary because the STREAM
602  type isn't visible at the global level */
603 
605 static int checkKeyLength( INOUT STREAM *stream,
607  const BOOLEAN hasAlgoParameters )
608  {
609  const long startPos = stell( stream );
610  int keyLength, status;
611 
612  assert( isWritePtr( stream, sizeof( STREAM ) ) );
613 
614  REQUIRES( isPkcAlgo( cryptAlgo ) );
615 
616  /* ECC algorithms are a complete mess to handle because of the arbitrary
617  manner in which the algorithm parameters can be represented. To deal
618  with this we skip the parameters and read the public key value, which
619  is a point on a curve stuffed in a variety of creative ways into an
620  BIT STRING. Since this contains two values (the x and y coordinates)
621  we divide the lengths used by two to get an approximation of the
622  nominal key size */
623  if( isEccAlgo( cryptAlgo ) )
624  {
625  readUniversal( stream ); /* Skip algorithm parameters */
626  status = readBitStringHole( stream, &keyLength,
628  DEFAULT_TAG );
629  if( cryptStatusOK( status ) && isShortECCKey( keyLength / 2 ) )
630  status = CRYPT_ERROR_NOSECURE;
631  if( cryptStatusError( status ) )
632  return( status );
633 
634  return( sseek( stream, startPos ) );
635  }
636 
637  /* Read the key component that defines the nominal key size, either the
638  first algorithm parameter or the first public-key component */
639  if( hasAlgoParameters )
640  {
641  readSequence( stream, NULL );
642  status = readGenericHole( stream, &keyLength, MIN_PKCSIZE_THRESHOLD,
643  BER_INTEGER );
644  }
645  else
646  {
647  readBitStringHole( stream, NULL, MIN_PKCSIZE_THRESHOLD, DEFAULT_TAG );
648  readSequence( stream, NULL );
649  status = readGenericHole( stream, &keyLength, MIN_PKCSIZE_THRESHOLD,
650  BER_INTEGER );
651  }
652  if( cryptStatusError( status ) )
653  return( status );
654 
655  /* Check whether the nominal keysize is within the range defined as
656  being a weak key */
657  if( isShortPKCKey( keyLength ) )
658  return( CRYPT_ERROR_NOSECURE );
659 
660  return( sseek( stream, startPos ) );
661  }
662 
663 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
664 int iCryptReadSubjectPublicKey( INOUT TYPECAST( STREAM * ) void *streamPtr,
667  const BOOLEAN deferredLoad )
668  {
671  MESSAGE_CREATEOBJECT_INFO createInfo;
673  STREAM *stream = streamPtr;
674  void *spkiPtr = DUMMY_INIT_PTR;
675  int spkiLength, length, status;
676 
677  assert( isReadPtr( stream, sizeof( STREAM ) ) );
678  assert( isWritePtr( iPubkeyContext, sizeof( CRYPT_CONTEXT ) ) );
679 
680  REQUIRES( iCreatorHandle == SYSTEM_OBJECT_HANDLE || \
681  isHandleRangeValid( iCreatorHandle ) );
682 
683  /* Clear return value */
684  *iPubkeyContext = CRYPT_ERROR;
685 
686  /* Pre-parse the SubjectPublicKeyInfo, both to ensure that it's (at
687  least generally) valid before we go to the extent of creating an
688  encryption context to contain it and to get access to the
689  SubjectPublicKeyInfo data and algorithm information. Because all
690  sorts of bizarre tagging exists due to things like CRMF we read the
691  wrapper as a generic hole rather than the more obvious SEQUENCE */
692  status = getStreamObjectLength( stream, &spkiLength );
693  if( cryptStatusOK( status ) )
694  status = sMemGetDataBlock( stream, &spkiPtr, spkiLength );
695  if( cryptStatusOK( status ) )
696  {
697  status = readGenericHole( stream, NULL,
699  DEFAULT_TAG );
700  }
701  if( cryptStatusError( status ) )
702  return( status );
703  status = readAlgoIDparam( stream, &cryptAlgo, &length,
705  if( cryptStatusError( status ) )
706  return( status );
707 
708  /* Perform minimal key-length checking. We need to do this at this
709  point (rather than having it done implicitly in the
710  SubjectPublicKeyInfo read code) because a too-short key (or at least
711  too-short key data) will result in the kernel rejecting the
712  SubjectPublicKeyInfo before it can be processed, leading to a rather
713  misleading CRYPT_ERROR_BADDATA return status rather the correct
714  CRYPT_ERROR_NOSECURE */
715  status = checkKeyLength( stream, cryptAlgo,
716  ( length > 0 ) ? TRUE : FALSE );
717  if( cryptStatusError( status ) )
718  return( status );
719 
720  /* Skip the remainder of the key components in the stream, first the
721  algorithm parameters (if there are any) and then the public-key
722  data */
723  if( length > 0 )
724  readUniversal( stream );
725  status = readUniversal( stream );
726  if( cryptStatusError( status ) )
727  return( status );
728 
729  /* Create the public-key context and send the public-key data to it */
730  setMessageCreateObjectInfo( &createInfo, cryptAlgo );
731  status = krnlSendMessage( iCreatorHandle, IMESSAGE_DEV_CREATEOBJECT,
732  &createInfo, OBJECT_TYPE_CONTEXT );
733  if( cryptStatusError( status ) )
734  return( status );
735  iCryptContext = createInfo.cryptHandle;
736  setMessageData( &msgData, spkiPtr, spkiLength );
737  status = krnlSendMessage( iCryptContext, IMESSAGE_SETATTRIBUTE_S,
738  &msgData, deferredLoad ? \
739  CRYPT_IATTRIBUTE_KEY_SPKI_PARTIAL : \
740  CRYPT_IATTRIBUTE_KEY_SPKI );
741  if( cryptStatusError( status ) )
742  {
743  krnlSendNotifier( iCryptContext, IMESSAGE_DECREFCOUNT );
744  if( cryptArgError( status ) )
745  {
746  DEBUG_DIAG(( "Public-key load returned argError status" ));
747  assert( DEBUG_WARN );
748  return( CRYPT_ERROR_BADDATA );
749  }
750  return( status );
751  }
752  *iPubkeyContext = iCryptContext;
753  assert( cryptStatusError( \
754  krnlSendMessage( iCryptContext, IMESSAGE_CHECK,
755  NULL, MESSAGE_CHECK_PKC_PRIVATE ) ) );
756  return( CRYPT_OK );
757  }
758 
759 /****************************************************************************
760 * *
761 * Safe Text-line Read Functions *
762 * *
763 ****************************************************************************/
764 
765 /* Read a line of text data ending in an EOL. If we get more data than will
766  fit into the read buffer we discard it until we find an EOL. As a
767  secondary concern we want to strip leading, trailing, and repeated
768  whitespace. Leading whitespace is handled by setting the seen-whitespace
769  flag to true initially, this treats any whitespace at the start of the
770  line as superfluous and strips it. Stripping of repeated whitespace is
771  also handled by the seenWhitespace flag, and stripping of trailing
772  whitespace is handled by walking back through any final whitespace once we
773  see the EOL.
774 
775  We also handle continued lines denoted by the MIME convention of a
776  semicolon as the last non-whitespace character by setting the
777  seenContinuation flag if we see a semicolon as the last non-whitespace
778  character.
779 
780  Finally, we also need to handle generic DoS attacks. If we see more than
781  MAX_LINE_LENGTH chars in a line we bail out */
782 
783 #define MAX_LINE_LENGTH 4096
784 
785 /* The extra level of indirection provided by this function is necessary
786  because the the extended error information isn't accessible from outside
787  the stream code so we can't set it in readTextLine() in the usual manner
788  via a retExt(). Instead we use a retExt() in the dummy function
789  formatTextLineError() and then pass it down to the stream layer via an
790  ioctl */
791 
792 RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
793 static int formatTextLineError( OUT ERROR_INFO *errorInfo,
794  FORMAT_STRING const char *format,
795  const int value1, const int value2 )
796  {
797  assert( isWritePtr( errorInfo, sizeof( ERROR_INFO ) ) );
798  assert( isReadPtr( format, 4 ) );
799 
801  ( CRYPT_ERROR_BADDATA, errorInfo,
802  format, value1, value2 ) );
803  }
804 
805 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3, 5 ) ) \
806 int readTextLine( READCHARFUNCTION readCharFunction,
807  INOUT void *streamPtr,
808  OUT_BUFFER( lineBufferMaxLen, *lineBufferSize ) \
809  char *lineBuffer,
810  IN_LENGTH_SHORT_MIN( 16 ) const int lineBufferMaxLen,
813  {
814  BOOLEAN seenWhitespace, seenContinuation = FALSE;
815  int totalChars, bufPos = 0;
816 
817  assert( isWritePtr( streamPtr, sizeof( STREAM ) ) );
818  assert( isWritePtr( lineBuffer, lineBufferMaxLen ) );
819  assert( isWritePtr( lineBufferSize, sizeof( int ) ) );
820  assert( localError == NULL || \
821  isWritePtr( localError, sizeof( BOOLEAN ) ) );
822 
823  REQUIRES( readCharFunction != NULL );
824  REQUIRES( lineBufferMaxLen >= 16 && \
825  lineBufferMaxLen < MAX_INTLENGTH_SHORT );
826 
827  /* Clear return values */
828  memset( lineBuffer, 0, min( 16, lineBufferMaxLen ) );
829  *lineBufferSize = 0;
830  if( localError != NULL )
831  *localError = FALSE;
832 
833  /* Set the seen-whitespace flag initially to strip leading whitespace */
834  seenWhitespace = TRUE;
835 
836  /* Read up to MAX_LINE_LENGTH chars. Anything longer than this is
837  probably a DoS */
838  for( totalChars = 0; totalChars < MAX_LINE_LENGTH; totalChars++ )
839  {
840  int ch;
841 
842  /* Get the next input character */
843  ch = readCharFunction( streamPtr );
844  if( cryptStatusError( ch ) )
845  return( ch );
846 
847  /* Process EOL */
848  if( ch == '\n' )
849  {
850  /* Strip trailing whitespace. At this point it's all been
851  canonicalised so we don't need to check for anything other
852  than spaces */
853  while( bufPos > 0 && lineBuffer[ bufPos - 1 ] == ' ' )
854  bufPos--;
855 
856  /* If we've seen a continuation marker as the last non-
857  whitespace char, the line continues on the next one. This
858  can theoretically result in stripping a space at the end of
859  a line but since continuations are only placed at MIME
860  keyword separators the space is superfluous and can be
861  safely removed */
862  if( seenContinuation )
863  {
864  seenContinuation = FALSE;
865  continue;
866  }
867 
868  /* We're done */
869  break;
870  }
871 
872  /* Ignore any additional decoration that may accompany EOLs */
873  if( ch == '\r' )
874  continue;
875 
876  /* If we're over the maximum buffer size discard any further input
877  until we either hit EOL or exceed the DoS threshold at
878  MAX_LINE_LENGTH */
879  if( bufPos > lineBufferMaxLen - 8 )
880  {
881  /* If we've run off into the weeds (for example we're reading
882  binary data following the text header), bail out */
883  if( ch <= 0 || ch > 0x7F || !isPrint( ch ) )
884  {
886 
887  if( localError != NULL )
888  *localError = TRUE;
889  formatTextLineError( &errorInfo, "Invalid character 0x%02X "
890  "at position %d", ch, totalChars );
891  sioctlSetString( streamPtr, STREAM_IOCTL_ERRORINFO,
892  &errorInfo, sizeof( ERROR_INFO ) );
893 
894  return( CRYPT_ERROR_BADDATA );
895  }
896  continue;
897  }
898 
899  /* Process whitespace. We can't use isspace() for this because it
900  includes all sorts of extra control characters that we don't want
901  to allow */
902  if( ch == ' ' || ch == '\t' )
903  {
904  if( seenWhitespace )
905  {
906  /* Ignore leading and repeated whitespace */
907  continue;
908  }
909  ch = ' '; /* Canonicalise whitespace */
910  }
911 
912  /* Process any remaining chars */
913  if( ch <= 0 || ch > 0x7F || !isPrint( ch ) )
914  {
916 
917  if( localError != NULL )
918  *localError = TRUE;
919  formatTextLineError( &errorInfo, "Invalid character 0x%02X at "
920  "position %d", ch, totalChars );
921  sioctlSetString( streamPtr, STREAM_IOCTL_ERRORINFO, &errorInfo,
922  sizeof( ERROR_INFO ) );
923 
924  return( CRYPT_ERROR_BADDATA );
925  }
926  lineBuffer[ bufPos++ ] = intToByte( ch );
927  ENSURES( bufPos > 0 && bufPos <= totalChars + 1 );
928  /* The 'totalChars + 1' is because totalChars is the loop
929  iterator and won't have been incremented yet at this
930  point */
931 
932  /* Update the state variables. If the character that we've just
933  processed was whitespace or if we've seen a continuation
934  character or we're processing whitespace after having seen a
935  continuation character (which makes it effectively leading
936  whitespace to be stripped), remember this */
937  seenWhitespace = ( ch == ' ' ) ? TRUE : FALSE;
938  seenContinuation = ( ch == ';' || \
939  ( seenContinuation && seenWhitespace ) ) ? \
940  TRUE : FALSE;
941  }
942  if( totalChars >= MAX_LINE_LENGTH )
943  {
945 
946  if( localError != NULL )
947  *localError = TRUE;
948  formatTextLineError( &errorInfo, "Text line too long", 0, 0 );
949  sioctlSetString( streamPtr, STREAM_IOCTL_ERRORINFO, &errorInfo,
950  sizeof( ERROR_INFO ) );
951 
952  return( CRYPT_ERROR_OVERFLOW );
953  }
954  *lineBufferSize = bufPos;
955 
956  return( CRYPT_OK );
957  }