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

📄 berparse.c

📁 支持SSL v2/v3, TLS, PKCS #5, PKCS #7, PKCS #11, PKCS #12, S/MIME, X.509v3证书等安全协议或标准的开发库编译用到NSPR
💻 C
字号:
/* * The contents of this file are subject to the Mozilla Public * License Version 1.1 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.mozilla.org/MPL/ *  * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. *  * The Original Code is the Netscape security libraries. *  * The Initial Developer of the Original Code is Netscape * Communications Corporation.  Portions created by Netscape are  * Copyright (C) 1994-2000 Netscape Communications Corporation.  All * Rights Reserved. *  * Contributor(s): *  * Alternatively, the contents of this file may be used under the * terms of the GNU General Public License Version 2 or later (the * "GPL"), in which case the provisions of the GPL are applicable  * instead of those above.  If you wish to allow use of your  * version of this file only under the terms of the GPL and not to * allow others to use your version of this file under the MPL, * indicate your decision by deleting the provisions above and * replace them with the notice and other provisions required by * the GPL.  If you do not delete the provisions above, a recipient * may use your version of this file under either the MPL or the * GPL. */#include "secutil.h"typedef enum {    tagDone, lengthDone, leafDone, compositeDone,    notDone,    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 */    SECArb *parent;} ParseStackElem;struct BERParseStr {    PRArenaPool *his;    PRArenaPool *mine;    ParseProc proc;    int stackDepth;    ParseStackElem *stackPtr;    ParseStackElem *stack;    int pending;		/* bytes remaining to complete this part */    int pos;			/* running length of consumed characters */    ParseState state;    PRBool keepLeaves;    PRBool derOnly;    BERFilterProc filter;    void *filterArg;    BERNotifyProc before;    void *beforeArg;    BERNotifyProc after;    void *afterArg;};#define UNKNOWN -1static 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);    return c;}static void ParseTag(BERParse *h, unsigned char **buf, int *len){    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;}static void ParseLength(BERParse *h, unsigned char **buf, int *len){    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;}static void ParseLeaf(BERParse *h, unsigned char **buf, int *len){    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;}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;    } 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);}SECStatus BER_ParseSome(BERParse *h, unsigned char *buf, int len){    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;}BERParse *BER_ParseInit(PRArenaPool *arena, PRBool derOnly){    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;}SECArb *BER_ParseFini(BERParse *h){    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;}void BER_SetFilter(BERParse *h, BERFilterProc proc, void *instance){    h->filter = proc;    h->filterArg = instance;}void BER_SetLeafStorage(BERParse *h, PRBool keep){    h->keepLeaves = keep;}void BER_SetNotifyProc(BERParse *h, BERNotifyProc proc, void *instance,			      PRBool beforeData){    if (beforeData) {	h->before = proc;	h->beforeArg = instance;    } else {	h->after = proc;	h->afterArg = instance;    }}

⌨️ 快捷键说明

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