1 /****************************************************************************
2 *																			*
3 *							cryptlib DBMS Interface							*
4 *						Copyright Peter Gutmann 1996-2014					*
5 *																			*
6 ****************************************************************************/
7 
8 #ifndef _DBMS_DEFINED
9 
10 #define _DBMS_DEFINED
11 
12 #include <stdarg.h>
13 #if defined( INC_ALL )
14   #include "crypt.h"
15   #include "stream.h"
16 #else
17   #include "crypt.h"
18   #include "io/stream.h"
19 #endif /* Compiler-specific includes */
20 
21 /****************************************************************************
22 *																			*
23 *							Database Keyset Headers							*
24 *																			*
25 ****************************************************************************/
26 
27 /* Handle ODBC support.  This gets rather complex, with all sorts of special-
28    case handling of headers and types required across different systems */
29 
30 #ifdef USE_ODBC
31 
32 /* As part of the ever-changing way of identifying Win32, Microsoft changed
33    the predefined constant from WIN32 to _WIN32 in VC++ 2.1.  However the
34    ODBC header files still expect to find WIN32 and if this isn't defined
35    will use the default (i.e. C) calling convention instead of the Pascal
36    convention which is actually used by the ODBC functions.  This means that
37    both the caller and the callee clean up the stack so that for each ODBC
38    call the stack creeps upwards by a few bytes until eventually the local
39    variables and/or return address get trashed.  This problem is usually
40    hidden by the fact that something else defines WIN32 so everything works
41    OK, but the October 1997 development platform upgrade changes this so
42    that compiling the code after this update is installed breaks things.  To
43    avoid this problem, we define WIN32 if it isn't defined, which ensures
44    that the ODBC header files work properly */
45 #if defined( __WIN32__ ) && !defined( WIN32 )
46   #define WIN32
47 #endif /* __WIN32__ && !WIN32 */
48 
49 #ifdef __WINDOWS__
50   /* Borland have their own weird place to put ODBC headers */
51   #if defined( __BORLANDC__ )
52 	#include <mfc/sqltypes.h>
53   #else
54 	/* UnixODBC defines its own version of various Windows types, if we're
55 	   building under Windows we have to disable this.  The UnixODBC headers
56 	   have a guard ALLREADY_HAVE_WINDOWS_TYPE (sic) but this is all-or-
57 	   nothing, disabling the defining of Windows *and* SQL types.  Defining
58 	   the guard value fixes most compile problems but in order to build it
59 	   the commented-out typedefs also need to be defined.  These are
60 	   already defined in the standard (Windows) sqltypes.h so their use
61 	   needs to be manually enabled for UnixODBC under Windows, which is
62 	   unlikely to occur given that it's a Unix-only driver */
63 	#define ALLREADY_HAVE_WINDOWS_TYPE
64 	#if 0
65 	typedef signed short RETCODE;
66 	typedef short int SWORD;
67 	typedef long int SDWORD;
68 	typedef signed char SQLSCHAR;
69 	typedef HWND SQLHWND;
70 	#endif /* 0 */
71 
72 	#pragma warning( push )
73 	#pragma warning( disable : 4255 )	/* Errors in sqlext.h */
74 	#include <sql.h>
75 	#include <sqlext.h>
76 	#pragma warning( pop )
77   #endif /* Compiler-specific include locations */
78 #else
79   #include <sql.h>
80   #include <sqlext.h>
81 #endif /* Windows vs.everything else */
82 
83 #endif /* USE_ODBC */
84 
85 /****************************************************************************
86 *																			*
87 *							Database Keyset Constants						*
88 *																			*
89 ****************************************************************************/
90 
91 /* The size of the ID fields, derived from the base64-encoded first 128 bits
92    of an SHA-1 hash.  The field size value is also given in text form for
93    use in SQL strings */
94 
95 #define DBXKEYID_SIZE			16		/* Full keyID = 128 bits */
96 #define ENCODED_DBXKEYID_SIZE	22		/* base64-encoded key ID */
97 #define TEXT_DBXKEYID_SIZE		"22"
98 
99 /* The maximum SQL query size */
100 
101 #define MAX_SQL_QUERY_SIZE		256
102 
103 /* When performing a query the database glue code limits the maximum returned
104    data size to a certain size, the following define allows us to declare a
105    fixed-size buffer that we know will always be big enough */
106 
107 #define MAX_QUERY_RESULT_SIZE	MAX_ENCODED_CERT_SIZE
108 
109 /* Database status flags.  These are:
110 
111 	FLAG_BINARYBLOBS: Database supports binary blobs.
112 
113 	FLAG_CERTSTORE/FLAG_CERTSTORE_FIELDS: Certificate stores are designated
114 			by two flags, a main one for standard database/certificate store
115 			differentiation and a secondary one that indicates that it's a
116 			certificate store opened as a standard database, for example
117 			when it's being used for read-only access with a key server.  In
118 			this case it's possible to perform extended queries on fields
119 			that aren't present in standard databases so we set the
120 			secondary flags to indicate that extended queries are possible
121 			even though certificate store functionality isn't present.
122 
123 	FLAG_QUERYACTIVE: A query (returning a multiple-element result set) is
124 			currently in progress.
125 
126 	FLAG_UPDATEACTIVE: An update is currently in progress.  This is required
127 			because we can sometimes run into a situation where an update
128 			falls through to an abort without ever having been begun, this
129 			happens if there's a sequence of miscellaneous setup operations
130 			taking place and one of them fails before we begin the update.
131 			Although it'd be better if the caller handled this, in practice
132 			it'd mean passing extra status information (failed vs.failed but
133 			need to abort a commenced update) across a number of different
134 			functions, to avoid this we record whether an update has begun
135 			and if not skip an abort operation if there's no update currently
136 			in progress */
137 
138 #define DBMS_FLAG_NONE			0x00	/* No DBMS flag */
139 #define DBMS_FLAG_BINARYBLOBS	0x01	/* DBMS supports blobs */
140 #define DBMS_FLAG_UPDATEACTIVE	0x02	/* Ongoing update in progress */
141 #define DBMS_FLAG_QUERYACTIVE	0x04	/* Ongoing query in progress */
142 #define DBMS_FLAG_CERTSTORE		0x08	/* Full certificate store */
143 #define DBMS_FLAG_CERTSTORE_FIELDS 0x10	/* Certificate store fields */
144 #define DBMS_FLAG_MAX			0x1F	/* Maximum possible flag value */
145 
146 /* Database feature information returned when the keyset is opened */
147 
148 #define DBMS_FEATURE_FLAG_NONE	0x00	/* No DBMS features */
149 #define DBMS_FEATURE_FLAG_BINARYBLOBS 0x01 /* DBMS supports binary blobs */
150 #define DBMS_FEATURE_FLAG_READONLY 0x02	/* DBMS doesn't allow write access */
151 #define DBMS_FEATURE_FLAG_PRIVILEGES 0x04 /* DBMS supports GRANT/REVOKE */
152 #define DBMS_FEATURE_FLAG_MAX	0x07	/* Maximum possible flag value */
153 
154 /* The certstore and binary blobs flags are checked often enough that we
155    define a macro for them */
156 
157 #define hasBinaryBlobs( dbmsInfo ) \
158 		( ( dbmsInfo )->flags & DBMS_FLAG_BINARYBLOBS )
159 #define isCertStore( dbmsInfo ) \
160 		( ( dbmsInfo )->flags & DBMS_FLAG_CERTSTORE )
161 
162 /* When we perform a DBMS transaction there are several variations on the
163    basic operation type.  The following values tell performQuery() and
164    performUpdate() which type of operation to perform */
165 
166 typedef enum {
167 	DBMS_QUERY_NONE,				/* No DBMS query */
168 	DBMS_QUERY_NORMAL,				/* Standard data fetch */
169 	DBMS_QUERY_CHECK,				/* Check-type fetch, don't fetch data */
170 	DBMS_QUERY_START,				/* Begin an ongoing query */
171 	DBMS_QUERY_CONTINUE,			/* Continue an ongoing query */
172 	DBMS_QUERY_CANCEL,				/* Cancel ongoing query */
173 	DBMS_QUERY_LAST					/* Last valid DBMS query type */
174 	} DBMS_QUERY_TYPE;
175 
176 typedef enum {
177 	DBMS_UPDATE_NONE,				/* No DBMS update */
178 	DBMS_UPDATE_NORMAL,				/* Standard update */
179 	DBMS_UPDATE_BEGIN,				/* Begin a transaction */
180 	DBMS_UPDATE_CONTINUE,			/* Continue an ongoing transaction */
181 	DBMS_UPDATE_COMMIT,				/* Commit a transaction */
182 	DBMS_UPDATE_ABORT,				/* Abort a transaction */
183 	DBMS_UPDATE_LAST				/* Last valid DBMS update type */
184 	} DBMS_UPDATE_TYPE;
185 
186 /* To optimise database accesses we use prepared queries that are prepared
187    once and then re-used whenever a new result set is required.  The following
188    values are used to refer to the prepared query types */
189 
190 typedef enum {
191 	DBMS_CACHEDQUERY_NONE,			/* No cached query */
192 	DBMS_CACHEDQUERY_CERTID,		/* Query on certificate ID */
193 	DBMS_CACHEDQUERY_ISSUERID,		/* Query on issuer ID */
194 	DBMS_CACHEDQUERY_NAMEID,		/* Query in name ID */
195 	DBMS_CACHEDQUERY_URI,			/* Query on URI */
196 	DBMS_CACHEDQUERY_LAST			/* Last valid cached query type */
197 	} DBMS_CACHEDQUERY_TYPE;
198 
199 #define NO_CACHED_QUERIES	5
200 
201 /* When we add or read information to/from a table we sometimes have to
202    specify type information which is an integer value, however SQL requires
203    that things be set out as character strings so we use the following
204    defines to provide the string form of the value for insertion into an SQL
205    query.  Unfortunately we can't check this at compile time so we have to
206    check it via an assertion in the CA dispatch function */
207 
208 #define TEXT_CERTTYPE_REQUEST_CERT			"5"
209 #define TEXT_CERTTYPE_REQUEST_REVOCATION	"6"
210 
211 #define TEXT_CERTACTION_CREATE				"1"
212 #define TEXTCH_CERTACTION_ADDUSER			'5'
213 #define TEXT_CERTACTION_REQUEST_CERT		"7"
214 #define TEXTCH_CERTACTION_REQUEST_CERT		'7'
215 #define TEXT_CERTACTION_REQUEST_RENEWAL		"8"
216 #define TEXTCH_CERTACTION_REQUEST_RENEWAL	'8'
217 #define TEXT_CERTACTION_CERT_CREATION		"10"
218 
219 /* Special escape strings used in database keys to indicate that the value is
220    physically but not logically present.  This is used to handle (currently-)
221    incomplete certificate issues and similar events where intermediate state
222    information has to be stored in the database but the object in question
223    isn't ready for use yet */
224 
225 #define KEYID_ESC1				"--"
226 #define KEYID_ESC2				"##"
227 #define KEYID_ESC_SIZE			2
228 
229 /* The ways in which we can add a certificate object to a table.  Normally
230    we just add the certificate as is, however if we're awaiting confirmation
231    from a user before we can complete the certificate issue process we
232    perform a partial add that marks the certificate as not quite ready for
233    use yet.  A variant of this is when we're renewing a certificate (i.e.
234    re-issuing it with the same key, which is really bad but required by some
235    certificate mismanagement protocols) in which case we have to process the
236    update as a multi-stage process because we're replacing an existing
237    certificate with one which is exactly the same as far as the uniqueness
238    constraints on the certificate store are concerned */
239 
240 typedef enum {
241 	CERTADD_NONE,				/* No certificate-add operation */
242 	CERTADD_NORMAL,				/* Standard one-step add */
243 	CERTADD_PARTIAL,			/* Partial add */
244 	CERTADD_PARTIAL_RENEWAL,	/* Partial add with certificate replacement to follow */
245 	CERTADD_RENEWAL_COMPLETE,	/* Completion of renewal */
246 	CERTADD_LAST				/* Last valid certificate-add type */
247 	} CERTADD_TYPE;
248 
249 /* In order to make reporting of parameter errors in the multi-parameter
250    CA management function easier we provide symbolic defines mapping the
251    CA management-specific parameter type to its corresponding parameter
252    error type */
253 
254 #define CAMGMT_ARGERROR_CAKEY		CRYPT_ARGERROR_NUM1
255 #define CAMGMT_ARGERROR_REQUEST		CRYPT_ARGERROR_NUM2
256 #define CAMGMT_ARGERROR_ACTION		CRYPT_ARGERROR_VALUE
257 
258 /* To avoid SQL injection attacks and speed up performance we make extensive
259    use of bound parameters.  The following structure is used to communicate
260    these parameters to the database back-end */
261 
262 typedef enum {
263 	BOUND_DATA_NONE,		/* No bound data type */
264 	BOUND_DATA_STRING,		/* Character string */
265 	BOUND_DATA_BLOB,		/* Binary string */
266 	BOUND_DATA_TIME,		/* Date/time */
267 	BOUND_DATA_LAST			/* Last bound data type */
268 	} BOUND_DATA_TYPE;
269 
270 typedef struct {
271 	BOUND_DATA_TYPE type;	/* Type of this data item */
272 	BUFFER_FIXED( dataLength ) \
273 	const void *data;		/* Data and data length */
274 	int dataLength;
275 	} BOUND_DATA;
276 
277 #define BOUND_DATA_MAXITEMS		16
278 
279 /* Macros to initialise the bound-data information.  When we're binding
280    standard data values (i.e. non-blob data) the buffer to contain the value
281    is always present but if there's no data in it then the length will be
282    zero, so we perform a check for a buffer with a length of zero and set
283    the buffer pointer to NULL if this is the case */
284 
285 #define initBoundData( boundData ) \
286 		memset( ( boundData ), 0, sizeof( BOUND_DATA ) * BOUND_DATA_MAXITEMS )
287 #define setBoundData( bdStorage, bdIndex, bdValue, bdValueLen ) \
288 		{ \
289 		const int bdLocalIndex = ( bdIndex ); \
290 		\
291 		( bdStorage )[ bdLocalIndex ].type = BOUND_DATA_STRING; \
292 		( bdStorage )[ bdLocalIndex ].data = ( bdValueLen > 0 ) ? bdValue : NULL; \
293 		( bdStorage )[ bdLocalIndex ].dataLength = bdValueLen; \
294 		}
295 #define setBoundDataBlob( bdStorage, bdIndex, bdValue, bdValueLen ) \
296 		{ \
297 		const int bdLocalIndex = ( bdIndex ); \
298 		\
299 		( bdStorage )[ bdLocalIndex ].type = BOUND_DATA_BLOB; \
300 		( bdStorage )[ bdLocalIndex ].data = bdValue; \
301 		( bdStorage )[ bdLocalIndex ].dataLength = bdValueLen; \
302 		}
303 #define setBoundDataDate( bdStorage, bdIndex, bdValue ) \
304 		{ \
305 		const int bdLocalIndex = ( bdIndex ); \
306 		\
307 		( bdStorage )[ bdLocalIndex ].type = BOUND_DATA_TIME; \
308 		( bdStorage )[ bdLocalIndex ].data = bdValue; \
309 		( bdStorage )[ bdLocalIndex ].dataLength = sizeof( time_t ); \
310 		}
311 
312 /****************************************************************************
313 *																			*
314 *							Database Keyset Structures						*
315 *																			*
316 ****************************************************************************/
317 
318 /* A structure to parse the database access information into so that it can
319    be used by backend-specific connect functions */
320 
321 typedef struct {
322 	BUFFER( CRYPT_MAX_TEXTSIZE, userLen ) \
323 	char userBuffer[ CRYPT_MAX_TEXTSIZE + 8 ];
324 	BUFFER_OPT( CRYPT_MAX_TEXTSIZE, userLen ) \
325 	char *user;
326 	BUFFER( CRYPT_MAX_TEXTSIZE, passwordLen ) \
327 	char passwordBuffer[ CRYPT_MAX_TEXTSIZE + 8 ];
328 	BUFFER_OPT( CRYPT_MAX_TEXTSIZE, passwordLen ) \
329 	char *password;
330 	BUFFER( CRYPT_MAX_TEXTSIZE, serverLen ) \
331 	char serverBuffer[ CRYPT_MAX_TEXTSIZE + 8 ];
332 	BUFFER_OPT( CRYPT_MAX_TEXTSIZE, serverLen ) \
333 	char *server;
334 	BUFFER( CRYPT_MAX_TEXTSIZE, nameLen ) \
335 	char nameBuffer[ CRYPT_MAX_TEXTSIZE + 8 ];
336 	BUFFER_OPT( CRYPT_MAX_TEXTSIZE, nameLen ) \
337 	char *name;
338 	int userLen, passwordLen, serverLen, nameLen;
339 	} DBMS_NAME_INFO;
340 
341 /* Database state information maintained by the database back-end specific
342    code */
343 
344 typedef struct {
345 	/* DBMS status information */
346 	BOOLEAN needsUpdate;			/* Whether data remains to be committed */
347 	BOOLEAN hasBinaryBlobs;			/* Whether back-end supports binary blobs */
348 
349 	/* Error information returned by the back-end.  This is copied over to
350 	   the keyset object as required */
351 	ERROR_INFO errorInfo;
352 
353 	/* Database-specific information */
354   #ifdef USE_ODBC
355 	/* ODBC access information */
356 	SQLHENV hEnv;					/* Environment handle */
357 	SQLHDBC hDbc;					/* Connection handle */
358 	BOOLEAN connectionOpen;			/* Whether hDbc connection is active */
359 	ARRAY_FIXED( NO_CACHED_QUERIES ) \
360 	SQLHSTMT hStmt[ NO_CACHED_QUERIES + 8 ];/* Statement handles */
361 	ARRAY_FIXED( NO_CACHED_QUERIES ) \
362 	BOOLEAN hStmtPrepared[ NO_CACHED_QUERIES + 8 ];/* Whether stmt is prepared on handle */
363 	BOOLEAN transactIsDestructive;	/* Whether commit/rollback destroys prep'd queries */
364 	SQLSMALLINT blobType;			/* SQL type of blob data type */
365 	BUFFER( CRYPT_MAX_TEXTSIZE, blobNameLength ) \
366 	char blobName[ CRYPT_MAX_TEXTSIZE + 8 ];/* Name of blob data type */
367 	int blobNameLength;				/* Length of blob data type name */
368 	SQLINTEGER dateTimeNameColSize;	/* Back-end specific size of datetime column */
369 	BUFFER( CRYPT_MAX_TEXTSIZE, dateTimeNameLength ) \
370 	char dateTimeName[ CRYPT_MAX_TEXTSIZE + 8 ];/* Name of datetime data type */
371 	int dateTimeNameLength;			/* Length of datetime data type name */
372 	BOOLEAN needLongLength;			/* Back-end needs blob length at bind.time */
373 	int backendType;				/* Back-end type if special handling is req'd */
374   #endif /* USE_ODBC */
375   #ifdef USE_DATABASE
376 	#error Need to add database backend-specific state variables
377   #endif /* USE_DATABASE */
378   #ifdef USE_TCP
379 	STREAM stream;					/* Network I/O stream */
380   #endif /* USE_TCP */
381 	} DBMS_STATE_INFO;
382 
383 /****************************************************************************
384 *																			*
385 *								DBMS Access Macros							*
386 *																			*
387 ****************************************************************************/
388 
389 /* Macros to make use of the DBMS access functions less painful.  These
390    assume the existence of a variable 'dbmsInfo' that contains DBMS access
391    state information */
392 
393 #define dbmsOpen( name, nameLen, options, featureFlags ) \
394 		dbmsInfo->openDatabaseFunction( dbmsInfo, name, nameLen, options, featureFlags )
395 #define dbmsClose() \
396 		dbmsInfo->closeDatabaseFunction( dbmsInfo )
397 #define dbmsStaticUpdate( command ) \
398 		dbmsInfo->performStaticUpdateFunction( dbmsInfo, command )
399 #define dbmsUpdate( command, updateBoundData, updateType ) \
400 		dbmsInfo->performUpdateFunction( dbmsInfo, command, updateBoundData, \
401 										 updateType )
402 #define dbmsStaticQuery( command, queryEntry, queryType ) \
403 		dbmsInfo->performStaticQueryFunction( dbmsInfo, command, queryEntry, \
404 											  queryType )
405 #define dbmsQuery( command, data, dataMaxLength, dataLength, queryBoundData, queryEntry, queryType ) \
406 		dbmsInfo->performQueryFunction( dbmsInfo, command, data, dataMaxLength, \
407 										dataLength, queryBoundData, queryEntry, \
408 										queryType )
409 
410 #ifdef USE_RPCAPI
411 int cmdClose( void *stateInfo, COMMAND_INFO *cmd );
412 int cmdGetErrorInfo( void *stateInfo, COMMAND_INFO *cmd );
413 int cmdOpen( void *stateInfo, COMMAND_INFO *cmd );
414 int cmdQuery( void *stateInfo, COMMAND_INFO *cmd );
415 int cmdUpdate( void *stateInfo, COMMAND_INFO *cmd );
416 #endif /* USE_RPCAPI */
417 
418 /* In order to provide access to the backend-specific error information for
419    the cryptlib error message-formatting routines we need to dig down into
420    the DBMS state structure to extract the error information */
421 
422 #define getDbmsErrorInfo( dbmsInfo ) \
423 		( &( ( ( DBMS_STATE_INFO * ) ( dbmsInfo )->stateInfo )->errorInfo ) )
424 
425 /* Other non-macro functions */
426 
427 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 4 ) ) \
428 int dbmsFormatQuery( OUT_BUFFER( outMaxLength, *outLength ) char *output,
429 					 IN_LENGTH_SHORT const int outMaxLength,
430 					 OUT_LENGTH_BOUNDED_Z( outMaxLength ) int *outLength,
431 					 IN_BUFFER( inputLength ) const char *input,
432 					 IN_LENGTH_SHORT const int inputLength );
433 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
434 int dbmsParseName( OUT DBMS_NAME_INFO *nameInfo,
435 				   IN_BUFFER( nameLen ) const char *name,
436 				   IN_LENGTH_NAME const int nameLen );
437 
438 /****************************************************************************
439 *																			*
440 *								DBMS Functions								*
441 *																			*
442 ****************************************************************************/
443 
444 /* Forward declaration for argument to function pointers.  These structs are
445    declared in keyset.h, but that's included after dbms.h since the structs
446    in keyset.h depend on values in dbms.h */
447 
448 struct DI;
449 struct KI;
450 
451 /* Prototypes for interface routines in DBMS modules */
452 
453 CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
454 int initDbxSession( INOUT struct KI *keysetInfoPtr,
455 					IN_ENUM( CRYPT_KEYSET ) const CRYPT_KEYSET_TYPE type );
456 RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
457 int endDbxSession( INOUT struct KI *keysetInfoPtr );
458 CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
459 int initDBMSread( INOUT struct KI *keysetInfoPtr );
460 CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
461 int initDBMSwrite( INOUT struct KI *keysetInfoPtr );
462 CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
463 int initDBMSCA( INOUT struct KI *keysetInfoPtr );
464 
465 /* Prototypes for functions in dbx_rd.c/dbx_wr.c */
466 
467 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 9 ) ) \
468 int getItemData( INOUT struct DI *dbmsInfo,
469 				 OUT_HANDLE_OPT CRYPT_CERTIFICATE *iCertificate,
470 				 OUT_OPT int *stateInfo,
471 				 IN_ENUM_OPT( KEYMGMT_ITEM ) const KEYMGMT_ITEM_TYPE itemType,
472 				 IN_ENUM_OPT( CRYPT_KEYID ) const CRYPT_KEYID_TYPE keyIDtype,
473 				 IN_BUFFER_OPT( keyValueLength ) const char *keyValue,
474 				 IN_LENGTH_KEYID_Z const int keyValueLength,
475 				 IN_FLAGS_Z( KEYMGMT ) const int options,
476 				 INOUT ERROR_INFO *errorInfo );
477 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 6 ) ) \
478 int addCert( INOUT struct DI *dbmsInfo,
479 			 IN_HANDLE const CRYPT_HANDLE iCryptHandle,
480 			 IN_ENUM( CRYPT_CERTTYPE ) const CRYPT_CERTTYPE_TYPE certType,
481 			 IN_ENUM( CERTADD ) const CERTADD_TYPE addType,
482 			 IN_ENUM( DBMS_UPDATE ) const DBMS_UPDATE_TYPE updateType,
483 			 INOUT ERROR_INFO *errorInfo );
484 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 5 ) ) \
485 int addCRL( INOUT struct DI *dbmsInfo,
486 			IN_HANDLE const CRYPT_CERTIFICATE iCryptCRL,
487 			IN_HANDLE_OPT const CRYPT_CERTIFICATE iCryptRevokeCert,
488 			IN_ENUM( DBMS_UPDATE ) const DBMS_UPDATE_TYPE updateType,
489 			INOUT ERROR_INFO *errorInfo );
490 
491 /* Prototypes for routines in dbx_misc.c */
492 
493 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 5 ) ) \
494 int makeKeyID( OUT_BUFFER( keyIdMaxLen, *keyIdLen ) char *keyID,
495 			   IN_LENGTH_SHORT_MIN( ENCODED_DBXKEYID_SIZE ) \
496 					const int keyIdMaxLen,
497 			   OUT_LENGTH_BOUNDED_Z( keyIdMaxLen ) int *keyIdLen,
498 			   IN_KEYID const CRYPT_KEYID_TYPE iDtype,
499 			   IN_BUFFER( idValueLength ) const void *idValue,
500 			   IN_LENGTH_SHORT const int idValueLength );
501 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \
502 int getKeyID( OUT_BUFFER( keyIdMaxLen, *keyIdLen ) char *keyID,
503 			  IN_LENGTH_SHORT_MIN( 16 ) const int keyIdMaxLen,
504 			  OUT_LENGTH_BOUNDED_Z( keyIdMaxLen ) int *keyIdLen,
505 			  IN_HANDLE const CRYPT_HANDLE cryptHandle,
506 			  IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE keyIDtype );
507 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \
508 int getCertKeyID( OUT_BUFFER( keyIdMaxLen, *keyIdLen ) char *keyID,
509 				  IN_LENGTH_SHORT_MIN( 16 ) const int keyIdMaxLen,
510 				  OUT_LENGTH_BOUNDED_Z( keyIdMaxLen ) int *keyIdLen,
511 				  IN_HANDLE const CRYPT_CERTIFICATE iCryptCert );
512 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \
513 int getPkiUserKeyID( OUT_BUFFER( keyIdMaxLen, *keyIdLen ) char *keyID,
514 					 IN_LENGTH_SHORT_MIN( 16 ) const int keyIdMaxLen,
515 					 OUT_LENGTH_BOUNDED_Z( keyIdMaxLen ) int *keyIdLen,
516 					 IN_HANDLE const CRYPT_CERTIFICATE iCryptCert );
517 CHECK_RETVAL STDC_NONNULL_ARG( ( 3, 5 ) ) \
518 int extractCertData( IN_HANDLE const CRYPT_CERTIFICATE iCryptCert,
519 					 IN_INT const int formatType,
520 					 OUT_BUFFER( certDataMaxLength, *certDataLength ) \
521 						void *certDataBuffer,
522 					 IN_LENGTH_SHORT_MIN( MIN_CRYPT_OBJECTSIZE ) \
523 						const int certDataMaxLength,
524 					 OUT_LENGTH_BOUNDED_Z( certDataMaxLength ) \
525 						int *certDataLength );
526 RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
527 int resetErrorInfo( INOUT struct DI *dbmsInfo );
528 CHECK_RETVAL_PTR \
529 char *getKeyName( IN_ENUM( CRYPT_KEYID ) const CRYPT_KEYID_TYPE keyIDtype );
530 
531 /* Prototypes for routines in ca_add.c */
532 
533 CHECK_RETVAL_BOOL \
534 BOOLEAN checkRequest( IN_HANDLE const CRYPT_CERTIFICATE iCertRequest,
535 					  IN_ENUM_OPT( CRYPT_CERTACTION ) \
536 						const CRYPT_CERTACTION_TYPE action );
537 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 6 ) ) \
538 int caAddCertRequest( INOUT struct DI *dbmsInfo,
539 					  IN_HANDLE const CRYPT_CERTIFICATE iCertRequest,
540 					  IN_ENUM( CRYPT_CERTTYPE ) \
541 						const CRYPT_CERTTYPE_TYPE requestType,
542 					  const BOOLEAN isRenewal, const BOOLEAN isInitialOp,
543 					  INOUT ERROR_INFO *errorInfo );
544 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \
545 int caAddPKIUser( INOUT struct DI *dbmsInfo,
546 				  IN_HANDLE const CRYPT_CERTIFICATE iPkiUser,
547 				  INOUT ERROR_INFO *errorInfo );
548 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 5 ) ) \
549 int caDeletePKIUser( INOUT struct DI *dbmsInfo,
550 					 IN_ENUM( CRYPT_KEYID ) const CRYPT_KEYID_TYPE keyIDtype,
551 					 IN_BUFFER( keyIDlength ) const void *keyID,
552 					 IN_LENGTH_KEYID const int keyIDlength,
553 					 INOUT ERROR_INFO *errorInfo );
554 
555 /* Prototypes for routines in ca_clean.c */
556 
557 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \
558 int caCleanup( INOUT struct DI *dbmsInfo,
559 			   IN_ENUM( CRYPT_CERTACTION ) const CRYPT_CERTACTION_TYPE action,
560 			   INOUT ERROR_INFO *errorInfo );
561 
562 /* Prototypes for routines in ca_issue.c */
563 
564 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \
565 int completeCertRenewal( INOUT struct DI *dbmsInfo,
566 						 IN_HANDLE const CRYPT_CERTIFICATE iReplaceCertificate,
567 						 INOUT ERROR_INFO *errorInfo );
568 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 6 ) ) \
569 int caIssueCert( INOUT struct DI *dbmsInfo,
570 				 OUT_OPT_HANDLE_OPT CRYPT_CERTIFICATE *iCertificate,
571 				 IN_HANDLE const CRYPT_CERTIFICATE caKey,
572 				 IN_HANDLE const CRYPT_CERTIFICATE iCertRequest,
573 				 IN_ENUM( CRYPT_CERTACTION ) const CRYPT_CERTACTION_TYPE action,
574 				 INOUT ERROR_INFO *errorInfo );
575 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 4 ) ) \
576 int caIssueCertComplete( INOUT struct DI *dbmsInfo,
577 						 IN_HANDLE const CRYPT_CERTIFICATE iCertificate,
578 						 IN_ENUM( CRYPT_CERTACTION ) \
579 							const CRYPT_CERTACTION_TYPE action,
580 						 INOUT ERROR_INFO *errorInfo );
581 
582 /* Prototypes for routines in ca_rev.c */
583 
584 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 4 ) ) \
585 int revokeCertDirect( INOUT struct DI *dbmsInfo,
586 					  IN_HANDLE const CRYPT_CERTIFICATE iCertificate,
587 					  IN_ENUM( CRYPT_CERTACTION ) \
588 						const CRYPT_CERTACTION_TYPE action,
589 					  INOUT ERROR_INFO *errorInfo );
590 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 5 ) ) \
591 int caRevokeCert( INOUT struct DI *dbmsInfo,
592 				  IN_HANDLE const CRYPT_CERTIFICATE iCertRequest,
593 				  IN_HANDLE_OPT const CRYPT_CERTIFICATE iCertificate,
594 				  IN_ENUM( CRYPT_CERTACTION ) const CRYPT_CERTACTION_TYPE action,
595 				  INOUT ERROR_INFO *errorInfo );
596 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \
597 int caIssueCRL( INOUT struct DI *dbmsInfo,
598 				OUT_HANDLE_OPT CRYPT_CERTIFICATE *iCryptCRL,
599 				IN_HANDLE const CRYPT_CONTEXT caKey,
600 				INOUT ERROR_INFO *errorInfo );
601 
602 /* Prototypes for routines in ca_misc.c */
603 
604 RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
605 int updateCertLog( INOUT struct DI *dbmsInfo,
606 				   IN_ENUM( CRYPT_CERTACTION ) const CRYPT_CERTACTION_TYPE action,
607 				   IN_BUFFER_OPT( certIDlength ) const char *certID,
608 				   IN_LENGTH_SHORT_Z const int certIDlength,
609 				   IN_BUFFER_OPT( reqCertIDlength ) const char *reqCertID,
610 				   IN_LENGTH_SHORT_Z const int reqCertIDlength,
611 				   IN_BUFFER_OPT( subjCertIDlength ) const char *subjCertID,
612 				   IN_LENGTH_SHORT_Z const int subjCertIDlength,
613 				   IN_BUFFER_OPT( dataLength ) const void *data,
614 				   IN_LENGTH_SHORT_Z const int dataLength,
615 				   IN_ENUM( DBMS_UPDATE ) const DBMS_UPDATE_TYPE updateType );
616 RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \
617 int updateCertErrorLog( INOUT struct DI *dbmsInfo,
618 						IN_ERROR const int errorStatus,
619 						IN_STRING const char *errorString,
620 						IN_BUFFER_OPT( certIDlength ) const char *certID,
621 						IN_LENGTH_SHORT_Z const int certIDlength,
622 						IN_BUFFER_OPT( reqCertIDlength ) const char *reqCertID,
623 						IN_LENGTH_SHORT_Z const int reqCertIDlength,
624 						IN_BUFFER_OPT( subjCertIDlength ) const char *subjCertID,
625 						IN_LENGTH_SHORT_Z const int subjCertIDlength,
626 						IN_BUFFER_OPT( dataLength ) const void *data,
627 						IN_LENGTH_SHORT_Z const int dataLength );
628 RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \
629 int updateCertErrorLogMsg( INOUT struct DI *dbmsInfo,
630 						   IN_ERROR const int errorStatus,
631 						   IN_STRING const char *errorString );
632 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3, 5 ) ) \
633 int caGetIssuingUser( INOUT struct DI *dbmsInfo,
634 					  OUT_HANDLE_OPT CRYPT_CERTIFICATE *iPkiUser,
635 					  IN_BUFFER( initialCertIDlength ) const char *initialCertID,
636 					  IN_LENGTH_FIXED( ENCODED_DBXKEYID_SIZE ) \
637 						const int initialCertIDlength,
638 					  INOUT ERROR_INFO *errorInfo );
639 
640 #endif /* _DBMS_DEFINED */
641 
642