Back to index

lightning-sunbird  0.9+nobinonly
Classes | Defines | Typedefs | Enumerations | Functions
berparse.c File Reference
#include "secutil.h"

Go to the source code of this file.

Classes

struct  ParseStackElem
struct  BERParseStr

Defines

#define UNKNOWN   -1

Typedefs

typedef unsigned char Byte
typedef void(* ParseProc )(BERParse *h, unsigned char **buf, int *len)

Enumerations

enum  ParseState {
  tagDone, lengthDone, leafDone, compositeDone,
  notDone, parseError, parseComplete, tagDone,
  lengthDone, leafDone, compositeDone, notDone,
  parseError, parseComplete
}

Functions

static unsigned char NextChar (BERParse *h, unsigned char **buf, int *len)
static void ParseTag (BERParse *h, unsigned char **buf, int *len)
static void ParseLength (BERParse *h, unsigned char **buf, int *len)
static void ParseLeaf (BERParse *h, unsigned char **buf, int *len)
static void CreateArbNode (BERParse *h)
SECStatus BER_ParseSome (BERParse *h, unsigned char *buf, int len)
BERParse * BER_ParseInit (PRArenaPool *arena, PRBool derOnly)
SECArb * BER_ParseFini (BERParse *h)
void BER_SetFilter (BERParse *h, BERFilterProc proc, void *instance)
void BER_SetLeafStorage (BERParse *h, PRBool keep)
void BER_SetNotifyProc (BERParse *h, BERNotifyProc proc, void *instance, PRBool beforeData)

Class Documentation

struct ParseStackElem

Definition at line 46 of file berparse.c.

Collaboration diagram for ParseStackElem:
Class Members
SECArb arb
SECArb * parent
int pos
struct BERParseStr

Definition at line 52 of file berparse.c.

Collaboration diagram for BERParseStr:
Class Members
BERNotifyProc after
void * afterArg
BERNotifyProc before
void * beforeArg
PRBool derOnly
BERFilterProc filter
void * filterArg
PRArenaPool * his
PRBool keepLeaves
PRArenaPool * mine
int pending
int pos
ParseProc proc
ParseStackElem * stack
int stackDepth
ParseStackElem * stackPtr
ParseState state

Define Documentation

#define UNKNOWN   -1

Definition at line 72 of file berparse.c.


Typedef Documentation

typedef unsigned char Byte

Definition at line 44 of file berparse.c.

typedef void(* ParseProc)(BERParse *h, unsigned char **buf, int *len)

Definition at line 45 of file berparse.c.


Enumeration Type Documentation

enum ParseState
Enumerator:
tagDone 
lengthDone 
leafDone 
compositeDone 
notDone 
parseError 
parseComplete 
tagDone 
lengthDone 
leafDone 
compositeDone 
notDone 
parseError 
parseComplete 

Definition at line 38 of file berparse.c.


Function Documentation

SECArb* BER_ParseFini ( BERParse *  h)

Definition at line 365 of file berparse.c.

{
    PRArenaPool *myArena = h->mine;
    SECArb *arb;

    if (h->state != parseComplete) {
       arb = NULL;
    } else {
       arb = PORT_ArenaAlloc(h->his, sizeof(SECArb));
       *arb = h->stackPtr->arb;
    }

    PORT_FreeArena(myArena, PR_FALSE);

    return arb;
}

Here is the call graph for this function:

BERParse* BER_ParseInit ( PRArenaPool arena,
PRBool  derOnly 
)

Definition at line 334 of file berparse.c.

{
    BERParse *h;
    PRArenaPool *temp = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
    if (temp == NULL) {
       PORT_SetError(SEC_ERROR_NO_MEMORY);
       return NULL;
    }
    h = PORT_ArenaAlloc(temp, sizeof(BERParse));
    if (h == NULL) {
       PORT_FreeArena(temp, PR_FALSE);
       PORT_SetError(SEC_ERROR_NO_MEMORY);
       return NULL;
    }
    h->his = arena;
    h->mine = temp;
    h->proc = ParseTag;
    h->stackDepth = 20;
    h->stack = PORT_ArenaZAlloc(h->mine,
                           sizeof(ParseStackElem) * h->stackDepth);
    h->stackPtr = h->stack;
    h->state = notDone;
    h->pos = 0;
    h->keepLeaves = PR_TRUE;
    h->before = NULL;
    h->after = NULL;
    h->filter = NULL;
    h->derOnly = derOnly;
    return h;
}

Here is the call graph for this function:

SECStatus BER_ParseSome ( BERParse *  h,
unsigned char *  buf,
int  len 
)

Definition at line 216 of file berparse.c.

