home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / crypl200.zip / KEYMGMT / ASN1.C next >
Text File  |  1996-09-30  |  58KB  |  1,971 lines

  1. /****************************************************************************
  2. *                                                                            *
  3. *                           ASN.1 Core Library Routines                        *
  4. *                        Copyright Peter Gutmann 1992-1996                    *
  5. *                                                                            *
  6. ****************************************************************************/
  7.  
  8. #include <ctype.h>
  9. #include <stdio.h>
  10. #include <stdlib.h>
  11. #include <string.h>
  12. #if defined( INC_ALL )
  13.   #include "crypt.h"
  14.   #include "asn1.h"
  15. #elif defined( INC_CHILD )
  16.   #include "../crypt.h"
  17.   #include "asn1.h"
  18. #else
  19.   #include "crypt.h"
  20.   #include "keymgmt/asn1.h"
  21. #endif /* Compiler-specific includes */
  22.  
  23. /* Limits of these routines (mainly for easy portability to all systems):
  24.  
  25.    Type identifiers are assumed to be less then 2^16, the lengths of a few
  26.    other types (mainly constructed or otherwise complex types) are assumed to
  27.    be less than 2^16.  This is mainly to allow easy use on systems with
  28.    16-bit ints, and shouldn't be a serious problem.
  29.  
  30.    Encoding follows the Distinguished Encoding Rules.  Things like
  31.    constructed encodings and alternate long forms aren't used.
  32.  
  33.    These routines include handling for a small number other useful types. */
  34.  
  35. /* Some ASN.1 structures are unused, either because they aren't needed or
  36.    because they're impractical.  These are made conditional by the following
  37.    define.  Uncommenting it will make these routines available for use (as
  38.    well as increasing the total code size somewhat) */
  39.  
  40. /* #define STRICT_ASN1 */
  41.  
  42. /* The difference between the Unix and Julian epochs, in seconds */
  43.  
  44. #define EPOCH_DIFF    0x18A41200L        /* 0x3118A41200 or 210866803200 secs */
  45.  
  46. /****************************************************************************
  47. *                                                                            *
  48. *                                Utility Routines                            *
  49. *                                                                            *
  50. ****************************************************************************/
  51.  
  52. #ifdef STRICT_ASN1
  53.  
  54. /* Calculate the size of an encoded flagged value */
  55.  
  56. static int calculateFlaggedSize( const long value )
  57.     {
  58.     if( value >= 16384L )
  59.         return( 3 );
  60.     else
  61.         if( value >= 128L )
  62.             return( 2 );
  63.         else
  64.             return( 1 );
  65.     }
  66. #endif /* STRICT_ASN1 */
  67.  
  68. /* Calculate the size of the encoded length octets */
  69.  
  70. int calculateLengthSize( const long length )
  71.     {
  72.     if( length < 127 )
  73.         /* Use short form of length octets */
  74.         return( 1 );
  75.     else
  76.         /* Use long form of length octets: length-of-length followed by
  77.            32, 24, 16, or 8-bit length */
  78.         return( 1 + ( ( length > 0xFFFFFFL ) ? 4 : \
  79.                       ( length > 0xFFFF ) ? 3 : ( length > 0xFF ) ? 2 : 1 ) );
  80.     }
  81.  
  82. /****************************************************************************
  83. *                                                                            *
  84. *                    Constructors/Destructors for ASN.1 Types                *
  85. *                                                                            *
  86. ****************************************************************************/
  87.  
  88. /* Initialise an integer to a given value, and destroy it afterwards */
  89.  
  90. int newInteger( INTEGER *integer, const long value )
  91.     {
  92.     /* Initialise long format fields */
  93.     integer->precision = 0;
  94.     integer->longInteger = NULL;
  95.  
  96.     /* Initialise short format fields */
  97.     integer->shortInteger = value;
  98.     return( CRYPT_OK );
  99.     }
  100.  
  101. int deleteInteger( INTEGER *integer )
  102.     {
  103.     /* Free any storage used and zero fields */
  104.     if( integer->longInteger != NULL )
  105.         free( integer->longInteger );
  106.     return( newInteger( integer, 0L ) );
  107.     }
  108.  
  109. /* Assign a value to an integer */
  110.  
  111. int assignInteger( INTEGER *integer, const long value )
  112.     {
  113.     deleteInteger( integer );
  114.     return( newInteger( integer, value ) );
  115.     }
  116.  
  117. #ifdef STRICT_ASN1
  118.  
  119. /* Initialise an octet string to a given value, and destroy it afterwards */
  120.  
  121. int newOctetString( OCTETSTRING *octetString, const BYTE *value,
  122.                     const int length )
  123.     {
  124.     octetString->length = length;
  125.     if( !length )
  126.         /* No length, set string field to null value */
  127.         octetString->string = NULL;
  128.     else
  129.         {
  130.         /* Allocate room for data and initialise it */
  131.         if( ( octetString->string = ( BYTE * ) malloc( length ) ) == NULL )
  132.             return( CRYPT_ERROR );
  133.         memcpy( octetString->string, value, length );
  134.         }
  135.     return( CRYPT_OK );
  136.     }
  137.  
  138. int deleteOctetString( OCTETSTRING *octetString )
  139.     {
  140.     /* Free any storage used and zero fields */
  141.     if( octetString->string != NULL )
  142.         free( octetString->string );
  143.     return( newOctetString( octetString, NULL, 0 ) );
  144.     }
  145.  
  146. /* Assign a value to an octet string */
  147.  
  148. int assignOctetString( OCTETSTRING *octetString, const BYTE *value,
  149.                        const int length )
  150.     {
  151.     deleteOctetString( octetString );
  152.     return( newOctetString( octetString, value, length ) );
  153.     }
  154.  
  155. /* Initialise a generalized time structure to a given value, and destroy it
  156.    afterwards */
  157.  
  158. int newGeneralizedTime( GENERALIZED_TIME *generalizedTime,
  159.                         const int years, const int months, const int days,
  160.                         const int hours, const int minutes, const int seconds )
  161.     {
  162.     /* Set up main time fields */
  163.     generalizedTime->years = years;
  164.     generalizedTime->months = months;
  165.     generalizedTime->days = days;
  166.     generalizedTime->hours = hours;
  167.     generalizedTime->minutes = minutes;
  168.     generalizedTime->seconds = seconds;
  169.  
  170.     /* Fractional seconds are system-specific */
  171.     generalizedTime->fractional = 0;
  172.  
  173.     /* Currently we don't have any time differential information */
  174.     generalizedTime->timeDiff = 0;
  175.     return( CRYPT_OK );
  176.     }
  177.  
  178. int deleteGeneralizedTime( GENERALIZED_TIME *generalizedTime )
  179.     {
  180.     /* Zero fields */
  181.     return( newGeneralizedTime( generalizedTime, 0, 0, 0, 0, 0, 0 ) );
  182.     }
  183.  
  184. /* Assign a value to a generalized time structure */
  185.  
  186. int assignGeneralizedTime( GENERALIZED_TIME *generalizedTime,
  187.                            const int years, const int months, const int days,
  188.                            const int hours, const int minutes, const int seconds )
  189.     {
  190.     deleteGeneralizedTime( generalizedTime );
  191.     return( newGeneralizedTime( generalizedTime, years, months, days,
  192.                                 hours, minutes, seconds ) );
  193.     }
  194. #endif /* STRICT_ASN1 */
  195.  
  196. /* Initialise a generalized string string structure, and destroy it
  197.    afterwards */
  198.  
  199. int newGeneralizedString( GENERALIZED_STRING *generalizedString,
  200.                           const STRINGTYPE type, const BYTE *string,
  201.                           const int length )
  202.     {
  203.     /* Set up general information */
  204.     generalizedString->length = length;
  205.     generalizedString->type = type;
  206.  
  207.     if( !length )
  208.         /* No length, set string field to null value */
  209.         generalizedString->string = NULL;
  210.     else
  211.         {
  212.         /* Allocate room for data and initialise it, adding a null terminator
  213.            for those routines which expect one */
  214.         if( ( generalizedString->string = ( BYTE * ) malloc( length + 1 ) ) == NULL )
  215.             return( CRYPT_ERROR );
  216.         memcpy( generalizedString->string, string, length );
  217.         generalizedString->string[ length ] = '\0';
  218.         }
  219.     return( CRYPT_OK );
  220.     }
  221.  
  222. int deleteGeneralizedString( GENERALIZED_STRING *generalizedString )
  223.     {
  224.     /* Free any storage used and zero fields */
  225.     if( generalizedString->string != NULL )
  226.         free( generalizedString->string );
  227.     return( newGeneralizedString( generalizedString, STRINGTYPE_NONE, NULL, 0 ) );
  228.     }
  229.  
  230. /* Assign a value to a generalized string */
  231.  
  232. int assignGeneralizedString( GENERALIZED_STRING *generalizedString,
  233.                              const STRINGTYPE type, const BYTE *string,
  234.                              const int length )
  235.     {
  236.     deleteGeneralizedString( generalizedString );
  237.     return( newGeneralizedString( generalizedString, type, string, length ) );
  238.     }
  239.  
  240. /* Initialise a time structure to a given value, and destroy it afterwards */
  241.  
  242. int newTime( TIME *time, const time_t seconds, const time_t fractional )
  243.     {
  244.     /* Set up time fields */
  245.     time->seconds = seconds;
  246.     time->fractional = fractional;
  247.     return( CRYPT_OK );
  248.     }
  249.  
  250. int deleteTime( TIME *time )
  251.     {
  252.     /* Zero fields */
  253.     return( newTime( time, 0L, 0L ) );
  254.     }
  255.  
  256. /* Assign a value to a time structure */
  257.  
  258. int assignTime( TIME *time, const time_t seconds, const time_t fractional )
  259.     {
  260.     deleteTime( time );
  261.     return( newTime( time, seconds, fractional ) );
  262.     }
  263.  
  264. /* Initialise a monetary amount structure to a given value, and destroy it
  265.    afterwards */
  266.  
  267. int newMonetaryAmount( MONETARY_AMOUNT *monetaryAmount,
  268.                        const CURRENCYTYPE currency, const long units,
  269.                        const long fractional )
  270.     {
  271.     /* Set up monetary amount fields */
  272.     monetaryAmount->currency = currency;
  273.     monetaryAmount->units = units;
  274.     monetaryAmount->fractional = fractional;
  275.     return( CRYPT_OK );
  276.     }
  277.  
  278. int deleteMonetaryAmount( MONETARY_AMOUNT *monetaryAmount )
  279.     {
  280.     /* Zero fields */
  281.     return( newMonetaryAmount( monetaryAmount, CURRENCYTYPE_NONE, 0L, 0L ) );
  282.     }
  283.  
  284. /* Assign a value to a monetary amount structure */
  285.  
  286. int assignMonetaryAmount( MONETARY_AMOUNT *monetaryAmount,
  287.                           const CURRENCYTYPE currency, const long units,
  288.                           const long fractional )
  289.     {
  290.     deleteMonetaryAmount( monetaryAmount );
  291.     return( newMonetaryAmount( monetaryAmount, currency, units, fractional ) );
  292.     }
  293.  
  294. /****************************************************************************
  295. *                                                                            *
  296. *                        sizeof() methods for ASN.1 Types                    *
  297. *                                                                            *
  298. ****************************************************************************/
  299.  
  300. /* Determine the encoded size of an object given only a length.  This can be
  301.    used for a number of simple objects and avoids having to create an object
  302.    only to destroy it after a single call to a sizeof() routine */
  303.  
  304. long sizeofObject( const long length )
  305.     {
  306.     /* Return the total encoded size */
  307.     return( sizeof( BYTE ) + calculateLengthSize( length ) + length );
  308.     }
  309.  
  310. /* Determine the encoded size of an integer value */
  311.  
  312. int sizeofInteger( const INTEGER *integer )
  313.     {
  314.     int size;
  315.  
  316.     if( !integer->precision )
  317.         /* It's stored internally as a signed short value */
  318.         size = ( integer->shortInteger < 128 ) ? 1 :
  319.                ( integer->shortInteger < 32768L ) ? 2 :
  320.                ( integer->shortInteger < 8388608L ) ? 3 :
  321.                ( integer->shortInteger < 2147483648UL ) ? 4 : 5;
  322.     else
  323.         /* It's stored internally as a little-endian long value */
  324.         size = integer->precision;
  325.  
  326.     /* Return the total encoded size */
  327.     return( sizeof( BYTE ) + calculateLengthSize( size ) + size );
  328.     }
  329.  
  330. /* Determine the encoded size of a short integer value.  This saves having
  331.    to create an integer type just to pass it to sizeofInteger() */
  332.  
  333. int sizeofShortInteger( const long value )
  334.     {
  335.     INTEGER integer;
  336.     int size;
  337.  
  338.     /* Create an integer to hold the numeric value, find it's size, and
  339.        delete it.  The encoding is the same as that of an integer */
  340.     newInteger( &integer, ( long ) value );
  341.     size = sizeofInteger( &integer );
  342.     deleteInteger( &integer );
  343.     return( size );
  344.     }
  345.  
  346. /* Determine the encoded size of an enumerated value.  This is encoded as an
  347.    integer so we just create an integer for it and calculate its value */
  348.  
  349. int sizeofEnumerated( const int enumerated )
  350.     {
  351.     return( sizeofShortInteger( enumerated ) );
  352.     }
  353.  
  354. #ifdef STRICT_ASN1
  355.  
  356. /* Determine the encoded size of an octet string */
  357.  
  358. int sizeofOctetString( const OCTETSTRING *octetString )
  359.     {
  360.     /* Return the total encoded size */
  361.     return( sizeof( BYTE ) + calculateLengthSize( octetString->length ) +
  362.             octetString->length );
  363.     }
  364. #endif /* STRICT_ASN1 */
  365.  
  366. /* Determine the encoded size of a bitstring */
  367.  
  368. int sizeofBitString( const long bitString )
  369.     {
  370.     int size = ( bitString > 65535L ) ? 3 : ( bitString > 256 ) ? 2 : 1;
  371.  
  372.     /* Return the total encoded size (the extra byte is for the bitcount
  373.        mod 8) */
  374.     return( sizeof( BYTE ) + calculateLengthSize( size ) + 1 + size );
  375.     }
  376.  
  377. #ifdef STRICT_ASN1
  378.  
  379. /* Determine the encoded size of an ISO 646 string */
  380.  
  381. int sizeofISO646string( const char *iso646string )
  382.     {
  383.     int size = strlen( iso646string );
  384.  
  385.     /* Return the total encoded size */
  386.     return( sizeof( BYTE ) + calculateLengthSize( size ) + size );
  387.     }
  388.  
  389. /* Determine the encoded size of an object identifier */
  390.  
  391. int sizeofObjectIdentifier( const OBJECT_IDENTIFIER *objectIdentifier )
  392.     {
  393.     int size = sizeof( BYTE ) + calculateFlaggedSize( objectIdentifier->ident );
  394.  
  395.     /* Calculate the size of the optional fields */
  396.     if( objectIdentifier->noFields > 3 )
  397.         size += calculateFlaggedSize( objectIdentifier->subIdent1 );
  398.     if( objectIdentifier->noFields > 4 )
  399.         size += calculateFlaggedSize( objectIdentifier->subIdent2 );
  400.     if( objectIdentifier->noFields > 5 )
  401.         size += calculateFlaggedSize( objectIdentifier->subIdent3 );
  402.  
  403.     /* Return the total encoded size */
  404.     return( sizeof( BYTE ) + calculateLengthSize( size ) + size );
  405.     }
  406.  
  407. /* Determine the encoded size of a generalized time value */
  408.  
  409. int sizeofGeneralizedTime( const GENERALIZED_TIME *generalizedTime )
  410.     {
  411.     char buffer[ 10 ];
  412.     int size = 14;            /* Size of fixed-size fields */
  413.  
  414.     /* Add the fractional seconds field if there is one present */
  415.     if( generalizedTime->fractional )
  416.         size += sprintf( buffer, ".%d", generalizedTime->fractional );
  417.  
  418.     /* Add the time differential if there is one */
  419.     if( generalizedTime->timeDiff )
  420.         size += 5;            /* '+' + 4-digit hour difference */
  421.  
  422.     /* Return the total encoded size */
  423.     return( sizeof( BYTE ) + calculateLengthSize( size ) + size );
  424.     }
  425. #endif /* STRICT_ASN1 */
  426.  
  427. /* Determine the encoded size of a generalizedString value */
  428.  
  429. int sizeofGeneralizedString( const GENERALIZED_STRING *generalizedString )
  430.     {
  431.     int size;
  432.  
  433.     /* It's a composite type.  Evaluate the size of the enumerated value
  434.        needed to encode the string type and the octet string needed to
  435.        encode the string itself */
  436.     size = sizeofEnumerated( generalizedString->type ) +
  437.            ( int ) sizeofObject( generalizedString->length );
  438.  
  439.     return( sizeof( BYTE ) + calculateLengthSize( size ) + size );
  440.     }
  441.  
  442. /* Determine the encoded size of an ASCII string value.  This saves having
  443.    to create a generalizedString type just to pass it to
  444.    sizeofGeneralizedString() */
  445.  
  446. int sizeofTextString( const char *string )
  447.     {
  448.     int size = sizeofEnumerated( STRINGTYPE_ISO646 ) +
  449.                ( int ) sizeofObject( strlen( string ) );
  450.  
  451.     return( sizeof( BYTE ) + calculateLengthSize( size ) + size );
  452.     }
  453.  
  454. /* Determine the encoded size of a time value */
  455.  
  456. int sizeofTime( const TIME *time )
  457.     {
  458.     int size = 2 + 5;    /* Size of fixed-size fields for 5-byte INTEGER */
  459.  
  460.     if( time->fractional )
  461.         {
  462.         INTEGER integer;
  463.  
  464.         /* Calculate size of fractional component.  It's actually a context-
  465.            specific tagged type, but the encoded size is the same as an
  466.            integer */
  467.         newInteger( &integer, time->fractional );
  468.         size += sizeofInteger( &integer );
  469.         deleteInteger( &integer );
  470.         }
  471.  
  472.     /* Return the total encoded size */
  473.     return( sizeof( BYTE ) + calculateLengthSize( size ) + size );
  474.     }
  475.  
  476. /* Determine the encoded size of a monetary amount value */
  477.  
  478. int sizeofMonetaryAmount( const MONETARY_AMOUNT *monetaryAmount )
  479.     {
  480.     int size;
  481.  
  482.     /* It's a composite type.  Evaluate the size of the enumerated value
  483.        needed to encode the currency and the integer and optional fractional
  484.        component needed to encode the monetary amount */
  485.     size = sizeofEnumerated( monetaryAmount->currency );
  486.     size += sizeofShortInteger( monetaryAmount->units );
  487.     if( monetaryAmount->fractional )
  488.         /* Calculate size of fractional component.  It's actually a context-
  489.            specific tagged type, but the encoded size is the same as an
  490.            integer */
  491.         size += sizeofShortInteger( monetaryAmount->fractional );
  492.  
  493.     /* Return the total encoded size */
  494.     return( sizeof( BYTE ) + calculateLengthSize( size ) + size );
  495.     }
  496.  
  497. /****************************************************************************
  498. *                                                                            *
  499. *                            ASN.1 Output Routines                            *
  500. *                                                                            *
  501. ****************************************************************************/
  502.  
  503. /* Write a value in 7-bit flagged format */
  504.  
  505. static void writeFlagged( STREAM *stream, const long value )
  506.     {
  507.     long flaggedValue = value;
  508.     BOOLEAN hasHighBits = FALSE;
  509.  
  510.     /* Write the high octets (if necessary) with flag bits set, followed by
  511.        the final octet */
  512.     if( flaggedValue >= 16384L )
  513.         {
  514.         sputc( stream, ( BYTE ) ( 0x80 | ( flaggedValue >> 14 ) ) );
  515.         flaggedValue -= 16384L;
  516.         hasHighBits = TRUE;
  517.         }
  518.     if( ( flaggedValue > 128L ) || hasHighBits )
  519.         {
  520.         sputc( stream, ( BYTE ) ( 0x80 | ( flaggedValue >> 7 ) ) );
  521.         flaggedValue -= 128L;
  522.         }
  523.     sputc( stream, ( BYTE ) flaggedValue );
  524.     }
  525.  
  526. #ifdef STRICT_ASN1
  527.  
  528. /* Write the identifier octets for an ASN.1 data type */
  529.  
  530. void writeIdentifier( STREAM *stream, const int class,
  531.                       const BOOLEAN isConstructed, const int identifier )
  532.     {
  533.     int constructed = ( isConstructed ) ? BER_CONSTRUCTED : 0;
  534.  
  535.     /* Check if we can write it as a short encoding of the type */
  536.     if( identifier <= MAX_SHORT_BER_ID )
  537.         sputc( stream, ( BYTE ) ( class | constructed | identifier ) );
  538.     else
  539.         {
  540.         /* Write it as a long encoding */
  541.         sputc( stream, ( BYTE ) ( class | constructed | LONG_BER_ID ) );
  542.  
  543.         /* Write the identifier as a flagged value */
  544.         writeFlagged( stream, identifier );
  545.         }
  546.     }
  547. #endif /* STRICT_ASN1 */
  548.  
  549. /* Write a context-specific tag */
  550.  
  551. void writeCtag( STREAM *stream, const int identifier,
  552.                 const BOOLEAN isConstructed )
  553.     {
  554.     int constructed = ( isConstructed ) ? BER_CONSTRUCTED : 0;
  555.  
  556.     /* Check if we can write it as a short encoding of the type */
  557.     if( identifier <= MAX_SHORT_BER_ID )
  558.         sputc( stream, ( BYTE ) ( BER_CONTEXT_SPECIFIC | constructed | \
  559.                                   identifier ) );
  560.     else
  561.         {
  562.         /* Write it as a long encoding */
  563.         sputc( stream, ( BYTE ) ( BER_CONTEXT_SPECIFIC | constructed | \
  564.                                   LONG_BER_ID ) );
  565.  
  566.         /* Write the identifier as a flagged value */
  567.         writeFlagged( stream, identifier );
  568.         }
  569.     }
  570.  
  571. /* Write the length octets for an ASN.1 data type */
  572.  
  573. void writeLength( STREAM *stream, long length )
  574.     {
  575.     /* Check if we can use the short form of length octets */
  576.     if( length < 127 )
  577.         sputc( stream, ( BYTE ) length );
  578.     else
  579.         {
  580.         int noLengthOctets = ( length > 0xFFFFFFL ) ? 4 : \
  581.                              ( length > 0xFFFFL ) ? 3 : \
  582.                              ( length > 0xFF ) ? 2 : 1;
  583.  
  584.         /* Write number of length octets */
  585.         sputc( stream, ( BYTE ) ( 0x80 | noLengthOctets ) );
  586.  
  587.         /* Write the length octets themselves */
  588.         if( length > 0xFFFFFFL )
  589.             {
  590.             sputc( stream, ( BYTE ) ( length >> 24 ) );
  591.             length &= 0xFFFFFFL;
  592.             }
  593.         if( length > 0xFFFFL )
  594.             {
  595.             sputc( stream, ( BYTE ) ( length >> 16 ) );
  596.             length &= 0xFFFFL;
  597.             }
  598.         if( length > 0xFF )
  599.             {
  600.             sputc( stream, ( BYTE ) ( length >> 8 ) );
  601.             length &= 0xFF;
  602.             }
  603.         sputc( stream, ( BYTE ) length );
  604.         }
  605.     }
  606.  
  607. /* Write a (non-bignum) numeric value - used by several routines */
  608.  
  609. static void writeNumeric( STREAM *stream, const long integer )
  610.     {
  611.     BOOLEAN needsLZ = TRUE;
  612.     BYTE buffer[ 5 ];
  613.     int length = 0, i;
  614.  
  615.     /* Determine the number of bytes necessary to encode the integer and
  616.        encode it into a temporary buffer */
  617.     if( integer < 0 )
  618.         buffer[ length++ ] = 0;
  619.     if( integer > 0x00FFFFFFL )
  620.         {
  621.         buffer[ length++ ] = ( BYTE ) ( integer >> 24 );
  622.         needsLZ = FALSE;
  623.         }
  624.     if( integer >= 0x00800000L && needsLZ )
  625.         buffer[ length++ ] = 0;
  626.     if( integer > 0x0000FFFFL )
  627.         {
  628.         buffer[ length++ ] = ( BYTE ) ( integer >> 16 );
  629.         needsLZ = FALSE;
  630.         }
  631.     if( integer >= 0x00008000L && needsLZ )
  632.         buffer[ length++ ] = 0;
  633.     if( integer > 0x000000FFL )
  634.         {
  635.         buffer[ length++ ] = ( BYTE ) ( integer >> 8 );
  636.         needsLZ = FALSE;
  637.         }
  638.     if( integer >= 0x00000080L && needsLZ )
  639.         buffer[ length++ ] = 0;
  640.     buffer[ length++ ] = ( BYTE ) integer;
  641.  
  642.     /* Write the length and integer */
  643.     writeLength( stream, length );
  644.     for( i = 0; i < length; i++ )
  645.         sputc( stream, buffer[ i ] );
  646.     zeroise( buffer, sizeof( buffer ) );
  647.     }
  648.  
  649. /* Write an integer */
  650.  
  651. int writeInteger( STREAM *stream, const INTEGER *integer, const int tag )
  652.     {
  653.     /* Write the identifier field */
  654.     if( tag == DEFAULT_TAG )
  655.         writeTag( stream, BER_INTEGER );
  656.     else
  657.         writeCtag( stream, tag, FALSE );
  658.  
  659.     /* Check if it's stored internally as a short value */
  660.     if( !integer->precision )
  661.         writeNumeric( stream, integer->shortInteger );
  662.     else
  663.         {
  664.         /* Write it as a big-endian long value */
  665.         writeLength( stream, integer->precision );
  666.         swrite( stream, integer->longInteger, integer->precision );
  667.         }
  668.     return( sGetStatus( stream ) );
  669.     }
  670.  
  671. /* Write a short integer value */
  672.  
  673. int writeShortInteger( STREAM *stream, const long integer, const int tag )
  674.     {
  675.     /* Write the identifier and numeric fields */
  676.     if( tag == DEFAULT_TAG )
  677.         writeTag( stream, BER_INTEGER );
  678.     else
  679.         writeCtag( stream, tag, FALSE );
  680.     writeNumeric( stream, integer );
  681.     return( sGetStatus( stream ) );
  682.     }
  683.  
  684. /* Write a bignum integer value */
  685.  
  686. int writeStaticInteger( STREAM *stream, const BYTE *integer,
  687.                         const int integerLength, const int tag )
  688.     {
  689.     /* Write the identifier field */
  690.     if( tag == DEFAULT_TAG )
  691.         writeTag( stream, BER_INTEGER );
  692.     else
  693.         writeCtag( stream, tag, FALSE );
  694.  
  695.     /* Write it as a big-endian long value */
  696.     writeLength( stream, integerLength );
  697.     swrite( stream, integer, integerLength );
  698.  
  699.     return( sGetStatus( stream ) );
  700.     }
  701.  
  702. /* Write an enumerated value */
  703.  
  704. int writeEnumerated( STREAM *stream, const int enumerated, const int tag )
  705.     {
  706.     /* Write the identifier and numeric fields */
  707.     if( tag == DEFAULT_TAG )
  708.         writeTag( stream, BER_ENUMERATED );
  709.     else
  710.         writeCtag( stream, tag, FALSE );
  711.     writeNumeric( stream, ( long ) enumerated );
  712.     return( sGetStatus( stream ) );
  713.     }
  714.  
  715. /* Write a null value */
  716.  
  717. int writeNull( STREAM *stream, const int tag )
  718.     {
  719.     /* Write the identifier and null length octet */
  720.     if( tag == DEFAULT_TAG )
  721.         writeTag( stream, BER_NULL );
  722.     else
  723.         writeCtag( stream, tag, FALSE );
  724.     sputc( stream, 0 );
  725.     return( sGetStatus( stream ) );
  726.     }
  727.  
  728. /* Write a boolean value.  Note that we always encode TRUE as 1 and FALSE
  729.    as 0 even though the BER state that TRUE can be any nonzero value */
  730.  
  731. int writeBoolean( STREAM *stream, const BOOLEAN boolean, const int tag )
  732.     {
  733.     /* Write the identifier and boolean value */
  734.     if( tag == DEFAULT_TAG )
  735.         writeTag( stream, BER_BOOLEAN );
  736.     else
  737.         writeCtag( stream, tag, FALSE );
  738.     sputc( stream, 1 );                                /* Length is one byte */
  739.     sputc( stream, ( BYTE ) ( boolean ? 1 : 0 ) );    /* Write TRUE or FALSE */
  740.     return( sGetStatus( stream ) );
  741.     }
  742.  
  743. #ifdef STRICT_ASN1
  744.  
  745. /* Write an octet string */
  746.  
  747. int writeOctetString( STREAM *stream, const OCTETSTRING *octetString,
  748.                       const int tag )
  749.     {
  750.     /* Write the identifier and string fields */
  751.     if( tag == DEFAULT_TAG )
  752.         writeTag( stream, BER_OCTETSTRING );
  753.     else
  754.         writeCtag( stream, tag, FALSE );
  755.     writeLength( stream, octetString->length );
  756.     swrite( stream, octetString->string, octetString->length );
  757.     return( sGetStatus( stream ) );
  758.     }
  759. #endif /* STRICT_ASN1 */
  760.  
  761. /* Write a byte string.  This saves having to create an octet string just
  762.    to write a block of bytes */
  763.  
  764. int writeByteString( STREAM *stream, const BYTE *string, const int length,
  765.                      const int tag )
  766.     {
  767.     /* Write the identifier and string fields */
  768.     if( tag == DEFAULT_TAG )
  769.         writeTag( stream, BER_OCTETSTRING );
  770.     else
  771.         writeCtag( stream, tag, FALSE );
  772.     writeLength( stream, length );
  773.     swrite( stream, string, length );
  774.     return( sGetStatus( stream ) );
  775.     }
  776.  
  777. /* Write a bit string */
  778.  
  779. int writeBitString( STREAM *stream, const long bitString, const int tag )
  780.     {
  781.     int octetLength = ( bitString > 0xFFFFFFL ) ? 4 : \
  782.                       ( bitString > 0xFFFFL ) ? 3 : \
  783.                       ( bitString > 0xFF ) ? 2 : 1;
  784.  
  785.     /* Write the identifier and length (string length in octets + extra octet
  786.        for remaining bits).  Since we always work in octets to make things
  787.        easier to handle, the bit remainder count is always 0 (all unused data
  788.        bits are set to 0) */
  789.     if( tag == DEFAULT_TAG )
  790.         writeTag( stream, BER_BITSTRING );
  791.     else
  792.         writeCtag( stream, tag, FALSE );
  793.     writeLength( stream, octetLength + 1 );
  794.     sputc( stream, 0 );            /* Write bit remainder octet */
  795.  
  796.     /* Write the bit string itself */
  797.     if( bitString > 0xFFFFFFL )
  798.         sputc( stream, ( BYTE ) ( bitString >> 24 ) );
  799.     if( bitString > 0xFFFFL )
  800.         sputc( stream, ( BYTE ) ( bitString >> 16 ) );
  801.     if( bitString > 0xFF )
  802.         sputc( stream, ( BYTE ) ( bitString >> 8 ) );
  803.     sputc( stream, ( BYTE ) bitString );
  804.     return( sGetStatus( stream ) );
  805.     }
  806.  
  807. #ifdef STRICT_ASN1
  808.  
  809. /* Write an ISO 646 string */
  810.  
  811. int writeISO646string( STREAM *stream, const char *iso646string,
  812.                         const int tag )
  813.     {
  814.     /* Write the identifier and string fields */
  815.     if( tag == DEFAULT_TAG )
  816.         writeTag( stream, BER_STRING_ISO646 );
  817.     else
  818.         writeCtag( stream, tag, FALSE );
  819.     writeLength( stream, isi646tring->length );
  820.     swrite( stream, iso646tring->string, iso646tring->length );
  821.     return( sGetStatus( stream ) );
  822.     }
  823.  
  824. /* Write an object identifier */
  825.  
  826. int writeObjectIdentifier( STREAM *stream, const OBJECT_IDENTIFIER *objectIdentifier,
  827.                             const int tag )
  828.     {
  829.     int length = sizeof( BYTE ) + calculateFlaggedSize( objectIdentifier->ident );
  830.  
  831.     /* Write the identifier and length fields.  The root, type, and ident
  832.        fields are always present, the rest are optional.  The first two are
  833.        encoded as one byte, the remaining values are variable - length and
  834.        their size must be determined at runtime */
  835.     if( tag == DEFAULT_TAG )
  836.         writeTag( stream, BER_OBJECT_IDENTIFIER );
  837.     else
  838.         writeCtag( stream, tag, FALSE );
  839.     if( objectIdentifier->noFields > 3 )
  840.         length += calculateFlaggedSize( objectIdentifier->subIdent1 );
  841.     if( objectIdentifier->noFields > 4 )
  842.         length += calculateFlaggedSize( objectIdentifier->subIdent2 );
  843.     if( objectIdentifier->noFields > 5 )
  844.         length += calculateFlaggedSize( objectIdentifier->subIdent3 );
  845.     writeLength( stream, length );
  846.  
  847.     /* Write the object identifier */
  848.     writeFlagged( stream, ( objectIdentifier->root * 40 ) + objectIdentifier->type );
  849.     writeFlagged( stream, objectIdentifier->ident );
  850.     if( objectIdentifier->noFields > 3 )
  851.         writeFlagged( stream, objectIdentifier->subIdent1 );
  852.     if( objectIdentifier->noFields > 4 )
  853.         writeFlagged( stream, objectIdentifier->subIdent2 );
  854.     if( objectIdentifier->noFields > 5 )
  855.         writeFlagged( stream, objectIdentifier->subIdent3 );
  856.     }
  857.  
  858. /* Write a generalized time value */
  859.  
  860. int writeGeneralizedTime( STREAM *stream, const GENERALIZED_TIME *generalizedTime,
  861.                            const int tag )
  862.     {
  863.     char buffer[ 40 ];
  864.     int count;
  865.  
  866.     /* Print the main time fields */
  867.     count = sprintf( buffer, "%04d%02d%02d%02d%02d%02d", generalizedTime->years,
  868.                      generalizedTime->months, generalizedTime->days,
  869.                      generalizedTime->hours, generalizedTime->minutes,
  870.                      generalizedTime->seconds );
  871.  
  872.     /* Add the fractional seconds field if there is one present */
  873.     if( generalizedTime->fractional )
  874.         count += sprintf( buffer + count, ".%d", generalizedTime->fractional );
  875.  
  876.     /* Add the time differential if there is one */
  877.     if( generalizedTime->timeDiff )
  878.         count += sprintf( buffer + count, "+%02d00", generalizedTime->timeDiff );
  879.  
  880.     /* Write the identifier and length fields */
  881.     if( tag == DEFAULT_TAG )
  882.         writeTag( stream, BER_TIME_GENERALIZED );
  883.     else
  884.         writeCtag( stream, tag, FALSE );
  885.     writeLength( stream, count );
  886.  
  887.     /* Write the time string */
  888.     swrite( stream, ( BYTE * ) buffer, count );
  889.     }
  890. #endif /* STRICT_ASN1 */
  891.  
  892. /* Write a generalized string value */
  893.  
  894. int writeGeneralizedString( STREAM *stream, const GENERALIZED_STRING *generalizedString,
  895.                              const int tag )
  896.     {
  897.     /* Write the identifier and length fields */
  898.     if( tag == DEFAULT_TAG )
  899.         writeTag( stream, BER_SEQUENCE );
  900.     else
  901.         writeCtag( stream, tag, TRUE );
  902.     writeLength( stream, sizeofEnumerated( generalizedString->type ) +
  903.                          ( int ) sizeofObject( generalizedString->length ) );
  904.  
  905.     /* It's a composite type.  Write the enumeration which encodes the string
  906.        type, followed by the data as an octet string */
  907.     writeEnumerated( stream, generalizedString->type, DEFAULT_TAG );
  908.     writeByteString( stream, generalizedString->string,
  909.                      generalizedString->length, DEFAULT_TAG );
  910.  
  911.     return( sGetStatus( stream ) );
  912.     }
  913.  
  914. /* Generalized strings are often just ISO 646/ASCII strings, so we use the
  915.    following special-case routine to write these simple string values to save
  916.    having to create a generalizedString just to write it out */
  917.  
  918. int writeTextString( STREAM *stream, const char *string, const int tag )
  919.     {
  920.     /* Write the identifier and length fields */
  921.     if( tag == DEFAULT_TAG )
  922.         writeTag( stream, BER_SEQUENCE );
  923.     else
  924.         writeCtag( stream, tag, TRUE );
  925.     writeLength( stream, sizeofEnumerated( STRINGTYPE_ISO646 ) +
  926.                  ( int ) sizeofObject( strlen( string ) ) );
  927.  
  928.     /* It's a composite type.  Write the enumeration which encodes the string
  929.        type, followed by the data as an octet string */
  930.     writeEnumerated( stream, STRINGTYPE_ISO646, DEFAULT_TAG );
  931.     writeByteString( stream, ( BYTE * ) string, strlen( string ), DEFAULT_TAG );
  932.  
  933.     return( sGetStatus( stream ) );
  934.     }
  935.  
  936. /* Write a time value */
  937.  
  938. int writeTime( STREAM *stream, const TIME *time, const int tag )
  939.     {
  940.     time_t seconds = time->seconds + EPOCH_DIFF;
  941.  
  942.     /* Write the identifier field */
  943.     if( tag == DEFAULT_TAG )
  944.         writeTag( stream, BER_SEQUENCE );
  945.     else
  946.         writeCtag( stream, tag, TRUE );
  947.  
  948.     /* Calculate the length and write it.  The seconds field is (for all
  949.        intents and purposes) always 2 bytes for the integer encoding + 5 bytes
  950.        for the payload (it's + 4 bytes before 4576BCE and + 6 bytes after
  951.        34,865AD) */
  952.     writeLength( stream, 2 + 5 + ( ( time->fractional ) ? \
  953.                                    sizeofShortInteger( time->fractional ) : 0 ) );
  954.  
  955.     /* Write seconds component */
  956.     writeTag( stream, BER_INTEGER );
  957.     writeLength( stream, 5 );
  958.     sputc( stream, 0x31 );        /* Write MSB of time in seconds */
  959.     sputc( stream, ( BYTE ) ( seconds >> 24 ) );
  960.     sputc( stream, ( BYTE ) ( seconds >> 16 ) );
  961.     sputc( stream, ( BYTE ) ( seconds >> 8 ) );
  962.     sputc( stream, ( BYTE ) seconds );
  963.  
  964.     /* Write fractional component */
  965.     if( time->fractional )
  966.         writeShortInteger( stream, time->fractional, DEFAULT_TAG );
  967.     return( sGetStatus( stream ) );
  968.     }
  969.  
  970. #if 0
  971.  
  972. /* Write a monetary amount value */
  973.  
  974. int writeMonetaryAmount( STREAM *stream, const MONETARY_AMOUNT *monetaryAmount,
  975.                           const int tag )
  976.     {
  977.     /* Write the identifier and length fields */
  978.     if( tag == DEFAULT_TAG )
  979.         writeTag( stream, BER_MONETARY_AMOUNT );
  980.     else
  981.         writeCtag( stream, tag, TRUE );
  982.     writeLength( stream, sizeofEnumerated( monetaryAmount->currency ) +
  983.                  sizeofShortInteger( monetaryAmount->units ) +
  984.                  sizeofShortInteger( monetaryAmount->fractional ) );
  985.  
  986.     /* It's a composite type.  Write the enumeration which encodes the
  987.        currency type, followed by the data as an integer and optional second
  988.        integer */
  989.     writeEnumerated( stream, monetaryAmount->currency, DEFAULT_TAG );
  990.     writeShortInteger( stream, monetaryAmount->units, DEFAULT_TAG );
  991.     if( monetaryAmount->fractional )
  992.         writeShortInteger( stream, monetaryAmount->fractional, 0 );
  993.  
  994.     return( sGetStatus( stream ) );
  995.     }
  996. #endif /* 0 */
  997.  
  998. /****************************************************************************
  999. *                                                                            *
  1000. *                            ASN.1 Input Routines                            *
  1001. *                                                                            *
  1002. ****************************************************************************/
  1003.  
  1004. /* Read a value in 7-bit flagged format */
  1005.  
  1006. static int readFlagged( STREAM *stream, long *flaggedValue )
  1007.     {
  1008.     long value = 0L;
  1009.     int readDataLength = 1, count = 4;
  1010.     BYTE data;
  1011.  
  1012.     /* Read the high octets (if any) with flag bits set, followed by
  1013.        the final octet */
  1014.     data = sgetc( stream );
  1015.     while( count-- && ( data & 0x80 ) )
  1016.         {
  1017.         int ch;
  1018.  
  1019.         value <<= 7;
  1020.         value |= data & 0x7F;
  1021.         ch = sgetc( stream );
  1022.         if( ch == STREAM_EMPTY || ch == STREAM_READ )
  1023.             return( CRYPT_ERROR );
  1024.         data = ch;
  1025.         readDataLength++;
  1026.         }
  1027.     *flaggedValue = value | data;
  1028.     if( count <= 0 )
  1029.         {
  1030.         sSetError( stream, STREAM_BADDATA );
  1031.         return( CRYPT_ERROR );
  1032.         }
  1033.  
  1034.     return( readDataLength );
  1035.     }
  1036.  
  1037. /* Read the identifier octets for an ASN.1 data type */
  1038.  
  1039. int readIdentifier( STREAM *stream, BER_TAGINFO *tagInfo )
  1040.     {
  1041.     BYTE data;
  1042.     int readDataLength = 1;
  1043.  
  1044.     data = sgetc( stream );
  1045.     tagInfo->class = data & BER_CLASS_MASK;
  1046.     tagInfo->constructed = ( data & BER_CONSTRUCTED_MASK ) ? TRUE : FALSE;
  1047.     if( ( data & BER_SHORT_ID_MASK ) != LONG_BER_ID )
  1048.         /* ID is encoded in short form */
  1049.         tagInfo->identifier = data & BER_SHORT_ID_MASK;
  1050.     else
  1051.         {
  1052.         /* ID is encoded in long form */
  1053.         long value;
  1054.  
  1055.         readDataLength += readFlagged( stream, &value );
  1056.         tagInfo->identifier = ( int ) value;
  1057.         }
  1058.     tagInfo->length = 0;
  1059.  
  1060.     return( readDataLength );
  1061.     }
  1062.  
  1063. /* Undo a read for when we're looking ahead for a certain tagged type */
  1064.  
  1065. int unreadTag( STREAM *stream )
  1066.     {
  1067.     /* This code isn't very general-purpose in that it assumes that the tag
  1068.        will fit into a single octet.  However since we're only going to use
  1069.        this to undo lookahead for context-specific tags of optional types,
  1070.        this should be safe */
  1071.     sungetc( stream );
  1072.     return( 1 );
  1073.     }
  1074.  
  1075. /* Read and check the type of a tag */
  1076.  
  1077. int checkReadTag( STREAM *stream, const int tag )
  1078.     {
  1079.     /* Read the start of the fixed sequence of fields */
  1080.     if( readTag( stream ) != tag )
  1081.         {
  1082.         unreadTag( stream );
  1083.         return( 0 );
  1084.         }
  1085.     return( 1 );
  1086.     }
  1087.  
  1088. /* Read and check the type of a context-specific tag */
  1089.  
  1090. int checkReadCtag( STREAM *stream, const int identifier,
  1091.                    const BOOLEAN isConstructed )
  1092.     {
  1093.     BER_TAGINFO tagInfo;
  1094.     int readDataLength;
  1095.  
  1096.     /* Read the start of the fixed sequence of fields */
  1097.     readDataLength = readIdentifier( stream, &tagInfo );
  1098.     if( tagInfo.class != BER_CONTEXT_SPECIFIC || \
  1099.         tagInfo.constructed != isConstructed ||
  1100.         tagInfo.identifier != identifier )
  1101.         {
  1102.         unreadTag( stream );
  1103.         return( 0 );
  1104.         }
  1105.     return( readDataLength );
  1106.     }
  1107.  
  1108. /* Read the length octets for an ASN.1 data type */
  1109.  
  1110. int readLength( STREAM *stream, long *length )
  1111.     {
  1112.     int readDataLength = 1;
  1113.     BYTE data;
  1114.  
  1115.     data = sgetc( stream );
  1116.     if( !( data & 0x80 ) )
  1117.         /* Data is encoded in short form */
  1118.         *length = ( long ) data;
  1119.     else
  1120.         {
  1121.         /* Data is encoded in long form.  First get the octet count */
  1122.         int noLengthOctets = data & 0x7F;
  1123.         long localLength = 0;
  1124.  
  1125.         /* Now read the length octets themselves */
  1126.         while( noLengthOctets-- > 0 )    /* Terminates after max.127 iterations */
  1127.             {
  1128.             localLength <<= 8;
  1129.             localLength |= ( unsigned int ) sgetc( stream );
  1130.             readDataLength++;
  1131.             }
  1132.         *length = localLength;
  1133.         }
  1134.  
  1135.     return( readDataLength );
  1136.     }
  1137.  
  1138. /* Read a short (< 128 bytes) raw object without decoding it.  This is used
  1139.    to read short data blocks like object identifiers which are only ever
  1140.    handled in encoded form */
  1141.  
  1142. int readRawObject( STREAM *stream, BYTE *buffer, int *bufferLength,
  1143.                    const int maxLength, const int tag )
  1144.     {
  1145.     int readDataLength = 2, remainder = 0, length, status;
  1146.  
  1147.     /* Read the identifier field and length.  Since we need to remember each
  1148.        byte as it is read we can't just call readLength() for the length,
  1149.        but since we only need to handle lengths which can be encoded in a
  1150.        single byte this isn't much of a problem */
  1151.     if( readTag( stream ) != tag )
  1152.         {
  1153.         sSetError( stream, STREAM_BADDATA );
  1154.         return( CRYPT_ERROR );
  1155.         }
  1156.     length = sgetc( stream );
  1157.     if( length & 0x80 )
  1158.         {
  1159.         /* If the object is longer than 127 bytes, we can't handle it */
  1160.         sSetError( stream, STREAM_BADDATA );
  1161.         return( CRYPT_ERROR );
  1162.         }
  1163.     buffer[ 0 ] = tag;
  1164.     buffer[ 1 ] = length;
  1165.  
  1166.     /* Read in the object, limiting the size to the maximum buffer size */
  1167.     if( length > maxLength - 2 )
  1168.         {
  1169.         remainder = ( int ) length - ( maxLength - 2 );
  1170.         length = maxLength - 2;
  1171.         }
  1172.     sread( stream, buffer + 2, ( int ) length );
  1173.     *bufferLength = ( int ) length;
  1174.  
  1175.     /* Read in any remaining data if necessary */
  1176.     if( remainder > 0 && \
  1177.         ( status = sSkip( stream, remainder ) ) != STREAM_OK )
  1178.         return( status );
  1179.  
  1180.     return( readDataLength + ( int ) length );
  1181.     }
  1182.  
  1183. /* Read a numeric value - used by several routines */
  1184.  
  1185. static int readNumeric( STREAM *stream, INTEGER *integer )
  1186.     {
  1187.     int readDataLength;
  1188.     long length;
  1189.  
  1190.     /* Read the length field */
  1191.     readDataLength = readLength( stream, &length );
  1192.     readDataLength += ( int ) length;
  1193.  
  1194.     /* Check if it's a short value */
  1195.     if( length <= sizeof( long ) )
  1196.         {
  1197.         integer->precision = 0;
  1198.         integer->shortInteger = 0L;
  1199.         while( length-- > 0 )    /* Terminates after sizeof( long ) iterations */
  1200.             {
  1201.             integer->shortInteger <<= 8;
  1202.             integer->shortInteger |= sgetc( stream );
  1203.             }
  1204.         }
  1205.     else
  1206.         {
  1207.         int status;
  1208.  
  1209.         /* Read it in as a long value.  First, allocate the room for it */
  1210.         if( integer->longInteger != NULL )
  1211.             free( integer->longInteger );
  1212.         if( ( integer->longInteger = ( BYTE * ) malloc( ( size_t ) length ) ) == NULL )
  1213.             return( CRYPT_ERROR );
  1214.  
  1215.         /* Now read it in as a big-endian value */
  1216.         integer->precision = ( int ) length;
  1217.         status = sread( stream, integer->longInteger, ( int ) length );
  1218.         if( status != STREAM_OK )
  1219.             return( status );
  1220.         }
  1221.  
  1222.     return( readDataLength );
  1223.     }
  1224.  
  1225. /* Read an integer value into a static buffer - used by internal routines */
  1226.  
  1227. int readStaticInteger( STREAM *stream, BYTE *integer, int *integerLength,
  1228.                        const int maxLength )
  1229.     {
  1230.     int readDataLength = 1, remainder = 0, status;
  1231.     long length;
  1232.  
  1233.     /* Read the identifier field */
  1234.     if( readTag( stream ) != BER_INTEGER )
  1235.         {
  1236.         sSetError( stream, STREAM_BADDATA );
  1237.         return( CRYPT_ERROR );
  1238.         }
  1239.  
  1240.     /* Read the length field */
  1241.     readDataLength += readLength( stream, &length );
  1242.     readDataLength += ( int ) length;
  1243.     *integerLength = ( int ) length;
  1244.  
  1245.     /* Now read in the numeric value, limiting the size to the maximum buffer
  1246.        size */
  1247.     if( length > maxLength )
  1248.         {
  1249.         remainder = ( int ) length - maxLength;
  1250.         length = maxLength;
  1251.         }
  1252.     if( ( status = sread( stream, integer, ( int ) length ) ) != STREAM_OK )
  1253.         return( status );
  1254.  
  1255.     /* Read in any remaining data */
  1256.     if( ( status = sSkip( stream, remainder ) ) != STREAM_OK )
  1257.         return( status );
  1258.     return( readDataLength );
  1259.     }
  1260.  
  1261. /* Read a string value - used by several routines */
  1262.  
  1263. int readStringValue( STREAM *stream, BYTE **string, int *stringLength )
  1264.     {
  1265.     int readDataLength;
  1266.     long length;
  1267.  
  1268.     /* Read the string length */
  1269.     readDataLength = readLength( stream, &length );
  1270.     *stringLength = ( int ) length;
  1271.  
  1272.     /* Read the string itself.  First allocate the room for it */
  1273.     if( *string != NULL )
  1274.         free( *string );
  1275.     if( ( *string = ( BYTE * ) malloc( ( size_t ) length + 1 ) ) == NULL )
  1276.         return( CRYPT_ERROR );
  1277.  
  1278.     /* Now read it in, adding a null terminator for those routines which
  1279.        need it */
  1280.     sread( stream, *string, ( int ) length );
  1281.     ( *string )[ ( int ) length ] = '\0';
  1282.  
  1283.     if( sGetStatus( stream ) != STREAM_OK )
  1284.         return( sGetStatus( stream ) );
  1285.     return( readDataLength + ( int ) length );
  1286.     }
  1287.  
  1288. /* Read an octet string value into a static buffer - used by internal routines */
  1289.  
  1290. int _readStaticOctetString( STREAM *stream, BYTE *string, int *stringLength,
  1291.                             const int maxLength, const BOOLEAN readIdent )
  1292.     {
  1293.     int readDataLength = 0, remainder = 0, status;
  1294.     long length;
  1295.  
  1296.     /* Read the identifier field if necessary */
  1297.     if( readIdent )
  1298.         {
  1299.         if( readTag( stream ) != BER_OCTETSTRING )
  1300.             {
  1301.             sSetError( stream, STREAM_BADDATA );
  1302.             return( CRYPT_ERROR );
  1303.             }
  1304.         readDataLength++;
  1305.         }
  1306.  
  1307.     /* Now read in the string, limiting the size to the maximum buffer size */
  1308.     readDataLength += readLength( stream, &length );
  1309.     if( length > maxLength )
  1310.         {
  1311.         remainder = ( int ) length - maxLength;
  1312.         length = maxLength;
  1313.         }
  1314.     sread( stream, string, ( int ) length );
  1315.     *stringLength = ( int ) length;
  1316.  
  1317.     /* Read in any remaining data */
  1318.     if( ( status = sSkip( stream, remainder ) ) != STREAM_OK )
  1319.         return( status );
  1320.     return( readDataLength + ( int ) length );
  1321.     }
  1322.  
  1323. /* Read an ISO 646/ASCII string value into a static buffer - used by internal
  1324.    routines */
  1325.  
  1326. int readStaticTextString( STREAM *stream, char *string, const int maxLength,
  1327.                           const BOOLEAN readIdent )
  1328.     {
  1329.     int dataLength, readDataLength = 0, status;
  1330.     long length;
  1331.  
  1332.     /* Read the identifier field if necessary */
  1333.     if( readIdent )
  1334.         {
  1335.         if( readTag( stream ) != BER_SEQUENCE )
  1336.             {
  1337.             sSetError( stream, STREAM_BADDATA );
  1338.             return( CRYPT_ERROR );
  1339.             }
  1340.         readDataLength++;
  1341.         }
  1342.     readDataLength += readLength( stream, &length );    /* Skip SEQUENCE length info */
  1343.     readDataLength += readEnumerated( stream, &status );
  1344.     if( status != STRINGTYPE_ISO646 )
  1345.         {
  1346.         /* If it's not an ISO 646 string, we shouldn't be using a
  1347.            textString function to read it */
  1348.         sSetError( stream, STREAM_BADDATA );
  1349.         return( CRYPT_ERROR );
  1350.         }
  1351.     readDataLength += readStaticOctetString( stream, ( BYTE * ) string,
  1352.                                              &dataLength, maxLength - 1 );
  1353.     string[ dataLength ] = '\0';
  1354.  
  1355.     if( sGetStatus( stream ) != STREAM_OK )
  1356.         return( sGetStatus( stream ) );
  1357.     return( readDataLength );
  1358.     }
  1359.  
  1360. /* Read a universal type and discard it (used to skip unknown or unwanted
  1361.    types) */
  1362.  
  1363. int readUniversalData( STREAM *stream )
  1364.     {
  1365.     long length;
  1366.     int readDataLength = readLength( stream, &length ), status;
  1367.  
  1368.     readDataLength += ( int ) length;
  1369.     if( ( status = sSkip( stream, ( int ) length ) ) != STREAM_OK )
  1370.         return( status );
  1371.     return( readDataLength );
  1372.     }
  1373.  
  1374. int readUniversal( STREAM *stream )
  1375.     {
  1376.     readTag( stream );
  1377.     return( readUniversalData( stream ) + 1 );
  1378.     }
  1379.  
  1380. /* Read an integer */
  1381.  
  1382. int _readInteger( STREAM *stream, INTEGER *integer, const BOOLEAN readIdent )
  1383.     {
  1384.     int readDataLength = 0;
  1385.  
  1386.     /* Read the identifier field if necessary */
  1387.     if( readIdent )
  1388.         {
  1389.         if( readTag( stream ) != BER_INTEGER )
  1390.             {
  1391.             sSetError( stream, STREAM_BADDATA );
  1392.             return( CRYPT_ERROR );
  1393.             }
  1394.         readDataLength++;
  1395.         }
  1396.  
  1397.     /* Read the numeric field */
  1398.     readDataLength += readNumeric( stream, integer );
  1399.  
  1400.     if( sGetStatus( stream ) != STREAM_OK )
  1401.         return( sGetStatus( stream ) );
  1402.     return( readDataLength );
  1403.     }
  1404.  
  1405. /* Read a short integer value */
  1406.  
  1407. int _readShortInteger( STREAM *stream, long *value, const BOOLEAN readIdent )
  1408.     {
  1409.     INTEGER integer;
  1410.     int readDataLength;
  1411.  
  1412.     /* Create an integer to hold the numeric value */
  1413.     newInteger( &integer, 0L );
  1414.  
  1415.     /* Read the numeric field and extract the integer value */
  1416.     readDataLength = _readInteger( stream, &integer, readIdent );
  1417.     *value = integer.shortInteger;
  1418.  
  1419.     /* Delete the created integer */
  1420.     deleteInteger( &integer );
  1421.  
  1422.     if( integer.precision )
  1423.         {
  1424.         /* If we're expecting a short integer and get a bignum, something has
  1425.            gone wrong */
  1426.         sSetError( stream, STREAM_BADDATA );
  1427.         return( CRYPT_ERROR );
  1428.         }
  1429.     if( sGetStatus( stream ) != STREAM_OK )
  1430.         return( sGetStatus( stream ) );
  1431.     return( readDataLength );
  1432.     }
  1433.  
  1434. /* Read an enumerated value.  This is encoded as an integer so we just
  1435.    create an integer for it and read it as such */
  1436.  
  1437. int _readEnumerated( STREAM *stream, int *enumeration, const BOOLEAN readIdent )
  1438.     {
  1439.     INTEGER integer;
  1440.     int readDataLength = 0;
  1441.  
  1442.     /* Read the identifier field if necessary */
  1443.     if( readIdent )
  1444.         {
  1445.         if( readTag( stream ) != BER_ENUMERATED )
  1446.             {
  1447.             sSetError( stream, STREAM_BADDATA );
  1448.             return( CRYPT_ERROR );
  1449.             }
  1450.         readDataLength++;
  1451.         }
  1452.  
  1453.     /* Create an integer to hold the numeric value */
  1454.     newInteger( &integer, 0L );
  1455.  
  1456.     /* Read the numeric field and extract the enumerated type */
  1457.     readDataLength += readNumeric( stream, &integer );
  1458.     *enumeration = ( int ) integer.shortInteger;
  1459.  
  1460.     /* Delete the created integer */
  1461.     deleteInteger( &integer );
  1462.  
  1463.     if( sGetStatus( stream ) != STREAM_OK )
  1464.         return( sGetStatus( stream ) );
  1465.     return( readDataLength );
  1466.     }
  1467.  
  1468. /* Read a null value */
  1469.  
  1470. int _readNull( STREAM *stream, const BOOLEAN readIdent )
  1471.     {
  1472.     int readDataLength = 0;
  1473.  
  1474.     /* Read the identifier if necessary */
  1475.     if( readIdent )
  1476.         {
  1477.         if( readTag( stream ) != BER_NULL )
  1478.             {
  1479.             sSetError( stream, STREAM_BADDATA );
  1480.             return( CRYPT_ERROR );
  1481.             }
  1482.         readDataLength++;
  1483.         }
  1484.  
  1485.     /* Skip length octet */
  1486.     sgetc( stream );
  1487.  
  1488.     if( sGetStatus( stream ) != STREAM_OK )
  1489.         return( sGetStatus( stream ) );
  1490.     return( readDataLength + 1 );
  1491.     }
  1492.  
  1493. /* Read a boolean value */
  1494.  
  1495. int _readBoolean( STREAM *stream, BOOLEAN *boolean, const BOOLEAN readIdent )
  1496.     {
  1497.     int readDataLength = 0;
  1498.  
  1499.     /* Read the identifier if necessary */
  1500.     if( readIdent )
  1501.         {
  1502.         if( readTag( stream ) != BER_BOOLEAN )
  1503.             {
  1504.             sSetError( stream, STREAM_BADDATA );
  1505.             return( CRYPT_ERROR );
  1506.             }
  1507.         readDataLength++;
  1508.         }
  1509.  
  1510.     /* Skip length octet and read boolean value */
  1511.     sgetc( stream  );
  1512.     *boolean = sgetc( stream ) ? TRUE : FALSE;
  1513.  
  1514.     if( sGetStatus( stream ) != STREAM_OK )
  1515.         return( sGetStatus( stream ) );
  1516.     return( readDataLength + 2 );
  1517.     }
  1518.  
  1519. #ifdef STRICT_ASN1
  1520.  
  1521. /* Read an octet string */
  1522.  
  1523. int _readOctetString( STREAM *stream, OCTETSTRING *octetString,
  1524.                       const BOOLEAN readIdent )
  1525.     {
  1526.     int readDataLength = 0;
  1527.  
  1528.     /* Read the identifier field if necessary */
  1529.     if( readIdent )
  1530.         {
  1531.         if( readTag( stream ) != BER_OCTETSTRING )
  1532.             {
  1533.             sSetError( stream, STREAM_BADDATA );
  1534.             return( CRYPT_ERROR );
  1535.             }
  1536.         readDataLength++;
  1537.         }
  1538.  
  1539.     /* Read the string field */
  1540.     readDataLength += readStringValue( stream, &octetString->string,
  1541.                                        &octetString->length );
  1542.  
  1543.     if( sGetStatus( stream ) != STREAM_OK )
  1544.         return( sGetStatus( stream ) );
  1545.     return( readDataLength );
  1546.     }
  1547. #endif /* STRICT_ASN1 */
  1548.  
  1549. /* Read a bit string */
  1550.  
  1551. int _readBitString( STREAM *stream, long *bitString, const BOOLEAN readIdent )
  1552.     {
  1553.     int readDataLength = 0, byteCount;
  1554.     long length, bitValue = 0;
  1555.  
  1556.     /* Read the identifier field if necessary */
  1557.     if( readIdent )
  1558.         {
  1559.         if( readTag( stream ) != BER_BITSTRING )
  1560.             {
  1561.             sSetError( stream, STREAM_BADDATA );
  1562.             return( CRYPT_ERROR );
  1563.             }
  1564.         readDataLength++;
  1565.         }
  1566.  
  1567.     /* Read the length field (string length in octets + extra octet for
  1568.        remaining bits) */
  1569.     readDataLength += readLength( stream, &length ) + 1;
  1570.     length--;                        /* Don't count length of extra octet */
  1571.     byteCount = sgetc( stream );    /* Read remainder bits */
  1572.     if( length > 4 )
  1573.         {
  1574.         sSetError( stream, STREAM_BADDATA );
  1575.         return( CRYPT_BADDATA );
  1576.         }
  1577.  
  1578.     /* Read the bit string itself */
  1579.     for( byteCount = 0; byteCount < length; byteCount++ )
  1580.         bitValue = ( bitValue << 8 ) | sgetc( stream );
  1581.     *bitString = bitValue;
  1582.     if( sGetStatus( stream ) != STREAM_OK )
  1583.         return( sGetStatus( stream ) );
  1584.     return( readDataLength + ( int ) length );
  1585.     }
  1586.  
  1587. #ifdef STRICT_ASN1
  1588.  
  1589. /* Read an ISO 646 string */
  1590.  
  1591. int _readISO646string( STREAM *stream, char *iso646string,
  1592.                        const BOOLEAN readIdent )
  1593.     {
  1594.     int readDataLength = 0, dummy;
  1595.  
  1596.     /* Read the identifier field if necessary */
  1597.     if( readIdent )
  1598.         {
  1599.         if( readTag( stream ) != BER_STRING_ISO646 )
  1600.             {
  1601.             sSetError( stream, STREAM_BADDATA );
  1602.             return( CRYPT_ERROR );
  1603.             }
  1604.         readDataLength++;
  1605.         }
  1606.  
  1607.     /* Read the string fields */
  1608.     readDataLength += readStringValue( stream, ( ( BYTE ** ) &iso646string ), &dummy );
  1609.  
  1610.     if( sGetStatus( stream ) != STREAM_OK )
  1611.         return( sGetStatus( stream ) );
  1612.     return( readDataLength );
  1613.     }
  1614.  
  1615. /* Read an object identifier */
  1616.  
  1617. int _readObjectIdentifier( STREAM *stream, OBJECT_IDENTIFIER *objectIdentifier, BOOLEAN readIdent )
  1618.     {
  1619.     long value;
  1620.     int data, readDataLength = 0;
  1621.  
  1622.     /* Read the identifier field if necessary */
  1623.     if( readIdent )
  1624.         {
  1625.         if( readTag( stream ) != BER_OBJECT_IDENTIFIER )
  1626.             {
  1627.             sSetError( stream, STREAM_BADDATA );
  1628.             return( CRYPT_ERROR );
  1629.             }
  1630.         readDataLength++;
  1631.         }
  1632.  
  1633.     /* Read the length fields.  The length field is one shorter than the
  1634.        in-memory value since the first two values are encoded as one */
  1635.     readDataLength = readLength( stream, &objectIdentifier->noFields );
  1636.     objectIdentifier->noFields++;
  1637.  
  1638.     /* Read the identifier itself */
  1639.     readDataLength += readFlagged( stream, &value );
  1640.     data = ( int ) value;
  1641.     objectIdentifier->root = data / 40;
  1642.     objectIdentifier->type = data % 40;
  1643.     length += readFlagged( stream, &value);
  1644.     objectIdentifier->ident = value;
  1645.     if( objectIdentifier->noFields > 3 )
  1646.         {
  1647.         readDataLength += readFlagged( stream, &value );
  1648.         objectIdentifier->subIdent1 = value;
  1649.         }
  1650.     if( objectIdentifier->noFields > 4 )
  1651.         {
  1652.         readDataLength += readFlagged( stream, &value );
  1653.         objectIdentifier->subIdent2 = value;
  1654.         }
  1655.     if( objectIdentifier->noFields > 5 )
  1656.         {
  1657.         readDataLength += readFlagged( stream, &value );
  1658.         objectIdentifier->subIdent3 = value;
  1659.         }
  1660.  
  1661.     if( sGetStatus( stream ) != STREAM_OK )
  1662.         return( sGetStatus( stream ) );
  1663.     return( readDataLength );
  1664.     }
  1665. /* Read a generalized time value */
  1666.  
  1667. int _readGeneralizedTime( STREAM *stream, GENERALIZED_TIME *generalizedTime, BOOLEAN readIdent )
  1668.     {
  1669.     char buffer[ 40 ];
  1670.     int length, readDataLength = 0, index;
  1671.  
  1672.     /* Read the identifier field if necessary */
  1673.     if( readIdent )
  1674.         {
  1675.         if( readTag( stream ) != BER_GENERALIZED_TIME )
  1676.             {
  1677.             sSetError( stream, STREAM_BADDATA );
  1678.             return( CRYPT_ERROR );
  1679.             }
  1680.         readDataLength++;
  1681.         }
  1682.  
  1683.     /* Read the length field */
  1684.     readDataLength = readLength( stream, &length );
  1685.  
  1686.     /* Read the time string itself into memory */
  1687.     sread( stream, ( BYTE * ) buffer, length );
  1688.  
  1689.     /* Read the main time fields */
  1690.     sscanf( buffer, "%04d%02d%02d%02d%02d%02d", &generalizedTime->years,
  1691.             &generalizedTime->months, &generalizedTime->days,
  1692.             &generalizedTime->hours, &generalizedTime->minutes,
  1693.             &generalizedTime->seconds );
  1694.     index = 14;        /* Size of main time field */
  1695.  
  1696.     /* Read the fractional seconds field if there is one present */
  1697.     if( buffer[ index ] == '.' )
  1698.         {
  1699.         sscanf( buffer + index + 1, "%d", &generalizedTime->fractional );
  1700.         index++;        /* Skip dit */
  1701.         while( index < length && isalpha( buffer[ index ] ) )
  1702.             index++;    /* Skip to end of fractional field */
  1703.         }
  1704.  
  1705.     /* Read the time differential if there is one */
  1706.     if( buffer[ index ] == '-' || buffer[ index ] == '+' )
  1707.         sscanf( buffer + index + 1, "%02d", &generalizedTime->timeDiff );
  1708.  
  1709.     if( sGetStatus( stream ) != STREAM_OK )
  1710.         return( sGetStatus( stream ) );
  1711.     return( readDataLength + length );
  1712.     }
  1713. #endif /* STRICT_ASN1 */
  1714.  
  1715. /* Read a UTC time value */
  1716.  
  1717. static int getDigits( STREAM *stream )
  1718.     {
  1719.     int result, ch = sgetc( stream );
  1720.  
  1721.     if( isdigit( ch ) )
  1722.         {
  1723.         result = ( ch - '0' ) * 10;
  1724.         ch = sgetc( stream );
  1725.         if( isdigit( ch ) )
  1726.             return( result + ( ch - '0' ) );
  1727.         }
  1728.  
  1729.     return( -1 );
  1730.     }
  1731.  
  1732. int _readUTCTime( STREAM *stream, time_t *time, const BOOLEAN readIdent )
  1733.     {
  1734.     int readDataLength = 0, status = CRYPT_OK;
  1735.     struct tm utcTime;
  1736.     long length;
  1737.  
  1738.     /* Read the identifier field if necessary */
  1739.     if( readIdent )
  1740.         {
  1741.         if( readTag( stream ) != BER_TIME_UTC )
  1742.             {
  1743.             sSetError( stream, STREAM_BADDATA );
  1744.             return( CRYPT_ERROR );
  1745.             }
  1746.         readDataLength++;
  1747.         }
  1748.  
  1749.     /* Read the length field and make sure it's of the correct size */
  1750.     readDataLength = readLength( stream, &length );
  1751.     if( length < 11 || length > 17 )
  1752.         {
  1753.         sSetError( stream, STREAM_BADDATA );
  1754.         return( CRYPT_ERROR );
  1755.         }
  1756.  
  1757.     /* Decode the time fields.  Ideally we should use sscanf(), but there
  1758.        are too many dodgy versions of this around */
  1759.     memset( &utcTime, 0, sizeof( struct tm ) );
  1760.     utcTime.tm_year = getDigits( stream );
  1761.     utcTime.tm_mon = getDigits( stream ) - 1;
  1762.     utcTime.tm_mday = getDigits( stream );
  1763.     utcTime.tm_hour = getDigits( stream );
  1764.     utcTime.tm_min = getDigits( stream );
  1765.     length -= 10;
  1766.  
  1767.     /* Read any extra fields if necessary */
  1768.     if( length )
  1769.         {
  1770.         int ch = sgetc( stream );
  1771.  
  1772.         /* Read the seconds field if there is one present */
  1773.         if( length >= 2 && isdigit( ch ) )
  1774.             {
  1775.             sungetc( stream );
  1776.             utcTime.tm_sec = getDigits( stream );
  1777.             length -= 2;
  1778.             if( length )
  1779.                 ch = sgetc( stream );
  1780.             }
  1781.  
  1782.         /* Read the time differential if there is one.  Since the differential
  1783.            is given as the difference between GMT and the local time, the sign
  1784.            of the amount to add is the opposite of the differential sign (eg
  1785.            GMT-0500 means add 5 hours to get GMT) */
  1786.         if( length == 5 && ( ch == '-' || ch == '+' ) )
  1787.             {
  1788.             int sign = ( ch == '-' ) ? 1 : -1;
  1789.             int hourOffset, minuteOffset;
  1790.  
  1791.             hourOffset = getDigits( stream );
  1792.             minuteOffset = getDigits( stream );
  1793.             if( ( minuteOffset | hourOffset ) == -1 )
  1794.                 status = CRYPT_ERROR;
  1795.             utcTime.tm_hour += hourOffset * sign;
  1796.             utcTime.tm_min += minuteOffset * sign;
  1797.             }
  1798.         else
  1799.             /* If there's anything left, the data format is wrong */
  1800.             if( length && !( length == 1 && ch == 'Z' ) )
  1801.                 status = CRYPT_ERROR;
  1802.         }
  1803.  
  1804.     /* Make sure there were no format errors */
  1805.     if( ( utcTime.tm_year | utcTime.tm_mon | utcTime.tm_mon | \
  1806.           utcTime.tm_mday | utcTime.tm_hour | utcTime.tm_min | \
  1807.           utcTime.tm_sec ) == -1 )
  1808.         status = CRYPT_ERROR;
  1809.  
  1810.     /* Finally, convert it to the local time.  Since the UTCTime doesn't
  1811.        take centuries into account (and you'd think that when the ISO came up
  1812.        with the worlds least efficient time encoding format they could have
  1813.        spared another two bytes to fully specify the year), we adjust by one
  1814.        century for years < 80, and hope there aren't any Y2K bugs in
  1815.        mktime().
  1816.  
  1817.         "The time is out of joint; o cursed spite,
  1818.          That ever I was born to set it right"    - Shakespeare,
  1819.                                                   "Hamlet" */
  1820.     if( utcTime.tm_year < 80 )
  1821.         utcTime.tm_year += 100;
  1822.     if( status == CRYPT_OK )
  1823.         {
  1824.         time_t theTime = mktime( &utcTime );
  1825.  
  1826.         if( theTime == -1 )
  1827.             status = CRYPT_ERROR;
  1828.         else
  1829.             *time = mktime( localtime( &theTime ) );
  1830.         }
  1831.     if( status == CRYPT_ERROR )
  1832.         {
  1833.         *time = 0;
  1834.         sSetError( stream, STREAM_BADDATA );
  1835.         return( CRYPT_ERROR );
  1836.         }
  1837.  
  1838.     if( sGetStatus( stream ) != STREAM_OK )
  1839.         return( sGetStatus( stream ) );
  1840.     return( readDataLength + ( int ) length );
  1841.     }
  1842.  
  1843. /* Read a generalized string value */
  1844.  
  1845. int _readGeneralizedString( STREAM *stream, GENERALIZED_STRING *generalizedString,
  1846.                             const BOOLEAN readIdent )
  1847.     {
  1848.     BER_TAGINFO tagInfo;
  1849.     int readDataLength = 0;
  1850.     long dummy;
  1851.  
  1852.     /* Read the identifier field if necessary */
  1853.     if( readIdent )
  1854.         {
  1855.         if( readTag( stream ) != BER_SEQUENCE )
  1856.             {
  1857.             sSetError( stream, STREAM_BADDATA );
  1858.             return( CRYPT_ERROR );
  1859.             }
  1860.         readDataLength++;
  1861.         }
  1862.  
  1863.     /* Read type and string data components */
  1864.     readDataLength += readLength( stream, &dummy );    /* Skip SEQUENCE length info */
  1865.     readDataLength += readEnumerated( stream, ( int * ) &generalizedString->type );
  1866.     readDataLength += readIdentifier( stream, &tagInfo );    /* Skip OCTET STRING tag */
  1867.     readDataLength += readStringValue( stream, &generalizedString->string,
  1868.                                        &generalizedString->length );
  1869.  
  1870.     if( sGetStatus( stream ) != STREAM_OK )
  1871.         return( sGetStatus( stream ) );
  1872.     return( readDataLength );
  1873.     }
  1874.  
  1875. /* Read a time value */
  1876.  
  1877. int _readTime( STREAM *stream, TIME *time, const BOOLEAN readIdent )
  1878.     {
  1879.     int tagLength = 0, readDataLength = 0;
  1880.     BER_TAGINFO tagInfo;
  1881.     long length, totalLength;
  1882.     time_t timeStamp;
  1883.  
  1884.     /* Read the identifier field if necessary */
  1885.     if( readIdent )
  1886.         {
  1887.         if( readTag( stream ) != BER_SEQUENCE )
  1888.             {
  1889.             sSetError( stream, STREAM_BADDATA );
  1890.             return( CRYPT_ERROR );
  1891.             }
  1892.         readDataLength++;
  1893.         }
  1894.  
  1895.     /* Read the length field */
  1896.     readDataLength = readLength( stream, &totalLength );
  1897.     tagLength += readDataLength;
  1898.  
  1899.     /* Read seconds component.  Because this is outside the range of time_t
  1900.        on most systems we can't use readInteger.  Instead we skip the first
  1901.        octet and treat the remainder as a time_t */
  1902.     readDataLength += readIdentifier( stream, &tagInfo );
  1903.     readDataLength += readLength( stream, &length );
  1904.     readDataLength += ( int ) length;
  1905.     sgetc( stream );    /* Skip billions of seconds */
  1906.     timeStamp = ( time_t ) sgetc( stream ) << 24;
  1907.     timeStamp |= ( time_t ) sgetc( stream ) << 16;
  1908.     timeStamp |= ( time_t ) sgetc( stream ) << 8;
  1909.     timeStamp |= ( time_t ) sgetc( stream );
  1910.     timeStamp -= EPOCH_DIFF;
  1911.     time->seconds = timeStamp;
  1912.  
  1913.     /* Read optional fractional component */
  1914.     if( totalLength - readDataLength > 0 )
  1915.         {
  1916.         long integer;
  1917.  
  1918.         readShortInteger( stream, &integer );
  1919.         time->fractional = ( time_t ) integer;
  1920.         }
  1921.  
  1922.     if( sGetStatus( stream ) != STREAM_OK )
  1923.         return( sGetStatus( stream ) );
  1924.     return( tagLength + ( int ) totalLength );
  1925.     }
  1926.  
  1927. #if 0
  1928.  
  1929. /* Read a monetary amount value */
  1930.  
  1931. int _readMonetaryAmount( STREAM *stream, MONETARY_AMOUNT *monetaryAmount,
  1932.                          const BOOLEAN readIdent )
  1933.     {
  1934.     int readDataLength = 0, totalLength;
  1935.  
  1936.     /* Read the identifier field if necessary */
  1937.     if( readIdent )
  1938.         {
  1939.         if( readTag( stream ) != BER_MONETARY_AMOUNT )
  1940.             {
  1941.             sSetError( stream, STREAM_BADDATA );
  1942.             return( CRYPT_ERROR );
  1943.             }
  1944.         readDataLength++;
  1945.         }
  1946.  
  1947.     /* Read type and units components */
  1948.     readDataLength += readLength( stream, &totalLength );
  1949.     readDataLength += readEnumerated( stream, ( int * ) &monetaryAmount->currency );
  1950.     readDataLength += readShortInteger( stream, &monetaryAmount->units );
  1951.  
  1952.     /* Read optional fractional component */
  1953.     if( totalLength - readDataLength > 0 )
  1954.         {
  1955.         INTEGER fractional;
  1956.         int length;
  1957.  
  1958.         newInteger( &fractional, 0L );
  1959.         if( ( length = checkReadCtagIdentifier( stream, 0, TRUE ) ) != CRYPT_OK )
  1960.             return( CRYPT_ERROR );
  1961.         readDataLength += readIntegerData( stream, &fractional ) + length;
  1962.         monetaryAmount->fractional = fractional.shortInteger;
  1963.         deleteInteger( &fractional );
  1964.         }
  1965.  
  1966.     if( sGetStatus( stream ) != STREAM_OK )
  1967.         return( sGetStatus( stream ) );
  1968.     return( readDataLength );
  1969.     }
  1970. #endif /* 0 */
  1971.