1 /****************************************************************************
2 *																			*
3 *						  cryptlib PKCS #12 Routines						*
4 *						Copyright Peter Gutmann 1997-2010					*
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 "pkcs12.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/pkcs12.h"
20 #endif /* Compiler-specific includes */
21 
22 #ifdef USE_PKCS12
23 
24 /* OID information used to read the header of a PKCS #12 keyset */
25 
26 static const CMS_CONTENT_INFO FAR_BSS oidInfoEncryptedData = { 0, 2 };
27 
28 static const FAR_BSS OID_INFO dataOIDinfo[] = {
29     { OID_CMS_DATA, CRYPT_OK },
30     { NULL, 0 }, { NULL, 0 }
31     };
32 
33 /****************************************************************************
34 *																			*
35 *								Utility Functions							*
36 *																			*
37 ****************************************************************************/
38 
39 /* Sanity-check the PKCS #12 information state */
40 
41 CHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \
sanityCheck(const PKCS12_INFO * pkcs12infoPtr)42 static BOOLEAN sanityCheck( const PKCS12_INFO *pkcs12infoPtr )
43 	{
44 	const PKCS12_OBJECT_INFO *objectInfoPtr;
45 
46 	assert( isReadPtr( pkcs12infoPtr, sizeof( PKCS12_INFO ) ) );
47 
48 	/* Check that the basic fields are in order.  Since all of the fields are
49 	   optional, either of them may not be present */
50 	if( pkcs12infoPtr->labelLength == 0 )
51 		{
52 		/* No label, there must be an ID present */
53 		if( pkcs12infoPtr->idLength < 0 || \
54 			pkcs12infoPtr->idLength > CRYPT_MAX_HASHSIZE )
55 			return( FALSE );
56 		}
57 	else
58 		{
59 		/* There's a label, the ID is optional */
60 		if( pkcs12infoPtr->labelLength <= 0 || \
61 			pkcs12infoPtr->labelLength > CRYPT_MAX_TEXTSIZE || \
62 			pkcs12infoPtr->idLength < 0 || \
63 			pkcs12infoPtr->idLength > CRYPT_MAX_HASHSIZE )
64 			return( FALSE );
65 		}
66 
67 	/* Check that the object-specific fields have reasonable values.  This
68 	   is a general check for reasonable values that's more targeted at
69 	   catching inadvertent memory corruption than a strict sanity check */
70 	objectInfoPtr = &pkcs12infoPtr->keyInfo;
71 	if( objectInfoPtr->data != NULL )
72 		{
73 		if( objectInfoPtr->dataSize <= 0 || \
74 			objectInfoPtr->dataSize > MAX_INTLENGTH_SHORT || \
75 			objectInfoPtr->payloadOffset <= 0 || \
76 			objectInfoPtr->payloadOffset >= objectInfoPtr->dataSize || \
77 			objectInfoPtr->payloadSize <= 0 || \
78 			objectInfoPtr->payloadSize >= objectInfoPtr->dataSize )
79 			return( FALSE );
80 		}
81 	else
82 		{
83 		if( objectInfoPtr->dataSize != 0 || \
84 			objectInfoPtr->payloadOffset != 0 || \
85 			objectInfoPtr->payloadSize != 0 )
86 			return( FALSE );
87 		}
88 	if( objectInfoPtr->keySize < 0 || \
89 		objectInfoPtr->keySize > CRYPT_MAX_KEYSIZE || \
90 		objectInfoPtr->saltSize < 0 || \
91 		objectInfoPtr->saltSize > CRYPT_MAX_HASHSIZE || \
92 		objectInfoPtr->iterations < 0 || \
93 		objectInfoPtr->iterations > MAX_KEYSETUP_ITERATIONS )
94 		return( FALSE );
95 	objectInfoPtr = &pkcs12infoPtr->certInfo;
96 	if( objectInfoPtr->data != NULL )
97 		{
98 		/* Make sure that the payload is contained within the data.  The
99 		   payload may be the same as the data, so we can have a start offset
100 		   of 0 and a size equal to the payload size */
101 		if( objectInfoPtr->dataSize <= 0 || \
102 			objectInfoPtr->dataSize > MAX_INTLENGTH_SHORT || \
103 			objectInfoPtr->payloadOffset < 0 || \
104 			objectInfoPtr->payloadOffset >= objectInfoPtr->dataSize || \
105 			objectInfoPtr->payloadSize < 0 || \
106 			objectInfoPtr->payloadSize > objectInfoPtr->dataSize )
107 			return( FALSE );
108 		}
109 	else
110 		{
111 		if( objectInfoPtr->dataSize != 0 || \
112 			objectInfoPtr->payloadOffset != 0 || \
113 			objectInfoPtr->payloadSize != 0 )
114 			return( FALSE );
115 		}
116 	if( objectInfoPtr->keySize < 0 || \
117 		objectInfoPtr->keySize > CRYPT_MAX_KEYSIZE || \
118 		objectInfoPtr->saltSize < 0 || \
119 		objectInfoPtr->saltSize > CRYPT_MAX_HASHSIZE || \
120 		objectInfoPtr->iterations < 0 || \
121 		objectInfoPtr->iterations > MAX_KEYSETUP_ITERATIONS )
122 		return( FALSE );
123 
124 	/* Check that the crypto-related fields are in order.  This is a general
125 	   check for reasonable values that's more targeted at catching
126 	   inadvertent memory corruption than a strict sanity check */
127 	if( pkcs12infoPtr->macSaltSize < 0 || \
128 		pkcs12infoPtr->macSaltSize > MAX_INTLENGTH_SHORT || \
129 		pkcs12infoPtr->macIterations < 0 || \
130 		pkcs12infoPtr->macIterations > MAX_INTLENGTH )
131 		return( FALSE );
132 
133 	return( TRUE );
134 	}
135 
136 /* Locate a PKCS #12 object based on an ID */
137 
138 #define matchID( src, srcLen, dest, destLen ) \
139 		( ( srcLen ) > 0 && ( srcLen ) == ( destLen ) && \
140 		  !memcmp( ( src ), ( dest ), ( destLen ) ) )
141 
142 CHECK_RETVAL_PTR STDC_NONNULL_ARG( ( 1 ) ) \
pkcs12FindEntry(IN_ARRAY (noPkcs12objects)const PKCS12_INFO * pkcs12info,IN_LENGTH_SHORT const int noPkcs12objects,IN_KEYID const CRYPT_KEYID_TYPE keyIDtype,IN_BUFFER_OPT (keyIDlength)const void * keyID,IN_LENGTH_KEYID_Z const int keyIDlength,const BOOLEAN isWildcardMatch)143 PKCS12_INFO *pkcs12FindEntry( IN_ARRAY( noPkcs12objects ) \
144 									const PKCS12_INFO *pkcs12info,
145 							  IN_LENGTH_SHORT const int noPkcs12objects,
146 							  IN_KEYID const CRYPT_KEYID_TYPE keyIDtype,
147 							  IN_BUFFER_OPT( keyIDlength ) const void *keyID,
148 							  IN_LENGTH_KEYID_Z const int keyIDlength,
149 							  const BOOLEAN isWildcardMatch )
150 	{
151 	int i;
152 
153 	assert( isReadPtr( pkcs12info, \
154 					   sizeof( PKCS12_INFO ) * noPkcs12objects ) );
155 	assert( ( keyID == NULL && keyIDlength == 0 ) || \
156 			isReadPtr( keyID, keyIDlength ) );
157 
158 	REQUIRES_N( noPkcs12objects >= 1 && \
159 				noPkcs12objects < MAX_INTLENGTH_SHORT );
160 	REQUIRES_N( keyIDtype == CRYPT_KEYID_NAME || \
161 				keyIDtype == CRYPT_KEYID_URI || \
162 				keyIDtype == CRYPT_IKEYID_KEYID );
163 	REQUIRES_N( ( keyID == NULL && keyIDlength == 0 ) || \
164 				( keyID != NULL && \
165 				  keyIDlength > 0 && keyIDlength < MAX_ATTRIBUTE_SIZE ) );
166 	REQUIRES_N( ( isWildcardMatch && keyID == NULL ) || !isWildcardMatch );
167 
168 	/* Try and locate the appropriate object in the PKCS #12 collection */
169 	for( i = 0; i < noPkcs12objects && i < FAILSAFE_ITERATIONS_MED; i++ )
170 		{
171 		const PKCS12_INFO *pkcs12infoPtr = &pkcs12info[ i ];
172 
173 		/* If there's no entry at this position, continue */
174 		if( pkcs12infoPtr->flags == PKCS12_FLAG_NONE )
175 			continue;
176 
177 		ENSURES_N( sanityCheck( pkcs12infoPtr ) );
178 
179 		/* If we're doing a wildcard matches, match the first private-key
180 		   entry.  This is required because PKCS #12 provides almost no
181 		   useful indexing information, and works because most keysets
182 		   contain only a single entry */
183 		if( isWildcardMatch )
184 			{
185 			if( pkcs12infoPtr->keyInfo.data == NULL )
186 				continue;	/* No private-key data present, continue */
187 			return( ( PKCS12_INFO * ) pkcs12infoPtr );
188 			}
189 
190 		/* Check for a match based on the ID type */
191 		switch( keyIDtype )
192 			{
193 			case CRYPT_KEYID_NAME:
194 			case CRYPT_KEYID_URI:
195 				if( matchID( pkcs12infoPtr->label, pkcs12infoPtr->labelLength,
196 							 keyID, keyIDlength ) )
197 					return( ( PKCS12_INFO * ) pkcs12infoPtr );
198 				break;
199 
200 			case CRYPT_IKEYID_KEYID:
201 				if( matchID( pkcs12infoPtr->id, pkcs12infoPtr->idLength,
202 							 keyID, keyIDlength ) )
203 					return( ( PKCS12_INFO * ) pkcs12infoPtr );
204 				break;
205 
206 			default:
207 				retIntError_Null();
208 			}
209 		}
210 	ENSURES_N( i < FAILSAFE_ITERATIONS_MED );
211 
212 	return( NULL );
213 	}
214 
215 /* Find a free PKCS #12 entry */
216 
217 CHECK_RETVAL_PTR STDC_NONNULL_ARG( ( 1 ) ) \
pkcs12FindFreeEntry(IN_ARRAY (noPkcs12objects)const PKCS12_INFO * pkcs12info,IN_LENGTH_SHORT const int noPkcs12objects,OUT_OPT_INDEX (noPkcs12objects)int * index)218 PKCS12_INFO *pkcs12FindFreeEntry( IN_ARRAY( noPkcs12objects ) \
219 									const PKCS12_INFO *pkcs12info,
220 								  IN_LENGTH_SHORT const int noPkcs12objects,
221 								  OUT_OPT_INDEX( noPkcs12objects ) int *index )
222 	{
223 	int i;
224 
225 	assert( isReadPtr( pkcs12info, \
226 					   sizeof( PKCS12_INFO ) * noPkcs12objects ) );
227 	assert( ( index == NULL ) || isWritePtr( index, sizeof( int ) ) );
228 
229 	REQUIRES_N( noPkcs12objects >= 1 && \
230 				noPkcs12objects < MAX_INTLENGTH_SHORT );
231 
232 	/* Clear return value */
233 	if( index != NULL )
234 		*index = CRYPT_ERROR;
235 
236 	for( i = 0; i < noPkcs12objects && i < FAILSAFE_ITERATIONS_MED; i++ )
237 		{
238 		if( pkcs12info[ i ].flags == PKCS12_FLAG_NONE )
239 			break;
240 		}
241 	ENSURES_N( i < FAILSAFE_ITERATIONS_MED );
242 	if( i >= noPkcs12objects )
243 		return( NULL );
244 
245 	/* Remember the index value (used for enumerating PKCS #12 entries) for
246 	   this entry if required */
247 	if( index != NULL )
248 		*index = i;
249 
250 	return( ( PKCS12_INFO * ) &pkcs12info[ i ] );
251 	}
252 
253 /* Free object entries */
254 
255 STDC_NONNULL_ARG( ( 1 ) ) \
pkcs12freeObjectEntry(INOUT PKCS12_OBJECT_INFO * pkcs12objectInfo)256 void pkcs12freeObjectEntry( INOUT PKCS12_OBJECT_INFO *pkcs12objectInfo )
257 	{
258 	void *dataPtr = ( void * ) pkcs12objectInfo->data;
259 		 /* Although the data is declared 'const' since it can't be
260 		    modified, we still have to be able to zeroise it on free so
261 			we override the const for this */
262 
263 	assert( isWritePtr( pkcs12objectInfo, sizeof( PKCS12_OBJECT_INFO ) ) );
264 
265 	zeroise( dataPtr, pkcs12objectInfo->dataSize );
266 	clFree( "pkcs12freeObjectEntry", dataPtr );
267 	zeroise( pkcs12objectInfo, sizeof( PKCS12_OBJECT_INFO ) );
268 	}
269 
270 STDC_NONNULL_ARG( ( 1 ) ) \
pkcs12freeEntry(INOUT PKCS12_INFO * pkcs12info)271 void pkcs12freeEntry( INOUT PKCS12_INFO *pkcs12info )
272 	{
273 	assert( isWritePtr( pkcs12info, sizeof( PKCS12_INFO ) ) );
274 
275 	if( pkcs12info->macInitialised )
276 		krnlSendNotifier( pkcs12info->iMacContext, IMESSAGE_DECREFCOUNT );
277 	if( pkcs12info->keyInfo.data != NULL )
278 		pkcs12freeObjectEntry( &pkcs12info->keyInfo );
279 	if( pkcs12info->certInfo.data != NULL )
280 		pkcs12freeObjectEntry( &pkcs12info->certInfo );
281 
282 	zeroise( pkcs12info, sizeof( PKCS12_INFO ) );
283 	}
284 
285 STDC_NONNULL_ARG( ( 1 ) ) \
INOUT_ARRAY(noPkcs12objects)286 void pkcs12Free( INOUT_ARRAY( noPkcs12objects ) PKCS12_INFO *pkcs12info,
287 				 IN_RANGE( 1, MAX_PKCS12_OBJECTS ) const int noPkcs12objects )
288 	{
289 	int i;
290 
291 	assert( isWritePtr( pkcs12info, \
292 						sizeof( PKCS12_INFO ) * noPkcs12objects ) );
293 
294 	REQUIRES_V( noPkcs12objects >= 1 && \
295 				noPkcs12objects <= MAX_PKCS12_OBJECTS );
296 
297 	for( i = 0; i < noPkcs12objects && i < FAILSAFE_ITERATIONS_MED; i++ )
298 		pkcs12freeEntry( &pkcs12info[ i ] );
299 	ENSURES_V( i < FAILSAFE_ITERATIONS_MED );
300 	zeroise( pkcs12info, sizeof( PKCS12_INFO ) * noPkcs12objects );
301 	}
302 
303 /* Read the header of a PKCS #12 keyset */
304 
305 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \
readPkcs12header(INOUT STREAM * stream,OUT_INT_Z long * endPosPtr,INOUT ERROR_INFO * errorInfo)306 static int readPkcs12header( INOUT STREAM *stream,
307 							 OUT_INT_Z long *endPosPtr,
308 							 INOUT ERROR_INFO *errorInfo )
309 	{
310 	long version, endPos DUMMY_INIT, currentPos;
311 	int status;
312 
313 	assert( isWritePtr( stream, sizeof( STREAM ) ) );
314 	assert( isWritePtr( endPosPtr, sizeof( long ) ) );
315 	assert( isWritePtr( errorInfo, sizeof( ERROR_INFO ) ) );
316 
317 	/* Clear return value */
318 	*endPosPtr = 0;
319 
320 	/* Read the outer header and make sure that it's valid */
321 	readSequence( stream, NULL );
322 	status = readShortInteger( stream, &version );
323 	if( cryptStatusOK( status ) && version != 3 )
324 		status = CRYPT_ERROR_BADDATA;
325 	if( cryptStatusOK( status ) )
326 		{
327 		status = readCMSheader( stream, dataOIDinfo,
328 								FAILSAFE_ARRAYSIZE( dataOIDinfo, OID_INFO ),
329 								&endPos, READCMS_FLAG_DEFINITELENGTH_OPT );
330 		}
331 	if( cryptStatusError( status ) )
332 		{
333 		retExt( status,
334 				( status, errorInfo,
335 				  "Invalid PKCS #12 keyset header" ) );
336 		}
337 
338 	/* If we couldn't get the length from the CMS header, try again with the
339 	   next level of nested data */
340 	if( endPos == CRYPT_UNUSED )
341 		{
342 		int length;
343 
344 		status = readSequence( stream, &length );
345 		if( cryptStatusOK( status ) && length == CRYPT_UNUSED )
346 			{
347 			retExt( CRYPT_ERROR_BADDATA,
348 					( CRYPT_ERROR_BADDATA, errorInfo,
349 					  "Can't process indefinite-length PKCS #12 "
350 					  "content" ) );
351 			}
352 		endPos = length;	/* int -> long, readSequence() requires an int */
353 		}
354 	else
355 		{
356 		const int startPos = stell( stream );
357 
358 		/* Just skip the next level of nesting.  We don't rely on the value
359 		   returned from readSequence() in case it has an indefinite length,
360 		   since we've already got a definite length earlier */
361 		status = readSequence( stream, NULL );
362 		if( cryptStatusOK( status ) )
363 			endPos -= ( stell( stream ) - startPos );
364 		}
365 	if( cryptStatusError( status ) )
366 		{
367 		retExt( status,
368 				( status, errorInfo,
369 				  "Invalid PKCS #12 keyset inner header" ) );
370 		}
371 
372 	/* Make sure that the length information is sensible */
373 	currentPos = stell( stream );
374 	if( endPos < 16 + MIN_OBJECT_SIZE || \
375 		currentPos + endPos >= MAX_INTLENGTH_SHORT )
376 		{
377 		retExt( CRYPT_ERROR_BADDATA,
378 				( CRYPT_ERROR_BADDATA, errorInfo,
379 				  "Invalid PKCS #12 keyset length information" ) );
380 		}
381 	*endPosPtr = currentPos + endPos;
382 
383 	return( CRYPT_OK );
384 	}
385 
386 /****************************************************************************
387 *																			*
388 *								Crypto Functions							*
389 *																			*
390 ****************************************************************************/
391 
392 /* Set up the parameters used to derive a password for encryption/MACing */
393 
394 CHECK_RETVAL STDC_NONNULL_ARG( ( 2, 4, 5 ) ) \
initDeriveParams(IN_HANDLE const CRYPT_USER cryptOwner,OUT_BUFFER (saltMaxLength,* saltLength)void * salt,IN_LENGTH_SHORT_MIN (KEYWRAP_SALTSIZE)const int saltMaxLength,OUT_LENGTH_BOUNDED_Z (saltMaxLength)int * saltLength,OUT_INT_Z int * iterations)395 static int initDeriveParams( IN_HANDLE const CRYPT_USER cryptOwner,
396 							 OUT_BUFFER( saltMaxLength, *saltLength ) \
397 								void *salt,
398 							 IN_LENGTH_SHORT_MIN( KEYWRAP_SALTSIZE ) \
399 								const int saltMaxLength,
400 							 OUT_LENGTH_BOUNDED_Z( saltMaxLength ) \
401 								int *saltLength,
402 							 OUT_INT_Z int *iterations )
403 	{
404 	MESSAGE_DATA msgData;
405 	int value, status;
406 
407 	assert( isWritePtr( salt, saltMaxLength ) );
408 	assert( isWritePtr( saltLength, sizeof( int ) ) );
409 	assert( isWritePtr( iterations, sizeof( int ) ) );
410 
411 	REQUIRES( cryptOwner == DEFAULTUSER_OBJECT_HANDLE || \
412 			  isHandleRangeValid( cryptOwner ) );
413 	REQUIRES( saltMaxLength >= KEYWRAP_SALTSIZE && \
414 			  saltMaxLength < MAX_INTLENGTH_SHORT );
415 
416 	/* Clear return values */
417 	memset( salt, 0, min( 16, saltMaxLength ) );
418 	*saltLength = 0;
419 	*iterations = 0;
420 
421 	/* Generate the salt */
422 	setMessageData( &msgData, salt, KEYWRAP_SALTSIZE );
423 	status = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_GETATTRIBUTE_S,
424 							  &msgData, CRYPT_IATTRIBUTE_RANDOM_NONCE );
425 	if( cryptStatusError( status ) )
426 		return( status );
427 	*saltLength = KEYWRAP_SALTSIZE;
428 
429 	/* In the interests of luser-proofing we force the use of a safe minimum
430 	   number of iterations */
431 	status = krnlSendMessage( cryptOwner, IMESSAGE_GETATTRIBUTE,
432 							  &value, CRYPT_OPTION_KEYING_ITERATIONS );
433 	if( cryptStatusError( status ) || value < MIN_KEYING_ITERATIONS )
434 		value = MIN_KEYING_ITERATIONS;
435 	*iterations = value;
436 
437 	return( CRYPT_OK );
438 	}
439 
440 /* Set up an encryption/MAC context */
441 
442 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 4, 6 ) ) \
initContext(OUT_HANDLE_OPT CRYPT_CONTEXT * iCryptContext,IN_ALGO const CRYPT_ALGO_TYPE cryptAlgo,IN_LENGTH_KEY const int keySize,IN_BUFFER (passwordLength)const void * password,IN_LENGTH_TEXT const int passwordLength,IN_BUFFER (saltLength)const void * salt,IN_LENGTH_SHORT const int saltLength,IN_INT const int iterations,const BOOLEAN isCryptContext)443 static int initContext( OUT_HANDLE_OPT CRYPT_CONTEXT *iCryptContext,
444 						IN_ALGO const CRYPT_ALGO_TYPE cryptAlgo,
445 						IN_LENGTH_KEY const int keySize,
446 						IN_BUFFER( passwordLength ) const void *password,
447 						IN_LENGTH_TEXT const int passwordLength,
448 						IN_BUFFER( saltLength ) const void *salt,
449 						IN_LENGTH_SHORT const int saltLength,
450 						IN_INT const int iterations,
451 						const BOOLEAN isCryptContext )
452 	{
453 	CRYPT_CONTEXT iLocalCryptContext;
454 	MESSAGE_CREATEOBJECT_INFO createInfo;
455 	MECHANISM_DERIVE_INFO deriveInfo;
456 	MESSAGE_DATA msgData;
457 	BYTE key[ CRYPT_MAX_KEYSIZE + 8 ], iv[ CRYPT_MAX_IVSIZE + 8 ];
458 	BYTE saltData[ 1 + CRYPT_MAX_IVSIZE + 8 ];
459 	int ivSize DUMMY_INIT, localKeySize = keySize, status;
460 
461 	assert( isWritePtr( iCryptContext, sizeof( CRYPT_CONTEXT ) ) );
462 	assert( isReadPtr( password, passwordLength ) );
463 	assert( isReadPtr( salt, saltLength ) );
464 
465 	REQUIRES( ( isCryptContext && isConvAlgo( cryptAlgo ) ) || \
466 			  ( !isCryptContext && isMacAlgo( cryptAlgo ) ) );
467 	REQUIRES( keySize >= bitsToBytes( 40 ) && keySize <= CRYPT_MAX_KEYSIZE );
468 			  /* 40 bits is a special case for certificates encrypted with
469 			     RC2-40 */
470 	REQUIRES( passwordLength >= MIN_NAME_LENGTH && \
471 			  passwordLength <= CRYPT_MAX_TEXTSIZE );
472 	REQUIRES( saltLength >= 1 && saltLength <= CRYPT_MAX_HASHSIZE );
473 	REQUIRES( iterations >= 1 && iterations < MAX_INTLENGTH );
474 
475 	/* Clear return value */
476 	*iCryptContext = CRYPT_ERROR;
477 
478 	/* Create the encryption/MAC context and get any required parameter
479 	   information.  Note that this assumes that the encryption algorithm
480 	   is a block cipher, which always seems to be the case */
481 	setMessageCreateObjectInfo( &createInfo, cryptAlgo );
482 	status = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_CREATEOBJECT,
483 							  &createInfo, OBJECT_TYPE_CONTEXT );
484 	if( cryptStatusError( status ) )
485 		return( status );
486 	iLocalCryptContext = createInfo.cryptHandle;
487 	if( isCryptContext )
488 		status = krnlSendMessage( iLocalCryptContext, IMESSAGE_GETATTRIBUTE,
489 								  &ivSize, CRYPT_CTXINFO_IVSIZE );
490 	if( cryptStatusError( status ) )
491 		{
492 		krnlSendNotifier( iLocalCryptContext, IMESSAGE_DECREFCOUNT );
493 		return( status );
494 		}
495 
496 	/* Since the salt also includes a diversifier as its first byte we copy
497 	   it to a working buffer with room for the extra data byte */
498 	memcpy( saltData + 1, salt, saltLength );
499 
500 	/* Derive the encryption/MAC key and optional IV from the password */
501 	if( isCryptContext )
502 		saltData[ 0 ] = KEYWRAP_ID_WRAPKEY;
503 	else
504 		saltData[ 0 ] = KEYWRAP_ID_MACKEY;
505 	setMechanismDeriveInfo( &deriveInfo, key, keySize, password,
506 							passwordLength, CRYPT_ALGO_SHA1, saltData,
507 							saltLength + 1, iterations );
508 	status = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_DERIVE,
509 							  &deriveInfo, MECHANISM_DERIVE_PKCS12 );
510 	if( cryptStatusOK( status ) && isCryptContext )
511 		{
512 		saltData[ 0 ] = KEYWRAP_ID_IV;
513 		setMechanismDeriveInfo( &deriveInfo, iv, ivSize, password,
514 								passwordLength, CRYPT_ALGO_SHA1, saltData,
515 								saltLength + 1, iterations );
516 		status = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_DERIVE,
517 								  &deriveInfo, MECHANISM_DERIVE_PKCS12 );
518 		}
519 	clearMechanismInfo( &deriveInfo );
520 	if( cryptStatusError( status ) )
521 		{
522 		zeroise( key, CRYPT_MAX_KEYSIZE );
523 		zeroise( iv, CRYPT_MAX_IVSIZE );
524 		krnlSendNotifier( iLocalCryptContext, IMESSAGE_DECREFCOUNT );
525 		return( status );
526 		}
527 
528 	/* We need to add special-case processing for RC2-40, which is still
529 	   universally used by Windows and possibly other implementations as
530 	   well.  The kernel (and pretty much everything else) won't allow keys
531 	   of less then MIN_KEYSIZE bytes, to get around this we create a
532 	   pseudo-key consisting of two copies of the string "PKCS#12" followed
533 	   by the actual key, with a total length of 19 bytes / 152 bits.  The
534 	   RC2 code checks for this special string at the start of any key that
535 	   it loads and only uses the last 40 bits.  This is a horrible kludge,
536 	   but RC2 is disabled by default (unless USE_PKCS12 is defined) so the
537 	   only time that it'll ever be used anyway is as RC2-40 */
538 	if( cryptAlgo == CRYPT_ALGO_RC2 && keySize == bitsToBytes( 40 ) )
539 		{
540 		memmove( key + 14, key, bitsToBytes( 40 ) );
541 		memcpy( key, "PKCS#12PKCS#12", 14 );
542 		localKeySize = 14 + bitsToBytes( 40 );
543 		}
544 
545 	/* Create an encryption/MAC context and load the key and IV into it */
546 	setMessageData( &msgData, key, localKeySize );
547 	status = krnlSendMessage( iLocalCryptContext, IMESSAGE_SETATTRIBUTE_S,
548 							  &msgData, CRYPT_CTXINFO_KEY );
549 	if( cryptStatusOK( status ) && isCryptContext )
550 		{
551 		setMessageData( &msgData, iv, ivSize );
552 		status = krnlSendMessage( iLocalCryptContext,
553 								  IMESSAGE_SETATTRIBUTE_S, &msgData,
554 								  CRYPT_CTXINFO_IV );
555 		}
556 	zeroise( key, CRYPT_MAX_KEYSIZE );
557 	zeroise( iv, CRYPT_MAX_IVSIZE );
558 	if( cryptStatusError( status ) )
559 		{
560 		krnlSendNotifier( iLocalCryptContext, IMESSAGE_DECREFCOUNT );
561 		return( status );
562 		}
563 	*iCryptContext = iLocalCryptContext;
564 
565 	return( CRYPT_OK );
566 	}
567 
568 /* Create key wrap and MAC contexts from a password */
569 
570 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 5 ) ) \
createPkcs12KeyWrapContext(INOUT PKCS12_OBJECT_INFO * pkcs12objectInfo,IN_HANDLE const CRYPT_USER cryptOwner,IN_BUFFER (passwordLength)const char * password,IN_LENGTH_TEXT const int passwordLength,OUT_HANDLE_OPT CRYPT_CONTEXT * iCryptContext,const BOOLEAN initParams)571 int createPkcs12KeyWrapContext( INOUT PKCS12_OBJECT_INFO *pkcs12objectInfo,
572 								IN_HANDLE const CRYPT_USER cryptOwner,
573 								IN_BUFFER( passwordLength ) const char *password,
574 								IN_LENGTH_TEXT const int passwordLength,
575 								OUT_HANDLE_OPT CRYPT_CONTEXT *iCryptContext,
576 								const BOOLEAN initParams )
577 	{
578 	int status;
579 
580 	assert( isWritePtr( pkcs12objectInfo, sizeof( PKCS12_OBJECT_INFO ) ) );
581 	assert( isReadPtr( password, passwordLength ) );
582 	assert( isWritePtr( iCryptContext, sizeof( CRYPT_CONTEXT ) ) );
583 
584 	REQUIRES( cryptOwner == DEFAULTUSER_OBJECT_HANDLE || \
585 			  isHandleRangeValid( cryptOwner ) );
586 	REQUIRES( passwordLength >= MIN_NAME_LENGTH && \
587 			  passwordLength <= CRYPT_MAX_TEXTSIZE );
588 
589 	/* Clear return value */
590 	*iCryptContext = CRYPT_ERROR;
591 
592 	/* Set up the parameters for the encryption key and IV if required.
593 	   The only (useful) encryption algorithm that's available is 3DES, so
594 	   we hardcode that in */
595 	if( initParams )
596 		{
597 		pkcs12objectInfo->cryptAlgo = CRYPT_ALGO_3DES;
598 		pkcs12objectInfo->keySize = bitsToBytes( 192 );
599 		status = initDeriveParams( cryptOwner, pkcs12objectInfo->salt,
600 								   CRYPT_MAX_HASHSIZE,
601 								   &pkcs12objectInfo->saltSize,
602 								   &pkcs12objectInfo->iterations );
603 		if( cryptStatusError( status ) )
604 			return( status );
605 		}
606 
607 	/* Derive the encryption key and IV from the password */
608 	return( initContext( iCryptContext, pkcs12objectInfo->cryptAlgo,
609 						 pkcs12objectInfo->keySize, password,
610 						 passwordLength, pkcs12objectInfo->salt,
611 						 pkcs12objectInfo->saltSize,
612 						 pkcs12objectInfo->iterations, TRUE ) );
613 	}
614 
615 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 5 ) ) \
createPkcs12MacContext(INOUT PKCS12_INFO * pkcs12info,IN_HANDLE const CRYPT_USER cryptOwner,IN_BUFFER (passwordLength)const char * password,IN_LENGTH_TEXT const int passwordLength,OUT_HANDLE_OPT CRYPT_CONTEXT * iCryptContext,const BOOLEAN initParams)616 int createPkcs12MacContext( INOUT PKCS12_INFO *pkcs12info,
617 							IN_HANDLE const CRYPT_USER cryptOwner,
618 							IN_BUFFER( passwordLength ) const char *password,
619 							IN_LENGTH_TEXT const int passwordLength,
620 							OUT_HANDLE_OPT CRYPT_CONTEXT *iCryptContext,
621 							const BOOLEAN initParams )
622 	{
623 	int status;
624 
625 	assert( isWritePtr( pkcs12info, sizeof( PKCS12_INFO ) ) );
626 	assert( isReadPtr( password, passwordLength ) );
627 	assert( isWritePtr( iCryptContext, sizeof( CRYPT_CONTEXT ) ) );
628 
629 	REQUIRES( cryptOwner == DEFAULTUSER_OBJECT_HANDLE || \
630 			  isHandleRangeValid( cryptOwner ) );
631 	REQUIRES( passwordLength >= MIN_NAME_LENGTH && \
632 			  passwordLength <= CRYPT_MAX_TEXTSIZE );
633 
634 	/* Clear return value */
635 	*iCryptContext = CRYPT_ERROR;
636 
637 	/* Set up the parameters used to derive the MAC key if required */
638 	if( initParams )
639 		{
640 		status = initDeriveParams( cryptOwner, pkcs12info->macSalt,
641 								   CRYPT_MAX_HASHSIZE,
642 								   &pkcs12info->macSaltSize,
643 								   &pkcs12info->macIterations );
644 		if( cryptStatusError( status ) )
645 			return( status );
646 		}
647 
648 	/* Derive the MAC key from the password.  PKCS #12 currently hardcodes
649 	   this to HMAC-SHA1 with a 160-bit key */
650 	return( initContext( iCryptContext, CRYPT_ALGO_HMAC_SHA1,
651 						 20, password, passwordLength, pkcs12info->macSalt,
652 						 pkcs12info->macSaltSize,
653 						 pkcs12info->macIterations, FALSE ) );
654 	}
655 
656 /****************************************************************************
657 *																			*
658 *								Init/Shutdown Functions						*
659 *																			*
660 ****************************************************************************/
661 
662 /* A PKCS #12 keyset can contain steaming mounds of keys and whatnot, so
663    when we open it we parse the contents into memory for later use */
664 
665 CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
initFunction(INOUT KEYSET_INFO * keysetInfoPtr,STDC_UNUSED const char * name,STDC_UNUSED const int nameLength,IN_ENUM (CRYPT_KEYOPT)const CRYPT_KEYOPT_TYPE options)666 static int initFunction( INOUT KEYSET_INFO *keysetInfoPtr,
667 						 STDC_UNUSED const char *name,
668 						 STDC_UNUSED const int nameLength,
669 						 IN_ENUM( CRYPT_KEYOPT ) const CRYPT_KEYOPT_TYPE options )
670 	{
671 	PKCS12_INFO *pkcs12info;
672 	STREAM *stream = &keysetInfoPtr->keysetFile->stream;
673 	long endPos DUMMY_INIT;
674 	int status;
675 
676 	assert( isWritePtr( keysetInfoPtr, sizeof( KEYSET_INFO ) ) );
677 
678 	REQUIRES( keysetInfoPtr->type == KEYSET_FILE && \
679 			  keysetInfoPtr->subType == KEYSET_SUBTYPE_PKCS12 );
680 	REQUIRES( name == NULL && nameLength == 0 );
681 	REQUIRES( options >= CRYPT_KEYOPT_NONE && options < CRYPT_KEYOPT_LAST );
682 
683 	/* If we're opening an existing keyset skip the outer header.  We do
684 	   this before we perform any setup operations to weed out potential
685 	   problem keysets */
686 	if( options != CRYPT_KEYOPT_CREATE )
687 		{
688 		status = readPkcs12header( stream, &endPos, KEYSET_ERRINFO );
689 		if( cryptStatusError( status ) )
690 			return( status );
691 		}
692 
693 	/* Allocate the PKCS #12 object information */
694 	if( ( pkcs12info = clAlloc( "initFunction", \
695 								sizeof( PKCS12_INFO ) * \
696 								MAX_PKCS12_OBJECTS ) ) == NULL )
697 		return( CRYPT_ERROR_MEMORY );
698 	memset( pkcs12info, 0, sizeof( PKCS12_INFO ) * MAX_PKCS12_OBJECTS );
699 	keysetInfoPtr->keyData = pkcs12info;
700 	keysetInfoPtr->keyDataSize = sizeof( PKCS12_INFO ) * MAX_PKCS12_OBJECTS;
701 	keysetInfoPtr->keyDataNoObjects = MAX_PKCS12_OBJECTS;
702 
703 	/* If this is a newly-created keyset, there's nothing left to do */
704 	if( options == CRYPT_KEYOPT_CREATE )
705 		return( CRYPT_OK );
706 
707 	/* Read all of the keys in the keyset */
708 	status = pkcs12ReadKeyset( &keysetInfoPtr->keysetFile->stream,
709 							   pkcs12info, MAX_PKCS12_OBJECTS, endPos,
710 							   KEYSET_ERRINFO );
711 	if( cryptStatusError( status ) )
712 		{
713 		clFree( "initFunction", keysetInfoPtr->keyData );
714 		keysetInfoPtr->keyData = NULL;
715 		keysetInfoPtr->keyDataSize = 0;
716 		if( options != CRYPT_KEYOPT_CREATE )
717 			{
718 			/* Reset the stream position to account for the header
719 			   information that we've already read */
720 			sseek( stream, 0 ) ;
721 			}
722 		return( status );
723 		}
724 
725 	return( CRYPT_OK );
726 	}
727 
728 /* Shut down the PKCS #12 state, flushing information to disk if necessary */
729 
730 STDC_NONNULL_ARG( ( 1 ) ) \
shutdownFunction(INOUT KEYSET_INFO * keysetInfoPtr)731 static int shutdownFunction( INOUT KEYSET_INFO *keysetInfoPtr )
732 	{
733 	int status = CRYPT_OK;
734 
735 	assert( isWritePtr( keysetInfoPtr, sizeof( KEYSET_INFO ) ) );
736 
737 	REQUIRES( keysetInfoPtr->type == KEYSET_FILE && \
738 			  keysetInfoPtr->subType == KEYSET_SUBTYPE_PKCS12 );
739 
740 	/* If the contents have been changed, allocate a working I/O buffer for
741 	   the duration of the flush and commit the changes to disk */
742 	if( keysetInfoPtr->flags & KEYSET_DIRTY )
743 		{
744 		STREAM *stream = &keysetInfoPtr->keysetFile->stream;
745 		BYTE buffer[ STREAM_BUFSIZE + 8 ];
746 
747 		sseek( stream, 0 );
748 		memset( buffer, 0, STREAM_BUFSIZE );
749 				/* Keep static analysers happy */
750 		sioctlSetString( stream, STREAM_IOCTL_IOBUFFER, buffer,
751 						 STREAM_BUFSIZE );
752 		status = pkcs12Flush( stream, keysetInfoPtr->keyData,
753 							  keysetInfoPtr->keyDataNoObjects );
754 		sioctlSet( stream, STREAM_IOCTL_IOBUFFER, 0 );
755 		if( status == OK_SPECIAL )
756 			{
757 			keysetInfoPtr->flags |= KEYSET_EMPTY;
758 			status = CRYPT_OK;
759 			}
760 		}
761 
762 	/* Free the PKCS #12 object information */
763 	if( keysetInfoPtr->keyData != NULL )
764 		{
765 		pkcs12Free( keysetInfoPtr->keyData, MAX_PKCS12_OBJECTS );
766 		zeroise( keysetInfoPtr->keyData, keysetInfoPtr->keyDataSize );
767 		clFree( "shutdownFunction", keysetInfoPtr->keyData );
768 		}
769 
770 	if( cryptStatusError( status ) )
771 		{
772 		retExt( status,
773 				( status, KEYSET_ERRINFO,
774 				  "Couldn't send PKCS #12 data to persistent storage" ) );
775 		}
776 
777 	return( CRYPT_OK );
778 	}
779 
780 /****************************************************************************
781 *																			*
782 *							Keyset Access Routines							*
783 *																			*
784 ****************************************************************************/
785 
786 CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
setAccessMethodPKCS12(INOUT KEYSET_INFO * keysetInfoPtr)787 int setAccessMethodPKCS12( INOUT KEYSET_INFO *keysetInfoPtr )
788 	{
789 	int status;
790 
791 	assert( isWritePtr( keysetInfoPtr, sizeof( KEYSET_INFO ) ) );
792 
793 	REQUIRES( keysetInfoPtr->type == KEYSET_FILE && \
794 			  keysetInfoPtr->subType == KEYSET_SUBTYPE_PKCS12 );
795 
796 	/* Set the access method pointers */
797 	FNPTR_SET( keysetInfoPtr->initFunction, initFunction );
798 	FNPTR_SET( keysetInfoPtr->shutdownFunction, shutdownFunction );
799 	status = initPKCS12get( keysetInfoPtr );
800 	if( cryptStatusOK( status ) )
801 		status = initPKCS12set( keysetInfoPtr );
802 	return( status );
803 	}
804 #endif /* USE_PKCS12 */
805