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

📄 x509.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 4 页
字号:
}/* * malloc and return a new Bytes structure capable of * holding len bytes. (len >= 0) */static Bytes*newbytes(int len){	Bytes* ans;	ans = (Bytes*)emalloc(OFFSETOF(data[0], Bytes) + len);	ans->len = len;	return ans;}/* * newbytes(len), with data initialized from buf */static Bytes*makebytes(uchar* buf, int len){	Bytes* ans;	ans = newbytes(len);	memmove(ans->data, buf, len);	return ans;}static voidfreebytes(Bytes* b){	if(b != nil)		free(b);}/* * Make a new Bytes, containing bytes of b1 followed by those of b2. * Either b1 or b2 or both can be nil. */static Bytes*catbytes(Bytes* b1, Bytes* b2){	Bytes* ans;	int n;	if(b1 == nil) {		if(b2 == nil)			ans = newbytes(0);		else			ans = makebytes(b2->data, b2->len);	}	else if(b2 == nil) {		ans = makebytes(b1->data, b1->len);	}	else {		n = b1->len + b2->len;		ans = newbytes(n);		ans->len = n;		memmove(ans->data, b1->data, b1->len);		memmove(ans->data+b1->len, b2->data, b2->len);	}	return ans;}/* len is number of ints */static Ints*newints(int len){	Ints* ans;	ans = (Ints*)emalloc(OFFSETOF(data[0], Ints) + len*sizeof(int));	ans->len = len;	return ans;}static Ints*makeints(int* buf, int len){	Ints* ans;	ans = newints(len);	if(len > 0)		memmove(ans->data, buf, len*sizeof(int));	return ans;}static voidfreeints(Ints* b){	if(b != nil)		free(b);}/* len is number of bytes */static Bits*newbits(int len){	Bits* ans;	ans = (Bits*)emalloc(OFFSETOF(data[0], Bits) + len);	ans->len = len;	ans->unusedbits = 0;	return ans;}static Bits*makebits(uchar* buf, int len, int unusedbits){	Bits* ans;	ans = newbits(len);	memmove(ans->data, buf, len);	ans->unusedbits = unusedbits;	return ans;}static voidfreebits(Bits* b){	if(b != nil)		free(b);}static Elist*mkel(Elem e, Elist* tail){	Elist* el;	el = (Elist*)emalloc(sizeof(Elist));	setmalloctag(el, getcallerpc(&e));	el->hd = e;	el->tl = tail;	return el;}static intelistlen(Elist* el){	int ans = 0;	while(el != nil) {		ans++;		el = el->tl;	}	return ans;}/* Frees elist, but not fields inside values of constituent elems */static voidfreeelist(Elist* el){	Elist* next;	while(el != nil) {		next = el->tl;		free(el);		el = next;	}}/* free any allocated structures inside v (recursively freeing Elists) */static voidfreevalfields(Value* v){	Elist* el;	Elist* l;	if(v == nil)		return;	switch(v->tag) { 	case VOctets:		freebytes(v->u.octetsval);		break;	case VBigInt:		freebytes(v->u.bigintval);		break;	case VReal:		freebytes(v->u.realval);		break;	case VOther:		freebytes(v->u.otherval);		break;	case VBitString:		freebits(v->u.bitstringval);		break;	case VObjId:		freeints(v->u.objidval);		break;	case VString:		if(v->u.stringval)			free(v->u.stringval);		break;	case VSeq:		el = v->u.seqval;		for(l = el; l != nil; l = l->tl)			freevalfields(&l->hd.val);		if(el)			freeelist(el);		break;	case VSet:		el = v->u.setval;		for(l = el; l != nil; l = l->tl)			freevalfields(&l->hd.val);		if(el)			freeelist(el);		break;	}}/* end of general ASN1 functions *//*=============================================================*//* * Decode and parse an X.509 Certificate, defined by this ASN1: *	Certificate ::= SEQUENCE { *		certificateInfo CertificateInfo, *		signatureAlgorithm AlgorithmIdentifier, *		signature BIT STRING } * *	CertificateInfo ::= SEQUENCE { *		version [0] INTEGER DEFAULT v1 (0), *		serialNumber INTEGER, *		signature AlgorithmIdentifier, *		issuer Name, *		validity Validity, *		subject Name, *		subjectPublicKeyInfo SubjectPublicKeyInfo } *	(version v2 has two more fields, optional unique identifiers for *  issuer and subject; since we ignore these anyway, we won't parse them) * *	Validity ::= SEQUENCE { *		notBefore UTCTime, *		notAfter UTCTime } * *	SubjectPublicKeyInfo ::= SEQUENCE { *		algorithm AlgorithmIdentifier, *		subjectPublicKey BIT STRING } * *	AlgorithmIdentifier ::= SEQUENCE { *		algorithm OBJECT IDENTIFER, *		parameters ANY DEFINED BY ALGORITHM OPTIONAL } * *	Name ::= SEQUENCE OF RelativeDistinguishedName * *	RelativeDistinguishedName ::= SETOF SIZE(1..MAX) OF AttributeTypeAndValue * *	AttributeTypeAndValue ::= SEQUENCE { *		type OBJECT IDENTIFER, *		value DirectoryString } *	(selected attributes have these Object Ids: *		commonName {2 5 4 3} *		countryName {2 5 4 6} *		localityName {2 5 4 7} *		stateOrProvinceName {2 5 4 8} *		organizationName {2 5 4 10} *		organizationalUnitName {2 5 4 11} *	) * *	DirectoryString ::= CHOICE { *		teletexString TeletexString, *		printableString PrintableString, *		universalString UniversalString } * *  See rfc1423, rfc2437 for AlgorithmIdentifier, subjectPublicKeyInfo, signature. * *  Not yet implemented: *   CertificateRevocationList ::= SIGNED SEQUENCE{ *           signature       AlgorithmIdentifier, *           issuer          Name, *           lastUpdate      UTCTime, *           nextUpdate      UTCTime, *           revokedCertificates *                           SEQUENCE OF CRLEntry OPTIONAL} *   CRLEntry ::= SEQUENCE{ *           userCertificate SerialNumber, *           revocationDate UTCTime} */typedef struct CertX509 {	int	serial;	char*	issuer;	char*	validity_start;	char*	validity_end;	char*	subject;	int	publickey_alg;	Bytes*	publickey;	int	signature_alg;	Bytes*	signature;} CertX509;/* Algorithm object-ids */enum {	ALG_rsaEncryption,	ALG_md2WithRSAEncryption,	ALG_md4WithRSAEncryption,	ALG_md5WithRSAEncryption,	ALG_sha1WithRSAEncryption,	ALG_md5,	NUMALGS};typedef struct Ints7 {	int		len;	int		data[7];} Ints7;static Ints7 oid_rsaEncryption = {7, 1, 2, 840, 113549, 1, 1, 1 };static Ints7 oid_md2WithRSAEncryption = {7, 1, 2, 840, 113549, 1, 1, 2 };static Ints7 oid_md4WithRSAEncryption = {7, 1, 2, 840, 113549, 1, 1, 3 };static Ints7 oid_md5WithRSAEncryption = {7, 1, 2, 840, 113549, 1, 1, 4 };static Ints7 oid_sha1WithRSAEncryption ={7, 1, 2, 840, 113549, 1, 1, 5 };static Ints7 oid_md5 ={6, 1, 2, 840, 113549, 2, 5, 0 };static Ints *alg_oid_tab[NUMALGS+1] = {	(Ints*)&oid_rsaEncryption,	(Ints*)&oid_md2WithRSAEncryption,	(Ints*)&oid_md4WithRSAEncryption,	(Ints*)&oid_md5WithRSAEncryption,	(Ints*)&oid_sha1WithRSAEncryption,	(Ints*)&oid_md5,	nil};static DigestFun digestalg[NUMALGS+1] = { md5, md5, md5, md5, sha1, md5, nil };static voidfreecert(CertX509* c){	if(!c) return;	if(c->issuer != nil)		free(c->issuer);	if(c->validity_start != nil)		free(c->validity_start);	if(c->validity_end != nil)		free(c->validity_end);	if(c->subject != nil)		free(c->subject);	freebytes(c->publickey);	freebytes(c->signature);	free(c);}/* * Parse the Name ASN1 type. * The sequence of RelativeDistinguishedName's gives a sort of pathname, * from most general to most specific.  Each element of the path can be * one or more (but usually just one) attribute-value pair, such as * countryName="US". * We'll just form a "postal-style" address string by concatenating the elements * from most specific to least specific, separated by commas. * Return name-as-string (which must be freed by caller). */static char*parse_name(Elem* e){	Elist* el;	Elem* es;	Elist* esetl;	Elem* eat;	Elist* eatl;	char* s;	enum { MAXPARTS = 100 };	char* parts[MAXPARTS];	int i;	int plen;	char* ans = nil;	if(!is_seq(e, &el))		goto errret;	i = 0;	plen = 0;	while(el != nil) {		es = &el->hd;		if(!is_set(es, &esetl))			goto errret;		while(esetl != nil) {			eat = &esetl->hd;			if(!is_seq(eat, &eatl) || elistlen(eatl) != 2)				goto errret;			if(!is_string(&eatl->tl->hd, &s) || i>=MAXPARTS)				goto errret;			parts[i++] = s;			plen += strlen(s) + 2;		/* room for ", " after */			esetl = esetl->tl;		}		el = el->tl;	}	if(i > 0) {		ans = (char*)emalloc(plen);		*ans = '\0';		while(--i >= 0) {			s = parts[i];			strcat(ans, s);			if(i > 0)				strcat(ans, ", ");		}	}errret:	return ans;}/* * Parse an AlgorithmIdentifer ASN1 type. * Look up the oid in oid_tab and return one of OID_rsaEncryption, etc.., * or -1 if not found. * For now, ignore parameters, since none of our algorithms need them. */static intparse_alg(Elem* e){	Elist* el;	Ints* oid;	if(!is_seq(e, &el) || el == nil || !is_oid(&el->hd, &oid))		return -1;	return oid_lookup(oid, alg_oid_tab);}static CertX509*decode_cert(Bytes* a){	int ok = 0;	int n;	CertX509* c = nil;	Elem  ecert;	Elem* ecertinfo;	Elem* esigalg;	Elem* esig;	Elem* eserial;	Elem* eissuer;	Elem* evalidity;	Elem* esubj;	Elem* epubkey;	Elist* el;	Elist* elcert = nil;	Elist* elcertinfo = nil;	Elist* elvalidity = nil;	Elist* elpubkey = nil;	Bits* bits = nil;	Bytes* b;	Elem* e;	if(decode(a->data, a->len, &ecert) != ASN_OK)		goto errret;	c = (CertX509*)emalloc(sizeof(CertX509));	c->serial = -1;	c->issuer = nil;	c->validity_start = nil;	c->validity_end = nil;	c->subject = nil;	c->publickey_alg = -1;	c->publickey = nil;	c->signature_alg = -1;	c->signature = nil;	/* Certificate */ 	if(!is_seq(&ecert, &elcert) || elistlen(elcert) !=3)		goto errret; 	ecertinfo = &elcert->hd; 	el = elcert->tl; 	esigalg = &el->hd;	c->signature_alg = parse_alg(esigalg); 	el = el->tl; 	esig = &el->hd;	/* Certificate Info */	if(!is_seq(ecertinfo, &elcertinfo))		goto errret;	n = elistlen(elcertinfo);  	if(n < 6)		goto errret;	eserial =&elcertinfo->hd; 	el = elcertinfo->tl; 	/* check for optional version, marked by explicit context tag 0 */	if(eserial->tag.class == Context && eserial->tag.num == 0) { 		eserial = &el->hd; 		if(n < 7) 			goto errret; 		el = el->tl; 	}	if(parse_alg(&el->hd) != c->signature_alg)		goto errret; 	el = el->tl; 	eissuer = &el->hd; 	el = el->tl; 	evalidity = &el->hd; 	el = el->tl; 	esubj = &el->hd; 	el = el->tl; 	epubkey = &el->hd; 	if(!is_int(eserial, &c->serial)) {		if(!is_bigint(eserial, &b))			goto errret;		c->serial = -1;	/* else we have to change cert struct */  	}	c->issuer = parse_name(eissuer);	if(c->issuer == nil)		goto errret;	/* Validity */  	if(!is_seq(evalidity, &elvalidity))		goto errret;	if(elistlen(elvalidity) != 2)		goto errret;	e = &elvalidity->hd;	if(!is_time(e, &c->validity_start))		goto errret;	e->val.u.stringval = nil;	/* string ownership transfer */	e = &elvalidity->tl->hd; 	if(!is_time(e, &c->validity_end))		goto errret;	e->val.u.stringval = nil;	/* string ownership transfer */	/* resume CertificateInfo */ 	c->subject = parse_name(esubj);	if(c->subject == nil)		goto errret;	/* SubjectPublicKeyInfo */ 	if(!is_seq(epubkey, &elpubkey))		goto errret;	if(elistlen(elpubkey) != 2)		goto errret;	c->publickey_alg = parse_alg(&elpubkey->hd);	if(c->publickey_alg < 0)		goto errret;  	if(!is_bitstring(&elpubkey->tl->hd, &bits))		goto errret;	if(bits->unusedbits != 0)		goto errret; 	c->publickey = makebytes(bits->data, bits->len);	/*resume Certificate */	if(c->signature_alg < 0)		goto errret; 	if(!is_bitstring(esig, &bits))		goto errret; 	c->signature = makebytes(bits->data, bits->len);	ok = 1;errret:	freevalfields(&ecert.val);	/* recurses through lists, too */	if(!ok){		freecert(c);		c = nil;	}	return c;}/* *	RSAPublickKey :: SEQUENCE { *		modulus INTEGER, *		publicExponent INTEGER *	} */static RSApub*decode_rsapubkey(Bytes* a){	Elem e;	Elist *el, *l;	mpint *mp;	RSApub* key;	l = nil;	key = rsapuballoc();	if(decode(a->data, a->len, &e) != ASN_OK)		goto errret;	if(!is_seq(&e, &el) || elistlen(el) != 2)		goto errret;		l = el;	key->n = mp = asn1mpint(&el->hd);	if(mp == nil)		goto errret;	el = el->tl;	key->ek = mp = asn1mpint(&el->hd);	if(mp == nil)		goto errret;	if(l != nil)		freeelist(l);	return key;errret:	if(l != nil)		freeelist(l);	rsapubfree(key);	return nil;}/* *	RSAPrivateKey ::= SEQUENCE { *		version Version, *		modulus INTEGER, -- n *		publicExponent INTEGER, -- e *		privateExponent INTEGER, -- d *		prime1 INTEGER, -- p *		prime2 INTEGER, -- q *		exponent1 INTEGER, -- d mod (p-1) *		exponent2 INTEGER, -- d mod (q-1) *		coefficient INTEGER -- (inverse of q) mod p } */static RSApriv*decode_rsaprivkey(Bytes* a){	int version;	Elem e;	Elist *el;	mpint *mp;	RSApriv* key;	key = rsaprivalloc();	if(decode(a->data, a->len, &e) != ASN_OK)		goto errret;	if(!is_seq(&e, &el) || elistlen(el) != 9)		goto errret;	if(!is_int(&el->hd, &version) || version != 0)		goto errret;	el = el->tl;	key->pub.n = mp = asn1mpint(&el->hd);	if(mp == nil)		goto errret;	el = el->tl;	key->pub.ek = mp = asn1mpint(&el->hd);	if(mp == nil)		goto errret;	el = el->tl;	key->dk = mp = asn1mpint(&el->hd);	if(mp == nil)		goto errret;	el = el->tl;	key->q = mp = asn1mpint(&el->hd);	if(mp == nil)

⌨️ 快捷键说明

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