⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 asn1util.c

📁 Netscape公司提供的安全套接字层
💻 C
字号:
/*  *********************************************************************
    File: asn1util.c

    SSLRef 3.0 Final -- 11/19/96

    Copyright (c)1996 by Netscape Communications Corp.

    By retrieving this software you are bound by the licensing terms
    disclosed in the file "LICENSE.txt". Please read it, and if you don't
    accept the terms, delete this software.

    SSLRef 3.0 was developed by Netscape Communications Corp. of Mountain
    View, California <http://home.netscape.com/> and Consensus Development
    Corporation of Berkeley, California <http://www.consensus.com/>.

    *********************************************************************

    File: asn1util.c   Utilities for ASN.1

    A number of functions which assist with interpreting and preparing
    ASN.1 elements.

    ****************************************************************** */

#ifndef _ASN1UTIL_H_
#include "asn1util.h"
#endif

#include <string.h>
#include <time.h>

/* ASNErr ASNParseBER(SSLBuffer ber, ASN1Type *asnList, int *listSize);
 *  Parse ASN.1 BER-encoded data
 *  Input:  a buffer of BER-encoded ASN.1 data
 *          an array of ASN1Type structures
 *          a count of how big the array is
 *  Returns:    0 if sucessfully parsed
 *              ASNTooFewTypesErr if parsing list isn't big enough
 *              ASNBadEncodingErr if BER appears to be incorrect
 *  Side effects:   asnList is filled in with specifiers of encoded sub-structures
 *                  (sequential BER types)
 *              *listSize is changed to how many elements were parsed
 */
ASNErr
ASNParseBER(SSLBuffer ber, ASN1Type *asnList, int *listSize)
{   uint8       *p,val;
    int         itemsLeft;
    ASN1Type    curType;
    
    itemsLeft = *listSize;
    *listSize = 0;
    p = ber.data;
    
    while (p <= ber.data + ber.length - 2)  /* Minimum type length is 2 bytes */
    {   curType.identifier = *p++;
        if ((val = *p) < 0x80)
        {   curType.contents.length = val;
            curType.contents.data = p + 1;
            p += val + 1;
        }
        else
        {   val &= ~0x80;                   /* strip top bit for length */
            if (val > 4)
                return ASNBadEncodingErr;   /* We only support lengths < 2^32 */
            
            curType.contents.length = 0;
            ++p;
            while (val-- > 0)
            {   curType.contents.length = (curType.contents.length << 8) | *p++;
            }
            curType.contents.data = p;
            p += curType.contents.length;
        }
        if (itemsLeft-- <= 0)
            return SSLOverflowErr;
        
        *asnList++ = curType;
        ++*listSize;
    }
    
    if (p != ber.data + ber.length)
    {   --*listSize;                /* Strip one off of the list; it's probably bad */
        return ASNBadEncodingErr;
    }
    
    return SSLNoErr;
}

/* ASNErr ASNCountBERElements(SSLBuffer ber, int *listSize);
 *  Count how many BER-encoded elements are in a buffer; allows you to
 *      pre-flight allocating an array to pass to ASNParseBER
 *  Input:  a buffer of BER-encoded ASN.1 data
 *          a pointer to an integer to return a value in
 *  Returns:    0 if sucessfully parsed
 *              ASNBadEncodingErr if BER appears to be incorrect
 *  Side effects:   *listSize is changed to how many elements were parsed
 */
ASNErr
ASNCountBERElements(SSLBuffer ber, int *listSize)
{   uint8       *p,val;
    uint32      len;
    
    *listSize = 0;
    p = ber.data;
    
    while (p <= ber.data + ber.length - 2)  /* Minimum type length is 2 bytes */
    {   ++p;                        /* Skip identifier */
        if ((val = *p) < 0x80)
        {   p += val + 1;           /* Skip length & data */
        }
        else
        {   val &= ~0x80;                   /* strip top bit for length */
            if (val > 4)
                return ASNBadEncodingErr;   /* We only support lengths < 2^32 */
            
            len = 0;
            ++p;
            while (val-- > 0)
            {   len = (len << 8) | *p++;
            }
            p += len;
        }
        ++*listSize;
    }
    
    if (p != ber.data + ber.length)
        return ASNBadEncodingErr;
    
    return SSLNoErr;    /* no error */
}

/* ASNErr ASNDecodeInteger(SSLBuffer data, sint32 *value);
 *  Attempt to decode a BER encoded integer into a 32-bit value
 *  Input:  contents of an ASN.1 INTEGER type
 *          a pointer to storage for a signed 32-bit int
 *  Returns:    0 if sucessfully parsed
 *              ASNBadEncodingErr if a BER error is found
 *              ASNIntegerTooBigErr if the integer exceeds 32 bits
 *  Side effects:   none
 */
ASNErr
ASNDecodeInteger(SSLBuffer data, sint32 *value)
{   unsigned int    i;
    sint32          result;
    
    if (data.length == 0)
        return ASNBadEncodingErr;
    if (data.length > 1 && data.data[0] == 0)
        return ASNBadEncodingErr;
    
    if (data.length > 4)
        return ASNIntegerTooBigErr;
    
    result = 0;
    for (i = 0; i < data.length; i++)
        result = (result << 8) | data.data[i];
    
    *value = result;
    return SSLNoErr;
}

