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