1 /****************************************************************************
2 *																			*
3 *				Miscellaneous (Non-ASN.1) Read/Write Routines				*
4 *						Copyright Peter Gutmann 1992-2007					*
5 *																			*
6 ****************************************************************************/
7 
8 #if defined( INC_ALL )
9   #include "crypt.h"
10   #include "bn.h"
11   #include "misc_rw.h"
12 #else
13   #include "crypt.h"
14   #include "bn/bn.h"
15   #include "enc_dec/misc_rw.h"
16 #endif /* Compiler-specific includes */
17 
18 /****************************************************************************
19 *																			*
20 *								Utility Routines							*
21 *																			*
22 ****************************************************************************/
23 
24 /* Read large integer data */
25 
26 typedef enum {
27 	LENGTH_NONE,		/* No length type */
28 	LENGTH_16U,			/* Unsigned int, 16-bit length */
29 	LENGTH_16U_BITS,	/* Unsigned int, 16-bit length, length in bits */
30 	LENGTH_32,			/* Signed int, 32-bit length */
31 	LENGTH_LAST			/* Last possible length type */
32 	} LENGTH_TYPE;
33 
34 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \
readInteger(INOUT STREAM * stream,OUT_BUFFER_OPT (maxLength,* integerLength)void * integer,OUT_LENGTH_BOUNDED_Z (maxLength)int * integerLength,IN_LENGTH_PKC const int minLength,IN_LENGTH_PKC const int maxLength,IN_ENUM (LENGTH)const LENGTH_TYPE lengthType,IN_ENUM_OPT (KEYSIZE_CHECK)const KEYSIZE_CHECK_TYPE checkType)35 static int readInteger( INOUT STREAM *stream,
36 						OUT_BUFFER_OPT( maxLength, \
37 										*integerLength ) void *integer,
38 						OUT_LENGTH_BOUNDED_Z( maxLength ) int *integerLength,
39 						IN_LENGTH_PKC const int minLength,
40 						IN_LENGTH_PKC const int maxLength,
41 						IN_ENUM( LENGTH ) const LENGTH_TYPE lengthType,
42 						IN_ENUM_OPT( KEYSIZE_CHECK ) \
43 							const KEYSIZE_CHECK_TYPE checkType )
44 	{
45 	int length;
46 
47 	assert( isWritePtr( stream, sizeof( STREAM ) ) );
48 	assert( integer == NULL || isWritePtr( integer, maxLength ) );
49 	assert( isWritePtr( integerLength, sizeof( int ) ) );
50 
51 	REQUIRES_S( minLength > 0 && minLength < maxLength && \
52 				maxLength <= CRYPT_MAX_PKCSIZE );
53 	REQUIRES_S( lengthType > LENGTH_NONE && lengthType < LENGTH_LAST );
54 	REQUIRES_S( checkType >= KEYSIZE_CHECK_NONE && \
55 				checkType < KEYSIZE_CHECK_LAST );
56 
57 	/* Clear return values */
58 	if( integer != NULL )
59 		memset( integer, 0, min( 16, maxLength ) );
60 	*integerLength = 0;
61 
62 	/* Read the length and make sure that it's within range, with a 2-byte
63 	   allowance for extra zero-padding (the exact length will be checked
64 	   later after the padding is stripped) */
65 	if( lengthType == LENGTH_16U || lengthType == LENGTH_16U_BITS )
66 		length = readUint16( stream );
67 	else
68 		length = readUint32( stream );
69 	if( cryptStatusError( length ) )
70 		return( length );
71 	if( lengthType == LENGTH_16U_BITS )
72 		length = bitsToBytes( length );
73 	if( checkType != KEYSIZE_CHECK_NONE )
74 		{
75 		REQUIRES( ( checkType == KEYSIZE_CHECK_ECC && \
76 					minLength > bitsToBytes( 176 ) ) || \
77 				  ( checkType != KEYSIZE_CHECK_ECC && \
78 					minLength > bitsToBytes( 256 ) ) );
79 
80 		/* If the length is below the minimum allowed but still looks at
81 		   least vaguely valid, report it as a too-short key rather than a
82 		   bad data error */
83 		if( checkType == KEYSIZE_CHECK_ECC )
84 			{
85 			if( isShortECCKey( length ) )
86 				return( CRYPT_ERROR_NOSECURE );
87 			}
88 		else
89 			{
90 			if( isShortPKCKey( length ) )
91 				return( CRYPT_ERROR_NOSECURE );
92 			}
93 		}
94 	if( length < minLength || length > maxLength + 2 )
95 		return( sSetError( stream, CRYPT_ERROR_BADDATA ) );
96 
97 	/* If we're reading a signed integer then the sign bit can't be set
98 	   since this would produce a negative value.  This differs from the
99 	   ASN.1 code, where the incorrect setting of the sign bit is so common
100 	   that we always treat integers as unsigned */
101 	if( lengthType == LENGTH_32 && ( sPeek( stream ) & 0x80 ) )
102 		return( sSetError( stream, CRYPT_ERROR_BADDATA ) );
103 
104 	/* Skip possible leading-zero padding and repeat the length check once
105 	   the zero-padding has been adjusted */
106 	while( length > 0 && sPeek( stream ) == 0 )
107 		{
108 		int status;
109 
110 		status = sgetc( stream );
111 		if( cryptStatusError( status ) )
112 			return( status );
113 		length--;
114 		}
115 	if( checkType != KEYSIZE_CHECK_NONE )
116 		{
117 		/* Repeat the earlier check on the adjusted value */
118 		if( checkType == KEYSIZE_CHECK_ECC )
119 			{
120 			if( isShortECCKey( length ) )
121 				return( CRYPT_ERROR_NOSECURE );
122 			}
123 		else
124 			{
125 			if( isShortPKCKey( length ) )
126 				return( CRYPT_ERROR_NOSECURE );
127 			}
128 		}
129 	if( length < minLength || length > maxLength )
130 		return( sSetError( stream, CRYPT_ERROR_BADDATA ) );
131 
132 	/* Read the value */
133 	*integerLength = length;
134 	if( integer == NULL )
135 		return( sSkip( stream, length, MAX_INTLENGTH_SHORT ) );
136 	return( sread( stream, integer, length ) );
137 	}
138 
139 /****************************************************************************
140 *																			*
141 *								Data Read Routines							*
142 *																			*
143 ****************************************************************************/
144 
145 /* Read 16- and 32-bit integer values */
146 
147 RETVAL_RANGE( 0, 0xFFFF ) STDC_NONNULL_ARG( ( 1 ) ) \
readUint16(INOUT STREAM * stream)148 int readUint16( INOUT STREAM *stream )
149 	{
150 	BYTE buffer[ UINT16_SIZE + 8 ];
151 	long value;
152 	int status;
153 
154 	assert( isWritePtr( stream, sizeof( STREAM ) ) );
155 
156 	status = sread( stream, buffer, UINT16_SIZE );
157 	if( cryptStatusError( status ) )
158 		return( status );
159 	value = ( ( long ) buffer[ 0 ] << 8 ) | buffer[ 1 ];
160 	if( value < 0 || value > 0xFFFFL || value >= INT_MAX )
161 		{
162 		/* On 16-bit systems, INT_MAX may be less than 0xFFFFL */
163 		return( sSetError( stream, CRYPT_ERROR_BADDATA ) );
164 		}
165 	return( value );
166 	}
167 
168 RETVAL_RANGE( 0, INT_MAX ) STDC_NONNULL_ARG( ( 1 ) ) \
readUint32(INOUT STREAM * stream)169 int readUint32( INOUT STREAM *stream )
170 	{
171 	BYTE buffer[ UINT32_SIZE + 8 ];
172 	long value;
173 	int status;
174 
175 	assert( isWritePtr( stream, sizeof( STREAM ) ) );
176 
177 	status = sread( stream, buffer, UINT32_SIZE );
178 	if( cryptStatusError( status ) )
179 		return( status );
180 	if( buffer[ 0 ] & 0x80 )
181 		return( sSetError( stream, CRYPT_ERROR_BADDATA ) );
182 	value = ( ( long ) buffer[ 0 ] << 24 ) | \
183 			( ( long ) buffer[ 1 ] << 16 ) | \
184 			( ( long ) buffer[ 2 ] << 8 ) | \
185 					   buffer[ 3 ];
186 	if( value < 0 || value >= MAX_INTLENGTH )
187 		return( sSetError( stream, CRYPT_ERROR_BADDATA ) );
188 	return( value );
189 	}
190 
191 /* Read 32-bit time values */
192 
193 RETVAL_RANGE( 0, INT_MAX ) STDC_NONNULL_ARG( ( 1, 2 ) ) \
readUint32Time(INOUT STREAM * stream,OUT time_t * timeVal)194 int readUint32Time( INOUT STREAM *stream, OUT time_t *timeVal )
195 	{
196 	BYTE buffer[ UINT32_SIZE + 8 ];
197 	long value;
198 	int status;
199 
200 	assert( isWritePtr( stream, sizeof( STREAM ) ) );
201 	assert( isWritePtr( timeVal, sizeof( time_t ) ) );
202 
203 	/* Clear return value */
204 	*timeVal = 0;
205 
206 	status = sread( stream, buffer, UINT32_SIZE );
207 	if( cryptStatusError( status ) )
208 		return( status );
209 	if( buffer[ 0 ] & 0x80 )
210 		return( sSetError( stream, CRYPT_ERROR_BADDATA ) );
211 	value = ( ( long ) buffer[ 0 ] << 24 ) | \
212 			( ( long ) buffer[ 1 ] << 16 ) | \
213 			( ( long ) buffer[ 2 ] << 8 ) | \
214 					   buffer[ 3 ];
215 	if( value < MIN_STORED_TIME_VALUE || value >= 0x7FFFFFFFL )
216 		return( sSetError( stream, CRYPT_ERROR_BADDATA ) );
217 	*timeVal = ( time_t ) value;
218 	return( CRYPT_OK );
219 	}
220 
221 #ifndef NDEBUG
222 
223 /* Read 64-bit integer and time values, only used by SFTP so not needed */
224 
225 RETVAL_RANGE( 0, INT_MAX ) STDC_NONNULL_ARG( ( 1 ) ) \
readUint64(INOUT STREAM * stream)226 int readUint64( INOUT STREAM *stream )
227 	{
228 	BYTE buffer[ ( UINT64_SIZE / 2 ) + 8 ];
229 	int status;
230 
231 	assert( isWritePtr( stream, sizeof( STREAM ) ) );
232 
233 	/* This is never a 64-bit value but always an overprovisioned int/long,
234 	   so we verify that the top four bytes are zero and then read it as
235 	   a Uint32 */
236 	status = sread( stream, buffer, UINT64_SIZE / 2 );
237 	if( cryptStatusError( status ) )
238 		return( status );
239 	if( memcmp( buffer, "\x00\x00\x00\x00", UINT64_SIZE / 2 ) )
240 		return( sSetError( stream, CRYPT_ERROR_BADDATA ) );
241 	return( readUint32( stream ) );
242 	}
243 
244 RETVAL_RANGE( 0, INT_MAX ) STDC_NONNULL_ARG( ( 1, 2 ) ) \
readUint64Time(INOUT STREAM * stream,OUT time_t * timeVal)245 int readUint64Time( INOUT STREAM *stream, OUT time_t *timeVal )
246 	{
247 	int value, status;
248 
249 	assert( isWritePtr( stream, sizeof( STREAM ) ) );
250 	assert( isWritePtr( timeVal, sizeof( time_t ) ) );
251 
252 	/* Clear return value */
253 	*timeVal = 0;
254 
255 	status = value = readUint64( stream );
256 	if( cryptStatusError( status ) )
257 		return( status );
258 	if( value < MIN_STORED_TIME_VALUE )
259 		return( sSetError( stream, CRYPT_ERROR_BADDATA ) );
260 	*timeVal = ( time_t ) value;
261 	return( CRYPT_OK );
262 	}
263 #endif /* NDEBUG */
264 
265 /* Read a string preceded by a 32-bit length */
266 
267 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \
readData32(INOUT STREAM * stream,OUT_BUFFER (dataMaxLength,* dataLength)void * data,IN_LENGTH_SHORT const int dataMaxLength,OUT_LENGTH_BOUNDED_Z (dataMaxLength)int * dataLength,const BOOLEAN includeLengthField)268 static int readData32( INOUT STREAM *stream,
269 					   OUT_BUFFER( dataMaxLength, *dataLength ) void *data,
270 					   IN_LENGTH_SHORT const int dataMaxLength,
271 					   OUT_LENGTH_BOUNDED_Z( dataMaxLength ) int *dataLength,
272 					   const BOOLEAN includeLengthField )
273 	{
274 	BYTE *dataPtr = data;
275 	const int headerSize = includeLengthField ? UINT32_SIZE : 0;
276 	int length;
277 
278 	assert( isWritePtr( stream, sizeof( STREAM ) ) );
279 	assert( isWritePtr( data, dataMaxLength ) );
280 	assert( isWritePtr( dataLength, sizeof( int ) ) );
281 
282 	REQUIRES_S( dataMaxLength > 0 && dataMaxLength < MAX_INTLENGTH_SHORT );
283 
284 	/* Clear return values */
285 	memset( data, 0, min( 16, dataMaxLength ) );
286 	*dataLength = 0;
287 
288 	length = readUint32( stream );
289 	if( length <= 0 )
290 		{
291 		/* Error or zero length.  If it's zero length we don't return any
292 		   data */
293 		return( length );
294 		}
295 	if( headerSize + length > dataMaxLength || length > MAX_INTLENGTH_SHORT )
296 		return( sSetError( stream, CRYPT_ERROR_BADDATA ) );
297 	if( includeLengthField )
298 		{
299 		dataPtr[ 0 ] = ( length >> 24 ) & 0xFF;
300 		dataPtr[ 1 ] = ( length >> 16 ) & 0xFF;
301 		dataPtr[ 2 ] = ( length >> 8 ) & 0xFF;
302 		dataPtr[ 3 ] = length & 0xFF;
303 		}
304 	*dataLength = headerSize + length;
305 	return( sread( stream, dataPtr + headerSize, length ) );
306 	}
307 
308 RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \
readString32(INOUT STREAM * stream,OUT_BUFFER (stringMaxLength,* stringLength)void * string,IN_LENGTH_SHORT const int stringMaxLength,OUT_LENGTH_BOUNDED_Z (stringMaxLength)int * stringLength)309 int readString32( INOUT STREAM *stream,
310 				  OUT_BUFFER( stringMaxLength, \
311 							  *stringLength ) void *string,
312 				  IN_LENGTH_SHORT const int stringMaxLength,
313 				  OUT_LENGTH_BOUNDED_Z( stringMaxLength ) int *stringLength )
314 	{
315 	assert( isWritePtr( stream, sizeof( STREAM ) ) );
316 	assert( isWritePtr( string, stringMaxLength ) );
317 	assert( isWritePtr( stringLength, sizeof( int ) ) );
318 
319 	REQUIRES_S( stringMaxLength > 0 && stringMaxLength < MAX_INTLENGTH_SHORT );
320 
321 	/* Read the string, limiting the size to the maximum buffer size */
322 	return( readData32( stream, string, stringMaxLength, stringLength, FALSE ) );
323 	}
324 
325 /* Read a raw object preceded by a 32-bit length */
326 
327 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \
328 int readRawObject32( INOUT STREAM *stream,
329 					 OUT_BUFFER( bufferMaxLength, *bufferLength ) \
330 						void *buffer,
331 					 IN_LENGTH_SHORT_MIN( UINT32_SIZE + 1 ) \
332 						const int bufferMaxLength,
333 					 OUT_LENGTH_BOUNDED_Z( bufferMaxLength ) \
334 						int *bufferLength )
335 	{
336 	assert( isWritePtr( stream, sizeof( STREAM ) ) );
337 	assert( isWritePtr( buffer, bufferMaxLength ) );
338 	assert( isWritePtr( bufferLength, sizeof( int ) ) );
339 
340 	REQUIRES_S( bufferMaxLength >= UINT32_SIZE + 1 && \
341 				bufferMaxLength < MAX_INTLENGTH_SHORT );
342 
343 	/* Read the string, limiting the size to the maximum buffer size */
344 	return( readData32( stream, buffer, bufferMaxLength, bufferLength,
345 						TRUE ) );
346 	}
347 
348 /* Read a universal type and discard it, used to skip unknown or unwanted
349    types.  Since it's only used to skip short no-op fields, we limit the
350    maximum length to MAX_INTLENGTH_SHORT */
351 
352 CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
readUniversal(INOUT STREAM * stream,IN_ENUM (LENGTH)const LENGTH_TYPE lengthType)353 static int readUniversal( INOUT STREAM *stream,
354 						  IN_ENUM( LENGTH ) const LENGTH_TYPE lengthType )
355 	{
356 	int length, status;
357 
358 	assert( isWritePtr( stream, sizeof( STREAM ) ) );
359 
360 	REQUIRES_S( lengthType == LENGTH_16U || lengthType == LENGTH_32 );
361 
362 	/* Read the length and skip the data */
363 	if( lengthType == LENGTH_16U )
364 		status = length = readUint16( stream );
365 	else
366 		status = length = readUint32( stream );
367 	if( cryptStatusError( status ) )
368 		return( status );
369 	if( length <= 0 )
370 		return( CRYPT_OK );		/* Zero-length data */
371 	if( length >= MAX_INTLENGTH_SHORT )
372 		return( CRYPT_ERROR_BADDATA );
373 	return( sSkip( stream, length, MAX_INTLENGTH_SHORT ) );
374 	}
375 
376 RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
readUniversal16(INOUT STREAM * stream)377 int readUniversal16( INOUT STREAM *stream )
378 	{
379 	return( readUniversal( stream, LENGTH_16U ) );
380 	}
381 
382 RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
readUniversal32(INOUT STREAM * stream)383 int readUniversal32( INOUT STREAM *stream )
384 	{
385 	return( readUniversal( stream, LENGTH_32 ) );
386 	}
387 
388 /* Read (large) integers in various formats */
389 
390 RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \
readInteger16U(INOUT STREAM * stream,OUT_BUFFER_OPT (maxLength,* integerLength)void * integer,OUT_LENGTH_BOUNDED_Z (maxLength)int * integerLength,IN_LENGTH_PKC const int minLength,IN_LENGTH_PKC const int maxLength)391 int readInteger16U( INOUT STREAM *stream,
392 					OUT_BUFFER_OPT( maxLength, \
393 									*integerLength ) void *integer,
394 					OUT_LENGTH_BOUNDED_Z( maxLength ) \
395 						int *integerLength,
396 					IN_LENGTH_PKC const int minLength,
397 					IN_LENGTH_PKC const int maxLength )
398 	{
399 	return( readInteger( stream, integer, integerLength, minLength,
400 						 maxLength, LENGTH_16U, KEYSIZE_CHECK_NONE ) );
401 	}
402 
403 RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \
readInteger16Ubits(INOUT STREAM * stream,OUT_BUFFER_OPT (maxLength,* integerLength)void * integer,OUT_LENGTH_BOUNDED_Z (maxLength)int * integerLength,IN_LENGTH_PKC const int minLength,IN_LENGTH_PKC const int maxLength)404 int readInteger16Ubits( INOUT STREAM *stream,
405 						OUT_BUFFER_OPT( maxLength, \
406 										*integerLength ) void *integer,
407 						OUT_LENGTH_BOUNDED_Z( maxLength ) \
408 							int *integerLength,
409 						IN_LENGTH_PKC const int minLength,
410 						IN_LENGTH_PKC const int maxLength )
411 	{
412 	return( readInteger( stream, integer, integerLength, minLength,
413 						 maxLength, LENGTH_16U_BITS, KEYSIZE_CHECK_NONE ) );
414 	}
415 
416 RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \
readInteger32(INOUT STREAM * stream,OUT_BUFFER_OPT (maxLength,* integerLength)void * integer,OUT_LENGTH_BOUNDED_Z (maxLength)int * integerLength,IN_LENGTH_PKC const int minLength,IN_LENGTH_PKC const int maxLength)417 int readInteger32( INOUT STREAM *stream,
418 				   OUT_BUFFER_OPT( maxLength, \
419 								   *integerLength ) void *integer,
420 				   OUT_LENGTH_BOUNDED_Z( maxLength  ) int *integerLength,
421 				   IN_LENGTH_PKC const int minLength,
422 				   IN_LENGTH_PKC const int maxLength )
423 	{
424 	return( readInteger( stream, integer, integerLength, minLength,
425 						 maxLength, LENGTH_32, KEYSIZE_CHECK_NONE ) );
426 	}
427 
428 /* Special-case large integer read routines that explicitly check for a too-
429    short key and return CRYPT_ERROR_NOSECURE rather than the
430    CRYPT_ERROR_BADDATA that'd otherwise be returned */
431 
432 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \
readInteger16UChecked(INOUT STREAM * stream,OUT_BUFFER_OPT (maxLength,* integerLength)void * integer,OUT_LENGTH_BOUNDED_Z (maxLength)int * integerLength,IN_LENGTH_PKC const int minLength,IN_LENGTH_PKC const int maxLength)433 int readInteger16UChecked( INOUT STREAM *stream,
434 						   OUT_BUFFER_OPT( maxLength, *integerLength ) \
435 								void *integer,
436 						   OUT_LENGTH_BOUNDED_Z( maxLength ) \
437 								int *integerLength,
438 						   IN_LENGTH_PKC const int minLength,
439 						   IN_LENGTH_PKC const int maxLength )
440 	{
441 	return( readInteger( stream, integer, integerLength, minLength,
442 						 maxLength, LENGTH_16U, KEYSIZE_CHECK_PKC ) );
443 	}
444 
445 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \
readInteger32Checked(INOUT STREAM * stream,OUT_BUFFER_OPT (maxLength,* integerLength)void * integer,OUT_LENGTH_BOUNDED_Z (maxLength)int * integerLength,IN_LENGTH_PKC const int minLength,IN_LENGTH_PKC const int maxLength)446 int readInteger32Checked( INOUT STREAM *stream,
447 						  OUT_BUFFER_OPT( maxLength, *integerLength ) \
448 								void *integer,
449 						  OUT_LENGTH_BOUNDED_Z( maxLength ) \
450 								int *integerLength,
451 						  IN_LENGTH_PKC const int minLength,
452 						  IN_LENGTH_PKC const int maxLength )
453 	{
454 	/* Perform the appropriate length check for the algorithm type.  The
455 	   way that this is currently done is a bit of a nasty hack, but it
456 	   saves having to create a special-case ECC-only function that's only
457 	   used in one place */
458 	if( minLength == MIN_PKCSIZE_ECCPOINT && \
459 		maxLength == MAX_PKCSIZE_ECCPOINT )
460 		{
461 		return( readInteger( stream, integer, integerLength, minLength,
462 							 maxLength, LENGTH_32, KEYSIZE_CHECK_ECC ) );
463 		}
464 	return( readInteger( stream, integer, integerLength, minLength,
465 						 maxLength, LENGTH_32, KEYSIZE_CHECK_PKC ) );
466 	}
467 
468 #ifdef USE_PKC
469 
470 /* Read integers as bignums in various formats */
471 
472 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
readBignumInteger(INOUT STREAM * stream,INOUT TYPECAST (BIGNUM *)void * bignum,IN_LENGTH_PKC const int minLength,IN_LENGTH_PKC const int maxLength,IN_OPT TYPECAST (BIGNUM *)const void * maxRange,IN_ENUM (LENGTH)const LENGTH_TYPE lengthType,IN_ENUM_OPT (KEYSIZE_CHECK)const KEYSIZE_CHECK_TYPE checkType)473 static int readBignumInteger( INOUT STREAM *stream,
474 							  INOUT TYPECAST( BIGNUM * ) void *bignum,
475 							  IN_LENGTH_PKC const int minLength,
476 							  IN_LENGTH_PKC const int maxLength,
477 							  IN_OPT TYPECAST( BIGNUM * ) const void *maxRange,
478 							  IN_ENUM( LENGTH ) const LENGTH_TYPE lengthType,
479 							  IN_ENUM_OPT( KEYSIZE_CHECK ) \
480 									const KEYSIZE_CHECK_TYPE checkType )
481 	{
482 	BYTE buffer[ CRYPT_MAX_PKCSIZE + 8 ];
483 	int length, status;
484 
485 	assert( isWritePtr( stream, sizeof( STREAM ) ) );
486 	assert( isWritePtr( bignum, sizeof( BIGNUM ) ) );
487 	assert( maxRange == NULL || isReadPtr( maxRange, sizeof( BIGNUM ) ) );
488 
489 	REQUIRES_S( minLength > 0 && minLength < maxLength && \
490 				maxLength <= CRYPT_MAX_PKCSIZE );
491 	REQUIRES_S( lengthType > LENGTH_NONE && lengthType < LENGTH_LAST );
492 	REQUIRES( checkType >= KEYSIZE_CHECK_NONE && \
493 			  checkType < KEYSIZE_CHECK_LAST );
494 
495 	/* Read the integer data */
496 	status = readInteger( stream, buffer, &length, minLength, maxLength,
497 						  lengthType, checkType );
498 	if( cryptStatusError( status ) )
499 		return( status );
500 
501 	/* Convert the value to a bignum.  Note that we use the checkKEYSIZE
502 	   parameter for both readInteger() and importBignum(), since the
503 	   former merely checks the byte count while the latter actually parses
504 	   and processes the bignum */
505 	status = importBignum( bignum, buffer, length, minLength, maxLength,
506 						   maxRange, checkType );
507 	if( cryptStatusError( status ) )
508 		status = sSetError( stream, status );
509 	zeroise( buffer, CRYPT_MAX_PKCSIZE );
510 	return( status );
511 	}
512 
513 RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
readBignumInteger16U(INOUT STREAM * stream,INOUT TYPECAST (BIGNUM *)void * bignum,IN_LENGTH_PKC const int minLength,IN_LENGTH_PKC const int maxLength,IN_OPT TYPECAST (BIGNUM *)const void * maxRange)514 int readBignumInteger16U( INOUT STREAM *stream,
515 						  INOUT TYPECAST( BIGNUM * ) void *bignum,
516 						  IN_LENGTH_PKC const int minLength,
517 						  IN_LENGTH_PKC const int maxLength,
518 						  IN_OPT TYPECAST( BIGNUM * ) const void *maxRange )
519 	{
520 	return( readBignumInteger( stream, bignum, minLength, maxLength,
521 							   maxRange, LENGTH_16U, KEYSIZE_CHECK_NONE ) );
522 	}
523 
524 RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
readBignumInteger16Ubits(INOUT STREAM * stream,INOUT TYPECAST (BIGNUM *)void * bignum,IN_LENGTH_PKC_BITS const int minBits,IN_LENGTH_PKC_BITS const int maxBits,IN_OPT TYPECAST (BIGNUM *)const void * maxRange)525 int readBignumInteger16Ubits( INOUT STREAM *stream,
526 							  INOUT TYPECAST( BIGNUM * ) void *bignum,
527 							  IN_LENGTH_PKC_BITS const int minBits,
528 							  IN_LENGTH_PKC_BITS const int maxBits,
529 							  IN_OPT TYPECAST( BIGNUM * ) const void *maxRange )
530 	{
531 	return( readBignumInteger( stream, bignum, bitsToBytes( minBits ),
532 							   bitsToBytes( maxBits ), maxRange,
533 							   LENGTH_16U_BITS, KEYSIZE_CHECK_NONE ) );
534 	}
535 
536 RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
readBignumInteger32(INOUT STREAM * stream,INOUT TYPECAST (BIGNUM *)void * bignum,IN_LENGTH_PKC const int minLength,IN_LENGTH_PKC const int maxLength,IN_OPT TYPECAST (BIGNUM *)const void * maxRange)537 int readBignumInteger32( INOUT STREAM *stream,
538 						 INOUT TYPECAST( BIGNUM * ) void *bignum,
539 						 IN_LENGTH_PKC const int minLength,
540 						 IN_LENGTH_PKC const int maxLength,
541 						 IN_OPT TYPECAST( BIGNUM * ) const void *maxRange )
542 	{
543 	return( readBignumInteger( stream, bignum, minLength, maxLength,
544 							   maxRange, LENGTH_32, KEYSIZE_CHECK_NONE ) );
545 	}
546 
547 /* Special-case bignum read routines that explicitly check for a too-short
548    key and return CRYPT_ERROR_NOSECURE rather than the CRYPT_ERROR_BADDATA
549    that'd otherwise be returned */
550 
551 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
readBignumInteger16UChecked(INOUT STREAM * stream,INOUT TYPECAST (BIGNUM *)void * bignum,IN_LENGTH_PKC const int minLength,IN_LENGTH_PKC const int maxLength)552 int readBignumInteger16UChecked( INOUT STREAM *stream,
553 								 INOUT TYPECAST( BIGNUM * ) void *bignum,
554 								 IN_LENGTH_PKC const int minLength,
555 								 IN_LENGTH_PKC const int maxLength )
556 	{
557 	return( readBignumInteger( stream, bignum, minLength, maxLength, NULL,
558 							   LENGTH_16U, KEYSIZE_CHECK_PKC ) );
559 	}
560 
561 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
readBignumInteger16UbitsChecked(INOUT STREAM * stream,INOUT TYPECAST (BIGNUM *)void * bignum,IN_LENGTH_PKC_BITS const int minBits,IN_LENGTH_PKC_BITS const int maxBits)562 int readBignumInteger16UbitsChecked( INOUT STREAM *stream,
563 									 INOUT TYPECAST( BIGNUM * ) void *bignum,
564 									 IN_LENGTH_PKC_BITS const int minBits,
565 									 IN_LENGTH_PKC_BITS const int maxBits )
566 	{
567 	return( readBignumInteger( stream, bignum, bitsToBytes( minBits ),
568 							   bitsToBytes( maxBits ), NULL,
569 							   LENGTH_16U_BITS, KEYSIZE_CHECK_PKC ) );
570 	}
571 
572 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
readBignumInteger32Checked(INOUT STREAM * stream,INOUT TYPECAST (BIGNUM *)void * bignum,IN_LENGTH_PKC const int minLength,IN_LENGTH_PKC const int maxLength)573 int readBignumInteger32Checked( INOUT STREAM *stream,
574 								INOUT TYPECAST( BIGNUM * ) void *bignum,
575 								IN_LENGTH_PKC const int minLength,
576 								IN_LENGTH_PKC const int maxLength )
577 	{
578 	return( readBignumInteger( stream, bignum, minLength, maxLength,
579 							   NULL, LENGTH_32, KEYSIZE_CHECK_PKC ) );
580 	}
581 #endif /* USE_PKC */
582 
583 /****************************************************************************
584 *																			*
585 *								Data Write Routines							*
586 *																			*
587 ****************************************************************************/
588 
589 /* Write 16-, 32- and 64-bit integer values */
590 
591 RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
592 int writeUint16( INOUT STREAM *stream,
593 				 IN_RANGE( 0, 0xFFFF ) const int value )
594 	{
595 	assert( isWritePtr( stream, sizeof( STREAM ) ) );
596 
597 	REQUIRES_S( value >= 0 && value <= 0xFFFFL );
598 
599 	sputc( stream, ( value >> 8 ) & 0xFF );
600 	return( sputc( stream, value & 0xFF ) );
601 	}
602 
603 RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
writeUint32(INOUT STREAM * stream,IN_INT_Z const long value)604 int writeUint32( INOUT STREAM *stream, IN_INT_Z const long value )
605 	{
606 	BYTE buffer[ UINT32_SIZE + 8 ];
607 
608 	assert( isWritePtr( stream, sizeof( STREAM ) ) );
609 
610 	REQUIRES_S( value >= 0 && value < MAX_INTLENGTH );
611 
612 	buffer[ 0 ] = ( value >> 24 ) & 0xFF;
613 	buffer[ 1 ] = ( value >> 16 ) & 0xFF;
614 	buffer[ 2 ] = ( value >> 8 ) & 0xFF;
615 	buffer[ 3 ] = value & 0xFF;
616 	return( swrite( stream, buffer, UINT32_SIZE ) );
617 	}
618 
619 RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
writeUint64(INOUT STREAM * stream,IN_INT_Z const long value)620 int writeUint64( INOUT STREAM *stream, IN_INT_Z const long value )
621 	{
622 	assert( isWritePtr( stream, sizeof( STREAM ) ) );
623 
624 	REQUIRES_S( value >= 0 && value < MAX_INTLENGTH );
625 
626 	swrite( stream, "\x00\x00\x00\x00", UINT64_SIZE / 2 );
627 	return( writeUint32( stream, value ) );
628 	}
629 
630 /* Write 32- and 64-bit time values */
631 
632 RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
writeUint32Time(INOUT STREAM * stream,const time_t timeVal)633 int writeUint32Time( INOUT STREAM *stream, const time_t timeVal )
634 	{
635 	REQUIRES_S( timeVal >= MIN_TIME_VALUE );
636 
637 	return( writeUint32( stream, ( int ) timeVal ) );
638 	}
639 
640 RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
writeUint64Time(INOUT STREAM * stream,const time_t timeVal)641 int writeUint64Time( INOUT STREAM *stream, const time_t timeVal )
642 	{
643 	REQUIRES_S( timeVal >= MIN_TIME_VALUE );
644 
645 	return( writeUint64( stream, ( int ) timeVal ) );
646 	}
647 
648 /* Write a string preceded by a 32-bit length */
649 
650 RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
writeString32(INOUT STREAM * stream,IN_BUFFER (stringLength)const void * string,IN_LENGTH_SHORT const int stringLength)651 int writeString32( INOUT STREAM *stream,
652 				   IN_BUFFER( stringLength ) const void *string,
653 				   IN_LENGTH_SHORT const int stringLength )
654 	{
655 	assert( isWritePtr( stream, sizeof( STREAM ) ) );
656 	assert( isReadPtr( string, stringLength ) );
657 
658 	REQUIRES_S( stringLength > 0 && stringLength < MAX_INTLENGTH );
659 
660 	writeUint32( stream, stringLength );
661 	return( swrite( stream, string, stringLength ) );
662 	}
663 
664 /* Write large integers in various formats */
665 
666 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
writeInteger(INOUT STREAM * stream,IN_BUFFER (integerLength)const void * integer,IN_LENGTH_PKC const int integerLength,IN_ENUM (LENGTH)const LENGTH_TYPE lengthType)667 static int writeInteger( INOUT STREAM *stream,
668 						 IN_BUFFER( integerLength ) const void *integer,
669 						 IN_LENGTH_PKC const int integerLength,
670 						 IN_ENUM( LENGTH ) const LENGTH_TYPE lengthType )
671 	{
672 	const BYTE *intPtr = integer;
673 	int length = integerLength;
674 
675 	assert( isWritePtr( stream, sizeof( STREAM ) ) );
676 	assert( isReadPtr( integer, integerLength ) );
677 
678 	REQUIRES_S( integerLength > 0 && integerLength <= CRYPT_MAX_PKCSIZE );
679 	REQUIRES_S( lengthType > LENGTH_NONE && lengthType < LENGTH_LAST );
680 
681 	/* Integers may be passed to us from higher-level code with leading
682 	   zeroes as part of the encoding.  Before we write them out we strip
683 	   out any superfluous leading zeroes that may be present */
684 	while( length > 0 && *intPtr == 0 )
685 		{
686 		/* This is usually a problem since quietly changing the length of a
687 		   low-level internal value before writing it will cause problems
688 		   with higher-level code that doesn't expect to have the data
689 		   length if internal components changed */
690 		assert( DEBUG_WARN );
691 		intPtr++;
692 		length--;
693 		}
694 	ENSURES( length > 0 );
695 
696 	switch( lengthType )
697 		{
698 		case LENGTH_16U:
699 			writeUint16( stream, length );
700 			break;
701 
702 		case LENGTH_16U_BITS:
703 			writeUint16( stream, bytesToBits( length ) );
704 			break;
705 
706 		case LENGTH_32:
707 			{
708 			const BOOLEAN leadingOneBit = *intPtr & 0x80;
709 
710 			writeUint32( stream, length + ( leadingOneBit ? 1 : 0 ) );
711 			if( leadingOneBit )
712 				sputc( stream, 0 );	/* MPIs are signed values */
713 			break;
714 			}
715 
716 		default:
717 			retIntError_Stream( stream );
718 		}
719 	return( swrite( stream, intPtr, length ) );
720 	}
721 
722 RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
writeInteger16U(INOUT STREAM * stream,IN_BUFFER (integerLength)const void * integer,IN_LENGTH_PKC const int integerLength)723 int writeInteger16U( INOUT STREAM *stream,
724 					 IN_BUFFER( integerLength ) const void *integer,
725 					 IN_LENGTH_PKC const int integerLength )
726 	{
727 	return( writeInteger( stream, integer, integerLength, LENGTH_16U ) );
728 	}
729 
730 RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
writeInteger16Ubits(INOUT STREAM * stream,IN_BUFFER (integerLength)const void * integer,IN_LENGTH_PKC const int integerLength)731 int writeInteger16Ubits( INOUT STREAM *stream,
732 						 IN_BUFFER( integerLength ) const void *integer,
733 						 IN_LENGTH_PKC const int integerLength )
734 	{
735 	return( writeInteger( stream, integer, integerLength, LENGTH_16U_BITS ) );
736 	}
737 
738 RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
writeInteger32(INOUT STREAM * stream,IN_BUFFER (integerLength)const void * integer,IN_LENGTH_PKC const int integerLength)739 int writeInteger32( INOUT STREAM *stream,
740 					IN_BUFFER( integerLength ) const void *integer,
741 					IN_LENGTH_PKC const int integerLength )
742 	{
743 	return( writeInteger( stream, integer, integerLength, LENGTH_32 ) );
744 	}
745 
746 #ifdef USE_PKC
747 
748 /* Write integers from bignums in various formats */
749 
CHECK_RETVAL_RANGE(UINT32_SIZE,MAX_INTLENGTH_SHORT)750 CHECK_RETVAL_RANGE( UINT32_SIZE, MAX_INTLENGTH_SHORT ) STDC_NONNULL_ARG( ( 1 ) ) \
751 int sizeofBignumInteger32( const void *bignum )
752 	{
753 	assert( isReadPtr( bignum, sizeof( BIGNUM ) ) );
754 
755 	return( UINT32_SIZE + BN_high_bit( ( BIGNUM * ) bignum ) + \
756 						  BN_num_bytes( bignum ) );
757 	}
758 
759 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
writeBignumInteger(INOUT STREAM * stream,TYPECAST (BIGNUM *)const void * bignum,IN_ENUM (LENGTH)const LENGTH_TYPE lengthType)760 static int writeBignumInteger( INOUT STREAM *stream,
761 							   TYPECAST( BIGNUM * ) const void *bignum,
762 							   IN_ENUM( LENGTH ) const LENGTH_TYPE lengthType )
763 	{
764 	BYTE buffer[ CRYPT_MAX_PKCSIZE + 8 ];
765 	int bnLength, status;
766 
767 	assert( isWritePtr( stream, sizeof( STREAM ) ) );
768 	assert( isReadPtr( bignum, sizeof( BIGNUM ) ) );
769 
770 	REQUIRES_S( lengthType > LENGTH_NONE && lengthType < LENGTH_LAST );
771 
772 	status = exportBignum( buffer, CRYPT_MAX_PKCSIZE, &bnLength, bignum );
773 	ENSURES_S( cryptStatusOK( status ) );
774 	if( lengthType == LENGTH_16U_BITS )
775 		{
776 		const int bitCount = BN_num_bits( bignum );
777 
778 		/* We can't call down to writeInteger() from here because we need to
779 		   write a precise length in bits rather than a value reconstructed
780 		   from the byte count.  This also means that we can't easily
781 		   perform the leading-zero truncation that writeInteger() does
782 		   without a lot of low-level fiddling that duplicates code in
783 		   writeInteger() */
784 		if( cryptStatusError( bitCount ) )
785 			return( bitCount );
786 		writeUint16( stream, bitCount );
787 		status = swrite( stream, buffer, bnLength );
788 		}
789 	else
790 		status = writeInteger( stream, buffer, bnLength, lengthType );
791 	zeroise( buffer, CRYPT_MAX_PKCSIZE );
792 	return( status );
793 	}
794 
795 RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
writeBignumInteger16U(INOUT STREAM * stream,TYPECAST (BIGNUM *)const void * bignum)796 int writeBignumInteger16U( INOUT STREAM *stream,
797 						   TYPECAST( BIGNUM * ) const void *bignum )
798 	{
799 	return( writeBignumInteger( stream, bignum, LENGTH_16U ) );
800 	}
801 
802 RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
writeBignumInteger16Ubits(INOUT STREAM * stream,TYPECAST (BIGNUM *)const void * bignum)803 int writeBignumInteger16Ubits( INOUT STREAM *stream,
804 							   TYPECAST( BIGNUM * ) const void *bignum )
805 	{
806 	return( writeBignumInteger( stream, bignum, LENGTH_16U_BITS ) );
807 	}
808 
809 RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
writeBignumInteger32(INOUT STREAM * stream,TYPECAST (BIGNUM *)const void * bignum)810 int writeBignumInteger32( INOUT STREAM *stream,
811 						  TYPECAST( BIGNUM * ) const void *bignum )
812 	{
813 	return( writeBignumInteger( stream, bignum, LENGTH_32 ) );
814 	}
815 #endif /* USE_PKC */
816