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

📄 x509.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 4 页
字号:
	uchar* pold;	Elem	elem;	err = ASN_OK;	p = *pp;	ans = nil;	if(length >= 0 && !isconstr) {		ans = makebytes(p, length);		p += length;	}	else {		/* constructed, either definite or indefinite length */		pstart = p;		for(;;) {			if(length >= 0 && p >= pstart + length) {				if(p != pstart + length)					err = ASN_EVALLEN;				break;			}			pold = p;			err = ber_decode(&p, pend, &elem);			if(err != ASN_OK)				break;			switch(elem.val.tag) {			case VOctets:				newans = catbytes(ans, elem.val.u.octetsval);				freebytes(ans);				ans = newans;				break;			case VEOC:				if(length != -1) {					p = pold;					err = ASN_EINVAL;				}				goto cloop_done;			default:				p = pold;				err = ASN_EINVAL;				goto cloop_done;			}		}cloop_done:		;	}	*pp = p;	*pbytes = ans;	return err;}/* * Decode a sequence or set. * We've already checked that length==-1 implies isconstr==1, * and otherwise that specified length fits within (*p..pend) */static intseq_decode(uchar** pp, uchar* pend, int length, int isconstr, Elist** pelist){	int err;	uchar* p;	uchar* pstart;	uchar* pold;	Elist* ans;	Elem elem;	Elist* lve;	Elist* lveold;	err = ASN_OK;	ans = nil;	p = *pp;	if(!isconstr)		err = ASN_EPRIM;	else {		/* constructed, either definite or indefinite length */		lve = nil;		pstart = p;		for(;;) {			if(length >= 0 && p >= pstart + length) {				if(p != pstart + length)					err = ASN_EVALLEN;				break;			}			pold = p;			err = ber_decode(&p, pend, &elem);			if(err != ASN_OK)				break;			if(elem.val.tag == VEOC) {				if(length != -1) {					p = pold;					err = ASN_EINVAL;				}				break;			}			else				lve = mkel(elem, lve);		}		if(err == ASN_OK) {			/* reverse back to original order */			while(lve != nil) {				lveold = lve;				lve = lve->tl;				lveold->tl = ans;				ans = lveold;			}		}	}	*pp = p;	*pelist = ans;	setmalloctag(ans, getcallerpc(&pp));	return err;}/* * Encode e by BER rules, putting answer in *pbytes. * This is done by first calling enc with lenonly==1 * to get the length of the needed buffer, * then allocating the buffer and using enc again to fill it up. */static intencode(Elem e, Bytes** pbytes){	uchar* p;	Bytes* ans;	int err;	uchar uc;	p = &uc;	err = enc(&p, e, 1);	if(err == ASN_OK) {		ans = newbytes(p-&uc);		p = ans->data;		err = enc(&p, e, 0);		*pbytes = ans;	}	return err;}/* * The various enc functions take a pointer to a pointer * into a buffer, and encode their entity starting there, * updating the pointer afterwards. * If lenonly is 1, only the pointer update is done, * allowing enc to be called first to calculate the needed * buffer length. * If lenonly is 0, it is assumed that the answer will fit. */static intenc(uchar** pp, Elem e, int lenonly){	int err;	int vlen;	int constr;	Tag tag;	int v;	int ilen;	uchar* p;	uchar* psave;	p = *pp;	err = val_enc(&p, e, &constr, 1);	if(err != ASN_OK)		return err;	vlen = p - *pp;	p = *pp;	tag = e.tag;	v = tag.class|constr;	if(tag.num < 31) {		if(!lenonly)			*p = (v|tag.num);		p++;	}	else {		if(!lenonly)			*p = (v|31);		p++;		if(tag.num < 0)			return ASN_EINVAL;		uint7_enc(&p, tag.num, lenonly);	}	if(vlen < 0x80) {		if(!lenonly)			*p = vlen;		p++;	}	else {		psave = p;		int_enc(&p, vlen, 1, 1);		ilen = p-psave;		p = psave;		if(!lenonly) {			*p++ = (0x80 | ilen);			int_enc(&p, vlen, 1, 0);		}		else			p += 1 + ilen;	}	if(!lenonly)		val_enc(&p, e, &constr, 0);	else		p += vlen;	*pp = p;	return err;}static intval_enc(uchar** pp, Elem e, int *pconstr, int lenonly){	int err;	uchar* p;	int kind;	int cl;	int v;	Bytes* bb = nil;	Bits* bits;	Ints* oid;	int k;	Elist* el;	char* s;	p = *pp;	err = ASN_OK;	kind = e.tag.num;	cl = e.tag.class;	*pconstr = 0;	if(cl != Universal) {		switch(e.val.tag) {		case VBool:			kind = BOOLEAN;			break;		case VInt:			kind = INTEGER;			break;		case VBigInt:			kind = INTEGER;			break;		case VOctets:			kind = OCTET_STRING;			break;		case VReal:			kind = REAL;			break;		case VOther:			kind = OCTET_STRING;			break;		case VBitString:			kind = BIT_STRING;			break;		case VNull:			kind = NULLTAG;			break;		case VObjId:			kind = OBJECT_ID;			break;		case VString:			kind = UniversalString;			break;		case VSeq:			kind = SEQUENCE;			break;		case VSet:			kind = SETOF;			break;		}	}	switch(kind) {	case BOOLEAN:		if(is_int(&e, &v)) {			if(v != 0)				v = 255;			 int_enc(&p, v, 1, lenonly);		}		else			err = ASN_EINVAL;		break;	case INTEGER:	case ENUMERATED:		if(is_int(&e, &v))			int_enc(&p, v, 0, lenonly);		else {			if(is_bigint(&e, &bb)) {				if(!lenonly)					memmove(p, bb->data, bb->len);				p += bb->len;			}			else				err = ASN_EINVAL;		}		break;	case BIT_STRING:		if(is_bitstring(&e, &bits)) {			if(bits->len == 0) {				if(!lenonly)					*p = 0;				p++;			}			else {				v = bits->unusedbits;				if(v < 0 || v > 7)					err = ASN_EINVAL;				else {					if(!lenonly) {						*p = v;						memmove(p+1, bits->data, bits->len);					}					p += 1 + bits->len;				}			}		}		else			err = ASN_EINVAL;		break;	case OCTET_STRING:	case ObjectDescriptor:	case EXTERNAL:	case REAL:	case EMBEDDED_PDV:		bb = nil;		switch(e.val.tag) {		case VOctets:			bb = e.val.u.octetsval;			break;		case VReal:			bb = e.val.u.realval;			break;		case VOther:			bb = e.val.u.otherval;			break;		}		if(bb != nil) {			if(!lenonly)				memmove(p, bb->data, bb->len);			p += bb->len;		}			else				err = ASN_EINVAL;		break;	case NULLTAG:		break;	case OBJECT_ID:		if(is_oid(&e, &oid)) {			for(k = 0; k < oid->len; k++) {				v = oid->data[k];				if(k == 0) {					v *= 40;					if(oid->len > 1)						v += oid->data[++k];				}				uint7_enc(&p, v, lenonly);			}		}		else			err = ASN_EINVAL;		break;	case SEQUENCE:	case SETOF:		el = nil;		if(e.val.tag == VSeq)			el = e.val.u.seqval;		else if(e.val.tag == VSet)			el = e.val.u.setval;		else			err = ASN_EINVAL;		if(el != nil) {			*pconstr = CONSTR_MASK;			for(; el != nil; el = el->tl) {				err = enc(&p, el->hd, lenonly);				if(err != ASN_OK)					break;			}		}		break;	case UTF8String:	case NumericString:	case PrintableString:	case TeletexString:	case VideotexString:	case IA5String:	case UTCTime:	case GeneralizedTime:	case GraphicString:	case VisibleString:	case GeneralString:	case UniversalString:	case BMPString:		if(e.val.tag == VString) {			s = e.val.u.stringval;			if(s != nil) {				v = strlen(s);				if(!lenonly)					memmove(p, s, v);				p += v;			}		}		else			err = ASN_EINVAL;		break;	default:		err = ASN_EINVAL;	}	*pp = p;	return err;}/* * Encode num as unsigned 7 bit values with top bit 1 on all bytes * except last, only putting in bytes if !lenonly. */static voiduint7_enc(uchar** pp, int num, int lenonly){	int n;	int v;	int k;	uchar* p;	p = *pp;	n = 1;	v = num >> 7;	while(v > 0) {		v >>= 7;		n++;	}	if(lenonly)		p += n;	else {		for(k = (n - 1)*7; k > 0; k -= 7)			*p++= ((num >> k)|0x80);		*p++ = (num&0x7F);	}	*pp = p;}/* * Encode num as unsigned or signed integer, * only putting in bytes if !lenonly. * Encoding is length followed by bytes to concatenate. */static voidint_enc(uchar** pp, int num, int unsgned, int lenonly){	int v;	int n;	int prevv;	int k;	uchar* p;	p = *pp;	v = num;	if(v < 0)		v = -(v + 1);	n = 1;	prevv = v;	v >>= 8;	while(v > 0) {		prevv = v;		v >>= 8;		n++;	}	if(!unsgned && (prevv&0x80))		n++;	if(lenonly)		p += n;	else {		for(k = (n - 1)*8; k >= 0; k -= 8)			*p++ = (num >> k);	}	*pp = p;}static intints_eq(Ints* a, Ints* b){	int	alen;	int	i;	alen = a->len;	if(alen != b->len)		return 0;	for(i = 0; i < alen; i++)		if(a->data[i] != b->data[i])			return 0;	return 1;}/* * Look up o in tab (which must have nil entry to terminate). * Return index of matching entry, or -1 if none. */static intoid_lookup(Ints* o, Ints** tab){	int i;	for(i = 0; tab[i] != nil; i++)		if(ints_eq(o, tab[i]))			return  i;	return -1;}/* * Return true if *pe is a SEQUENCE, and set *pseq to * the value of the sequence if so. */static intis_seq(Elem* pe, Elist** pseq){	if(pe->tag.class == Universal && pe->tag.num == SEQUENCE && pe->val.tag == VSeq) {		*pseq = pe->val.u.seqval;		return 1;	}	return 0;}static intis_set(Elem* pe, Elist** pset){	if(pe->tag.class == Universal && pe->tag.num == SETOF && pe->val.tag == VSet) {		*pset = pe->val.u.setval;		return 1;	}	return 0;}static intis_int(Elem* pe, int* pint){	if(pe->tag.class == Universal) {		if(pe->tag.num == INTEGER && pe->val.tag == VInt) {			*pint = pe->val.u.intval;			return 1;		}		else if(pe->tag.num == BOOLEAN && pe->val.tag == VBool) {			*pint = pe->val.u.boolval;			return 1;		}	}	return 0;}/* * for convience, all VInt's are readable via this routine, * as well as all VBigInt's */static intis_bigint(Elem* pe, Bytes** pbigint){	int v, n, i;	if(pe->tag.class == Universal && pe->tag.num == INTEGER) {		if(pe->val.tag == VBigInt)			*pbigint = pe->val.u.bigintval;		else if(pe->val.tag == VInt){			v = pe->val.u.intval;			for(n = 1; n < 4; n++)				if((1 << (8 * n)) > v)					break;			*pbigint = newbytes(n);			for(i = 0; i < n; i++)				(*pbigint)->data[i] = (v >> ((n - 1 - i) * 8));		}else			return 0;		return 1;	}	return 0;}static intis_bitstring(Elem* pe, Bits** pbits){	if(pe->tag.class == Universal && pe->tag.num == BIT_STRING && pe->val.tag == VBitString) {		*pbits = pe->val.u.bitstringval;		return 1;	}	return 0;}static intis_octetstring(Elem* pe, Bytes** poctets){	if(pe->tag.class == Universal && pe->tag.num == OCTET_STRING && pe->val.tag == VOctets) {		*poctets = pe->val.u.octetsval;		return 1;	}	return 0;}static intis_oid(Elem* pe, Ints** poid){	if(pe->tag.class == Universal && pe->tag.num == OBJECT_ID && pe->val.tag == VObjId) {		*poid = pe->val.u.objidval;		return 1;	}	return 0;}static intis_string(Elem* pe, char** pstring){	if(pe->tag.class == Universal) {		switch(pe->tag.num) {		case UTF8String:		case NumericString:		case PrintableString:		case TeletexString:		case VideotexString:		case IA5String:		case GraphicString:		case VisibleString:		case GeneralString:		case UniversalString:		case BMPString:			if(pe->val.tag == VString) {				*pstring = pe->val.u.stringval;				return 1;			}		}	}	return 0;}static intis_time(Elem* pe, char** ptime){	if(pe->tag.class == Universal	   && (pe->tag.num == UTCTime || pe->tag.num == GeneralizedTime)	   && pe->val.tag == VString) {		*ptime = pe->val.u.stringval;		return 1;	}	return 0;

⌨️ 快捷键说明

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