{
    if (h->state == parseError) return PR_TRUE;

    while (len) {
        (*h->proc)(h, &buf, &len);
       if (h->state == parseComplete) {
           PORT_SetError(SEC_ERROR_BAD_DER);
           h->state = parseError;
           return PR_TRUE;
       }
       if (h->state == parseError) return PR_TRUE;
       PORT_Assert(h->state != parseComplete);

        if (h->state <= compositeDone) {
           if (h->proc == ParseTag) {
              PORT_Assert(h->state == tagDone);
              h->proc = ParseLength;
              h->state = notDone;
           } else if (h->proc == ParseLength) {
              SECArb *arb = &(h->stackPtr->arb);
              PORT_Assert(h->state == lengthDone || h->state == compositeDone);

              if (h->before)
                  (*h->before)(h->beforeArg, arb,
                             h->stackPtr - h->stack, PR_TRUE);

              /*
               * Check to see if this is the end of an indefinite
               * length composite
               */
              if (h->state == compositeDone) {
                  SECArb *parent = h->stackPtr->parent;
                  PORT_Assert(parent);
                  PORT_Assert(parent->tag & DER_CONSTRUCTED);
                  if (parent->length != 0) {
                     PORT_SetError(SEC_ERROR_BAD_DER);
                     h->state = parseError;
                     return PR_TRUE;
                  }
                  /*
                   * NOTE: This does not check for an indefinite length
                   * composite being contained inside a definite length
                   * composite. It is not clear that is legal.
                   */
                  h->stackPtr--;
                  CreateArbNode(h);
              } else {
                  h->stackPtr->pos = h->pos;


                  if (arb->tag & DER_CONSTRUCTED) {
                     SECArb *parent;
                     /*
                      * Make sure there is room on the stack before we
                      * stick anything else there.
                      */
                     PORT_Assert(h->stackPtr - h->stack < h->stackDepth);
                     if (h->stackPtr - h->stack == h->stackDepth - 1) {
                         int newDepth = h->stackDepth * 2;
                         h->stack = DS_ArenaGrow(h->mine, h->stack,
                            sizeof(ParseStackElem) * h->stackDepth,
                            sizeof(ParseStackElem) * newDepth);
                         h->stackPtr = h->stack + h->stackDepth + 1;
                         h->stackDepth = newDepth;
                     }
                     parent = &(h->stackPtr->arb);
                     h->stackPtr++;
                     h->stackPtr->parent = parent;
                     h->proc = ParseTag;
                     h->state = notDone;
                     h->pending = UNKNOWN;
                  } else {
                     if (arb->length < 0) {
                         PORT_SetError(SEC_ERROR_BAD_DER);
                         h->state = parseError;
                         return PR_TRUE;
                     }
                     arb->body.item.len = 0;
                     if (arb->length > 0 && h->keepLeaves) {
                         arb->body.item.data =
                            PORT_ArenaAlloc(h->his, arb->length);
                     } else {
                         arb->body.item.data = NULL;
                     }
                     h->proc = ParseLeaf;
                     h->state = notDone;
                     h->pending = arb->length;
                  }
              }
           } else {
              ParseStackElem *parent;
              PORT_Assert(h->state = leafDone);
              PORT_Assert(h->proc == ParseLeaf);

              for (;;) {
                  CreateArbNode(h);
                  if (h->stackPtr == h->stack)
                     break;
                  parent = (h->stackPtr - 1);
                  PORT_Assert(parent->arb.tag & DER_CONSTRUCTED);
                  if (parent->arb.length == 0) /* need explicit end */
                     break;
                  if (parent->pos + parent->arb.length > h->pos)
                     break;
                  if (parent->pos + parent->arb.length < h->pos) {
                     PORT_SetError(SEC_ERROR_BAD_DER);
                     h->state = parseError;
                     return PR_TRUE;
                  }
                  h->stackPtr = parent;
              }
           }

       }
    }
    return PR_FALSE;
}

Here is the call graph for this function:

void BER_SetFilter ( BERParse *  h,
BERFilterProc  proc,
void instance 
)

Definition at line 383 of file berparse.c.

{
    h->filter = proc;
    h->filterArg = instance;
}
void BER_SetLeafStorage ( BERParse *  h,
PRBool  keep 
)

Definition at line 389 of file berparse.c.

{
    h->keepLeaves = keep;
}
void BER_SetNotifyProc ( BERParse *  h,
BERNotifyProc  proc,
void instance,
PRBool  beforeData 
)

Definition at line 394 of file berparse.c.

