diff options
Diffstat (limited to 'nss/cmd/lib/berparse.c')
-rw-r--r-- | nss/cmd/lib/berparse.c | 419 |
1 files changed, 216 insertions, 203 deletions
diff --git a/nss/cmd/lib/berparse.c b/nss/cmd/lib/berparse.c index 9e65361..8cd1eba 100644 --- a/nss/cmd/lib/berparse.c +++ b/nss/cmd/lib/berparse.c @@ -4,16 +4,20 @@ #include "secutil.h" typedef enum { - tagDone, lengthDone, leafDone, compositeDone, + tagDone, + lengthDone, + leafDone, + compositeDone, notDone, - parseError, parseComplete + parseError, + parseComplete } ParseState; typedef unsigned char Byte; typedef void (*ParseProc)(BERParse *h, unsigned char **buf, int *len); typedef struct { SECArb arb; - int pos; /* length from global start to item start */ + int pos; /* length from global start to item start */ SECArb *parent; } ParseStackElem; @@ -24,8 +28,8 @@ struct BERParseStr { int stackDepth; ParseStackElem *stackPtr; ParseStackElem *stack; - int pending; /* bytes remaining to complete this part */ - int pos; /* running length of consumed characters */ + int pending; /* bytes remaining to complete this part */ + int pos; /* running length of consumed characters */ ParseState state; PRBool keepLeaves; PRBool derOnly; @@ -39,46 +43,49 @@ struct BERParseStr { #define UNKNOWN -1 -static unsigned char NextChar(BERParse *h, unsigned char **buf, int *len) +static unsigned char +NextChar(BERParse *h, unsigned char **buf, int *len) { unsigned char c = *(*buf)++; (*len)--; h->pos++; if (h->filter) - (*h->filter)(h->filterArg, &c, 1); + (*h->filter)(h->filterArg, &c, 1); return c; } -static void ParseTag(BERParse *h, unsigned char **buf, int *len) +static void +ParseTag(BERParse *h, unsigned char **buf, int *len) { - SECArb* arb = &(h->stackPtr->arb); + 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 - */ + /* + * 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->state = parseError; + return; } h->pending = UNKNOWN; arb->length = UNKNOWN; if (arb->tag & DER_CONSTRUCTED) { - arb->body.cons.numSubs = 0; - arb->body.cons.subs = NULL; + arb->body.cons.numSubs = 0; + arb->body.cons.subs = NULL; } else { - arb->body.item.len = UNKNOWN; - arb->body.item.data = NULL; + arb->body.item.len = UNKNOWN; + arb->body.item.data = NULL; } h->state = tagDone; } -static void ParseLength(BERParse *h, unsigned char **buf, int *len) +static void +ParseLength(BERParse *h, unsigned char **buf, int *len) { Byte b; SECArb *arb = &(h->stackPtr->arb); @@ -86,46 +93,47 @@ static void ParseLength(BERParse *h, unsigned char **buf, int *len) 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; + 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--; + 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; + if (h->derOnly && (arb->length == 0)) + h->state = parseError; + else + h->state = lengthDone; } return; } -static void ParseLeaf(BERParse *h, unsigned char **buf, int *len) +static void +ParseLeaf(BERParse *h, unsigned char **buf, int *len) { int count; SECArb *arb = &(h->stackPtr->arb); @@ -134,191 +142,196 @@ static void ParseLeaf(BERParse *h, unsigned char **buf, int *len) PORT_Assert(h->pending >= 0); if (*len < h->pending) - count = *len; + count = *len; else - count = h->pending; + count = h->pending; if (h->keepLeaves) - memcpy(arb->body.item.data + arb->body.item.len, *buf, count); + memcpy(arb->body.item.data + arb->body.item.len, *buf, count); if (h->filter) - (*h->filter)(h->filterArg, *buf, count); + (*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; + h->state = leafDone; } return; } -static void CreateArbNode(BERParse *h) +static void +CreateArbNode(BERParse *h) { 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; + 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; + 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); + (*h->after)(h->afterArg, arb, h->stackPtr - h->stack, PR_FALSE); } -SECStatus BER_ParseSome(BERParse *h, unsigned char *buf, int len) +SECStatus +BER_ParseSome(BERParse *h, unsigned char *buf, int len) { - if (h->state == parseError) return PR_TRUE; + 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 == 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; - } - } - - } + 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; } -BERParse *BER_ParseInit(PLArenaPool *arena, PRBool derOnly) +BERParse * +BER_ParseInit(PLArenaPool *arena, PRBool derOnly) { BERParse *h; PLArenaPool *temp = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); if (temp == NULL) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - return 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; + 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); + sizeof(ParseStackElem) * h->stackDepth); h->stackPtr = h->stack; h->state = notDone; h->pos = 0; @@ -330,16 +343,17 @@ BERParse *BER_ParseInit(PLArenaPool *arena, PRBool derOnly) return h; } -SECArb *BER_ParseFini(BERParse *h) +SECArb * +BER_ParseFini(BERParse *h) { PLArenaPool *myArena = h->mine; SECArb *arb; if (h->state != parseComplete) { - arb = NULL; + arb = NULL; } else { - arb = PORT_ArenaAlloc(h->his, sizeof(SECArb)); - *arb = h->stackPtr->arb; + arb = PORT_ArenaAlloc(h->his, sizeof(SECArb)); + *arb = h->stackPtr->arb; } PORT_FreeArena(myArena, PR_FALSE); @@ -347,29 +361,28 @@ SECArb *BER_ParseFini(BERParse *h) return arb; } - -void BER_SetFilter(BERParse *h, BERFilterProc proc, void *instance) +void +BER_SetFilter(BERParse *h, BERFilterProc proc, void *instance) { h->filter = proc; h->filterArg = instance; } -void BER_SetLeafStorage(BERParse *h, PRBool keep) +void +BER_SetLeafStorage(BERParse *h, PRBool keep) { h->keepLeaves = keep; } -void BER_SetNotifyProc(BERParse *h, BERNotifyProc proc, void *instance, - PRBool beforeData) +void +BER_SetNotifyProc(BERParse *h, BERNotifyProc proc, void *instance, + PRBool beforeData) { if (beforeData) { - h->before = proc; - h->beforeArg = instance; + h->before = proc; + h->beforeArg = instance; } else { - h->after = proc; - h->afterArg = instance; + h->after = proc; + h->afterArg = instance; } } - - - |