cryptlib  3.4.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Macros
sign.c
Go to the documentation of this file.
1 /****************************************************************************
2 * *
3 * Signature Routines *
4 * Copyright Peter Gutmann 1993-2007 *
5 * *
6 ****************************************************************************/
7 
8 #if defined( INC_ALL )
9  #include "crypt.h"
10  #include "asn1.h"
11  #include "asn1_ext.h"
12  #include "misc_rw.h"
13  #include "pgp_rw.h"
14  #include "mech.h"
15 #else
16  #include "crypt.h"
17  #include "enc_dec/asn1.h"
18  #include "enc_dec/asn1_ext.h"
19  #include "enc_dec/misc_rw.h"
20  #include "enc_dec/pgp_rw.h"
21  #include "mechs/mech.h"
22 #endif /* Compiler-specific includes */
23 
24 /****************************************************************************
25 * *
26 * Utility Functions *
27 * *
28 ****************************************************************************/
29 
30 /* Try and determine the format of the signed data */
31 
32 CHECK_RETVAL_ENUM( CRYPT_FORMAT ) STDC_NONNULL_ARG( ( 1 ) ) \
33 static CRYPT_FORMAT_TYPE getFormatType( IN_BUFFER( dataLength ) const void *data,
35  {
36  STREAM stream;
37  long value;
38  int status;
39 
40  assert( isReadPtr( data, dataLength ) );
41 
42  REQUIRES( dataLength > MIN_CRYPT_OBJECTSIZE && \
43  dataLength < MAX_INTLENGTH );
44 
45  sMemConnect( &stream, data, min( 16, dataLength ) );
46 
47  /* Figure out what we've got. A PKCS #7/CMS/SMIME signature begins:
48 
49  cryptlibSignature ::= SEQUENCE {
50  version INTEGER (3),
51  keyID [ 0 ] OCTET STRING
52 
53  while a CMS signature begins:
54 
55  cmsSignature ::= SEQUENCE {
56  version INTEGER (1),
57  digestAlgo SET OF {
58 
59  which allows us to determine which type of object we have. Note that
60  we use sPeek() rather than peekTag() because we want to continue
61  processing (or at least checking for) PGP data if it's no ASN.1 */
62  if( sPeek( &stream ) == BER_SEQUENCE )
63  {
65 
66  readSequence( &stream, NULL );
67  status = readShortInteger( &stream, &value );
68  if( cryptStatusError( status ) )
69  {
70  sMemDisconnect( &stream );
71  return( CRYPT_FORMAT_NONE );
72  }
73  switch( value )
74  {
75  case SIGNATURE_VERSION:
76  formatType = CRYPT_FORMAT_CMS;
77  break;
78 
80  formatType = CRYPT_FORMAT_CRYPTLIB;
81  break;
82 
83  default:
84  formatType = CRYPT_FORMAT_NONE;
85  }
86  sMemDisconnect( &stream );
87 
88  return( formatType );
89  }
90 
91 #ifdef USE_PGP
92  /* It's not ASN.1 data, check for PGP data */
93  status = pgpReadPacketHeader( &stream, NULL, &value, 30 );
94  if( cryptStatusOK( status ) && value > 30 && value < 8192 )
95  {
96  sMemDisconnect( &stream );
97  return( CRYPT_FORMAT_PGP );
98  }
99 #endif /* USE_PGP */
100 
101  sMemDisconnect( &stream );
102 
103  return( CRYPT_FORMAT_NONE );
104  }
105 
106 /****************************************************************************
107 * *
108 * Create a Signature *
109 * *
110 ****************************************************************************/
111 
112 /* Create an extended signature type */
113 
121  {
123  BOOLEAN hasSigParams = FALSE;
124  int value, status;
125 
126  /* Perform basic error checking. We have to use an internal message to
127  check for signing capability because the DLP algorithms have
128  specialised data-formatting requirements that can't normally be
129  directly accessed via external messages, and even the non-DLP
130  algorithms may be internal-use-only if there's a certificate attached
131  to the context. To make sure that the context is OK we first check
132  its external accessibility by performing a dummy attribute read.
133  Note that we can't safely use the certificate-type read performed
134  later on for this check because some error conditions (e.g. "not a
135  certificate") are valid in this case, but we don't want to have mess
136  with trying to distinguish OK-in-this-instance vs.not-OK error
137  conditions */
138  if( signature != NULL )
139  {
140  if( signatureMaxLength <= MIN_CRYPT_OBJECTSIZE || \
141  signatureMaxLength >= MAX_INTLENGTH )
142  return( CRYPT_ERROR_PARAM2 );
143  if( !isWritePtr( signature, signatureMaxLength ) )
144  return( CRYPT_ERROR_PARAM1 );
145  memset( signature, 0, MIN_CRYPT_OBJECTSIZE );
146  }
147  else
148  {
149  if( signatureMaxLength != 0 )
150  return( CRYPT_ERROR_PARAM2 );
151  }
152  if( !isWritePtrConst( signatureLength, sizeof( int ) ) )
153  return( CRYPT_ERROR_PARAM3 );
154  *signatureLength = 0;
155  if( formatType <= CRYPT_FORMAT_NONE || \
156  formatType >= CRYPT_FORMAT_LAST_EXTERNAL )
157  return( CRYPT_ERROR_PARAM4 );
158  status = krnlSendMessage( signContext, MESSAGE_GETATTRIBUTE,
159  &value, CRYPT_CTXINFO_ALGO );
160  if( cryptStatusError( status ) )
161  return( cryptArgError( status ) ? CRYPT_ERROR_PARAM5 : status );
162  status = krnlSendMessage( signContext, IMESSAGE_CHECK, NULL,
164  if( cryptStatusError( status ) )
165  return( cryptArgError( status ) ? CRYPT_ERROR_PARAM5 : status );
166  status = krnlSendMessage( hashContext, MESSAGE_CHECK, NULL,
168  if( cryptStatusError( status ) )
169  return( cryptArgError( status ) ? CRYPT_ERROR_PARAM6 : status );
170 
171  /* Perform any required format-specific checking */
172  switch( formatType )
173  {
174  case CRYPT_FORMAT_AUTO:
176  /* If it's a cryptlib-format signature there can't be any extra
177  signing attributes present */
178  if( extraData != CRYPT_UNUSED )
179  return( CRYPT_ERROR_PARAM7 );
180  break;
181 
182  case CRYPT_FORMAT_CMS:
183  case CRYPT_FORMAT_SMIME:
184  {
185  int certType; /* int vs.enum */
186 
187  /* Make sure that the signing context has a certificate attached
188  to it */
189  status = krnlSendMessage( signContext, MESSAGE_GETATTRIBUTE,
190  &certType, CRYPT_CERTINFO_CERTTYPE );
191  if( cryptStatusError( status ) || \
192  ( certType != CRYPT_CERTTYPE_CERTIFICATE && \
193  certType != CRYPT_CERTTYPE_CERTCHAIN ) )
194  return( CRYPT_ERROR_PARAM5 );
195 
196  /* Make sure that the extra data object is in order */
197  if( extraData != CRYPT_USE_DEFAULT )
198  {
199  status = krnlSendMessage( extraData, MESSAGE_GETATTRIBUTE,
200  &certType, CRYPT_CERTINFO_CERTTYPE );
201  if( cryptStatusError( status ) || \
202  certType != CRYPT_CERTTYPE_CMS_ATTRIBUTES )
203  return( CRYPT_ERROR_PARAM7 );
204  }
205  break;
206  }
207 
208 #ifdef USE_PGP
209  case CRYPT_FORMAT_PGP:
210  /* There's nothing specific to check for PGP signatures */
211  break;
212 #endif /* USE_PGP */
213 
214  default:
215  retIntError();
216  }
217 
218  /* Set up any optional signing parameters if required */
219  if( extraData != CRYPT_UNUSED )
220  {
221  initSigParams( &sigParams );
222  if( extraData == CRYPT_USE_DEFAULT )
223  sigParams.useDefaultAuthAttr = TRUE;
224  else
225  sigParams.iAuthAttr = extraData;
226  hasSigParams = TRUE;
227  }
228  if( formatType == CRYPT_FORMAT_PGP )
229  {
230  initSigParams( &sigParams );
231  sigParams.sigType = PGP_SIG_DATA;
232  hasSigParams = TRUE;
233  }
234 
235  /* Call the low-level signature create function to create the
236  signature */
237  status = iCryptCreateSignature( signature, signatureMaxLength,
238  signatureLength, formatType, signContext, hashContext,
239  hasSigParams ? &sigParams : NULL );
240  if( cryptArgError( status ) )
241  {
242  /* Remap the error code to refer to the correct parameter */
243  status = ( status == CRYPT_ARGERROR_NUM1 ) ? \
245  }
246  return( status );
247  }
248 
254  {
255  int status;
256 
257  status = cryptCreateSignatureEx( signature, signatureMaxLength,
258  signatureLength, CRYPT_FORMAT_CRYPTLIB,
259  signContext, hashContext,
260  CRYPT_UNUSED );
261  if( cryptStatusError( status ) )
262  {
263  /* Remap parameter errors to the correct position */
264  if( status == CRYPT_ERROR_PARAM5 )
265  status = CRYPT_ERROR_PARAM4;
266  if( status == CRYPT_ERROR_PARAM6 )
267  status = CRYPT_ERROR_PARAM5;
268  }
269  return( status );
270  }
271 
272 /****************************************************************************
273 * *
274 * Check a Signature *
275 * *
276 ****************************************************************************/
277 
278 /* Check an extended signature type */
279 
281  C_IN int signatureLength,
285  {
289  int status;
290 
291  /* Perform basic error checking */
292  if( signatureLength <= MIN_CRYPT_OBJECTSIZE || \
293  signatureLength >= MAX_INTLENGTH_SHORT )
294  return( CRYPT_ERROR_PARAM2 );
295  if( !isReadPtr( signature, signatureLength ) )
296  return( CRYPT_ERROR_PARAM1 );
297  if( ( formatType = getFormatType( signature, \
298  signatureLength ) ) == CRYPT_FORMAT_NONE )
299  return( CRYPT_ERROR_BADDATA );
300  status = krnlSendMessage( sigCheckKey, MESSAGE_GETDEPENDENT,
301  &sigCheckContext, OBJECT_TYPE_CONTEXT );
302  if( cryptStatusOK( status ) )
303  status = krnlSendMessage( sigCheckContext, IMESSAGE_CHECK,
305  if( cryptStatusOK( status ) )
306  {
307  status = krnlSendMessage( hashContext, MESSAGE_CHECK, NULL,
309  if( cryptArgError( status ) )
310  status = CRYPT_ERROR_PARAM4;
311  }
312  else
313  {
314  if( cryptArgError( status ) )
315  status = CRYPT_ERROR_PARAM3;
316  }
317  if( cryptStatusError( status ) )
318  return( status );
319  if( formatType == CRYPT_FORMAT_CMS || \
320  formatType == CRYPT_FORMAT_SMIME )
321  {
322  int certType; /* int vs.enum */
323 
324  /* Make sure that the sig check key includes a certificate */
325  status = krnlSendMessage( sigCheckKey, MESSAGE_GETATTRIBUTE,
326  &certType, CRYPT_CERTINFO_CERTTYPE );
327  if( cryptStatusError( status ) ||
328  ( certType != CRYPT_CERTTYPE_CERTIFICATE && \
329  certType != CRYPT_CERTTYPE_CERTCHAIN ) )
330  return( CRYPT_ERROR_PARAM3 );
331  }
332 
333  /* Perform any required format-specific checking */
334  switch( formatType )
335  {
337  /* If it's a cryptlib-format signature there can't be any extra
338  signing attributes present */
339  if( extraData != NULL )
340  return( CRYPT_ERROR_PARAM5 );
341  break;
342 
343  case CRYPT_FORMAT_CMS:
344  case CRYPT_FORMAT_SMIME:
345  if( extraData != NULL )
346  {
347  if( !isWritePtrConst( extraData, sizeof( int ) ) )
348  return( CRYPT_ERROR_PARAM6 );
349  *extraData = CRYPT_ERROR;
350  }
351  break;
352 
353 #ifdef USE_PGP
354  case CRYPT_FORMAT_PGP:
355  /* PGP doesn't have signing attributes */
356  if( extraData != NULL )
357  return( CRYPT_ERROR_PARAM5 );
358  break;
359 #endif /* USE_PGP */
360 
361  default:
362  retIntError();
363  }
364 
365  /* Call the low-level signature create function to check the signature */
366  status = iCryptCheckSignature( signature, signatureLength, formatType,
367  sigCheckKey, hashContext, CRYPT_UNUSED,
368  ( extraData != NULL ) ? &iExtraData : NULL );
369  if( cryptArgError( status ) )
370  {
371  /* Remap the error code to refer to the correct parameter */
372  status = ( status == CRYPT_ARGERROR_NUM1 ) ? \
374  }
375  if( extraData == NULL )
376  return( status );
377 
378  /* The caller has requested to see the the recovered signing attributes,
379  make them externally visible. Bailing out if this operation fails
380  may be a bit excessive in that the signature has already verified so
381  failing the whole operation just because we can't make auxiliary
382  attributes visible could be seen as overkill, however since the
383  caller has indicated an interest in the attributes it can be argued
384  that an inability to return them is as serious as a general sig.check
385  failure */
386  status = krnlSendMessage( iExtraData, IMESSAGE_SETATTRIBUTE,
388  CRYPT_IATTRIBUTE_INTERNAL );
389  if( cryptStatusError( status ) )
390  {
391  krnlSendNotifier( iExtraData, IMESSAGE_DECREFCOUNT );
392  return( status );
393  }
394  *extraData = iExtraData;
395 
396  return( CRYPT_OK );
397  }
398 
400  C_IN int signatureLength,
403  {
404  return( cryptCheckSignatureEx( signature, signatureLength, sigCheckKey,
405  hashContext, NULL ) );
406  }
407 
408 /****************************************************************************
409 * *
410 * Internal Import/Export Functions *
411 * *
412 ****************************************************************************/
413 
414 /* Internal versions of the above. These skip a lot of the explicit
415  checking done by the external versions (e.g. "Is this value really a
416  handle to a valid PKC context?") since they're only called by cryptlib
417  internal functions rather than being passed untrusted user data */
418 
420 int iCryptCreateSignature( OUT_BUFFER_OPT( signatureMaxLength, *signatureLength ) \
421  void *signature,
424  IN_ENUM( CRYPT_FORMAT ) \
428  IN_OPT const SIGPARAMS *sigParams )
429  {
430  int certType, status; /* int vs.enum */
431 
432  assert( signature == NULL || isWritePtr( signature, signatureMaxLength ) );
433  assert( isWritePtr( signatureLength, sizeof( int ) ) );
434  assert( sigParams == NULL || isReadPtr( sigParams, sizeof( SIGPARAMS ) ) );
435 
436  REQUIRES( ( signature == NULL && signatureMaxLength == 0 ) || \
437  ( signature != NULL && \
438  signatureMaxLength > MIN_CRYPT_OBJECTSIZE && \
439  signatureMaxLength < MAX_INTLENGTH ) );
440  REQUIRES( formatType > CRYPT_FORMAT_NONE && \
441  formatType < CRYPT_FORMAT_LAST );
442  REQUIRES( isHandleRangeValid( iSignContext ) );
443  REQUIRES( isHandleRangeValid( iHashContext ) );
444  REQUIRES( ( ( formatType == CRYPT_FORMAT_CRYPTLIB || \
445  formatType == CRYPT_IFORMAT_SSH || \
446  formatType == CRYPT_IFORMAT_TLS12 ) && \
447  sigParams == NULL ) ||
448  ( ( formatType == CRYPT_FORMAT_CMS || \
449  formatType == CRYPT_FORMAT_SMIME || \
450  formatType == CRYPT_FORMAT_PGP || \
451  formatType == CRYPT_IFORMAT_SSL ) && \
452  sigParams != NULL ) );
453  /* The sigParams structure is too complex to check fully here
454  so we check it in the switch statement below */
455 
456  ANALYSER_HINT( signatureLength != NULL );
457 
458  /* Clear return value */
459  *signatureLength = 0;
460 
461  /* If the signing context has a certificate chain attached then the
462  currently-selected certificate may not be the leaf certificate. To
463  ensure that we use the correct certificate we lock the chain (which
464  both protects us from having the user select a different certificate
465  while we're using it and saves the selection state for when we later
466  unlock it) and explicitly select the leaf certificate. Certificates
467  are used for formats other than the obvious CRYPT_FORMAT_CMS/
468  CRYPT_FORMAT_SMIME so we perform this operation unconditionally
469  rather than only for those two formats */
470  status = krnlSendMessage( iSignContext, MESSAGE_GETATTRIBUTE,
471  &certType, CRYPT_CERTINFO_CERTTYPE );
472  if( cryptStatusError( status ) )
473  {
474  /* There's no certificate of the required type attached */
475  certType = CRYPT_CERTTYPE_NONE;
476  }
477  else
478  {
479  /* If it's a certificate chain, lock it and select the leaf
480  certificate */
481  if( certType == CRYPT_CERTTYPE_CERTCHAIN )
482  {
483  status = krnlSendMessage( iSignContext, IMESSAGE_SETATTRIBUTE,
485  CRYPT_IATTRIBUTE_LOCKED );
486  if( cryptStatusError( status ) )
487  return( status );
488  status = krnlSendMessage( iSignContext, IMESSAGE_SETATTRIBUTE,
491  if( cryptStatusError( status ) )
492  {
493  ( void ) krnlSendMessage( iSignContext, IMESSAGE_SETATTRIBUTE,
495  CRYPT_IATTRIBUTE_LOCKED );
496  return( status );
497  }
498  }
499  }
500 
501  /* Call the low-level signature create function to create the signature */
502  switch( formatType )
503  {
505  status = createSignature( signature, signatureMaxLength,
506  signatureLength, iSignContext,
507  iHashContext, CRYPT_UNUSED,
509  break;
510 
511  case CRYPT_FORMAT_CMS:
512  case CRYPT_FORMAT_SMIME:
513  {
514  REQUIRES( ( sigParams->iAuthAttr == CRYPT_ERROR && \
515  sigParams->useDefaultAuthAttr == FALSE ) || \
516  ( sigParams->iAuthAttr == CRYPT_ERROR && \
517  sigParams->useDefaultAuthAttr == TRUE ) || \
518  ( isHandleRangeValid( sigParams->iAuthAttr ) && \
519  sigParams->useDefaultAuthAttr == FALSE ) );
520  REQUIRES( sigParams->iTspSession == CRYPT_ERROR || \
521  isHandleRangeValid( sigParams->iTspSession ) );
522 
523  status = createSignatureCMS( signature, signatureMaxLength,
524  signatureLength, iSignContext,
525  iHashContext,
526  sigParams->useDefaultAuthAttr,
527  ( sigParams->iAuthAttr == CRYPT_ERROR ) ? \
528  CRYPT_UNUSED : sigParams->iAuthAttr,
529  ( sigParams->iTspSession == CRYPT_ERROR ) ? \
530  CRYPT_UNUSED : sigParams->iTspSession,
531  formatType );
532  }
533  break;
534 
535 
536 #ifdef USE_PGP
537  case CRYPT_FORMAT_PGP:
538  REQUIRES( sigParams->useDefaultAuthAttr == FALSE && \
539  sigParams->iAuthAttr == CRYPT_ERROR && \
540  sigParams->iTspSession == CRYPT_ERROR && \
541  ( sigParams->sigType >= PGP_SIG_NONE && \
542  sigParams->sigType < PGP_SIG_LAST ) && \
543  sigParams->iSecondHash == CRYPT_ERROR );
544 
545  status = createSignaturePGP( signature, signatureMaxLength,
546  signatureLength, iSignContext,
547  iHashContext, sigParams->sigType );
548  break;
549 #endif /* USE_PGP */
550 
551 #ifdef USE_SSL
552  case CRYPT_IFORMAT_SSL:
553  REQUIRES( sigParams->useDefaultAuthAttr == FALSE && \
554  sigParams->iAuthAttr == CRYPT_ERROR && \
555  sigParams->iTspSession == CRYPT_ERROR && \
556  sigParams->sigType == PGP_SIG_NONE && \
557  isHandleRangeValid( sigParams->iSecondHash ) );
558 
559  status = createSignature( signature, signatureMaxLength,
560  signatureLength, iSignContext,
561  iHashContext, sigParams->iSecondHash,
562  SIGNATURE_SSL );
563  break;
564 
565  case CRYPT_IFORMAT_TLS12:
566  REQUIRES( sigParams == NULL );
567 
568  status = createSignature( signature, signatureMaxLength,
569  signatureLength, iSignContext,
570  iHashContext, CRYPT_UNUSED,
571  SIGNATURE_TLS12 );
572  break;
573 #endif /* USE_SSL */
574 
575 #ifdef USE_SSH
576  case CRYPT_IFORMAT_SSH:
577  status = createSignature( signature, signatureMaxLength,
578  signatureLength, iSignContext,
579  iHashContext, CRYPT_UNUSED,
580  SIGNATURE_SSH );
581  break;
582 #endif /* USE_SSH */
583 
584  default:
585  retIntError();
586  }
587  if( cryptArgError( status ) )
588  {
589  /* Catch any parameter errors that slip through */
590  DEBUG_DIAG(( "Signature creation return argError status" ));
591  assert( DEBUG_WARN );
592  status = CRYPT_ERROR_FAILED;
593  }
594  if( certType == CRYPT_CERTTYPE_CERTCHAIN )
595  {
596  /* We're signing with a certificate chain, restore its state and
597  unlock it to allow others access. If this fails there's not much
598  that we can do to recover so we don't do anything with the return
599  value */
600  ( void ) krnlSendMessage( iSignContext, IMESSAGE_SETATTRIBUTE,
602  CRYPT_IATTRIBUTE_LOCKED );
603  }
604 
605  return( status );
606  }
607 
609 int iCryptCheckSignature( IN_BUFFER( signatureLength ) const void *signature,
610  IN_LENGTH_SHORT const int signatureLength,
611  IN_ENUM( CRYPT_FORMAT ) \
617  {
619  int status;
620 
621  assert( isReadPtr( signature, signatureLength ) );
622 
623  REQUIRES( signatureLength > 40 && \
624  signatureLength < MAX_INTLENGTH_SHORT );
625  REQUIRES( formatType > CRYPT_FORMAT_NONE && \
626  formatType < CRYPT_FORMAT_LAST );
627  REQUIRES( isHandleRangeValid( iSigCheckKey ) );
628  REQUIRES( isHandleRangeValid( iHashContext ) );
629  REQUIRES( ( formatType == CRYPT_IFORMAT_SSL && \
630  isHandleRangeValid( iHash2Context ) && extraData == NULL ) || \
631  ( ( formatType == CRYPT_FORMAT_CMS || \
632  formatType == CRYPT_FORMAT_SMIME || \
633  formatType == CRYPT_IFORMAT_TLS12 ) && \
634  iHash2Context == CRYPT_UNUSED ) || \
635  ( ( formatType == CRYPT_FORMAT_CRYPTLIB || \
636  formatType == CRYPT_FORMAT_PGP || \
637  formatType == CRYPT_IFORMAT_TLS12 || \
638  formatType == CRYPT_IFORMAT_SSH ) && \
639  iHash2Context == CRYPT_UNUSED && extraData == NULL ) );
640 
641  /* Perform basic error checking */
642  status = krnlSendMessage( iSigCheckKey, IMESSAGE_GETDEPENDENT,
643  &sigCheckContext, OBJECT_TYPE_CONTEXT );
644  if( cryptStatusError( status ) )
645  return( status );
646 
647  /* Call the low-level signature check function to check the signature */
648  switch( formatType )
649  {
651  status = checkSignature( signature, signatureLength,
652  sigCheckContext, iHashContext,
654  break;
655 
656 #ifdef USE_PGP
657  case CRYPT_FORMAT_PGP:
658  status = checkSignaturePGP( signature, signatureLength,
659  sigCheckContext, iHashContext );
660  break;
661 #endif /* USE_PGP */
662 
663 #ifdef USE_SSL
664  case CRYPT_IFORMAT_SSL:
665  status = checkSignature( signature, signatureLength,
666  sigCheckContext, iHashContext,
667  iHash2Context, SIGNATURE_SSL );
668  break;
669 
670  case CRYPT_IFORMAT_TLS12:
671  status = checkSignature( signature, signatureLength,
672  sigCheckContext, iHashContext,
674  break;
675 #endif /* USE_SSL */
676 
677 #ifdef USE_SSH
678  case CRYPT_IFORMAT_SSH:
679  status = checkSignature( signature, signatureLength,
680  sigCheckContext, iHashContext,
682  break;
683 #endif /* USE_SSH */
684 
685  case CRYPT_FORMAT_CMS:
686  case CRYPT_FORMAT_SMIME:
687  if( extraData != NULL )
688  *extraData = CRYPT_ERROR;
689  status = checkSignatureCMS( signature, signatureLength,
690  sigCheckContext, iHashContext,
691  extraData, iSigCheckKey );
692  break;
693 
694  default:
695  retIntError();
696  }
697  if( cryptArgError( status ) )
698  {
699  /* Catch any parameter errors that slip through */
700  DEBUG_DIAG(( "Signature creation return argError status" ));
701  assert( DEBUG_WARN );
702  status = CRYPT_ERROR_SIGNATURE;
703  }
704  return( status );
705  }