{
    if (beforeData) {
       h->before = proc;
       h->beforeArg = instance;
    } else {
       h->after = proc;
       h->afterArg = instance;
    }
}
static void CreateArbNode ( BERParse *  h) [static]

Definition at line 188 of file berparse.c.

{
    SECArb *arb = PORT_ArenaAlloc(h->his, sizeof(SECArb));

    *arb = h->stackPtr->arb;

    /* 
     * Special case closing the root
     */       
    if (h->stackPtr == h->stack) {
       PORT_Assert(arb->tag & DER_CONSTRUCTED);
       h->state = parseComplete;
    } else {
       SECArb *parent = h->stackPtr->parent;
       parent->body.cons.subs = DS_ArenaGrow(
           h->his, parent->body.cons.subs,
           (parent->body.cons.numSubs) * sizeof(SECArb*),
           (parent->body.cons.numSubs + 1) * sizeof(SECArb*));
       parent->body.cons.subs[parent->body.cons.numSubs] = arb;
       parent->body.cons.numSubs++;
       h->proc = ParseTag;
       h->state = notDone;
       h->pending = UNKNOWN;
    }
    if (h->after)
       (*h->after)(h->afterArg, arb, h->stackPtr - h->stack, PR_FALSE);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static unsigned char NextChar ( BERParse *  h,
unsigned char **  buf,
int len 
) [static]

Definition at line 74 of file berparse.c.

{
    unsigned char c = *(*buf)++;
    (*len)--;
    h->pos++;
    if (h->filter)
       (*h->filter)(h->filterArg, &c, 1);
    return c;
}

Here is the caller graph for this function:

static void ParseLeaf ( BERParse *  h,
unsigned char **  buf,
int len 
) [static]

Definition at line 160 of file berparse.c.

{
    int count;
    SECArb *arb = &(h->stackPtr->arb);

    PORT_Assert(h->state == notDone);
    PORT_Assert(h->pending >= 0);

    if (*len < h->pending)
       count = *len;
    else
       count = h->pending;

    if (h->keepLeaves)
       memcpy(arb->body.item.data + arb->body.item.len, *buf, count);
    if (h->filter)
       (*h->filter)(h->filterArg, *buf, count);
    *buf += count;
    *len -= count;
    arb->body.item.len += count;
    h->pending -= count;
    h->pos += count;
    if (h->pending == 0) {
       h->state = leafDone;
    }
    return;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void ParseLength ( BERParse *  h,
unsigned char **  buf,
int len 
) [static]

Definition at line 113 of file berparse.c.

{
    Byte b;
    SECArb *arb = &(h->stackPtr->arb);

    PORT_Assert(h->state == notDone);

    if (h->pending == UNKNOWN) {
       b = NextChar(h, buf, len);
       if ((b & 0x80) == 0) {      /* short form */
           arb->length = b;
           /*
            * if the tag and the length are both zero bytes, then this
            * should be the marker showing end of list for the
            * indefinite length composite
            */
           if (arb->length == 0 && arb->tag == 0)
              h->state = compositeDone;
           else
              h->state = lengthDone;
           return;
       }

       h->pending = b & 0x7f;
       /* 0 implies this is an indefinite length */
       if (h->pending > 4) {
           PORT_SetError(SEC_ERROR_BAD_DER);
           h->state = parseError;
           return;
       }
       arb->length = 0;
    }

    while ((*len > 0) && (h->pending > 0)) {
       b = NextChar(h, buf, len);
       arb->length = (arb->length << 8) + b;
       h->pending--;
    }
    if (h->pending == 0) {
       if (h->derOnly && (arb->length == 0))
           h->state = parseError;
       else
           h->state = lengthDone;
    }
    return;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void ParseTag ( BERParse *  h,
unsigned char **  buf,
int len 
) [static]

Definition at line 84 of file berparse.c.

{
    SECArb* arb = &(h->stackPtr->arb);
    arb->tag = NextChar(h, buf, len);

    PORT_Assert(h->state == notDone);

  /*
   * NOTE: This does not handle the high-tag-number form
   */
    if ((arb->tag & DER_HIGH_TAG_NUMBER) == DER_HIGH_TAG_NUMBER) {
        PORT_SetError(SEC_ERROR_BAD_DER);
       h->state = parseError;
       return;
    }

    h->pending = UNKNOWN;
    arb->length = UNKNOWN;
    if (arb->tag & DER_CONSTRUCTED) {
       arb->body.cons.numSubs = 0;
       arb->body.cons.subs = NULL;
    } else {
       arb->body.item.len = UNKNOWN;
       arb->body.item.data = NULL;
    }

    h->state = tagDone;
}

Here is the call graph for this function:

Here is the caller graph for this function: