cryptlib  3.4.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Macros
mech_int.c
Go to the documentation of this file.
1 /****************************************************************************
2 * *
3 * cryptlib Internal Mechanism Routines *
4 * Copyright Peter Gutmann 1992-2008 *
5 * *
6 ****************************************************************************/
7 
8 #ifdef INC_ALL
9  #include "crypt.h"
10  #include "mech_int.h"
11 #else
12  #include "crypt.h"
13  #include "mechs/mech_int.h"
14 #endif /* Compiler-specific includes */
15 
16 /****************************************************************************
17 * *
18 * PKC Routines *
19 * *
20 ****************************************************************************/
21 
22 /* The length of the input data for PKCS #1 transformations is usually
23  determined by the key size but sometimes we can be passed data that has
24  been zero-padded (for example data coming from an ASN.1 INTEGER in which
25  the high bit is a sign bit) making it longer than the key size, or that
26  has leading zero byte(s) making it shorter than the key size. The best
27  place to handle this is somewhat uncertain, it's an encoding issue so it
28  probably shouldn't be visible to the raw crypto routines but putting it
29  at the mechanism layer removes the algorithm-independence of that layer
30  and putting it at the mid-level sign/key-exchange routine layer both
31  removes the algorithm-independence and requires duplication of the code
32  for signatures and encryption. The best place to put it seems to be at
33  the mechanism layer since an encoding issue really shouldn't be visible
34  at the crypto layer and because it would require duplicating the handling
35  every time a new PKC implementation is plugged in.
36 
37  The intent of the size adjustment is to make the data size match the key
38  length. If it's longer we try to strip leading zero bytes. If it's
39  shorter we pad it with zero bytes to match the key size. The result is
40  either the data adjusted to match the key size or CRYPT_ERROR_BADDATA if
41  this isn't possible */
42 
44 int adjustPKCS1Data( OUT_BUFFER_FIXED( outDataMaxLen ) BYTE *outData,
46  const int outDataMaxLen,
47  IN_BUFFER( inLen ) const BYTE *inData,
48  IN_LENGTH_SHORT const int inLen,
49  IN_LENGTH_SHORT const int keySize )
50  {
51  int length = inLen;
52 
53  assert( isWritePtr( outData, outDataMaxLen ) );
54  assert( isReadPtr( inData, inLen ) );
55 
56  REQUIRES( outDataMaxLen >= CRYPT_MAX_PKCSIZE && \
57  outDataMaxLen < MAX_INTLENGTH_SHORT );
58  REQUIRES( inLen > 0 && inLen <= outDataMaxLen && \
59  inLen < MAX_INTLENGTH_SHORT );
60  REQUIRES( keySize >= MIN_PKCSIZE && keySize <= CRYPT_MAX_PKCSIZE );
61  REQUIRES( outData != inData );
62 
63  /* Make sure that the result will fit in the output buffer. This has
64  already been checked by the kernel mechanism ACL and by the
65  REQUIRES() predicate above but we make the check explicit here */
66  if( keySize > outDataMaxLen )
67  return( CRYPT_ERROR_OVERFLOW );
68 
69  /* Find the start of the data payload. If it's suspiciously short,
70  don't try and process it */
71  for( length = inLen;
72  length >= MIN_PKCSIZE - 8 && *inData == 0;
73  length--, inData++ );
74  if( length < MIN_PKCSIZE - 8 || length > keySize )
75  return( CRYPT_ERROR_BADDATA );
76 
77  /* If it's of the correct size, exit */
78  if( length == keySize )
79  {
80  memcpy( outData, inData, keySize );
81  return( CRYPT_OK );
82  }
83 
84  /* We've adjusted the size to account for zero-padding during encoding,
85  now we have to move the data into a fixed-length format to match the
86  key size. To do this we copy the payload into the output buffer with
87  enough leading-zero bytes to bring the total size up to the key size */
88  memset( outData, 0, keySize );
89  memcpy( outData + ( keySize - length ), inData, length );
90 
91  return( CRYPT_OK );
92  }
93 
94 /* Get PKC algorithm parameters */
95 
97 int getPkcAlgoParams( IN_HANDLE const CRYPT_CONTEXT pkcContext,
100  {
101  int status;
102 
103  assert( ( pkcAlgo == NULL ) || \
104  isWritePtr( pkcAlgo, sizeof( CRYPT_ALGO_TYPE ) ) );
105  assert( isWritePtr( pkcKeySize, sizeof( int ) ) );
106 
107  REQUIRES( isHandleRangeValid( pkcContext ) );
108 
109  /* Clear return values */
110  if( pkcAlgo != NULL )
111  *pkcAlgo = CRYPT_ALGO_NONE;
112  *pkcKeySize = 0;
113 
114  /* Get various PKC algorithm parameters */
115  if( pkcAlgo != NULL )
116  {
117  status = krnlSendMessage( pkcContext, IMESSAGE_GETATTRIBUTE,
118  pkcAlgo, CRYPT_CTXINFO_ALGO );
119  if( cryptStatusError( status ) )
120  return( status );
121  }
122  return( krnlSendMessage( pkcContext, IMESSAGE_GETATTRIBUTE,
123  pkcKeySize, CRYPT_CTXINFO_KEYSIZE ) );
124  }
125 
126 /****************************************************************************
127 * *
128 * Hash Routines *
129 * *
130 ****************************************************************************/
131 
132 /* Get hash algorithm parameters */
133 
135 int getHashAlgoParams( IN_HANDLE const CRYPT_CONTEXT hashContext,
138  {
139  int status;
140 
141  assert( isWritePtr( hashAlgo, sizeof( CRYPT_ALGO_TYPE ) ) );
142  assert( ( hashSize == NULL ) || \
143  isWritePtr( hashSize, sizeof( int ) ) );
144 
145  REQUIRES( isHandleRangeValid( hashContext ) );
146 
147  /* Clear return values */
148  *hashAlgo = CRYPT_ALGO_NONE;
149  if( hashSize != NULL )
150  *hashSize = 0;
151 
152  /* Get various PKC algorithm parameters */
153  if( hashSize != NULL )
154  {
155  status = krnlSendMessage( hashContext, IMESSAGE_GETATTRIBUTE,
156  hashSize, CRYPT_CTXINFO_BLOCKSIZE );
157  if( cryptStatusError( status ) )
158  return( status );
159  }
160  return( krnlSendMessage( hashContext, IMESSAGE_GETATTRIBUTE,
161  hashAlgo, CRYPT_CTXINFO_ALGO ) );
162  }
163