cryptlib  3.4.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Macros
sign_int.c
Go to the documentation of this file.
1 /****************************************************************************
2 * *
3 * Internal 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 "mech.h"
12  #include "pgp.h"
13 #else
14  #include "crypt.h"
15  #include "enc_dec/asn1.h"
16  #include "mechs/mech.h"
17  #include "misc/pgp.h"
18 #endif /* Compiler-specific includes */
19 
20 /****************************************************************************
21 * *
22 * DLP Signature Handling *
23 * *
24 ****************************************************************************/
25 
26 /* Create a DLP signature */
27 
29 static int createDlpSignature( OUT_BUFFER_OPT( bufSize, *length ) void *buffer,
30  IN_RANGE( 0, CRYPT_MAX_PKCSIZE ) const int bufSize,
31  OUT_LENGTH_Z int *length,
34  IN_ENUM( SIGNATURE ) \
35  const SIGNATURE_TYPE signatureType,
36  const BOOLEAN isECC )
37  {
38  DLP_PARAMS dlpParams;
40  BYTE hash[ CRYPT_MAX_HASHSIZE + 8 ];
41  int hashSize, status;
42 
43  assert( ( buffer == NULL && bufSize == 0 ) || \
44  isWritePtr( buffer, bufSize ) );
45  assert( isWritePtr( length, sizeof( int ) ) );
46 
47  REQUIRES( ( buffer == NULL && bufSize == 0 ) || \
48  ( buffer != NULL && \
49  bufSize > MIN_CRYPT_OBJECTSIZE && \
50  bufSize <= CRYPT_MAX_PKCSIZE ) );
51  REQUIRES( isHandleRangeValid( iSignContext ) );
52  REQUIRES( isHandleRangeValid( iHashContext ) );
53  REQUIRES( signatureType > SIGNATURE_NONE && \
54  signatureType < SIGNATURE_LAST );
55 
56  /* Clear return value */
57  *length = 0;
58 
59  /* Extract the hash value from the context. If we're doing a length
60  check then there's no hash value present yet, so we just fill in the
61  hash length value from the blocksize attribute */
62  if( buffer == NULL )
63  {
64  memset( hash, 0, CRYPT_MAX_HASHSIZE ); /* Keep mem.checkers happy */
65  status = krnlSendMessage( iHashContext, IMESSAGE_GETATTRIBUTE,
66  &msgData.length,
68  }
69  else
70  {
71  setMessageData( &msgData, hash, CRYPT_MAX_HASHSIZE );
72  status = krnlSendMessage( iHashContext, IMESSAGE_GETATTRIBUTE_S,
73  &msgData, CRYPT_CTXINFO_HASHVALUE );
74  }
75  if( cryptStatusError( status ) )
76  return( status );
77  hashSize = msgData.length;
78 
79  /* Standard DSA is only defined for hash algorithms with a block size of
80  160 bits, FIPS 186-3 extends this to allow use with larger hashes but
81  the use with algorithms other than SHA-1 is a bit unclear so we always
82  require 160 bits */
83  if( !isECC && hashSize != 20 )
84  {
85  /* The error reporting here is a bit complex, see the comment in
86  createSignature() for how this works */
87  return( CRYPT_ARGERROR_NUM1 );
88  }
89 
90  /* If we're doing a length check and the signature is being written in
91  cryptlib format the length is just an estimate since it can change by
92  several bytes depending on whether the signature values have the high
93  bit set or not (which requires zero-padding of the ASN.1-encoded
94  integers) or have the high bytes set to zero(es). We use a worst-
95  case estimate here and assume that both integers will be of the
96  maximum size and need padding, which is rather nasty because it means
97  that we can't tell how large a signature will be without actually
98  creating it */
99  if( buffer == NULL )
100  {
101  int sigComponentSize = hashSize;
102 
103  if( isECC )
104  {
105  /* For ECC signatures the reduction is done mod n, which is
106  variable-length, but for standard curves is the same as the
107  key size */
108  status = krnlSendMessage( iSignContext, IMESSAGE_GETATTRIBUTE,
109  &sigComponentSize,
111  if( cryptStatusError( status ) )
112  return( status );
113  }
114  *length = ( signatureType == SIGNATURE_PGP ) ? \
115  2 * ( 2 + sigComponentSize ) : \
116  sizeofObject( ( 2 * sizeofObject( \
117  sigComponentSize + 1 ) ) );
118  return( CRYPT_OK );
119  }
120 
121  /* Sign the data */
122  setDLPParams( &dlpParams, hash, hashSize, buffer, bufSize );
123  if( signatureType == SIGNATURE_PGP )
124  dlpParams.formatType = CRYPT_FORMAT_PGP;
125  if( signatureType == SIGNATURE_SSH )
126  dlpParams.formatType = CRYPT_IFORMAT_SSH;
127  status = krnlSendMessage( iSignContext, IMESSAGE_CTX_SIGN,
128  &dlpParams, sizeof( DLP_PARAMS ) );
129  if( cryptStatusOK( status ) )
130  *length = dlpParams.outLen;
131  return( status );
132  }
133 
134 /* Check a DLP signature */
135 
137 static int checkDlpSignature( IN_BUFFER( signatureDataLength ) \
138  const void *signatureData,
139  IN_LENGTH_SHORT const int signatureDataLength,
141  IN_HANDLE const CRYPT_CONTEXT iHashContext,
142  IN_ENUM( SIGNATURE ) \
143  const SIGNATURE_TYPE signatureType,
144  const BOOLEAN isECC )
145  {
146  DLP_PARAMS dlpParams;
148  BYTE hash[ CRYPT_MAX_HASHSIZE + 8 ];
149  int hashSize, status;
150 
151  REQUIRES( ( signatureType == SIGNATURE_SSH && \
152  signatureDataLength == 40 ) || \
153  ( signatureDataLength > 40 && \
154  signatureDataLength < MAX_INTLENGTH_SHORT ) );
155  REQUIRES( isHandleRangeValid( iSigCheckContext ) );
156  REQUIRES( isHandleRangeValid( iHashContext ) );
157  REQUIRES( signatureType > SIGNATURE_NONE && \
158  signatureType < SIGNATURE_LAST );
159 
160  /* Extract the hash value from the context */
161  setMessageData( &msgData, hash, CRYPT_MAX_HASHSIZE );
162  status = krnlSendMessage( iHashContext, IMESSAGE_GETATTRIBUTE_S,
163  &msgData, CRYPT_CTXINFO_HASHVALUE );
164  if( cryptStatusError( status ) )
165  return( status );
166  hashSize = msgData.length;
167 
168  /* Standard DSA is only defined for hash algorithms with a block size of
169  160 bits, FIPS 186-3 extends this to allow use with larger hashes but
170  the use with algorithms other than SHA-1 is a bit unclear so we always
171  require 160 bits */
172  if( !isECC && hashSize != 20 )
173  {
174  /* The error reporting here is a bit complex, see the comment in
175  createSignature() for how this works */
176  return( CRYPT_ARGERROR_NUM1 );
177  }
178 
179  /* Check the signature validity using the encoded signature data and
180  hash */
181  setDLPParams( &dlpParams, hash, hashSize, NULL, 0 );
182  dlpParams.inParam2 = signatureData;
183  dlpParams.inLen2 = signatureDataLength;
184  if( signatureType == SIGNATURE_PGP )
185  dlpParams.formatType = CRYPT_FORMAT_PGP;
186  if( signatureType == SIGNATURE_SSH )
187  dlpParams.formatType = CRYPT_IFORMAT_SSH;
188  return( krnlSendMessage( iSigCheckContext, IMESSAGE_CTX_SIGCHECK,
189  &dlpParams, sizeof( DLP_PARAMS ) ) );
190  }
191 
192 /****************************************************************************
193 * *
194 * Create a Signature *
195 * *
196 ****************************************************************************/
197 
198 /* Common signature-creation routine, used by other sign_xxx.c modules */
199 
201 int createSignature( OUT_BUFFER_OPT( sigMaxLength, *signatureLength ) \
202  void *signature,
203  IN_LENGTH_Z const int sigMaxLength,
205  IN_HANDLE const CRYPT_CONTEXT iSignContext,
206  IN_HANDLE const CRYPT_CONTEXT iHashContext,
208  IN_ENUM( SIGNATURE ) const SIGNATURE_TYPE signatureType )
209  {
210  STREAM stream;
211  const WRITESIG_FUNCTION writeSigFunction = getWriteSigFunction( signatureType );
212  BYTE buffer[ CRYPT_MAX_PKCSIZE + 8 ];
213  BYTE *bufPtr = ( signature == NULL ) ? NULL : buffer;
214  const BOOLEAN isSSLsig = ( signatureType == SIGNATURE_SSL ) ? TRUE : FALSE;
215  const int bufSize = ( signature == NULL ) ? 0 : CRYPT_MAX_PKCSIZE;
216  int signAlgo, hashAlgo, length = DUMMY_INIT, hashParam = 0, status;
217 
218  assert( ( signature == NULL && sigMaxLength == 0 ) || \
219  isWritePtr( signature, sigMaxLength ) );
220  assert( isWritePtr( signatureLength, sizeof( int ) ) );
221 
222  REQUIRES( ( signature == NULL && sigMaxLength == 0 ) || \
223  ( signature != NULL && \
224  sigMaxLength > MIN_CRYPT_OBJECTSIZE && \
225  sigMaxLength < MAX_INTLENGTH ) );
226  REQUIRES( isHandleRangeValid( iSignContext ) );
227  REQUIRES( isHandleRangeValid( iHashContext ) );
228  REQUIRES( ( signatureType == SIGNATURE_SSL && \
229  isHandleRangeValid( iHashContext2 ) ) || \
230  ( ( signatureType == SIGNATURE_CMS || \
231  signatureType == SIGNATURE_CRYPTLIB || \
232  signatureType == SIGNATURE_PGP || \
233  signatureType == SIGNATURE_RAW || \
234  signatureType == SIGNATURE_SSH || \
235  signatureType == SIGNATURE_TLS12 || \
236  signatureType == SIGNATURE_X509 ) && \
237  iHashContext2 == CRYPT_UNUSED ) );
238 
239  /* Make sure that the requested signature format is available */
240  if( writeSigFunction == NULL )
241  return( CRYPT_ERROR_NOTAVAIL );
242 
243  /* Extract general information */
244  status = krnlSendMessage( iSignContext, IMESSAGE_GETATTRIBUTE, &signAlgo,
246  if( cryptStatusError( status ) )
248  status = krnlSendMessage( iHashContext, IMESSAGE_GETATTRIBUTE,
249  &hashAlgo, CRYPT_CTXINFO_ALGO );
250  if( cryptStatusOK( status ) && hashAlgo == CRYPT_ALGO_SHA2 )
251  status = krnlSendMessage( iHashContext, IMESSAGE_GETATTRIBUTE,
252  &hashParam, CRYPT_CTXINFO_BLOCKSIZE );
253  if( cryptStatusError( status ) )
254  return( cryptArgError( status ) ? CRYPT_ARGERROR_NUM2 : status );
255 
256  /* DLP and ECDLP signatures are handled somewhat specially */
257  if( isDlpAlgo( signAlgo ) || isEccAlgo( signAlgo ) )
258  {
259  /* In addition to the special-case processing for DLP/ECDLP
260  signatures, we have to provide even further special handling for
261  SSL signatures, which normally sign a dual hash of MD5 and SHA-1
262  but for DLP only sign the second SHA-1 hash */
263  status = createDlpSignature( bufPtr, bufSize, &length, iSignContext,
264  isSSLsig ? iHashContext2 : iHashContext,
265  signatureType,
266  isEccAlgo( signAlgo ) ? TRUE : FALSE );
267  }
268  else
269  {
271 
272  /* It's a standard signature, process it as normal */
273  setMechanismSignInfo( &mechanismInfo, bufPtr, bufSize, iHashContext,
274  iHashContext2, iSignContext );
275  status = krnlSendMessage( iSignContext, IMESSAGE_DEV_SIGN, &mechanismInfo,
276  isSSLsig ? MECHANISM_SIG_SSL : \
278  if( cryptStatusOK( status ) )
279  length = mechanismInfo.signatureLength;
280  clearMechanismInfo( &mechanismInfo );
281  }
282  if( cryptStatusError( status ) )
283  {
284  /* The mechanism messages place the acted-on object (in this case the
285  hash context) first while the higher-level functions place the
286  signature context next to the signature data, in other words
287  before the hash context. Because of this we have to reverse
288  parameter error values when translating from the mechanism to the
289  signature function level */
290  if( bufPtr != NULL )
291  zeroise( bufPtr, CRYPT_MAX_PKCSIZE );
292  return( ( status == CRYPT_ARGERROR_NUM1 ) ? \
294  ( status == CRYPT_ARGERROR_NUM2 ) ? \
295  CRYPT_ARGERROR_NUM1 : status );
296  }
297 
298  /* If we're perfoming a dummy sign for a length check, set up a dummy
299  value to write */
300  if( signature == NULL )
301  memset( buffer, 0x01, length );
302 
303  /* Write the signature record to the output */
304  sMemOpenOpt( &stream, signature, sigMaxLength );
305  status = writeSigFunction( &stream, iSignContext, hashAlgo, hashParam,
306  signAlgo, buffer, length );
307  if( cryptStatusOK( status ) )
308  *signatureLength = stell( &stream );
309  sMemDisconnect( &stream );
310 
311  /* Clean up */
312  zeroise( buffer, CRYPT_MAX_PKCSIZE );
313  return( status );
314  }
315 
316 /****************************************************************************
317 * *
318 * Check a Signature *
319 * *
320 ****************************************************************************/
321 
322 /* Common signature-checking routine, used by other sign_xxx.c modules */
323 
325 int checkSignature( IN_BUFFER( signatureLength ) const void *signature,
326  IN_LENGTH_SHORT const int signatureLength,
327  IN_HANDLE const CRYPT_CONTEXT iSigCheckContext,
328  IN_HANDLE const CRYPT_CONTEXT iHashContext,
329  IN_HANDLE_OPT const CRYPT_CONTEXT iHashContext2,
330  IN_ENUM( SIGNATURE ) const SIGNATURE_TYPE signatureType )
331  {
333  const READSIG_FUNCTION readSigFunction = getReadSigFunction( signatureType );
335  STREAM stream;
336  void *signatureData;
337  const BOOLEAN isSSLsig = ( signatureType == SIGNATURE_SSL ) ? TRUE : FALSE;
338  int signAlgo, hashAlgo, signatureDataLength, hashParam = 0, status;
339 
340  assert( isReadPtr( signature, signatureLength ) );
341 
342  REQUIRES( signatureLength > 40 && \
343  signatureLength < MAX_INTLENGTH_SHORT );
344  REQUIRES( isHandleRangeValid( iSigCheckContext ) );
345  REQUIRES( isHandleRangeValid( iHashContext ) );
346  REQUIRES( ( signatureType == SIGNATURE_SSL && \
347  isHandleRangeValid( iHashContext2 ) ) || \
348  ( ( signatureType == SIGNATURE_CMS || \
349  signatureType == SIGNATURE_CRYPTLIB || \
350  signatureType == SIGNATURE_PGP || \
351  signatureType == SIGNATURE_RAW || \
352  signatureType == SIGNATURE_SSH || \
353  signatureType == SIGNATURE_TLS12 || \
354  signatureType == SIGNATURE_X509 ) && \
355  iHashContext2 == CRYPT_UNUSED ) );
356 
357  /* Make sure that the requested signature format is available */
358  if( readSigFunction == NULL )
359  return( CRYPT_ERROR_NOTAVAIL );
360 
361  /* Extract general information */
362  status = krnlSendMessage( iSigCheckContext, IMESSAGE_GETATTRIBUTE,
363  &signAlgo, CRYPT_CTXINFO_ALGO );
364  if( cryptStatusError( status ) )
365  return( cryptArgError( status ) ? CRYPT_ARGERROR_NUM1 : status );
366  status = krnlSendMessage( iHashContext, IMESSAGE_GETATTRIBUTE,
367  &hashAlgo, CRYPT_CTXINFO_ALGO );
368  if( cryptStatusOK( status ) && hashAlgo == CRYPT_ALGO_SHA2 )
369  status = krnlSendMessage( iHashContext, IMESSAGE_GETATTRIBUTE,
370  &hashParam, CRYPT_CTXINFO_BLOCKSIZE );
371  if( cryptStatusError( status ) )
372  return( cryptArgError( status ) ? CRYPT_ARGERROR_NUM2 : status );
373 
374  /* Read and check the signature record */
375  sMemConnect( &stream, signature, signatureLength );
376  status = readSigFunction( &stream, &queryInfo );
377  sMemDisconnect( &stream );
378  if( cryptStatusError( status ) )
379  {
380  zeroise( &queryInfo, sizeof( QUERY_INFO ) );
381  return( status );
382  }
383 
384  /* Make sure that we've been given the correct algorithms. Raw
385  signatures specify the algorithm information elsewhere so the check
386  is done at a higher level when we process the signature data */
387  if( signatureType != SIGNATURE_RAW && signatureType != SIGNATURE_SSL )
388  {
389  if( signAlgo != queryInfo.cryptAlgo )
390  status = CRYPT_ERROR_SIGNATURE;
391  if( signatureType != SIGNATURE_SSH )
392  {
393  if( hashAlgo != queryInfo.hashAlgo )
394  status = CRYPT_ERROR_SIGNATURE;
395  if( hashAlgo == CRYPT_ALGO_SHA2 && hashParam != 32 && \
396  hashParam != queryInfo.hashParam )
397  status = CRYPT_ERROR_SIGNATURE;
398  }
399  if( cryptStatusError( status ) )
400  {
401  zeroise( &queryInfo, sizeof( QUERY_INFO ) );
402  return( status );
403  }
404  }
405 
406  /* Make sure that we've been given the correct key if the signature
407  format supports this type of check. SIGNATURE_CMS supports a check
408  with MESSAGE_COMPARE_ISSUERANDSERIALNUMBER but this has already been
409  done while procesing the other CMS data before we were called so we
410  don't need to do it again */
411  if( signatureType == SIGNATURE_CRYPTLIB || \
412  signatureType == SIGNATURE_PGP )
413  {
415 
416  setMessageData( &msgData, queryInfo.keyID, queryInfo.keyIDlength );
417  status = krnlSendMessage( iSigCheckContext, IMESSAGE_COMPARE,
418  &msgData,
419  ( signatureType == SIGNATURE_CRYPTLIB ) ? \
421  ( queryInfo.version == PGP_VERSION_2 ) ? \
424  if( cryptStatusError( status ) )
425  {
426  /* A failed comparison is reported as a generic CRYPT_ERROR,
427  convert it into a wrong-key error if necessary */
428  zeroise( &queryInfo, sizeof( QUERY_INFO ) );
429  return( ( status == CRYPT_ERROR ) ? \
430  CRYPT_ERROR_WRONGKEY : status );
431  }
432  }
433  REQUIRES( rangeCheck( queryInfo.dataStart, queryInfo.dataLength,
434  signatureLength ) );
435  signatureData = ( BYTE * ) signature + queryInfo.dataStart;
436  signatureDataLength = queryInfo.dataLength;
437  zeroise( &queryInfo, sizeof( QUERY_INFO ) );
438 
439  /* DLP and ECDLP signatures are handled somewhat specially */
440  if( isDlpAlgo( signAlgo ) || isEccAlgo( signAlgo ) )
441  {
442  /* In addition to the special-case processing for DLP/ECDLP
443  signatures, we have to provide even further special handling for
444  SSL signatures, which normally sign a dual hash of MD5 and SHA-1
445  but for DLP only sign the second SHA-1 hash */
446  return( checkDlpSignature( signatureData, signatureDataLength,
447  iSigCheckContext,
448  isSSLsig ? iHashContext2 : iHashContext,
449  signatureType,
450  isEccAlgo( signAlgo ) ? TRUE : FALSE ) );
451  }
452 
453  /* It's a standard signature, process it as normal */
454  setMechanismSignInfo( &mechanismInfo, signatureData, signatureDataLength,
455  iHashContext, iHashContext2, iSigCheckContext );
457  &mechanismInfo, isSSLsig ? MECHANISM_SIG_SSL : \
459  clearMechanismInfo( &mechanismInfo );
460  if( cryptStatusError( status ) )
461  {
462  /* The mechanism messages place the acted-on object (in this case the
463  hash context) first while the higher-level functions place the
464  signature context next to the signature data, in other words
465  before the hash context. Because of this we have to reverse
466  parameter error values when translating from the mechanism to the
467  signature function level */
468  return( ( status == CRYPT_ARGERROR_NUM1 ) ? \
470  ( status == CRYPT_ARGERROR_NUM2 ) ? \
471  CRYPT_ARGERROR_NUM1 : status );
472  }
473 
474  return( CRYPT_OK );
475  }