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