cryptlib  3.4.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Macros
pkcs15_rd.c
Go to the documentation of this file.
1 /****************************************************************************
2 * *
3 * cryptlib PKCS #15 Read Routines *
4 * Copyright Peter Gutmann 1996-2007 *
5 * *
6 ****************************************************************************/
7 
8 #if defined( INC_ALL )
9  #include "crypt.h"
10  #include "asn1.h"
11  #include "asn1_ext.h"
12  #include "keyset.h"
13  #include "pkcs15.h"
14 #else
15  #include "crypt.h"
16  #include "enc_dec/asn1.h"
17  #include "enc_dec/asn1_ext.h"
18  #include "keyset/keyset.h"
19  #include "keyset/pkcs15.h"
20 #endif /* Compiler-specific includes */
21 
22 #ifdef USE_PKCS15
23 
24 /****************************************************************************
25 * *
26 * Utility Functions *
27 * *
28 ****************************************************************************/
29 
30 /* Copy any new object ID information that we've just read across to the
31  object information */
32 
33 STDC_NONNULL_ARG( ( 1, 2 ) ) \
34 static void copyObjectIdInfo( INOUT PKCS15_INFO *pkcs15infoPtr,
35  const PKCS15_INFO *pkcs15objectInfo )
36  {
37  assert( isWritePtr( pkcs15infoPtr, sizeof( PKCS15_INFO ) ) );
38  assert( isReadPtr( pkcs15objectInfo, sizeof( PKCS15_INFO ) ) );
39 
40  /* If any new ID information has become available, copy it over. The
41  keyID defaults to the iD so we only copy the newly-read keyID over if
42  it's something other than the existing iD */
43  if( pkcs15objectInfo->keyIDlength > 0 && \
44  ( pkcs15infoPtr->iDlength != pkcs15objectInfo->keyIDlength || \
45  memcmp( pkcs15infoPtr->iD, pkcs15objectInfo->keyID,
46  pkcs15objectInfo->keyIDlength ) ) )
47  {
48  memcpy( pkcs15infoPtr->keyID, pkcs15objectInfo->keyID,
49  pkcs15objectInfo->keyIDlength );
50  pkcs15infoPtr->keyIDlength = pkcs15objectInfo->keyIDlength;
51  }
52  if( pkcs15objectInfo->iAndSIDlength > 0 )
53  {
54  memcpy( pkcs15infoPtr->iAndSID, pkcs15objectInfo->iAndSID,
55  pkcs15objectInfo->iAndSIDlength );
56  pkcs15infoPtr->iAndSIDlength = pkcs15objectInfo->iAndSIDlength;
57  }
58  if( pkcs15objectInfo->subjectNameIDlength > 0 )
59  {
60  memcpy( pkcs15infoPtr->subjectNameID, pkcs15objectInfo->subjectNameID,
61  pkcs15objectInfo->subjectNameIDlength );
62  pkcs15infoPtr->subjectNameIDlength = pkcs15objectInfo->subjectNameIDlength;
63  }
64  if( pkcs15objectInfo->issuerNameIDlength > 0 )
65  {
66  memcpy( pkcs15infoPtr->issuerNameID, pkcs15objectInfo->issuerNameID,
67  pkcs15objectInfo->issuerNameIDlength );
68  pkcs15infoPtr->issuerNameIDlength = pkcs15objectInfo->issuerNameIDlength;
69  }
70  if( pkcs15objectInfo->pgp2KeyIDlength > 0 )
71  {
72  memcpy( pkcs15infoPtr->pgp2KeyID, pkcs15objectInfo->pgp2KeyID,
73  pkcs15objectInfo->pgp2KeyIDlength );
74  pkcs15infoPtr->pgp2KeyIDlength = pkcs15objectInfo->pgp2KeyIDlength;
75  }
76  if( pkcs15objectInfo->openPGPKeyIDlength > 0 )
77  {
78  memcpy( pkcs15infoPtr->openPGPKeyID, pkcs15objectInfo->openPGPKeyID,
79  pkcs15objectInfo->openPGPKeyIDlength );
80  pkcs15infoPtr->openPGPKeyIDlength = pkcs15objectInfo->openPGPKeyIDlength;
81  }
82  }
83 
84 /* Copy any new object payload information that we've just read across to
85  the object information */
86 
87 STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \
88 static int copyObjectPayloadInfo( INOUT PKCS15_INFO *pkcs15infoPtr,
89  const PKCS15_INFO *pkcs15objectInfo,
90  IN_BUFFER( objectLength ) const void *object,
91  IN_LENGTH_SHORT const int objectLength,
92  IN_ENUM( PKCS15_OBJECT ) \
93  const PKCS15_OBJECT_TYPE type )
94  {
95  assert( isWritePtr( pkcs15infoPtr, sizeof( PKCS15_INFO ) ) );
96  assert( isReadPtr( pkcs15objectInfo, sizeof( PKCS15_INFO ) ) );
97  assert( isReadPtr( object, objectLength ) );
98 
99  REQUIRES( objectLength > 0 && objectLength < MAX_INTLENGTH_SHORT );
100  REQUIRES( type > PKCS15_OBJECT_NONE && type < PKCS15_OBJECT_LAST );
101 
102  switch( type )
103  {
105  pkcs15infoPtr->type = PKCS15_SUBTYPE_NORMAL;
106  pkcs15infoPtr->pubKeyData = ( void * ) object;
107  pkcs15infoPtr->pubKeyDataSize = objectLength;
108  pkcs15infoPtr->pubKeyOffset = pkcs15objectInfo->pubKeyOffset;
109  pkcs15infoPtr->pubKeyUsage = pkcs15objectInfo->pubKeyUsage;
110  break;
111 
113  pkcs15infoPtr->type = PKCS15_SUBTYPE_NORMAL;
114  pkcs15infoPtr->privKeyData = ( void * ) object;
115  pkcs15infoPtr->privKeyDataSize = objectLength;
116  pkcs15infoPtr->privKeyOffset = pkcs15objectInfo->privKeyOffset;
117  pkcs15infoPtr->privKeyUsage = pkcs15objectInfo->privKeyUsage;
118  break;
119 
120  case PKCS15_OBJECT_CERT:
121  if( pkcs15infoPtr->type == PKCS15_SUBTYPE_NONE )
122  pkcs15infoPtr->type = PKCS15_SUBTYPE_CERT;
123  pkcs15infoPtr->certData = ( void * ) object;
124  pkcs15infoPtr->certDataSize = objectLength;
125  pkcs15infoPtr->certOffset = pkcs15objectInfo->certOffset;
126  pkcs15infoPtr->trustedUsage = pkcs15objectInfo->trustedUsage;
127  pkcs15infoPtr->implicitTrust = pkcs15objectInfo->implicitTrust;
128  break;
129 
131  /* We don't try and return an error for this, it's not something
132  that we can make use of but if it's ever reached it just ends
133  up as an empty (non-useful) object entry */
134  DEBUG_DIAG(( "Found secret-key object" ));
135  assert( DEBUG_WARN );
136  break;
137 
138  case PKCS15_OBJECT_DATA:
139  pkcs15infoPtr->type = PKCS15_SUBTYPE_DATA;
140  pkcs15infoPtr->dataType = pkcs15objectInfo->dataType;
141  pkcs15infoPtr->dataData = ( void * ) object;
142  pkcs15infoPtr->dataDataSize = objectLength;
143  pkcs15infoPtr->dataOffset = pkcs15objectInfo->dataOffset;
144  break;
145 
146  default:
147  /* We don't try and return an error for this, it's not something
148  that we can make use of but if it's ever reached it just ends
149  up as an empty (non-useful) object entry */
150  DEBUG_DIAG(( "Found unknown object type %d", type ));
151  assert( DEBUG_WARN );
152  break;
153  }
154 
155  return( CRYPT_OK );
156  }
157 
158 /****************************************************************************
159 * *
160 * Read a Keyset *
161 * *
162 ****************************************************************************/
163 
164 /* Read a single object in a keyset */
165 
166 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3, 4, 6 ) ) \
167 static int readObject( INOUT STREAM *stream,
168  OUT PKCS15_INFO *pkcs15objectInfo,
171  IN_ENUM( PKCS15_OBJECT ) const PKCS15_OBJECT_TYPE type,
173  {
174  STREAM objectStream;
175  void *objectData;
176  int objectLength, status;
177 
178  assert( isWritePtr( stream, sizeof( STREAM ) ) );
179  assert( isWritePtr( pkcs15objectInfo, sizeof( PKCS15_INFO ) ) );
180  assert( isWritePtr( objectPtrPtr, sizeof( void * ) ) );
181  assert( isWritePtr( objectLengthPtr, sizeof( int ) ) );
182 
183  REQUIRES( type > PKCS15_OBJECT_NONE && type < PKCS15_OBJECT_LAST );
184  REQUIRES( errorInfo != NULL );
185 
186  /* Clear return values */
187  memset( pkcs15objectInfo, 0, sizeof( PKCS15_INFO ) );
188  *objectPtrPtr = NULL;
189  *objectLengthPtr = 0;
190 
191  /* Read the current object's data */
192  status = readRawObjectAlloc( stream, &objectData, &objectLength,
194  if( cryptStatusError( status ) )
195  {
196  retExt( status,
197  ( status, errorInfo,
198  "Couldn't read PKCS #15 object data" ) );
199  }
200 
201  /* Read the object attributes from the in-memory object data */
202  sMemConnect( &objectStream, objectData, objectLength );
203  status = readObjectAttributes( &objectStream, pkcs15objectInfo, type,
204  errorInfo );
205  sMemDisconnect( &objectStream );
206  if( cryptStatusError( status ) )
207  {
208  clFree( "readObject", objectData );
209  return( status );
210  }
211 
212  /* Remember the encoded object data */
213  *objectPtrPtr = objectData;
214  *objectLengthPtr = objectLength;
215 
216  return( CRYPT_OK );
217  }
218 
219 /* Read an entire keyset */
220 
221 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 5 ) ) \
222 int readPkcs15Keyset( INOUT STREAM *stream,
223  OUT_ARRAY( maxNoPkcs15objects ) PKCS15_INFO *pkcs15info,
225  IN_LENGTH const long endPos,
226  INOUT ERROR_INFO *errorInfo )
227  {
228  int iterationCount, status;
229 
230  assert( isWritePtr( stream, sizeof( STREAM ) ) );
231  assert( isWritePtr( pkcs15info, sizeof( PKCS15_INFO ) * \
232  maxNoPkcs15objects ) );
233  assert( isWritePtr( errorInfo, sizeof( ERROR_INFO ) ) );
234 
235  REQUIRES( maxNoPkcs15objects >= 1 && \
236  maxNoPkcs15objects < MAX_INTLENGTH_SHORT );
237  REQUIRES( endPos > 0 && endPos > stell( stream ) && \
238  endPos < MAX_INTLENGTH );
239 
240  /* Clear return value */
241  memset( pkcs15info, 0, sizeof( PKCS15_INFO ) * maxNoPkcs15objects );
242 
243  /* Scan all of the objects in the keyset */
244  for( status = CRYPT_OK, iterationCount = 0;
245  cryptStatusOK( status ) && stell( stream ) < endPos && \
246  iterationCount < FAILSAFE_ITERATIONS_MED; iterationCount++ )
247  {
248  static const MAP_TABLE tagToTypeTbl[] = {
257  { CRYPT_ERROR, 0 }, { CRYPT_ERROR, 0 }
258  };
260  int tag, value, innerEndPos, innerIterationCount;
261 
262  /* Map the object tag to a PKCS #15 object type */
263  tag = peekTag( stream );
264  if( cryptStatusError( tag ) )
265  return( tag );
266  tag = EXTRACT_CTAG( tag );
267  status = mapValue( tag, &value, tagToTypeTbl,
268  FAILSAFE_ARRAYSIZE( tagToTypeTbl, MAP_TABLE ) );
269  if( cryptStatusError( status ) )
270  {
272  ( CRYPT_ERROR_BADDATA, errorInfo,
273  "Invalid PKCS #15 object type %02X", tag ) );
274  }
275  type = value;
276 
277  /* Read the [n] [0] wrapper to find out what we're dealing with.
278  Note that we set the upper limit at MAX_INTLENGTH rather than
279  MAX_INTLENGTH_SHORT because some keysets with many large objects
280  may have a combined group-of-objects length larger than
281  MAX_INTLENGTH_SHORT */
282  readConstructed( stream, NULL, tag );
283  status = readConstructed( stream, &innerEndPos, CTAG_OV_DIRECT );
284  if( cryptStatusError( status ) )
285  return( status );
286  if( innerEndPos < MIN_OBJECT_SIZE || innerEndPos >= MAX_INTLENGTH )
287  {
289  ( CRYPT_ERROR_BADDATA, errorInfo,
290  "Invalid PKCS #15 object data size %d",
291  innerEndPos ) );
292  }
293  innerEndPos += stell( stream );
294 
295  /* Scan all objects of this type */
296  for( innerIterationCount = 0;
297  stell( stream ) < innerEndPos && \
298  innerIterationCount < FAILSAFE_ITERATIONS_LARGE;
299  innerIterationCount++ )
300  {
301  PKCS15_INFO pkcs15objectInfo, *pkcs15infoPtr = NULL;
302  void *object;
303  int objectLength;
304 
305  /* Read the object */
306  status = readObject( stream, &pkcs15objectInfo, &object,
307  &objectLength, type, errorInfo );
308  if( cryptStatusError( status ) )
309  return( status );
310 
311  /* If we read an object with associated ID information, find out
312  where to add the object data */
313  if( pkcs15objectInfo.iDlength > 0 )
314  {
315  pkcs15infoPtr = findEntry( pkcs15info, maxNoPkcs15objects,
317  pkcs15objectInfo.iD,
318  pkcs15objectInfo.iDlength,
320  }
321  if( pkcs15infoPtr == NULL )
322  {
323  int index;
324 
325  /* This personality isn't present yet, find out where we can
326  add the object data and copy the fixed object information
327  over */
328  pkcs15infoPtr = findFreeEntry( pkcs15info,
329  maxNoPkcs15objects, &index );
330  if( pkcs15infoPtr == NULL )
331  {
332  clFree( "readKeyset", object );
334  ( CRYPT_ERROR_OVERFLOW, errorInfo,
335  "No more room in keyset to add further items" ) );
336  }
337  memcpy( pkcs15infoPtr, &pkcs15objectInfo,
338  sizeof( PKCS15_INFO ) );
339  pkcs15infoPtr->index = index;
340  }
341 
342  /* Copy over any ID information */
343  copyObjectIdInfo( pkcs15infoPtr, &pkcs15objectInfo );
344 
345  /* Copy over any other new information that may have become
346  available. The semantics when multiple date ranges are
347  present (for example one for a key and one for a certificate)
348  are a bit uncertain, we use the most recent date available on
349  the assumption that this reflects the newest information */
350  if( pkcs15objectInfo.validFrom > pkcs15infoPtr->validFrom )
351  pkcs15infoPtr->validFrom = pkcs15objectInfo.validFrom;
352  if( pkcs15objectInfo.validTo > pkcs15infoPtr->validTo )
353  pkcs15infoPtr->validTo = pkcs15objectInfo.validTo;
354 
355  /* Copy the payload over */
356  copyObjectPayloadInfo( pkcs15infoPtr, &pkcs15objectInfo,
357  object, objectLength, type );
358  }
359  ENSURES( innerIterationCount < FAILSAFE_ITERATIONS_LARGE );
360  }
361  ENSURES( iterationCount < FAILSAFE_ITERATIONS_MED );
362 
363  return( CRYPT_OK );
364  }
365 #endif /* USE_PKCS15 */