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