1 /****************************************************************************
2 *																			*
3 *					  cryptlib PKCS #11 Item Read Routines					*
4 *						Copyright Peter Gutmann 1998-2012					*
5 *																			*
6 ****************************************************************************/
7 
8 #define PKC_CONTEXT		/* Tell context.h that we're working with PKC contexts */
9 #if defined( INC_ALL )
10   #include "crypt.h"
11   #include "context.h"
12   #include "device.h"
13   #include "pkcs11_api.h"
14   #include "asn1.h"
15   #if defined( USE_ECDH ) || defined( USE_ECDSA )
16 	#include "asn1_ext.h"
17   #endif /* USE_ECDH || USE_ECDSA */
18 #else
19   #include "crypt.h"
20   #include "context/context.h"
21   #include "device/device.h"
22   #include "device/pkcs11_api.h"
23   #include "enc_dec/asn1.h"
24   #if defined( USE_ECDH ) || defined( USE_ECDSA )
25 	#include "enc_dec/asn1_ext.h"
26   #endif /* USE_ECDH || USE_ECDSA */
27 #endif /* Compiler-specific includes */
28 
29 /* In some rare situations only incomplete PKCS #11 support is available in
30    the underlying device, for example with a token that's been initialised
31    via CryptoAPI (which doesn't populate all the PKCS #11 fields) but which
32    is now being accessed through a PKCS #11 driver.  Define the following
33    to have cryptlib perform an object search by enumerating every object of
34    the required type in the token and matching by the requested ID
35    information */
36 
37 #define PKCS11_FIND_VIA_CRYPTLIB
38 
39 /* We sometimes need to read things into local memory from a device in a
40    manner that can't be handled by a dynBuf since the data is coming from a
41    device rather than a cryptlib object.  The following value defines the
42    maximum size of the on-stack buffer, if the data is larger than this then
43    we dynamically allocate the buffer (this almost never occurs) */
44 
45 #define MAX_STACK_BUFFER_SIZE		1024
46 
47 #ifdef USE_PKCS11
48 
49 /****************************************************************************
50 *																			*
51 *						 		Utility Routines							*
52 *																			*
53 ****************************************************************************/
54 
55 /* Get a PKCS #11 attribute value.  If the passed-in buffer is large enough
56    to contain the value (it almost always is) then we use that, otherwise
57    we dynamically allocate the storage for it, which is why the caller has
58    to call an explicit cleanup function when they're finished with the
59    data */
60 
61 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 4, 5, 6 ) ) \
62 static int getAttributeValue( INOUT PKCS11_INFO *pkcs11Info,
63 							  const CK_OBJECT_HANDLE hObject,
64 							  const CK_ATTRIBUTE_TYPE type,
65 							  OUT_BUFFER_ALLOC_OPT( *valueLength ) void **value,
66 							  OUT_LENGTH_SHORT_Z int *valueLength,
67 							  OUT_BUFFER( valueBufLength, *valueLength ) \
68 									void *valueBuffer,
69 							  IN_LENGTH_SHORT_MIN( 16 ) const int valueBufLength )
70 	{
71 	CK_ATTRIBUTE valueTemplate = \
72 		{ type, NULL_PTR, 0 };
73 	CK_RV status;
74 
75 	assert( isWritePtr( pkcs11Info, sizeof( PKCS11_INFO ) ) );
76 	assert( isWritePtr( value, sizeof( void * ) ) );
77 	assert( isWritePtr( valueLength, sizeof( int ) ) );
78 	assert( isWritePtr( valueBuffer, valueBufLength ) );
79 
80 	REQUIRES( valueBufLength >= 16 && valueBufLength < MAX_INTLENGTH_SHORT );
81 
82 	/* Clear return values */
83 	*value = NULL;
84 	memset( valueBuffer, 0, min( 16, valueBufLength ) );
85 	*valueLength = 0;
86 
87 	/* Find out how big the attribute value is */
88 	status = C_GetAttributeValue( pkcs11Info->hSession, hObject,
89 								  &valueTemplate, 1 );
90 	if( status != CKR_OK )
91 		return( pkcs11MapError( status, CRYPT_ERROR_NOTFOUND ) );
92 
93 	/* If it's larger than the supplied buffer, allocate the storage
94 	   dynamically */
95 	if( valueTemplate.ulValueLen > valueBufLength )
96 		{
97 		if( valueTemplate.ulValueLen >= MAX_INTLENGTH_SHORT )
98 			return( CRYPT_ERROR_OVERFLOW );
99 		if( ( valueTemplate.pValue = clAlloc( "getAttributeValue", \
100 					( size_t ) ( valueTemplate.ulValueLen ) ) ) == NULL )
101 			return( CRYPT_ERROR_MEMORY );
102 		}
103 	else
104 		valueTemplate.pValue = valueBuffer;
105 
106 	/* Get the attribute value */
107 	status = C_GetAttributeValue( pkcs11Info->hSession, hObject,
108 								  &valueTemplate, 1 );
109 	if( status != CKR_OK )
110 		{
111 		if( valueTemplate.pValue != valueBuffer )
112 			clFree( "getAttributeValue", valueTemplate.pValue );
113 		return( pkcs11MapError( status, CRYPT_ERROR_NOTFOUND ) );
114 		}
115 	*value = valueTemplate.pValue;
116 	*valueLength = valueTemplate.ulValueLen;
117 
118 	return( CRYPT_OK );
119 	}
120 
121 STDC_NONNULL_ARG( ( 1, 2 ) ) \
getAttributeValueEnd(IN void * value,const void * valueBuffer)122 static void getAttributeValueEnd( IN void *value,
123 								  const void *valueBuffer )
124 	{
125 	assert( isReadPtr( value, 16 ) );
126 	assert( isReadPtr( valueBuffer, 16 ) );
127 
128 	if( value != valueBuffer )
129 		clFree( "getAttributeValueEnd", value );
130 	}
131 
132 /* Get the label for an object, truncating overly long labels if required.
133    We can't use a dynBuf for this because it's a PKCS #11 attribute rather
134    than a cryptlib attribute */
135 
136 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 5 ) ) \
137 static int getObjectLabel( INOUT PKCS11_INFO *pkcs11Info,
138 						   const CK_OBJECT_HANDLE hObject,
139 						   OUT_BUFFER( maxLabelSize, *labelLength ) \
140 								char *label,
141 						   IN_LENGTH_SHORT_MIN( 16 ) \
142 								const int maxLabelSize,
143 						   OUT_LENGTH_BOUNDED_Z( maxLabelSize ) \
144 								int *labelLength )
145 	{
146 	char labelBuffer[ CRYPT_MAX_TEXTSIZE + 8 ], *localLabel;
147 	int localLabelLength, cryptStatus;
148 
149 	assert( isWritePtr( pkcs11Info, sizeof( PKCS11_INFO ) ) );
150 	assert( isWritePtr( label, maxLabelSize ) );
151 	assert( isWritePtr( labelLength, sizeof( int ) ) );
152 
153 	REQUIRES( maxLabelSize >= 16 && maxLabelSize < MAX_INTLENGTH_SHORT );
154 
155 	/* Clear return values */
156 	memset( label, 0, maxLabelSize );
157 	*labelLength = 0;
158 
159 	cryptStatus = getAttributeValue( pkcs11Info, hObject, CKA_LABEL,
160 									 &localLabel, &localLabelLength,
161 									 labelBuffer, CRYPT_MAX_TEXTSIZE );
162 	if( cryptStatusError( cryptStatus ) )
163 		return( cryptStatus );
164 	*labelLength = min( localLabelLength, maxLabelSize );
165 	REQUIRES( *labelLength > 0 && *labelLength < MAX_INTLENGTH_SHORT );
166 	memcpy( label, localLabel, *labelLength );
167 	getAttributeValueEnd( localLabel, labelBuffer );
168 
169 	return( CRYPT_OK );
170 	}
171 
172 /* Read a flag for an object.  An absent value is treated as FALSE */
173 
174 CHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \
readFlag(const PKCS11_INFO * pkcs11Info,const CK_OBJECT_HANDLE hObject,const CK_ATTRIBUTE_TYPE flagType)175 static BOOLEAN readFlag( const PKCS11_INFO *pkcs11Info,
176 						 const CK_OBJECT_HANDLE hObject,
177 						 const CK_ATTRIBUTE_TYPE flagType )
178 	{
179 	CK_BBOOL bFlag = FALSE;
180 	CK_ATTRIBUTE flagTemplate = { flagType, &bFlag, sizeof( CK_BBOOL ) };
181 
182 	assert( isReadPtr( pkcs11Info, sizeof( PKCS11_INFO ) ) );
183 
184 	/* Some buggy implementations return CKR_OK but forget to set the
185 	   data value in the template (!!!) so we have to initialise bFlag
186 	   to a default of FALSE to handle this */
187 	return( ( C_GetAttributeValue( pkcs11Info->hSession, hObject,
188 								   &flagTemplate, 1 ) == CKR_OK && bFlag ) ? \
189 			TRUE : FALSE );
190 	}
191 
192 /* Get the permitted-action flags for an object */
193 
CHECK_RETVAL_RANGE(ACTION_PERM_FLAG_NONE,ACTION_PERM_FLAG_MAX)194 CHECK_RETVAL_RANGE( ACTION_PERM_FLAG_NONE, ACTION_PERM_FLAG_MAX ) STDC_NONNULL_ARG( ( 1 ) ) \
195 int getActionFlags( INOUT PKCS11_INFO *pkcs11Info,
196 					const CK_OBJECT_HANDLE hObject,
197 					IN_ENUM( KEYMGMT_ITEM ) const KEYMGMT_ITEM_TYPE itemType,
198 					IN_ALGO const CRYPT_ALGO_TYPE cryptAlgo )
199 	{
200 	const BOOLEAN checkSign = ( isSigAlgo( cryptAlgo ) || \
201 								isMacAlgo( cryptAlgo ) ) ? \
202 							  TRUE : FALSE;
203 	const BOOLEAN checkCrypt = ( isCryptAlgo( cryptAlgo ) || \
204 								 isConvAlgo( cryptAlgo ) ) ? \
205 							   TRUE : FALSE;
206 	const BOOLEAN checkWrap = isCryptAlgo( cryptAlgo );
207 	BOOLEAN cryptAllowed = FALSE, sigAllowed = FALSE;
208 	int actionFlags = 0;
209 
210 	assert( isWritePtr( pkcs11Info, sizeof( PKCS11_INFO ) ) );
211 
212 	REQUIRES( itemType == KEYMGMT_ITEM_PUBLICKEY || \
213 			  itemType == KEYMGMT_ITEM_PRIVATEKEY || \
214 			  itemType == KEYMGMT_ITEM_SECRETKEY );
215 	REQUIRES( cryptAlgo >= CRYPT_ALGO_FIRST_CONVENTIONAL && \
216 			  cryptAlgo <= CRYPT_ALGO_LAST_MAC );
217 
218 	/* Get the permitted actions for the object.  Some devices report bogus
219 	   capabilities (for example encrypt for a MAC object) so we restrict
220 	   the actions that we check for to try and weed out false positives.
221 	   The kernel won't allow the setting of an invalid action anyway, but
222 	   it's better to be safe here.
223 
224 	   We also have to provide special translation for the sign and sig-
225 	   check action flags, PKCS #11 treats the MAC operation as a member
226 	   of the signature family while cryptlib treats it as a member of the
227 	   hash family so if we get a sign/sigcheck permitted action for a MAC
228 	   object we map it to a hash permitted action */
229 	if( ( checkCrypt && readFlag( pkcs11Info, hObject, CKA_ENCRYPT ) ) || \
230 		( checkWrap && readFlag( pkcs11Info, hObject, CKA_WRAP ) ) )
231 		{
232 		actionFlags |= MK_ACTION_PERM( MESSAGE_CTX_ENCRYPT, ACTION_PERM_ALL );
233 		cryptAllowed = TRUE;
234 		}
235 	if( ( checkCrypt && itemType != KEYMGMT_ITEM_PUBLICKEY && \
236 		  readFlag( pkcs11Info, hObject, CKA_DECRYPT ) ) || \
237 		( checkWrap && itemType == KEYMGMT_ITEM_PRIVATEKEY && \
238 		  readFlag( pkcs11Info, hObject, CKA_UNWRAP ) ) )
239 		{
240 		actionFlags |= MK_ACTION_PERM( MESSAGE_CTX_DECRYPT, ACTION_PERM_ALL );
241 		cryptAllowed = TRUE;
242 		}
243 	if( checkSign && itemType != KEYMGMT_ITEM_PUBLICKEY && \
244 		readFlag( pkcs11Info, hObject, CKA_SIGN ) )
245 		{
246 		if( isMacAlgo( cryptAlgo ) )
247 			actionFlags |= MK_ACTION_PERM( MESSAGE_CTX_HASH, ACTION_PERM_ALL );
248 		else
249 			actionFlags |= MK_ACTION_PERM( MESSAGE_CTX_SIGN, ACTION_PERM_ALL );
250 		sigAllowed = TRUE;
251 		}
252 	if( checkSign && readFlag( pkcs11Info, hObject, CKA_VERIFY ) )
253 		{
254 		if( isMacAlgo( cryptAlgo ) )
255 			actionFlags |= MK_ACTION_PERM( MESSAGE_CTX_HASH, ACTION_PERM_ALL );
256 		else
257 			actionFlags |= MK_ACTION_PERM( MESSAGE_CTX_SIGCHECK, ACTION_PERM_ALL );
258 		sigAllowed = TRUE;
259 		}
260 	if( cryptAlgo == CRYPT_ALGO_RSA )
261 		{
262 		/* If there are any restrictions on the key usage then we have to
263 		   make it internal-only because of RSA's signature/encryption
264 		   duality */
265 		if( !( cryptAllowed && sigAllowed ) )
266 			actionFlags = MK_ACTION_PERM_NONE_EXTERNAL( actionFlags );
267 		}
268 	else
269 		{
270 		if( isDlpAlgo( cryptAlgo ) || isEccAlgo( cryptAlgo ) )
271 			{
272 			/* Because of the special-case data formatting requirements for
273 			   DLP/ECDLP algorithms we make the usage internal-only */
274 			actionFlags = MK_ACTION_PERM_NONE_EXTERNAL( actionFlags );
275 			}
276 		}
277 
278 	return( actionFlags );
279 	}
280 
281 /* Get cryptlib algorithm and capability information for a PKCS #11 object */
282 
283 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 5, 6 ) ) \
getMechanismInfo(const PKCS11_INFO * pkcs11Info,const CK_OBJECT_HANDLE hObject,const void * capabilityInfoList,const BOOLEAN isPKC,const CAPABILITY_INFO ** capabilityInfoPtrPtr,OUT_ALGO_Z CRYPT_ALGO_TYPE * cryptAlgo)284 static int getMechanismInfo( const PKCS11_INFO *pkcs11Info,
285 							 const CK_OBJECT_HANDLE hObject,
286 							 const void *capabilityInfoList,
287 							 const BOOLEAN isPKC,
288 							 const CAPABILITY_INFO **capabilityInfoPtrPtr,
289 							 OUT_ALGO_Z CRYPT_ALGO_TYPE *cryptAlgo )
290 	{
291 	CK_KEY_TYPE keyType DUMMY_INIT;
292 	CK_ATTRIBUTE keyTypeTemplate = \
293 		{ CKA_KEY_TYPE, ( CK_VOID_PTR ) &keyType, sizeof( CK_KEY_TYPE ) };
294 	CK_RV status;
295 	const CAPABILITY_INFO *capabilityInfoPtr;
296 	const PKCS11_MECHANISM_INFO *mechanismInfoPtr;
297 	int mechanismInfoSize, i;
298 
299 	assert( isReadPtr( pkcs11Info, sizeof( PKCS11_INFO ) ) );
300 	assert( isReadPtr( capabilityInfoPtrPtr, sizeof( CAPABILITY_INFO ) ) );
301 	assert( isWritePtr( cryptAlgo, sizeof( CRYPT_ALGO_TYPE ) ) );
302 
303 	REQUIRES( capabilityInfoList != NULL );
304 
305 	/* Clear return values */
306 	*capabilityInfoPtrPtr = NULL;
307 	*cryptAlgo = CRYPT_ALGO_NONE;
308 
309 	/* Get the key type (equivalent to the cryptlib algoID) for this
310 	   object */
311 	status = C_GetAttributeValue( pkcs11Info->hSession, hObject,
312 								  &keyTypeTemplate, 1 );
313 	if( status != CKR_OK )
314 		{
315 		DEBUG_DIAG(( "Couldn't read CKA_KEY_TYPE" ));
316 		assert( DEBUG_WARN );
317 		return( CRYPT_ERROR_FAILED );
318 		}
319 
320 	/* Hack for PKCS #11's broken HMAC "support", PKCS #11 has no HMAC
321 	   object types so if we find a generic secret key object we assume that
322 	   it's an HMAC-SHA1 object, the most common type */
323 	if( keyType == CKK_GENERIC_SECRET )
324 		{
325 		*cryptAlgo = CRYPT_ALGO_HMAC_SHA1;
326 		capabilityInfoPtr = findCapabilityInfo( capabilityInfoList,
327 												*cryptAlgo );
328 		if( capabilityInfoPtr == NULL )
329 			return( CRYPT_ERROR_NOTAVAIL );
330 		*capabilityInfoPtrPtr = capabilityInfoPtr;
331 
332 		return( CRYPT_OK );
333 		}
334 
335 	/* Get the equivalent cryptlib algorithm type and use that to get the
336 	   capability information for the algorithm */
337 	if( isPKC )
338 		mechanismInfoPtr = getMechanismInfoPKC( &mechanismInfoSize );
339 	else
340 		mechanismInfoPtr = getMechanismInfoConv( &mechanismInfoSize );
341 	for( i = 0; i < mechanismInfoSize && \
342 				mechanismInfoPtr[ i ].keyType != keyType; i++ );
343 	if( i >= mechanismInfoSize )
344 		{
345 		/* If we can't find a match for the PKCS #11 algorithm type in the
346 		   list of mechanisms then we're trying to instantiate an object
347 		   that uses an unsupported algorithm type */
348 		DEBUG_DIAG(( "Tried to read object with unsupported PKCS #11 "
349 					 "algorithm type %d", keyType ));
350 		return( CRYPT_ERROR_NOTAVAIL );
351 		}
352 	mechanismInfoPtr = &mechanismInfoPtr[ i ];
353 	*cryptAlgo = mechanismInfoPtr->cryptAlgo;
354 	capabilityInfoPtr = findCapabilityInfo( capabilityInfoList, *cryptAlgo );
355 	if( capabilityInfoPtr == NULL )
356 		return( CRYPT_ERROR_NOTAVAIL );
357 	*capabilityInfoPtrPtr = capabilityInfoPtr;
358 
359 	return( CRYPT_OK );
360 	}
361 
362 #if defined( USE_ECDH ) || defined( USE_ECDSA )
363 
364 /* Get the named curve type for an ECC object */
365 
366 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \
getEccCurveType(INOUT PKCS11_INFO * pkcs11Info,const CK_OBJECT_HANDLE hObject,OUT_ENUM_OPT (CRYPT_ECCCURVE)CRYPT_ECCCURVE_TYPE * curveType)367 int getEccCurveType( INOUT PKCS11_INFO *pkcs11Info,
368 					 const CK_OBJECT_HANDLE hObject,
369 					 OUT_ENUM_OPT( CRYPT_ECCCURVE ) \
370 						CRYPT_ECCCURVE_TYPE *curveType )
371 	{
372 	CRYPT_ECCCURVE_TYPE curve;
373 	STREAM stream;
374 	BYTE ecOidBuffer[ MAX_OID_SIZE + 8 ], *ecOid;
375 	int ecOidLength, cryptStatus;
376 
377 	assert( isWritePtr( curveType, sizeof( CRYPT_ECCCURVE_TYPE ) ) );
378 
379 	/* Clear return value */
380 	*curveType = CRYPT_ECCCURVE_NONE;
381 
382 	/* ECC algorithms are a serious pain, the only parameter that we have
383 	   available for them is CKA_EC_PARAMS, an OID for the curve that's
384 	   being used.  In order to get the curve type from that we have to read
385 	   the OID and then convert it to the named-curve type */
386 	cryptStatus = getAttributeValue( pkcs11Info, hObject, CKA_EC_PARAMS,
387 									 &ecOid, &ecOidLength, ecOidBuffer,
388 									 MAX_OID_SIZE );
389 	if( cryptStatusError( cryptStatus ) )
390 		return( cryptStatus );
391 	sMemConnect( &stream, ecOid, ecOidLength );
392 	cryptStatus = readECCOID( &stream, &curve );
393 	sMemDisconnect( &stream );
394 	getAttributeValueEnd( ecOid, ecOidBuffer );
395 	if( cryptStatusOK( cryptStatus ) )
396 		*curveType = curve;
397 
398 	return( cryptStatus );
399 	}
400 #endif /* USE_ECDH || USE_ECDSA */
401 
402 /****************************************************************************
403 *																			*
404 *						 Template Manipulation Routines						*
405 *																			*
406 ****************************************************************************/
407 
408 /* Add the components of an issuerAndSerialnumber to a certificate
409    template */
410 
411 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \
readIAndS(INOUT STREAM * stream,INOUT CK_ATTRIBUTE * certTemplateI,INOUT CK_ATTRIBUTE * certTemplateS)412 static int readIAndS( INOUT STREAM *stream,
413 					  INOUT CK_ATTRIBUTE *certTemplateI,
414 					  INOUT CK_ATTRIBUTE *certTemplateS )
415 	{
416 	void *dataPtr DUMMY_INIT_PTR;
417 	int length, cryptStatus;
418 
419 	assert( isWritePtr( stream, sizeof( STREAM ) ) );
420 	assert( isWritePtr( certTemplateI, sizeof( CK_ATTRIBUTE ) ) );
421 	assert( isWritePtr( certTemplateS, sizeof( CK_ATTRIBUTE ) ) );
422 
423 	/* We don't clear the return values since these have already been
424 	   partially initialised with attribute information by the caller */
425 
426 	/* Read the wrapper tag */
427 	cryptStatus = readSequence( stream, NULL );
428 	if( cryptStatusError( cryptStatus ) )
429 		return( cryptStatus );
430 
431 	/* Read the issuer DN and add it to the template */
432 	cryptStatus = getStreamObjectLength( stream, &length );
433 	if( cryptStatusOK( cryptStatus ) )
434 		{
435 		certTemplateI->ulValueLen = length;
436 		cryptStatus = sMemGetDataBlock( stream, &dataPtr, length );
437 		}
438 	if( cryptStatusOK( cryptStatus ) )
439 		{
440 		certTemplateI->pValue = dataPtr;
441 		cryptStatus = sSkip( stream, length, MAX_INTLENGTH_SHORT );
442 		}
443 	if( cryptStatusError( cryptStatus ) )
444 		return( cryptStatus );
445 
446 	/* Read the serial number and add it to the template */
447 	cryptStatus = getStreamObjectLength( stream, &length );
448 	if( cryptStatusOK( cryptStatus ) )
449 		{
450 		certTemplateS->ulValueLen = length;
451 		cryptStatus = sMemGetDataBlock( stream, &dataPtr, length );
452 		}
453 	if( cryptStatusOK( cryptStatus ) )
454 		{
455 		certTemplateS->pValue = dataPtr;
456 		cryptStatus = sSkip( stream, length, MAX_INTLENGTH_SHORT );
457 		}
458 	return( cryptStatus );
459 	}
460 
461 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
462 int addIAndSToTemplate( INOUT_ARRAY_C( 2 ) CK_ATTRIBUTE *certTemplate,
463 						IN_BUFFER( iAndSLength ) const void *iAndSPtr,
464 						IN_LENGTH_SHORT const int iAndSLength )
465 	{
466 	STREAM stream;
467 	int cryptStatus;
468 
469 	assert( isWritePtr( certTemplate, sizeof( CK_ATTRIBUTE ) * 2 ) );
470 	assert( isReadPtr( iAndSPtr, iAndSLength ) );
471 
472 	REQUIRES( iAndSLength > 0 && iAndSLength < MAX_INTLENGTH_SHORT );
473 
474 	/* We don't clear the return value since this has already been
475 	   partially initialised with attribute information by the caller */
476 
477 	/* Parse the iAndS data and add it to the template */
478 	sMemConnect( &stream, iAndSPtr, iAndSLength );
479 	cryptStatus = readIAndS( &stream, &certTemplate[ 0 ],
480 							 &certTemplate[ 1 ] );
481 	sMemDisconnect( &stream );
482 	return( cryptStatus );
483 	}
484 
485 /* Set up a search template for an issuerAndSerialNumber.  Because Netscape
486    incorrectly used the raw serial number instead of the DER-encoded form
487    and other applications copied this, we also set up an alternative
488    template with the serial number in this alternative form that we fall
489    back to if a search using the correct form fails */
490 
491 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \
492 static int initIAndSTemplate( OUT_ARRAY_C( 4 ) CK_ATTRIBUTE *iAndSTemplate,
493 							  OUT_ARRAY_C( 4 ) CK_ATTRIBUTE *iAndSTemplateAlt,
494 							  IN_BUFFER( keyIDlength ) const void *keyID,
495 							  IN_LENGTH_KEYID const int keyIDlength )
496 	{
497 	static const CK_OBJECT_CLASS certClass = CKO_CERTIFICATE;
498 	static const CK_CERTIFICATE_TYPE certType = CKC_X_509;
499 	static const CK_ATTRIBUTE initTemplate[] = {
500 		{ CKA_CLASS, ( CK_VOID_PTR ) &certClass, sizeof( CK_OBJECT_CLASS ) },
501 		{ CKA_CERTIFICATE_TYPE, ( CK_VOID_PTR ) &certType, sizeof( CK_CERTIFICATE_TYPE ) },
502 		{ CKA_ISSUER, NULL_PTR, 0 },
503 		{ CKA_SERIAL_NUMBER, NULL_PTR, 0 }
504 		};
505 	STREAM stream;
506 	int offset DUMMY_INIT, length, cryptStatus;
507 
508 	assert( isWritePtr( iAndSTemplate, 4 * sizeof( CK_ATTRIBUTE ) ) );
509 	assert( isWritePtr( iAndSTemplateAlt, 4 * sizeof( CK_ATTRIBUTE ) ) );
510 	assert( isReadPtr( keyID, keyIDlength ) );
511 
512 	REQUIRES( keyIDlength >= MIN_NAME_LENGTH && \
513 			  keyIDlength < MAX_ATTRIBUTE_SIZE );
514 
515 	/* Set up the issuerAndSerialNumber template */
516 	memcpy( iAndSTemplate, initTemplate, 4 * sizeof( CK_ATTRIBUTE ) );
517 	cryptStatus = addIAndSToTemplate( &iAndSTemplate[ 2 ], keyID,
518 									  keyIDlength );
519 	if( cryptStatusError( cryptStatus ) )
520 		return( cryptStatus );
521 
522 	/* Set up the alternate template to the same as the main template, but
523 	   with the tag and length stripped from the serial number */
524 	memcpy( iAndSTemplateAlt, iAndSTemplate, 4 * sizeof( CK_ATTRIBUTE ) );
525 	sMemConnect( &stream, iAndSTemplateAlt[ 3 ].pValue,
526 				 iAndSTemplateAlt[ 3 ].ulValueLen );
527 	cryptStatus = readGenericHole( &stream, &length, 1, BER_INTEGER );
528 	if( cryptStatusOK( cryptStatus ) )
529 		offset = stell( &stream );
530 	sMemDisconnect( &stream );
531 	if( cryptStatusError( cryptStatus ) )
532 		return( cryptStatus );
533 	iAndSTemplateAlt[ 3 ].pValue = \
534 				( BYTE * ) iAndSTemplateAlt[ 3 ].pValue + offset;
535 	iAndSTemplateAlt[ 3 ].ulValueLen = length;
536 
537 	return( CRYPT_OK );
538 	}
539 
540 /****************************************************************************
541 *																			*
542 *						 	Certificate Import Routines						*
543 *																			*
544 ****************************************************************************/
545 
546 /* Instantiate a certificate object from a PKCS #11 object handle */
547 
548 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \
instantiateCert(INOUT PKCS11_INFO * pkcs11Info,const CK_OBJECT_HANDLE hCertificate,OUT_HANDLE_OPT CRYPT_CERTIFICATE * iCryptCert,const BOOLEAN createContext)549 static int instantiateCert( INOUT PKCS11_INFO *pkcs11Info,
550 							const CK_OBJECT_HANDLE hCertificate,
551 							OUT_HANDLE_OPT CRYPT_CERTIFICATE *iCryptCert,
552 							const BOOLEAN createContext )
553 	{
554 	MESSAGE_CREATEOBJECT_INFO createInfo;
555 	BYTE buffer[ MAX_STACK_BUFFER_SIZE + 8 ], *bufPtr;
556 	int length, cryptStatus;
557 
558 	assert( isWritePtr( pkcs11Info, sizeof( PKCS11_INFO ) ) );
559 	assert( isWritePtr( iCryptCert, sizeof( CRYPT_CERTIFICATE ) ) );
560 
561 	/* Clear return value */
562 	*iCryptCert = CRYPT_ERROR;
563 
564 	/* Fetch the certificate data into local memory.  We can't use a dynBuf
565 	   for this because it's a PKCS #11 attribute rather than a cryptlib
566 	   attribute */
567 	cryptStatus = getAttributeValue( pkcs11Info, hCertificate, CKA_VALUE,
568 									 &bufPtr, &length, buffer,
569 									 MAX_STACK_BUFFER_SIZE );
570 	if( cryptStatusError( cryptStatus ) )
571 		return( cryptStatus );
572 
573 	/* Import the certificate as a cryptlib object */
574 	setMessageCreateObjectIndirectInfoEx( &createInfo, bufPtr, length,
575 					CRYPT_CERTTYPE_CERTIFICATE, !createContext ? \
576 						KEYMGMT_FLAG_DATAONLY_CERT : KEYMGMT_FLAG_NONE );
577 	cryptStatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
578 								   IMESSAGE_DEV_CREATEOBJECT_INDIRECT,
579 								   &createInfo, OBJECT_TYPE_CERTIFICATE );
580 	getAttributeValueEnd( bufPtr, buffer );
581 	if( cryptStatusOK( cryptStatus ) )
582 		*iCryptCert = createInfo.cryptHandle;
583 	return( cryptStatus );
584 	}
585 
586 /* Get a certificate chain from a device */
587 
588 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 4 ) ) \
getCertChain(INOUT PKCS11_INFO * pkcs11Info,IN_HANDLE const CRYPT_DEVICE iCertSource,const CK_OBJECT_HANDLE hCertificate,OUT_HANDLE_OPT CRYPT_CERTIFICATE * iCryptCert,const BOOLEAN createContext)589 static int getCertChain( INOUT PKCS11_INFO *pkcs11Info,
590 						 IN_HANDLE const CRYPT_DEVICE iCertSource,
591 						 const CK_OBJECT_HANDLE hCertificate,
592 						 OUT_HANDLE_OPT CRYPT_CERTIFICATE *iCryptCert,
593 						 const BOOLEAN createContext )
594 	{
595 	CK_ATTRIBUTE idTemplate = \
596 		{ CKA_ID, NULL_PTR, 0 };
597 	CK_RV status;
598 	BYTE keyID[ MAX_STACK_BUFFER_SIZE + 8 ];
599 
600 	assert( isWritePtr( pkcs11Info, sizeof( PKCS11_INFO ) ) );
601 	assert( isWritePtr( iCryptCert, sizeof( CRYPT_CERTIFICATE ) ) );
602 
603 	REQUIRES( isHandleRangeValid( iCertSource ) );
604 
605 	/* Clear return value */
606 	*iCryptCert = CRYPT_ERROR;
607 
608 	/* Find the ID for this certificate */
609 	status = C_GetAttributeValue( pkcs11Info->hSession, hCertificate,
610 								  &idTemplate, 1 );
611 	if( status == CKR_OK && idTemplate.ulValueLen <= MAX_STACK_BUFFER_SIZE )
612 		{
613 		idTemplate.pValue = keyID;
614 		status = C_GetAttributeValue( pkcs11Info->hSession, hCertificate,
615 									  &idTemplate, 1 );
616 		}
617 	if( status != CKR_OK || idTemplate.ulValueLen > MAX_STACK_BUFFER_SIZE )
618 		{
619 		/* We couldn't get the ID to build the chain or it's too large to be
620 		   usable, we can at least still return the individual certificate */
621 		return( instantiateCert( pkcs11Info, hCertificate, iCryptCert,
622 								 createContext ) );
623 		}
624 
625 	/* Create the certificate chain via an indirect import */
626 	return( iCryptImportCertIndirect( iCryptCert, iCertSource,
627 							CRYPT_IKEYID_KEYID, keyID, idTemplate.ulValueLen,
628 							createContext ? KEYMGMT_FLAG_DATAONLY_CERT : 0 ) );
629 	}
630 
631 /****************************************************************************
632 *																			*
633 *						 		Find-Item Routines							*
634 *																			*
635 ****************************************************************************/
636 
637 /* Find an object based on a given template.  There are two variations of
638    this, one that finds one and only one object and the other that returns
639    the first object that it finds without treating the presence of multiple
640    objects as an error.
641 
642    The way in which this call works has special significance, there are PKCS
643    #11 implementations that don't allow any other calls during the init/find/
644    final sequence so the code is structured to always call them one after
645    the other without any intervening calls.  In addition some drivers are
646    confused over whether they're 1.x or 2.x and may or may not implement
647    C_FindObjectsFinal().  Because of this we call it if it exists, if it
648    doesn't then we assume that the driver can handle cleanup itself (this
649    situation shouldn't occur because we've checked for 1.x drivers earlier,
650    but there are one or two drivers where it does happen) */
651 
652 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \
653 static int findDeviceObjects( INOUT PKCS11_INFO *pkcs11Info,
654 							  OUT CK_OBJECT_HANDLE *hObject,
655 							  IN_ARRAY( templateCount ) \
656 								const CK_ATTRIBUTE *objectTemplate,
657 							  IN_RANGE( 1, 64 ) const CK_ULONG templateCount,
658 							  const BOOLEAN onlyOne )
659 	{
660 	CK_OBJECT_HANDLE hObjectArray[ 2 + 8 ];
661 	CK_ULONG ulObjectCount;
662 	CK_RV status;
663 
664 	assert( isWritePtr( pkcs11Info, sizeof( PKCS11_INFO ) ) );
665 	assert( isWritePtr( hObject, sizeof( CK_OBJECT_HANDLE  ) ) );
666 	assert( isReadPtr( objectTemplate, \
667 					   sizeof( CK_ATTRIBUTE ) * templateCount ) );
668 
669 	REQUIRES( templateCount >= 1 && templateCount <= 64 );
670 
671 	/* Clear return value */
672 	*hObject = CK_OBJECT_NONE;
673 
674 	status = C_FindObjectsInit( pkcs11Info->hSession,
675 								( CK_ATTRIBUTE_PTR ) objectTemplate,
676 								templateCount );
677 	if( status != CKR_OK )
678 		return( pkcs11MapError( status, CRYPT_ERROR_NOTFOUND ) );
679 	status = C_FindObjects( pkcs11Info->hSession, hObjectArray, 2,
680 							&ulObjectCount );
681 	if( C_FindObjectsFinal != NULL )
682 		C_FindObjectsFinal( pkcs11Info->hSession );
683 	if( status != CKR_OK )
684 		return( pkcs11MapError( status, CRYPT_ERROR_NOTFOUND ) );
685 	if( ulObjectCount <= 0 )
686 		return( CRYPT_ERROR_NOTFOUND );
687 	if( ulObjectCount > 1 && onlyOne )
688 		return( CRYPT_ERROR_DUPLICATE );
689 	*hObject = hObjectArray[ 0 ];
690 
691 	return( CRYPT_OK );
692 	}
693 
694 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \
695 int findObject( INOUT PKCS11_INFO *pkcs11Info,
696 				OUT CK_OBJECT_HANDLE *hObject,
697 				IN_ARRAY( templateCount ) \
698 					const CK_ATTRIBUTE *objectTemplate,
699 				IN_RANGE( 1, 64 ) const CK_ULONG templateCount )
700 	{
701 	assert( isWritePtr( pkcs11Info, sizeof( PKCS11_INFO ) ) );
702 	assert( isWritePtr( hObject, sizeof( CK_OBJECT_HANDLE  ) ) );
703 	assert( isReadPtr( objectTemplate, \
704 					   sizeof( CK_ATTRIBUTE ) * templateCount ) );
705 
706 	REQUIRES( templateCount >= 1 && templateCount <= 64 );
707 
708 	return( findDeviceObjects( pkcs11Info, hObject,
709 							   objectTemplate, templateCount, TRUE ) );
710 	}
711 
712 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \
713 int findObjectEx( INOUT PKCS11_INFO *pkcs11Info,
714 				  OUT CK_OBJECT_HANDLE *hObject,
715 				  IN_ARRAY( templateCount ) \
716 					const CK_ATTRIBUTE *objectTemplate,
717 				  IN_RANGE( 1, 64 ) const CK_ULONG templateCount )
718 	{
719 	assert( isWritePtr( pkcs11Info, sizeof( PKCS11_INFO ) ) );
720 	assert( isWritePtr( hObject, sizeof( CK_OBJECT_HANDLE  ) ) );
721 	assert( isReadPtr( objectTemplate, \
722 					   sizeof( CK_ATTRIBUTE ) * templateCount ) );
723 
724 	REQUIRES( templateCount >= 1 && templateCount <= 64 );
725 
726 	return( findDeviceObjects( pkcs11Info, hObject,
727 							   objectTemplate, templateCount, FALSE ) );
728 	}
729 
730 /* Find an object from a source object by matching IDs.  This is used to
731    find a key matching a certificate, a public key matching a private key,
732    or other objects with similar relationships */
733 
734 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 4 ) ) \
findObjectFromObject(INOUT PKCS11_INFO * pkcs11Info,const CK_OBJECT_HANDLE hSourceObject,const CK_OBJECT_CLASS objectClass,OUT CK_OBJECT_HANDLE * hObject)735 int findObjectFromObject( INOUT PKCS11_INFO *pkcs11Info,
736 						  const CK_OBJECT_HANDLE hSourceObject,
737 						  const CK_OBJECT_CLASS objectClass,
738 						  OUT CK_OBJECT_HANDLE *hObject )
739 	{
740 	CK_ATTRIBUTE keyTemplate[] = {
741 		{ CKA_CLASS, ( CK_VOID_PTR ) &objectClass, sizeof( CK_OBJECT_CLASS ) },
742 		{ CKA_ID, NULL_PTR, 0 }
743 		};
744 	BYTE buffer[ MAX_STACK_BUFFER_SIZE + 8 ], *bufPtr;
745 	int length, cryptStatus;
746 
747 	assert( isWritePtr( pkcs11Info, sizeof( PKCS11_INFO ) ) );
748 	assert( isWritePtr( hObject, sizeof( CK_OBJECT_HANDLE ) ) );
749 
750 	/* Clear return value */
751 	*hObject = CK_OBJECT_NONE;
752 
753 	/* We're looking for a key whose ID matches that of the source object,
754 	   read its certificate ID.  We can't use a dynBuf for this because it's
755 	   a PKCS #11 attribute rather than a cryptlib attribute */
756 	cryptStatus = getAttributeValue( pkcs11Info, hSourceObject, CKA_ID,
757 									 &bufPtr, &length, buffer,
758 									 MAX_STACK_BUFFER_SIZE );
759 	if( cryptStatusError( cryptStatus ) )
760 		return( cryptStatus );
761 
762 	/* Find the key object with the given ID */
763 	keyTemplate[ 1 ].pValue = bufPtr;
764 	keyTemplate[ 1 ].ulValueLen = length;
765 	cryptStatus = findObject( pkcs11Info, hObject, keyTemplate, 2 );
766 	getAttributeValueEnd( bufPtr, buffer );
767 
768 	return( cryptStatus );
769 	}
770 
771 /* Find a certificate object based on various search criteria:
772 
773 	- Find a certificate matching a supplied template - certFromTemplate()
774 	- Find a certificate matching a given label - certFromLabel()
775 	- Find a certificate matching a given ID - certFromID()
776 	- Find a certificate matching the ID of an object hObject - certFromObject()
777 	- Find any X.509 certificate - certFromLabel(), no label supplied.
778 
779   These are general-purpose functions whose behaviour can be modified through
780   the following action codes */
781 
782 typedef enum {
783 	FINDCERT_NONE,			/* No find-cert flag */
784 	FINDCERT_NORMAL,		/* Instantiate standard a certificate+context */
785 	FINDCERT_DATAONLY,		/* Instantiate data-only certificate */
786 	FINDCERT_P11OBJECT,		/* Return handle to PKCS #11 object */
787 	FINDCERT_LAST			/* Maximum possible flag value */
788 	} FINDCERT_ACTION_TYPE;
789 
790 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \
791 static int findCertFromTemplate( INOUT PKCS11_INFO *pkcs11Info,
792 								 IN_HANDLE const CRYPT_DEVICE iCertSource,
793 								 IN_ARRAY( templateCount ) \
794 									const CK_ATTRIBUTE *findTemplate,
795 								 IN_RANGE( 1, 64 ) const int templateCount,
796 								 OUT_OPT_HANDLE_OPT CRYPT_CERTIFICATE *iCryptCert,
797 								 OUT_OPT CK_OBJECT_HANDLE *hCertificate,
798 								 IN_ENUM( FINDCERT ) \
799 									const FINDCERT_ACTION_TYPE findAction )
800 	{
801 	CK_OBJECT_HANDLE hFindCertificate;
802 	int cryptStatus;
803 
804 	assert( isWritePtr( pkcs11Info, sizeof( PKCS11_INFO ) ) );
805 	assert( isReadPtr( findTemplate, \
806 					   sizeof( CK_ATTRIBUTE ) * templateCount ) );
807 	assert( ( isWritePtr( iCryptCert, sizeof( CRYPT_CERTIFICATE ) ) && \
808 			  hCertificate == NULL ) || \
809 			( iCryptCert == NULL && \
810 			  isWritePtr( hCertificate, sizeof( CK_OBJECT_HANDLE ) ) ) );
811 
812 	REQUIRES( isHandleRangeValid( iCertSource ) );
813 	REQUIRES( templateCount >= 1 && templateCount <= 64 );
814 	REQUIRES( ( iCryptCert != NULL && hCertificate == NULL ) || \
815 			  ( iCryptCert == NULL && hCertificate != NULL ) );
816 	REQUIRES( findAction > FINDCERT_NONE && findAction < FINDCERT_LAST );
817 
818 	/* Clear return values */
819 	if( iCryptCert != NULL )
820 		*iCryptCert = CRYPT_ERROR;
821 	if( hCertificate != NULL )
822 		*hCertificate = CK_OBJECT_NONE;
823 
824 	/* Try and find the certificate from the given template */
825 	cryptStatus = findObject( pkcs11Info, &hFindCertificate, findTemplate,
826 							  templateCount );
827 	if( cryptStatusError( cryptStatus ) )
828 		return( cryptStatus );
829 	if( findAction == FINDCERT_P11OBJECT )
830 		{
831 		*hCertificate = hFindCertificate;
832 		return( CRYPT_OK );
833 		}
834 
835 	return( getCertChain( pkcs11Info, iCertSource, hFindCertificate, iCryptCert,
836 						  ( findAction == FINDCERT_NORMAL ) ? TRUE : FALSE ) );
837 	}
838 
839 CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
findCertFromLabel(INOUT PKCS11_INFO * pkcs11Info,IN_HANDLE const CRYPT_DEVICE iCertSource,const CK_ATTRIBUTE_TYPE labelType,IN_BUFFER_OPT (labelLength)const char * label,IN_LENGTH_SHORT_Z const int labelLength,OUT_OPT_HANDLE_OPT CRYPT_CERTIFICATE * iCryptCert,OUT_OPT CK_OBJECT_HANDLE * hCertificate,IN_ENUM (FINDCERT)const FINDCERT_ACTION_TYPE findAction)840 static int findCertFromLabel( INOUT PKCS11_INFO *pkcs11Info,
841 							  IN_HANDLE const CRYPT_DEVICE iCertSource,
842 							  const CK_ATTRIBUTE_TYPE labelType,
843 							  IN_BUFFER_OPT( labelLength ) const char *label,
844 							  IN_LENGTH_SHORT_Z const int labelLength,
845 							  OUT_OPT_HANDLE_OPT CRYPT_CERTIFICATE *iCryptCert,
846 							  OUT_OPT CK_OBJECT_HANDLE *hCertificate,
847 							  IN_ENUM( FINDCERT ) \
848 									const FINDCERT_ACTION_TYPE findAction )
849 	{
850 	static const CK_OBJECT_CLASS certClass = CKO_CERTIFICATE;
851 	static const CK_CERTIFICATE_TYPE certType = CKC_X_509;
852 	CK_ATTRIBUTE certTemplate[] = {
853 		{ CKA_CLASS, ( CK_VOID_PTR ) &certClass, sizeof( CK_OBJECT_CLASS ) },
854 		{ CKA_CERTIFICATE_TYPE, ( CK_VOID_PTR ) &certType, sizeof( CK_CERTIFICATE_TYPE ) },
855 		{ CKA_LABEL, NULL, 0 }
856 		};
857 
858 	assert( isWritePtr( pkcs11Info, sizeof( PKCS11_INFO ) ) );
859 	assert( ( label == NULL && labelLength == 0 ) || \
860 			isReadPtr( label, labelLength ) );
861 	assert( ( isWritePtr( iCryptCert, sizeof( CRYPT_CERTIFICATE ) ) && \
862 			  hCertificate == NULL ) || \
863 			( iCryptCert == NULL && \
864 			  isWritePtr( hCertificate, sizeof( CK_OBJECT_HANDLE ) ) ) );
865 
866 	REQUIRES( isHandleRangeValid( iCertSource ) );
867 	REQUIRES( ( label == NULL && labelLength == 0 ) || \
868 			  ( label != NULL && \
869 				labelLength > 0 && labelLength < MAX_INTLENGTH_SHORT ) );
870 	REQUIRES( ( iCryptCert != NULL && hCertificate == NULL ) || \
871 			  ( iCryptCert == NULL && hCertificate != NULL ) );
872 	REQUIRES( findAction > FINDCERT_NONE && findAction < FINDCERT_LAST );
873 
874 	/* Clear return values */
875 	if( iCryptCert != NULL )
876 		*iCryptCert = CRYPT_ERROR;
877 	if( hCertificate != NULL )
878 		*hCertificate = CK_OBJECT_NONE;
879 
880 	/* Try and find the certificate with the given label if there's one
881 	   supplied.  Usually this is the CKA_LABEL but it can also be something
882 	   like a CKA_URL */
883 	if( label != NULL )
884 		{
885 		certTemplate[ 2 ].type = labelType;
886 		certTemplate[ 2 ].pValue = ( CK_VOID_PTR ) label;
887 		certTemplate[ 2 ].ulValueLen = labelLength;
888 		}
889 	return( findCertFromTemplate( pkcs11Info, iCertSource, certTemplate,
890 								  ( label == NULL ) ? 2 : 3, iCryptCert,
891 								  hCertificate, findAction ) );
892 	}
893 
894 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \
findCertFromID(INOUT PKCS11_INFO * pkcs11Info,IN_HANDLE const CRYPT_DEVICE iCertSource,IN_BUFFER (certIDlength)const void * certID,IN_LENGTH_SHORT const int certIDlength,OUT_OPT_HANDLE_OPT CRYPT_CERTIFICATE * iCryptCert,OUT_OPT CK_OBJECT_HANDLE * hCertificate,IN_ENUM (FINDCERT)const FINDCERT_ACTION_TYPE findAction)895 static int findCertFromID( INOUT PKCS11_INFO *pkcs11Info,
896 						   IN_HANDLE const CRYPT_DEVICE iCertSource,
897 						   IN_BUFFER( certIDlength ) const void *certID,
898 						   IN_LENGTH_SHORT const int certIDlength,
899 						   OUT_OPT_HANDLE_OPT CRYPT_CERTIFICATE *iCryptCert,
900 						   OUT_OPT CK_OBJECT_HANDLE *hCertificate,
901 						   IN_ENUM( FINDCERT ) \
902 								const FINDCERT_ACTION_TYPE findAction )
903 	{
904 	static const CK_OBJECT_CLASS certClass = CKO_CERTIFICATE;
905 	static const CK_CERTIFICATE_TYPE certType = CKC_X_509;
906 	CK_ATTRIBUTE certTemplate[] = {
907 		{ CKA_CLASS, ( CK_VOID_PTR ) &certClass, sizeof( CK_OBJECT_CLASS ) },
908 		{ CKA_CERTIFICATE_TYPE, ( CK_VOID_PTR ) &certType, sizeof( CK_CERTIFICATE_TYPE ) },
909 		{ CKA_ID, ( CK_VOID_PTR ) certID, certIDlength }
910 		};
911 
912 	assert( isWritePtr( pkcs11Info, sizeof( PKCS11_INFO ) ) );
913 	assert( isReadPtr( certID, certIDlength ) );
914 	assert( ( isWritePtr( iCryptCert, sizeof( CRYPT_CERTIFICATE ) ) && \
915 			  hCertificate == NULL ) || \
916 			( iCryptCert == NULL && \
917 			  isWritePtr( hCertificate, sizeof( CK_OBJECT_HANDLE ) ) ) );
918 
919 	REQUIRES( isHandleRangeValid( iCertSource ) );
920 	REQUIRES( certIDlength > 0 && certIDlength < MAX_INTLENGTH_SHORT );
921 	REQUIRES( ( iCryptCert != NULL && hCertificate == NULL ) || \
922 			  ( iCryptCert == NULL && hCertificate != NULL ) );
923 	REQUIRES( findAction > FINDCERT_NONE && findAction < FINDCERT_LAST );
924 
925 	/* Clear return values */
926 	if( iCryptCert != NULL )
927 		*iCryptCert = CRYPT_ERROR;
928 	if( hCertificate != NULL )
929 		*hCertificate = CK_OBJECT_NONE;
930 
931 	/* Try and find the certificate with the given ID */
932 	return( findCertFromTemplate( pkcs11Info, iCertSource, certTemplate, 3,
933 								  iCryptCert, hCertificate, findAction ) );
934 	}
935 
936 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 4 ) ) \
findCertFromObject(INOUT PKCS11_INFO * pkcs11Info,IN_HANDLE const CRYPT_DEVICE iCertSource,const CK_OBJECT_HANDLE hObject,OUT_HANDLE_OPT CRYPT_CERTIFICATE * iCryptCert,IN_ENUM (FINDCERT)const FINDCERT_ACTION_TYPE findAction)937 static int findCertFromObject( INOUT PKCS11_INFO *pkcs11Info,
938 							   IN_HANDLE const CRYPT_DEVICE iCertSource,
939 							   const CK_OBJECT_HANDLE hObject,
940 							   OUT_HANDLE_OPT CRYPT_CERTIFICATE *iCryptCert,
941 							   IN_ENUM( FINDCERT ) \
942 									const FINDCERT_ACTION_TYPE findAction )
943 	{
944 	BYTE buffer[ MAX_STACK_BUFFER_SIZE + 8 ], *bufPtr;
945 	int length, cryptStatus;
946 
947 	assert( isWritePtr( pkcs11Info, sizeof( PKCS11_INFO ) ) );
948 	assert( isWritePtr( iCryptCert, sizeof( CRYPT_CERTIFICATE ) ) );
949 
950 	REQUIRES( isHandleRangeValid( iCertSource ) );
951 	REQUIRES( findAction > FINDCERT_NONE && findAction < FINDCERT_LAST );
952 
953 	/* Clear return value */
954 	*iCryptCert = CRYPT_ERROR;
955 
956 	/* We're looking for a certificate whose ID matches the object, read the
957 	   key ID from the device.  We can't use a dynBuf for this because it's a
958 	   PKCS #11 attribute rather than a cryptlib attribute */
959 	cryptStatus = getAttributeValue( pkcs11Info, hObject, CKA_ID, &bufPtr,
960 									 &length, buffer, MAX_STACK_BUFFER_SIZE );
961 	if( cryptStatusError( cryptStatus ) )
962 		return( cryptStatus );
963 
964 	/* Look for a certificate with the same ID as the key */
965 	cryptStatus = findCertFromID( pkcs11Info, iCertSource, bufPtr, length,
966 								  iCryptCert, NULL, findAction );
967 	getAttributeValueEnd( bufPtr, buffer );
968 	return( cryptStatus );
969 	}
970 
971 /* Find an object using a non-PKCS #11 ID.  This is a special-case function
972    that's used in rare situations where only incomplete PKCS #11 format
973    support is available in the underlying device, for example with a token
974    that's been initialised via CryptoAPI (which doesn't populate all of the
975    PKCS #11 fields) but which is now being accessed through a PKCS #11
976    driver.  It works by enumerating every object (of the required type,
977    which in this case is only certificates) in the token, creating a
978    cryptlib native object from them, and matching by the ID information
979    provided by cryptlib.
980 
981    Since this complex search function is used by both findCert() (which
982    always tries to return a complete certificate chain) and getFirst()/
983    getNext() (which are called indirectly by findCert() and which only
984    require a PKCS #11 certificate object handle to turn into a single
985    standalone certificate) we have to provide a dual-purpose interface,
986    one that returns a certificate chain when called from findCert() and a
987    second one that returns a PKCS #11 certificate object handle when called
988    from getFirst()/getNext() as called by findCert() */
989 
990 #ifdef PKCS11_FIND_VIA_CRYPTLIB
991 
992 CHECK_RETVAL STDC_NONNULL_ARG( ( 3 ) ) \
matchID(IN_HANDLE CRYPT_CERTIFICATE iCryptCert,IN_KEYID_OPT const CRYPT_KEYID_TYPE keyIDtype,IN_BUFFER (keyIDlength)const void * keyID,IN_LENGTH_KEYID const int keyIDlength)993 static int matchID( IN_HANDLE CRYPT_CERTIFICATE iCryptCert,
994 					IN_KEYID_OPT const CRYPT_KEYID_TYPE keyIDtype,
995 					IN_BUFFER( keyIDlength ) const void *keyID,
996 					IN_LENGTH_KEYID const int keyIDlength )
997 	{
998 	MESSAGE_DATA msgData;
999 	char buffer[ MAX_ATTRIBUTE_SIZE + 8 ];
1000 	int cryptStatus;
1001 
1002 	assert( isReadPtr( keyID, keyIDlength ) );
1003 
1004 	REQUIRES( isHandleRangeValid( iCryptCert ) );
1005 	REQUIRES( keyIDtype == CRYPT_KEYID_NAME || \
1006 			  keyIDtype == CRYPT_KEYID_URI || \
1007 			  keyIDtype == CRYPT_IKEYID_KEYID || \
1008 			  keyIDtype == CRYPT_IKEYID_ISSUERANDSERIALNUMBER || \
1009 			  keyIDtype == CRYPT_KEYID_NONE );
1010 			  /* _NONE is by subject DN, i.e. child.issuerDN */
1011 	REQUIRES( keyIDlength >= MIN_NAME_LENGTH && \
1012 			  keyIDlength < MAX_ATTRIBUTE_SIZE );
1013 
1014 	switch( keyIDtype )
1015 		{
1016 		case CRYPT_KEYID_NAME:
1017 			/* This identifier is usually an arbitrary user-defined label
1018 			   attached to the object, in the absence of this we use the
1019 			   certificate CN (or equivalent) as the item to match on.  This
1020 			   is consistent with the use in updateCertificate(), which sets
1021 			   the holder name as the PKCS #11 label when a new certificate
1022 			   is added (only explicitly-created public- or private-key
1023 			   objects have user-defined labels) */
1024 			setMessageData( &msgData, buffer, MAX_ATTRIBUTE_SIZE );
1025 			cryptStatus = krnlSendMessage( iCryptCert, IMESSAGE_GETATTRIBUTE_S,
1026 										   &msgData,
1027 										   CRYPT_IATTRIBUTE_HOLDERNAME );
1028 			if( cryptStatusError( cryptStatus ) )
1029 				return( cryptStatus );
1030 			if( msgData.length != keyIDlength || \
1031 				strCompare( msgData.data, keyID, keyIDlength ) )
1032 				return( CRYPT_ERROR_NOTFOUND );
1033 			return( CRYPT_OK );
1034 
1035 		case CRYPT_KEYID_URI:
1036 			setMessageData( &msgData, buffer, MAX_ATTRIBUTE_SIZE );
1037 			cryptStatus = krnlSendMessage( iCryptCert, IMESSAGE_GETATTRIBUTE_S,
1038 										   &msgData,
1039 										   CRYPT_IATTRIBUTE_HOLDERURI );
1040 			if( cryptStatusError( cryptStatus ) )
1041 				return( cryptStatus );
1042 			if( msgData.length != keyIDlength || \
1043 				strCompare( msgData.data, keyID, keyIDlength ) )
1044 				return( CRYPT_ERROR_NOTFOUND );
1045 			return( CRYPT_OK );
1046 
1047 		case CRYPT_IKEYID_KEYID:
1048 			setMessageData( &msgData, ( void * ) keyID, keyIDlength );
1049 			return( krnlSendMessage( iCryptCert, IMESSAGE_COMPARE, &msgData,
1050 									 MESSAGE_COMPARE_KEYID ) );
1051 
1052 		case CRYPT_IKEYID_ISSUERANDSERIALNUMBER:
1053 			setMessageData( &msgData, ( void * ) keyID, keyIDlength );
1054 			return( krnlSendMessage( iCryptCert, IMESSAGE_COMPARE, &msgData,
1055 									 MESSAGE_COMPARE_ISSUERANDSERIALNUMBER ) );
1056 
1057 		case CRYPT_KEYID_NONE:
1058 			/* This is a special-case code to used denote a match of the
1059 			   subject name, specifically the issuer DN of the child
1060 			   certificate (which is the next certificate's subject DN) when
1061 			   chain building */
1062 			setMessageData( &msgData, ( void * ) keyID, keyIDlength );
1063 			return( krnlSendMessage( iCryptCert, IMESSAGE_COMPARE, &msgData,
1064 									 MESSAGE_COMPARE_SUBJECT ) );
1065 
1066 		default:
1067 			retIntError();
1068 		}
1069 	retIntError();
1070 	}
1071 
1072 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 5 ) ) \
searchDeviceObjects(INOUT PKCS11_INFO * pkcs11Info,OUT_OPT_HANDLE_OPT CRYPT_CERTIFICATE * iCryptCert,OUT_OPT CK_OBJECT_HANDLE * hObject,IN_KEYID_OPT const CRYPT_KEYID_TYPE keyIDtype,IN_BUFFER (keyIDlength)const void * keyID,IN_LENGTH_KEYID const int keyIDlength,const BOOLEAN onlyOne)1073 static int searchDeviceObjects( INOUT PKCS11_INFO *pkcs11Info,
1074 								OUT_OPT_HANDLE_OPT CRYPT_CERTIFICATE *iCryptCert,
1075 								OUT_OPT CK_OBJECT_HANDLE *hObject,
1076 								IN_KEYID_OPT const CRYPT_KEYID_TYPE keyIDtype,
1077 								IN_BUFFER( keyIDlength ) const void *keyID,
1078 								IN_LENGTH_KEYID const int keyIDlength,
1079 								const BOOLEAN onlyOne )
1080 	{
1081 	static const CK_OBJECT_CLASS certClass = CKO_CERTIFICATE;
1082 	static const CK_CERTIFICATE_TYPE certType = CKC_X_509;
1083 	CK_ATTRIBUTE certTemplate[] = {
1084 		{ CKA_CLASS, ( CK_VOID_PTR ) &certClass, sizeof( CK_OBJECT_CLASS ) },
1085 		{ CKA_CERTIFICATE_TYPE, ( CK_VOID_PTR ) &certType, sizeof( CK_CERTIFICATE_TYPE ) },
1086 		};
1087 	CK_OBJECT_HANDLE hMatchedObject = CK_OBJECT_NONE;
1088 	CK_ULONG ulObjectCount;
1089 	CK_RV status;
1090 	CRYPT_CERTIFICATE iMatchedCert = CRYPT_ERROR;
1091 	BOOLEAN foundMatch = FALSE;
1092 	int i, cryptStatus = CRYPT_ERROR_NOTFOUND;
1093 
1094 	assert( isWritePtr( pkcs11Info, sizeof( PKCS11_INFO ) ) );
1095 	assert( ( isWritePtr( iCryptCert, sizeof( CRYPT_CERTIFICATE ) ) && \
1096 			  hObject == NULL ) || \
1097 			( iCryptCert == NULL && \
1098 			  isWritePtr( hObject, sizeof( CK_OBJECT_HANDLE ) ) ) );
1099 	assert( isReadPtr( keyID, keyIDlength ) );
1100 
1101 	REQUIRES( ( iCryptCert != NULL && hObject == NULL ) || \
1102 			  ( iCryptCert == NULL && hObject != NULL ) );
1103 	REQUIRES( keyIDtype == CRYPT_KEYID_NAME || \
1104 			  keyIDtype == CRYPT_KEYID_URI || \
1105 			  keyIDtype == CRYPT_IKEYID_KEYID || \
1106 			  keyIDtype == CRYPT_IKEYID_ISSUERANDSERIALNUMBER || \
1107 			  keyIDtype == CRYPT_KEYID_NONE );
1108 			  /* _NONE is by subject DN, i.e. child.issuerDN */
1109 	REQUIRES( keyIDlength >= MIN_NAME_LENGTH && \
1110 			  keyIDlength < MAX_ATTRIBUTE_SIZE );
1111 
1112 	/* Clear return values */
1113 	if( iCryptCert != NULL )
1114 		*iCryptCert = CRYPT_ERROR;
1115 	if( hObject != NULL )
1116 		*hObject = CK_OBJECT_NONE;
1117 
1118 	status = C_FindObjectsInit( pkcs11Info->hSession,
1119 								( CK_ATTRIBUTE_PTR ) &certTemplate, 2 );
1120 	if( status != CKR_OK )
1121 		return( pkcs11MapError( status, CRYPT_ERROR_NOTFOUND ) );
1122 	for( i = 0; i < FAILSAFE_ITERATIONS_LARGE; i++ )
1123 		{
1124 		CK_OBJECT_HANDLE hMatchObject;
1125 		CRYPT_CERTIFICATE iMatchCert;
1126 
1127 		/* Try and get the next object of the requested type */
1128 		status = C_FindObjects( pkcs11Info->hSession, &hMatchObject, 1,
1129 								&ulObjectCount );
1130 		if( status != CKR_OK )
1131 			{
1132 			cryptStatus = pkcs11MapError( status, CRYPT_ERROR_NOTFOUND );
1133 			break;
1134 			}
1135 		if( ulObjectCount <= 0 )
1136 			{
1137 			cryptStatus = CRYPT_ERROR_NOTFOUND;
1138 			break;
1139 			}
1140 
1141 		/* Check whether this certificate meets the match criteria.  If
1142 		   we're matching on keyID we have to create the context associated
1143 		   with the certificate in order to calculate the keyID, otherwise
1144 		   we use a data-only certificate */
1145 		cryptStatus = instantiateCert( pkcs11Info, hMatchObject, &iMatchCert,
1146 									   ( keyIDtype == CRYPT_IKEYID_KEYID ) ? \
1147 											TRUE : FALSE );
1148 		if( cryptStatusError( cryptStatus ) )
1149 			{
1150 			/* We couldn't create a certificate from the stored data, this
1151 			   is a non-fatal error since there may be more objects present
1152 			   so we move on to those */
1153 			continue;
1154 			}
1155 		cryptStatus = matchID( iMatchCert, keyIDtype, keyID, keyIDlength );
1156 		if( cryptStatusOK( cryptStatus ) && !foundMatch )
1157 			{
1158 			/* We've found a matching certificate, remember it for later */
1159 			hMatchedObject = hMatchObject;
1160 			iMatchedCert = iMatchCert;
1161 			}
1162 		else
1163 			krnlSendNotifier( iMatchCert, IMESSAGE_DECREFCOUNT );
1164 		if( cryptStatusError( cryptStatus ) )
1165 			continue;
1166 
1167 		/* We've found a matching certificate, if we're looking for a first-
1168 		   match then we're done */
1169 		if( !onlyOne )
1170 			break;
1171 
1172 		/* We're only looking for one matching certificate, if we've found a
1173 		   second match then this is an error */
1174 		if( foundMatch )
1175 			{
1176 			krnlSendNotifier( iMatchedCert, IMESSAGE_DECREFCOUNT );
1177 			iMatchedCert = CRYPT_ERROR;
1178 			hMatchedObject = CK_OBJECT_NONE;
1179 			cryptStatus = CRYPT_ERROR_DUPLICATE;
1180 			break;
1181 			}
1182 		foundMatch = TRUE;
1183 		}
1184 	ENSURES( i < FAILSAFE_ITERATIONS_LARGE );
1185 	if( C_FindObjectsFinal != NULL )
1186 		C_FindObjectsFinal( pkcs11Info->hSession );
1187 
1188 	/* If we found a matching certificate, return it to the caller.  We
1189 	   can't directly return the status code since the last one encountered
1190 	   may have been a CRYPT_ERROR_NOTFOUND if we're checking for the
1191 	   existence of only a single certificate by enumerating all
1192 	   certificates present */
1193 	if( iMatchedCert != CRYPT_ERROR )
1194 		{
1195 		if( iCryptCert != NULL )
1196 			*iCryptCert = iMatchedCert;
1197 		else
1198 			{
1199 			krnlSendNotifier( iMatchedCert, IMESSAGE_DECREFCOUNT );
1200 			*hObject = hMatchedObject;
1201 			}
1202 		return( CRYPT_OK );
1203 		}
1204 	return( cryptStatus );
1205 	}
1206 #endif /* PKCS11_FIND_VIA_CRYPTLIB */
1207 
1208 /* Umbrella find-a-certificate function */
1209 
1210 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 4 ) ) \
findCert(INOUT PKCS11_INFO * pkcs11Info,IN_HANDLE const CRYPT_DEVICE iCertSource,IN_KEYID const CRYPT_KEYID_TYPE keyIDtype,IN_BUFFER (keyIDlength)const void * keyID,IN_LENGTH_KEYID const int keyIDlength,OUT_OPT_HANDLE_OPT CRYPT_CERTIFICATE * iCryptCert,OUT_OPT CK_OBJECT_HANDLE * hCertificate)1211 static int findCert( INOUT PKCS11_INFO *pkcs11Info,
1212 					 IN_HANDLE const CRYPT_DEVICE iCertSource,
1213 					 IN_KEYID const CRYPT_KEYID_TYPE keyIDtype,
1214 					 IN_BUFFER( keyIDlength ) const void *keyID,
1215 					 IN_LENGTH_KEYID const int keyIDlength,
1216 					 OUT_OPT_HANDLE_OPT CRYPT_CERTIFICATE *iCryptCert,
1217 					 OUT_OPT CK_OBJECT_HANDLE *hCertificate )
1218 	{
1219 	CK_ATTRIBUTE iAndSTemplate[ 4 + 8 ], iAndSTemplateAlt[ 4 + 8 ];
1220 #ifdef PKCS11_FIND_VIA_CRYPTLIB
1221 	CK_OBJECT_HANDLE hFindCertificate;
1222 #endif /* PKCS11_FIND_VIA_CRYPTLIB */
1223 	const FINDCERT_ACTION_TYPE findAction = \
1224 			( hCertificate != NULL ) ? FINDCERT_P11OBJECT : FINDCERT_NORMAL;
1225 	int cryptStatus;
1226 
1227 	assert( isWritePtr( pkcs11Info, sizeof( PKCS11_INFO ) ) );
1228 	assert( ( isWritePtr( iCryptCert, sizeof( CRYPT_CERTIFICATE ) ) && \
1229 			  hCertificate == NULL ) || \
1230 			( iCryptCert == NULL && \
1231 			  isWritePtr( hCertificate, sizeof( CK_OBJECT_HANDLE ) ) ) );
1232 
1233 	REQUIRES( isHandleRangeValid( iCertSource ) );
1234 	REQUIRES( keyIDtype == CRYPT_KEYID_NAME || \
1235 			  keyIDtype == CRYPT_KEYID_URI || \
1236 			  keyIDtype == CRYPT_IKEYID_KEYID || \
1237 			  keyIDtype == CRYPT_IKEYID_ISSUERANDSERIALNUMBER );
1238 	REQUIRES( keyIDlength >= MIN_NAME_LENGTH && \
1239 			  keyIDlength < MAX_ATTRIBUTE_SIZE );
1240 	REQUIRES( ( iCryptCert != NULL && hCertificate == NULL ) || \
1241 			  ( iCryptCert == NULL && hCertificate != NULL ) );
1242 
1243 	/* Clear return values */
1244 	if( iCryptCert != NULL )
1245 		*iCryptCert = CRYPT_ERROR;
1246 	if( hCertificate != NULL )
1247 		*hCertificate = CK_OBJECT_NONE;
1248 
1249 	switch( keyIDtype )
1250 		{
1251 		case CRYPT_IKEYID_ISSUERANDSERIALNUMBER:
1252 			cryptStatus = initIAndSTemplate( iAndSTemplate,
1253 											 iAndSTemplateAlt,
1254 											 keyID, keyIDlength );
1255 			if( cryptStatusError( cryptStatus ) )
1256 				return( cryptStatus );
1257 			cryptStatus = findCertFromTemplate( pkcs11Info, iCertSource,
1258 												iAndSTemplate, 4, iCryptCert,
1259 												NULL, findAction );
1260 			if( cryptStatus == CRYPT_ERROR_NOTFOUND )
1261 				cryptStatus = findCertFromTemplate( pkcs11Info, iCertSource,
1262 													iAndSTemplateAlt, 4, iCryptCert,
1263 													NULL, findAction );
1264 			if( cryptStatusOK( cryptStatus ) )
1265 				return( cryptStatus );
1266 			break;
1267 
1268 		case CRYPT_IKEYID_KEYID:
1269 			cryptStatus = findCertFromID( pkcs11Info, iCertSource,
1270 										  keyID, keyIDlength, iCryptCert,
1271 										  hCertificate, findAction );
1272 			if( cryptStatusOK( cryptStatus ) )
1273 				return( cryptStatus );
1274 			break;
1275 
1276 		case CRYPT_KEYID_NAME:
1277 		case CRYPT_KEYID_URI:
1278 			cryptStatus = findCertFromLabel( pkcs11Info, iCertSource,
1279 											 ( keyIDtype == CRYPT_KEYID_NAME ) ? \
1280 												CKA_LABEL : CKA_URL,
1281 											 keyID, keyIDlength, iCryptCert,
1282 											 hCertificate, findAction );
1283 			if( cryptStatus == CRYPT_ERROR_NOTFOUND )
1284 				{
1285 				/* Some devices use the iD in place of the label, if a
1286 				   search by label fails we try again with the label as the
1287 				   iD */
1288 				cryptStatus = findCertFromID( pkcs11Info, iCertSource,
1289 											  keyID, keyIDlength, iCryptCert,
1290 											  hCertificate, findAction );
1291 				}
1292 			if( cryptStatusOK( cryptStatus ) )
1293 				return( cryptStatus );
1294 			break;
1295 
1296 		default:
1297 			retIntError();
1298 		}
1299 
1300 	/* A standard search has failed, this may be because the necessary PKCS
1301 	   #11 ID information isn't present in the token, in which case we
1302 	   optionally try again by performing the search ourselves */
1303 #ifdef PKCS11_FIND_VIA_CRYPTLIB
1304 	cryptStatus = searchDeviceObjects( pkcs11Info, NULL, &hFindCertificate,
1305 									   keyIDtype, keyID, keyIDlength,
1306 									   TRUE );
1307 	if( cryptStatusOK( cryptStatus ) )
1308 		{
1309 		return( getCertChain( pkcs11Info, iCertSource, hFindCertificate,
1310 							  iCryptCert,
1311 							  ( findAction == FINDCERT_NORMAL ) ? \
1312 									TRUE : FALSE ) );
1313 		}
1314 #endif /* PKCS11_FIND_VIA_CRYPTLIB */
1315 
1316 	return( cryptStatus );
1317 	}
1318 
1319 /* Find a public- or private-key object.  Alongside the standard cryptlib
1320    status code we return an extended information code to handle the
1321    convoluted search strategy required in getItemFunction(), see the
1322    comments inline for the reason for the extra codes */
1323 
1324 typedef enum {
1325 	FIND_PUBPRIV_NONE,		/* No find-cert flag */
1326 	FIND_PUBPRIV_CERTVIAKEY,/* Key found via certificate */
1327 	FIND_PUBPRIV_KEYVIACERT,/* Certificate found via key */
1328 	FIND_PUBPRIV_LAST		/* Maximum possible flag value */
1329 	} FIND_PUBPRIV_TYPE;
1330 
1331 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3, 4, 6 ) ) \
findPubPrivKey(INOUT PKCS11_INFO * pkcs11Info,OUT CK_OBJECT_HANDLE * hObject,OUT CK_OBJECT_HANDLE * hCertificate,OUT_ENUM_OPT (FIND_PUBPRIV)FIND_PUBPRIV_TYPE * findType,IN_KEYID const CRYPT_KEYID_TYPE keyIDtype,IN_BUFFER_OPT (keyIDlength)const void * keyID,IN_LENGTH_KEYID_Z const int keyIDlength,const BOOLEAN isPublicKey)1332 static int findPubPrivKey( INOUT PKCS11_INFO *pkcs11Info,
1333 						   OUT CK_OBJECT_HANDLE *hObject,
1334 						   OUT CK_OBJECT_HANDLE *hCertificate,
1335 						   OUT_ENUM_OPT( FIND_PUBPRIV ) \
1336 								FIND_PUBPRIV_TYPE *findType,
1337 						   IN_KEYID const CRYPT_KEYID_TYPE keyIDtype,
1338 						   IN_BUFFER_OPT( keyIDlength ) const void *keyID,
1339 						   IN_LENGTH_KEYID_Z const int keyIDlength,
1340 						   const BOOLEAN isPublicKey )
1341 	{
1342 	static const CK_OBJECT_CLASS pubkeyClass = CKO_PUBLIC_KEY;
1343 	static const CK_OBJECT_CLASS privkeyClass = CKO_PRIVATE_KEY;
1344 	CK_ATTRIBUTE keyTemplate[] = {
1345 		{ CKA_CLASS, ( CK_VOID_PTR ) \
1346 					 ( isPublicKey ? &pubkeyClass : &privkeyClass ),
1347 										sizeof( CK_OBJECT_CLASS ) },
1348 		{ CKA_LABEL, ( CK_VOID_PTR ) keyID, keyIDlength }
1349 		};
1350 	int cryptStatus;
1351 
1352 	assert( isWritePtr( pkcs11Info, sizeof( PKCS11_INFO ) ) );
1353 	assert( isWritePtr( hObject, sizeof( CK_OBJECT_HANDLE ) ) );
1354 	assert( isWritePtr( hCertificate, sizeof( CK_OBJECT_HANDLE ) ) );
1355 	assert( isWritePtr( findType, sizeof( FIND_PUBPRIV_TYPE ) ) );
1356 	assert( isReadPtr( keyID, keyIDlength ) );
1357 
1358 	REQUIRES( keyIDtype == CRYPT_KEYID_NAME || \
1359 			  keyIDtype == CRYPT_KEYID_URI || \
1360 			  keyIDtype == CRYPT_IKEYID_KEYID );
1361 	REQUIRES( keyIDlength >= MIN_NAME_LENGTH && \
1362 			  keyIDlength < MAX_ATTRIBUTE_SIZE );
1363 
1364 	/* Clear return values */
1365 	*hObject = CK_OBJECT_NONE;
1366 	*hCertificate = CK_OBJECT_NONE;
1367 	*findType = FIND_PUBPRIV_NONE;
1368 
1369 	/* Try and find the object with the given label/ID, or the first object
1370 	   of the given class if no ID is given */
1371 	if( keyIDtype == CRYPT_IKEYID_KEYID )
1372 		keyTemplate[ 1 ].type = CKA_ID;
1373 	cryptStatus = findObject( pkcs11Info, hObject, keyTemplate, 2 );
1374 	if( cryptStatus != CRYPT_ERROR_NOTFOUND )
1375 		return( cryptStatus );
1376 
1377 	/* Some devices use the iD in place of the label, if we're doing a
1378 	   search by label and it fails then we try again with the label as
1379 	   the iD */
1380 	if( keyIDtype == CRYPT_KEYID_NAME )
1381 		{
1382 		keyTemplate[ 1 ].type = CKA_ID;
1383 		cryptStatus = findObject( pkcs11Info, hObject, keyTemplate, 2 );
1384 		keyTemplate[ 1 ].type = CKA_LABEL;
1385 		if( cryptStatus != CRYPT_ERROR_NOTFOUND )
1386 			return( cryptStatus );
1387 		}
1388 
1389 	/* Some devices may only contain private key objects with associated
1390 	   certificates that can't be picked out of the other cruft that's
1391 	   present without going via the private key, so if we're looking for a
1392 	   public key and don't find one we try again for a private key whose
1393 	   sole function is to point to an associated certificate */
1394 	if( isPublicKey )
1395 		{
1396 		keyTemplate[ 0 ].pValue = ( CK_VOID_PTR ) &privkeyClass;
1397 		cryptStatus = findObject( pkcs11Info, hObject, keyTemplate, 2 );
1398 		if( cryptStatusError( cryptStatus ) )
1399 			return( cryptStatus );
1400 
1401 		/* Tell the caller that although we've got a private key object we
1402 		   only need it to find the associated certificate and not finding
1403 		   an associated certificate is an error */
1404 		*findType = FIND_PUBPRIV_CERTVIAKEY;
1405 
1406 		return( CRYPT_OK );
1407 		}
1408 
1409 	/* A standard search has failed, this may be because the necessary PKCS
1410 	   #11 ID information isn't present in the token, in which case we
1411 	   optionally try again by performing the search ourselves */
1412 #ifdef PKCS11_FIND_VIA_CRYPTLIB
1413 	cryptStatus = searchDeviceObjects( pkcs11Info, NULL, hCertificate,
1414 									   keyIDtype, keyID, keyIDlength, TRUE );
1415 	if( cryptStatusError( cryptStatus ) )
1416 		return( cryptStatus );
1417 
1418 	/* We've found the identified certificate, use it to find the
1419 	   corresponding private key */
1420 	cryptStatus = findObjectFromObject( pkcs11Info, *hCertificate,
1421 										CKO_PRIVATE_KEY, hObject );
1422 	if( cryptStatusError( cryptStatus ) )
1423 		return( cryptStatus );
1424 
1425 	/* Tell the caller that we've already got a certificate to attach to
1426 	   the private key */
1427 	*findType = FIND_PUBPRIV_KEYVIACERT;
1428 
1429 	return( CRYPT_OK );
1430 #else
1431 	return( CRYPT_ERROR_NOTFOUND );
1432 #endif /* PKCS11_FIND_VIA_CRYPTLIB */
1433 	}
1434 
1435 /****************************************************************************
1436 *																			*
1437 *						 	Read an Item from a Device						*
1438 *																			*
1439 ****************************************************************************/
1440 
1441 /* Set public-key information (in the form of the SubjectPublicKeyInfo) for
1442    a native object */
1443 
1444 CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
setPublicComponents(INOUT PKCS11_INFO * pkcs11Info,IN_HANDLE const CRYPT_CONTEXT iCryptContext,const CK_OBJECT_HANDLE hObject,IN_ALGO const CRYPT_ALGO_TYPE cryptAlgo,const BOOLEAN isPrivateKey,const BOOLEAN nativeContext)1445 static int setPublicComponents( INOUT PKCS11_INFO *pkcs11Info,
1446 								IN_HANDLE const CRYPT_CONTEXT iCryptContext,
1447 								const CK_OBJECT_HANDLE hObject,
1448 								IN_ALGO const CRYPT_ALGO_TYPE cryptAlgo,
1449 								const BOOLEAN isPrivateKey,
1450 								const BOOLEAN nativeContext )
1451 	{
1452 	CK_OBJECT_HANDLE hPubKeyObject DUMMY_INIT;
1453 	int cryptStatus;
1454 
1455 	/* If it's an RSA object then we can set the public components from it
1456 	   directly */
1457 	if( cryptAlgo == CRYPT_ALGO_RSA )
1458 		return( rsaSetPublicComponents( pkcs11Info, iCryptContext, hObject,
1459 										nativeContext ) );
1460 
1461 	/* If we're creating a private-key object then we need to be able to set
1462 	   the SubjectPublicKeyInfo for it.  Only RSA allows us to access the
1463 	   public-key components from a private-key object, for everything else
1464 	   we need to locate a corresponding public-key object in order to get
1465 	   the public-key components */
1466 	if( isPrivateKey )
1467 		{
1468 		cryptStatus = findObjectFromObject( pkcs11Info, hObject,
1469 											CKO_PUBLIC_KEY, &hPubKeyObject );
1470 		if( cryptStatusError( cryptStatus ) )
1471 			return( cryptStatus );
1472 		}
1473 
1474 	/* Send the SubjectPublicKey information to the context */
1475 	switch( cryptAlgo )
1476 		{
1477 		case CRYPT_ALGO_DSA:
1478 			return( dsaSetPublicComponents( pkcs11Info, iCryptContext,
1479 											hPubKeyObject,
1480 											nativeContext ) );
1481 
1482 #if defined( USE_ECDSA )
1483 		case CRYPT_ALGO_ECDSA:
1484 			return( ecdsaSetPublicComponents( pkcs11Info, iCryptContext,
1485 											  hPubKeyObject,
1486 											  nativeContext ) );
1487 #endif /* USE_ECDSA */
1488 		}
1489 
1490 	return( CRYPT_ERROR_NOTAVAIL );
1491 	}
1492 
1493 /* Instantiate an object in a device.  This works like the create context
1494    function but instantiates a cryptlib object using data already contained
1495    in the device (for example public-key components stored with a private
1496    key or a stored certificate) */
1497 
1498 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
createNativeObject(INOUT PKCS11_INFO * pkcs11Info,OUT_HANDLE_OPT CRYPT_CONTEXT * iCryptContext,const CK_OBJECT_HANDLE hObject,IN_ENUM (KEYMGMT_ITEM)const KEYMGMT_ITEM_TYPE itemType,IN_ALGO const CRYPT_ALGO_TYPE cryptAlgo)1499 static int createNativeObject( INOUT PKCS11_INFO *pkcs11Info,
1500 							   OUT_HANDLE_OPT CRYPT_CONTEXT *iCryptContext,
1501 							   const CK_OBJECT_HANDLE hObject,
1502 							   IN_ENUM( KEYMGMT_ITEM ) \
1503 									const KEYMGMT_ITEM_TYPE itemType,
1504 							   IN_ALGO const CRYPT_ALGO_TYPE cryptAlgo )
1505 	{
1506 	CRYPT_CONTEXT iLocalContext;
1507 	MESSAGE_CREATEOBJECT_INFO createInfo;
1508 	int actionFlags, cryptStatus;
1509 
1510 	assert( isWritePtr( pkcs11Info, sizeof( PKCS11_INFO ) ) );
1511 	assert( isWritePtr( iCryptContext, sizeof( CRYPT_CONTEXT ) ) );
1512 
1513 	REQUIRES( itemType == KEYMGMT_ITEM_PUBLICKEY || \
1514 			  itemType == KEYMGMT_ITEM_PRIVATEKEY || \
1515 			  itemType == KEYMGMT_ITEM_SECRETKEY );
1516 	REQUIRES( cryptAlgo >= CRYPT_ALGO_FIRST_CONVENTIONAL && \
1517 			  cryptAlgo <= CRYPT_ALGO_LAST_MAC );
1518 
1519 	/* Clear return value */
1520 	*iCryptContext = CRYPT_ERROR;
1521 
1522 	/* Get the permitted-action flags for the object.  If no usage is
1523 	   allowed then we can't do anything with the object so we don't even
1524 	   try and create it */
1525 	actionFlags = getActionFlags( pkcs11Info, hObject, itemType, cryptAlgo );
1526 	if( actionFlags <= 0 )
1527 		return( CRYPT_ERROR_PERMISSION );
1528 
1529 	/* We're creating a public-key context, make it a native context instead
1530 	   of a device one.  This solves a variety of problems including the
1531 	   fact that some devices (which function purely as key stores coupled
1532 	   to modexp accelerators) only support private-key operations, that
1533 	   performing public-key operations natively is much, much faster than
1534 	   on any token, and finally that if we do it ourselves we can defend
1535 	   against a variety of RSA padding and timing attacks that have come up
1536 	   since the device firmware was done */
1537 	setMessageCreateObjectInfo( &createInfo, cryptAlgo );
1538 	cryptStatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
1539 								   IMESSAGE_DEV_CREATEOBJECT, &createInfo,
1540 								   OBJECT_TYPE_CONTEXT );
1541 	if( cryptStatusError( cryptStatus ) )
1542 		return( cryptStatus );
1543 	iLocalContext = createInfo.cryptHandle;
1544 
1545 	/* Send the SubjectPublicKeyInfo and action permissions for the
1546 	   context */
1547 	cryptStatus = setPublicComponents( pkcs11Info, iLocalContext, hObject,
1548 									   cryptAlgo,
1549 									   ( itemType == KEYMGMT_ITEM_PRIVATEKEY ) ? \
1550 										 TRUE : FALSE, TRUE );
1551 	if( cryptStatusOK( cryptStatus ) )
1552 		{
1553 		cryptStatus = krnlSendMessage( iLocalContext, IMESSAGE_SETATTRIBUTE,
1554 									   &actionFlags,
1555 									   CRYPT_IATTRIBUTE_ACTIONPERMS );
1556 		}
1557 	if( cryptStatusError( cryptStatus ) )
1558 		{
1559 		krnlSendNotifier( iLocalContext, IMESSAGE_DECREFCOUNT );
1560 		return( cryptStatus );
1561 		}
1562 	*iCryptContext = iLocalContext;
1563 
1564 	return( CRYPT_OK );
1565 	}
1566 
1567 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 7 ) ) \
createDeviceObject(INOUT PKCS11_INFO * pkcs11Info,OUT_HANDLE_OPT CRYPT_CONTEXT * iCryptContext,const CK_OBJECT_HANDLE hObject,IN_HANDLE_OPT const CRYPT_CERTIFICATE iCryptCert,IN_HANDLE const CRYPT_USER iOwnerHandle,IN_HANDLE const CRYPT_DEVICE iDeviceHandle,const CAPABILITY_INFO * capabilityInfoPtr,IN_ENUM (KEYMGMT_ITEM)const KEYMGMT_ITEM_TYPE itemType,IN_ALGO const CRYPT_ALGO_TYPE cryptAlgo,IN_RANGE (MIN_KEYSIZE,CRYPT_MAX_PKCSIZE)const int keySize)1568 static int createDeviceObject( INOUT PKCS11_INFO *pkcs11Info,
1569 							   OUT_HANDLE_OPT CRYPT_CONTEXT *iCryptContext,
1570 							   const CK_OBJECT_HANDLE hObject,
1571 							   IN_HANDLE_OPT const CRYPT_CERTIFICATE iCryptCert,
1572 							   IN_HANDLE const CRYPT_USER iOwnerHandle,
1573 							   IN_HANDLE const CRYPT_DEVICE iDeviceHandle,
1574 							   const CAPABILITY_INFO *capabilityInfoPtr,
1575 							   IN_ENUM( KEYMGMT_ITEM ) \
1576 									const KEYMGMT_ITEM_TYPE itemType,
1577 							   IN_ALGO const CRYPT_ALGO_TYPE cryptAlgo,
1578 							   IN_RANGE( MIN_KEYSIZE, CRYPT_MAX_PKCSIZE ) \
1579 									const int keySize )
1580 	{
1581 	CRYPT_CONTEXT iLocalContext;
1582 	MESSAGE_DATA msgData;
1583 	char label[ CRYPT_MAX_TEXTSIZE + 8 ];
1584 	int createFlags = CREATEOBJECT_FLAG_DUMMY;
1585 	int actionFlags, labelLength, cryptStatus;
1586 
1587 	assert( isWritePtr( pkcs11Info, sizeof( PKCS11_INFO ) ) );
1588 	assert( isWritePtr( iCryptContext, sizeof( CRYPT_CONTEXT ) ) );
1589 	assert( isReadPtr( capabilityInfoPtr, sizeof( CAPABILITY_INFO ) ) );
1590 
1591 	REQUIRES( ( iCryptCert == CRYPT_UNUSED ) || \
1592 			  isHandleRangeValid( iCryptCert ) );
1593 	REQUIRES( iOwnerHandle == DEFAULTUSER_OBJECT_HANDLE || \
1594 			  isHandleRangeValid( iOwnerHandle ) );
1595 	REQUIRES( isHandleRangeValid( iDeviceHandle ) );
1596 	REQUIRES( itemType == KEYMGMT_ITEM_PRIVATEKEY || \
1597 			  itemType == KEYMGMT_ITEM_SECRETKEY );
1598 	REQUIRES( cryptAlgo >= CRYPT_ALGO_FIRST_CONVENTIONAL && \
1599 			  cryptAlgo <= CRYPT_ALGO_LAST_MAC );
1600 	REQUIRES( keySize >= MIN_KEYSIZE && keySize <= CRYPT_MAX_PKCSIZE );
1601 
1602 	/* Clear return value */
1603 	*iCryptContext = CRYPT_ERROR;
1604 
1605 	/* Check whether this is a persistent object */
1606 	if( readFlag( pkcs11Info, hObject, CKA_TOKEN ) )
1607 		createFlags |= CREATEOBJECT_FLAG_PERSISTENT;
1608 
1609 	/* Get the permitted-action flags for the object */
1610 	actionFlags = getActionFlags( pkcs11Info, hObject, itemType, cryptAlgo );
1611 	if( actionFlags <= 0 )
1612 		{
1613 		/* If no usage is allowed then we can't do anything with the object
1614 		   so we don't even try to create it */
1615 		return( CRYPT_ERROR_PERMISSION );
1616 		}
1617 
1618 	/* Create a dummy context for the key and remember the device that it's
1619 	   contained in */
1620 	cryptStatus = getObjectLabel( pkcs11Info, hObject, label,
1621 								  CRYPT_MAX_TEXTSIZE, &labelLength );
1622 	if( cryptStatusError( cryptStatus ) )
1623 		return( cryptStatus );
1624 	if( labelLength <= 0 )
1625 		{
1626 		/* If there's no label present, use a dummy value */
1627 		strlcpy_s( label, CRYPT_MAX_TEXTSIZE, "Label-less PKCS #11 key" );
1628 		labelLength = 23;
1629 		}
1630 	cryptStatus = createContextFromCapability( &iLocalContext,
1631 							iOwnerHandle, capabilityInfoPtr,
1632 							createFlags | CREATEOBJECT_FLAG_PERSISTENT );
1633 	if( cryptStatusError( cryptStatus ) )
1634 		return( cryptStatus );
1635 	cryptStatus = krnlSendMessage( iLocalContext, IMESSAGE_SETDEPENDENT,
1636 								   ( MESSAGE_CAST ) &iDeviceHandle,
1637 								   SETDEP_OPTION_INCREF );
1638 	if( cryptStatusOK( cryptStatus ) )
1639 		cryptStatus = krnlSendMessage( iLocalContext, IMESSAGE_SETATTRIBUTE,
1640 									   &actionFlags,
1641 									   CRYPT_IATTRIBUTE_ACTIONPERMS );
1642 	if( cryptStatusError( cryptStatus ) )
1643 		{
1644 		krnlSendNotifier( iLocalContext, IMESSAGE_DECREFCOUNT );
1645 		return( cryptStatus );
1646 		}
1647 
1648 	/* Set the object's label.  This requires special care because the label
1649 	   that we're setting matches that of an existing object so trying to
1650 	   set it as a standard CRYPT_CTXINFO_LABEL will return a
1651 	   CRYPT_ERROR_DUPLICATE error when the context code checks for the
1652 	   existence of an existing label.  To handle this we use the attribute
1653 	   CRYPT_IATTRIBUTE_EXISTINGLABEL to indicate that we're setting a label
1654 	   that matches an existing object in the device */
1655 	setMessageData( &msgData, label, min( labelLength, CRYPT_MAX_TEXTSIZE ) );
1656 	cryptStatus = krnlSendMessage( iLocalContext, IMESSAGE_SETATTRIBUTE_S,
1657 								   &msgData, CRYPT_IATTRIBUTE_EXISTINGLABEL );
1658 	if( cryptStatusError( cryptStatus ) )
1659 		{
1660 		krnlSendNotifier( iLocalContext, IMESSAGE_DECREFCOUNT );
1661 		return( cryptStatus );
1662 		}
1663 
1664 	/* Send the keying information to the context.  For non-PKC contexts we
1665 	   only need to set the key length to let the user query the key size,
1666 	   for PKC contexts we also have to set the key components so that they
1667 	   can be written into certificates */
1668 	if( isPkcAlgo( cryptAlgo ) )
1669 		{
1670 		cryptStatus = setPublicComponents( pkcs11Info, iLocalContext,
1671 										   hObject, cryptAlgo, TRUE, FALSE );
1672 		}
1673 	else
1674 		{
1675 		cryptStatus = krnlSendMessage( iLocalContext, IMESSAGE_SETATTRIBUTE,
1676 									   ( MESSAGE_CAST ) &keySize,
1677 									   CRYPT_IATTRIBUTE_KEYSIZE );
1678 		}
1679 	if( cryptStatusError( cryptStatus ) )
1680 		{
1681 		krnlSendNotifier( iLocalContext, IMESSAGE_DECREFCOUNT );
1682 		return( cryptStatus );
1683 		}
1684 
1685 	/* Finally, record the handle for the device-internal key and mark it as
1686 	   initialised (i.e. with a key loaded) */
1687 	cryptStatus = krnlSendMessage( iLocalContext, IMESSAGE_SETATTRIBUTE,
1688 								   ( MESSAGE_CAST ) &hObject,
1689 								   CRYPT_IATTRIBUTE_DEVICEOBJECT );
1690 	if( cryptStatusOK( cryptStatus ) )
1691 		{
1692 		cryptStatus = krnlSendMessage( iLocalContext, IMESSAGE_SETATTRIBUTE,
1693 									   MESSAGE_VALUE_UNUSED,
1694 									   CRYPT_IATTRIBUTE_INITIALISED );
1695 		}
1696 	if( cryptStatusOK( cryptStatus ) && ( iCryptCert != CRYPT_UNUSED ) )
1697 		{
1698 		/* If it's a public key and there's a certificate present attach it
1699 		   to the context.  The certificate is an internal object used only
1700 		   by the context so we tell the kernel to mark it as owned by the
1701 		   context only */
1702 		cryptStatus = krnlSendMessage( iLocalContext, IMESSAGE_SETDEPENDENT,
1703 									   ( MESSAGE_CAST ) &iCryptCert,
1704 									   SETDEP_OPTION_NOINCREF );
1705 		}
1706 	if( cryptStatusError( cryptStatus ) )
1707 		{
1708 		krnlSendNotifier( iLocalContext, IMESSAGE_DECREFCOUNT );
1709 		return( cryptStatus );
1710 		}
1711 	*iCryptContext = iLocalContext;
1712 
1713 	return( CRYPT_OK );
1714 	}
1715 
1716 /* Get an item from a device and instantiate either a native or a device
1717    object from it */
1718 
1719 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3, 5 ) ) \
getSecretKey(INOUT DEVICE_INFO * deviceInfo,INOUT PKCS11_INFO * pkcs11Info,OUT_HANDLE_OPT CRYPT_HANDLE * iCryptHandle,IN_KEYID const CRYPT_KEYID_TYPE keyIDtype,IN_BUFFER (keyIDlength)const void * keyID,IN_LENGTH_KEYID const int keyIDlength,IN_FLAGS_Z (KEYMGMT)const int flags)1720 static int getSecretKey( INOUT DEVICE_INFO *deviceInfo,
1721 						 INOUT PKCS11_INFO *pkcs11Info,
1722 						 OUT_HANDLE_OPT CRYPT_HANDLE *iCryptHandle,
1723 						 IN_KEYID const CRYPT_KEYID_TYPE keyIDtype,
1724 						 IN_BUFFER( keyIDlength ) const void *keyID,
1725 						 IN_LENGTH_KEYID const int keyIDlength,
1726 						 IN_FLAGS_Z( KEYMGMT ) const int flags )
1727 	{
1728 	static const CK_OBJECT_CLASS secKeyClass = CKO_SECRET_KEY;
1729 	const CAPABILITY_INFO *capabilityInfoPtr;
1730 	CK_ULONG secKeySize DUMMY_INIT;
1731 	CK_ATTRIBUTE keyTemplate[] = {
1732 		{ CKA_CLASS, ( CK_VOID_PTR ) &secKeyClass, sizeof( CK_OBJECT_CLASS ) },
1733 		{ CKA_LABEL, NULL_PTR, 0 }
1734 		};
1735 	CK_ATTRIBUTE secKeySizeTemplate = \
1736 		{ CKA_VALUE_LEN, &secKeySize, sizeof( CK_ULONG ) };
1737 	CK_OBJECT_HANDLE hObject = CK_OBJECT_NONE;
1738 	CRYPT_ALGO_TYPE cryptAlgo;
1739 	int status, cryptStatus;
1740 
1741 	assert( isWritePtr( deviceInfo, sizeof( DEVICE_INFO ) ) );
1742 	assert( isWritePtr( pkcs11Info, sizeof( PKCS11_INFO ) ) );
1743 	assert( isWritePtr( iCryptHandle, sizeof( CRYPT_CONTEXT ) ) );
1744 	assert( isReadPtr( keyID, keyIDlength ) );
1745 
1746 	REQUIRES( keyIDtype == CRYPT_KEYID_NAME || \
1747 			  keyIDtype == CRYPT_IKEYID_KEYID );
1748 	REQUIRES( keyIDlength >= MIN_NAME_LENGTH && \
1749 			  keyIDlength < MAX_ATTRIBUTE_SIZE );
1750 	REQUIRES( flags >= KEYMGMT_FLAG_NONE && flags < KEYMGMT_FLAG_MAX );
1751 
1752 	/* Clear return value */
1753 	*iCryptHandle = CRYPT_ERROR;
1754 
1755 	/* Try and find the object with the given label/ID */
1756 	if( keyIDtype == CRYPT_IKEYID_KEYID )
1757 		keyTemplate[ 1 ].type = CKA_ID;
1758 	keyTemplate[ 1 ].pValue = ( CK_VOID_PTR ) keyID;
1759 	keyTemplate[ 1 ].ulValueLen = keyIDlength;
1760 	cryptStatus = findObject( pkcs11Info, &hObject, keyTemplate, 2 );
1761 	if( cryptStatus == CRYPT_ERROR_NOTFOUND )
1762 		{
1763 		/* Some devices use the iD in place of the label, if a search by
1764 		   label fails we try again with the label as the iD */
1765 		keyTemplate[ 1 ].type = CKA_ID;
1766 		cryptStatus = findObject( pkcs11Info, &hObject, keyTemplate, 2 );
1767 		}
1768 	if( cryptStatusError( cryptStatus ) )
1769 		return( cryptStatus );
1770 
1771 	/* If it's just an existence check, return now */
1772 	if( flags & KEYMGMT_FLAG_CHECK_ONLY )
1773 		return( CRYPT_OK );
1774 
1775 	/* We found something, map the key type to a cryptlib algorithm ID and
1776 	   find its capabilities */
1777 	cryptStatus = getMechanismInfo( pkcs11Info, hObject,
1778 									deviceInfo->capabilityInfoList,
1779 									FALSE, &capabilityInfoPtr,
1780 									&cryptAlgo );
1781 	if( cryptStatusError( cryptStatus ) )
1782 		return( cryptStatus );
1783 	status = C_GetAttributeValue( pkcs11Info->hSession, hObject,
1784 								  &secKeySizeTemplate, 1 );
1785 	if( status != CKR_OK )
1786 		return( pkcs11MapError( status, CRYPT_ERROR_NOTINITED ) );
1787 	ENSURES( secKeySize >= MIN_KEYSIZE && \
1788 			 secKeySize <= CRYPT_MAX_KEYSIZE );
1789 
1790 	/* Create the object as a device object */
1791 	return( createDeviceObject( pkcs11Info, iCryptHandle, hObject,
1792 								CRYPT_UNUSED, deviceInfo->ownerHandle,
1793 							    deviceInfo->objectHandle, capabilityInfoPtr,
1794 							    KEYMGMT_ITEM_SECRETKEY, cryptAlgo,
1795 								secKeySize ) );
1796 	}
1797 
1798 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 5, 8 ) ) \
getItemFunction(INOUT DEVICE_INFO * deviceInfo,OUT_HANDLE_OPT CRYPT_HANDLE * iCryptHandle,IN_ENUM (KEYMGMT_ITEM)const KEYMGMT_ITEM_TYPE itemType,IN_KEYID const CRYPT_KEYID_TYPE keyIDtype,IN_BUFFER (keyIDlength)const void * keyID,IN_LENGTH_KEYID const int keyIDlength,IN_OPT void * auxInfo,INOUT_LENGTH_SHORT_Z int * auxInfoLength,IN_FLAGS_Z (KEYMGMT)const int flags)1799 static int getItemFunction( INOUT DEVICE_INFO *deviceInfo,
1800 							OUT_HANDLE_OPT CRYPT_HANDLE *iCryptHandle,
1801 							IN_ENUM( KEYMGMT_ITEM ) \
1802 								const KEYMGMT_ITEM_TYPE itemType,
1803 							IN_KEYID const CRYPT_KEYID_TYPE keyIDtype,
1804 							IN_BUFFER( keyIDlength ) const void *keyID,
1805 							IN_LENGTH_KEYID const int keyIDlength,
1806 							IN_OPT void *auxInfo,
1807 							INOUT_LENGTH_SHORT_Z int *auxInfoLength,
1808 							IN_FLAGS_Z( KEYMGMT ) const int flags )
1809 	{
1810 	static const MAP_TABLE keySizeMapTbl[] = {
1811 		{ CRYPT_ALGO_RSA, CKA_MODULUS },
1812 		{ CRYPT_ALGO_DSA, CKA_PRIME },
1813 		{ CRYPT_ALGO_DH, CKA_PRIME },
1814 		{ CRYPT_ERROR, CRYPT_ERROR }, { CRYPT_ERROR, CRYPT_ERROR }
1815 		};
1816 	const CAPABILITY_INFO *capabilityInfoPtr;
1817 	CK_ATTRIBUTE keySizeTemplate = { 0, NULL, 0 };
1818 	CK_OBJECT_HANDLE hObject = CK_OBJECT_NONE, hCertificate = CK_OBJECT_NONE;
1819 	CK_RV status;
1820 	CRYPT_CERTIFICATE iCryptCert DUMMY_INIT;
1821 	CRYPT_ALGO_TYPE cryptAlgo;
1822 	PKCS11_INFO *pkcs11Info = deviceInfo->devicePKCS11;
1823 	BOOLEAN certViaPrivateKey = FALSE, privateKeyViaCert = FALSE;
1824 	BOOLEAN certPresent = FALSE;
1825 	int keySize DUMMY_INIT, cryptStatus;
1826 
1827 	assert( isWritePtr( deviceInfo, sizeof( DEVICE_INFO ) ) );
1828 	assert( isWritePtr( iCryptHandle, sizeof( CRYPT_CONTEXT ) ) );
1829 	assert( isReadPtr( keyID, keyIDlength ) );
1830 	assert( ( auxInfo == NULL && *auxInfoLength == 0 ) || \
1831 			isReadPtr( auxInfo, *auxInfoLength ) );
1832 
1833 	REQUIRES( itemType == KEYMGMT_ITEM_PUBLICKEY || \
1834 			  itemType == KEYMGMT_ITEM_PRIVATEKEY || \
1835 			  itemType == KEYMGMT_ITEM_SECRETKEY );
1836 	REQUIRES( keyIDtype == CRYPT_KEYID_NAME || \
1837 			  keyIDtype == CRYPT_KEYID_URI || \
1838 			  keyIDtype == CRYPT_IKEYID_KEYID || \
1839 			  keyIDtype == CRYPT_IKEYID_ISSUERANDSERIALNUMBER );
1840 	REQUIRES( keyIDlength >= MIN_NAME_LENGTH && \
1841 			  keyIDlength < MAX_ATTRIBUTE_SIZE );
1842 	REQUIRES( ( auxInfo == NULL && *auxInfoLength == 0 ) || \
1843 			  ( auxInfo != NULL && \
1844 				*auxInfoLength > 0 && \
1845 				*auxInfoLength < MAX_INTLENGTH_SHORT ) );
1846 	REQUIRES( flags >= KEYMGMT_FLAG_NONE && flags < KEYMGMT_FLAG_MAX );
1847 
1848 	/* Clear return value */
1849 	*iCryptHandle = CRYPT_ERROR;
1850 
1851 	/* If we're looking for a secret key then it's fairly straightforward */
1852 	if( itemType == KEYMGMT_ITEM_SECRETKEY )
1853 		{
1854 		return( getSecretKey( deviceInfo, pkcs11Info, iCryptHandle,
1855 							  keyIDtype, keyID, keyIDlength, flags ) );
1856 		}
1857 
1858 	/* If we're looking for a public key, try for a certificate first.  Some
1859 	   non-crypto-capable devices don't have an explicit CKO_PUBLIC_KEY but
1860 	   only a CKO_CERTIFICATE and some apps delete the public key since it's
1861 	   redundant, so we try to create a certificate object before we try
1862 	   anything else.  If the keyID type is an ID or label then this won't
1863 	   necessarily locate the certificate since it could be unlabelled or
1864 	   have a different label/ID, so if this fails we try again by going via
1865 	   the private key with the given label/ID */
1866 	if( itemType == KEYMGMT_ITEM_PUBLICKEY )
1867 		{
1868 		CK_OBJECT_HANDLE hCertificateLabelObject DUMMY_INIT;
1869 
1870 		if( flags & ( KEYMGMT_FLAG_CHECK_ONLY | KEYMGMT_FLAG_LABEL_ONLY ) )
1871 			{
1872 			cryptStatus = findCert( pkcs11Info, deviceInfo->objectHandle,
1873 									keyIDtype, keyID, keyIDlength, NULL,
1874 									&hCertificateLabelObject );
1875 			}
1876 		else
1877 			{
1878 			cryptStatus = findCert( pkcs11Info, deviceInfo->objectHandle,
1879 									keyIDtype, keyID, keyIDlength,
1880 									&iCryptCert, NULL );
1881 			}
1882 		if( cryptStatusOK( cryptStatus ) )
1883 			{
1884 			/* If we're just checking whether an object exists, return now.
1885 			   If all we want is the key label, copy it back to the caller
1886 			   and exit */
1887 			if( flags & KEYMGMT_FLAG_CHECK_ONLY )
1888 				return( CRYPT_OK );
1889 			if( flags & KEYMGMT_FLAG_LABEL_ONLY )
1890 				{
1891 				return( getObjectLabel( pkcs11Info, hCertificateLabelObject,
1892 										auxInfo, *auxInfoLength,
1893 										auxInfoLength ) );
1894 				}
1895 			*iCryptHandle = iCryptCert;
1896 
1897 			return( CRYPT_OK );
1898 			}
1899 
1900 		/* If we're looking for a specific match on a certificate (rather
1901 		   than just a general public key) and we don't find anything, exit
1902 		   now */
1903 		if( keyIDtype == CRYPT_IKEYID_ISSUERANDSERIALNUMBER )
1904 			return( cryptStatus );
1905 		}
1906 
1907 	/* Either there were no certificates found or we're looking for a
1908 	   private key (or, somewhat unusually, a raw public key).  At this
1909 	   point we can approach the problem from one of two sides, if we've
1910 	   got an issuerAndSerialNumber we have to find the matching certificate
1911 	   and get the key from that, otherwise we find the key and get the
1912 	   certificate from that */
1913 	if( keyIDtype == CRYPT_IKEYID_ISSUERANDSERIALNUMBER )
1914 		{
1915 		CK_ATTRIBUTE iAndSTemplate[ 4 + 8 ], iAndSTemplateAlt[ 4 + 8 ];
1916 
1917 		/* Try and find the certificate from the given template.  Note that
1918 		   we can't use findCert() for this because it returns a cryptlib
1919 		   certificate and not a PKCS #11 object handle */
1920 		cryptStatus = initIAndSTemplate( iAndSTemplate, iAndSTemplateAlt,
1921 										 keyID, keyIDlength );
1922 		if( cryptStatusError( cryptStatus ) )
1923 			return( cryptStatus );
1924 		cryptStatus = findObject( pkcs11Info, &hCertificate,
1925 								  iAndSTemplate, 4 );
1926 		if( cryptStatus == CRYPT_ERROR_NOTFOUND )
1927 			cryptStatus = findObject( pkcs11Info, &hCertificate,
1928 									  iAndSTemplateAlt, 4 );
1929 #ifdef PKCS11_FIND_VIA_CRYPTLIB
1930 		if( cryptStatus == CRYPT_ERROR_NOTFOUND )
1931 			{
1932 			cryptStatus = searchDeviceObjects( pkcs11Info, NULL,
1933 											   &hCertificate, keyIDtype,
1934 											   keyID, keyIDlength, TRUE );
1935 			}
1936 #endif /* PKCS11_FIND_VIA_CRYPTLIB */
1937 		if( cryptStatusOK( cryptStatus ) )
1938 			{
1939 			/* We've found the identified certificate, use it to find the
1940 			   corresponding private key */
1941 			cryptStatus = findObjectFromObject( pkcs11Info, hCertificate,
1942 												CKO_PRIVATE_KEY, &hObject );
1943 			if( cryptStatusError( cryptStatus ) )
1944 				return( cryptStatus );
1945 
1946 			/* Remember that we've already got a certificate to attach to
1947 			   the private key */
1948 			privateKeyViaCert = TRUE;
1949 			}
1950 		else
1951 			{
1952 			/* If we didn't find anything it may be because whoever set up
1953 			   the token didn't set the iAndS rather than because there's no
1954 			   key there so we only bail out if we got some unexpected type
1955 			   of error */
1956 			if( cryptStatus != CRYPT_ERROR_NOTFOUND )
1957 				return( cryptStatus );
1958 			}
1959 		}
1960 	else
1961 		{
1962 		FIND_PUBPRIV_TYPE findType;
1963 
1964 		cryptStatus = findPubPrivKey( pkcs11Info, &hObject, &hCertificate,
1965 								&findType, keyIDtype, keyID, keyIDlength,
1966 								( itemType == KEYMGMT_ITEM_PUBLICKEY ) ? \
1967 									TRUE : FALSE );
1968 		if( cryptStatusError( cryptStatus ) )
1969 			return( cryptStatus );
1970 		switch( findType )
1971 			{
1972 			case FIND_PUBPRIV_NONE:
1973 				/* No special handling */
1974 				break;
1975 
1976 			case FIND_PUBPRIV_CERTVIAKEY:
1977 				/* Remember that although we've got a private key object, we
1978 				   only need it to find the associated certificate and not
1979 				   finding an associated certificate is an error */
1980 				certViaPrivateKey = TRUE;
1981 				break;
1982 
1983 			case FIND_PUBPRIV_KEYVIACERT:
1984 				/* Remember that we've already got a certificate to attach
1985 				   to the private key */
1986 				privateKeyViaCert = TRUE;
1987 				break;
1988 
1989 			default:
1990 				retIntError();
1991 			}
1992 		}
1993 
1994 	/* If we're looking for any kind of private key and we either have an
1995 	   explicit certificate ID but couldn't find a certificate for it or we
1996 	   don't have a proper ID to search on and a generic search found more
1997 	   than one matching object, chances are that we're after a generic
1998 	   decrypt key.  The former only occurs in misconfigured or limited-
1999 	   memory tokens, the latter only in rare tokens that store more than
2000 	   one private key, typically one for signing and one for verification.
2001 
2002 	   If either of these cases occur then we try again looking specifically
2003 	   for a decryption key.  Even this doesn't always work, there are some
2004 	   >1-key tokens that mark a signing key as a decryption key so we still
2005 	   get a CRYPT_ERROR_DUPLICATE error.
2006 
2007 	   Finally, if we can't find a decryption key either, we look for an
2008 	   unwrapping key.  This may or may not work depending on whether we
2009 	   have a decryption key marked as valid for unwrapping but not
2010 	   decryption or a key that's genuinely only valid for unwrapping, but
2011 	   at this point we're ready to try anything */
2012 	if( itemType == KEYMGMT_ITEM_PRIVATEKEY && \
2013 		( keyIDtype == CRYPT_IKEYID_ISSUERANDSERIALNUMBER && \
2014 		  cryptStatus == CRYPT_ERROR_NOTFOUND ) || \
2015 		( cryptStatus == CRYPT_ERROR_DUPLICATE ) )
2016 		{
2017 		static const CK_OBJECT_CLASS privkeyClass = CKO_PRIVATE_KEY;
2018 		static const CK_BBOOL bTrue = TRUE;
2019 		CK_ATTRIBUTE decryptKeyTemplate[] = {
2020 			{ CKA_CLASS, ( CK_VOID_PTR ) &privkeyClass, sizeof( CK_OBJECT_CLASS ) },
2021 			{ CKA_DECRYPT, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) }
2022 			};
2023 
2024 		cryptStatus = findObject( pkcs11Info, &hObject,
2025 								  decryptKeyTemplate, 2 );
2026 		if( cryptStatusError( cryptStatus ) && \
2027 			cryptStatus != CRYPT_ERROR_DUPLICATE )
2028 			{
2029 			decryptKeyTemplate[ 1 ].type = CKA_UNWRAP;
2030 			cryptStatus = findObject( pkcs11Info, &hObject,
2031 									  decryptKeyTemplate, 2 );
2032 			}
2033 		}
2034 	if( cryptStatusError( cryptStatus ) )
2035 		return( cryptStatus );
2036 
2037 	/* Sanity check that we actually found something */
2038 	ENSURES( hObject != CK_OBJECT_NONE );
2039 
2040 	/* If we're just checking whether an object exists, return now.  If all
2041 	   we want is the key label, copy it back to the caller and exit */
2042 	if( flags & KEYMGMT_FLAG_CHECK_ONLY )
2043 		return( CRYPT_OK );
2044 	if( flags & KEYMGMT_FLAG_LABEL_ONLY )
2045 		return( getObjectLabel( pkcs11Info, hObject, auxInfo, *auxInfoLength,
2046 								auxInfoLength ) );
2047 
2048 	/* We found something, map the key type to a cryptlib algorithm ID,
2049 	   determine the key size, and find its capabilities */
2050 	cryptStatus = getMechanismInfo( pkcs11Info, hObject,
2051 									deviceInfo->capabilityInfoList,
2052 									TRUE, &capabilityInfoPtr, &cryptAlgo );
2053 	if( cryptStatusError( cryptStatus ) )
2054 		return( cryptStatus );
2055 #if defined( USE_ECDH ) || defined( USE_ECDSA )
2056 	if( isEccAlgo( cryptAlgo ) )
2057 		{
2058 		CRYPT_ECCCURVE_TYPE curveType;
2059 
2060 		/* Get the field size for the named curve */
2061 		cryptStatus = getEccCurveType( pkcs11Info, hObject, &curveType );
2062 		if( cryptStatusOK( cryptStatus ) )
2063 			cryptStatus = getECCFieldSize( curveType, &keySize, FALSE );
2064 		if( cryptStatusError( cryptStatus ) )
2065 			return( cryptStatus );
2066 		}
2067 	else
2068 #endif /* USE_ECDH || USE_ECDSA */
2069 		{
2070 		cryptStatus = mapValue( cryptAlgo, &keySize, keySizeMapTbl,
2071 								FAILSAFE_ARRAYSIZE( keySizeMapTbl, MAP_TABLE ) );
2072 		if( cryptStatusError( cryptStatus ) )
2073 			{
2074 			/* This can happen if the object that we're fetching uses an
2075 			   unknown or non-PKC algorithm */
2076 			return( cryptStatus );
2077 			}
2078 		keySizeTemplate.type = keySize;		/* For int vs. enum */
2079 		status = C_GetAttributeValue( pkcs11Info->hSession, hObject,
2080 									  &keySizeTemplate, 1 );
2081 		if( status != CKR_OK )
2082 			return( pkcs11MapError( status, CRYPT_ERROR_FAILED ) );
2083 		keySize = keySizeTemplate.ulValueLen;
2084 		}
2085 	ENSURES( keySize >= MIN_PKCSIZE_ECC && \
2086 			 keySize <= CRYPT_MAX_PKCSIZE );
2087 
2088 	/* Try and find a certificate that matches the key.  The process is as
2089 	   follows:
2090 
2091 		if certificate object found in issuerAndSerialNumber search
2092 			-- Implies key == private key
2093 			create native data-only certificate object
2094 			attach certificate object to key
2095 		else
2096 			{
2097 			if public key read
2098 				{
2099 				if certificate
2100 					create native certificate (+context) object
2101 				else
2102 					create context object
2103 				}
2104 			else
2105 				{
2106 				create device privkey object, mark as "key loaded"
2107 				if certificate
2108 					create native data-only certificate object
2109 					attach certificate object to key
2110 				}
2111 			}
2112 
2113 	   The reason for doing things this way is given in the comments earlier
2114 	   on in this function */
2115 	if( privateKeyViaCert )
2116 		{
2117 		/* Sanity check that we actually found a certificate */
2118 		REQUIRES( hCertificate != CK_OBJECT_NONE );
2119 
2120 		/* We've already got the certificate object handle, instantiate a
2121 		   native data-only certificate from it */
2122 		cryptStatus = getCertChain( pkcs11Info, deviceInfo->objectHandle,
2123 									hCertificate, &iCryptCert, FALSE );
2124 		if( cryptStatusError( cryptStatus ) )
2125 			return( cryptStatus );
2126 		certPresent = TRUE;
2127 		}
2128 	else
2129 		{
2130 		cryptStatus = findCertFromObject( pkcs11Info, deviceInfo->objectHandle,
2131 										  hObject, &iCryptCert,
2132 										  ( itemType == KEYMGMT_ITEM_PUBLICKEY ) ? \
2133 										  FINDCERT_NORMAL : FINDCERT_DATAONLY );
2134 		if( cryptStatusError( cryptStatus ) )
2135 			{
2136 			/* If we get a CRYPT_ERROR_NOTFOUND this is OK since it means
2137 			   that there's no certificate present, however anything else is
2138 			   an error.  In addition if we've got a private key whose only
2139 			   function is to point to an associated certificate then not
2140 			   finding anything is also an error */
2141 			if( cryptStatus != CRYPT_ERROR_NOTFOUND || certViaPrivateKey )
2142 				return( cryptStatus );
2143 			}
2144 		else
2145 			{
2146 			/* We got the certificate, if we're being asked for a public key
2147 			   then we've created a native object to contain it so we return
2148 			   that */
2149 			certPresent = TRUE;
2150 			if( itemType == KEYMGMT_ITEM_PUBLICKEY )
2151 				{
2152 				*iCryptHandle = iCryptCert;
2153 				return( CRYPT_OK );
2154 				}
2155 			}
2156 		}
2157 
2158 	/* Create the object.  If it's a public-key object we create a native
2159 	   object for the reasons given in createNativeObject(), otherwise we
2160 	   create a device object */
2161 	if( itemType == KEYMGMT_ITEM_PUBLICKEY )
2162 		{
2163 		return( createNativeObject( pkcs11Info, iCryptHandle, hObject,
2164 									KEYMGMT_ITEM_PUBLICKEY, cryptAlgo ) );
2165 		}
2166 	cryptStatus = createDeviceObject( pkcs11Info, iCryptHandle, hObject,
2167 									  certPresent ? iCryptCert : CRYPT_UNUSED,
2168 									  deviceInfo->ownerHandle,
2169 									  deviceInfo->objectHandle,
2170 									  capabilityInfoPtr,
2171 									  KEYMGMT_ITEM_PRIVATEKEY, cryptAlgo,
2172 									  keySize );
2173 	if( cryptStatusError( cryptStatus ) && certPresent )
2174 		krnlSendNotifier( iCryptCert, IMESSAGE_DECREFCOUNT );
2175 	return( cryptStatus );
2176 	}
2177 
2178 /* Get the sequence of certificates in a chain from a device */
2179 
2180 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3, 5 ) ) \
getFirstItemFunction(INOUT DEVICE_INFO * deviceInfo,OUT_HANDLE_OPT CRYPT_CERTIFICATE * iCertificate,OUT int * stateInfo,IN_KEYID const CRYPT_KEYID_TYPE keyIDtype,IN_BUFFER (keyIDlength)const void * keyID,IN_LENGTH_KEYID const int keyIDlength,IN_ENUM (KEYMGMT_ITEM)const KEYMGMT_ITEM_TYPE itemType,IN_FLAGS_Z (KEYMGMT)const int options)2181 static int getFirstItemFunction( INOUT DEVICE_INFO *deviceInfo,
2182 								 OUT_HANDLE_OPT CRYPT_CERTIFICATE *iCertificate,
2183 								 OUT int *stateInfo,
2184 								 IN_KEYID const CRYPT_KEYID_TYPE keyIDtype,
2185 								 IN_BUFFER( keyIDlength ) const void *keyID,
2186 								 IN_LENGTH_KEYID const int keyIDlength,
2187 								 IN_ENUM( KEYMGMT_ITEM ) \
2188 									const KEYMGMT_ITEM_TYPE itemType,
2189 								 IN_FLAGS_Z( KEYMGMT ) const int options )
2190 	{
2191 	static const CK_OBJECT_CLASS certClass = CKO_CERTIFICATE;
2192 	static const CK_CERTIFICATE_TYPE certType = CKC_X_509;
2193 	CK_ATTRIBUTE certTemplate[] = {
2194 		{ CKA_CLASS, ( CK_VOID_PTR ) &certClass, sizeof( CK_OBJECT_CLASS ) },
2195 		{ CKA_CERTIFICATE_TYPE, ( CK_VOID_PTR ) &certType, sizeof( CK_CERTIFICATE_TYPE ) },
2196 		{ CKA_ID, ( CK_VOID_PTR ) keyID, keyIDlength }
2197 		};
2198 	CK_OBJECT_HANDLE hCertificate;
2199 	PKCS11_INFO *pkcs11Info = deviceInfo->devicePKCS11;
2200 	int cryptStatus;
2201 
2202 	assert( isWritePtr( deviceInfo, sizeof( DEVICE_INFO ) ) );
2203 	assert( isWritePtr( iCertificate, sizeof( CRYPT_CERTIFICATE ) ) );
2204 	assert( isReadPtr( keyID, keyIDlength ) );
2205 	assert( isWritePtr( stateInfo, sizeof( int ) ) );
2206 
2207 	REQUIRES( keyIDtype == CRYPT_IKEYID_KEYID );
2208 	REQUIRES( keyIDlength >= 1 && keyIDlength < MAX_ATTRIBUTE_SIZE );
2209 			  /* The keyID can be as little as a single byte when coming
2210 			     from a non-cryptlib source */
2211 	REQUIRES( itemType == KEYMGMT_ITEM_PUBLICKEY );
2212 	REQUIRES( options >= KEYMGMT_FLAG_NONE && \
2213 			  options < KEYMGMT_FLAG_MAX );
2214 
2215 	/* Clear return values */
2216 	*iCertificate = CRYPT_ERROR;
2217 	*stateInfo = CRYPT_ERROR;
2218 
2219 	/* Try and find the certificate with the given ID.  This should work
2220 	   because we've just read the ID for the indirect-import that lead to
2221 	   the getFirst() call.  Note that we can't use findCert() for this
2222 	   because it uses getCertChain() to build the full chain of
2223 	   certificates from the leaf, which would end up calling back to
2224 	   here */
2225 	cryptStatus = findObject( pkcs11Info, &hCertificate, certTemplate, 3 );
2226 	ENSURES( cryptStatusOK( cryptStatus ) );
2227 
2228 	/* Instantiate the certificate from the device */
2229 	cryptStatus = instantiateCert( pkcs11Info, hCertificate, iCertificate,
2230 								   ( options & KEYMGMT_FLAG_DATAONLY_CERT ) ? \
2231 									TRUE : FALSE );
2232 	if( cryptStatusError( cryptStatus ) )
2233 		return( cryptStatus );
2234 	*stateInfo = *iCertificate;
2235 	return( CRYPT_OK );
2236 	}
2237 
2238 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \
getNextItemFunction(INOUT DEVICE_INFO * deviceInfo,OUT_HANDLE_OPT CRYPT_CERTIFICATE * iCertificate,INOUT int * stateInfo,IN_FLAGS_Z (KEYMGMT)const int options)2239 static int getNextItemFunction( INOUT DEVICE_INFO *deviceInfo,
2240 								OUT_HANDLE_OPT CRYPT_CERTIFICATE *iCertificate,
2241 								INOUT int *stateInfo,
2242 								IN_FLAGS_Z( KEYMGMT ) const int options )
2243 	{
2244 	static const CK_OBJECT_CLASS certClass = CKO_CERTIFICATE;
2245 	static const CK_CERTIFICATE_TYPE certType = CKC_X_509;
2246 	CK_ATTRIBUTE certTemplate[] = {
2247 		{ CKA_CLASS, ( CK_VOID_PTR ) &certClass, sizeof( CK_OBJECT_CLASS ) },
2248 		{ CKA_CERTIFICATE_TYPE, ( CK_VOID_PTR ) &certType, sizeof( CK_CERTIFICATE_TYPE ) },
2249 		{ CKA_SUBJECT, NULL, 0 }
2250 		};
2251 	CK_OBJECT_HANDLE hCertificate;
2252 	PKCS11_INFO *pkcs11Info = deviceInfo->devicePKCS11;
2253 	DYNBUF subjectDB;
2254 	int cryptStatus;
2255 
2256 	assert( isWritePtr( deviceInfo, sizeof( DEVICE_INFO ) ) );
2257 	assert( isWritePtr( iCertificate, sizeof( CRYPT_CERTIFICATE ) ) );
2258 	assert( isWritePtr( stateInfo, sizeof( int ) ) );
2259 
2260 	REQUIRES( isHandleRangeValid( *stateInfo ) || *stateInfo == CRYPT_ERROR );
2261 	REQUIRES( options >= KEYMGMT_FLAG_NONE && options < KEYMGMT_FLAG_MAX );
2262 
2263 	/* Clear return value */
2264 	*iCertificate = CRYPT_ERROR;
2265 
2266 	/* If the previous certificate was the last one, there's nothing left to
2267 	   fetch */
2268 	if( *stateInfo == CRYPT_ERROR )
2269 		return( CRYPT_ERROR_NOTFOUND );
2270 
2271 	/* Get the issuerName of the previous certificate, which is the
2272 	   subjectName of the certificate that we want */
2273 	cryptStatus = dynCreate( &subjectDB, *stateInfo,
2274 							 CRYPT_IATTRIBUTE_ISSUER );
2275 	if( cryptStatusError( cryptStatus ) )
2276 		return( cryptStatus );
2277 	certTemplate[ 2 ].pValue = dynData( subjectDB );
2278 	certTemplate[ 2 ].ulValueLen = dynLength( subjectDB );
2279 
2280 	/* Get the certificate with the subject's issuer DN.  Note that we
2281 	   can't use findCert() for this because it uses getCertChain() to
2282 	   build the full chain of certificates from the leaf, which would end
2283 	   up calling back to here */
2284 	cryptStatus = findObject( pkcs11Info, &hCertificate, certTemplate, 3 );
2285 	if( cryptStatusOK( cryptStatus ) )
2286 		{
2287 		cryptStatus = instantiateCert( pkcs11Info, hCertificate, iCertificate,
2288 									   ( options & KEYMGMT_FLAG_DATAONLY_CERT ) ? \
2289 										 TRUE : FALSE );
2290 		}
2291 #ifdef PKCS11_FIND_VIA_CRYPTLIB
2292 	else
2293 		{
2294 		cryptStatus = searchDeviceObjects( pkcs11Info, iCertificate, NULL,
2295 										   CRYPT_KEYID_NONE,
2296 										   dynData( subjectDB ),
2297 										   dynLength( subjectDB ), TRUE );
2298 		}
2299 #endif /* PKCS11_FIND_VIA_CRYPTLIB */
2300 	dynDestroy( &subjectDB );
2301 	if( cryptStatusError( cryptStatus ) )
2302 		{
2303 		*stateInfo = CRYPT_ERROR;
2304 		return( cryptStatus );
2305 		}
2306 	*stateInfo = *iCertificate;
2307 	return( CRYPT_OK );
2308 	}
2309 
2310 /****************************************************************************
2311 *																			*
2312 *							Device Access Routines							*
2313 *																			*
2314 ****************************************************************************/
2315 
2316 /* Set up the function pointers to the read methods */
2317 
2318 STDC_NONNULL_ARG( ( 1 ) ) \
initPKCS11Read(INOUT DEVICE_INFO * deviceInfo)2319 void initPKCS11Read( INOUT DEVICE_INFO *deviceInfo )
2320 	{
2321 	assert( isWritePtr( deviceInfo, sizeof( DEVICE_INFO ) ) );
2322 
2323 	deviceInfo->getItemFunction = getItemFunction;
2324 	deviceInfo->getFirstItemFunction = getFirstItemFunction;
2325 	deviceInfo->getNextItemFunction = getNextItemFunction;
2326 	}
2327 #endif /* USE_PKCS11 */
2328