1 /****************************************************************************
2 *																			*
3 *						  Signature Read/Write Routines						*
4 *						Copyright Peter Gutmann 1992-2007					*
5 *																			*
6 ****************************************************************************/
7 
8 #if defined( INC_ALL )
9   #include "asn1.h"
10   #include "asn1_ext.h"
11   #include "misc_rw.h"
12   #include "pgp_rw.h"
13   #include "mech.h"
14 #else
15   #include "enc_dec/asn1.h"
16   #include "enc_dec/asn1_ext.h"
17   #include "enc_dec/misc_rw.h"
18   #include "enc_dec/pgp_rw.h"
19   #include "mechs/mech.h"
20 #endif /* Compiler-specific includes */
21 
22 /* Context-specific tags for the SignerInfo record */
23 
24 enum { CTAG_SI_SKI };
25 
26 /****************************************************************************
27 *																			*
28 *							X.509 Signature Routines						*
29 *																			*
30 ****************************************************************************/
31 
32 #ifdef USE_INT_ASN1
33 
34 /* Read/write raw signatures */
35 
36 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
readRawSignature(INOUT STREAM * stream,OUT QUERY_INFO * queryInfo)37 static int readRawSignature( INOUT STREAM *stream,
38 							 OUT QUERY_INFO *queryInfo )
39 	{
40 	const int startPos = stell( stream );
41 	int status;
42 
43 	assert( isWritePtr( stream, sizeof( STREAM ) ) );
44 	assert( isWritePtr( queryInfo, sizeof( QUERY_INFO ) ) );
45 
46 	REQUIRES( startPos >= 0 && startPos < MAX_BUFFER_SIZE );
47 
48 	/* Clear return value */
49 	memset( queryInfo, 0, sizeof( QUERY_INFO ) );
50 
51 	/* Read the start of the signature */
52 	status = readBitStringHole( stream, &queryInfo->dataLength, 18 + 18,
53 								DEFAULT_TAG );
54 	if( cryptStatusError( status ) )
55 		return( status );
56 	queryInfo->dataStart = stell( stream ) - startPos;
57 
58 	/* Make sure that the remaining signature data is present */
59 	return( sSkip( stream, queryInfo->dataLength, MAX_INTLENGTH_SHORT ) );
60 	}
61 
62 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 6 ) ) \
63 static int writeRawSignature( INOUT STREAM *stream,
64 							  STDC_UNUSED const CRYPT_CONTEXT iSignContext,
65 							  STDC_UNUSED const CRYPT_ALGO_TYPE hashAlgo,
66 							  STDC_UNUSED const int hashParam,
67 							  STDC_UNUSED const CRYPT_ALGO_TYPE signAlgo,
68 							  IN_BUFFER( signatureLength ) const BYTE *signature,
69 							  IN_LENGTH_SHORT_MIN( 40 ) const int signatureLength )
70 	{
71 	assert( isWritePtr( stream, sizeof( STREAM ) ) );
72 	assert( isReadPtr( signature, signatureLength ) );
73 			/* Other parameters aren't used for this format */
74 
75 	REQUIRES( signatureLength >= 40 && \
76 			  signatureLength < MAX_INTLENGTH_SHORT );
77 
78 	/* Write the BIT STRING wrapper and signature */
79 	writeBitStringHole( stream, signatureLength, DEFAULT_TAG );
80 	return( writeRawObject( stream, signature, signatureLength ) );
81 	}
82 
83 /* Read/write X.509 signatures */
84 
85 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
readX509Signature(INOUT STREAM * stream,OUT QUERY_INFO * queryInfo)86 static int readX509Signature( INOUT STREAM *stream,
87 							  OUT QUERY_INFO *queryInfo )
88 	{
89 	const int startPos = stell( stream );
90 	int status;
91 
92 	assert( isWritePtr( stream, sizeof( STREAM ) ) );
93 	assert( isWritePtr( queryInfo, sizeof( QUERY_INFO ) ) );
94 
95 	REQUIRES( startPos >= 0 && startPos < MAX_BUFFER_SIZE );
96 
97 	/* Clear return value */
98 	memset( queryInfo, 0, sizeof( QUERY_INFO ) );
99 
100 	/* Read the signature/hash algorithm information followed by the start
101 	   of the signature */
102 	status = readAlgoIDex( stream, &queryInfo->cryptAlgo,
103 						   &queryInfo->hashAlgo, &queryInfo->hashAlgoParam,
104 						   ALGOID_CLASS_PKCSIG );
105 	if( cryptStatusOK( status ) )
106 		{
107 		status = readBitStringHole( stream, &queryInfo->dataLength, 18 + 18,
108 									DEFAULT_TAG );
109 		}
110 	if( cryptStatusError( status ) )
111 		return( status );
112 	queryInfo->dataStart = stell( stream ) - startPos;
113 
114 	/* Make sure that the remaining signature data is present */
115 	return( sSkip( stream, queryInfo->dataLength, MAX_INTLENGTH_SHORT ) );
116 	}
117 
118 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 6 ) ) \
119 static int writeX509Signature( INOUT STREAM *stream,
120 							   IN_HANDLE const CRYPT_CONTEXT iSignContext,
121 							   IN_ALGO const CRYPT_ALGO_TYPE hashAlgo,
122 							   STDC_UNUSED const int hashParam,
123 							   STDC_UNUSED const CRYPT_ALGO_TYPE signAlgo,
124 							   IN_BUFFER( signatureLength ) const BYTE *signature,
125 							   IN_LENGTH_SHORT_MIN( 40 ) const int signatureLength )
126 	{
127 	assert( isWritePtr( stream, sizeof( STREAM ) ) );
128 	assert( isReadPtr( signature, signatureLength ) );
129 			/* Other parameters aren't used for this format */
130 
131 	REQUIRES( isHandleRangeValid( iSignContext ) );
132 	REQUIRES( isHashAlgo( hashAlgo ) );
133 	REQUIRES( signatureLength >= 40 && \
134 			  signatureLength < MAX_INTLENGTH_SHORT );
135 
136 	/* Write the hash+signature algorithm identifier followed by the BIT
137 	   STRING wrapper and signature */
138 	writeContextAlgoID( stream, iSignContext, hashAlgo );
139 	writeBitStringHole( stream, signatureLength, DEFAULT_TAG );
140 	return( writeRawObject( stream, signature, signatureLength ) );
141 	}
142 #endif /* USE_INT_ASN1 */
143 
144 /****************************************************************************
145 *																			*
146 *							CMS Signature Routines							*
147 *																			*
148 ****************************************************************************/
149 
150 #ifdef USE_INT_CMS
151 
152 /* Read/write PKCS #7/CMS (issuerAndSerialNumber) signatures */
153 
154 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
readCmsSignature(INOUT STREAM * stream,OUT QUERY_INFO * queryInfo)155 static int readCmsSignature( INOUT STREAM *stream,
156 							 OUT QUERY_INFO *queryInfo )
157 	{
158 	const int startPos = stell( stream );
159 	long value, endPos;
160 	int tag, length, status;
161 
162 	assert( isWritePtr( stream, sizeof( STREAM ) ) );
163 	assert( isWritePtr( queryInfo, sizeof( QUERY_INFO ) ) );
164 
165 	REQUIRES( startPos >= 0 && startPos < MAX_BUFFER_SIZE );
166 
167 	/* Clear return value */
168 	memset( queryInfo, 0, sizeof( QUERY_INFO ) );
169 
170 	status = getStreamObjectLength( stream, &length );
171 	if( cryptStatusError( status ) )
172 		return( status );
173 	endPos = startPos + length;
174 
175 	/* Read the header */
176 	readSequence( stream, NULL );
177 	status = readShortInteger( stream, &value );
178 	if( cryptStatusError( status ) )
179 		return( status );
180 	if( value != SIGNATURE_VERSION )
181 		return( CRYPT_ERROR_BADDATA );
182 
183 	/* Read the issuer and serial number and hash algorithm ID.  Since we're
184 	   recording the position of the issuerAndSerialNumber as a blob we have
185 	   to use getStreamObjectLength() to get the overall blob data size */
186 	status = getStreamObjectLength( stream, &length );
187 	if( cryptStatusError( status ) )
188 		return( status );
189 	queryInfo->iAndSStart = stell( stream ) - startPos;
190 	queryInfo->iAndSLength = length;
191 	status = sSkip( stream, length, MAX_INTLENGTH_SHORT );
192 	if( cryptStatusOK( status ) )
193 		{
194 		status = readAlgoIDex( stream, &queryInfo->hashAlgo, NULL,
195 							   &queryInfo->hashAlgoParam,
196 							   ALGOID_CLASS_HASH );
197 		}
198 	if( cryptStatusError( status ) )
199 		return( status );
200 
201 	/* Read the authenticated attributes if there are any present */
202 	if( checkStatusPeekTag( stream, status, tag ) && \
203 		tag == MAKE_CTAG( 0 ) )
204 		{
205 		status = getStreamObjectLength( stream, &length );
206 		if( cryptStatusError( status ) )
207 			return( status );
208 		queryInfo->attributeStart = stell( stream ) - startPos;
209 		queryInfo->attributeLength = length;
210 		status = sSkip( stream, length, MAX_INTLENGTH_SHORT );
211 		}
212 	if( cryptStatusError( status ) )
213 		return( status );
214 
215 	/* Read the CMS/cryptlib signature algorithm and the start of the
216 	   signature.  CMS separates the signature algorithm from the hash
217 	   algorithm so we read it as ALGOID_CLASS_PKC and not
218 	   ALGOID_CLASS_PKCSIG.  Unfortunately some buggy implementations get
219 	   this wrong and write an algorithm+hash algoID, to get around this the
220 	   decoding table contains an alternative interpretation of the
221 	   ALGOID_CLASS_PKCSIG information pretending to be an
222 	   ALGOID_CLASS_PKC.  This broken behaviour was codified in RFC 5652
223 	   (section 10.1.2, "SignatureAlgorithmIdentifier") so it's now part
224 	   of the standard */
225 	status = readAlgoID( stream, &queryInfo->cryptAlgo,
226 						 ALGOID_CLASS_PKC );
227 	if( cryptStatusOK( status ) )
228 		{
229 		status = readOctetStringHole( stream, &queryInfo->dataLength,
230 									  18 + 18, DEFAULT_TAG );
231 		}
232 	if( cryptStatusOK( status ) )
233 		{
234 		queryInfo->dataStart = stell( stream ) - startPos;
235 		status = sSkip( stream, queryInfo->dataLength, MAX_INTLENGTH_SHORT );
236 		}
237 	if( cryptStatusError( status ) )
238 		return( status );
239 
240 	/* Read the unauthenticated attributes if there are any present */
241 	if( stell( stream ) < endPos && \
242 		checkStatusPeekTag( stream, status, tag ) && \
243 		tag == MAKE_CTAG( 1 ) )
244 		{
245 		status = getStreamObjectLength( stream, &length );
246 		if( cryptStatusError( status ) )
247 			return( status );
248 		queryInfo->unauthAttributeStart = stell( stream ) - startPos;
249 		queryInfo->unauthAttributeLength = length;
250 		status = sSkip( stream, length, MAX_INTLENGTH_SHORT );
251 		}
252 
253 	return( cryptStatusError( status ) ? status : CRYPT_OK );
254 	}		/* checkStatusPeekTag() can return tag as status */
255 
256 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 6 ) ) \
257 static int writeCmsSignature( INOUT STREAM *stream,
258 							  IN_HANDLE const CRYPT_CONTEXT iSignContext,
259 							  STDC_UNUSED const CRYPT_ALGO_TYPE hashAlgo,
260 							  STDC_UNUSED const int hashParam,
261 							  STDC_UNUSED const CRYPT_ALGO_TYPE signAlgo,
262 							  IN_BUFFER( signatureLength ) const BYTE *signature,
263 							  IN_LENGTH_SHORT_MIN( 40 ) const int signatureLength )
264 	{
265 	assert( isWritePtr( stream, sizeof( STREAM ) ) );
266 	assert( isReadPtr( signature, signatureLength ) );
267 			/* Other parameters aren't used for this format */
268 
269 	REQUIRES( isHandleRangeValid( iSignContext ) );
270 	REQUIRES( signatureLength >= 40 && \
271 			  signatureLength < MAX_INTLENGTH_SHORT );
272 
273 	/* Write the signature algorithm identifier and signature data.  The
274 	   handling of CMS signatures is non-orthogonal to readCmsSignature()
275 	   because creating a CMS signature involves adding assorted additional
276 	   data like iAndS and signed attributes that present too much
277 	   information to pass into a basic writeSignature() call */
278 	writeContextAlgoID( stream, iSignContext, CRYPT_ALGO_NONE );
279 	return( writeOctetString( stream, signature, signatureLength, DEFAULT_TAG ) );
280 	}
281 
282 /* Read/write cryptlib/CMS (keyID) signatures */
283 
284 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
readCryptlibSignature(INOUT STREAM * stream,OUT QUERY_INFO * queryInfo)285 static int readCryptlibSignature( INOUT STREAM *stream,
286 								  OUT QUERY_INFO *queryInfo )
287 	{
288 	const int startPos = stell( stream );
289 	long value;
290 	int status;
291 
292 	assert( isWritePtr( stream, sizeof( STREAM ) ) );
293 	assert( isWritePtr( queryInfo, sizeof( QUERY_INFO ) ) );
294 
295 	REQUIRES( startPos >= 0 && startPos < MAX_BUFFER_SIZE );
296 
297 	/* Clear return value */
298 	memset( queryInfo, 0, sizeof( QUERY_INFO ) );
299 
300 	/* Read the header */
301 	readSequence( stream, NULL );
302 	status = readShortInteger( stream, &value );
303 	if( cryptStatusError( status ) )
304 		return( status );
305 	if( value != SIGNATURE_EX_VERSION )
306 		return( CRYPT_ERROR_BADDATA );
307 
308 	/* Read the key ID and hash algorithm identifier */
309 	status = readOctetStringTag( stream, queryInfo->keyID,
310 								 &queryInfo->keyIDlength, 8,
311 								 CRYPT_MAX_HASHSIZE, CTAG_SI_SKI );
312 	if( cryptStatusOK( status ) )
313 		{
314 		status = readAlgoIDex( stream, &queryInfo->hashAlgo, NULL,
315 							   &queryInfo->hashAlgoParam,
316 							   ALGOID_CLASS_HASH );
317 		}
318 	if( cryptStatusError( status ) )
319 		return( status );
320 
321 	/* Read the CMS/cryptlib signature algorithm and the start of the
322 	   signature.  CMS separates the signature algorithm from the hash
323 	   algorithm so we we use ALGOID_CLASS_PKC rather than
324 	   ALGOID_CLASS_PKCSIG */
325 	status = readAlgoID( stream, &queryInfo->cryptAlgo, ALGOID_CLASS_PKC );
326 	if( cryptStatusOK( status ) )
327 		{
328 		status = readOctetStringHole( stream, &queryInfo->dataLength,
329 									  18 + 18, DEFAULT_TAG );
330 		}
331 	if( cryptStatusError( status ) )
332 		return( status );
333 	queryInfo->dataStart = stell( stream ) - startPos;
334 
335 	/* Make sure that the remaining signature data is present */
336 	return( sSkip( stream, queryInfo->dataLength, MAX_INTLENGTH_SHORT ) );
337 	}
338 
339 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 6 ) ) \
340 static int writeCryptlibSignature( INOUT STREAM *stream,
341 								   IN_HANDLE const CRYPT_CONTEXT iSignContext,
342 								   IN_ALGO const CRYPT_ALGO_TYPE hashAlgo,
343 								   STDC_UNUSED const int hashParam,
344 								   STDC_UNUSED const CRYPT_ALGO_TYPE signAlgo,
345 								   IN_BUFFER( signatureLength ) \
346 									const BYTE *signature,
347 								   IN_LENGTH_SHORT_MIN( 40 ) \
348 									const int signatureLength )
349 	{
350 	BYTE keyID[ 128 + 8 ];
351 	const int signAlgoIdSize = \
352 				sizeofContextAlgoID( iSignContext, CRYPT_ALGO_NONE );
353 	const int hashAlgoIdSize = sizeofAlgoID( hashAlgo );
354 	int keyIDlength, status;
355 
356 	assert( isWritePtr( stream, sizeof( STREAM ) ) );
357 	assert( isReadPtr( signature, signatureLength ) );
358 			/* Other parameters aren't used for this format */
359 
360 	REQUIRES( isHandleRangeValid( iSignContext ) );
361 	REQUIRES( isHashAlgo( hashAlgo ) );
362 	REQUIRES( signatureLength >= 40 && \
363 			  signatureLength < MAX_INTLENGTH_SHORT );
364 
365 	if( cryptStatusError( signAlgoIdSize ) )
366 		return( signAlgoIdSize );
367 	if( cryptStatusError( hashAlgoIdSize ) )
368 		return( hashAlgoIdSize );
369 
370 	/* Get the key ID */
371 	status = getCmsKeyIdentifier( iSignContext, keyID, 128, &keyIDlength );
372 	if( cryptStatusError( status ) )
373 		return( status );
374 
375 	/* Write the header */
376 	writeSequence( stream, sizeofShortInteger( SIGNATURE_EX_VERSION ) + \
377 				   sizeofObject( keyIDlength ) + \
378 				   signAlgoIdSize + hashAlgoIdSize + \
379 				   sizeofObject( signatureLength ) );
380 
381 	/* Write the version, key ID and algorithm identifier */
382 	writeShortInteger( stream, SIGNATURE_EX_VERSION, DEFAULT_TAG );
383 	writeOctetString( stream, keyID, keyIDlength, CTAG_SI_SKI );
384 	writeAlgoID( stream, hashAlgo );
385 	writeContextAlgoID( stream, iSignContext, CRYPT_ALGO_NONE );
386 	return( writeOctetString( stream, signature, signatureLength, DEFAULT_TAG ) );
387 	}
388 #endif /* USE_INT_CMS */
389 
390 /****************************************************************************
391 *																			*
392 *							PGP Signature Routines							*
393 *																			*
394 ****************************************************************************/
395 
396 #ifdef USE_PGP
397 
398 /* Read a PGP type-and-value packet and check whether it's one of ours */
399 
400 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
readTypeAndValue(INOUT STREAM * stream,INOUT QUERY_INFO * queryInfo,IN_LENGTH_Z const int startPos)401 static int readTypeAndValue( INOUT STREAM *stream,
402 							 INOUT QUERY_INFO *queryInfo,
403 							 IN_LENGTH_Z const int startPos )
404 	{
405 	BYTE nameBuffer[ 32 + 8 ];
406 	static const char FAR_BSS *nameString = "issuerAndSerialNumber";
407 	int nameLength, valueLength, status;	/* length = 21 */
408 
409 	assert( isWritePtr( stream, sizeof( STREAM ) ) );
410 	assert( isWritePtr( queryInfo, sizeof( QUERY_INFO ) ) );
411 
412 	REQUIRES( startPos >= 0 && startPos < MAX_BUFFER_SIZE );
413 	REQUIRES( startPos < stell( stream ) );
414 
415 	/* Skip the flags */
416 	status = sSkip( stream, UINT32_SIZE, UINT32_SIZE );
417 	if( cryptStatusError( status ) )
418 		return( status );
419 
420 	/* Read the attribute length information and make sure that it looks
421 	   valid */
422 	nameLength = readUint16( stream );
423 	status = valueLength = readUint16( stream );
424 	if( cryptStatusError( status ) )
425 		return( status );
426 	if( nameLength < 1 || nameLength > 255 || \
427 		valueLength < 1 || valueLength >= MAX_INTLENGTH_SHORT )
428 		{
429 		/* The RFC is, as usual, silent on what's a sane size for a type-
430 		   and-value pair, so we define our own, hopefully sensible,
431 		   limits */
432 		return( CRYPT_ERROR_BADDATA );
433 		}
434 	if( nameLength != 21 || valueLength < 16 || valueLength > 2048 )
435 		{
436 		/* This is a somewhat different check to the above one in that out-
437 		   of-range (but plausible) sizes are skipped rather than being
438 		   counted as an error */
439 		return( sSkip( stream, nameLength + valueLength,
440 					   MAX_INTLENGTH_SHORT ) );
441 		}
442 
443 	/* Read the name and check whether it's one that we recognise */
444 	status = sread( stream, nameBuffer, nameLength );
445 	if( cryptStatusError( status ) )
446 		return( status );
447 	if( !memcmp( nameBuffer, nameString, nameLength ) )
448 		{
449 		/* It's an issuerAndSerialNumber, remember it for later */
450 		queryInfo->iAndSStart = stell( stream ) - startPos;
451 		queryInfo->iAndSLength = valueLength;
452 		}
453 	return( sSkip( stream, valueLength, MAX_INTLENGTH_SHORT ) );
454 	}
455 
456 /* Read signature subpackets.  In theory we could do something with the
457    isAuthenticated flag but at the moment we don't rely on any attributes
458    that require authentication.  The most that an attacker can do by
459    changing the keyID/iAndS field is cause the signature check to fail,
460    which they can do just as easily by flipping a bit */
461 
462 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
readSignatureSubpackets(INOUT STREAM * stream,INOUT QUERY_INFO * queryInfo,IN_LENGTH_SHORT const int length,IN_DATALENGTH const int startPos,const BOOLEAN isAuthenticated)463 static int readSignatureSubpackets( INOUT STREAM *stream,
464 									INOUT QUERY_INFO *queryInfo,
465 									IN_LENGTH_SHORT const int length,
466 									IN_DATALENGTH const int startPos,
467 									const BOOLEAN isAuthenticated )
468 	{
469 	BOOLEAN seenTimestamp = FALSE;
470 	const int endPos = stell( stream ) + length;
471 	int noSubpackets;
472 
473 	assert( isWritePtr( stream, sizeof( STREAM ) ) );
474 	assert( isWritePtr( queryInfo, sizeof( QUERY_INFO ) ) );
475 
476 	REQUIRES( length > 0 && length < MAX_INTLENGTH_SHORT );
477 	REQUIRES( startPos >= 0 && startPos < MAX_BUFFER_SIZE );
478 	REQUIRES( startPos < stell( stream ) );
479 	REQUIRES( endPos > 0 && endPos < MAX_BUFFER_SIZE );
480 
481 	for( noSubpackets = 0;
482 		 stell( stream ) < endPos && \
483 			noSubpackets < FAILSAFE_ITERATIONS_MED;
484 		 noSubpackets++ )
485 		{
486 		int subpacketLength, type DUMMY_INIT, status;
487 
488 		/* Read the subpacket length and type */
489 		status = pgpReadShortLength( stream, &subpacketLength,
490 									 PGP_CTB_OPENPGP );
491 		if( cryptStatusOK( status ) && subpacketLength < 1 )
492 			{
493 			/* We must have at least a packet-type indicator present */
494 			status = CRYPT_ERROR_BADDATA;
495 			}
496 		if( cryptStatusOK( status ) )
497 			status = type = sgetc( stream );
498 		if( cryptStatusError( status ) )
499 			return( status );
500 
501 		/* If it's an unrecognised subpacket with the critical flag set,
502 		   reject the signature.  The range check isn't complete since there
503 		   are a few holes in the range, but since the holes presumably exist
504 		   because of deprecated subpacket types any new packets will be
505 		   added at the end so it's safe to use */
506 		if( ( type & 0x80 ) && ( ( type & 0x7F ) > PGP_SUBPACKET_LAST ) )
507 			return( CRYPT_ERROR_NOTAVAIL );
508 
509 		switch( type )
510 			{
511 			case PGP_SUBPACKET_TIME:
512 				status = sSkip( stream, UINT32_SIZE, UINT32_SIZE );
513 
514 				/* Remember that we've seen the (mandatory) timestamp
515 				   packet */
516 				seenTimestamp = TRUE;
517 				break;
518 
519 			case PGP_SUBPACKET_KEYID:
520 				/* Make sure that the length is valid */
521 				if( subpacketLength != PGP_KEYID_SIZE + 1 )
522 					return( CRYPT_ERROR_BADDATA );
523 
524 				/* If it's a key ID and we haven't already set this from a
525 				   preceding one-pass signature packet (which can happen
526 				   with detached sigs), set it now */
527 				if( queryInfo->keyIDlength <= 0 )
528 					{
529 					status = sread( stream, queryInfo->keyID, PGP_KEYID_SIZE );
530 					queryInfo->keyIDlength = PGP_KEYID_SIZE;
531 					}
532 				else
533 					{
534 					/* We've already got the ID, skip it and continue.  The
535 					   -1 is for the packet type, which we've already read */
536 					status = sSkip( stream, subpacketLength - 1,
537 									MAX_INTLENGTH_SHORT );
538 					}
539 				break;
540 
541 			case PGP_SUBPACKET_TYPEANDVALUE:
542 				/* It's a type-and-value packet, check whether it's one of
543 				   ours */
544 				status = readTypeAndValue( stream, queryInfo, startPos );
545 				break;
546 
547 			default:
548 				/* It's something else, skip it and continue.  The -1 is for
549 				   the packet type, which we've already read */
550 				if( subpacketLength > 1 )
551 					{
552 					status = sSkip( stream, subpacketLength - 1,
553 									MAX_INTLENGTH_SHORT );
554 					}
555 			}
556 		if( cryptStatusError( status ) )
557 			return( status );
558 		}
559 	if( noSubpackets >= FAILSAFE_ITERATIONS_MED )
560 		{
561 		/* If we've found this many packets in a row all supposedly
562 		   belonging to the same signature then there's something wrong */
563 		DEBUG_DIAG(( "Encountered more than %d subpackets for a single "
564 					 "signature", noSubpackets ));
565 		assert_nofuzz( DEBUG_WARN );
566 		return( CRYPT_ERROR_BADDATA );
567 		}
568 
569 	/* Make sure that the mandatory fields are present in the subpacket
570 	   data.  We also need to check for the presence of the keyID but this
571 	   can be in either the authenticated or unauthenticated attributes, so
572 	   it has to be checked by the calling function */
573 	if( isAuthenticated && !seenTimestamp )
574 		return( CRYPT_ERROR_INVALID );
575 
576 	return( CRYPT_OK );
577 	}
578 
579 /* Signature info:
580 
581 	byte	ctb = PGP_PACKET_SIGNATURE_ONEPASS
582 	byte[]	length
583 	byte	version = 3 (= OpenPGP, not the expected PGP3)
584 	byte	sigType
585 	byte	hashAlgo
586 	byte	sigAlgo
587 	byte[8]	keyID
588 	byte	1 */
589 
590 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
readPgpOnepassSigPacket(INOUT STREAM * stream,INOUT QUERY_INFO * queryInfo)591 int readPgpOnepassSigPacket( INOUT STREAM *stream,
592 							 INOUT QUERY_INFO *queryInfo )
593 	{
594 	int status;
595 
596 	assert( isWritePtr( stream, sizeof( STREAM ) ) );
597 	assert( isWritePtr( queryInfo, sizeof( QUERY_INFO ) ) );
598 
599 	/* Make sure that the packet header is in order and check the packet
600 	   version.  This is an OpenPGP-only packet */
601 	status = getPgpPacketInfo( stream, queryInfo );
602 	if( cryptStatusError( status ) )
603 		return( status );
604 	if( sgetc( stream ) != 3 )
605 		return( CRYPT_ERROR_BADDATA );
606 	queryInfo->version = PGP_VERSION_OPENPGP;
607 
608 	/* Skip the sig.type and get the hash algorithm and signature
609 	   algorithms */
610 	status = sgetc( stream );	/* Skip signature type */
611 	if( !cryptStatusError( status ) )
612 		{
613 		status = readPgpAlgo( stream, &queryInfo->hashAlgo,
614 							  &queryInfo->hashAlgoParam,
615 							  PGP_ALGOCLASS_HASH );
616 		}
617 	if( cryptStatusOK( status ) )
618 		{
619 		status = readPgpAlgo( stream, &queryInfo->cryptAlgo,
620 							  &queryInfo->cryptAlgoParam,
621 							  PGP_ALGOCLASS_SIGN );
622 		}
623 	if( cryptStatusError( status ) )
624 		return( status );
625 	queryInfo->type = CRYPT_OBJECT_SIGNATURE;
626 
627 	/* Get the PGP key ID and make sure that this isn't a nested signature */
628 	status = sread( stream, queryInfo->keyID, PGP_KEYID_SIZE );
629 	if( cryptStatusError( status ) )
630 		return( status );
631 	queryInfo->keyIDlength = PGP_KEYID_SIZE;
632 	return( ( sgetc( stream ) != 1 ) ? CRYPT_ERROR_BADDATA : CRYPT_OK );
633 	}
634 
635 /* Read/write PGP signatures.
636 
637 		byte	ctb = PGP_PACKET_SIGNATURE
638 		byte[]	length
639 	v3:	byte	version = PGP_2,3	v4: byte	version = PGP_VERSION_OPENPGP
640 		byte	infoLen = 5				byte	sigType
641 			byte	sigType				byte	sigAlgo
642 			byte[4]	sig.time			byte	hashAlgo
643 		byte[8]	keyID					uint16	length of auth.attributes
644 		byte	sigAlgo					byte[]	authenticated attributes
645 		byte	hashAlgo				uint16	length of unauth.attributes
646 		byte[2]	hash check				byte[]	unauthenticated attributes
647 		mpi(s)	signature							-- Contains keyID
648 										byte[2]	hash check
649 										mpi(s)	signature */
650 
651 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
readPgp2SigInfo(INOUT STREAM * stream,INOUT QUERY_INFO * queryInfo,IN_DATALENGTH_Z const int startPos)652 static int readPgp2SigInfo( INOUT STREAM *stream,
653 							INOUT QUERY_INFO *queryInfo,
654 							IN_DATALENGTH_Z const int startPos )
655 	{
656 	int value, status;
657 
658 	assert( isWritePtr( stream, sizeof( STREAM ) ) );
659 	assert( isWritePtr( queryInfo, sizeof( QUERY_INFO ) ) );
660 
661 	REQUIRES( startPos >= 0 && startPos < MAX_BUFFER_SIZE );
662 	REQUIRES( startPos < stell( stream ) );
663 
664 	/* Read PGP 2.x additional signature information */
665 	status = value = sgetc( stream );
666 	if( cryptStatusError( status ) )
667 		return( status );
668 	if( value != 5 )
669 		return( CRYPT_ERROR_BADDATA );
670 	queryInfo->attributeStart = stell( stream ) - startPos;
671 	queryInfo->attributeLength = 5;
672 	status = sSkip( stream, 5, 5 );
673 	if( cryptStatusError( status ) )
674 		return( status );
675 
676 	/* Read the signer keyID and signature and hash algorithms */
677 	status = sread( stream, queryInfo->keyID, PGP_KEYID_SIZE );
678 	if( cryptStatusError( status ) )
679 		return( status );
680 	queryInfo->keyIDlength = PGP_KEYID_SIZE;
681 	status = readPgpAlgo( stream, &queryInfo->cryptAlgo,
682 						  &queryInfo->cryptAlgoParam, PGP_ALGOCLASS_SIGN );
683 	if( cryptStatusOK( status ) )
684 		{
685 		status = readPgpAlgo( stream, &queryInfo->hashAlgo,
686 							  &queryInfo->hashAlgoParam,
687 							  PGP_ALGOCLASS_HASH );
688 		}
689 	return( status );
690 	}
691 
692 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
readOpenPgpSigInfo(INOUT STREAM * stream,INOUT QUERY_INFO * queryInfo,IN_DATALENGTH_Z const int startPos)693 static int readOpenPgpSigInfo( INOUT STREAM *stream,
694 							   INOUT QUERY_INFO *queryInfo,
695 							   IN_DATALENGTH_Z const int startPos )
696 	{
697 	int length, status;
698 
699 	assert( isWritePtr( stream, sizeof( STREAM ) ) );
700 	assert( isWritePtr( queryInfo, sizeof( QUERY_INFO ) ) );
701 
702 	REQUIRES( startPos >= 0 && startPos < MAX_BUFFER_SIZE );
703 	REQUIRES( startPos < stell( stream ) );
704 
705 	/* Remember the extra data to be hashed and read the signature and hash
706 	   algorithms.  Since the extra data starts at the version byte that
707 	   we've already read, we add a -1 offset to the start position, as well
708 	   as including it in the overall length calculation */
709 	queryInfo->attributeStart = ( stell( stream ) - 1 ) - startPos;
710 	queryInfo->attributeLength = PGP_VERSION_SIZE + 1 + \
711 								 PGP_ALGOID_SIZE + PGP_ALGOID_SIZE;
712 	status = sgetc( stream );	/* Skip signature type */
713 	if( !cryptStatusError( status ) )
714 		{
715 		status = readPgpAlgo( stream, &queryInfo->cryptAlgo,
716 							  &queryInfo->cryptAlgoParam,
717 							  PGP_ALGOCLASS_SIGN );
718 		}
719 	if( cryptStatusOK( status ) )
720 		{
721 		status = readPgpAlgo( stream, &queryInfo->hashAlgo,
722 							  &queryInfo->hashAlgoParam,
723 							  PGP_ALGOCLASS_HASH );
724 		}
725 	if( cryptStatusError( status ) )
726 		return( status );
727 
728 	/* Process the authenticated attributes */
729 	status = length = readUint16( stream );
730 	if( cryptStatusError( status ) )
731 		return( status );
732 	if( length < 0 || length > 2048 )
733 		return( CRYPT_ERROR_BADDATA );
734 	queryInfo->attributeLength += UINT16_SIZE + length;
735 	if( length > 0 )
736 		{
737 		status = readSignatureSubpackets( stream, queryInfo, length,
738 										  startPos, TRUE );
739 		if( cryptStatusError( status ) )
740 			return( status );
741 		}
742 
743 	/* Process the unauthenticated attributes */
744 	queryInfo->unauthAttributeStart = stell( stream ) - startPos;
745 	status = length = readUint16( stream );
746 	if( cryptStatusError( status ) )
747 		return( status );
748 	if( length < 0 || length > 2048 )
749 		return( CRYPT_ERROR_BADDATA );
750 	queryInfo->unauthAttributeLength = UINT16_SIZE + length;
751 	if( length > 0 )
752 		{
753 		status = readSignatureSubpackets( stream, queryInfo, length,
754 										  startPos, FALSE );
755 		if( cryptStatusError( status ) )
756 			return( status );
757 		}
758 
759 	/* Check the the presence of required attributes.  The mandatory ones
760 	   per the RFC are checked when the authenticated attributes are being
761 	   read, however the keyID, which is required to check the signature,
762 	   can be present in either the authenticated or unauthenticated
763 	   attributes depending on the mood of the implementer, so we have to
764 	   check for it outside the attribute-read code */
765 	if( queryInfo->keyIDlength <= 0 )
766 		return( CRYPT_ERROR_INVALID );
767 
768 	return( CRYPT_OK );
769 	}
770 
771 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
readPgpSignature(INOUT STREAM * stream,OUT QUERY_INFO * queryInfo)772 static int readPgpSignature( INOUT STREAM *stream,
773 							 OUT QUERY_INFO *queryInfo )
774 	{
775 	const int startPos = stell( stream );
776 	int value, status;
777 
778 	assert( isWritePtr( stream, sizeof( STREAM ) ) );
779 	assert( isWritePtr( queryInfo, sizeof( QUERY_INFO ) ) );
780 
781 	REQUIRES( startPos >= 0 && startPos < MAX_BUFFER_SIZE );
782 
783 	/* Clear return value */
784 	memset( queryInfo, 0, sizeof( QUERY_INFO ) );
785 
786 	/* Make sure that the packet header is in order and check the packet
787 	   version.  For this packet type a version number of 3 denotes PGP 2.x
788 	   whereas for key transport it denotes OpenPGP */
789 	status = getPgpPacketInfo( stream, queryInfo );
790 	if( cryptStatusError( status ) )
791 		return( status );
792 	status = value = sgetc( stream );
793 	if( cryptStatusError( status ) )
794 		return( status );
795 	if( value != PGP_VERSION_2 && value != PGP_VERSION_3 && \
796 		value != PGP_VERSION_OPENPGP )
797 		return( CRYPT_ERROR_BADDATA );
798 	queryInfo->type = CRYPT_OBJECT_SIGNATURE;
799 	queryInfo->version = ( value == PGP_VERSION_OPENPGP ) ? \
800 						 PGP_VERSION_OPENPGP : PGP_VERSION_2;
801 
802 	/* Read the signing attributes and skip the hash check */
803 	if( value != PGP_VERSION_OPENPGP )
804 		status = readPgp2SigInfo( stream, queryInfo, startPos );
805 	else
806 		status = readOpenPgpSigInfo( stream, queryInfo, startPos );
807 	if( cryptStatusOK( status ) )
808 		status = sSkip( stream, 2, 2 );
809 	if( cryptStatusError( status ) )
810 		return( status );
811 
812 	/* Read the signature, recording the position and length of the raw RSA
813 	   signature data.  We have to be careful how we handle this because
814 	   readInteger16Ubits() returns the canonicalised form of the values
815 	   (with leading zeroes truncated) so an stell() before the read doesn't
816 	   necessarily represent the start of the payload:
817 
818 		startPos	dataStart		 stell()
819 			|			|				|
820 			v			v <-- length -->v
821 		+---+-----------+---------------+
822 		|	|			|///////////////| Stream
823 		+---+-----------+---------------+ */
824 	if( queryInfo->cryptAlgo == CRYPT_ALGO_RSA )
825 		{
826 		status = readInteger16Ubits( stream, NULL, &queryInfo->dataLength,
827 									 MIN_PKCSIZE, CRYPT_MAX_PKCSIZE );
828 		if( cryptStatusError( status ) )
829 			return( status );
830 		queryInfo->dataStart = ( stell( stream ) - startPos ) - \
831 							   queryInfo->dataLength;
832 		}
833 	else
834 		{
835 		const int dataStartPos = stell( stream );
836 		int dummy;
837 
838 		REQUIRES( dataStartPos >= 0 && dataStartPos < MAX_BUFFER_SIZE );
839 		REQUIRES( queryInfo->cryptAlgo == CRYPT_ALGO_DSA );
840 
841 		/* Read the DSA signature, recording the position and combined
842 		   lengths of the MPI pair.  Again, we can't use the length returned
843 		   by readInteger16Ubits() to determine the overall size but have to
844 		   calculate it from the position in the stream */
845 		status = readInteger16Ubits( stream, NULL, &dummy, 16, 20 );
846 		if( cryptStatusOK( status ) )
847 			status = readInteger16Ubits( stream, NULL, &dummy, 16, 20 );
848 		if( cryptStatusError( status ) )
849 			return( status );
850 		queryInfo->dataStart = dataStartPos - startPos;
851 		queryInfo->dataLength = stell( stream ) - dataStartPos;
852 		}
853 
854 	/* Make sure that we've read the entire object.  This check is necessary
855 	   to detect corrupted length values, which can result in reading past
856 	   the end of the object */
857 	if( ( stell( stream ) - startPos ) != queryInfo->size )
858 		return( CRYPT_ERROR_BADDATA );
859 
860 	return( CRYPT_OK );
861 	}
862 
863 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 6 ) ) \
864 static int writePgpSignature( INOUT STREAM *stream,
865 							  STDC_UNUSED const CRYPT_CONTEXT iSignContext,
866 							  STDC_UNUSED const CRYPT_ALGO_TYPE hashAlgo,
867 							  STDC_UNUSED const int hashParam,
868 							  IN_ALGO const CRYPT_ALGO_TYPE signAlgo,
869 							  IN_BUFFER( signatureLength ) const BYTE *signature,
870 							  IN_LENGTH_SHORT_MIN( 18 + 18 + 1 ) \
871 								const int signatureLength )
872 	{
873 	assert( isWritePtr( stream, sizeof( STREAM ) ) );
874 	assert( isReadPtr( signature, signatureLength ) );
875 			/* Other parameters aren't used for this format */
876 
877 	REQUIRES( isPkcAlgo( signAlgo ) );
878 	REQUIRES( signatureLength > ( 18 + 18 ) && \
879 			  signatureLength < MAX_INTLENGTH_SHORT );
880 
881 	/* If it's a DLP/ECDLP algorithm then we've already specified the low-
882 	   level signature routines' output format as PGP so there's no need for
883 	   further processing.  The handling of PGP signatures is non-orthogonal
884 	   to readPgpSignature() because creating a PGP signature involves
885 	   adding assorted additional data like key IDs and authenticated
886 	   attributes, which present too much information to pass into a basic
887 	   writeSignature() call */
888 	if( isDlpAlgo( signAlgo ) || isEccAlgo( signAlgo ) )
889 		return( swrite( stream, signature, signatureLength ) );
890 
891 	/* Write the signature as a PGP MPI */
892 	return( writeInteger16Ubits( stream, signature, signatureLength ) );
893 	}
894 #endif /* USE_PGP */
895 
896 /****************************************************************************
897 *																			*
898 *						Miscellaneous Signature Routines					*
899 *																			*
900 ****************************************************************************/
901 
902 #ifdef USE_SSH
903 
904 /* Read/write SSH signatures.  SSH signature data is treated as a blob
905    encoded as an SSH string rather than properly-formatted data so we don't
906    encode/decode it as SSH MPIs */
907 
908 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
readSshSignature(INOUT STREAM * stream,OUT QUERY_INFO * queryInfo)909 static int readSshSignature( INOUT STREAM *stream,
910 							 OUT QUERY_INFO *queryInfo )
911 	{
912 	const int startPos = stell( stream );
913 	BYTE buffer[ CRYPT_MAX_TEXTSIZE + 8 ];
914 	int length, status;
915 
916 	assert( isWritePtr( stream, sizeof( STREAM ) ) );
917 	assert( isWritePtr( queryInfo, sizeof( QUERY_INFO ) ) );
918 
919 	REQUIRES( startPos >= 0 && startPos < MAX_BUFFER_SIZE );
920 
921 	/* Clear return value */
922 	memset( queryInfo, 0, sizeof( QUERY_INFO ) );
923 
924 	/* Read the signature record size and algorithm information */
925 	readUint32( stream );
926 	status = readString32( stream, buffer, CRYPT_MAX_TEXTSIZE, &length );
927 	if( cryptStatusError( status ) )
928 		return( status );
929 	if( length == 7 )
930 		{
931 		/* If it's a string of length 7 it's a conventional signature
932 		   algorithm */
933 		if( !memcmp( buffer, "ssh-rsa", 7 ) )
934 			queryInfo->cryptAlgo = CRYPT_ALGO_RSA;
935 		else
936 			{
937 			if( !memcmp( buffer, "ssh-dss", 7 ) )
938 				queryInfo->cryptAlgo = CRYPT_ALGO_DSA;
939 			else
940 				return( CRYPT_ERROR_BADDATA );
941 			}
942 		queryInfo->hashAlgo = CRYPT_ALGO_SHA1;
943 		}
944 	else
945 		{
946 		if( length == 12 )
947 			{
948 			if( memcmp( buffer, "rsa-sha2-256", 12 ) )
949 				return( CRYPT_ERROR_BADDATA );
950 			queryInfo->cryptAlgo = CRYPT_ALGO_RSA;
951 			queryInfo->hashAlgo = CRYPT_ALGO_SHA2;
952 			}
953 		else
954 			{
955 			/* It's probably an ECC signature algorithm.  We don't bother
956 			   checking the exact type since this is implicitly specified by
957 			   the signature-check key */
958 			if( length < 19 )		/* "ecdsa-sha2-nistXXXX" */
959 				return( CRYPT_ERROR_BADDATA );
960 			if( memcmp( buffer, "ecdsa-sha2-", 11 ) )
961 				return( CRYPT_ERROR_BADDATA );
962 			queryInfo->cryptAlgo = CRYPT_ALGO_ECDSA;
963 			queryInfo->hashAlgo = CRYPT_ALGO_SHA2;
964 			}
965 		}
966 
967 	/* Read the start of the signature */
968 	status = length = readUint32( stream );
969 	if( cryptStatusError( status ) )
970 		return( status );
971 	switch( queryInfo->cryptAlgo )
972 		{
973 		case CRYPT_ALGO_RSA:
974 			if( length < MIN_PKCSIZE || length > CRYPT_MAX_PKCSIZE )
975 				return( CRYPT_ERROR_BADDATA );
976 			break;
977 
978 		case CRYPT_ALGO_DSA:
979 			if( length != ( 20 + 20 ) )
980 				return( CRYPT_ERROR_BADDATA );
981 			break;
982 
983 		case CRYPT_ALGO_ECDSA:
984 			if( length < MIN_PKCSIZE_ECCPOINT || \
985 				length > MAX_PKCSIZE_ECCPOINT )
986 				return( CRYPT_ERROR_BADDATA );
987 			break;
988 
989 		default:
990 			retIntError();
991 		}
992 	queryInfo->dataStart = stell( stream ) - startPos;
993 	queryInfo->dataLength = length;
994 
995 	/* Make sure that the remaining signature data is present */
996 	return( sSkip( stream, length, MAX_INTLENGTH_SHORT ) );
997 	}
998 
999 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 6 ) ) \
1000 static int writeSshSignature( INOUT STREAM *stream,
1001 #ifdef USE_ECDSA
1002 							  const CRYPT_CONTEXT iSignContext,
1003 #else
1004 							  STDC_UNUSED const CRYPT_CONTEXT iSignContext,
1005 #endif /* !USE_ECDSA */
1006 							  const CRYPT_ALGO_TYPE hashAlgo,
1007 							  STDC_UNUSED const int hashParam,
1008 							  IN_ALGO const CRYPT_ALGO_TYPE signAlgo,
1009 							  IN_BUFFER( signatureLength ) const BYTE *signature,
1010 							  IN_LENGTH_SHORT_MIN( 40 ) const int signatureLength )
1011 	{
1012 	assert( isWritePtr( stream, sizeof( STREAM ) ) );
1013 	assert( isReadPtr( signature, signatureLength ) );
1014 			/* Other parameters aren't used for this format */
1015 
1016 	REQUIRES( hashAlgo == CRYPT_ALGO_SHA1 || hashAlgo == CRYPT_ALGO_SHA2 );
1017 	REQUIRES( signAlgo == CRYPT_ALGO_RSA || signAlgo == CRYPT_ALGO_DSA || \
1018 			  signAlgo == CRYPT_ALGO_ECDSA );
1019 	REQUIRES( signatureLength >= ( 20 + 20 ) && \
1020 			  signatureLength < MAX_INTLENGTH_SHORT );
1021 
1022 #ifdef USE_ECDSA
1023 	/* ECC signatures require all sorts of calisthenics that aren't
1024 	   necessary for standard signatures, specifically we have to encode the
1025 	   curve type in the algorithm name.  See the long comment in
1026 	   session/ssh.c on the possible problems that the following can run
1027 	   into */
1028 	if( signAlgo == CRYPT_ALGO_ECDSA )
1029 		{
1030 		const char *algoName;
1031 		int keySize, algoNameLen, status;
1032 
1033 		status = krnlSendMessage( iSignContext, IMESSAGE_GETATTRIBUTE,
1034 								  &keySize, CRYPT_CTXINFO_KEYSIZE );
1035 		if( cryptStatusError( status ) )
1036 			return( status );
1037 		switch( keySize )
1038 			{
1039 			case bitsToBytes( 256 ):
1040 				algoName = "ecdsa-sha2-nistp256";
1041 				algoNameLen = 19;
1042 				break;
1043 
1044 			case bitsToBytes( 384 ):
1045 				algoName = "ecdsa-sha2-nistp384";
1046 				algoNameLen = 19;
1047 				break;
1048 
1049 			case bitsToBytes( 521 ):
1050 				algoName = "ecdsa-sha2-nistp521";
1051 				algoNameLen = 19;
1052 				break;
1053 
1054 			default:
1055 				retIntError();
1056 			}
1057 
1058 		writeUint32( stream, sizeofString32( algoNameLen ) + \
1059 							 sizeofString32( signatureLength ) );
1060 		writeString32( stream, algoName, algoNameLen );
1061 		return( writeString32( stream, signature, signatureLength ) );
1062 		}
1063 #endif /* USE_ECDSA */
1064 
1065 	/* Write a non-ECC signature */
1066 	if( hashAlgo == CRYPT_ALGO_SHA1 )
1067 		{
1068 		writeUint32( stream, sizeofString32( 7 ) + \
1069 							 sizeofString32( signatureLength ) );
1070 		writeString32( stream, ( signAlgo == CRYPT_ALGO_RSA ) ? \
1071 							   "ssh-rsa" : "ssh-dss", 7 );
1072 		}
1073 	else
1074 		{
1075 		REQUIRES( signAlgo == CRYPT_ALGO_RSA && \
1076 				  hashAlgo == CRYPT_ALGO_SHA2 );
1077 
1078 		writeUint32( stream, sizeofString32( 12 ) + \
1079 							 sizeofString32( signatureLength ) );
1080 		writeString32( stream, "rsa-sha2-256", 12 );
1081 		}
1082 	return( writeString32( stream, signature, signatureLength ) );
1083 	}
1084 #endif /* USE_SSH */
1085 
1086 #ifdef USE_SSL
1087 
1088 /* Read/write SSL signatures.  This is just a raw signature without any
1089    encapsulation */
1090 
1091 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
readSslSignature(INOUT STREAM * stream,OUT QUERY_INFO * queryInfo)1092 static int readSslSignature( INOUT STREAM *stream,
1093 							 OUT QUERY_INFO *queryInfo )
1094 	{
1095 	const int startPos = stell( stream );
1096 	int length, status;
1097 
1098 	assert( isWritePtr( stream, sizeof( STREAM ) ) );
1099 	assert( isWritePtr( queryInfo, sizeof( QUERY_INFO ) ) );
1100 
1101 	REQUIRES( startPos >= 0 && startPos < MAX_BUFFER_SIZE );
1102 
1103 	/* Clear return value */
1104 	memset( queryInfo, 0, sizeof( QUERY_INFO ) );
1105 
1106 	/* Read the start of the signature */
1107 	status = length = readUint16( stream );
1108 	if( cryptStatusError( status ) )
1109 		return( status );
1110 	if( length < min( MIN_PKCSIZE, MIN_PKCSIZE_ECCPOINT ) || \
1111 		length > CRYPT_MAX_PKCSIZE )
1112 		return( CRYPT_ERROR_BADDATA );
1113 	queryInfo->dataStart = stell( stream ) - startPos;
1114 	queryInfo->dataLength = length;
1115 
1116 	/* Make sure that the remaining signature data is present */
1117 	return( sSkip( stream, length, MAX_INTLENGTH_SHORT ) );
1118 	}
1119 
1120 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 6 ) ) \
1121 static int writeSslSignature( INOUT STREAM *stream,
1122 							  STDC_UNUSED const CRYPT_CONTEXT iSignContext,
1123 							  STDC_UNUSED const CRYPT_ALGO_TYPE hashAlgo,
1124 							  STDC_UNUSED const int hashParam,
1125 							  STDC_UNUSED const CRYPT_ALGO_TYPE signAlgo,
1126 							  IN_BUFFER( signatureLength ) const BYTE *signature,
1127 							  IN_LENGTH_SHORT_MIN( 18 + 18 + 1 ) \
1128 								const int signatureLength )
1129 	{
1130 	assert( isWritePtr( stream, sizeof( STREAM ) ) );
1131 	assert( isReadPtr( signature, signatureLength ) );
1132 			/* Other parameters aren't used for this format */
1133 
1134 	REQUIRES( signatureLength > ( 18 + 18 ) && \
1135 			  signatureLength < MAX_INTLENGTH_SHORT );
1136 
1137 	writeUint16( stream, signatureLength );
1138 	return( swrite( stream, signature, signatureLength ) );
1139 	}
1140 
1141 /* Read/write TLS 1.2 signatures, which specify a hash algorithm before the
1142    signature and use PKCS #1 formatting instead of SSL's raw dual-hash */
1143 
1144 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
readTls12Signature(INOUT STREAM * stream,OUT QUERY_INFO * queryInfo)1145 static int readTls12Signature( INOUT STREAM *stream,
1146 							   OUT QUERY_INFO *queryInfo )
1147 	{
1148 	static const MAP_TABLE hashAlgoIDTbl[] = {
1149 		{ /* TLS_HASHALGO_MD5 */ 1, CRYPT_ALGO_MD5 },
1150 		{ /* TLS_HASHALGO_SHA1 */ 2, CRYPT_ALGO_SHA1 },
1151 		{ /* TLS_HASHALGO_SHA2 */ 4, CRYPT_ALGO_SHA2 },
1152 		{ /* TLS_HASHALGO_SHA384 */ 5, CRYPT_ALGO_SHA2 },
1153 		{ /* TLS_HASHALGO_SHA512 */ 6, CRYPT_ALGO_SHA2 },
1154 		{ CRYPT_ERROR, 0 }, { CRYPT_ERROR, 0 }
1155 		};
1156 	static const MAP_TABLE sigAlgoIDTbl[] = {
1157 		{ /* TLS_SIGALGO_RSA */ 1, CRYPT_ALGO_RSA },
1158 		{ /* TLS_SIGALGO_DSA */ 2, CRYPT_ALGO_DSA },
1159 		{ /* TLS_SIGALGO_ECDSA */ 3, CRYPT_ALGO_ECDSA },
1160 		{ CRYPT_ERROR, 0 }, { CRYPT_ERROR, 0 }
1161 		};
1162 	const int startPos = stell( stream );
1163 	int hashAlgoID, sigAlgoID, value, length, status;
1164 
1165 	assert( isWritePtr( stream, sizeof( STREAM ) ) );
1166 	assert( isWritePtr( queryInfo, sizeof( QUERY_INFO ) ) );
1167 
1168 	REQUIRES( startPos >= 0 && startPos < MAX_BUFFER_SIZE );
1169 
1170 	/* Clear return value */
1171 	memset( queryInfo, 0, sizeof( QUERY_INFO ) );
1172 
1173 	/* Read the hash and signature algorithm data */
1174 	hashAlgoID = sgetc( stream );
1175 	status = sigAlgoID = sgetc( stream );
1176 	if( cryptStatusError( status ) )
1177 		return( status );
1178 	if( hashAlgoID <= 0 || hashAlgoID >= 7 || \
1179 		sigAlgoID <= 0 || sigAlgoID >= 4 )
1180 		return( CRYPT_ERROR_BADDATA );
1181 	status = mapValue( hashAlgoID, &value, hashAlgoIDTbl,
1182 					   FAILSAFE_ARRAYSIZE( hashAlgoIDTbl, MAP_TABLE ) );
1183 	if( cryptStatusError( status ) )
1184 		return( status );
1185 	queryInfo->hashAlgo = value;	/* int vs.enum */
1186 	if( isHashMacExtAlgo( value ) )
1187 		{
1188 		/* If it's a parameterised algorithm then we have to return extra
1189 		   information to indicate the sub-algorithm type */
1190 		switch( hashAlgoID )
1191 			{
1192 			case 4:
1193 				queryInfo->hashAlgoParam = bitsToBytes( 256 );
1194 				break;
1195 
1196 #ifdef USE_SHA2_EXT
1197 			case 5:
1198 				queryInfo->hashAlgoParam = bitsToBytes( 384 );
1199 				break;
1200 
1201 			case 6:
1202 				queryInfo->hashAlgoParam = bitsToBytes( 512 );
1203 				break;
1204 #endif /* USE_SHA2_EXT */
1205 
1206 			default:
1207 				return( CRYPT_ERROR_BADDATA );
1208 			}
1209 		}
1210 	status = mapValue( sigAlgoID, &value, sigAlgoIDTbl,
1211 					   FAILSAFE_ARRAYSIZE( sigAlgoIDTbl, MAP_TABLE ) );
1212 	if( cryptStatusError( status ) )
1213 		return( status );
1214 	queryInfo->cryptAlgo = value;	/* int vs.enum */
1215 
1216 	/* Read the start of the signature */
1217 	status = length = readUint16( stream );
1218 	if( cryptStatusError( status ) )
1219 		return( status );
1220 	if( length < min( MIN_PKCSIZE, MIN_PKCSIZE_ECCPOINT ) || \
1221 		length > CRYPT_MAX_PKCSIZE )
1222 		return( CRYPT_ERROR_BADDATA );
1223 	queryInfo->dataStart = stell( stream ) - startPos;
1224 	queryInfo->dataLength = length;
1225 
1226 	/* Make sure that the remaining signature data is present */
1227 	return( sSkip( stream, length, MAX_INTLENGTH_SHORT ) );
1228 	}
1229 
1230 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 6 ) ) \
1231 static int writeTls12Signature( INOUT STREAM *stream,
1232 								STDC_UNUSED const CRYPT_CONTEXT iSignContext,
1233 								IN_ALGO const CRYPT_ALGO_TYPE hashAlgo,
1234 								IN_INT_SHORT_Z const int hashParam,
1235 								IN_ALGO const CRYPT_ALGO_TYPE signAlgo,
1236 								IN_BUFFER( signatureLength ) const BYTE *signature,
1237 								IN_LENGTH_SHORT_MIN( 18 + 18 + 1 ) \
1238 									const int signatureLength )
1239 	{
1240 	static const MAP_TABLE hashAlgoIDTbl[] = {
1241 		{ CRYPT_ALGO_MD5, /* TLS_HASHALGO_MD5 */ 1 },
1242 		{ CRYPT_ALGO_SHA1, /* TLS_HASHALGO_SHA1 */ 2 },
1243 		{ CRYPT_ALGO_SHA2, /* TLS_HASHALGO_SHA2 */ 4 },
1244 		{ CRYPT_ERROR, 0 }, { CRYPT_ERROR, 0 }
1245 		};
1246 	static const MAP_TABLE sigAlgoIDTbl[] = {
1247 		{ CRYPT_ALGO_RSA, /* TLS_SIGALGO_RSA */ 1 },
1248 		{ CRYPT_ALGO_DSA, /* TLS_SIGALGO_DSA */ 2 },
1249 		{ CRYPT_ALGO_ECDSA, /* TLS_SIGALGO_ECDSA */ 3 },
1250 		{ CRYPT_ERROR, 0 }, { CRYPT_ERROR, 0 }
1251 		};
1252 	int hashAlgoID, sigAlgoID, status;
1253 
1254 	assert( isWritePtr( stream, sizeof( STREAM ) ) );
1255 	assert( isReadPtr( signature, signatureLength ) );
1256 			/* Other parameters aren't used for this format */
1257 
1258 	REQUIRES( hashAlgo == CRYPT_ALGO_SHA1 || hashAlgo == CRYPT_ALGO_SHA2 );
1259 	REQUIRES( hashParam >= 0 && hashParam < MAX_INTLENGTH_SHORT );
1260 	REQUIRES( signatureLength > ( 18 + 18 ) && \
1261 			  signatureLength < MAX_INTLENGTH_SHORT );
1262 
1263 	/* Write the hash and siagnature algorithm data */
1264 	status = mapValue( hashAlgo, &hashAlgoID, hashAlgoIDTbl,
1265 					   FAILSAFE_ARRAYSIZE( hashAlgoIDTbl, MAP_TABLE ) );
1266 	ENSURES( cryptStatusOK( status ) );
1267 #ifdef USE_SHA2_EXT
1268 	if( hashAlgo == CRYPT_ALGO_SHA2 && hashParam == bitsToBytes( 384 ) )
1269 		hashAlgoID = 5;	/* SHA-384 */
1270 #endif /* USE_SHA2_EXT */
1271 	status = mapValue( signAlgo, &sigAlgoID, sigAlgoIDTbl,
1272 					   FAILSAFE_ARRAYSIZE( sigAlgoIDTbl, MAP_TABLE ) );
1273 	ENSURES( cryptStatusOK( status ) );
1274 	sputc( stream, hashAlgoID );
1275 	sputc( stream, sigAlgoID );
1276 
1277 	/* Write the signature itself */
1278 	writeUint16( stream, signatureLength );
1279 	return( swrite( stream, signature, signatureLength ) );
1280 	}
1281 #endif /* USE_SSL */
1282 
1283 /****************************************************************************
1284 *																			*
1285 *					Signature Read/Write Access Functions					*
1286 *																			*
1287 ****************************************************************************/
1288 
1289 typedef struct {
1290 	const SIGNATURE_TYPE type;
1291 	const READSIG_FUNCTION function;
1292 	} SIG_READ_INFO;
1293 static const SIG_READ_INFO sigReadTable[] = {
1294 #ifdef USE_INT_ASN1
1295 	{ SIGNATURE_RAW, readRawSignature },
1296 	{ SIGNATURE_X509, readX509Signature },
1297 #endif /* USE_INT_ASN1 */
1298 #ifdef USE_INT_CMS
1299 	{ SIGNATURE_CMS, readCmsSignature },
1300 	{ SIGNATURE_CRYPTLIB, readCryptlibSignature },
1301 #endif /* USE_INT_CMS */
1302 #ifdef USE_PGP
1303 	{ SIGNATURE_PGP, readPgpSignature },
1304 #endif /* USE_PGP */
1305 #ifdef USE_SSH
1306 	{ SIGNATURE_SSH, readSshSignature },
1307 #endif /* USE_SSH */
1308 #ifdef USE_SSL
1309 	{ SIGNATURE_SSL, readSslSignature },
1310 	{ SIGNATURE_TLS12, readTls12Signature },
1311 #endif /* USE_SSL */
1312 	{ SIGNATURE_NONE, NULL }, { SIGNATURE_NONE, NULL }
1313 	};
1314 
1315 typedef struct {
1316 	const SIGNATURE_TYPE type;
1317 	const WRITESIG_FUNCTION function;
1318 	} SIG_WRITE_INFO;
1319 static const SIG_WRITE_INFO sigWriteTable[] = {
1320 #ifdef USE_INT_ASN1
1321 	{ SIGNATURE_RAW, writeRawSignature },
1322 	{ SIGNATURE_X509, writeX509Signature },
1323 #endif /* USE_INT_ASN1 */
1324 #ifdef USE_INT_CMS
1325 	{ SIGNATURE_CMS, writeCmsSignature },
1326 	{ SIGNATURE_CRYPTLIB, writeCryptlibSignature },
1327 #endif /* USE_INT_CMS */
1328 #ifdef USE_PGP
1329 	{ SIGNATURE_PGP, writePgpSignature },
1330 #endif /* USE_PGP */
1331 #ifdef USE_SSH
1332 	{ SIGNATURE_SSH, writeSshSignature },
1333 #endif /* USE_SSH */
1334 #ifdef USE_SSL
1335 	{ SIGNATURE_SSL, writeSslSignature },
1336 	{ SIGNATURE_TLS12, writeTls12Signature },
1337 #endif /* USE_SSH */
1338 	{ SIGNATURE_NONE, NULL }, { SIGNATURE_NONE, NULL }
1339 	};
1340 
1341 CHECK_RETVAL_PTR \
getReadSigFunction(IN_ENUM (SIGNATURE)const SIGNATURE_TYPE sigType)1342 READSIG_FUNCTION getReadSigFunction( IN_ENUM( SIGNATURE ) \
1343 										const SIGNATURE_TYPE sigType )
1344 	{
1345 	int i;
1346 
1347 	REQUIRES_N( sigType > SIGNATURE_NONE && sigType < SIGNATURE_LAST );
1348 
1349 	for( i = 0;
1350 		 sigReadTable[ i ].type != SIGNATURE_NONE && \
1351 			i < FAILSAFE_ARRAYSIZE( sigReadTable, SIG_READ_INFO );
1352 		 i++ )
1353 		{
1354 		if( sigReadTable[ i ].type == sigType )
1355 			return( sigReadTable[ i ].function );
1356 		}
1357 	ENSURES_N( i < FAILSAFE_ARRAYSIZE( sigReadTable, SIG_READ_INFO ) );
1358 
1359 	return( NULL );
1360 	}
1361 CHECK_RETVAL_PTR \
getWriteSigFunction(IN_ENUM (SIGNATURE)const SIGNATURE_TYPE sigType)1362 WRITESIG_FUNCTION getWriteSigFunction( IN_ENUM( SIGNATURE ) \
1363 										const SIGNATURE_TYPE sigType )
1364 	{
1365 	int i;
1366 
1367 	REQUIRES_N( sigType > SIGNATURE_NONE && sigType < SIGNATURE_LAST );
1368 
1369 	for( i = 0;
1370 		 sigWriteTable[ i ].type != SIGNATURE_NONE && \
1371 			i < FAILSAFE_ARRAYSIZE( sigWriteTable, SIG_WRITE_INFO );
1372 		 i++ )
1373 		{
1374 		if( sigWriteTable[ i ].type == sigType )
1375 			return( sigWriteTable[ i ].function );
1376 		}
1377 	ENSURES_N( i < FAILSAFE_ARRAYSIZE( sigWriteTable, SIG_WRITE_INFO ) );
1378 
1379 	return( NULL );
1380 	}
1381