📄 int_api.c
字号:
void *dataPtr = NULL;
int attrLength = 0, status;
assert( isWritePtr( stream, sizeof( STREAM ) ) );
assert( sStatusOK( stream ) );
REQUIRES( cryptHandle == SYSTEM_OBJECT_HANDLE || \
isHandleRangeValid( cryptHandle ) );
REQUIRES( isAttribute( attributeType ) || \
isInternalAttribute( attributeType ) );
REQUIRES( ( length == CRYPT_UNUSED ) || \
( length >= 8 && length < MAX_INTLENGTH_SHORT ) );
/* Get access to the stream buffer if required */
if( !sIsNullStream( stream ) )
{
if( length != CRYPT_UNUSED )
{
/* It's an explicit-length attribute, make sure that there's
enough room left in the stream for it */
attrLength = length;
status = sMemGetDataBlock( stream, &dataPtr, length );
}
else
{
/* It's an implicit-length attribute whose maximum length is
defined by the stream size */
status = sMemGetDataBlockRemaining( stream, &dataPtr,
&attrLength );
}
if( cryptStatusError( status ) )
return( status );
}
/* Export the attribute directly into the stream buffer */
setMessageData( &msgData, dataPtr, attrLength );
status = krnlSendMessage( cryptHandle, IMESSAGE_GETATTRIBUTE_S,
&msgData, attributeType );
if( cryptStatusOK( status ) )
status = sSkip( stream, msgData.length );
return( status );
}
CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
int exportAttributeToStream( INOUT TYPECAST( STREAM * ) void *streamPtr,
IN_HANDLE const CRYPT_HANDLE cryptHandle,
IN_ATTRIBUTE \
const CRYPT_ATTRIBUTE_TYPE attributeType )
{
assert( isWritePtr( streamPtr, sizeof( STREAM ) ) );
REQUIRES( isHandleRangeValid( cryptHandle ) );
REQUIRES( isAttribute( attributeType ) || \
isInternalAttribute( attributeType ) );
return( exportAttr( streamPtr, cryptHandle, attributeType, \
CRYPT_UNUSED ) );
}
CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
int exportVarsizeAttributeToStream( INOUT TYPECAST( STREAM * ) void *streamPtr,
IN_HANDLE const CRYPT_HANDLE cryptHandle,
IN_LENGTH_FIXED( CRYPT_IATTRIBUTE_RANDOM_NONCE ) \
const CRYPT_ATTRIBUTE_TYPE attributeType,
IN_RANGE( 8, 1024 ) \
const int attributeDataLength )
{
assert( isWritePtr( streamPtr, sizeof( STREAM ) ) );
REQUIRES( cryptHandle == SYSTEM_OBJECT_HANDLE );
REQUIRES( attributeType == CRYPT_IATTRIBUTE_RANDOM_NONCE );
REQUIRES( attributeDataLength >= 8 && attributeDataLength <= 1024 );
return( exportAttr( streamPtr, cryptHandle, attributeType,
attributeDataLength ) );
}
CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
int exportCertToStream( INOUT TYPECAST( STREAM * ) void *streamPtr,
IN_HANDLE const CRYPT_CERTIFICATE cryptCertificate,
IN_ENUM( CRYPT_CERTFORMAT ) \
const CRYPT_CERTFORMAT_TYPE certFormatType )
{
MESSAGE_DATA msgData;
STREAM *stream = streamPtr;
void *dataPtr = NULL;
int length = 0, status;
assert( isWritePtr( stream, sizeof( STREAM ) ) );
assert( sStatusOK( stream ) );
REQUIRES( isHandleRangeValid( cryptCertificate ) );
REQUIRES( certFormatType > CRYPT_CERTFORMAT_NONE && \
certFormatType < CRYPT_CERTFORMAT_LAST );
/* Get access to the stream buffer if required */
if( !sIsNullStream( stream ) )
{
status = sMemGetDataBlockRemaining( stream, &dataPtr, &length );
if( cryptStatusError( status ) )
return( status );
}
/* Export the cert directly into the stream buffer */
setMessageData( &msgData, dataPtr, length );
status = krnlSendMessage( cryptCertificate, IMESSAGE_CRT_EXPORT,
&msgData, certFormatType );
if( cryptStatusOK( status ) )
status = sSkip( stream, msgData.length );
return( status );
}
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
int importCertFromStream( INOUT void *streamPtr,
OUT_HANDLE_OPT CRYPT_CERTIFICATE *cryptCertificate,
IN_ENUM( CRYPT_CERTTYPE ) \
const CRYPT_CERTTYPE_TYPE certType,
IN_LENGTH_SHORT_MIN( MIN_CRYPT_OBJECTSIZE ) \
const int certDataLength )
{
MESSAGE_CREATEOBJECT_INFO createInfo;
STREAM *stream = streamPtr;
void *dataPtr;
int status;
assert( isWritePtr( stream, sizeof( STREAM ) ) );
assert( sStatusOK( stream ) );
assert( isWritePtr( cryptCertificate, sizeof( CRYPT_CERTIFICATE ) ) );
REQUIRES( certType > CRYPT_CERTTYPE_NONE && \
certType < CRYPT_CERTTYPE_LAST );
REQUIRES( certDataLength >= MIN_CRYPT_OBJECTSIZE && \
certDataLength < MAX_INTLENGTH_SHORT );
/* Clear return value */
*cryptCertificate = CRYPT_ERROR;
/* Get access to the stream buffer and skip over the certificate data */
status = sMemGetDataBlock( stream, &dataPtr, certDataLength );
if( cryptStatusOK( status ) )
status = sSkip( stream, certDataLength );
if( cryptStatusError( status ) )
return( status );
/* Import the cert directly from the stream buffer */
setMessageCreateObjectIndirectInfo( &createInfo, dataPtr,
certDataLength, certType );
status = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
IMESSAGE_DEV_CREATEOBJECT_INDIRECT,
&createInfo, OBJECT_TYPE_CERTIFICATE );
if( cryptStatusError( status ) )
return( status );
*cryptCertificate = createInfo.cryptHandle;
return( CRYPT_OK );
}
/****************************************************************************
* *
* Safe Text-line Read Functions *
* *
****************************************************************************/
/* Read a line of text data ending in an EOL. If we get more data than will
fit into the read buffer we discard it until we find an EOL. As a
secondary concern we want to strip leading, trailing, and repeated
whitespace. Leading whitespace is handled by setting the seen-whitespace
flag to true initially, this treats any whitespace at the start of the
line as superfluous and strips it. Stripping of repeated whitespace is
also handled by the seenWhitespace flag, and stripping of trailing
whitespace is handled by walking back through any final whitespace once we
see the EOL.
We also handle continued lines denoted by the MIME convention of a
semicolon as the last non-whitespace character by setting the
seenContinuation flag if we see a semicolon as the last non-whitespace
character.
Finally, we also need to handle generic DoS attacks. If we see more than
MAX_LINE_LENGTH chars in a line we bail out */
#define MAX_LINE_LENGTH 4096
/* The extra level of indirection provided by this function is necessary
because the the extended error information isn't accessible from outside
the stream code so we can't set it in readTextLine() in the usual manner
via a retExt(). Instead we use a retExt() in the dummy function
formatTextLineError() and then pass it down to the stream layer via an
ioctl */
RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
static int formatTextLineError( OUT ERROR_INFO *errorInfo,
FORMAT_STRING const char *format,
const int value1, const int value2 )
{
assert( isWritePtr( errorInfo, sizeof( ERROR_INFO ) ) );
assert( isReadPtr( format, 4 ) );
retExt( CRYPT_ERROR_BADDATA,
( CRYPT_ERROR_BADDATA, errorInfo,
format, value1, value2 ) );
}
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3, 5 ) ) \
int readTextLine( READCHARFUNCTION readCharFunction,
INOUT void *streamPtr,
OUT_BUFFER( lineBufferMaxLen, \
lineBufferSize ) char *lineBuffer,
IN_LENGTH_SHORT_MIN( 16 ) const int lineBufferMaxLen,
OUT_LENGTH_SHORT_Z int *lineBufferSize,
OUT_OPT_BOOL BOOLEAN *localError )
{
BOOLEAN seenWhitespace, seenContinuation = FALSE;
int totalChars, bufPos = 0;
assert( readCharFunction != NULL );
assert( isWritePtr( streamPtr, sizeof( STREAM ) ) );
assert( isWritePtr( lineBuffer, lineBufferMaxLen ) );
assert( isWritePtr( lineBufferSize, sizeof( int ) ) );
assert( localError == NULL || \
isWritePtr( localError, sizeof( BOOLEAN ) ) );
REQUIRES( lineBufferMaxLen >= 16 && \
lineBufferMaxLen < MAX_INTLENGTH_SHORT );
/* Clear return values */
memset( lineBuffer, 0, min( 16, lineBufferMaxLen ) );
*lineBufferSize = 0;
if( localError != NULL )
*localError = FALSE;
/* Set the seen-whitespace flag initially to strip leading whitespace */
seenWhitespace = TRUE;
/* Read up to MAX_LINE_LENGTH chars. Anything longer than this is
probably a DoS */
for( totalChars = 0; totalChars < MAX_LINE_LENGTH; totalChars++ )
{
int ch;
/* Get the next input character */
ch = readCharFunction( streamPtr );
if( cryptStatusError( ch ) )
return( ch );
/* Process EOL */
if( ch == '\n' )
{
/* Strip trailing whitespace. At this point it's all been
canonicalised so we don't need to check for anything other
than spaces */
while( bufPos > 0 && lineBuffer[ bufPos - 1 ] == ' ' )
bufPos--;
/* If we've seen a continuation marker as the last non-
whitespace char, the line continues on the next one. This
can theoretically result in stripping a space at the end of
a line but since continuations are only placed at MIME
keyword separators the space is superfluous and can be
safely removed */
if( seenContinuation )
{
seenContinuation = FALSE;
continue;
}
/* We're done */
break;
}
/* Ignore any additional decoration that may accompany EOLs */
if( ch == '\r' )
continue;
/* If we're over the maximum buffer size discard any further input
until we either hit EOL or exceed the DoS threshold at
MAX_LINE_LENGTH */
if( bufPos > lineBufferMaxLen - 8 )
{
/* If we've run off into the weeds (for example we're reading
binary data following the text header), bail out */
if( ch <= 0 || ch > 0x7F || !isPrint( ch ) )
{
ERROR_INFO errorInfo;
if( localError != NULL )
*localError = TRUE;
formatTextLineError( &errorInfo, "Invalid character 0x%02X "
"at position %d", ch, totalChars );
sioctl( streamPtr, STREAM_IOCTL_ERRORINFO, &errorInfo, 0 );
return( CRYPT_ERROR_BADDATA );
}
continue;
}
/* Process whitespace. We can't use isspace() for this because it
includes all sorts of extra control characters that we don't want
to allow */
if( ch == ' ' || ch == '\t' )
{
if( seenWhitespace )
{
/* Ignore leading and repeated whitespace */
continue;
}
ch = ' '; /* Canonicalise whitespace */
}
/* Process any remaining chars */
if( ch <= 0 || ch > 0x7F || !isPrint( ch ) )
{
ERROR_INFO errorInfo;
if( localError != NULL )
*localError = TRUE;
formatTextLineError( streamPtr, "Invalid character 0x%02X at "
"position %d", ch, totalChars );
sioctl( streamPtr, STREAM_IOCTL_ERRORINFO, &errorInfo, 0 );
return( CRYPT_ERROR_BADDATA );
}
lineBuffer[ bufPos++ ] = ch;
ENSURES( bufPos > 0 && bufPos <= totalChars + 1 );
/* The 'totalChars + 1' is because totalChars is the loop
iterator and won't have been incremented yet at this
point */
/* Update the state variables. If the character that we've just
processed was whitespace or if we've seen a continuation
character or we're processing whitespace after having seen a
continuation character (which makes it effectively leading
whitespace to be stripped), remember this */
seenWhitespace = ( ch == ' ' ) ? TRUE : FALSE;
seenContinuation = ( ch == ';' || \
( seenContinuation && seenWhitespace ) ) ? \
TRUE : FALSE;
}
if( totalChars >= MAX_LINE_LENGTH )
{
ERROR_INFO errorInfo;
if( localError != NULL )
*localError = TRUE;
formatTextLineError( streamPtr, "Text line too long", 0, 0 );
sioctl( streamPtr, STREAM_IOCTL_ERRORINFO, &errorInfo, 0 );
return( CRYPT_ERROR_OVERFLOW );
}
*lineBufferSize = bufPos;
return( CRYPT_OK );
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -