diff --git a/fmt_asn1int.c b/fmt_asn1int.c index 5b3adda..5c7fd46 100644 --- a/fmt_asn1int.c +++ b/fmt_asn1int.c @@ -1,5 +1,8 @@ #include +/* Store integer l according to ASN.1 DER rules. + * Use fmt_asn1INTEGER for default presents for tag. + * Return number of bytes needed. Only write if DEST!=NULL */ size_t fmt_asn1int(char* dest,enum asn1_tagclass tc,enum asn1_tagtype tt,enum asn1_tag tag,unsigned long l) { size_t len,tmp; /* first the tag */ diff --git a/fmt_asn1tagint.c b/fmt_asn1tagint.c index 338d7bf..b8ac41d 100644 --- a/fmt_asn1tagint.c +++ b/fmt_asn1tagint.c @@ -1,5 +1,8 @@ #include "asn1.h" +/* Common integer storing method, used in tags >= 0x1f and OIDs */ +/* Store big endian, 7 bits at a time, set high bit in all but last byte */ +/* Return number of bytes needed. Only write if dest!=NULL */ size_t fmt_asn1tagint(char* dest,unsigned long l) { size_t needed=((sizeof l)*7)/8,i; for (i=1; i +#include + +int main() { + char buf[10]; + assert(fmt_asn1tagint(buf,1)==1 && !memcmp(buf,"\x01",1)); + assert(fmt_asn1tagint(buf,0x7f)==1 && !memcmp(buf,"\x7f",1)); + assert(fmt_asn1tagint(buf,0x80)==2 && !memcmp(buf,"\x81\x00",2)); +} +#endif diff --git a/scan_asn1tagint.c b/scan_asn1tagint.c index 3085da0..3dccf16 100644 --- a/scan_asn1tagint.c +++ b/scan_asn1tagint.c @@ -1,12 +1,13 @@ #include "asn1.h" -size_t scan_asn1tagint(const char* src,const char* max,unsigned long* val) { +size_t scan_asn1tagint(const char* src,const char* bounds,unsigned long* val) { const char* orig=src; unsigned long l=0; - if (src==max || (unsigned char)src[0]==0x80) return 0; /* catch non-minimal encoding */ + if (src>=bounds || /* empty input */ + (unsigned char)src[0]==0x80) return 0; /* catch non-minimal encoding */ for (;; ++src) { - if (src>=max) return 0; - if (l>>(sizeof(l)*8-7)) return 0; /* catch integer overflow */ + if (src>=bounds || /* incomplete input */ + l>>(sizeof(l)*8-7)) return 0; /* catch integer overflow */ l=l*128+(*src&0x7F); if (!(*src&0x80)) break; } @@ -16,7 +17,34 @@ size_t scan_asn1tagint(const char* src,const char* max,unsigned long* val) { #ifdef UNITTEST #include +#include + +#include int main() { + char buf[10]; + unsigned long l; + assert(scan_asn1tagint(buf,buf,&l)==0); // empty input + strcpy(buf,"\x80\x01"); + assert(scan_asn1tagint(buf,buf+2,&l)==0); // non-minimal encoding + strcpy(buf,"\x01"); + assert(scan_asn1tagint(buf,buf+1,&l)==1 && l==1); + strcpy(buf,"\x7f"); + assert(scan_asn1tagint(buf,buf+1,&l)==1 && l==0x7f); + strcpy(buf,"\x81\x00"); + assert(scan_asn1tagint(buf,buf+2,&l)==2 && l==0x80); + assert(scan_asn1tagint(buf,buf+1,&l)==0); // incomplete input + memcpy(buf,"\xff\xff\xff\xff\xff\xff\xff\xff\xff\x7f",10); + assert(scan_asn1tagint(buf,buf+10,&l)==0); // value not representable + memcpy(buf,"\x8f\xff\xff\xff\x7f",9); + assert(scan_asn1tagint(buf,buf+10,&l)==5 && l==0xffffffff); // largest 32-bit + memcpy(buf,"\xff\xff\xff\xff\xff\xff\xff\xff\x7f",9); + if (sizeof(l)==8) { + assert(scan_asn1tagint(buf,buf+10,&l)==9 && l==0x7fffffffffffffff); + } else if (sizeof(l)==4) { + assert(scan_asn1tagint(buf,buf+10,&l)==0); // too large + memcpy(buf,"\x90\x00\x00\x00\x00",9); + assert(scan_asn1tagint(buf,buf+10,&l)==0); // too large + } } #endif