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