📄 x509.c
字号:
}/* * 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 + -