extern ASN1ObjectID ASNKnownObjectIDs[];

/* ASNErr ASNDecodeObjectID(SSLBuffer data, ASN1ObjectID *oid);
 *  Attempt to decode a BER encoded object ID, including
 *  decoding it into an integer identifier with the help
 *  of a table.
 *  Input:  contents of an ASN.1 OBJECT IDENITIFIER type
 *          a pointer to storage for an ASN1ObjectID type
 *  Returns:    0 if sucessfully parsed
 *  Uses:   ASN1ObjectID ASNKnownObjectIDs[]
 *  Side effects:   none
 */
ASNErr
ASNDecodeObjectID(SSLBuffer data, ASN1ObjectID *oid)
{   ASN1ObjectID    *oidTable;

    oid->objectID = data;       /* Keep a pointer to the real data */
    
    oidTable = ASNKnownObjectIDs;
    
    while (oidTable->oidValue != 0)
    {   if (oidTable->objectID.length == data.length)
            if (memcmp(data.data, oidTable->objectID.data, data.length) == 0)
                break;
        ++oidTable;
    }
    
    oid->oidValue = oidTable->oidValue;
    return SSLNoErr;
}

/*  Decode two ASCII characters into an integer [0-99].
    
    Return -1 for an invalid encoding
 */
static int
DecodeTwoASCII(unsigned char *data)
{
    if (data[0] < '0' || data[0] > '9' || data[1] < '0' || data[1] > '9')
        return -1;
    
    return (data[0] - '0')*10 + data[1] - '0';
}

/* ASNErr ASNDecodeUTCTime(SSLBuffer data, X509Time *time);
 *  Attempt to decode a BER encoded UTC time into seconds since 1/1/1970 GMT
 *  Input:  contents of an ASN.1 OBJECT IDENITIFIER type
 *          a pointer to storage for an X509Time
 *  Returns:    0 if sucessfully parsed
 *              ASNBadEncodingErr if invalid encoding is found
 *  Side effects:   none
 *
 *  Date format: YYMMDDhhmm[ss](Z|(+|-)hhmm)
 */
ASNErr
ASNDecodeUTCTime(SSLBuffer data, ASNUTCTime *timeResult)
{   struct tm       time;
    unsigned char   *utc = data.data, zoneFlag;
    unsigned int    hasSeconds, offsetMin;
    sint32          zoneOffset;
    
    if (data.length != 11 && data.length != 13 &&
        data.length != 15 && data.length != 17)
        return ASNBadEncodingErr;
    
    time.tm_year = DecodeTwoASCII(utc);
    if (time.tm_year < 0)
        return ASNBadEncodingErr;
    
/* Attempt to hack around lame two-digit years
 *  assume years before 1970 are actually in
 *  the 21st century
 */
    if (time.tm_year < 70)
        time.tm_year += 100;
    
    time.tm_mon = DecodeTwoASCII(utc+2) - 1;
    if (time.tm_mon < 0 || time.tm_mon > 11)
        return ASNBadEncodingErr;
    time.tm_mday = DecodeTwoASCII(utc+4);
    if (time.tm_mday < 1 || time.tm_mday > 31)
        return ASNBadEncodingErr;
    time.tm_hour = DecodeTwoASCII(utc+6);
    if (time.tm_hour < 0 || time.tm_hour > 23)
        return ASNBadEncodingErr;
    time.tm_min = DecodeTwoASCII(utc+8);
    if (time.tm_min < 0 || time.tm_min > 59)
        return ASNBadEncodingErr;
    if (utc[10] >= '0' && utc[10] <= '9')
    {   if (data.length < 13)
            return ASNBadEncodingErr;
        time.tm_sec = DecodeTwoASCII(utc+10);
        if (time.tm_sec < 0 || time.tm_sec > 59)
            return ASNBadEncodingErr;
        hasSeconds = 2;
    }
    else
    {   time.tm_sec = 0;
        hasSeconds = 0;
    }
    
    zoneFlag = utc[10+hasSeconds];
    if (zoneFlag != 'Z' && zoneFlag != '+' && zoneFlag != '-')
        return ASNBadEncodingErr;
    if (zoneFlag == 'Z')
    {   if (data.length != 11 + hasSeconds)
            return ASNBadEncodingErr;
        zoneOffset = 0;
    }
    else
    {   if (data.length != 15+hasSeconds)
            return ASNBadEncodingErr;
        zoneOffset = DecodeTwoASCII(utc+11+hasSeconds);
        if (zoneOffset < 0 || zoneOffset > 23)
            return ASNBadEncodingErr;
        offsetMin = DecodeTwoASCII(utc+13+hasSeconds);
        if (offsetMin < 0 || offsetMin > 59)
            return ASNBadEncodingErr;
        zoneOffset = (zoneOffset * 60 + offsetMin) * 60;
        if (zoneFlag == '-')
            zoneOffset = -zoneOffset;
    }
    
    *timeResult = mktime(&time);
    *timeResult += zoneOffset;      /* GMT = time + zone */
    
    /* Convert to UNIX seconds */
    
    return SSLNoErr;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -