static void sendErrorResponse( INOUT SESSION_INFO *sessionInfoPtr, INOUT SCEP_PROTOCOL_INFO *protocolInfo, IN_ERROR const int scepStatus ) { CRYPT_CERTIFICATE iCmsAttributes; int status; assert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) ); assert( isWritePtr( protocolInfo, sizeof( SCEP_PROTOCOL_INFO ) ) ); REQUIRES_V( cryptStatusError( scepStatus ) ); /* Sign the error response using the CA key and SCEP attributes */ status = createScepAttributes( sessionInfoPtr, protocolInfo, &iCmsAttributes, MESSAGETYPE_CERTREP, scepStatus ); if( cryptStatusOK( status ) ) { ERROR_INFO errorInfo; /* Since this message is being sent in response to an existing error, we don't care about the possible error information returned from the function that sends the error response, so the errorInfo result is ignored */ status = envelopeSign( NULL, 0, sessionInfoPtr->receiveBuffer, sessionInfoPtr->receiveBufSize, &sessionInfoPtr->receiveBufEnd, CRYPT_CONTENT_NONE, sessionInfoPtr->privateKey, iCmsAttributes, &errorInfo ); krnlSendNotifier( iCmsAttributes, IMESSAGE_DECREFCOUNT ); } if( cryptStatusError( status ) ) { HTTP_DATA_INFO httpDataInfo; /* If we encounter an error processing the initial request then there won't be enough information available to create an error response. Similarly if we run into problems generating the response then there won't be anything available to send. At this point the best that we can do is send an error at the HTTP level */ initHttpDataInfo( &httpDataInfo, sessionInfoPtr->receiveBuffer, sessionInfoPtr->receiveBufSize ); httpDataInfo.reqStatus = scepStatus; swrite( &sessionInfoPtr->stream, &httpDataInfo, sizeof( HTTP_DATA_INFO ) ); return; } DEBUG_DUMP_FILE( "scep_srespx", sessionInfoPtr->receiveBuffer, sessionInfoPtr->receiveBufEnd ); /* Return the response to the client, discarding any error indication from the write. Since we're already in an error state there's not much that we can do in terms of alerting the user if a further error occurs when writing the error response, so we ignore any potential write errors that occur at this point */ sioctlSet( &sessionInfoPtr->stream, STREAM_IOCTL_LASTMESSAGE, TRUE ); ( void ) writePkiDatagram( sessionInfoPtr, SCEP_CONTENT_TYPE, SCEP_CONTENT_TYPE_LEN ); }
static int createScepResponse( INOUT SESSION_INFO *sessionInfoPtr, INOUT SCEP_PROTOCOL_INFO *protocolInfo ) { CRYPT_CERTIFICATE iCmsAttributes; MESSAGE_DATA msgData; int dataLength, status; assert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) ); assert( isWritePtr( protocolInfo, sizeof( SCEP_PROTOCOL_INFO ) ) ); /* Extract the response data into the session buffer */ setMessageData( &msgData, sessionInfoPtr->receiveBuffer, sessionInfoPtr->receiveBufSize ); status = krnlSendMessage( sessionInfoPtr->iCertResponse, IMESSAGE_CRT_EXPORT, &msgData, CRYPT_CERTFORMAT_CERTCHAIN ); if( cryptStatusError( status ) ) { retExt( status, ( status, SESSION_ERRINFO, "Couldn't get PKCS #7 certificate chain from SCEP " "response object" ) ); } DEBUG_DUMP_FILE( "scep_sresp0", sessionInfoPtr->receiveBuffer, msgData.length ); /* Phase 1: Encrypt the data using the client's key */ status = envelopeWrap( sessionInfoPtr->receiveBuffer, msgData.length, sessionInfoPtr->receiveBuffer, sessionInfoPtr->receiveBufSize, &dataLength, CRYPT_FORMAT_CMS, CRYPT_CONTENT_NONE, protocolInfo->iScepCert ); if( cryptStatusError( status ) ) { retExt( status, ( status, SESSION_ERRINFO, "Couldn't encrypt response data with client key" ) ); } DEBUG_DUMP_FILE( "scep_sresp1", sessionInfoPtr->receiveBuffer, dataLength ); /* Create the SCEP signing attributes */ status = createScepAttributes( sessionInfoPtr, protocolInfo, &iCmsAttributes, FALSE, CRYPT_OK ); if( cryptStatusError( status ) ) { retExt( status, ( status, SESSION_ERRINFO, "Couldn't create SCEP response signing attributes" ) ); } /* Phase 2: Sign the data using the CA key and SCEP attributes */ status = envelopeSign( sessionInfoPtr->receiveBuffer, dataLength, sessionInfoPtr->receiveBuffer, sessionInfoPtr->receiveBufSize, &sessionInfoPtr->receiveBufEnd, CRYPT_CONTENT_NONE, sessionInfoPtr->privateKey, iCmsAttributes ); krnlSendNotifier( iCmsAttributes, IMESSAGE_DECREFCOUNT ); if( cryptStatusError( status ) ) { retExt( status, ( status, SESSION_ERRINFO, "Couldn't sign response data with CA key" ) ); } DEBUG_DUMP_FILE( "scep_sresp2", sessionInfoPtr->receiveBuffer, sessionInfoPtr->receiveBufEnd ); return( CRYPT_OK ); }