Back to index

lightning-sunbird  0.9+nobinonly
Functions
derdec.c File Reference
#include "secder.h"
#include "secerr.h"

Go to the source code of this file.

Functions

static uint32 der_indefinite_length (unsigned char *buf, unsigned char *end)
static SECStatus der_capture (unsigned char *buf, unsigned char *end, int *header_len_p, uint32 *contents_len_p)
SECStatus DER_Lengths (SECItem *item, int *header_len_p, uint32 *contents_len_p)

Function Documentation

static SECStatus der_capture ( unsigned char *  buf,
unsigned char *  end,
int header_len_p,
uint32 contents_len_p 
) [static]

Definition at line 107 of file derdec.c.

{
    unsigned char *bp;
    unsigned char whole_tag;
    uint32 contents_len;
    int tag_number;

    if ((buf + 2) > end) {
       *header_len_p = 0;
       *contents_len_p = 0;
       if (buf == end)
           return SECSuccess;
       return SECFailure;
    }

    bp = buf;

    /* Get tag and verify that it is ok. */
    whole_tag = *bp++;
    tag_number = whole_tag & DER_TAGNUM_MASK;

    /*
     * XXX This code does not (yet) handle the high-tag-number form!
     */
    if (tag_number == DER_HIGH_TAG_NUMBER) {
       PORT_SetError(SEC_ERROR_BAD_DER);
       return SECFailure;
    }

    if ((whole_tag & DER_CLASS_MASK) == DER_UNIVERSAL) {
       /* Check that the universal tag number is one we implement.  */
       switch (tag_number) {
         case DER_BOOLEAN:
         case DER_INTEGER:
         case DER_BIT_STRING:
         case DER_OCTET_STRING:
         case DER_NULL:
         case DER_OBJECT_ID:
         case DER_SEQUENCE:
         case DER_SET:
         case DER_PRINTABLE_STRING:
         case DER_T61_STRING:
         case DER_IA5_STRING:
         case DER_VISIBLE_STRING:
         case DER_UTC_TIME:
         case 0:                   /* end-of-contents tag */
           break;
         default:
           PORT_SetError(SEC_ERROR_BAD_DER);
           return SECFailure;
       }
    }

    /*
     * Get first byte of length code (might contain entire length, might not).
     */
    contents_len = *bp++;

    /*
     * If the high bit is set, then the length is in multibyte format,
     * or the thing has an indefinite-length.
     */
    if (contents_len & 0x80) {
       int bytes_of_encoded_len;

       bytes_of_encoded_len = contents_len & 0x7f;
       contents_len = 0;

       switch (bytes_of_encoded_len) {
         case 4:
           contents_len |= *bp++;
           contents_len <<= 8;
           /* fallthru */
         case 3:
           contents_len |= *bp++;
           contents_len <<= 8;
           /* fallthru */
         case 2:
           contents_len |= *bp++;
           contents_len <<= 8;
           /* fallthru */
         case 1:
           contents_len |= *bp++;
           break;

         case 0:
           contents_len = der_indefinite_length (bp, end);
           if (contents_len)
              break;
           /* fallthru */
         default:
           PORT_SetError(SEC_ERROR_BAD_DER);
           return SECFailure;
       }
    }

    if ((bp + contents_len) > end) {
       /* Ran past end of buffer */
       PORT_SetError(SEC_ERROR_BAD_DER);
       return SECFailure;
    }

    *header_len_p = bp - buf;
    *contents_len_p = contents_len;

    return SECSuccess;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static uint32 der_indefinite_length ( unsigned char *  buf,
unsigned char *  end 
) [static]

Definition at line 41 of file derdec.c.

{
    uint32 len, ret, dataLen;
    unsigned char tag, lenCode;
    int dataLenLen;

    len = 0;
    while ( 1 ) {
       if ((buf + 2) > end) {
           return(0);
       }
       
       tag = *buf++;
       lenCode = *buf++;
       len += 2;
       
       if ( ( tag == 0 ) && ( lenCode == 0 ) ) {
           return(len);
       }
       
       if ( lenCode == 0x80 ) {    /* indefinite length */
           ret = der_indefinite_length(buf, end); /* recurse to find length */
           if (ret == 0)
              return 0;
           len += ret;
           buf += ret;
       } else {                    /* definite length */
           if (lenCode & 0x80) {
              /* Length of data is in multibyte format */
              dataLenLen = lenCode & 0x7f;
              switch (dataLenLen) {
                case 1:
                  dataLen = buf[0];
                  break;
                case 2:
                  dataLen = (buf[0]<<8)|buf[1];
                  break;
                case 3:
                  dataLen = ((unsigned long)buf[0]<<16)|(buf[1]<<8)|buf[2];
                  break;
                case 4:
                  dataLen = ((unsigned long)buf[0]<<24)|
                     ((unsigned long)buf[1]<<16)|(buf[2]<<8)|buf[3];
                  break;
                default:
                  PORT_SetError(SEC_ERROR_BAD_DER);
                  return SECFailure;
              }
           } else {
              /* Length of data is in single byte */
              dataLen = lenCode;
              dataLenLen = 0;
           }

           /* skip this item */
           buf = buf + dataLenLen + dataLen;
           len = len + dataLenLen + dataLen;
       }
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

SECStatus DER_Lengths ( SECItem *  item,
int header_len_p,
uint32 contents_len_p 
)

Definition at line 217 of file derdec.c.

{
    return(der_capture(item->data, &item->data[item->len], header_len_p,
                     contents_len_p));
}

Here is the caller graph for this function: