cryptlib  3.4.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Macros
pkcs15_wr.c
Go to the documentation of this file.
1 /****************************************************************************
2 * *
3 * cryptlib PKCS #15 Write 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 * Write PKCS #15 Objects *
27 * *
28 ****************************************************************************/
29 
30 /* Write the wrapping needed for individual objects */
31 
33 static int writeObjectWrapper( INOUT STREAM *stream,
34  IN_LENGTH_SHORT const int length,
35  IN_TAG const int tag )
36  {
37  assert( isWritePtr( stream, sizeof( STREAM ) ) );
38 
39  REQUIRES( tag >= 0 && tag < MAX_TAG_VALUE );
40  REQUIRES( length > 0 && length < MAX_INTLENGTH_SHORT );
41 
42  writeConstructed( stream, sizeofObject( length ), tag );
43  return( writeConstructed( stream, length, CTAG_OV_DIRECT ) );
44  }
45 
46 /* Write a data item */
47 
48 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
49 static int sizeofDataItem( const PKCS15_INFO *pkcs15infoPtr,
50  OUT_LENGTH_SHORT_Z int *length )
51  {
52  const int dataSize = \
53  ( pkcs15infoPtr->dataType == CRYPT_IATTRIBUTE_USERINFO ) ? \
54  pkcs15infoPtr->dataDataSize : \
55  sizeofObject( pkcs15infoPtr->dataDataSize );
56  const int labelSize = \
57  ( pkcs15infoPtr->labelLength > 0 ) ? \
58  sizeofObject( pkcs15infoPtr->labelLength ) : 0;
59 
60  assert( isReadPtr( pkcs15infoPtr, sizeof( PKCS15_INFO ) ) );
61  assert( isWritePtr( length, sizeof( int ) ) );
62 
63  REQUIRES( labelSize >= 0 && labelSize < MAX_INTLENGTH_SHORT );
64  REQUIRES( dataSize > 0 && dataSize < MAX_INTLENGTH_SHORT );
65 
66  *length = ( int ) \
67  sizeofObject( \
68  sizeofObject( labelSize ) + \
69  sizeofObject( sizeofOID( OID_CRYPTLIB_CONTENTTYPE ) ) + \
70  sizeofObject( \
71  sizeofObject( \
72  sizeofOID( OID_CRYPTLIB_CONFIGDATA ) + dataSize ) ) );
73  return( CRYPT_OK );
74  }
75 
76 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
77 static int writeDataItem( INOUT STREAM *stream,
78  const PKCS15_INFO *pkcs15infoPtr )
79  {
80  const BYTE *oid = \
81  ( pkcs15infoPtr->dataType == CRYPT_IATTRIBUTE_CONFIGDATA ) ? \
83  ( pkcs15infoPtr->dataType == CRYPT_IATTRIBUTE_USERINDEX ) ? \
84  OID_CRYPTLIB_USERINDEX : OID_CRYPTLIB_USERINFO;
85  const int labelSize = \
86  ( pkcs15infoPtr->labelLength ) ? \
87  sizeofObject( pkcs15infoPtr->labelLength ) : 0;
88  const int contentSize = sizeofOID( oid ) + \
89  ( ( pkcs15infoPtr->dataType == CRYPT_IATTRIBUTE_USERINFO ) ? \
90  pkcs15infoPtr->dataDataSize : \
91  sizeofObject( pkcs15infoPtr->dataDataSize ) );
92 
93  assert( isWritePtr( stream, sizeof( STREAM ) ) );
94  assert( isReadPtr( pkcs15infoPtr, sizeof( PKCS15_INFO ) ) );
95 
96  REQUIRES( pkcs15infoPtr->dataType == CRYPT_IATTRIBUTE_CONFIGDATA || \
97  pkcs15infoPtr->dataType == CRYPT_IATTRIBUTE_USERINDEX || \
98  pkcs15infoPtr->dataType == CRYPT_IATTRIBUTE_USERINFO );
99  REQUIRES( labelSize >= 0 && labelSize < MAX_INTLENGTH_SHORT );
100  REQUIRES( contentSize > 0 && contentSize < MAX_INTLENGTH_SHORT );
101 
102  writeConstructed( stream, \
103  sizeofObject( labelSize ) + \
104  sizeofObject( sizeofOID( OID_CRYPTLIB_CONTENTTYPE ) ) + \
105  sizeofObject( sizeofObject( contentSize ) ),
106  CTAG_DO_OIDDO );
107  writeSequence( stream, labelSize );
108  if( labelSize > 0 )
109  writeCharacterString( stream, ( BYTE * ) pkcs15infoPtr->label,
110  pkcs15infoPtr->labelLength, BER_STRING_UTF8 );
111  writeSequence( stream, sizeofOID( OID_CRYPTLIB_CONTENTTYPE ) );
113  writeConstructed( stream, ( int ) sizeofObject( contentSize ),
115  writeSequence( stream, contentSize );
116  writeOID( stream, oid );
117  if( pkcs15infoPtr->dataType != CRYPT_IATTRIBUTE_USERINFO )
118  {
119  /* UserInfo is a straight object, the others are SEQUENCEs of
120  objects */
121  writeSequence( stream, pkcs15infoPtr->dataDataSize );
122  }
123  return( swrite( stream, pkcs15infoPtr->dataData, \
124  pkcs15infoPtr->dataDataSize ) );
125  }
126 
127 /* Flush a PKCS #15 collection to a stream */
128 
129 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
130 int pkcs15Flush( INOUT STREAM *stream,
131  IN_ARRAY( noPkcs15objects ) const PKCS15_INFO *pkcs15info,
132  IN_LENGTH_SHORT const int noPkcs15objects )
133  {
134  int pubKeySize = 0, privKeySize = 0, certSize = 0, dataSize = 0;
135  int objectsSize = 0, i, status;
136 
137  assert( isWritePtr( stream, sizeof( STREAM ) ) );
138  assert( isReadPtr( pkcs15info, \
139  sizeof( PKCS15_INFO ) * noPkcs15objects ) );
140 
141  REQUIRES( noPkcs15objects >= 1 && \
142  noPkcs15objects < MAX_INTLENGTH_SHORT );
143 
144  /* Determine the overall size of the objects */
145  for( i = 0; i < noPkcs15objects && i < FAILSAFE_ITERATIONS_MED; i++ )
146  {
147  switch( pkcs15info[ i ].type )
148  {
149  case PKCS15_SUBTYPE_NONE:
150  break;
151 
153  pubKeySize += pkcs15info[ i ].pubKeyDataSize;
154  privKeySize += pkcs15info[ i ].privKeyDataSize;
155  /* Drop through */
156 
157  case PKCS15_SUBTYPE_CERT:
158  certSize += pkcs15info[ i ].certDataSize;
159  break;
160 
162  retIntError();
163 
164  case PKCS15_SUBTYPE_DATA:
165  {
166  int length;
167 
168  status = sizeofDataItem( &pkcs15info[ i ], &length );
169  if( cryptStatusError( status ) )
170  return( status );
171  dataSize += length;
172  break;
173  }
174 
175  default:
176  retIntError();
177  }
178  }
179  ENSURES( i < FAILSAFE_ITERATIONS_MED );
180 
181  /* Determine how much data there is to write. If there's no data
182  present, let the caller know that the keyset is empty */
183  if( pubKeySize > 0 )
184  objectsSize += sizeofObject( sizeofObject( pubKeySize ) );
185  if( privKeySize > 0 )
186  objectsSize += sizeofObject( sizeofObject( privKeySize ) );
187  if( certSize > 0 )
188  objectsSize += sizeofObject( sizeofObject( certSize ) );
189  if( dataSize > 0 )
190  objectsSize += sizeofObject( sizeofObject( dataSize ) );
191  if( objectsSize <= 0 )
192  return( OK_SPECIAL ); /* Keyset is empty */
193 
194  /* Write the header information and each public key, private key, and
195  certificate */
196  status = writeCMSheader( stream, OID_PKCS15_CONTENTTYPE,
198  sizeofShortInteger( 0 ) + \
199  sizeofObject( objectsSize ), FALSE );
200  if( cryptStatusError( status ) )
201  return( status );
202  writeShortInteger( stream, 0, DEFAULT_TAG );
203  status = writeSequence( stream, objectsSize );
204  if( cryptStatusOK( status ) && privKeySize > 0 )
205  {
206  status = writeObjectWrapper( stream, privKeySize, CTAG_PO_PRIVKEY );
207  for( i = 0; cryptStatusOK( status ) && \
208  i < noPkcs15objects && i < FAILSAFE_ITERATIONS_MED; i++ )
209  {
210  if( pkcs15info[ i ].privKeyDataSize > 0 )
211  status = swrite( stream, pkcs15info[ i ].privKeyData,
212  pkcs15info[ i ].privKeyDataSize );
213  }
214  ENSURES( i < FAILSAFE_ITERATIONS_MED );
215  }
216  if( cryptStatusOK( status ) && pubKeySize > 0 )
217  {
218  status = writeObjectWrapper( stream, pubKeySize, CTAG_PO_PUBKEY );
219  for( i = 0; cryptStatusOK( status ) && \
220  i < noPkcs15objects && i < FAILSAFE_ITERATIONS_MED; i++ )
221  {
222  if( pkcs15info[ i ].pubKeyDataSize > 0 )
223  status = swrite( stream, pkcs15info[ i ].pubKeyData,
224  pkcs15info[ i ].pubKeyDataSize );
225  }
226  ENSURES( i < FAILSAFE_ITERATIONS_MED );
227  }
228  if( cryptStatusOK( status ) && certSize > 0 )
229  {
230  status = writeObjectWrapper( stream, certSize, CTAG_PO_CERT );
231  for( i = 0; cryptStatusOK( status ) && \
232  i < noPkcs15objects && i < FAILSAFE_ITERATIONS_MED; i++ )
233  {
234  if( ( pkcs15info[ i ].type == PKCS15_SUBTYPE_NORMAL && \
235  pkcs15info[ i ].certDataSize > 0 ) || \
236  ( pkcs15info[ i ].type == PKCS15_SUBTYPE_CERT ) )
237  status = swrite( stream, pkcs15info[ i ].certData,
238  pkcs15info[ i ].certDataSize );
239  }
240  ENSURES( i < FAILSAFE_ITERATIONS_MED );
241  }
242  if( cryptStatusOK( status ) && dataSize > 0 )
243  {
244  status = writeObjectWrapper( stream, dataSize, CTAG_PO_DATA );
245  for( i = 0; cryptStatusOK( status ) && \
246  i < noPkcs15objects && i < FAILSAFE_ITERATIONS_MED; i++ )
247  {
248  if( pkcs15info[ i ].dataDataSize > 0 )
249  status = writeDataItem( stream, &pkcs15info[ i ] );
250  }
251  ENSURES( i < FAILSAFE_ITERATIONS_MED );
252  }
253  ENSURES( cryptStatusOK( status ) );
254 
255  return( sflush( stream ) );
256  }
257 #endif /* USE_PKCS15 */