24 static const char FAR_BSS binToAscii[ 64 ] = {
25 'A',
'B',
'C',
'D',
'E',
'F',
'G',
'H',
26 'I',
'J',
'K',
'L',
'M',
'N',
'O',
'P',
27 'Q',
'R',
'S',
'T',
'U',
'V',
'W',
'X',
28 'Y',
'Z',
'a',
'b',
'c',
'd',
'e',
'f',
29 'g',
'h',
'i',
'j',
'k',
'l',
'm',
'n',
30 'o',
'p',
'q',
'r',
's',
't',
'u',
'v',
31 'w',
'x',
'y',
'z',
'0',
'1',
'2',
'3',
32 '4',
'5',
'6',
'7',
'8',
'9',
'+',
'/'
42 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B,
44 BERR, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
45 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E,
46 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
48 BERR, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20,
49 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
50 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30,
75 #define BASE64_LINESIZE 64
76 #define BASE64_MIN_LINESIZE 56
82 #define encode( data ) binToAscii[ ( data ) & 0x3F ]
83 #define decode( data ) asciiToBin[ ( data ) & 0xFF ]
98 "-----BEGIN CERTIFICATE-----" EOL, 27 + EOL_LEN,
99 "-----END CERTIFICATE-----" EOL, 25 + EOL_LEN },
101 "-----BEGIN ATTRIBUTE CERTIFICATE-----" EOL, 37 + EOL_LEN,
102 "-----END ATTRIBUTE CERTIFICATE-----" EOL, 35 + EOL_LEN },
104 "-----BEGIN CERTIFICATE CHAIN-----" EOL, 33 + EOL_LEN,
105 "-----END CERTIFICATE CHAIN-----" EOL, 31 + EOL_LEN },
107 "-----BEGIN NEW CERTIFICATE REQUEST-----" EOL, 39 + EOL_LEN,
108 "-----END NEW CERTIFICATE REQUEST-----" EOL, 37 + EOL_LEN },
110 "-----BEGIN NEW CERTIFICATE REQUEST-----" EOL, 39 + EOL_LEN,
111 "-----END NEW CERTIFICATE REQUEST-----" EOL, 37 + EOL_LEN },
113 "-----BEGIN CERTIFICATE REVOCATION LIST-----" EOL, 43 + EOL_LEN,
114 "-----END CERTIFICATE REVOCATION LIST-----" EOL, 41 + EOL_LEN },
116 "-----BEGIN CERTIFICATE OBJECT-----" EOL, 34 + EOL_LEN,
117 "-----END CERTIFICATE OBJECT-----" EOL, 32 + EOL_LEN },
119 "-----BEGIN CERTIFICATE OBJECT-----" EOL, 34 + EOL_LEN,
120 "-----END CERTIFICATE OBJECT-----" EOL, 32 + EOL_LEN }
163 if( memcmp( buffer,
"MI", 2 ) && \
164 memcmp( buffer,
"AA", 2 ) && \
165 memcmp( buffer,
"mQ", 2 ) )
170 sMemNullOpen( &nullStream );
172 sMemDisconnect( &nullStream );
188 char buffer[ 1024 + 8 ], *bufPtr =
buffer;
192 assert(
isWritePtr( headerLength,
sizeof(
int ) ) );
199 status = readTextLine( ( READCHARFUNCTION ) sgetc, stream,
200 buffer, 1024, &length, NULL );
203 if( length < 5 + 6 + 7 + 5 )
209 if( memcmp( bufPtr,
"-----BEGIN ", 11 ) &&
210 memcmp( bufPtr,
"---- BEGIN ", 11 ) )
230 if( length != 5 && length != 4 )
238 if( !isSSH && !isPGP )
240 *headerLength = stell( stream );
254 position = stell( stream );
255 status = readTextLine( ( READCHARFUNCTION ) sgetc, stream,
256 buffer, 1024, &length, NULL );
259 if( isSSH && strFindCh( buffer, length,
':' ) < 0 )
261 if( isPGP && length <= 0 )
264 if( lineCount >= FAILSAFE_ITERATIONS_MED )
269 sseek( stream, position );
271 *headerLength = stell( stream );
291 static
int checkEOL(
IN_BUFFER( srcLen )
const char *src,
300 assert(
isWritePtr( eolSize,
sizeof(
int ) ) );
310 if( format == CRYPT_ICERTFORMAT_SMIME_CERTIFICATE && src[ 0 ] ==
'\0' )
329 if( ( srcIndex < srcLen ) && src[ srcIndex ] ==
'\r' )
331 if( ( srcIndex < srcLen ) && src[ srcIndex ] ==
'\n' )
335 if( srcIndex >= srcLen )
339 if( format == CRYPT_ICERTFORMAT_SMIME_CERTIFICATE )
341 if( src[ srcIndex ] ==
'\0' || src[ srcIndex ] ==
'\n' || \
342 src[ srcIndex ] ==
'\r' )
347 if( srcIndex + 9 <= srcLen && \
348 !
strCompare( src + srcIndex,
"-----END ", 9 ) )
357 ENSURES( srcIndex > 0 && srcIndex < srcLen );
391 assert(
isWritePtr( startPos,
sizeof(
int ) ) );
402 if( dataLength < 64 )
405 sMemConnect( &stream, data, dataLength );
417 if( dataLength < 32000L )
418 status = readSequenceI( &stream, NULL );
420 status = readLongSequence( &stream, NULL );
423 sMemDisconnect( &stream );
427 sClearError( &stream );
433 for( length = 0, lineCount = 0;
437 char buffer[ 1024 + 8 ];
439 position = stell( &stream );
440 status = readTextLine( ( READCHARFUNCTION ) sgetc, &stream,
441 buffer, 1024, &length, NULL );
444 sMemDisconnect( &stream );
447 if( buffer[ 0 ] ==
'-' )
450 if( lineCount >= FAILSAFE_ITERATIONS_MED )
452 sMemDisconnect( &stream );
455 sseek( &stream, position );
461 status = checkPEMHeader( &stream, &position );
464 sMemDisconnect( &stream );
467 if( !checkBase64( &stream ) )
469 sMemDisconnect( &stream );
472 sMemDisconnect( &stream );
480 if( checkBase64( &stream ) )
482 sMemDisconnect( &stream );
488 sseek( &stream, position );
491 for( length = 1, lineCount = 0;
495 char buffer[ 1024 + 8 ];
497 status = readTextLine( ( READCHARFUNCTION ) sgetc, &stream,
498 buffer, 1024, &length, NULL );
501 sMemDisconnect( &stream );
504 if( !seenTransferEncoding && length >= 33 && \
505 !
strCompare( buffer,
"Content-Transfer-Encoding:", 26 ) )
507 int index = strSkipWhitespace( buffer + 26, length - 26 );
510 if( index < 0 || index > 1024 - 26 )
513 if( length - index < 6 )
518 if( !
strCompare( buffer + index,
"base64", 6 ) )
519 seenTransferEncoding =
TRUE;
522 if( !
strCompare( buffer + index,
"binary", 6 ) )
523 seenTransferEncoding = isBinaryEncoding =
TRUE;
527 if( lineCount >= FAILSAFE_ITERATIONS_MED || !seenTransferEncoding )
529 sMemDisconnect( &stream );
532 position = stell( &stream );
536 if( isBinaryEncoding )
538 if( dataLength < 32000L )
539 status = readSequenceI( &stream, NULL );
541 status = readLongSequence( &stream, NULL );
542 sMemDisconnect( &stream );
550 isBase64 = checkBase64( &stream );
551 sMemDisconnect( &stream );
555 *format = CRYPT_ICERTFORMAT_SMIME_CERTIFICATE;
569 static
int decodeBase64chunk(
INOUT STREAM *stream,
574 int c0, c1, c2 = 0, c3 = 0, cx;
575 int srcIndex = 0, outByteCount,
status;
596 cx = c0 | c1 | c2 | c3;
637 outByteCount = ( srcLeft > 4 ) ? 3 : srcLeft - 1;
639 ENSURES( outByteCount > 0 && outByteCount < 4 );
642 status = sputc( stream, ( ( c0 << 2 ) | ( c1 >> 4 ) ) & 0xFF );
643 if( outByteCount > 1 )
645 status = sputc( stream, ( ( c1 << 4 ) | ( c2 >> 2 ) ) & 0xFF );
646 if( outByteCount > 2 )
647 status = sputc( stream, ( ( c2 << 6 ) | c3 ) & 0xFF );
660 static
int fixedBase64decode(
STREAM *stream,
675 for( srcIndex = 0; srcIndex < srcLen && \
680 status = decodeBase64chunk( stream, src + srcIndex,
681 srcLen - srcIndex,
TRUE );
691 ENSURES( srcIndex < MAX_INTLENGTH );
706 int srcIndex, lineByteCount, lineSize = 0, status =
DUMMY_INIT;
708 assert( destMaxLen > 10 &&
isWritePtr( dest, destMaxLen ) );
709 assert(
isWritePtr( destLen,
sizeof(
int ) ) );
710 assert( srcLen > 10 &&
isReadPtr( src, srcLen ) );
712 REQUIRES( destMaxLen > 10 && destMaxLen < MAX_INTLENGTH );
713 REQUIRES( srcLen > 10 && srcLen < MAX_INTLENGTH );
718 memset( dest, 0,
min( 16, destMaxLen ) );
721 sMemOpen( &stream, dest, destMaxLen );
727 status = fixedBase64decode( &stream, src, srcLen );
729 *destLen = stell( &stream );
730 sMemDisconnect( &stream );
738 for( srcIndex = 0, lineByteCount = 0;
740 srcIndex += 4, lineByteCount += 4 )
746 if( lineSize <= 0 && \
747 ( src[ srcIndex ] ==
'\r' || src[ srcIndex ] ==
'\n' ) )
749 if( lineByteCount < BASE64_MIN_LINESIZE || lineByteCount > 128 )
752 sMemDisconnect( &stream );
755 lineSize = lineByteCount;
760 if( lineSize > 0 && lineByteCount >= lineSize )
764 status = checkEOL( src + srcIndex, srcLen - srcIndex,
765 &eolDataSize, format );
776 sMemDisconnect( &stream );
779 srcIndex += eolDataSize;
784 status = decodeBase64chunk( &stream, src + srcIndex,
785 srcLen - srcIndex,
FALSE );
803 sMemDisconnect( &stream );
807 ENSURES( srcIndex < MAX_INTLENGTH );
809 *destLen = stell( &stream );
810 sMemDisconnect( &stream );
818 int base64decodeLen(
IN_BUFFER( dataLength )
const char *data,
826 assert(
isWritePtr( decodedLength,
sizeof(
int ) ) );
828 REQUIRES( dataLength >= 10 && dataLength < MAX_INTLENGTH );
844 sMemConnect( &stream, data, dataLength );
845 for( iterationCount = 0; iterationCount <
MAX_INTLENGTH; iterationCount++ )
847 length = stell( &stream );
848 ch = sgetc( &stream );
851 if( ch ==
'\r' || ch ==
'\n' )
860 ENSURES( iterationCount < MAX_INTLENGTH );
861 sMemDisconnect( &stream );
867 *decodedLength = ( length * 3 ) / 4;
881 int base64encodeLen(
IN_LENGTH_MIN( 10 )
const int dataLength,
886 int length =
roundUp( ( dataLength * 4 ) / 3, 4 ), headerInfoIndex;
888 assert(
isWritePtr( encodedLength,
sizeof(
int ) ) );
890 REQUIRES( dataLength >= 10 && dataLength < MAX_INTLENGTH );
894 ENSURES( length >= 10 && length < MAX_INTLENGTH );
900 for( headerInfoIndex = 0;
901 headerInfo[ headerInfoIndex ].
type != certType && \
910 length = headerInfo[ headerInfoIndex ].headerLen + length + \
911 headerInfo[ headerInfoIndex ].trailerLen;
913 ENSURES( length > 10 && length < MAX_INTLENGTH );
923 int base64encode(
OUT_BUFFER( destMaxLen, *destLen )
char *dest,
933 int srcIndex, lineByteCount, remainder = srcLen % 3;
936 assert( destMaxLen > 10 &&
isWritePtr( dest, destMaxLen ) );
937 assert(
isWritePtr( destLen,
sizeof(
int ) ) );
938 assert( srcLen >= 10 &&
isReadPtr( src, srcLen ) );
940 REQUIRES( destMaxLen >= 10 && destMaxLen > srcLen && \
941 destMaxLen < MAX_INTLENGTH );
942 REQUIRES( srcLen >= 10 && srcLen < MAX_INTLENGTH );
947 memset( dest, 0,
min( 16, destMaxLen ) );
950 sMemOpen( &stream, dest, destMaxLen );
956 for( headerInfoIndex = 0;
957 headerInfo[ headerInfoIndex ].
type != certType && \
963 status = swrite( &stream, headerInfo[ headerInfoIndex ].header,
964 headerInfo[ headerInfoIndex ].headerLen );
967 sMemDisconnect( &stream );
973 for( srcIndex = 0, lineByteCount = 0;
977 const int srcLeft = srcLen - srcIndex;
985 status = swrite( &stream, EOL, EOL_LEN );
988 sMemDisconnect( &stream );
995 sputc( &stream,
encode( ( srcPtr[ srcIndex ] >> 2 ) & 0x3F ) );
999 status = sputc( &stream,
encode( ( srcPtr[ srcIndex ] << 4 ) & 0x30 ) );
1002 sputc( &stream,
encode( ( ( srcPtr[ srcIndex ] << 4 ) & 0x30 ) | \
1003 ( ( srcPtr[ srcIndex + 1 ] >> 4 ) & 0x0F ) ) );
1008 status = sputc( &stream,
encode( ( srcPtr[ srcIndex ] << 2 ) & 0x3C ) );
1011 sputc( &stream,
encode( ( ( srcPtr[ srcIndex ] << 2 ) & 0x3C ) | \
1012 ( ( srcPtr[ srcIndex + 1 ] >> 6 ) & 0x03 ) ) );
1014 status = sputc( &stream,
encode( srcPtr[ srcIndex++ ] & 0x3F ) );
1020 sMemDisconnect( &stream );
1034 status = sputc( &stream,
BPAD );
1035 if( remainder == 1 )
1036 status = sputc( &stream,
BPAD );
1039 sMemDisconnect( &stream );
1045 swrite( &stream, EOL, EOL_LEN );
1046 status = swrite( &stream, headerInfo[ headerInfoIndex ].trailer,
1047 headerInfo[ headerInfoIndex ].trailerLen );
1050 sMemDisconnect( &stream );
1054 *destLen = stell( &stream );
1055 sMemDisconnect( &stream );