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

📄 x509.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 4 页
字号:
		goto errret;	el = el->tl;	key->p = mp = asn1mpint(&el->hd);	if(mp == nil)		goto errret;	el = el->tl;	key->kq = mp = asn1mpint(&el->hd);	if(mp == nil)		goto errret;	el = el->tl;	key->kp = mp = asn1mpint(&el->hd);	if(mp == nil)		goto errret;	el = el->tl;	key->c2 = mp = asn1mpint(&el->hd);	if(mp == nil)		goto errret;	return key;errret:	rsaprivfree(key);	return nil;}static mpint*asn1mpint(Elem *e){	Bytes *b;	mpint *mp;	int v;	if(is_int(e, &v))		return itomp(v, nil);	if(is_bigint(e, &b)) {		mp = betomp(b->data, b->len, nil);		freebytes(b);		return mp;	}	return nil;}static mpint*pkcs1pad(Bytes *b, mpint *modulus){	int n = (mpsignif(modulus)+7)/8;	int pm1, i;	uchar *p;	mpint *mp;	pm1 = n - 1 - b->len;	p = (uchar*)emalloc(n);	p[0] = 0;	p[1] = 1;	for(i = 2; i < pm1; i++)		p[i] = 0xFF;	p[pm1] = 0;	memcpy(&p[pm1+1], b->data, b->len);	mp = betomp(p, n, nil);	free(p);	return mp;}RSApriv*asn1toRSApriv(uchar *kd, int kn){	Bytes *b;	RSApriv *key;	b = makebytes(kd, kn);	key = decode_rsaprivkey(b);	freebytes(b);	return key;}/* * digest(CertificateInfo) * Our ASN.1 library doesn't return pointers into the original * data array, so we need to do a little hand decoding. */static voiddigest_certinfo(Bytes *cert, DigestFun digestfun, uchar *digest){	uchar *info, *p, *pend;	ulong infolen;	int isconstr, length;	Tag tag;	Elem elem;	p = cert->data;	pend = cert->data + cert->len;	if(tag_decode(&p, pend, &tag, &isconstr) != ASN_OK ||	   tag.class != Universal || tag.num != SEQUENCE ||	   length_decode(&p, pend, &length) != ASN_OK ||	   p+length > pend ||	   p+length < p)		return;	info = p;	if(ber_decode(&p, pend, &elem) != ASN_OK)		return;	freevalfields(&elem.val);	if(elem.tag.num != SEQUENCE)		return;	infolen = p - info;	(*digestfun)(info, infolen, digest, nil);}static char*verify_signature(Bytes* signature, RSApub *pk, uchar *edigest, Elem **psigalg){	Elem e;	Elist *el;	Bytes *digest;	uchar *pkcs1buf, *buf;	int buflen;	mpint *pkcs1;	int nlen;	char *err;	err = nil;	pkcs1buf = nil;	/* one less than the byte length of the modulus */	nlen = (mpsignif(pk->n)-1)/8;	/* see 9.2.1 of rfc2437 */	pkcs1 = betomp(signature->data, signature->len, nil);	mpexp(pkcs1, pk->ek, pk->n, pkcs1);	buflen = mptobe(pkcs1, nil, 0, &pkcs1buf);	buf = pkcs1buf;	if(buflen != nlen || buf[0] != 1) {		err = "expected 1";		goto end;	}	buf++;	while(buf[0] == 0xff)		buf++;	if(buf[0] != 0) {		err = "expected 0";		goto end;	}	buf++;	buflen -= buf-pkcs1buf;	if(decode(buf, buflen, &e) != ASN_OK || !is_seq(&e, &el) || elistlen(el) != 2 ||			!is_octetstring(&el->tl->hd, &digest)) {		err = "signature parse error";		goto end;	}	*psigalg = &el->hd;	if(memcmp(digest->data, edigest, digest->len) == 0)		goto end;	err = "digests did not match";end:	if(pkcs1 != nil)		mpfree(pkcs1);	if(pkcs1buf != nil)		free(pkcs1buf);	return err;}	RSApub*X509toRSApub(uchar *cert, int ncert, char *name, int nname){	char *e;	Bytes *b;	CertX509 *c;	RSApub *pk;	b = makebytes(cert, ncert);	c = decode_cert(b);	freebytes(b);	if(c == nil)		return nil;	if(name != nil && c->subject != nil){		e = strchr(c->subject, ',');		if(e != nil)			*e = 0;  // take just CN part of Distinguished Name		strncpy(name, c->subject, nname);	}	pk = decode_rsapubkey(c->publickey);	freecert(c);	return pk;}char*X509verify(uchar *cert, int ncert, RSApub *pk){	char *e;	Bytes *b;	CertX509 *c;	uchar digest[SHA1dlen];	Elem *sigalg;	b = makebytes(cert, ncert);	c = decode_cert(b);	if(c != nil)		digest_certinfo(b, digestalg[c->signature_alg], digest);	freebytes(b);	if(c == nil)		return "cannot decode cert";	e = verify_signature(c->signature, pk, digest, &sigalg);	freecert(c);	return e;}/* ------- Elem constructors ---------- */static ElemNull(void){	Elem e;	e.tag.class = Universal;	e.tag.num = NULLTAG;	e.val.tag = VNull;	return e;}static Elemmkint(int j){	Elem e;	e.tag.class = Universal;	e.tag.num = INTEGER;	e.val.tag = VInt;	e.val.u.intval = j;	return e;}static Elemmkbigint(mpint *p){	Elem e;	uchar *buf;	int buflen;	e.tag.class = Universal;	e.tag.num = INTEGER;	e.val.tag = VBigInt;	buflen = mptobe(p, nil, 0, &buf);	e.val.u.bigintval = makebytes(buf, buflen);	free(buf);	return e;}static Elemmkstring(char *s){	Elem e;	e.tag.class = Universal;	e.tag.num = IA5String;	e.val.tag = VString;	e.val.u.stringval = estrdup(s);	return e;}static Elemmkoctet(uchar *buf, int buflen){	Elem e;	e.tag.class = Universal;	e.tag.num = OCTET_STRING;	e.val.tag = VOctets;	e.val.u.octetsval = makebytes(buf, buflen);	return e;}static Elemmkbits(uchar *buf, int buflen){	Elem e;	e.tag.class = Universal;	e.tag.num = BIT_STRING;	e.val.tag = VBitString;	e.val.u.bitstringval = makebits(buf, buflen, 0);	return e;}static Elemmkutc(long t){	Elem e;	char utc[50];	Tm *tm = gmtime(t);	e.tag.class = Universal;	e.tag.num = UTCTime;	e.val.tag = VString;	snprint(utc, 50, "%.2d%.2d%.2d%.2d%.2d%.2dZ",		tm->year % 100, tm->mon+1, tm->mday, tm->hour, tm->min, tm->sec);	e.val.u.stringval = estrdup(utc);	return e;}static Elemmkoid(Ints *oid){	Elem e;	e.tag.class = Universal;	e.tag.num = OBJECT_ID;	e.val.tag = VObjId;	e.val.u.objidval = makeints(oid->data, oid->len);	return e;}static Elemmkseq(Elist *el){	Elem e;	e.tag.class = Universal;	e.tag.num = SEQUENCE;	e.val.tag = VSeq;	e.val.u.seqval = el;	return e;}static Elemmkset(Elist *el){	Elem e;	e.tag.class = Universal;	e.tag.num = SETOF;	e.val.tag = VSet;	e.val.u.setval = el;	return e;}static Elemmkalg(int alg){	return mkseq(mkel(mkoid(alg_oid_tab[alg]), mkel(Null(), nil)));}typedef struct Ints7pref {	int		len;	int		data[7];	char	prefix[4];} Ints7pref;Ints7pref DN_oid[] = {	{4, 2, 5, 4, 6, 0, 0, 0,  "C="},	{4, 2, 5, 4, 8, 0, 0, 0,  "ST="},	{4, 2, 5, 4, 7, 0, 0, 0,  "L="},	{4, 2, 5, 4, 10, 0, 0, 0, "O="},	{4, 2, 5, 4, 11, 0, 0, 0, "OU="},	{4, 2, 5, 4, 3, 0, 0, 0,  "CN="}, 	{7, 1,2,840,113549,1,9,1, "E="},};static Elemmkname(Ints7pref *oid, char *subj){	return mkset(mkel(mkseq(mkel(mkoid((Ints*)oid), mkel(mkstring(subj), nil))), nil));}static ElemmkDN(char *dn){	int i, j, nf;	char *f[20], *prefix, *d2 = estrdup(dn);	Elist* el = nil;	nf = tokenize(d2, f, nelem(f));	for(i=nf-1; i>=0; i--){		for(j=0; j<nelem(DN_oid); j++){			prefix = DN_oid[j].prefix;			if(strncmp(f[i],prefix,strlen(prefix))==0){				el = mkel(mkname(&DN_oid[j],f[i]+strlen(prefix)), el);				break;			}		}	}	free(d2);	return mkseq(el);}uchar*X509gen(RSApriv *priv, char *subj, ulong valid[2], int *certlen){	int serial = 0;	uchar *cert = nil;	RSApub *pk = rsaprivtopub(priv);	Bytes *certbytes, *pkbytes, *certinfobytes, *sigbytes;	Elem e, certinfo, issuer, subject, pubkey, validity, sig;	uchar digest[MD5dlen], *buf;	int buflen;	mpint *pkcs1;	e.val.tag = VInt;  /* so freevalfields at errret is no-op */	issuer = mkDN(subj);	subject = mkDN(subj);	pubkey = mkseq(mkel(mkbigint(pk->n),mkel(mkint(mptoi(pk->ek)),nil)));	if(encode(pubkey, &pkbytes) != ASN_OK)		goto errret;	freevalfields(&pubkey.val);	pubkey = mkseq(		mkel(mkalg(ALG_rsaEncryption),		mkel(mkbits(pkbytes->data, pkbytes->len),		nil)));	freebytes(pkbytes);	validity = mkseq(		mkel(mkutc(valid[0]),		mkel(mkutc(valid[1]),		nil)));	certinfo = mkseq(		mkel(mkint(serial),		mkel(mkalg(ALG_md5WithRSAEncryption),		mkel(issuer,		mkel(validity,		mkel(subject,		mkel(pubkey,		nil)))))));	if(encode(certinfo, &certinfobytes) != ASN_OK)		goto errret;	md5(certinfobytes->data, certinfobytes->len, digest, 0);	freebytes(certinfobytes);	sig = mkseq(		mkel(mkalg(ALG_md5),		mkel(mkoctet(digest, MD5dlen),		nil)));	if(encode(sig, &sigbytes) != ASN_OK)		goto errret;	pkcs1 = pkcs1pad(sigbytes, pk->n);	freebytes(sigbytes);	rsadecrypt(priv, pkcs1, pkcs1);	buflen = mptobe(pkcs1, nil, 0, &buf);	mpfree(pkcs1);	e = mkseq(		mkel(certinfo,		mkel(mkalg(ALG_md5WithRSAEncryption),		mkel(mkbits(buf, buflen),		nil))));	free(buf);	if(encode(e, &certbytes) != ASN_OK)		goto errret;	if(certlen)		*certlen = certbytes->len;	cert = certbytes->data;errret:	freevalfields(&e.val);	return cert;}uchar*X509req(RSApriv *priv, char *subj, int *certlen){	/* RFC 2314, PKCS #10 Certification Request Syntax */	int version = 0;	uchar *cert = nil;	RSApub *pk = rsaprivtopub(priv);	Bytes *certbytes, *pkbytes, *certinfobytes, *sigbytes;	Elem e, certinfo, subject, pubkey, sig;	uchar digest[MD5dlen], *buf;	int buflen;	mpint *pkcs1;	e.val.tag = VInt;  /* so freevalfields at errret is no-op */	subject = mkDN(subj);	pubkey = mkseq(mkel(mkbigint(pk->n),mkel(mkint(mptoi(pk->ek)),nil)));	if(encode(pubkey, &pkbytes) != ASN_OK)		goto errret;	freevalfields(&pubkey.val);	pubkey = mkseq(		mkel(mkalg(ALG_rsaEncryption),		mkel(mkbits(pkbytes->data, pkbytes->len),		nil)));	freebytes(pkbytes);	certinfo = mkseq(		mkel(mkint(version),		mkel(subject,		mkel(pubkey,		nil))));	if(encode(certinfo, &certinfobytes) != ASN_OK)		goto errret;	md5(certinfobytes->data, certinfobytes->len, digest, 0);	freebytes(certinfobytes);	sig = mkseq(		mkel(mkalg(ALG_md5),		mkel(mkoctet(digest, MD5dlen),		nil)));	if(encode(sig, &sigbytes) != ASN_OK)		goto errret;	pkcs1 = pkcs1pad(sigbytes, pk->n);	freebytes(sigbytes);	rsadecrypt(priv, pkcs1, pkcs1);	buflen = mptobe(pkcs1, nil, 0, &buf);	mpfree(pkcs1);	e = mkseq(		mkel(certinfo,		mkel(mkalg(ALG_md5),		mkel(mkbits(buf, buflen),		nil))));	free(buf);	if(encode(e, &certbytes) != ASN_OK)		goto errret;	if(certlen)		*certlen = certbytes->len;	cert = certbytes->data;errret:	freevalfields(&e.val);	return cert;}static char*tagdump(Tag tag){	if(tag.class != Universal)		return smprint("class%d,num%d", tag.class, tag.num);	switch(tag.num){	case BOOLEAN: return "BOOLEAN";	case INTEGER: return "INTEGER";	case BIT_STRING: return "BIT STRING";	case OCTET_STRING: return "OCTET STRING";	case NULLTAG: return "NULLTAG";	case OBJECT_ID: return "OID";	case ObjectDescriptor: return "OBJECT_DES";	case EXTERNAL: return "EXTERNAL";	case REAL: return "REAL";	case ENUMERATED: return "ENUMERATED";	case EMBEDDED_PDV: return "EMBEDDED PDV";	case SEQUENCE: return "SEQUENCE";	case SETOF: return "SETOF";	case UTF8String: return "UTF8String";	case NumericString: return "NumericString";	case PrintableString: return "PrintableString";	case TeletexString: return "TeletexString";	case VideotexString: return "VideotexString";	case IA5String: return "IA5String";	case UTCTime: return "UTCTime";	case GeneralizedTime: return "GeneralizedTime";	case GraphicString: return "GraphicString";	case VisibleString: return "VisibleString";	case GeneralString: return "GeneralString";	case UniversalString: return "UniversalString";	case BMPString: return "BMPString";	default:		return smprint("Universal,num%d", tag.num);	}}static voidedump(Elem e){	Value v;	Elist *el;	int i;	print("%s{", tagdump(e.tag));	v = e.val;	switch(v.tag){	case VBool: print("Bool %d",v.u.boolval); break;	case VInt: print("Int %d",v.u.intval); break;	case VOctets: print("Octets[%d] %.2x%.2x...",v.u.octetsval->len,v.u.octetsval->data[0],v.u.octetsval->data[1]); break;	case VBigInt: print("BigInt[%d] %.2x%.2x...",v.u.bigintval->len,v.u.bigintval->data[0],v.u.bigintval->data[1]); break;	case VReal: print("Real..."); break;	case VOther: print("Other..."); break;	case VBitString: print("BitString..."); break;	case VNull: print("Null"); break;	case VEOC: print("EOC..."); break;	case VObjId: print("ObjId");		for(i = 0; i<v.u.objidval->len; i++)			print(" %d", v.u.objidval->data[i]);		break;	case VString: print("String \"%s\"",v.u.stringval); break;	case VSeq: print("Seq\n");		for(el = v.u.seqval; el!=nil; el = el->tl)			edump(el->hd);		break;	case VSet: print("Set\n");		for(el = v.u.setval; el!=nil; el = el->tl)			edump(el->hd);		break;	}	print("}\n");}voidasn1dump(uchar *der, int len){	Elem e;	if(decode(der, len, &e) != ASN_OK){		print("didn't parse\n");		exits("didn't parse");	}	edump(e);}voidX509dump(uchar *cert, int ncert){	char *e;	Bytes *b;	CertX509 *c;	RSApub *pk;	uchar digest[SHA1dlen];	Elem *sigalg;	print("begin X509dump\n");	b = makebytes(cert, ncert);	c = decode_cert(b);	if(c != nil)		digest_certinfo(b, digestalg[c->signature_alg], digest);	freebytes(b);	if(c == nil){		print("cannot decode cert");		return;	}	print("serial %d\n", c->serial);	print("issuer %s\n", c->issuer);	print("validity %s %s\n", c->validity_start, c->validity_end);	print("subject %s\n", c->subject);	pk = decode_rsapubkey(c->publickey);	print("pubkey e=%B n(%d)=%B\n", pk->ek, mpsignif(pk->n), pk->n);	print("sigalg=%d digest=%.*H\n", c->signature_alg, MD5dlen, digest);	e = verify_signature(c->signature, pk, digest, &sigalg);	if(e==nil){		e = "nil (meaning ok)";		print("sigalg=\n");		if(sigalg)			edump(*sigalg);	}	print("self-signed verify_signature returns: %s\n", e);	rsapubfree(pk);	freecert(c);	print("end X509dump\n");}

⌨️ 快捷键说明

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