1 /****************************************************************************
2 *																			*
3 *						 cryptlib Configuration Routines					*
4 *						Copyright Peter Gutmann 1994-2012					*
5 *																			*
6 ****************************************************************************/
7 
8 #include "crypt.h"
9 #ifdef INC_ALL
10   #include "user_int.h"
11   #include "user.h"
12 #else
13   #include "misc/user_int.h"
14   #include "misc/user.h"
15 #endif /* Compiler-specific includes */
16 
17 /****************************************************************************
18 *																			*
19 *							Configuration Options							*
20 *																			*
21 ****************************************************************************/
22 
23 /* Built-in default configuration options */
24 
25 #define MK_OPTION( option, value, index ) \
26 	{ option, OPTION_NUMERIC, index, NULL, value }
27 #define MK_OPTION_B( option, value, index ) \
28 	{ option, OPTION_BOOLEAN, index, NULL, value }
29 #define MK_OPTION_S( option, value, length, index ) \
30 	{ option, OPTION_STRING, index, value, length }
31 #define MK_OPTION_NONE() \
32 	{ CRYPT_ATTRIBUTE_NONE, OPTION_NONE, CRYPT_UNUSED, NULL, 0 }
33 
34 static const BUILTIN_OPTION_INFO FAR_BSS builtinOptionInfo[] = {
35 	/* cryptlib information (read-only) */
36 	MK_OPTION_S( CRYPT_OPTION_INFO_DESCRIPTION, "cryptlib security toolkit", 25, CRYPT_UNUSED ),
37 	MK_OPTION_S( CRYPT_OPTION_INFO_COPYRIGHT, "Copyright Peter Gutmann, Eric Young, OpenSSL, 1994-2015", 55, CRYPT_UNUSED ),
38 	MK_OPTION( CRYPT_OPTION_INFO_MAJORVERSION, 3, CRYPT_UNUSED ),
39 	MK_OPTION( CRYPT_OPTION_INFO_MINORVERSION, 4, CRYPT_UNUSED ),
40 	MK_OPTION( CRYPT_OPTION_INFO_STEPPING, 3, CRYPT_UNUSED ),
41 
42 	/* Context options, base = 0 */
43 	/* Algorithm = Conventional encryption/hash/MAC options */
44 	MK_OPTION( CRYPT_OPTION_ENCR_ALGO, CRYPT_ALGO_AES, 0 ),
45 	MK_OPTION( CRYPT_OPTION_ENCR_HASH, CRYPT_ALGO_SHA2, 1 ),
46 	MK_OPTION( CRYPT_OPTION_ENCR_MAC, CRYPT_ALGO_HMAC_SHA2, 2 ),
47 
48 	/* Algorithm = PKC options */
49 	MK_OPTION( CRYPT_OPTION_PKC_ALGO, CRYPT_ALGO_RSA, 3 ),
50 	MK_OPTION( CRYPT_OPTION_PKC_KEYSIZE, bitsToBytes( 1536 ), 4 ),
51 
52 	/* Algorithm = Signature options */
53 	MK_OPTION( CRYPT_OPTION_SIG_ALGO, CRYPT_ALGO_RSA, 5 ),
54 	MK_OPTION( CRYPT_OPTION_SIG_KEYSIZE, bitsToBytes( 1536 ), 6 ),
55 
56 	/* Algorithm = Key derivation options.  On a slower CPU we use a
57 	   lower number of iterations.  Conversely, on a fast CPU we use
58 	   a larger number */
59 	MK_OPTION( CRYPT_OPTION_KEYING_ALGO, CRYPT_ALGO_HMAC_SHA2, 7 ),
60 #if defined( CONFIG_SLOW_CPU )
61 	MK_OPTION( CRYPT_OPTION_KEYING_ITERATIONS, 1000, 8 ),
62 #elif defined( CONFIG_FAST_CPU )
63 	MK_OPTION( CRYPT_OPTION_KEYING_ITERATIONS, min( 50000, MAX_KEYSETUP_ITERATIONS ), 8 ),
64 #else
65 	MK_OPTION( CRYPT_OPTION_KEYING_ITERATIONS, 10000, 8 ),
66 #endif /* Options based on CPU speed */
67 
68 	/* Certificate options, base = 100 */
69 	MK_OPTION_B( CRYPT_OPTION_CERT_SIGNUNRECOGNISEDATTRIBUTES, FALSE, 100 ),
70 	MK_OPTION( CRYPT_OPTION_CERT_VALIDITY, 365, 101 ),
71 	MK_OPTION( CRYPT_OPTION_CERT_UPDATEINTERVAL, 90, 102 ),
72 	MK_OPTION( CRYPT_OPTION_CERT_COMPLIANCELEVEL, CRYPT_COMPLIANCELEVEL_STANDARD, 103 ),
73 	MK_OPTION_B( CRYPT_OPTION_CERT_REQUIREPOLICY, TRUE, 104 ),
74 
75 	/* CMS options */
76 	MK_OPTION_B( CRYPT_OPTION_CMS_DEFAULTATTRIBUTES, TRUE, 105 ),
77 
78 	/* Keyset options, base = 200 */
79 	/* Keyset = LDAP options */
80 	MK_OPTION_S( CRYPT_OPTION_KEYS_LDAP_OBJECTCLASS, "inetOrgPerson", 13, 200 ),
81 	MK_OPTION( CRYPT_OPTION_KEYS_LDAP_OBJECTTYPE, CRYPT_CERTTYPE_NONE, 201 ),
82 	MK_OPTION_S( CRYPT_OPTION_KEYS_LDAP_FILTER, "(objectclass=*)", 15, 202 ),
83 	MK_OPTION_S( CRYPT_OPTION_KEYS_LDAP_CACERTNAME, "cACertificate;binary", 20, 203 ),
84 	MK_OPTION_S( CRYPT_OPTION_KEYS_LDAP_CERTNAME, "userCertificate;binary", 32, 204 ),
85 	MK_OPTION_S( CRYPT_OPTION_KEYS_LDAP_CRLNAME, "certificateRevocationList;binary", 22, 205 ),
86 	MK_OPTION_S( CRYPT_OPTION_KEYS_LDAP_EMAILNAME, "mail", 4, 206 ),
87 
88 	/* Device options, base = 300 */
89 	/* Device = PKCS #11 token options */
90 	MK_OPTION_S( CRYPT_OPTION_DEVICE_PKCS11_DVR01, NULL, 0, 300 ),
91 	MK_OPTION_S( CRYPT_OPTION_DEVICE_PKCS11_DVR02, NULL, 0, 301 ),
92 	MK_OPTION_S( CRYPT_OPTION_DEVICE_PKCS11_DVR03, NULL, 0, 302 ),
93 	MK_OPTION_S( CRYPT_OPTION_DEVICE_PKCS11_DVR04, NULL, 0, 303 ),
94 	MK_OPTION_S( CRYPT_OPTION_DEVICE_PKCS11_DVR05, NULL, 0, 304 ),
95 	MK_OPTION_B( CRYPT_OPTION_DEVICE_PKCS11_HARDWAREONLY, FALSE, 305 ),
96 
97 	/* Session options, base = 400 */
98 
99 	/* Miscellaneous options, base = 500.  The network options are mostly
100 	   used by sessions but also apply to other object types like network
101 	   keysets so they're classed as miscellaneous options.
102 
103 	   Side-channel protection is usually disabled by default because a
104 	   survey of users found that a total of 0% indicated that they wanted
105 	   side-channel protection in exchange for a performance drop
106 	   (particularly in embedded systems where PKC ops already consume about
107 	   150% of the available CPU budget), however on fast systems we enable
108 	   it by default because they should be fast enough that no-one will
109 	   notice */
110 	MK_OPTION_S( CRYPT_OPTION_NET_SOCKS_SERVER, NULL, 0, 500 ),
111 	MK_OPTION_S( CRYPT_OPTION_NET_SOCKS_USERNAME, NULL, 0, 501 ),
112 	MK_OPTION_S( CRYPT_OPTION_NET_HTTP_PROXY, NULL, 0, 502 ),
113 	MK_OPTION( CRYPT_OPTION_NET_CONNECTTIMEOUT, NET_TIMEOUT_CONNECT, 503 ),
114 	MK_OPTION( CRYPT_OPTION_NET_READTIMEOUT, NET_TIMEOUT_READ, 504 ),
115 	MK_OPTION( CRYPT_OPTION_NET_WRITETIMEOUT, NET_TIMEOUT_WRITE, 505 ),
116 	MK_OPTION_B( CRYPT_OPTION_MISC_ASYNCINIT, TRUE, 506 ),
117 #if defined( CONFIG_FAST_CPU )
118 	MK_OPTION( CRYPT_OPTION_MISC_SIDECHANNELPROTECTION, 1, 507 ),
119 #else
120 	MK_OPTION( CRYPT_OPTION_MISC_SIDECHANNELPROTECTION, 0, 507 ),
121 #endif /* Options based on CPU speed */
122 
123 	/* All options beyond this point are ephemeral and aren't stored to disk.
124 	   Remember to update the LAST_STORED_OPTION define in user_int.h when
125 	   adding new options here */
126 
127 	/* cryptlib state information.  These are special-case options that
128 	   record state information rather than a static configuration value.
129 	   The configuration-option-changed status value is updated dynamically,
130 	   being set to TRUE if any configuration option is changed.  Writing it
131 	   to FALSE commits the changes to disk.  The self-test status value is
132 	   initially set to FALSE, writing it to TRUE triggers a self-test for
133 	   which the value remains at TRUE if the test succeeds */
134 	MK_OPTION_B( CRYPT_OPTION_CONFIGCHANGED, FALSE, CRYPT_UNUSED ),
135 	MK_OPTION( CRYPT_OPTION_SELFTESTOK, FALSE, CRYPT_UNUSED ),
136 
137 	/* End-of-list marker */
138 	MK_OPTION_NONE(), MK_OPTION_NONE()
139 	};
140 
141 /* The size of the variable-length configuration data, used when we allocate
142    storage for it and initialise it from the builtinOptionInfo template */
143 
144 #define OPTION_INFO_SIZE	( sizeof( OPTION_INFO ) * \
145 							  CRYPT_OPTION_CONFIGCHANGED - CRYPT_OPTION_FIRST )
146 
147 /****************************************************************************
148 *																			*
149 *							Utility Functions								*
150 *																			*
151 ****************************************************************************/
152 
153 /* Locate an entry in the built-in configuration options by looking up the
154    option code that identifies it when it's written to disk */
155 
156 CHECK_RETVAL_PTR \
157 const BUILTIN_OPTION_INFO *getBuiltinOptionInfoByCode( IN_RANGE( 0, LAST_OPTION_INDEX ) \
158 														const int optionCode )
159 	{
160 	int i;
161 
162 	REQUIRES_N( optionCode >= 0 && optionCode <= LAST_OPTION_INDEX );
163 
164 	for( i = 0;
165 		 builtinOptionInfo[ i ].option <= LAST_STORED_OPTION && \
166 			i < FAILSAFE_ARRAYSIZE( builtinOptionInfo, BUILTIN_OPTION_INFO ); i++ )
167 		{
168 		if( builtinOptionInfo[ i ].index == optionCode )
169 			return( &builtinOptionInfo[ i ] );
170 		}
171 	ENSURES_N( i < FAILSAFE_ARRAYSIZE( builtinOptionInfo, BUILTIN_OPTION_INFO ) );
172 
173 	/* Failing to find a match isn't an internal error since we're looking
174 	   up the options based on configuration data stored in an external
175 	   file */
176 	return( NULL );
177 	}
178 
179 /* Locate an entry in the current configuration options */
180 
181 CHECK_RETVAL_PTR STDC_NONNULL_ARG( ( 1 ) ) \
getOptionInfo(IN_ARRAY (configOptionsCount)const OPTION_INFO * optionList,IN_INT_SHORT const int configOptionsCount,IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE option)182 static const OPTION_INFO *getOptionInfo( IN_ARRAY( configOptionsCount ) \
183 											const OPTION_INFO *optionList,
184 										 IN_INT_SHORT const int configOptionsCount,
185 										 IN_ATTRIBUTE \
186 											const CRYPT_ATTRIBUTE_TYPE option )
187 	{
188 	int i;
189 
190 	assert( isReadPtr( optionList,
191 					   sizeof( OPTION_INFO ) * configOptionsCount ) );
192 
193 	REQUIRES_N( configOptionsCount > 0 && \
194 				configOptionsCount < MAX_INTLENGTH_SHORT );
195 	REQUIRES_N( option > CRYPT_OPTION_FIRST && option < CRYPT_OPTION_LAST );
196 
197 	for( i = 0;
198 		 i < configOptionsCount && \
199 			optionList[ i ].builtinOptionInfo != NULL && \
200 			optionList[ i ].builtinOptionInfo->option != CRYPT_ATTRIBUTE_NONE;
201 		 i++ )
202 		{
203 		if( optionList[ i ].builtinOptionInfo->option == option )
204 			return( &optionList[ i ] );
205 		}
206 	ENSURES_N( i < configOptionsCount );
207 
208 	retIntError_Null();
209 	}
210 
211 /* Record the fact that one of the configuration options has been changed */
212 
setConfigChanged(INOUT_ARRAY (configOptionsCount)OPTION_INFO * optionList,IN_INT_SHORT const int configOptionsCount)213 static void setConfigChanged( INOUT_ARRAY( configOptionsCount ) \
214 									OPTION_INFO *optionList,
215 							  IN_INT_SHORT const int configOptionsCount )
216 	{
217 	OPTION_INFO *optionInfoPtr;
218 
219 	assert( isReadPtr( optionList,
220 					   sizeof( OPTION_INFO ) * configOptionsCount ) );
221 
222 	REQUIRES_V( configOptionsCount > 0 && \
223 				configOptionsCount < MAX_INTLENGTH_SHORT );
224 
225 	optionInfoPtr = ( OPTION_INFO * ) \
226 					getOptionInfo( optionList, configOptionsCount,
227 								   CRYPT_OPTION_CONFIGCHANGED );
228 	ENSURES_V( optionInfoPtr != NULL );
229 	optionInfoPtr->intValue = TRUE;
230 	}
231 
232 /* Check whether a configuration option has been changed */
233 
234 CHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \
checkConfigChanged(IN_ARRAY (configOptionsCount)const OPTION_INFO * optionList,IN_INT_SHORT const int configOptionsCount)235 BOOLEAN checkConfigChanged( IN_ARRAY( configOptionsCount ) \
236 								const OPTION_INFO *optionList,
237 							IN_INT_SHORT const int configOptionsCount )
238 	{
239 	int i;
240 
241 	assert( isReadPtr( optionList,
242 					   sizeof( OPTION_INFO ) * configOptionsCount ) );
243 
244 	REQUIRES( configOptionsCount > 0 && \
245 			  configOptionsCount < MAX_INTLENGTH_SHORT );
246 
247 	for( i = 0;
248 		 i < configOptionsCount && \
249 			optionList[ i ].builtinOptionInfo != NULL && \
250 			optionList[ i ].builtinOptionInfo->option <= LAST_STORED_OPTION;
251 		 i++ )
252 		{
253 		if( optionList[ i ].dirty )
254 			return( TRUE );
255 		}
256 	ENSURES_B( i < configOptionsCount );
257 
258 	return( FALSE );
259 	}
260 
261 /****************************************************************************
262 *																			*
263 *							Get Configuration Options						*
264 *																			*
265 ****************************************************************************/
266 
267 /* Query the value of a numeric or string option */
268 
269 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 4 ) ) \
getOption(IN_ARRAY (configOptionsCount)TYPECAST (OPTION_INFO *)const void * configOptions,IN_INT_SHORT const int configOptionsCount,IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE option,OUT_INT_Z int * value)270 int getOption( IN_ARRAY( configOptionsCount ) TYPECAST( OPTION_INFO * ) \
271 					const void *configOptions,
272 			   IN_INT_SHORT const int configOptionsCount,
273 			   IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE option,
274 			   OUT_INT_Z int *value )
275 	{
276 	const OPTION_INFO *optionInfoPtr;
277 
278 	assert( isReadPtr( configOptions,
279 					   sizeof( OPTION_INFO ) * configOptionsCount ) );
280 	assert( isWritePtr( value, sizeof( int ) ) );
281 
282 	REQUIRES( configOptionsCount > 0 && \
283 			  configOptionsCount < MAX_INTLENGTH_SHORT );
284 	REQUIRES( option > CRYPT_OPTION_FIRST && option < CRYPT_OPTION_LAST );
285 
286 	/* Clear return value */
287 	*value = 0;
288 
289 	optionInfoPtr = getOptionInfo( configOptions, configOptionsCount,
290 								   option );
291 	ENSURES( optionInfoPtr != NULL && \
292 			 ( optionInfoPtr->builtinOptionInfo->type == OPTION_NUMERIC || \
293 			   optionInfoPtr->builtinOptionInfo->type == OPTION_BOOLEAN ) );
294 	*value = optionInfoPtr->intValue;
295 
296 	return( CRYPT_OK );
297 	}
298 
299 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 4, 5 ) ) \
getOptionString(IN_ARRAY (configOptionsCount)TYPECAST (OPTION_INFO *)const void * configOptions,IN_INT_SHORT const int configOptionsCount,IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE option,OUT_PTR_COND const void ** strPtrPtr,OUT_LENGTH_SHORT_Z int * strLen)300 int getOptionString( IN_ARRAY( configOptionsCount ) TYPECAST( OPTION_INFO * ) \
301 						const void *configOptions,
302 					 IN_INT_SHORT const int configOptionsCount,
303 					 IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE option,
304 					 OUT_PTR_COND const void **strPtrPtr,
305 					 OUT_LENGTH_SHORT_Z int *strLen )
306 	{
307 	const OPTION_INFO *optionInfoPtr;
308 
309 	assert( isReadPtr( configOptions,
310 					   sizeof( OPTION_INFO ) * configOptionsCount ) );
311 	assert( isReadPtr( strPtrPtr, sizeof( void * ) ) );
312 	assert( isWritePtr( strLen, sizeof( int ) ) );
313 
314 	REQUIRES( configOptionsCount > 0 && \
315 			  configOptionsCount < MAX_INTLENGTH_SHORT );
316 	REQUIRES( option > CRYPT_OPTION_FIRST && option < CRYPT_OPTION_LAST );
317 
318 	/* Clear return values */
319 	*strPtrPtr = NULL;
320 	*strLen = 0;
321 
322 	optionInfoPtr = getOptionInfo( configOptions, configOptionsCount,
323 								   option );
324 	ENSURES( optionInfoPtr != NULL && \
325 			 optionInfoPtr->builtinOptionInfo->type == OPTION_STRING );
326 	if( optionInfoPtr->intValue <= 0 )
327 		return( CRYPT_ERROR_NOTFOUND );
328 	*strPtrPtr = optionInfoPtr->strValue;
329 	*strLen = optionInfoPtr->intValue;
330 
331 	return( CRYPT_OK );
332 	}
333 
334 /****************************************************************************
335 *																			*
336 *							Set Configuration Options						*
337 *																			*
338 ****************************************************************************/
339 
340 /* Set the value of a numeric or string option */
341 
342 CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
setOption(INOUT_ARRAY (configOptionsCount)TYPECAST (OPTION_INFO *)void * configOptions,IN_INT_SHORT const int configOptionsCount,IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE option,IN_INT const int value)343 int setOption( INOUT_ARRAY( configOptionsCount ) TYPECAST( OPTION_INFO * ) \
344 					void *configOptions,
345 			   IN_INT_SHORT const int configOptionsCount,
346 			   IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE option,
347 			   IN_INT const int value )
348 	{
349 	const BUILTIN_OPTION_INFO *builtinOptionInfoPtr;
350 	OPTION_INFO *optionInfoPtr;
351 
352 	assert( isReadPtr( configOptions,
353 					   sizeof( OPTION_INFO ) * configOptionsCount ) );
354 
355 	REQUIRES( configOptionsCount > 0 && \
356 			  configOptionsCount < MAX_INTLENGTH_SHORT );
357 	REQUIRES( option > CRYPT_OPTION_FIRST && option < CRYPT_OPTION_LAST );
358 	REQUIRES( value >= 0 && value < MAX_INTLENGTH );
359 
360 	/* Get a pointer to the option information and make sure that everything
361 	   is OK */
362 	optionInfoPtr = ( OPTION_INFO * ) \
363 					getOptionInfo( configOptions, configOptionsCount,
364 								   option );
365 	ENSURES( optionInfoPtr != NULL );
366 	builtinOptionInfoPtr = optionInfoPtr->builtinOptionInfo;
367 	ENSURES( builtinOptionInfoPtr != NULL && \
368 			 ( builtinOptionInfoPtr->type == OPTION_NUMERIC || \
369 			   builtinOptionInfoPtr->type == OPTION_BOOLEAN ) );
370 
371 	/* If the stored value is the same as the new one, there's nothing to
372 	   do */
373 	if( optionInfoPtr->intValue == value )
374 		return( CRYPT_OK );
375 
376 	/* If we're forcing a commit by returning the configuration-changed flag
377 	   to its ground state, write any changed options to backing store */
378 	if( option == CRYPT_OPTION_CONFIGCHANGED )
379 		{
380 		/* When a non-configuration option (for example a certificate trust
381 		   option) is changed then we need to write the updated
382 		   configuration data to backing store, but there's no way to tell
383 		   that this is required because the configuration options are
384 		   unchanged.  To allow the caller to signal this change they can
385 		   explicitly set the configuration-changed setting to TRUE
386 		   (normally this is done implicitly by when another configuration
387 		   setting is changed).  This explicit setting can only be done by
388 		   the higher-level configuration-update code because the kernel
389 		   blocks any attempts to set it to a value other than FALSE */
390 		if( value )
391 			{
392 			optionInfoPtr->intValue = TRUE;
393 
394 			return( CRYPT_OK );
395 			}
396 
397 		/* Make sure that there's something to write.  We do this to avoid
398 		   problems with programs that always try to update the
399 		   configuration whether it's necessary or not, which can cause
400 		   problems with media with limited writeability */
401 		if( !optionInfoPtr->intValue )
402 			return( CRYPT_OK );
403 
404 		/* We don't do anything to write the configuration data at this
405 		   level since we currently have the user object locked and don't
406 		   want to stall all operations that depend on it while we're
407 		   updating the data, so all that we do is signal the user object
408 		   to perform the necessary operations */
409 		return( OK_SPECIAL );
410 		}
411 
412 	/* If we're forcing a self-test by changing the value of the self-test
413 	   status, perform an algorithm test */
414 	if( option == CRYPT_OPTION_SELFTESTOK )
415 		{
416 		/* The self-test can take some time to complete.  While it's running
417 		   we don't want to leave the user object locked since this will
418 		   block most other threads, which all eventually read some sort of
419 		   configuration option.  To get around this problem we set the
420 		   result value to an undefined status and unlock the user object
421 		   around the call, then re-lock it and set its actual value via
422 		   setOptionSpecial() once the self-test is done */
423 		if( optionInfoPtr->intValue == CRYPT_ERROR )
424 			return( CRYPT_ERROR_TIMEOUT );
425 		optionInfoPtr->intValue = CRYPT_ERROR;
426 
427 		return( OK_SPECIAL );
428 		}
429 
430 	/* Set the value and remember that the configuration options have been
431 	   changed */
432 	if( builtinOptionInfoPtr->type == OPTION_BOOLEAN )
433 		{
434 		/* Turn a generic zero/nonzero boolean into TRUE or FALSE */
435 		optionInfoPtr->intValue = ( value ) ? TRUE : FALSE;
436 		}
437 	else
438 		optionInfoPtr->intValue = value;
439 	optionInfoPtr->dirty = TRUE;
440 	setConfigChanged( configOptions, configOptionsCount );
441 
442 	return( CRYPT_OK );
443 	}
444 
445 CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
setOptionSpecial(INOUT_ARRAY (configOptionsCount)TYPECAST (OPTION_INFO *)void * configOptions,IN_INT_SHORT const int configOptionsCount,IN_RANGE_FIXED (CRYPT_OPTION_SELFTESTOK)const CRYPT_ATTRIBUTE_TYPE option,IN_INT_Z const int value)446 int setOptionSpecial( INOUT_ARRAY( configOptionsCount ) TYPECAST( OPTION_INFO * ) \
447 							void *configOptions,
448 					  IN_INT_SHORT const int configOptionsCount,
449 					  IN_RANGE_FIXED( CRYPT_OPTION_SELFTESTOK ) \
450 							const CRYPT_ATTRIBUTE_TYPE option,
451 					  IN_INT_Z const int value )
452 	{
453 	OPTION_INFO *optionInfoPtr;
454 
455 	assert( isReadPtr( configOptions,
456 					   sizeof( OPTION_INFO ) * configOptionsCount ) );
457 
458 	REQUIRES( configOptionsCount > 0 && \
459 			  configOptionsCount < MAX_INTLENGTH_SHORT );
460 
461 	/* The update of the self-test status is performed in two phases.  When
462 	   we begin the self-test, triggered by the user setting the
463 	   CRYPT_OPTION_SELFTESTOK, it's set to an undefined value via
464 	   setOption().  In other words the user can only ever set this to the
465 	   self-test-in-progress state.  Once the self-test completes it's set
466 	   to the test result value via setOptionSpecial(), which can only be
467 	   accessed from inside the user object */
468 	REQUIRES( option == CRYPT_OPTION_SELFTESTOK );
469 
470 	/* Get a pointer to the option information and make sure that everything
471 	   is OK */
472 	optionInfoPtr = ( OPTION_INFO * ) \
473 					getOptionInfo( configOptions, configOptionsCount,
474 								   option );
475 	ENSURES( optionInfoPtr != NULL && \
476 			 optionInfoPtr->intValue == CRYPT_ERROR );
477 
478 	optionInfoPtr->intValue = value;
479 
480 	return( CRYPT_OK );
481 	}
482 
483 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 4 ) ) \
setOptionString(INOUT_ARRAY (configOptionsCount)TYPECAST (OPTION_INFO *)void * configOptions,IN_INT_SHORT const int configOptionsCount,IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE option,IN_BUFFER (valueLength)const char * value,IN_LENGTH_SHORT const int valueLength)484 int setOptionString( INOUT_ARRAY( configOptionsCount ) TYPECAST( OPTION_INFO * ) \
485 						void *configOptions,
486 					 IN_INT_SHORT const int configOptionsCount,
487 					 IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE option,
488 					 IN_BUFFER( valueLength ) const char *value,
489 					 IN_LENGTH_SHORT const int valueLength )
490 	{
491 	const BUILTIN_OPTION_INFO *builtinOptionInfoPtr;
492 	OPTION_INFO *optionInfoPtr;
493 	char *valuePtr;
494 
495 	assert( isReadPtr( configOptions,
496 					   sizeof( OPTION_INFO ) * configOptionsCount ) );
497 	assert( isReadPtr( value, valueLength ) );
498 
499 	REQUIRES( configOptionsCount > 0 && \
500 			  configOptionsCount < MAX_INTLENGTH_SHORT );
501 	REQUIRES( option > CRYPT_OPTION_FIRST && option < CRYPT_OPTION_LAST );
502 	REQUIRES( valueLength > 0 && valueLength < MAX_INTLENGTH_SHORT );
503 
504 	/* Get a pointer to the option information and make sure that everything
505 	   is OK */
506 	optionInfoPtr = ( OPTION_INFO * ) \
507 					getOptionInfo( configOptions, configOptionsCount,
508 								   option );
509 	ENSURES( optionInfoPtr != NULL );
510 	builtinOptionInfoPtr = optionInfoPtr->builtinOptionInfo;
511 	ENSURES( builtinOptionInfoPtr != NULL && \
512 			 builtinOptionInfoPtr->type == OPTION_STRING );
513 
514 	/* If the value is the same as the current one, there's nothing to do */
515 	if( optionInfoPtr->strValue != NULL && \
516 		optionInfoPtr->intValue == valueLength && \
517 		!memcmp( optionInfoPtr->strValue, value, valueLength ) )
518 		return( CRYPT_OK );
519 
520 	/* If we're resetting a value to its default setting, just reset the
521 	   string pointers rather than storing the value */
522 	if( builtinOptionInfoPtr->strDefault != NULL && \
523 		builtinOptionInfoPtr->intDefault == valueLength && \
524 		!memcmp( builtinOptionInfoPtr->strDefault, value, valueLength ) )
525 		{
526 		if( optionInfoPtr->strValue != NULL && \
527 			optionInfoPtr->strValue != builtinOptionInfoPtr->strDefault )
528 			{
529 			zeroise( optionInfoPtr->strValue, optionInfoPtr->intValue );
530 			clFree( "setOptionString", optionInfoPtr->strValue );
531 			}
532 		optionInfoPtr->strValue = ( char * ) builtinOptionInfoPtr->strDefault;
533 		optionInfoPtr->dirty = TRUE;
534 		setConfigChanged( configOptions, configOptionsCount );
535 		return( CRYPT_OK );
536 		}
537 
538 	/* Try and allocate room for the new option */
539 	if( ( valuePtr = clAlloc( "setOptionString", valueLength ) ) == NULL )
540 		return( CRYPT_ERROR_MEMORY );
541 	memcpy( valuePtr, value, valueLength );
542 
543 	/* If the string value that's currently set isn't the default setting,
544 	   clear and free it */
545 	if( optionInfoPtr->strValue != NULL && \
546 		optionInfoPtr->strValue != builtinOptionInfoPtr->strDefault )
547 		{
548 		zeroise( optionInfoPtr->strValue, optionInfoPtr->intValue );
549 		clFree( "setOptionString", optionInfoPtr->strValue );
550 		}
551 
552 	/* Set the value and remember that the configuration options have been
553 	   changed */
554 	optionInfoPtr->strValue = valuePtr;
555 	optionInfoPtr->intValue = valueLength;
556 	optionInfoPtr->dirty = TRUE;
557 	setConfigChanged( configOptions, configOptionsCount );
558 	return( CRYPT_OK );
559 	}
560 
561 /****************************************************************************
562 *																			*
563 *						Misc.Configuration Options Routines					*
564 *																			*
565 ****************************************************************************/
566 
567 /* Delete an option */
568 
569 CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
deleteOption(INOUT_ARRAY (configOptionsCount)TYPECAST (OPTION_INFO *)void * configOptions,IN_INT_SHORT const int configOptionsCount,IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE option)570 int deleteOption( INOUT_ARRAY( configOptionsCount ) TYPECAST( OPTION_INFO * ) \
571 						void *configOptions,
572 				  IN_INT_SHORT const int configOptionsCount,
573 				  IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE option )
574 	{
575 	const BUILTIN_OPTION_INFO *builtinOptionInfoPtr;
576 	OPTION_INFO *optionInfoPtr;
577 
578 	assert( isReadPtr( configOptions,
579 					   sizeof( OPTION_INFO ) * configOptionsCount ) );
580 
581 	REQUIRES( configOptionsCount > 0 && \
582 			  configOptionsCount < MAX_INTLENGTH_SHORT );
583 	REQUIRES( option > CRYPT_OPTION_FIRST && option < CRYPT_OPTION_LAST );
584 
585 	/* Get a pointer to the option information and make sure that everything
586 	   is OK */
587 	optionInfoPtr = ( OPTION_INFO * ) \
588 					getOptionInfo( configOptions, configOptionsCount, option );
589 	ENSURES( optionInfoPtr != NULL );
590 	builtinOptionInfoPtr = optionInfoPtr->builtinOptionInfo;
591 	ENSURES( builtinOptionInfoPtr != NULL && \
592 			 builtinOptionInfoPtr->type == OPTION_STRING );
593 
594 	/* If we're deleting an option it can only be a string option without a
595 	   built-in default to fall back on (enforced by the kernel).  Since
596 	   these options don't have default values we check for a setting of
597 	   NULL rather than equivalence to a default string value.  In addition
598 	   since they contain a mixture of fixed and user-definable fields we
599 	   have to clear the fields explicitly rather than using a memset() */
600 	ENSURES( builtinOptionInfoPtr->strDefault == NULL );
601 	if( optionInfoPtr->strValue == NULL )
602 		return( CRYPT_ERROR_NOTFOUND );
603 	zeroise( optionInfoPtr->strValue, optionInfoPtr->intValue );
604 	clFree( "setOptionString", optionInfoPtr->strValue );
605 	optionInfoPtr->strValue = NULL;
606 	optionInfoPtr->intValue = 0;
607 	optionInfoPtr->dirty = TRUE;
608 	setConfigChanged( configOptions, configOptionsCount );
609 	return( CRYPT_OK );
610 	}
611 
612 /* Initialise/shut down the configuration option handling */
613 
614 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
initOptions(OUT_PTR_COND void ** configOptionsPtr,OUT_INT_SHORT_Z int * configOptionsCount)615 int initOptions( OUT_PTR_COND void **configOptionsPtr,
616 				 OUT_INT_SHORT_Z int *configOptionsCount )
617 	{
618 	OPTION_INFO *optionList;
619 	int i;
620 
621 	/* Clear return values */
622 	*configOptionsPtr = NULL;
623 	*configOptionsCount = 0;
624 
625 	/* Perform a consistency check on the options */
626 #ifndef CONFIG_FUZZ
627 	FORALL( i, 0, CRYPT_OPTION_LAST - CRYPT_OPTION_FIRST - 1,
628 			builtinOptionInfo[ i ].option == i + CRYPT_OPTION_FIRST + 1 );
629 #endif /* !CONFIG_FUZZ */
630 
631 	/* Allocate storage for the variable configuration data */
632 	if( ( optionList = clAlloc( "initOptions", OPTION_INFO_SIZE ) ) == NULL )
633 		return( CRYPT_ERROR_MEMORY );
634 	memset( optionList, 0, OPTION_INFO_SIZE );
635 
636 	/* Walk through the configuration option list setting up each option to
637 	   contain its default value */
638 	for( i = 0; builtinOptionInfo[ i ].option != CRYPT_ATTRIBUTE_NONE && \
639 				i < FAILSAFE_ARRAYSIZE( builtinOptionInfo, \
640 										BUILTIN_OPTION_INFO ); i++ )
641 		{
642 		const BUILTIN_OPTION_INFO *builtinOptionInfoPtr = &builtinOptionInfo[ i ];
643 		OPTION_INFO *optionInfoPtr = &optionList[ i ];
644 
645 		if( builtinOptionInfoPtr->type == OPTION_STRING )
646 			optionInfoPtr->strValue = ( char * ) builtinOptionInfoPtr->strDefault;
647 		optionInfoPtr->intValue = builtinOptionInfoPtr->intDefault;
648 		optionInfoPtr->builtinOptionInfo = builtinOptionInfoPtr;
649 		}
650 	ENSURES( i < FAILSAFE_ARRAYSIZE( builtinOptionInfo, BUILTIN_OPTION_INFO ) );
651 	*configOptionsPtr = optionList;
652 	*configOptionsCount = FAILSAFE_ARRAYSIZE( builtinOptionInfo, \
653 											  BUILTIN_OPTION_INFO );
654 
655 	return( CRYPT_OK );
656 	}
657 
658 STDC_NONNULL_ARG( ( 1 ) ) \
endOptions(IN_ARRAY (configOptionsCount)TYPECAST (OPTION_INFO *)void * configOptions,IN_INT_SHORT const int configOptionsCount)659 void endOptions( IN_ARRAY( configOptionsCount ) TYPECAST( OPTION_INFO * ) \
660 					void *configOptions,
661 				 IN_INT_SHORT const int configOptionsCount )
662 	{
663 	OPTION_INFO *optionList = configOptions;
664 	int i;
665 
666 	assert( isReadPtr( configOptions,
667 					   sizeof( OPTION_INFO ) * configOptionsCount ) );
668 
669 	REQUIRES_V( configOptionsCount > 0 && \
670 				configOptionsCount < MAX_INTLENGTH_SHORT );
671 
672 	/* Walk through the configuration option list clearing and freeing each
673 	   option */
674 	for( i = 0; builtinOptionInfo[ i ].option != CRYPT_ATTRIBUTE_NONE && \
675 				i < FAILSAFE_ARRAYSIZE( builtinOptionInfo, BUILTIN_OPTION_INFO );
676 		 i++ )
677 		{
678 		const BUILTIN_OPTION_INFO *builtinOptionInfoPtr = &builtinOptionInfo[ i ];
679 		OPTION_INFO *optionInfoPtr = &optionList[ i ];
680 
681 		if( builtinOptionInfoPtr->type == OPTION_STRING )
682 			{
683 			/* If the string value that's currently set isn't the default
684 			   setting, clear and free it */
685 			if( optionInfoPtr->strValue != builtinOptionInfoPtr->strDefault )
686 				{
687 				zeroise( optionInfoPtr->strValue, optionInfoPtr->intValue );
688 				clFree( "endOptions", optionInfoPtr->strValue );
689 				}
690 			}
691 		}
692 	ENSURES_V( i < FAILSAFE_ARRAYSIZE( builtinOptionInfo, BUILTIN_OPTION_INFO ) );
693 	ENSURES_V( i == configOptionsCount - 1 );
694 
695 	/* Clear and free the configuration option list */
696 	memset( optionList, 0, sizeof( OPTION_INFO ) * configOptionsCount );
697 	clFree( "endOptions", optionList );
698 	}
699