?? cryptmis.c
字號:
if( !dataOK || cryptStatusError( sGetStatus( &stream ) ) )
{
sMemDisconnect( &stream );
return( 0 );
}
}
/* Skip trailing blank lines */
do
ch = sgetc( &stream );
while( ch == '\r' || ch == '\n' );
sungetc( &stream );
ch = stell( &stream );
sMemDisconnect( &stream );
return( cryptStatusError( ch ) ? 0 : ch );
}
/* Encode a block of binary data into the base64 format, returning the total
number of output bytes */
int base64encode( char *outBuffer, const void *inBuffer, const int count,
const CRYPT_CERTTYPE_TYPE certType )
{
int srcIndex = 0, destIndex = 0, lineCount = 0, remainder = count % 3;
BYTE *inBufferPtr = ( BYTE * ) inBuffer;
/* If it's a certificate object, add the header */
if( certType != CRYPT_CERTTYPE_NONE )
{
strcpy( outBuffer, headerTbl[ certType ] );
destIndex = strlen( headerTbl[ certType ] );
}
/* Encode the data */
while( srcIndex < count )
{
/* If we've reached the end of a line of binary data and it's a
certificate, add the EOL marker */
if( certType != CRYPT_CERTTYPE_NONE && lineCount == BINARY_LINESIZE )
{
strcpy( outBuffer + destIndex, EOL );
destIndex += EOL_LEN;
lineCount = 0;
}
lineCount += 3;
/* Encode a block of data from the input buffer */
outBuffer[ destIndex++ ] = encode( inBufferPtr[ srcIndex ] >> 2 );
outBuffer[ destIndex++ ] = encode( ( ( inBufferPtr[ srcIndex ] << 4 ) & 0x30 ) |
( ( inBufferPtr[ srcIndex + 1 ] >> 4 ) & 0x0F ) );
srcIndex++;
outBuffer[ destIndex++ ] = encode( ( ( inBufferPtr[ srcIndex ] << 2 ) & 0x3C ) |
( ( inBufferPtr[ srcIndex + 1 ] >> 6 ) & 0x03 ) );
srcIndex++;
outBuffer[ destIndex++ ] = encode( inBufferPtr[ srcIndex++ ] & 0x3F );
}
/* Go back and add padding and correctly encode the last char if we've
encoded too many characters */
if( remainder == 2 )
{
/* There were only 2 bytes in the last group */
outBuffer[ destIndex - 1 ] = BPAD;
outBuffer[ destIndex - 2 ] = \
encode( ( inBufferPtr[ srcIndex - 2 ] << 2 ) & 0x3C );
}
else
if( remainder == 1 )
{
/* There was only 1 byte in the last group */
outBuffer[ destIndex - 2 ] = outBuffer[ destIndex - 1 ] = BPAD;
outBuffer[ destIndex - 3 ] = \
encode( ( inBufferPtr[ srcIndex - 3 ] << 4 ) & 0x30 );
}
/* If it's a certificate object, add the trailer */
if( certType != CRYPT_CERTTYPE_NONE )
{
strcpy( outBuffer + destIndex, EOL );
strcpy( outBuffer + destIndex + EOL_LEN, trailerTbl[ certType ] );
destIndex += strlen( trailerTbl[ certType ] );
}
else
{
/* It's not a certificate, truncate the unnecessary padding and add
der terminador */
destIndex -= ( 3 - remainder ) % 3;
outBuffer[ destIndex ] = '\0';
}
/* Return a count of encoded bytes */
return( destIndex );
}
/* Decode a block of binary data from the base64 format, returning the total
number of decoded bytes */
static int fixedBase64decode( void *outBuffer, const char *inBuffer,
const int count )
{
int srcIndex = 0, destIndex = 0;
BYTE *outBufferPtr = outBuffer;
/* Decode the base64 string as a fixed-length continuous string without
padding or newlines */
while( srcIndex < count )
{
BYTE c0, c1, c2 = 0, c3 = 0;
const int delta = count - srcIndex;
/* Decode a block of data from the input buffer */
c0 = decode( inBuffer[ srcIndex++ ] );
c1 = decode( inBuffer[ srcIndex++ ] );
if( delta > 2 )
{
c2 = decode( inBuffer[ srcIndex++ ] );
if( delta > 3 )
c3 = decode( inBuffer[ srcIndex++ ] );
}
if( ( c0 | c1 | c2 | c3 ) == BERR )
return( 0 );
/* Copy the decoded data to the output buffer */
outBufferPtr[ destIndex++ ] = ( c0 << 2 ) | ( c1 >> 4 );
if( delta > 2 )
{
outBufferPtr[ destIndex++ ] = ( c1 << 4 ) | ( c2 >> 2);
if( delta > 3 )
outBufferPtr[ destIndex++ ] = ( c2 << 6 ) | ( c3 );
}
}
/* Return count of decoded bytes */
return( destIndex );
}
int base64decode( void *outBuffer, const char *inBuffer, const int count,
const CRYPT_CERTFORMAT_TYPE format )
{
int srcIndex = 0, destIndex = 0, lineCount = 0, lineSize = 0;
BYTE c0, c1, c2, c3, *outBufferPtr = outBuffer;
/* If it's not a certificate, it's a straight base64 string and we can
use the simplified decoding routines */
if( format == CRYPT_CERTFORMAT_NONE )
return( fixedBase64decode( outBuffer, inBuffer, count ) );
/* Decode the certificate body */
while( TRUE )
{
BYTE cx;
/* Depending on implementations, the length of the base64-encoded
line can vary from 60 to 72 chars, we ajust for this by checking
for an EOL and setting the line length to this size */
if( !lineSize && \
( inBuffer[ srcIndex ] == '\r' || inBuffer[ srcIndex ] == '\n' ) )
lineSize = lineCount;
/* If we've reached the end of a line of text, look for the EOL
marker. There's one problematic special case here where, if the
encoding has produced bricktext, the end of the data will coincide
with the EOL. For CRYPT_CERTFORMAT_TEXT_CERTIFICATE this will give
us '-----END' on the next line which is easy to check for, but for
CRYPT_ICERTFORMAT_SMIME_CERTIFICATE what we end up with depends on
the calling code, it could truncate immediately at the end of the
data (which it isn't supposed to) so we get '\0', it could truncate
after the EOL (so we get EOL + '\0'), it could continue with a
futher content type after a blank line (so we get EOL + EOL), or
it could truncate without the '\0' so we get garbage, which is the
callers problem. Because of this we look for all of these
situations and, if any are found, set c0 to BEOF and advance
srcIndex by 4 to take into account the adjustment for overshoot
which occurs when we break out of the loop */
if( lineCount == lineSize )
{
/* Check for '\0' at the end of the data */
if( format == CRYPT_ICERTFORMAT_SMIME_CERTIFICATE && \
!inBuffer[ srcIndex ] )
{
c0 = BEOF;
srcIndex += 4;
break;
}
/* Check for EOL */
if( inBuffer[ srcIndex ] == '\n' )
srcIndex++;
else
if( inBuffer[ srcIndex ] == '\r' )
{
srcIndex++;
if( inBuffer[ srcIndex ] == '\n' )
srcIndex++;
}
lineCount = 0;
/* Check for '\0' or EOL (S/MIME) or '----END' (text) after EOL */
if( ( format == CRYPT_ICERTFORMAT_SMIME_CERTIFICATE && \
( !inBuffer[ srcIndex ] || inBuffer[ srcIndex ] == '\n' ||
inBuffer[ srcIndex ] == '\r' ) ) || \
( format == CRYPT_CERTFORMAT_TEXT_CERTIFICATE && \
!strncmp( inBuffer + srcIndex, "-----END ", 9 ) ) )
{
c0 = BEOF;
srcIndex += 4;
break;
}
}
/* Decode a block of data from the input buffer */
c0 = decode( inBuffer[ srcIndex++ ] );
c1 = decode( inBuffer[ srcIndex++ ] );
c2 = decode( inBuffer[ srcIndex++ ] );
c3 = decode( inBuffer[ srcIndex++ ] );
cx = c0 | c1 | c2 | c3;
if( c0 == BEOF || cx == BEOF )
/* We need to check c0 separately since hitting an EOF at c0 may
cause later chars to be decoded as BERR */
break;
else
if( cx == BERR )
return( 0 );
lineCount += 4;
/* Copy the decoded data to the output buffer */
outBufferPtr[ destIndex++ ] = ( c0 << 2 ) | ( c1 >> 4 );
outBufferPtr[ destIndex++ ] = ( c1 << 4 ) | ( c2 >> 2);
outBufferPtr[ destIndex++ ] = ( c2 << 6 ) | ( c3 );
}
/* Handle the truncation of data at the end. Due to the 3 -> 4 encoding,
we have the following mapping: 0 chars -> nothing, 1 char -> 2 + 2 pad,
2 chars = 3 + 1 pad */
if( c0 == BEOF )
/* No padding, move back 4 chars */
srcIndex -= 4;
else
{
/* 2 chars padding, decode 1 from 2 */
outBufferPtr[ destIndex++ ] = ( c0 << 2 ) | ( c1 >> 4 );
if( c2 != BEOF )
/* 1 char padding, decode 2 from 3 */
outBufferPtr[ destIndex++ ] = ( c1 << 4 ) | ( c2 >> 2);
}
/* Make sure the certificate trailer is present */
if( format == CRYPT_CERTFORMAT_TEXT_CERTIFICATE )
{
if( inBuffer[ srcIndex ] == '\n' )
srcIndex++;
else
if( inBuffer[ srcIndex ] == '\r' )
{
srcIndex++;
if( inBuffer[ srcIndex ] == '\n' )
srcIndex++;
}
if( strncmp( inBuffer + srcIndex, "-----END ", 9 ) )
return( 0 );
}
/* Return count of decoded bytes */
return( destIndex );
}
/* Calculate the size of a quantity of data once it's en/decoded as a
certificate */
int base64decodeLen( const char *data, const int dataLength )
{
STREAM stream;
int ch, length;
/* Skip ahead until we find the end of the decodable data */
sMemConnect( &stream, data, dataLength );
do
ch = sgetc( &stream );
while( decode( ch ) != BERR );
length = stell( &stream ) - 1;
sMemDisconnect( &stream );
/* Return a rough estimate of how much room the decoded data will occupy.
This ignores the EOL size so it always overestimates, but a strict
value isn't necessary since the user never sees it anyway */
return( ( length * 3 ) / 4 );
}
int base64encodeLen( const int dataLength,
const CRYPT_CERTTYPE_TYPE certType )
{
int length = roundUp( ( dataLength * 4 ) / 3, 4 );
/* Calculate extra length due to EOL's */
length += ( ( roundUp( dataLength, BINARY_LINESIZE ) / BINARY_LINESIZE ) * EOL_LEN );
/* Return the total length due to delimiters */
return( strlen( headerTbl[ certType ] ) + length + \
strlen( trailerTbl[ certType ] ) );
}
/* En/decode text representations of binary keys */
static const char codeTable[] = \
"ABCDEFGHJKLMNPQRSTUVWXYZ23456789"; /* No O/0, I/1 */
static const int hiMask[] = { 0x00, 0x00, 0x00, 0x00, 0x0F, 0x07, 0x03, 0x01 };
static const int loMask[] = { 0x00, 0x00, 0x00, 0x00, 0x80, 0xC0, 0xE0, 0xF0 };
BOOLEAN isUserValue( const char *encVal, const int encValueLength )
{
int i = 0;
/* Check whether a user value is of the form XXXXX-XXXXX-XXXXX{-XXXXX} */
if( ( encValueLength != ( 3 * 5 ) + 2 ) && \
( encValueLength != ( 4 * 5 ) + 3 ) )
return( FALSE );
while( i < encValueLength )
{
int j;
for( j = 0; j < 5; j++ )
{
const int ch = encVal[ i++ ];
if( !isalnum( ch ) )
return( FALSE );
}
if( i < encValueLength && encVal[ i++ ] != '-' )
return( FALSE );
}
return( TRUE );
}
int adjustUserValue( BYTE *value, const int noCodeGroups )
{
const int noBits = noCodeGroups * 25;
const int length = ( roundUp( noBits, 8 ) / 8 ) - 1;
/* Mask off the bits at the end of the data which can't be encoded in
the given number of code groups */
value[ length - 1 ] &= 0xFF << ( 8 - ( noBits % 8 ) );
return( length );
}
int encodeUserValue( char *encVal, const BYTE *value,
const int noCodeGroups )
{
BYTE valBuf[ 128 ], *valBufPtr = valBuf;
const int dataBytes = ( roundUp( noCodeGroups * 25, 8 ) / 8 );
int i, hi = 0, lo = 0, byteCount = 0, bitCount = 0, length;
/* Copy across the data bytes, leaving a gap at the start for the
checksum */
memcpy( valBuf + 1, value, dataBytes );
length = adjustUserValue( valBuf + 1, noCodeGroups ) + 1;
/* Calculate the Fletcher checksum and prepend it to the data bytes.
This is easier than handling the addition of a non-byte-aligned
quantity to the end of the data */
for( i = 1; i < length; i++ )
{
lo += valBuf[ i ];
hi += lo;
}
valBuf[ 0 ] = hi & 0xFF;
/* Encode the binary data as text */
for( length = 0, i = 1; i <= noCodeGroups * 5; i++ )
{
int value;
/* Extract the next 5-bit chunk and convert it to text form */
if( bitCount < 3 )
/* Everything's present in one byte, shift it down to the LSB */
value = ( valBuf[ byteCount ] >> ( 3 - bitCount ) ) & 0x1F;
else
if( bitCount == 3 )
/* It's the 5 LSB's */
value = valBuf[ byteCount ] & 0x1F;
else
/* The data spans two bytes, shift the bits from the high
byte up and the bits from the low byte down */
value = ( ( valBuf[ byteCount ] & \
hiMask[ bitCount ] ) << ( bitCount - 3 ) ) | \
( ( valBuf[ byteCount + 1 ] & \
loMask[ bitCount ] ) >> ( 11 - bitCount ) );
encVal[ length++ ] = codeTable[ value ];
if( !( i % 5 ) && i < noCodeGroups * 5 )
encVal[ length++ ] = '-';
/* Advance by 5 bits */
bitCount += 5;
if( bitCount >= 8 )
{
bitCount -= 8;
byteCount++;
}
}
return( length );
}
int decodeUserValue( BYTE *value, const char *encVal,
const int encValueLength )
{
BYTE valBuf[ 128 ], *valBufPtr = valBuf;
char encBuf[ 128 ], *encBufPtr = encBuf;
int i = 0, hi = 0, lo = 0, byteCount = 0, bitCount = 0, length = 0;
/* Undo the formatting of the encoded value */
while( i < encValueLength )
{
int j;
for( j = 0; j < 5; j++ )
{
const int ch = encVal[ i++ ];
if( !isalnum( ch ) || length >= encValueLength )
return( CRYPT_ERROR_BADDATA );
encBuf[ length++ ] = toupper( ch );
}
if( i < encValueLength && encVal[ i++ ] != '-' )
return( CRYPT_ERROR_BADDATA );
}
if( length % 5 )
return( CRYPT_ERROR_BADDATA );
/* Decode the text data into binary */
memset( valBuf, 0, 128 );
for( i = 0; i < length; i ++ )
{
const int ch = *encBufPtr++;
int value;
for( value = 0; value < 0x20; value++ )
if( codeTable[ value ] == ch )
break;
if( value == 0x20 )
return( CRYPT_ERROR_BADDATA );
/* Extract the next 5-bit chunk and convert it to text form */
if( bitCount < 3 )
/* Everything's present in one byte, shift it up into position */
valBuf[ byteCount ] |= value << ( 3 - bitCount );
else
if( bitCount == 3 )
/* It's the 5 LSB's */
valBuf[ byteCount ] |= value;
else
{
/* The data spans two bytes, shift the bits from the high
byte down and the bits from the low byte up */
valBuf[ byteCount ] |= \
( value >> ( bitCount - 3 ) ) & hiMask[ bitCount ];
valBuf[ byteCount + 1 ] = \
( value << ( 11 - bitCount ) ) & loMask[ bitCount ];
}
/* Advance by 5 bits */
bitCount += 5;
if( bitCount >= 8 )
{
bitCount -= 8;
byteCount++;
}
}
/* Calculate the Fletcher checksum and make sure it matches the value at
the start of the data bytes */
if( bitCount )
byteCount++; /* More bits in the last partial byte */
for( i = 1; i < byteCount; i++ )
{
lo += valBuf[ i ];
hi += lo;
}
if( valBuf[ 0 ] != ( hi & 0xFF ) )
return( CRYPT_ERROR_BADDATA );
/* Return the decoded value to the caller */
if( value != NULL )
memcpy( value, valBuf + 1, byteCount - 1 );
return( byteCount - 1 );
}
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -