1 /****************************************************************************
2 *																			*
3 *							cryptlib Internal API							*
4 *						Copyright Peter Gutmann 1992-2014					*
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 
30 CHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \
checkNontrivialKey(IN_BUFFER (dataLength)const BYTE * data,IN_LENGTH_SHORT_MIN (MIN_KEYSIZE)const int dataLength)31 static BOOLEAN checkNontrivialKey( IN_BUFFER( dataLength ) const BYTE *data,
32 								   IN_LENGTH_SHORT_MIN( MIN_KEYSIZE ) const int dataLength )
33 	{
34 	int i;
35 
36 	for( i = 0; i < dataLength; i++	)
37 		{
38 		if( !isAlnum( data[ i ] ) )
39 			break;
40 		}
41 	if( i >= dataLength )
42 		return( FALSE );
43 
44 	for( i = 0; i < dataLength - 1; i++ )
45 		{
46 		const int delta = abs( data[ i ] - data[ i + 1 ] );
47 
48 		if( delta > 8 )
49 			break;
50 		}
51 	if( i >= dataLength - 1 )
52 		return( FALSE );
53 
54 	return( TRUE );
55 	}
56 
57 CHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \
checkEntropy(IN_BUFFER (dataLength)const BYTE * data,IN_LENGTH_SHORT_MIN (MIN_KEYSIZE)const int dataLength)58 BOOLEAN checkEntropy( IN_BUFFER( dataLength ) const BYTE *data,
59 					  IN_LENGTH_SHORT_MIN( MIN_KEYSIZE ) const int dataLength )
60 	{
61 	const int delta = ( dataLength < 16 ) ? 1 : 0;
62 	int bitCount[ 8 + 8 ], noOnes, i;
63 
64 	assert( isReadPtr( data, dataLength ) );
65 
66 	REQUIRES_B( dataLength >= MIN_KEYSIZE && dataLength < MAX_INTLENGTH_SHORT );
67 
68 	memset( bitCount, 0, sizeof( int ) * 9 );
69 	for( i = 0; i < dataLength; i++ )
70 		{
71 		const int value = byteToInt( data[ i ] );
72 
73 		bitCount[ value & 3 ]++;
74 		bitCount[ ( value >> 2 ) & 3 ]++;
75 		bitCount[ ( value >> 4 ) & 3 ]++;
76 		bitCount[ ( value >> 6 ) & 3 ]++;
77 		}
78 
79 	/* Monobit test: Make sure that at least 1/4 of the bits are ones and 1/4
80 	   are zeroes */
81 	noOnes = bitCount[ 1 ] + bitCount[ 2 ] + ( 2 * bitCount[ 3 ] );
82 	if( noOnes < dataLength * 2 || noOnes > dataLength * 6 )
83 		{
84 		zeroise( bitCount, 8 * sizeof( int ) );
85 		return( FALSE );
86 		}
87 
88 	/* Poker test (almost): Make sure that each bit pair is present at least
89 	   1/16 of the time.  The FIPS 140 version uses 4-bit values but the
90 	   numer of samples available from the keys is far too small for this so
91 	   we can only use 2-bit values.
92 
93 	   This isn't precisely 1/16, for short samples (< 128 bits) we adjust
94 	   the count by one because of the small sample size and for odd-length
95 	   data we're getting four more samples so the actual figure is slightly
96 	   less than 1/16 */
97 	if( ( bitCount[ 0 ] + delta < dataLength / 2 ) || \
98 		( bitCount[ 1 ] + delta < dataLength / 2 ) || \
99 		( bitCount[ 2 ] + delta < dataLength / 2 ) || \
100 		( bitCount[ 3 ] + delta < dataLength / 2 ) )
101 		{
102 		zeroise( bitCount, 8 * sizeof( int ) );
103 		return( FALSE );
104 		}
105 
106 	zeroise( bitCount, 8 * sizeof( int ) );
107 	return( TRUE );
108 	}
109 
110 /* Copy a string attribute to external storage, with various range checks
111    to follow the cryptlib semantics (these will already have been done by
112    the caller, this is just a backup check).  There are two forms for this
113    function, one that takes a MESSAGE_DATA parameter containing all of the
114    result parameters in one place and the other that takes distinct result
115    parameters, typically because they've been passed down through several
116    levels of function call beyond the point where they were in a
117    MESSAGE_DATA */
118 
119 CHECK_RETVAL STDC_NONNULL_ARG( ( 3 ) ) \
attributeCopyParams(OUT_BUFFER_OPT (destMaxLength,* destLength)void * dest,IN_LENGTH_SHORT_Z const int destMaxLength,OUT_LENGTH_BOUNDED_SHORT_Z (destMaxLength)int * destLength,IN_BUFFER_OPT (sourceLength)const void * source,IN_LENGTH_SHORT_Z const int sourceLength)120 int attributeCopyParams( OUT_BUFFER_OPT( destMaxLength, \
121 										 *destLength ) void *dest,
122 						 IN_LENGTH_SHORT_Z const int destMaxLength,
123 						 OUT_LENGTH_BOUNDED_SHORT_Z( destMaxLength ) \
124 							int *destLength,
125 						 IN_BUFFER_OPT( sourceLength ) const void *source,
126 						 IN_LENGTH_SHORT_Z const int sourceLength )
127 	{
128 	assert( ( dest == NULL && destMaxLength == 0 ) || \
129 			( isWritePtr( dest, destMaxLength ) ) );
130 	assert( isWritePtr( destLength, sizeof( int ) ) );
131 	assert( ( source == NULL && sourceLength == 0 ) || \
132 			isReadPtr( source, sourceLength ) );
133 
134 	REQUIRES( ( dest == NULL && destMaxLength == 0 ) || \
135 			  ( dest != NULL && \
136 				destMaxLength > 0 && \
137 				destMaxLength < MAX_INTLENGTH_SHORT ) );
138 	REQUIRES( ( source == NULL && sourceLength == 0 ) || \
139 			  ( source != NULL && \
140 			    sourceLength > 0 && \
141 				sourceLength < MAX_INTLENGTH_SHORT ) );
142 
143 	/* Clear return value */
144 	*destLength = 0;
145 
146 	if( sourceLength <= 0 )
147 		return( CRYPT_ERROR_NOTFOUND );
148 	if( dest != NULL )
149 		{
150 		assert( isReadPtr( source, sourceLength ) );
151 
152 		if( sourceLength > destMaxLength || \
153 			!isWritePtr( dest, sourceLength ) )
154 			return( CRYPT_ERROR_OVERFLOW );
155 		memcpy( dest, source, sourceLength );
156 		}
157 	*destLength = sourceLength;
158 
159 	return( CRYPT_OK );
160 	}
161 
162 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
attributeCopy(INOUT MESSAGE_DATA * msgData,IN_BUFFER (attributeLength)const void * attribute,IN_LENGTH_SHORT_Z const int attributeLength)163 int attributeCopy( INOUT MESSAGE_DATA *msgData,
164 				   IN_BUFFER( attributeLength ) const void *attribute,
165 				   IN_LENGTH_SHORT_Z const int attributeLength )
166 	{
167 	assert( isWritePtr( msgData, sizeof( MESSAGE_DATA ) ) );
168 	assert( attributeLength == 0 || \
169 			isReadPtr( attribute, attributeLength ) );
170 
171 	REQUIRES( attributeLength >= 0 && \
172 			  attributeLength < MAX_INTLENGTH_SHORT );
173 
174 	return( attributeCopyParams( msgData->data, msgData->length,
175 								 &msgData->length, attribute,
176 								 attributeLength ) );
177 	}
178 
179 /* Check whether a given algorithm is available */
180 
181 CHECK_RETVAL_BOOL \
algoAvailable(IN_ALGO const CRYPT_ALGO_TYPE cryptAlgo)182 BOOLEAN algoAvailable( IN_ALGO const CRYPT_ALGO_TYPE cryptAlgo )
183 	{
184 	CRYPT_QUERY_INFO queryInfo;
185 
186 	REQUIRES_B( cryptAlgo > CRYPT_ALGO_NONE && \
187 				cryptAlgo < CRYPT_ALGO_LAST );
188 
189 	/* Short-circuit check for always-available algorithms.  The kernel
190 	   won't initialise without the symmetric and hash algorithms being
191 	   present (and SHA-x implies HMAC-SHAx) so it's safe to hardcode them
192 	   in here */
193 	if( cryptAlgo == CRYPT_ALGO_3DES || \
194 		cryptAlgo == CRYPT_ALGO_AES || \
195 		cryptAlgo == CRYPT_ALGO_SHA1 || \
196 		cryptAlgo == CRYPT_ALGO_HMAC_SHA1 || \
197 		cryptAlgo == CRYPT_ALGO_SHA2 || \
198 		cryptAlgo == CRYPT_ALGO_HMAC_SHA2 || \
199 		cryptAlgo == CRYPT_ALGO_RSA )
200 		return( TRUE );
201 
202 	return( cryptStatusOK( krnlSendMessage( SYSTEM_OBJECT_HANDLE,
203 									IMESSAGE_DEV_QUERYCAPABILITY, &queryInfo,
204 									cryptAlgo ) ) ? TRUE : FALSE );
205 	}
206 
207 /* For a given hash algorithm pair, check whether the first is stronger than
208    the second.  The order is:
209 
210 	SNAng > SHA2 > SHA-1 > all others */
211 
212 CHECK_RETVAL_BOOL \
isStrongerHash(IN_ALGO const CRYPT_ALGO_TYPE algorithm1,IN_ALGO const CRYPT_ALGO_TYPE algorithm2)213 BOOLEAN isStrongerHash( IN_ALGO const CRYPT_ALGO_TYPE algorithm1,
214 						IN_ALGO const CRYPT_ALGO_TYPE algorithm2 )
215 	{
216 	static const CRYPT_ALGO_TYPE algoPrecedence[] = {
217 		CRYPT_ALGO_SHAng, CRYPT_ALGO_SHA2, CRYPT_ALGO_SHA1,
218 		CRYPT_ALGO_NONE, CRYPT_ALGO_NONE };
219 	int algo1index, algo2index;
220 
221 	REQUIRES_B( isHashAlgo( algorithm1 ) );
222 	REQUIRES_B( isHashAlgo( algorithm2 ) );
223 
224 	/* Find the relative positions on the scale of the two algorithms */
225 	for( algo1index = 0;
226 		 algoPrecedence[ algo1index ] != algorithm1 && \
227 			algo1index < FAILSAFE_ARRAYSIZE( algoPrecedence, CRYPT_ALGO_TYPE );
228 		 algo1index++ )
229 		{
230 		/* If we've reached an unrated algorithm, it can't be stronger than
231 		   the other one */
232 		if( algoPrecedence[ algo1index ] == CRYPT_ALGO_NONE )
233 			return( FALSE );
234 		}
235 	ENSURES_B( algo1index < FAILSAFE_ARRAYSIZE( algoPrecedence, \
236 												CRYPT_ALGO_TYPE ) );
237 	for( algo2index = 0;
238 		 algoPrecedence[ algo2index ] != algorithm2 && \
239 			algo2index < FAILSAFE_ARRAYSIZE( algoPrecedence, CRYPT_ALGO_TYPE );
240 		 algo2index++ )
241 		{
242 		/* If we've reached an unrated algorithm, it's weaker than the other
243 		   one */
244 		if( algoPrecedence[ algo2index ] == CRYPT_ALGO_NONE )
245 			return( TRUE );
246 		}
247 	ENSURES_B( algo2index < FAILSAFE_ARRAYSIZE( algoPrecedence, \
248 												CRYPT_ALGO_TYPE ) );
249 
250 	/* If the first algorithm has a smaller index than the second, it's a
251 	   stronger algorithm */
252 	return( ( algo1index < algo2index ) ? TRUE : FALSE );
253 	}
254 
255 /* Return a random small integer.  This is used to perform lightweight
256    randomisation of various algorithms in order to make DoS attacks harder.
257    Because of this the values don't have to be cryptographically strong, so
258    all that we do is cache the data from CRYPT_IATTRIBUTE_RANDOM_NONCE and
259    pull out a small integer's worth on each call */
260 
261 #define RANDOM_BUFFER_SIZE	16
262 
263 CHECK_RETVAL_RANGE_NOERROR( 0, 32767 ) \
getRandomInteger(void)264 int getRandomInteger( void )
265 	{
266 	static BYTE nonceData[ RANDOM_BUFFER_SIZE + 8 ];
267 	static int nonceIndex = 0;
268 	int returnValue, status;
269 
270 	REQUIRES_EXT( !( nonceIndex & 1 ), 0 );
271 
272 	/* Initialise/reinitialise the nonce data if necessary.  See the long
273 	   coment for getNonce() in system.c for the reason why we don't bail
274 	   out on error but continue with a lower-quality generator */
275 	if( nonceIndex <= 0 )
276 		{
277 		MESSAGE_DATA msgData;
278 
279 		setMessageData( &msgData, nonceData, RANDOM_BUFFER_SIZE );
280 		status = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
281 								  IMESSAGE_GETATTRIBUTE_S, &msgData,
282 								  CRYPT_IATTRIBUTE_RANDOM_NONCE );
283 		if( cryptStatusError( status ) )
284 			return( ( int ) getTime() & 0x7FFF );
285 		}
286 
287 	/* Extract the next random integer value from the buffered data */
288 	returnValue = ( byteToInt( nonceData[ nonceIndex ] ) << 8 ) | \
289 					byteToInt( nonceData[ nonceIndex + 1 ] );
290 	nonceIndex = ( nonceIndex + 2 ) % RANDOM_BUFFER_SIZE;
291 	ENSURES_EXT( nonceIndex >= 0 && nonceIndex < RANDOM_BUFFER_SIZE, 0 );
292 
293 	/* Return the value constrained to lie within the range 0...32767 */
294 	return( returnValue & 0x7FFF );
295 	}
296 
297 /* Map one value to another, used to map values from one representation
298    (e.g. PGP algorithms or HMAC algorithms) to another (cryptlib algorithms
299    or the underlying hash used for the HMAC algorithm) */
300 
301 CHECK_RETVAL STDC_NONNULL_ARG( ( 2, 3 ) ) \
mapValue(IN_INT_SHORT_Z const int srcValue,OUT_INT_SHORT_Z int * destValue,IN_ARRAY (mapTblSize)const MAP_TABLE * mapTbl,IN_LENGTH_SHORT const int mapTblSize)302 int mapValue( IN_INT_SHORT_Z const int srcValue,
303 			  OUT_INT_SHORT_Z int *destValue,
304 			  IN_ARRAY( mapTblSize ) const MAP_TABLE *mapTbl,
305 			  IN_LENGTH_SHORT const int mapTblSize )
306 	{
307 	int i;
308 
309 	assert( isWritePtr( destValue, sizeof( int ) ) );
310 	assert( isReadPtr( mapTbl, mapTblSize * sizeof( MAP_TABLE ) ) );
311 
312 	REQUIRES( srcValue >= 0 && srcValue < MAX_INTLENGTH_SHORT );
313 	REQUIRES( mapTblSize > 0 && mapTblSize < 100 );
314 	REQUIRES( mapTbl[ mapTblSize ].source == CRYPT_ERROR );
315 
316 	/* Clear return value */
317 	*destValue = 0;
318 
319 	/* Convert the hash algorithm into the equivalent HMAC algorithm */
320 	for( i = 0; i < mapTblSize && mapTbl[ i ].source != CRYPT_ERROR && \
321 				i < FAILSAFE_ITERATIONS_LARGE; i++ )
322 		{
323 		if( mapTbl[ i ].source == srcValue )
324 			{
325 			*destValue = mapTbl[ i ].destination;
326 
327 			return( CRYPT_OK );
328 			}
329 		}
330 	ENSURES( i < mapTblSize );
331 
332 	return( CRYPT_ERROR_NOTAVAIL );
333 	}
334 
335 /****************************************************************************
336 *																			*
337 *							Checksum/Hash Functions							*
338 *																			*
339 ****************************************************************************/
340 
341 /* Calculate a 16-bit Fletcher-like checksum for a block of data.  This
342    isn't quite a pure Fletcher checksum, this isn't a big deal since all we
343    need is consistent results for identical data, the value itself is never
344    communicated externally.  In cases where it's used in critical checks
345    it's merely used as a quick pre-check for a full hash-based check, so it
346    doesn't have to be perfect.  In addition it's not in any way
347    cryptographically secure for the same reason, there's no particular need
348    for it to be secure.  If a requirement for at least some sort of
349    unpredictability did arise then something like Pearson hashing could be
350    substituted transparently */
351 
352 RETVAL_RANGE( MAX_ERROR, 0xFFFF ) STDC_NONNULL_ARG( ( 1 ) ) \
checksumData(IN_BUFFER (dataLength)const void * data,IN_DATALENGTH const int dataLength)353 int checksumData( IN_BUFFER( dataLength ) const void *data,
354 				  IN_DATALENGTH const int dataLength )
355 	{
356 	const BYTE *dataPtr = data;
357 	int sum1 = 1, sum2 = 0, i;
358 
359 	assert( isReadPtr( data, dataLength ) );
360 
361 	REQUIRES( data != NULL );
362 	REQUIRES( dataLength > 0 && dataLength < MAX_BUFFER_SIZE )
363 
364 	for( i = 0; i < dataLength; i++ )
365 		{
366 		sum1 += dataPtr[ i ];
367 		sum2 += sum1;
368 		}
369 
370 #if defined( SYSTEM_16BIT )
371 	return( sum2 & 0x7FFF );
372 #else
373 	return( ( ( sum2 & 0x7FFF ) << 16 ) | ( sum1 & 0xFFFF ) );
374 #endif /* 16- vs. 32-bit systems */
375 	}
376 
377 /* Calculate the hash of a block of data.  We use SHA-1 because it's the
378    built-in default, but any algorithm will do since we're only using it
379    to transform a variable-length value to a fixed-length one for easy
380    comparison purposes */
381 
382 STDC_NONNULL_ARG( ( 1, 3 ) ) \
hashData(OUT_BUFFER_FIXED (hashMaxLength)BYTE * hash,IN_LENGTH_HASH const int hashMaxLength,IN_BUFFER (dataLength)const void * data,IN_DATALENGTH const int dataLength)383 void hashData( OUT_BUFFER_FIXED( hashMaxLength ) BYTE *hash,
384 			   IN_LENGTH_HASH const int hashMaxLength,
385 			   IN_BUFFER( dataLength ) const void *data,
386 			   IN_DATALENGTH const int dataLength )
387 	{
388 	HASH_FUNCTION_ATOMIC hashFunctionAtomic;
389 	BYTE hashBuffer[ CRYPT_MAX_HASHSIZE + 8 ];
390 	int hashSize;
391 
392 	assert( isWritePtr( hash, hashMaxLength ) );
393 	assert( hashMaxLength >= 16 && \
394 			hashMaxLength <= CRYPT_MAX_HASHSIZE );
395 	assert( isReadPtr( data, dataLength ) );
396 	assert( dataLength > 0 && dataLength < MAX_BUFFER_SIZE );
397 
398 	/* Get the hash algorithm information if necessary */
399 	getHashAtomicParameters( CRYPT_ALGO_SHA1, 0, &hashFunctionAtomic,
400 							 &hashSize );
401 
402 	/* Error handling: If there's a problem, return a zero hash.  We use
403 	   this strategy since this is a void function and so the usual
404 	   REQUIRES() predicate won't be effective.  Note that this can lead to
405 	   a false-positive match if we're called multiple times with invalid
406 	   input, in theory we could fill the return buffer with nonce data to
407 	   ensure that we never get a false-positive match but since this is a
408 	   should-never-occur condition anyway it's not certain whether forcing
409 	   a match or forcing a non-match is the preferred behaviour */
410 	if( data == NULL || dataLength <= 0 || dataLength >= MAX_BUFFER_SIZE || \
411 		hashMaxLength < 16 || hashMaxLength > hashSize || \
412 		hashMaxLength > CRYPT_MAX_HASHSIZE || hashFunctionAtomic == NULL )
413 		{
414 		memset( hash, 0, hashMaxLength );
415 		retIntError_Void();
416 		}
417 
418 	/* Hash the data and copy as many bytes as the caller has requested to
419 	   the output.  Typically they'll require only a subset of the full
420 	   amount since all that we're doing is transforming a variable-length
421 	   value to a fixed-length value for easy comparison purposes */
422 	hashFunctionAtomic( hashBuffer, hashSize, data, dataLength );
423 	memcpy( hash, hashBuffer, hashMaxLength );
424 	zeroise( hashBuffer, hashSize );
425 	}
426 
427 /* Compare two blocks of memory in a time-independent manner.  This is used
428    to avoid potential timing attacks on memcmp(), which bails out as soon as
429    it finds a mismatch */
430 
431 CHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1, 2 ) ) \
compareDataConstTime(IN_BUFFER (length)const void * src,IN_BUFFER (length)const void * dest,IN_LENGTH_SHORT const int length)432 BOOLEAN compareDataConstTime( IN_BUFFER( length ) const void *src,
433 							  IN_BUFFER( length ) const void *dest,
434 							  IN_LENGTH_SHORT const int length )
435 	{
436 	const BYTE *srcPtr = src, *destPtr = dest;
437 	int value = 0, i;
438 
439 	assert( isReadPtr( src, length ) );
440 	assert( isReadPtr( dest, length ) );
441 
442 	REQUIRES_B( length > 0 && length < MAX_INTLENGTH_SHORT );
443 
444 	/* Compare the two values in a time-independent manner */
445 	for( i = 0; i < length; i++ )
446 		value |= srcPtr[ i ] ^ destPtr[ i ];
447 
448 	return( !value );
449 	}
450 
451 /****************************************************************************
452 *																			*
453 *							Stream Export/Import Routines					*
454 *																			*
455 ****************************************************************************/
456 
457 /* Export attribute or certificate data to a stream.  In theory we would
458    have to export this via a dynbuf and then write it to the stream but we
459    can save some overhead by writing it directly to the stream's buffer.
460 
461    Some attributes have a user-defined size (e.g.
462    CRYPT_IATTRIBUTE_RANDOM_NONCE) so we allow the caller to specify an
463    optional length parameter indicating how much of the attribute should be
464    exported */
465 
466 CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
exportAttr(INOUT STREAM * stream,IN_HANDLE const CRYPT_HANDLE cryptHandle,IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attributeType,IN_LENGTH_INDEF const int length)467 static int exportAttr( INOUT STREAM *stream,
468 					   IN_HANDLE const CRYPT_HANDLE cryptHandle,
469 					   IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attributeType,
470 					   IN_LENGTH_INDEF const int length )
471 							/* Declared as LENGTH_INDEF because SHORT_INDEF
472 							   doesn't make sense */
473 	{
474 	MESSAGE_DATA msgData;
475 	void *dataPtr = NULL;
476 	int attrLength = 0, status;
477 
478 	assert( isWritePtr( stream, sizeof( STREAM ) ) );
479 	assert( sStatusOK( stream ) );
480 
481 	REQUIRES( cryptHandle == SYSTEM_OBJECT_HANDLE || \
482 			  isHandleRangeValid( cryptHandle ) );
483 	REQUIRES( isAttribute( attributeType ) || \
484 			  isInternalAttribute( attributeType ) );
485 	REQUIRES( ( length == CRYPT_UNUSED ) || \
486 			  ( length >= 8 && length < MAX_INTLENGTH_SHORT ) );
487 
488 	/* Get access to the stream buffer if required */
489 	if( !sIsNullStream( stream ) )
490 		{
491 		if( length != CRYPT_UNUSED )
492 			{
493 			/* It's an explicit-length attribute, make sure that there's
494 			   enough room left in the stream for it */
495 			attrLength = length;
496 			status = sMemGetDataBlock( stream, &dataPtr, length );
497 			}
498 		else
499 			{
500 			/* It's an implicit-length attribute whose maximum length is
501 			   defined by the stream size */
502 			status = sMemGetDataBlockRemaining( stream, &dataPtr,
503 												&attrLength );
504 			}
505 		if( cryptStatusError( status ) )
506 			return( status );
507 		}
508 
509 	/* Export the attribute directly into the stream buffer */
510 	setMessageData( &msgData, dataPtr, attrLength );
511 	status = krnlSendMessage( cryptHandle, IMESSAGE_GETATTRIBUTE_S,
512 							  &msgData, attributeType );
513 	if( cryptStatusOK( status ) )
514 		status = sSkip( stream, msgData.length, SSKIP_MAX );
515 	return( status );
516 	}
517 
518 CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
exportAttributeToStream(INOUT TYPECAST (STREAM *)void * streamPtr,IN_HANDLE const CRYPT_HANDLE cryptHandle,IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attributeType)519 int exportAttributeToStream( INOUT TYPECAST( STREAM * ) void *streamPtr,
520 							 IN_HANDLE const CRYPT_HANDLE cryptHandle,
521 							 IN_ATTRIBUTE \
522 								const CRYPT_ATTRIBUTE_TYPE attributeType )
523 	{
524 	assert( isWritePtr( streamPtr, sizeof( STREAM ) ) );
525 
526 	REQUIRES( isHandleRangeValid( cryptHandle ) );
527 	REQUIRES( isAttribute( attributeType ) || \
528 			  isInternalAttribute( attributeType ) );
529 
530 	return( exportAttr( streamPtr, cryptHandle, attributeType, \
531 						CRYPT_UNUSED ) );
532 	}
533 
534 CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
535 int exportVarsizeAttributeToStream( INOUT TYPECAST( STREAM * ) void *streamPtr,
536 									IN_HANDLE const CRYPT_HANDLE cryptHandle,
537 									IN_LENGTH_FIXED( CRYPT_IATTRIBUTE_RANDOM_NONCE ) \
538 										const CRYPT_ATTRIBUTE_TYPE attributeType,
539 									IN_RANGE( 8, 1024 ) \
540 										const int attributeDataLength )
541 	{
542 	assert( isWritePtr( streamPtr, sizeof( STREAM ) ) );
543 
544 	REQUIRES( cryptHandle == SYSTEM_OBJECT_HANDLE );
545 	REQUIRES( attributeType == CRYPT_IATTRIBUTE_RANDOM_NONCE );
546 	REQUIRES( attributeDataLength >= 8 && \
547 			  attributeDataLength <= MAX_ATTRIBUTE_SIZE );
548 
549 	return( exportAttr( streamPtr, cryptHandle, attributeType,
550 						attributeDataLength ) );
551 	}
552 
553 CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
exportCertToStream(INOUT TYPECAST (STREAM *)void * streamPtr,IN_HANDLE const CRYPT_CERTIFICATE cryptCertificate,IN_ENUM (CRYPT_CERTFORMAT)const CRYPT_CERTFORMAT_TYPE certFormatType)554 int exportCertToStream( INOUT TYPECAST( STREAM * ) void *streamPtr,
555 						IN_HANDLE const CRYPT_CERTIFICATE cryptCertificate,
556 						IN_ENUM( CRYPT_CERTFORMAT ) \
557 							const CRYPT_CERTFORMAT_TYPE certFormatType )
558 	{
559 	MESSAGE_DATA msgData;
560 	STREAM *stream = streamPtr;
561 	void *dataPtr = NULL;
562 	int length = 0, status;
563 
564 	assert( isWritePtr( stream, sizeof( STREAM ) ) );
565 	assert( sStatusOK( stream ) );
566 
567 	REQUIRES( isHandleRangeValid( cryptCertificate ) );
568 	REQUIRES( certFormatType > CRYPT_CERTFORMAT_NONE && \
569 			  certFormatType < CRYPT_CERTFORMAT_LAST );
570 
571 	/* Get access to the stream buffer if required */
572 	if( !sIsNullStream( stream ) )
573 		{
574 		status = sMemGetDataBlockRemaining( stream, &dataPtr, &length );
575 		if( cryptStatusError( status ) )
576 			return( status );
577 		}
578 
579 	/* Export the certificate directly into the stream buffer */
580 	setMessageData( &msgData, dataPtr, length );
581 	status = krnlSendMessage( cryptCertificate, IMESSAGE_CRT_EXPORT,
582 							  &msgData, certFormatType );
583 	if( cryptStatusOK( status ) )
584 		status = sSkip( stream, msgData.length, SSKIP_MAX );
585 	return( status );
586 	}
587 
588 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
importCertFromStream(INOUT void * streamPtr,OUT_HANDLE_OPT CRYPT_CERTIFICATE * cryptCertificate,IN_HANDLE const CRYPT_USER iCryptOwner,IN_ENUM (CRYPT_CERTTYPE)const CRYPT_CERTTYPE_TYPE certType,IN_LENGTH_SHORT_MIN (MIN_CRYPT_OBJECTSIZE)const int certDataLength,IN_FLAGS_Z (KEYMGMT)const int options)589 int importCertFromStream( INOUT void *streamPtr,
590 						  OUT_HANDLE_OPT CRYPT_CERTIFICATE *cryptCertificate,
591 						  IN_HANDLE const CRYPT_USER iCryptOwner,
592 						  IN_ENUM( CRYPT_CERTTYPE ) \
593 							const CRYPT_CERTTYPE_TYPE certType,
594 						  IN_LENGTH_SHORT_MIN( MIN_CRYPT_OBJECTSIZE ) \
595 							const int certDataLength,
596 						  IN_FLAGS_Z( KEYMGMT ) const int options )
597 	{
598 	MESSAGE_CREATEOBJECT_INFO createInfo;
599 	STREAM *stream = streamPtr;
600 	void *dataPtr;
601 	int status;
602 
603 	assert( isWritePtr( stream, sizeof( STREAM ) ) );
604 	assert( sStatusOK( stream ) );
605 	assert( isWritePtr( cryptCertificate, sizeof( CRYPT_CERTIFICATE ) ) );
606 
607 	REQUIRES( iCryptOwner == DEFAULTUSER_OBJECT_HANDLE || \
608 			  isHandleRangeValid( iCryptOwner ) );
609 	REQUIRES( certType > CRYPT_CERTTYPE_NONE && \
610 			  certType < CRYPT_CERTTYPE_LAST );
611 	REQUIRES( certDataLength >= MIN_CRYPT_OBJECTSIZE && \
612 			  certDataLength < MAX_INTLENGTH_SHORT );
613 	REQUIRES( options >= KEYMGMT_FLAG_NONE && options < KEYMGMT_FLAG_MAX && \
614 			  ( options & ~KEYMGMT_FLAG_DATAONLY_CERT ) == 0 );
615 
616 	/* Clear return value */
617 	*cryptCertificate = CRYPT_ERROR;
618 
619 	/* Get access to the stream buffer and skip over the certificate data */
620 	status = sMemGetDataBlock( stream, &dataPtr, certDataLength );
621 	if( cryptStatusOK( status ) )
622 		status = sSkip( stream, certDataLength, SSKIP_MAX );
623 	if( cryptStatusError( status ) )
624 		return( status );
625 
626 	/* Import the certificate directly from the stream buffer */
627 	setMessageCreateObjectIndirectInfoEx( &createInfo, dataPtr,
628 						certDataLength, certType,
629 						( options & KEYMGMT_FLAG_DATAONLY_CERT ) ? \
630 							KEYMGMT_FLAG_DATAONLY_CERT : KEYMGMT_FLAG_NONE );
631 	createInfo.cryptOwner = iCryptOwner;
632 	status = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
633 							  IMESSAGE_DEV_CREATEOBJECT_INDIRECT,
634 							  &createInfo, OBJECT_TYPE_CERTIFICATE );
635 	if( cryptStatusError( status ) )
636 		return( status );
637 	*cryptCertificate = createInfo.cryptHandle;
638 	return( CRYPT_OK );
639 	}
640 
641 /****************************************************************************
642 *																			*
643 *							Public-key Import Routines						*
644 *																			*
645 ****************************************************************************/
646 
647 #ifdef USE_INT_ASN1
648 
649 /* Read a public key from an X.509 SubjectPublicKeyInfo record, creating the
650    context necessary to contain it in the process.  This is used by a variety
651    of modules including certificate-management, keyset, and crypto device.
652 
653    The use of the void * instead of STREAM * is necessary because the STREAM
654    type isn't visible at the global level */
655 
656 CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
checkKeyLength(INOUT STREAM * stream,const CRYPT_ALGO_TYPE cryptAlgo,const BOOLEAN hasAlgoParameters)657 static int checkKeyLength( INOUT STREAM *stream,
658 						   const CRYPT_ALGO_TYPE cryptAlgo,
659 						   const BOOLEAN hasAlgoParameters )
660 	{
661 	const long startPos = stell( stream );
662 	int keyLength, status;
663 
664 	assert( isWritePtr( stream, sizeof( STREAM ) ) );
665 
666 	REQUIRES( isPkcAlgo( cryptAlgo ) );
667 
668 	/* ECC algorithms are a complete mess to handle because of the arbitrary
669 	   manner in which the algorithm parameters can be represented.  To deal
670 	   with this we skip the parameters and read the public key value, which
671 	   is a point on a curve stuffed in a variety of creative ways into an
672 	   BIT STRING.  Since this contains two values (the x and y coordinates)
673 	   we divide the lengths used by two to get an approximation of the
674 	   nominal key size */
675 	if( isEccAlgo( cryptAlgo ) )
676 		{
677 		readUniversal( stream );	/* Skip algorithm parameters */
678 		status = readBitStringHole( stream, &keyLength,
679 									MIN_PKCSIZE_ECCPOINT_THRESHOLD,
680 									DEFAULT_TAG );
681 		if( cryptStatusOK( status ) && isShortECCKey( keyLength / 2 ) )
682 			status = CRYPT_ERROR_NOSECURE;
683 		if( cryptStatusError( status ) )
684 			return( status );
685 
686 		return( sseek( stream, startPos ) );
687 		}
688 
689 	/* Read the key component that defines the nominal key size, either the
690 	   first algorithm parameter or the first public-key component */
691 	if( hasAlgoParameters )
692 		{
693 		readSequence( stream, NULL );
694 		status = readGenericHole( stream, &keyLength, MIN_PKCSIZE_THRESHOLD,
695 								  BER_INTEGER );
696 		}
697 	else
698 		{
699 		readBitStringHole( stream, NULL, MIN_PKCSIZE_THRESHOLD, DEFAULT_TAG );
700 		readSequence( stream, NULL );
701 		status = readGenericHole( stream, &keyLength, MIN_PKCSIZE_THRESHOLD,
702 								  BER_INTEGER );
703 		}
704 	if( cryptStatusError( status ) )
705 		return( status );
706 
707 	/* Check whether the nominal keysize is within the range defined as
708 	   being a weak key */
709 	if( isShortPKCKey( keyLength ) )
710 		return( CRYPT_ERROR_NOSECURE );
711 
712 	return( sseek( stream, startPos ) );
713 	}
714 
715 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
iCryptReadSubjectPublicKey(INOUT TYPECAST (STREAM *)void * streamPtr,OUT_HANDLE_OPT CRYPT_CONTEXT * iPubkeyContext,IN_HANDLE const CRYPT_DEVICE iCreatorHandle,const BOOLEAN deferredLoad)716 int iCryptReadSubjectPublicKey( INOUT TYPECAST( STREAM * ) void *streamPtr,
717 								OUT_HANDLE_OPT CRYPT_CONTEXT *iPubkeyContext,
718 								IN_HANDLE const CRYPT_DEVICE iCreatorHandle,
719 								const BOOLEAN deferredLoad )
720 	{
721 	CRYPT_ALGO_TYPE cryptAlgo;
722 	CRYPT_CONTEXT iCryptContext;
723 	MESSAGE_CREATEOBJECT_INFO createInfo;
724 	MESSAGE_DATA msgData;
725 	STREAM *stream = streamPtr;
726 	void *spkiPtr DUMMY_INIT_PTR;
727 	int spkiLength, length, status;
728 
729 	assert( isReadPtr( stream, sizeof( STREAM ) ) );
730 	assert( isWritePtr( iPubkeyContext, sizeof( CRYPT_CONTEXT ) ) );
731 
732 	REQUIRES( iCreatorHandle == SYSTEM_OBJECT_HANDLE || \
733 			  isHandleRangeValid( iCreatorHandle ) );
734 
735 	/* Clear return value */
736 	*iPubkeyContext = CRYPT_ERROR;
737 
738 	/* Pre-parse the SubjectPublicKeyInfo, both to ensure that it's (at
739 	   least generally) valid before we go to the extent of creating an
740 	   encryption context to contain it and to get access to the
741 	   SubjectPublicKeyInfo data and algorithm information.  Because all
742 	   sorts of bizarre tagging exist due to things like CRMF we read the
743 	   wrapper as a generic hole rather than the more obvious SEQUENCE */
744 	status = getStreamObjectLength( stream, &spkiLength );
745 	if( cryptStatusOK( status ) )
746 		status = sMemGetDataBlock( stream, &spkiPtr, spkiLength );
747 	if( cryptStatusOK( status ) )
748 		{
749 		status = readGenericHole( stream, NULL,
750 								  MIN_PKCSIZE_ECCPOINT_THRESHOLD,
751 								  DEFAULT_TAG );
752 		}
753 	if( cryptStatusError( status ) )
754 		return( status );
755 	status = readAlgoIDparam( stream, &cryptAlgo, &length,
756 							  ALGOID_CLASS_PKC );
757 	if( cryptStatusError( status ) )
758 		return( status );
759 
760 	/* Perform minimal key-length checking.  We need to do this at this
761 	   point (rather than having it done implicitly in the
762 	   SubjectPublicKeyInfo read code) because a too-short key (or at least
763 	   too-short key data) will result in the kernel rejecting the
764 	   SubjectPublicKeyInfo before it can be processed, leading to a rather
765 	   misleading CRYPT_ERROR_BADDATA return status rather the correct
766 	   CRYPT_ERROR_NOSECURE */
767 	status = checkKeyLength( stream, cryptAlgo,
768 							 ( length > 0 ) ? TRUE : FALSE );
769 	if( cryptStatusError( status ) )
770 		return( status );
771 
772 	/* Skip the remainder of the key components in the stream, first the
773 	   algorithm parameters (if there are any) and then the public-key
774 	   data */
775 	if( length > 0 )
776 		readUniversal( stream );
777 	status = readUniversal( stream );
778 	if( cryptStatusError( status ) )
779 		return( status );
780 
781 	/* Create the public-key context and send the public-key data to it */
782 	setMessageCreateObjectInfo( &createInfo, cryptAlgo );
783 	status = krnlSendMessage( iCreatorHandle, IMESSAGE_DEV_CREATEOBJECT,
784 							  &createInfo, OBJECT_TYPE_CONTEXT );
785 	if( cryptStatusError( status ) )
786 		return( status );
787 	iCryptContext = createInfo.cryptHandle;
788 	setMessageData( &msgData, spkiPtr, spkiLength );
789 	status = krnlSendMessage( iCryptContext, IMESSAGE_SETATTRIBUTE_S,
790 							  &msgData, deferredLoad ? \
791 								CRYPT_IATTRIBUTE_KEY_SPKI_PARTIAL : \
792 								CRYPT_IATTRIBUTE_KEY_SPKI );
793 	if( cryptStatusError( status ) )
794 		{
795 		krnlSendNotifier( iCryptContext, IMESSAGE_DECREFCOUNT );
796 		if( status == CRYPT_ARGERROR_STR1 || \
797 			status == CRYPT_ARGERROR_NUM1 )
798 			{
799 			/* If the key data was rejected by the kernel before it got to
800 			   the SubjectPublicKeyInfo read code (see the comment above)
801 			   then it'll be rejected with an argument-error code, which we
802 			   have to convert to a bad-data error before returning it to
803 			   the caller */
804 			return( CRYPT_ERROR_BADDATA );
805 			}
806 		if( cryptArgError( status ) )
807 			{
808 			DEBUG_DIAG(( "Public-key load returned argError status" ));
809 			assert( DEBUG_WARN );
810 			status = CRYPT_ERROR_BADDATA;
811 			}
812 		return( status );
813 		}
814 	*iPubkeyContext = iCryptContext;
815 	assert( cryptStatusError( \
816 				krnlSendMessage( iCryptContext, IMESSAGE_CHECK,
817 								 NULL, MESSAGE_CHECK_PKC_PRIVATE ) ) );
818 	return( CRYPT_OK );
819 	}
820 #endif /* USE_INT_ASN1 */
821 
822 /****************************************************************************
823 *																			*
824 *							Safe Text-line Read Functions					*
825 *																			*
826 ****************************************************************************/
827 
828 #if defined( USE_HTTP ) || defined( USE_BASE64 ) || defined( USE_SSH )
829 
830 /* Read a line of text data ending in an EOL.  If we get more data than will
831    fit into the read buffer we discard it until we find an EOL.  As a
832    secondary concern we want to strip leading, trailing, and repeated
833    whitespace.  Leading whitespace is handled by setting the seen-whitespace
834    flag to true initially, this treats any whitespace at the start of the
835    line as superfluous and strips it.  Stripping of repeated whitespace is
836    also handled by the seenWhitespace flag, and stripping of trailing
837    whitespace is handled by walking back through any final whitespace once we
838    see the EOL.
839 
840    We optionally handle continued lines denoted by the MIME convention of a
841    semicolon as the last non-whitespace character by setting the
842    seenContinuation flag if we see a semicolon as the last non-whitespace
843    character.
844 
845    Finally, we also need to handle generic DoS attacks.  If we see more than
846    MAX_LINE_LENGTH chars in a line we bail out */
847 
848 #define MAX_LINE_LENGTH		4096
849 
850 /* The extra level of indirection provided by this function is necessary
851    because the the extended error information isn't accessible from outside
852    the stream code so we can't set it in formatTextLineError() in the usual
853    manner via a retExt().  Instead we call retExtFn() directly and then pass
854    the result down to the stream layer via an ioctl */
855 
856 CHECK_RETVAL_ERROR STDC_NONNULL_ARG( ( 1, 2 ) ) \
exitTextLineError(INOUT STREAM * stream,FORMAT_STRING const char * format,const int value1,const int value2,OUT_OPT_BOOL BOOLEAN * localError,IN_ERROR const int status)857 static int exitTextLineError( INOUT STREAM *stream,
858 							  FORMAT_STRING const char *format,
859 							  const int value1, const int value2,
860 							  OUT_OPT_BOOL BOOLEAN *localError,
861 							  IN_ERROR const int status )
862 	{
863 	ERROR_INFO errorInfo;
864 
865 	assert( isWritePtr( stream, sizeof( STREAM ) ) );
866 	assert( isReadPtr( format, 4 ) );
867 	assert( localError == NULL || \
868 			isReadPtr( localError, sizeof( BOOLEAN ) ) );
869 
870 	REQUIRES( cryptStatusError( status ) );
871 
872 	/* If the stream doesn't support extended error information, we're
873 	   done */
874 	if( localError == NULL )
875 		return( status );
876 
877 	/* The CRYPT_ERROR_BADDATA is a dummy code used in order to be able to
878 	   call retExtFn() to format the error string */
879 	*localError = TRUE;
880 	( void ) retExtFn( CRYPT_ERROR_BADDATA, &errorInfo, format,
881 					   value1, value2 );
882 	sioctlSetString( stream, STREAM_IOCTL_ERRORINFO, &errorInfo,
883 					 sizeof( ERROR_INFO ) );
884 
885 	return( status );
886 	}
887 
888 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3, 5 ) ) \
889 int readTextLine( READCHAR_FUNCTION readCharFunction,
890 				  INOUT void *streamPtr,
891 				  OUT_BUFFER( lineBufferMaxLen, *lineBufferSize ) \
892 						char *lineBuffer,
893 				  IN_LENGTH_SHORT_MIN( 16 ) const int lineBufferMaxLen,
894 				  OUT_RANGE( 0, lineBufferMaxLen ) int *lineBufferSize,
895 				  OUT_OPT_BOOL BOOLEAN *localError,
896 				  const BOOLEAN allowContinuation )
897 	{
898 	BOOLEAN seenWhitespace, seenContinuation = FALSE;
899 	int totalChars, bufPos = 0;
900 
901 	assert( isWritePtr( streamPtr, sizeof( STREAM ) ) );
902 	assert( isWritePtr( lineBuffer, lineBufferMaxLen ) );
903 	assert( isWritePtr( lineBufferSize, sizeof( int ) ) );
904 	assert( localError == NULL || \
905 			isWritePtr( localError, sizeof( BOOLEAN ) ) );
906 
907 	REQUIRES( readCharFunction != NULL );
908 	REQUIRES( lineBufferMaxLen >= 16 && \
909 			  lineBufferMaxLen < MAX_INTLENGTH_SHORT );
910 
911 	/* Clear return values */
912 	memset( lineBuffer, 0, min( 16, lineBufferMaxLen ) );
913 	*lineBufferSize = 0;
914 	if( localError != NULL )
915 		*localError = FALSE;
916 
917 	/* Set the seen-whitespace flag initially to strip leading whitespace */
918 	seenWhitespace = TRUE;
919 
920 	/* Read up to MAX_LINE_LENGTH chars.  Anything longer than this is
921 	   probably a DoS */
922 	for( totalChars = 0; totalChars < MAX_LINE_LENGTH; totalChars++ )
923 		{
924 		int ch, status;
925 
926 		/* Get the next input character */
927 		status = ch = readCharFunction( streamPtr );
928 		if( cryptStatusError( status ) )
929 			return( status );
930 
931 		/* If it's an EOL or a continuation marker, strip trailing
932 		   whitespace */
933 		if( ch == '\n' || ( allowContinuation && ch == ';' ) )
934 			{
935 			/* Strip trailing whitespace.  At this point it's all been
936 			   canonicalised so we don't need to check for anything other
937 			   than spaces */
938 			while( bufPos > 0 && lineBuffer[ bufPos - 1 ] == ' ' )
939 				bufPos--;
940 			}
941 
942 		/* Process EOL */
943 		if( ch == '\n' )
944 			{
945 			/* If we've seen a continuation marker, the line continues on
946 			   the next one */
947 			if( seenContinuation )
948 				{
949 				seenContinuation = FALSE;
950 				continue;
951 				}
952 
953 			/* We're done */
954 			break;
955 			}
956 
957 		/* Ignore any additional decoration that may accompany EOLs */
958 		if( ch == '\r' )
959 			continue;
960 
961 		/* If we're over the maximum buffer size discard any further input
962 		   until we either hit EOL or exceed the DoS threshold at
963 		   MAX_LINE_LENGTH */
964 		if( bufPos >= lineBufferMaxLen )
965 			{
966 			/* If we've run off into the weeds (for example we're reading
967 			   binary data following the text header), bail out */
968 			if( !isValidTextChar( ch ) )
969 				{
970 				return( exitTextLineError( streamPtr, "Invalid character "
971 										   "0x%02X at position %d", ch,
972 										   totalChars, localError,
973 										   CRYPT_ERROR_BADDATA ) );
974 				}
975 			continue;
976 			}
977 
978 		/* Process whitespace.  We can't use isspace() for this because it
979 		   includes all sorts of extra control characters that we don't want
980 		   to allow */
981 		if( ch == ' ' || ch == '\t' )
982 			{
983 			if( seenWhitespace )
984 				{
985 				/* Ignore leading and repeated whitespace */
986 				continue;
987 				}
988 			ch = ' ';	/* Canonicalise whitespace */
989 			}
990 
991 		/* Process any remaining chars */
992 		if( !isValidTextChar( ch ) )
993 			{
994 			return( exitTextLineError( streamPtr, "Invalid character "
995 									   "0x%02X at position %d", ch,
996 									   totalChars, localError,
997 									   CRYPT_ERROR_BADDATA ) );
998 			}
999 		lineBuffer[ bufPos++ ] = intToByte( ch );
1000 		ENSURES( bufPos > 0 && bufPos <= totalChars + 1 );
1001 				 /* The 'totalChars + 1' is because totalChars is the loop
1002 				    iterator and won't have been incremented yet at this
1003 					point */
1004 
1005 		/* Update the state variables.  If the character that we've just
1006 		   processed was whitespace or if we've seen a continuation
1007 		   character or we're processing whitespace after having seen a
1008 		   continuation character (which makes it effectively leading
1009 		   whitespace to be stripped), remember this */
1010 		seenWhitespace = ( ch == ' ' ) ? TRUE : FALSE;
1011 		seenContinuation = allowContinuation && \
1012 						   ( ch == ';' || \
1013 						     ( seenContinuation && seenWhitespace ) ) ? \
1014 						   TRUE : FALSE;
1015 		}
1016 	if( totalChars >= MAX_LINE_LENGTH )
1017 		{
1018 		return( exitTextLineError( streamPtr, "Text line too long, more "
1019 								   "than %d characters", MAX_LINE_LENGTH, 0,
1020 								   localError, CRYPT_ERROR_OVERFLOW ) );
1021 		}
1022 	*lineBufferSize = bufPos;
1023 
1024 	return( CRYPT_OK );
1025 	}
1026 #endif /* USE_HTTP || USE_BASE64 || USE_SSH */
1027 
1028 /****************************************************************************
1029 *																			*
1030 *								Self-test Functions							*
1031 *																			*
1032 ****************************************************************************/
1033 
1034 /* Test code for the above functions */
1035 
1036 #ifndef NDEBUG
1037 
1038 #if defined( USE_HTTP ) || defined( USE_BASE64 ) || defined( USE_SSH )
1039 
1040 #include "io/stream.h"
1041 
1042 CHECK_RETVAL_RANGE( 0, 255 ) STDC_NONNULL_ARG( ( 1 ) ) \
readCharFunction(INOUT TYPECAST (STREAM *)void * streamPtr)1043 static int readCharFunction( INOUT TYPECAST( STREAM * ) void *streamPtr )
1044 	{
1045 	STREAM *stream = streamPtr;
1046 	BYTE ch;
1047 	int status;
1048 
1049 	assert( isWritePtr( stream, sizeof( STREAM ) ) );
1050 
1051 	status = sread( stream, &ch, 1 );
1052 	return( cryptStatusError( status ) ? status : byteToInt( ch ) );
1053 	}
1054 
1055 CHECK_RETVAL_BOOL \
IN_BUFFER(dataInLength)1056 static BOOLEAN testReadLine( IN_BUFFER( dataInLength ) char *dataIn,
1057 							 IN_LENGTH_SHORT_MIN( 8 ) const int dataInLength,
1058 							 IN_BUFFER( dataOutLength ) char *dataOut,
1059 							 IN_LENGTH_SHORT_MIN( 1 ) const int dataOutLength,
1060 							 const BOOLEAN allowContinuation )
1061 	{
1062 	STREAM stream;
1063 	BYTE buffer[ 16 + 8 ];
1064 	int length, status;
1065 
1066 	assert( isReadPtr( dataIn, dataInLength ) );
1067 	assert( isReadPtr( dataOut, dataOutLength ) );
1068 
1069 	REQUIRES( dataInLength >= 8 && dataInLength < MAX_INTLENGTH_SHORT );
1070 	REQUIRES( dataOutLength >= 1 && dataOutLength < MAX_INTLENGTH_SHORT );
1071 
1072 	sMemPseudoConnect( &stream, dataIn, dataInLength );
1073 	status = readTextLine( readCharFunction, &stream, buffer, 16,
1074 						   &length, NULL, allowContinuation );
1075 	if( cryptStatusError( status ) )
1076 		return( FALSE );
1077 	if( length != dataOutLength || memcmp( buffer, dataOut, dataOutLength ) )
1078 		return( FALSE );
1079 	sMemDisconnect( &stream );
1080 
1081 	return( TRUE );
1082 	}
1083 #endif /* USE_HTTP || USE_BASE64 || USE_SSH */
1084 
1085 CHECK_RETVAL_BOOL \
testIntAPI(void)1086 BOOLEAN testIntAPI( void )
1087 	{
1088 #if 0
1089 checkNontrivialKey( "\x2E\x19\x76\x57\xDB\x30\xE6\x26", 8 );
1090 checkNontrivialKey( "\x14\xF3\x3C\x5A\xB8\x63\x13\xFB", 8 );
1091 checkNontrivialKey( "\x7B\xE0\xE4\x14\x5C\x7C\x2C\x07", 8 );
1092 checkNontrivialKey( "\xD3\x9C\x16\x37\xAD\x12\x19\xA2", 8 );
1093 checkNontrivialKey( "\x7F\x6B\x30\xAD\x02\x83\x96\xF9", 8 );
1094 checkNontrivialKey( "\x79\x92\xF9\xD1\x75\x43\x56\x87", 8 );
1095 checkNontrivialKey( "\x62\xAF\x14\xCF\x1F\x5F\xA7\xC6", 8 );
1096 checkNontrivialKey( "\xAE\x57\xF3\x63\x45\x03\x2E\x6B", 8 );
1097 checkNontrivialKey( "abcdefgh", 8 );
1098 checkNontrivialKey( "\x01\x23\x45\x67\x89\xAB\xCD\xEF", 8 );
1099 checkNontrivialKey( "\xA5\x5A\xA5\x5A\xA5\x5A\xA5\x5A", 8 );
1100 #endif
1101 
1102 	/* Test the entropy-check code */
1103 	if( !checkEntropy( "\x2E\x19\x76\x57\xDB\x30\xE6\x26", 8 ) || \
1104 		!checkEntropy( "\x14\xF3\x3C\x5A\xB8\x63\x13\xFB", 8 ) || \
1105 		!checkEntropy( "\x7B\xE0\xE4\x14\x5C\x7C\x2C\x07", 8 ) || \
1106 		!checkEntropy( "\xD3\x9C\x16\x37\xAD\x12\x19\xA2", 8 ) || \
1107 		!checkEntropy( "\x7F\x6B\x30\xAD\x02\x83\x96\xF9", 8 ) || \
1108 		!checkEntropy( "\x79\x92\xF9\xD1\x75\x43\x56\x87", 8 ) || \
1109 		!checkEntropy( "\x62\xAF\x14\xCF\x1F\x5F\xA7\xC6", 8 ) || \
1110 		!checkEntropy( "\xAE\x57\xF3\x63\x45\x03\x2E\x6B", 8 ) )
1111 		return( FALSE );
1112 	if( checkEntropy( "\xA5\x5A\xA5\x5A\xA5\x5A\xA5\x5A", 8 ) )
1113 		return( FALSE );
1114 	if( checkNontrivialKey( "abcdefgh", 8 ) )
1115 		return( FALSE );
1116 
1117 	/* Test the hash algorithm-strength code */
1118 	if( isStrongerHash( CRYPT_ALGO_SHA1, CRYPT_ALGO_SHA2 ) || \
1119 		!isStrongerHash( CRYPT_ALGO_SHA2, CRYPT_ALGO_SHA1 ) || \
1120 		isStrongerHash( CRYPT_ALGO_MD5, CRYPT_ALGO_SHA2 ) || \
1121 		!isStrongerHash( CRYPT_ALGO_SHA2, CRYPT_ALGO_MD5 ) )
1122 		return( FALSE );
1123 
1124 	/* Test the checksumming code */
1125 	if( checksumData( "12345678", 8 ) != checksumData( "12345678", 8 ) || \
1126 		checksumData( "12345678", 8 ) == checksumData( "12345778", 8 ) || \
1127 		checksumData( "12345678", 8 ) == checksumData( "12345\xB7" "78", 8 ) || \
1128 		checksumData( "12345678", 8 ) == checksumData( "12345\x00" "78", 8 ) )
1129 		return( FALSE );
1130 
1131 	/* Test the text-line read code */
1132 #if defined( USE_HTTP ) || defined( USE_BASE64 ) || defined( USE_SSH )
1133 	if( !testReadLine( "abcdefgh\n", 9, "abcdefgh", 8, FALSE ) || \
1134 		!testReadLine( "abcdefghijklmnopq\n", 18,
1135 					   "abcdefghijklmnop", 16, FALSE ) || \
1136 		!testReadLine( " abcdefgh\n", 10, "abcdefgh", 8, FALSE ) || \
1137 		!testReadLine( "abcdefgh \n", 10, "abcdefgh", 8, FALSE ) || \
1138 		!testReadLine( " ab cdefgh \n", 12, "ab cdefgh", 9, FALSE ) || \
1139 		!testReadLine( "   ab   cdefgh   \n", 18, "ab cdefgh", 9, FALSE ) )
1140 		return( FALSE );
1141 	if( !testReadLine( "abcdefgh\r\n", 10, "abcdefgh", 8, FALSE ) || \
1142 		!testReadLine( "abcdefgh\r\r\n", 11, "abcdefgh", 8, FALSE ) )
1143 		return( FALSE );
1144 	if( testReadLine( "   \t   \n", 8, "", 1, FALSE ) || \
1145 		testReadLine( "abc\x12" "efgh\n", 9, "", 1, FALSE ) )
1146 		return( FALSE );
1147 	if( !testReadLine( "abcdefgh;\nabc\n", 14,
1148 					   "abcdefgh;", 9, FALSE ) || \
1149 		!testReadLine( "abcdefgh;\nabc\n", 14,
1150 					   "abcdefgh;abc", 12, TRUE ) || \
1151 		!testReadLine( "abcdefgh; \n abc\n", 16,
1152 					   "abcdefgh;abc", 12, TRUE ) || \
1153 		!testReadLine( "abcdefgh ; \n abc\n", 17,
1154 					   "abcdefgh;abc", 12, TRUE ) || \
1155 		!testReadLine( "abcdefgh;abc\nabc\n", 17,
1156 					   "abcdefgh;abc", 12, TRUE ) )
1157 		return( FALSE );
1158 	if( testReadLine( "abcdefgh;\n", 10, "", 1, TRUE ) || \
1159 		testReadLine( "abcdefgh;\n\n", 11, "", 1, TRUE ) || \
1160 		testReadLine( "abcdefgh;\n \n", 12, "", 1, TRUE ) )
1161 		return( FALSE );
1162 #endif /* USE_HTTP || USE_BASE64 || USE_SSH */
1163 
1164 	return( TRUE );
1165 	}
1166 #endif /* !NDEBUG */
1167