diff --git a/scan_asn1BITSTRING.c b/scan_asn1BITSTRING.c index b42901a..14891b3 100644 --- a/scan_asn1BITSTRING.c +++ b/scan_asn1BITSTRING.c @@ -25,3 +25,36 @@ size_t scan_asn1BITSTRING(const char* src,const char* max,const char** s,size_t* } return 0; } + +#ifdef UNITTEST +#include +#include + +#undef UNITTEST +#include "scan_asn1tag.c" +#include "scan_asn1tagint.c" +#include "scan_asn1length.c" +#include "scan_asn1string.c" + +int main() { + char buf[100]; + const char* s; + size_t l; + strcpy(buf,"\x03\x02\x07\x01"); // 0x03 = UNIVERSAL PRIMITIVE BIT_STRING, 0x02 = length 5, 0x07 = unused bits in last octet, 0x01 = 1 + assert(scan_asn1BITSTRING(buf,buf+4,&s,&l)==4 && s==buf+2 && l==2); + assert(scan_asn1BITSTRING(buf,buf+3,&s,&l)==0); // short input, make scan_asn1string fail + buf[0]=0x13; // 0x13 = UNIVERSAL PRIMITIVE PrintableString + assert(scan_asn1BITSTRING(buf,buf+4,&s,&l)==0); // scan_asn1string succeeds but line 9 fails + buf[0]=0x03; buf[2]=8; + assert(scan_asn1BITSTRING(buf,buf+4,&s,&l)==0); // scan_asn1string succeeds but line 12 fails + buf[2]=7; buf[1]=0; + assert(scan_asn1BITSTRING(buf,buf+4,&s,&l)==0); // scan_asn1string succeeds but line 11 fails + strcpy(buf,"\x03\x01\x00"); // length 0 bit string + assert(scan_asn1BITSTRING(buf,buf+3,&s,&l)==3 && s==buf+2 && l==1); + buf[2]=1; + assert(scan_asn1BITSTRING(buf,buf+3,&s,&l)==0); // length 0 but says it has unused bits, return 0 in line 17 + strcpy(buf,"\x03\x02\x07\x81"); // 0x03 = UNIVERSAL PRIMITIVE BIT_STRING, 0x02 = length 5, 0x07 = unused bits in last octet, 0x01 = 1 + assert(scan_asn1BITSTRING(buf,buf+4,&s,&l)==0); // unused bits not 0, return 0 in line 21 + // we only care for 100% coverage of this file, the others have their own unit tests */ +} +#endif diff --git a/scan_asn1BOOLEAN.c b/scan_asn1BOOLEAN.c index 8a3958f..99bb7c1 100644 --- a/scan_asn1BOOLEAN.c +++ b/scan_asn1BOOLEAN.c @@ -14,3 +14,30 @@ size_t scan_asn1BOOLEAN(const char* src,const char* max,unsigned long* val) { } return 0; } + +#ifdef UNITTEST +#include +#include + +#undef UNITTEST +#include "scan_asn1tag.c" +#include "scan_asn1tagint.c" +#include "scan_asn1length.c" +#include "scan_asn1rawint.c" +#include "scan_asn1int.c" + +int main() { + char buf[100]; + unsigned long l; + strcpy(buf,"\x01\x01\x00"); // 0x01 = UNIVERSAL + CONSTRUCTED + BOOLEAN, 0x01 = length 1, 0x00 = false + assert(scan_asn1BOOLEAN(buf,buf+3,&l)==3 && l==0); + assert(scan_asn1BOOLEAN(buf,buf+2,&l)==0); // not enough input + buf[2]=1; + assert(scan_asn1BOOLEAN(buf,buf+3,&l)==3 && l==1); + buf[2]=2; + assert(scan_asn1BOOLEAN(buf,buf+3,&l)==0); // only 0 and 1 are valid values for BOOLEAN + buf[0]=0x30; buf[2]=1; + assert(scan_asn1BOOLEAN(buf,buf+3,&l)==0); // 0x30 = SEQUENCE_OF, fails line 10 + // we only care for 100% coverage of this file, the others have their own unit tests */ +} +#endif diff --git a/scan_asn1ENUMERATED.c b/scan_asn1ENUMERATED.c index 36347cc..de117a7 100644 --- a/scan_asn1ENUMERATED.c +++ b/scan_asn1ENUMERATED.c @@ -13,3 +13,26 @@ size_t scan_asn1ENUMERATED(const char* src,const char* max,unsigned long* val) { } return 0; } + +#ifdef UNITTEST +#include +#include + +#undef UNITTEST +#include "scan_asn1tag.c" +#include "scan_asn1tagint.c" +#include "scan_asn1length.c" +#include "scan_asn1rawint.c" +#include "scan_asn1int.c" + +int main() { + char buf[100]; + unsigned long l; + strcpy(buf,"\x0a\x01\x17"); // 0x0a = UNIVERSAL + CONSTRUCTED + ENUMERATED, 0x01 = length 1, 0x17 = value + assert(scan_asn1ENUMERATED(buf,buf+3,&l)==3 && l==23); + assert(scan_asn1ENUMERATED(buf,buf+2,&l)==0); // not enough input + buf[0]=0x30; + assert(scan_asn1ENUMERATED(buf,buf+3,&l)==0); // 0x30 = SEQUENCE_OF, fails line 10 + // we only care for 100% coverage of this file, the others have their own unit tests */ +} +#endif diff --git a/scan_asn1INTEGER.c b/scan_asn1INTEGER.c index 61d3ac5..7c8a708 100644 --- a/scan_asn1INTEGER.c +++ b/scan_asn1INTEGER.c @@ -10,3 +10,43 @@ size_t scan_asn1INTEGER(const char* src,const char* max,signed long* val) { return tmp; return 0; } + +#ifdef UNITTEST +#include +#include + +#undef UNITTEST +#include "scan_asn1tag.c" +#include "scan_asn1tagint.c" +#include "scan_asn1length.c" +#include "scan_asn1rawint.c" +#include "scan_asn1int.c" + +int main() { + char buf[100]; + unsigned long l; + strcpy(buf,"\x02\x01\x17"); // 0x02 = UNIVERSAL + CONSTRUCTED + INTEGER, 0x01 = length 1, 0x17 = value + assert(scan_asn1INTEGER(buf,buf+3,&l)==3 && l==23); + assert(scan_asn1INTEGER(buf,buf+2,&l)==0); // not enough input + buf[0]=0x01; + assert(scan_asn1INTEGER(buf,buf+3,&l)==0); // 0x01 = BOOLEAN, fails line 9 + // we only care for 100% coverage of this file, the others have their own unit tests */ + // let's do a few more to leave sample values here + strcpy(buf,"\x02\x01\xff"); // 0x02 = UNIVERSAL + CONSTRUCTED + INTEGER, 0x01 = length 1, 0xff = value (-1) + assert(scan_asn1INTEGER(buf,buf+3,&l)==3 && l==-1); + strcpy(buf,"\x02\x04\x12\x34\x56\x78"); // 0x02 = UNIVERSAL + CONSTRUCTED + INTEGER, 0x01 = length 4, 0x12345678 = value + assert(scan_asn1INTEGER(buf,buf+6,&l)==6 && l==0x12345678); + if (sizeof(l)==8) { + strcpy(buf,"\x02\x08\x11\x22\x33\x44\x55\x66\x77\x88"); + assert(scan_asn1INTEGER(buf,buf+10,&l)==10 && l==0x1122334455667788); + strcpy(buf,"\x02\x08\xee\xdd\xcc\xbb\xaa\x99\x88\x78"); + assert(scan_asn1INTEGER(buf,buf+10,&l)==10 && l==-0x1122334455667788); // two's complement + strcpy(buf,"\x02\x08\x7f\xff\xff\xff\xff\xff\xff\xff"); // LONG_MAX + assert(scan_asn1INTEGER(buf,buf+10,&l)==10 && l==0x7ffffffffffffffful); + memcpy(buf,"\x02\x08\x80\x00\x00\x00\x00\x00\x00\x00",10); // LONG_MIN + assert(scan_asn1INTEGER(buf,buf+10,&l)==10 && l==-0x8000000000000000ul); + strcpy(buf,"\x02\x08\xff\xff\xff\xff\xff\xff\xff\xff"); + assert(scan_asn1INTEGER(buf,buf+10,&l)==0); // non-minimal encoding of -1 + } +} +#endif diff --git a/scan_asn1SEQUENCE.c b/scan_asn1SEQUENCE.c index 41bdb4b..50c0a32 100644 --- a/scan_asn1SEQUENCE.c +++ b/scan_asn1SEQUENCE.c @@ -12,3 +12,28 @@ size_t scan_asn1SEQUENCE(const char* src,const char* max,size_t* len) { return res; return 0; } + +#ifdef UNITTEST +#include +#include + +#undef UNITTEST +#include "scan_asn1tag.c" +#include "scan_asn1tagint.c" +#include "scan_asn1length.c" + +int main() { + char buf[100]; + size_t l; + strcpy(buf,"\x30\x01\x01"); // 0x30 = UNIVERSAL + CONSTRUCTED + SEQUENCE_OF, 0x01 = length 1, 0x01 = dummy filler + // this function only parses the header so our test data doesn't need + // to have an actual sequence, only the header for one. \x01 is not a + // valid sequence. + assert(scan_asn1SEQUENCE(buf,buf+3,&l)==2 && l==1); + assert(scan_asn1SEQUENCE(buf,buf,&l)==0); // not enough input, first return 0 + assert(scan_asn1SEQUENCE(buf,buf+2,&l)==0); // not enough input, second return 0 + buf[0]=0x31; + assert(scan_asn1SEQUENCE(buf,buf+3,&l)==0); // 0x31 = SET_OF, third return 0 + // we only care for 100% coverage of this file, the others have their own unit tests */ +} +#endif diff --git a/scan_asn1SET.c b/scan_asn1SET.c index 7cced52..47ed3e8 100644 --- a/scan_asn1SET.c +++ b/scan_asn1SET.c @@ -5,10 +5,37 @@ size_t scan_asn1SET(const char* src,const char* max,size_t* len) { unsigned long tag; enum asn1_tagclass tc; enum asn1_tagtype tt; - if (!(res=scan_asn1tag(src,max,&tc,&tt,&tag))) return 0; - if (!(tmp=scan_asn1length(src+res,max,len))) return 0; + if (!(res=scan_asn1tag(src,max,&tc,&tt,&tag))) + return 0; + if (!(tmp=scan_asn1length(src+res,max,len))) + return 0; res+=tmp; if (tc==UNIVERSAL && tt==CONSTRUCTED && tag==SET_OF) return res; return 0; } + +#ifdef UNITTEST +#include +#include + +#undef UNITTEST +#include "scan_asn1tag.c" +#include "scan_asn1tagint.c" +#include "scan_asn1length.c" + +int main() { + char buf[100]; + size_t l; + strcpy(buf,"\x31\x01\x01"); // 0x31 = UNIVERSAL + CONSTRUCTED + SET_OF, 0x01 = length 1, 0x01 = dummy filler + // this function only parses the header so our test data doesn't need + // to have an actual set, only the header for one. \x01 is not a valid + // set. + assert(scan_asn1SET(buf,buf+3,&l)==2 && l==1); + assert(scan_asn1SET(buf,buf,&l)==0); // not enough input, first return 0 + assert(scan_asn1SET(buf,buf+2,&l)==0); // not enough input, second return 0 + buf[0]=0x30; + assert(scan_asn1SET(buf,buf+3,&l)==0); // 0x30 = SEQUENCE_OF, third return 0 + // we only care for 100% coverage of this file, the others have their own unit tests */ +} +#endif diff --git a/scan_asn1STRING.c b/scan_asn1STRING.c index a6edd14..540a02d 100644 --- a/scan_asn1STRING.c +++ b/scan_asn1STRING.c @@ -10,3 +10,26 @@ size_t scan_asn1STRING(const char* src,const char* max,const char** s,size_t* l) return tmp; return 0; } + +#ifdef UNITTEST +#include +#include + +#undef UNITTEST +#include "scan_asn1tag.c" +#include "scan_asn1tagint.c" +#include "scan_asn1length.c" +#include "scan_asn1string.c" + +int main() { + char buf[100]; + const char* s; + size_t l; + strcpy(buf,"\x04\x05""fnord"); // 0x04 = UNIVERSAL PRIMITIVE OCTET_STRING, 0x05 = length 5, "fnord" = the string + assert(scan_asn1STRING(buf,buf+7,&s,&l)==7 && s==buf+2 && l==5); + assert(scan_asn1STRING(buf,buf+6,&s,&l)==0); // short input, make scan_asn1string fail + buf[0]=0x13; // 0x13 = UNIVERSAL PRIMITIVE PrintableString + assert(scan_asn1STRING(buf,buf+7,&s,&l)==0); // scan_asn1string succeeds but line 9 fails + // we only care for 100% coverage of this file, the others have their own unit tests */ +} +#endif diff --git a/scan_asn1rawoid.c b/scan_asn1rawoid.c index d23e93a..c88dce1 100644 --- a/scan_asn1rawoid.c +++ b/scan_asn1rawoid.c @@ -3,9 +3,11 @@ size_t scan_asn1rawoid(const char* src,const char* max,size_t* array,size_t* arraylen) { const char* orig=src; size_t cur=0,al; - if (!arraylen) return 0; + if (!arraylen) + return 0; al=*arraylen; *arraylen=0; - if (max-src<1) return 0; /* there has to be at least one octet */ + if (max-src<1) + return 0; /* there has to be at least one octet */ { int a,b; @@ -39,3 +41,34 @@ size_t scan_asn1rawoid(const char* src,const char* max,size_t* array,size_t* arr return src-orig; } +#ifdef UNITTEST +#include +#include + +#undef UNITTEST +#include "scan_asn1tagint.c" + +int main() { + char buf[100]; + size_t retval[10]; + size_t retvals=10; + strcpy(buf,"\x55\x04\x03"); // 2.5.4.3 (commonName) + assert(scan_asn1rawoid(buf,buf+3,retval,&retvals)==3 && retvals==4 && retval[0]==2 && retval[1]==5 && retval[2]==4 && retval[3]==3); + retvals=3; + retval[3]=23; + assert(scan_asn1rawoid(buf,buf+3,retval,&retvals)==0); // oid too long for dest array, fail line 40 + assert(retval[3]==23); // make sure we didn't clobber sentinel + assert(retvals==4); // make sure it told us how many elements are needed + + assert(scan_asn1rawoid(buf,buf+3,retval,0)==0); // *retvals is NULL, fail line 7 + strcpy(buf,"\x55\x04\x03"); // 2.5.4.3 (commonName) + retvals=10; + assert(scan_asn1rawoid(buf,buf,retval,&retvals)==0); // src=max, fail line 10 + strcpy(buf,"\x55\x04\xff"); // 2.5.4.[invalid] + assert(scan_asn1rawoid(buf,buf+3,retval,&retvals)==0); // scan_asn1tagint fails, fail line 31 + strcpy(buf,"\xb4\x04\x03"); // 2.100.4.3 + retvals=10; + assert(scan_asn1rawoid(buf,buf+3,retval,&retvals)==3 && retvals==4 && retval[0]==2 && retval[1]==100 && retval[2]==4 && retval[3]==3); + // we only care for 100% coverage of this file, the others have their own unit tests */ +} +#endif