cryptlib  3.4.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Macros
cmp_svr.c
Go to the documentation of this file.
1 /****************************************************************************
2 * *
3 * cryptlib CMP Server Management *
4 * Copyright Peter Gutmann 1999-2009 *
5 * *
6 ****************************************************************************/
7 
8 #if defined( INC_ALL )
9  #include "crypt.h"
10  #include "session.h"
11  #include "cmp.h"
12 #else
13  #include "crypt.h"
14  #include "session/session.h"
15  #include "session/cmp.h"
16 #endif /* Compiler-specific includes */
17 
18 #ifdef USE_CMP
19 
20 /****************************************************************************
21 * *
22 * Utility Routines *
23 * *
24 ****************************************************************************/
25 
26 /* Map request to response types */
27 
28 static const MAP_TABLE reqClibReqMapTbl[] = {
36  };
37 
38 CHECK_RETVAL_RANGE( CRYPT_REQUESTYPE_NONE, CRYPT_REQUESTYPE_LAST ) \
39 static int reqToClibReq( IN_ENUM_OPT( CTAG_PB ) const CMP_MESSAGE_TYPE reqType )
40  {
41  int value, status;
42 
43  REQUIRES( reqType >= CTAG_PB_IR && reqType < CTAG_PB_LAST );
44  /* CTAG_PB_IR == 0 so this is the same as _NONE */
45 
46  status = mapValue( reqType, &value, reqClibReqMapTbl,
47  FAILSAFE_ARRAYSIZE( reqClibReqMapTbl, MAP_TABLE ) );
48  return( cryptStatusError( status ) ? status : value );
49  }
50 
51 /* Set up user authentication information (either a MAC context or a public
52  key) based on a request submitted by the client. This is done whenever
53  the client starts a new transaction with a new user ID or certificate
54  ID */
55 
56 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
57 int initServerAuthentMAC( INOUT SESSION_INFO *sessionInfoPtr,
59  {
60  CMP_INFO *cmpInfo = sessionInfoPtr->sessionCMP;
61  MESSAGE_KEYMGMT_INFO getkeyInfo;
63  char password[ CRYPT_MAX_TEXTSIZE + 8 ];
64  int status;
65 
66  assert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );
67  assert( isWritePtr( protocolInfo, sizeof( CMP_PROTOCOL_INFO ) ) );
68 
69  /* Set up general authentication information and if there's user
70  information still present from a previous transaction, clear it */
71  status = setCMPprotocolInfo( protocolInfo, NULL, 0,
73  if( cryptStatusError( status ) )
74  return( status );
75  if( cmpInfo->userInfo != CRYPT_ERROR )
76  {
78  cmpInfo->userInfo = CRYPT_ERROR;
79  }
80 
81  /* Get the user information for the user identified by the user ID from
82  the certificate store. If we get a not-found error we report it as
83  "signer not trusted", which can also mean "signer unknown" */
84  setMessageKeymgmtInfo( &getkeyInfo, CRYPT_IKEYID_KEYID,
85  protocolInfo->userID, protocolInfo->userIDsize,
86  NULL, 0, KEYMGMT_FLAG_NONE );
87  status = krnlSendMessage( sessionInfoPtr->cryptKeyset,
88  IMESSAGE_KEY_GETKEY, &getkeyInfo,
90  if( cryptStatusError( status ) )
91  {
92  const ATTRIBUTE_LIST *userNamePtr = \
93  findSessionInfo( sessionInfoPtr->attributeList,
95  char userID[ CRYPT_MAX_TEXTSIZE + 8 ];
96  int userIDlen;
97 
98  REQUIRES( userNamePtr != NULL );
99  if( userNamePtr->flags & ATTR_FLAG_ENCODEDVALUE )
100  {
101  userIDlen = min( userNamePtr->valueLength, CRYPT_MAX_TEXTSIZE );
102  memcpy( userID, userNamePtr->value, userIDlen );
103  }
104  else
105  {
106  /* The ID isn't a cryptlib user ID but a certificate ID used for
107  a cr rather than the user ID for an ir or rr (see the comment
108  at the start of initServerAuthentSign() for details), we have
109  to use a placeholder string since it's meaningless binary
110  data. We can't try and map this to a user ID since we've just
111  failed to find the PKI user object that would contain it.
112 
113  Alternatively, in less likely cases it could also be an
114  incorrect user ID that we couldn't recognise and record as a
115  cryptlib user ID, which we can't do much with either */
116  userIDlen = 18;
117  memcpy( userID, "the requested user", userIDlen );
118  }
119  protocolInfo->pkiFailInfo = CMPFAILINFO_SIGNERNOTTRUSTED;
120  retExtObj( status,
121  ( status, SESSION_ERRINFO, sessionInfoPtr->cryptKeyset,
122  "Couldn't find PKI user information for %s",
123  sanitiseString( userID, CRYPT_MAX_TEXTSIZE,
124  userIDlen ) ) );
125  }
126  cmpInfo->userInfo = getkeyInfo.cryptHandle;
127  protocolInfo->userIDchanged = FALSE;
128 
129  /* Get the password from the PKI user object */
130  setMessageData( &msgData, password, CRYPT_MAX_TEXTSIZE );
131  status = krnlSendMessage( cmpInfo->userInfo, IMESSAGE_GETATTRIBUTE_S,
133  if( cryptStatusOK( status ) )
134  {
135  status = updateSessionInfo( &sessionInfoPtr->attributeList,
136  CRYPT_SESSINFO_PASSWORD, password,
137  msgData.length, CRYPT_MAX_TEXTSIZE,
139  }
140  zeroise( password, CRYPT_MAX_TEXTSIZE );
141  if( cryptStatusError( status ) )
142  {
143  retExt( status,
144  ( status, SESSION_ERRINFO,
145  "Couldn't copy PKI user data from PKI user object to "
146  "session object" ) );
147  }
148 
149  return( CRYPT_OK );
150  }
151 
152 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
153 int initServerAuthentSign( INOUT SESSION_INFO *sessionInfoPtr,
154  INOUT CMP_PROTOCOL_INFO *protocolInfo )
155  {
156  CMP_INFO *cmpInfo = sessionInfoPtr->sessionCMP;
157  MESSAGE_KEYMGMT_INFO getkeyInfo;
159  char userName[ CRYPT_MAX_TEXTSIZE + 8 ];
160  int status;
161 
162  assert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );
163  assert( isWritePtr( protocolInfo, sizeof( CMP_PROTOCOL_INFO ) ) );
164 
165  /* Set up general authentication information and if there's client
166  authentication information still present from a previous transaction
167  that used MAC authentication, clear it */
168  status = setCMPprotocolInfo( protocolInfo, NULL, 0, CMP_INIT_FLAG_NONE,
169  TRUE );
170  if( cryptStatusError( status ) )
171  return( status );
172  if( cmpInfo->userInfo != CRYPT_ERROR )
173  {
175  cmpInfo->userInfo = CRYPT_ERROR;
176  }
177 
178  /* Get the user information for the user that originally authorised the
179  issue of the certificate that signed the request. This serves two
180  purposes, it obtains the original user ID if it wasn't supplied in
181  the request (for example if the request uses only a certificate ID
182  from a certificate five generations downstream from the original PKI
183  user after an ir -> cr -> cr -> cr -> cr and we've got the
184  certificate ID from the final cr in the series), and it verifies that
185  the authorising certificate belongs to a currently valid user */
186  setMessageKeymgmtInfo( &getkeyInfo, CRYPT_IKEYID_CERTID,
187  protocolInfo->certID, protocolInfo->certIDsize,
188  NULL, 0, KEYMGMT_FLAG_GETISSUER );
189  status = krnlSendMessage( sessionInfoPtr->cryptKeyset,
190  IMESSAGE_KEY_GETKEY, &getkeyInfo,
192  if( cryptStatusError( status ) )
193  {
194  protocolInfo->pkiFailInfo = CMPFAILINFO_SIGNERNOTTRUSTED;
195  retExtObj( status,
196  ( status, SESSION_ERRINFO, sessionInfoPtr->cryptKeyset,
197  "Couldn't find PKI user information for owner of "
198  "requesting certificate" ) );
199  }
200  cmpInfo->userInfo = getkeyInfo.cryptHandle;
201 
202  /* Update the user ID from the PKI user object */
203  setMessageData( &msgData, userName, CRYPT_MAX_TEXTSIZE );
204  status = krnlSendMessage( getkeyInfo.cryptHandle,
205  IMESSAGE_GETATTRIBUTE_S, &msgData,
207  if( cryptStatusOK( status ) )
208  {
209  status = updateSessionInfo( &sessionInfoPtr->attributeList,
210  CRYPT_SESSINFO_USERNAME, userName,
211  msgData.length, CRYPT_MAX_TEXTSIZE,
213  }
214  if( cryptStatusError( status ) )
215  {
216  retExt( status,
217  ( status, SESSION_ERRINFO,
218  "Couldn't copy PKI user data from PKI user object to "
219  "session object" ) );
220  }
221 
222  /* Get the public key identified by the certificate ID from the
223  certificate store. This verifies the assumption that the owner of an
224  existing certificate/existing user is authorised to request further
225  certificates using the existing one. If we get a not found error we
226  report it as "signer not trusted", which can also mean "signer
227  unknown" */
228  setMessageKeymgmtInfo( &getkeyInfo, CRYPT_IKEYID_CERTID,
229  protocolInfo->certID, protocolInfo->certIDsize,
230  NULL, 0, KEYMGMT_FLAG_USAGE_SIGN );
231  status = krnlSendMessage( sessionInfoPtr->cryptKeyset,
232  IMESSAGE_KEY_GETKEY, &getkeyInfo,
234  if( cryptStatusError( status ) )
235  {
236  protocolInfo->pkiFailInfo = CMPFAILINFO_SIGNERNOTTRUSTED;
237  retExtObj( status,
238  ( status, SESSION_ERRINFO, sessionInfoPtr->cryptKeyset,
239  "Couldn't find certificate for requested user" ) );
240  }
241  sessionInfoPtr->iAuthInContext = getkeyInfo.cryptHandle;
242  protocolInfo->certIDchanged = FALSE;
243 
244  return( CRYPT_OK );
245  }
246 
247 /* Deliver an Einladung betreff Kehrseite to the client. We don't bother
248  checking the return value for the write since there's nothing that we can
249  do in the case of an error except close the connection, which we do
250  anyway since this is the last message */
251 
252 STDC_NONNULL_ARG( ( 1, 2 ) ) \
253 static void sendErrorResponse( INOUT SESSION_INFO *sessionInfoPtr,
254  INOUT CMP_PROTOCOL_INFO *protocolInfo,
255  IN_ERROR const int errorStatus )
256  {
257  BOOLEAN writeHttpResponseOnly = !protocolInfo->headerRead;
258  int status;
259 
260  assert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );
261  assert( isWritePtr( protocolInfo, sizeof( CMP_PROTOCOL_INFO ) ) );
262 
263  REQUIRES_V( cryptStatusError( errorStatus ) );
264 
265  /* If we were going to protect the communication with the client with a
266  MAC and something failed we don't try and MAC the response since the
267  failure could be a client MAC failure, failure to locate the MAC key,
268  or something similar */
269  protocolInfo->useMACsend = FALSE;
270  protocolInfo->status = errorStatus;
271 
272  /* Write the error response if we can. We only do this if at least the
273  header of the client's message was successfully read (indicated by
274  the headerRead flag in the protocolInfo being set), otherwise we
275  can't create our own header for the response */
276  sioctlSet( &sessionInfoPtr->stream, STREAM_IOCTL_LASTMESSAGE, TRUE );
277  if( !writeHttpResponseOnly )
278  {
279  status = writePkiMessage( sessionInfoPtr, protocolInfo, CMPBODY_ERROR );
280  if( cryptStatusError( status ) )
281  writeHttpResponseOnly = TRUE;
282  }
283  if( writeHttpResponseOnly )
284  {
285  HTTP_DATA_INFO httpDataInfo;
286 
287  /* If we encounter an error processing the initial request then
288  there won't be enough information available to create an error
289  response. At this point the best that we can do is send an error
290  at the HTTP level */
291  initHttpDataInfo( &httpDataInfo, sessionInfoPtr->receiveBuffer,
292  sessionInfoPtr->receiveBufSize );
293  httpDataInfo.reqStatus = errorStatus;
294  swrite( &sessionInfoPtr->stream, &httpDataInfo,
295  sizeof( HTTP_DATA_INFO ) );
296  }
297  else
298  {
299  DEBUG_DUMP_CMP( CTAG_PB_ERROR, 1, sessionInfoPtr );
300  ( void ) writePkiDatagram( sessionInfoPtr, CMP_CONTENT_TYPE,
302  }
303  }
304 
305 /****************************************************************************
306 * *
307 * Init/Shutdown Functions *
308 * *
309 ****************************************************************************/
310 
311 /* Exchange data with a CMP client */
312 
314 static int serverTransact( INOUT SESSION_INFO *sessionInfoPtr )
315  {
316  CMP_INFO *cmpInfo = sessionInfoPtr->sessionCMP;
317  MESSAGE_CERTMGMT_INFO certMgmtInfo;
318  MESSAGE_KEYMGMT_INFO setkeyInfo;
320  const ATTRIBUTE_LIST *userNamePtr;
321  int status;
322 
323  assert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );
324 
325  /* Initialise the server-side protocol state information. Since the
326  server doesn't have a user ID (it uses what the client sends it), we
327  set the userID-sent flag to indicate that it's been implicitly
328  exchanged */
329  initCMPprotocolInfo( &protocolInfo,
330  ( sessionInfoPtr->flags & SESSION_ISCRYPTLIB ) ? \
331  TRUE : FALSE, TRUE );
332  protocolInfo.authContext = sessionInfoPtr->privateKey;
333  sessionInfoPtr->protocolFlags |= CMP_PFLAG_USERIDSENT;
334  userNamePtr = findSessionInfo( sessionInfoPtr->attributeList,
336  if( userNamePtr != NULL )
337  {
338  BYTE userID[ CRYPT_MAX_TEXTSIZE ];
339  int userIDsize;
340 
341  /* There's already user information present from a previous
342  transaction, try and re-use it (this can happen if we're
343  handling a series of transactions from the client, see the
344  dicussion in cmp.h for details). This information can still
345  be overridden by the client sending us new user information */
346  if( userNamePtr->flags & ATTR_FLAG_ENCODEDVALUE )
347  {
348  /* It's a cryptlib-style encoded user ID, decode it into its
349  binary value */
350  status = decodePKIUserValue( userID, CRYPT_MAX_TEXTSIZE,
351  &userIDsize,
352  userNamePtr->value,
353  userNamePtr->valueLength );
354  ENSURES( cryptStatusOK( status ) );
355  }
356  else
357  {
358  /* It's a standard user ID, use it as is */
359  userIDsize = min( userNamePtr->valueLength, CRYPT_MAX_TEXTSIZE );
360  memcpy( userID, userNamePtr->value, userIDsize );
361  }
362  status = setCMPprotocolInfo( &protocolInfo, userID, userIDsize,
364  if( cryptStatusError( status ) )
365  {
366  destroyCMPprotocolInfo( &protocolInfo );
367  return( status );
368  }
369 
370  /* We're (potentially) re-using user information from a previous
371  session, if there are cryptographic credentials associated with
372  the user information we have to move them over to the current
373  protocol state data */
374  if( cmpInfo->savedMacContext != CRYPT_ERROR )
375  {
376  protocolInfo.iMacContext = cmpInfo->savedMacContext;
377  cmpInfo->savedMacContext = CRYPT_ERROR;
378  }
379  }
380 
381  /* Read the initial message from the client. We don't write an error
382  response at the initial read stage to prevent scanning/DOS attacks
383  (vir sapit qui pauca loquitur) */
384  status = readPkiDatagram( sessionInfoPtr );
385  if( cryptStatusError( status ) )
386  {
387  destroyCMPprotocolInfo( &protocolInfo );
388  return( status );
389  }
390  status = readPkiMessage( sessionInfoPtr, &protocolInfo,
392  if( cryptStatusOK( status ) )
393  {
394  status = cmpInfo->requestType = \
395  reqToClibReq( protocolInfo.operation );
396  }
397  if( cryptStatusError( status ) )
398  {
399  sendErrorResponse( sessionInfoPtr, &protocolInfo, status );
400  destroyCMPprotocolInfo( &protocolInfo );
401  return( status );
402  }
403  DEBUG_DUMP_CMP( protocolInfo.operation, 1, sessionInfoPtr );
404 
405  /* If it's a PKIBoot request, send the PKIBoot response */
406  if( cmpInfo->requestType == CRYPT_REQUESTTYPE_PKIBOOT )
407  {
408  status = writePkiMessage( sessionInfoPtr, &protocolInfo,
409  CMPBODY_GENMSG );
410  if( cryptStatusOK( status ) )
411  {
412  DEBUG_DUMP_CMP( CTAG_PB_GENM, 2, sessionInfoPtr );
413  status = writePkiDatagram( sessionInfoPtr, CMP_CONTENT_TYPE,
415  }
416  if( cryptStatusError( status ) )
417  {
418  sendErrorResponse( sessionInfoPtr, &protocolInfo, status );
419  destroyCMPprotocolInfo( &protocolInfo );
420  return( status );
421  }
422 
423  /* Remember the authentication context in case we can reuse it for
424  another transaction */
425  cmpInfo->savedMacContext = protocolInfo.iMacContext;
426  protocolInfo.iMacContext = CRYPT_ERROR;
427 
428  return( CRYPT_OK );
429  }
430 
431  /* Make sure that the signature on the request data is OK (unless it's a
432  non-signed revocation request or a request for an encryption-only
433  key) */
434  if( protocolInfo.operation != CTAG_PB_RR && !protocolInfo.cryptOnlyKey )
435  {
436  status = krnlSendMessage( sessionInfoPtr->iCertRequest,
437  IMESSAGE_CRT_SIGCHECK, NULL,
438  CRYPT_UNUSED );
439  if( cryptStatusError( status ) )
440  {
441  sendErrorResponse( sessionInfoPtr, &protocolInfo, status );
442  destroyCMPprotocolInfo( &protocolInfo );
443  retExt( status,
444  ( status, SESSION_ERRINFO,
445  "Certificate request signature check failed" ) );
446  }
447  }
448 
449  /* Add the request to the certificate store */
450  setMessageKeymgmtInfo( &setkeyInfo, CRYPT_KEYID_NONE, NULL, 0, NULL, 0,
451  ( protocolInfo.operation == CTAG_PB_IR ) ? \
453  ( protocolInfo.operation == CTAG_PB_KUR ) ? \
455  setkeyInfo.cryptHandle = sessionInfoPtr->iCertRequest;
456  status = krnlSendMessage( sessionInfoPtr->cryptKeyset,
457  IMESSAGE_KEY_SETKEY, &setkeyInfo,
458  ( protocolInfo.operation == CTAG_PB_RR ) ? \
461  if( cryptStatusError( status ) )
462  {
463  /* If the certificate store reports that there's a problem with the
464  request, convert it to an invalid request error */
465  if( cryptArgError( status ) )
466  status = CRYPT_ERROR_INVALID;
467 
468  /* A special error condition at this point arises when the user
469  tries to submit a second initialisation request for a PKI user
470  that has already had a certificate issued for it, so we catch
471  this condition and provide a more informative error response to
472  the client than the generic failure response */
473  if( protocolInfo.operation == CTAG_PB_IR && \
474  status == CRYPT_ERROR_DUPLICATE )
476 
477  /* Clean up and return the appropriate error information to the
478  caller */
479  sendErrorResponse( sessionInfoPtr, &protocolInfo, status );
480  destroyCMPprotocolInfo( &protocolInfo );
481  if( protocolInfo.operation == CTAG_PB_IR && \
482  status == CRYPT_ERROR_DUPLICATE )
483  {
484  retExtObj( status,
485  ( status, SESSION_ERRINFO, sessionInfoPtr->cryptKeyset,
486  "Initialisation request couldn't be added to the "
487  "certificate store because another initialisation "
488  "request has already been processed for this user" ) );
489  }
490  retExtObj( status,
491  ( status, SESSION_ERRINFO, sessionInfoPtr->cryptKeyset,
492  "Request couldn't be added to the certificate store" ) );
493  }
494 
495  /* Create or revoke a certificate from the request */
496  if( protocolInfo.operation != CTAG_PB_RR )
497  {
498  setMessageCertMgmtInfo( &certMgmtInfo, sessionInfoPtr->privateKey,
499  sessionInfoPtr->iCertRequest );
500  status = krnlSendMessage( sessionInfoPtr->cryptKeyset,
501  IMESSAGE_KEY_CERTMGMT, &certMgmtInfo,
503  if( cryptStatusOK( status ) )
504  {
505  int value;
506 
507  /* Remember the issued certificate and save various pieces
508  of information that we'll need later */
509  sessionInfoPtr->iCertResponse = certMgmtInfo.cryptCert;
510  status = krnlSendMessage( sessionInfoPtr->iCertResponse,
511  IMESSAGE_GETATTRIBUTE, &value,
512  CRYPT_IATTRIBUTE_CERTHASHALGO );
513  if( cryptStatusOK( status ) )
514  protocolInfo.confHashAlgo = value;
515  }
516  }
517  else
518  {
519  setMessageCertMgmtInfo( &certMgmtInfo, CRYPT_UNUSED,
520  sessionInfoPtr->iCertRequest );
521  status = krnlSendMessage( sessionInfoPtr->cryptKeyset,
522  IMESSAGE_KEY_CERTMGMT, &certMgmtInfo,
524  }
525  if( cryptStatusError( status ) )
526  {
527  /* If the certificate store reports that there's a problem with the
528  request, convert it to an invalid request error */
529  if( cryptArgError( status ) )
530  status = CRYPT_ERROR_INVALID;
531  sendErrorResponse( sessionInfoPtr, &protocolInfo, status );
532  destroyCMPprotocolInfo( &protocolInfo );
533  retExtObj( status,
534  ( status, SESSION_ERRINFO, sessionInfoPtr->cryptKeyset,
535  "Certificate %s was denied by certificate store",
536  ( protocolInfo.operation != CTAG_PB_RR ) ? \
537  "issue" : "revocation" ) );
538  }
539 
540  /* Send the response to the client */
541  status = writePkiMessage( sessionInfoPtr, &protocolInfo, CMPBODY_NORMAL );
542  if( cryptStatusOK( status ) )
543  {
544  DEBUG_DUMP_CMP( protocolInfo.operation, 2, sessionInfoPtr );
545  status = writePkiDatagram( sessionInfoPtr, CMP_CONTENT_TYPE,
547  }
548  if( cryptStatusError( status ) )
549  {
550  sendErrorResponse( sessionInfoPtr, &protocolInfo, status );
551  if( protocolInfo.operation != CTAG_PB_RR )
552  {
553  /* If there was a problem, drop the partially-issued certificate.
554  We don't have to go all the way and do a full reversal
555  because it hasn't really been issued yet since we couldn't
556  get it to the client (or even if the client somehow got it,
557  the certificate store hasn't marked it as complete yet so
558  it's regarded as invalid if queried). In addition we don't
559  do anything with the return status since we want to return
560  the status that caused the problem, not the result of the
561  drop operation */
562  setMessageCertMgmtInfo( &certMgmtInfo, CRYPT_UNUSED,
563  sessionInfoPtr->iCertResponse );
564  ( void ) krnlSendMessage( sessionInfoPtr->cryptKeyset,
565  IMESSAGE_KEY_CERTMGMT, &certMgmtInfo,
567  }
568  destroyCMPprotocolInfo( &protocolInfo );
569  return( status );
570  }
571 
572  /* If it's a transaction type that doesn't need a confirmation, we're
573  done */
574  if( protocolInfo.operation == CTAG_PB_RR )
575  {
576  /* Remember the authentication context in case we can reuse it for
577  another transaction */
578  cmpInfo->savedMacContext = protocolInfo.iMacContext;
579  protocolInfo.iMacContext = CRYPT_ERROR;
580 
581  destroyCMPprotocolInfo( &protocolInfo );
582  return( CRYPT_OK );
583  }
584 
585  /* Read back the confirmation from the client */
586  status = readPkiDatagram( sessionInfoPtr );
587  if( cryptStatusOK( status ) )
588  status = readPkiMessage( sessionInfoPtr, &protocolInfo,
590  if( cryptStatusError( status ) )
591  {
592  sendErrorResponse( sessionInfoPtr, &protocolInfo, status );
593  destroyCMPprotocolInfo( &protocolInfo );
594 
595  /* Reverse the certificate issue operation by revoking the
596  incompletely-issued certificate, returning the status that caused
597  the failure earlier on */
598  setMessageCertMgmtInfo( &certMgmtInfo, CRYPT_UNUSED,
599  sessionInfoPtr->iCertResponse );
600  ( void ) krnlSendMessage( sessionInfoPtr->cryptKeyset,
601  IMESSAGE_KEY_CERTMGMT, &certMgmtInfo,
603  return( status );
604  }
605  DEBUG_DUMP_CMP( protocolInfo.operation, 3, sessionInfoPtr );
606  if( protocolInfo.status == CRYPT_ERROR )
607  {
608  int localStatus;
609 
610  /* The client rejected the certificate, this isn't a protocol error
611  so we send back a standard ack */
612  status = writePkiMessage( sessionInfoPtr, &protocolInfo, CMPBODY_ACK );
613  if( cryptStatusOK( status ) )
614  status = writePkiDatagram( sessionInfoPtr, CMP_CONTENT_TYPE,
616  destroyCMPprotocolInfo( &protocolInfo );
617 
618  /* Reverse the certificate issue operation by revoking the
619  incompletely-issued certificate */
620  setMessageCertMgmtInfo( &certMgmtInfo, CRYPT_UNUSED,
621  sessionInfoPtr->iCertResponse );
622  localStatus = krnlSendMessage( sessionInfoPtr->cryptKeyset,
623  IMESSAGE_KEY_CERTMGMT, &certMgmtInfo,
625  return( cryptStatusOK( status ) ? localStatus : status );
626  }
627 
628  /* The client has confirmed the certificate creation, finalise it */
629  setMessageCertMgmtInfo( &certMgmtInfo, CRYPT_UNUSED,
630  sessionInfoPtr->iCertResponse );
631  status = krnlSendMessage( sessionInfoPtr->cryptKeyset,
632  IMESSAGE_KEY_CERTMGMT, &certMgmtInfo,
634  if( cryptStatusError( status ) )
635  {
636  sendErrorResponse( sessionInfoPtr, &protocolInfo, status );
637  destroyCMPprotocolInfo( &protocolInfo );
638  retExtObj( status,
639  ( status, SESSION_ERRINFO, sessionInfoPtr->cryptKeyset,
640  "Certificate issue completion failed" ) );
641  }
642 
643  /* Send back the final ack and clean up */
644  status = writePkiMessage( sessionInfoPtr, &protocolInfo, CMPBODY_ACK );
645  if( cryptStatusOK( status ) )
646  {
647  DEBUG_DUMP_CMP( protocolInfo.operation, 4, sessionInfoPtr );
648  status = writePkiDatagram( sessionInfoPtr, CMP_CONTENT_TYPE,
650  }
651 
652  /* Remember the authentication context in case we can reuse it for
653  another transaction */
654  cmpInfo->savedMacContext = protocolInfo.iMacContext;
655  protocolInfo.iMacContext = CRYPT_ERROR;
656 
657  destroyCMPprotocolInfo( &protocolInfo );
658  return( status );
659  }
660 
661 /****************************************************************************
662 * *
663 * Session Access Routines *
664 * *
665 ****************************************************************************/
666 
667 STDC_NONNULL_ARG( ( 1 ) ) \
668 void initCMPserverProcessing( SESSION_INFO *sessionInfoPtr )
669  {
670  assert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );
671 
672  sessionInfoPtr->transactFunction = serverTransact;
673  }
674 #endif /* USE_CMP */