add missing check to length parser
add code to iterate through x509v3 extensions
This commit is contained in:
4
asn1.h
4
asn1.h
@@ -208,10 +208,12 @@ size_t lookupoid(const char* oid,size_t l);
|
||||
size_t scan_asn1generic(const char* src,const char* max,const char* fmt,...);
|
||||
size_t fmt_asn1generic(char* dest,const char* fmt,...);
|
||||
/* the format string works like this:
|
||||
* 'i' next argument is a long* (scan) or unsigned long (fmt)
|
||||
* 'i' parse INTEGER; next argument is a long* (scan) or unsigned long (fmt)
|
||||
* 'B' parse BOOLEAN; next argument is an int* (scan) or int (fmt)
|
||||
* '*' (fmt only) next argument is an unsigned long, tag type is set to APPLICATION and tag is set to that argument
|
||||
* '*' (scan only) next argument is an unsigned long*; for next tag, expect tag type to be APPLICATION and write tag to this unsigned long*
|
||||
* 'b' next argument is a struct string* but the length l in it is in bits, not bytes; if the length is not a multiple of 8, the unused bits are at the end of the last byte in the string
|
||||
* 'I' (fmt only) next argument is struct string *, send as BIT_STRING
|
||||
* 'S' (fmt only) next argument is struct string *, send as OCTET_STRING
|
||||
* 's' (fmt only) next argument is const char*, use strlen and send as OCTET_STRING
|
||||
* 's' (scan only) next argument is struct string*, parse OCTET_STRING into it
|
||||
|
||||
@@ -32,6 +32,17 @@ size_t fmt_asn1generic(char* dest,const char* fmt,...) {
|
||||
application=NULL;
|
||||
curlen+=fmt_asn1length(realdest?realdest+curlen:NULL,0);
|
||||
break;
|
||||
case 'B': // send boolean
|
||||
{
|
||||
int i=va_arg(args,int);
|
||||
if (i!=0 && i!=1) return 0;
|
||||
if (application)
|
||||
curlen=fmt_asn1int(realdest,APPLICATION,PRIMITIVE,*application,i);
|
||||
else
|
||||
curlen=fmt_asn1int(realdest,UNIVERSAL,PRIMITIVE,BOOLEAN,i);
|
||||
application=NULL;
|
||||
break;
|
||||
}
|
||||
case 'i': // send integer
|
||||
{
|
||||
unsigned long i=va_arg(args,unsigned long);
|
||||
@@ -50,7 +61,7 @@ size_t fmt_asn1generic(char* dest,const char* fmt,...) {
|
||||
curlen=fmt_asn1bitstring(realdest,UNIVERSAL,PRIMITIVE,BIT_STRING,s->s,s->l);
|
||||
application=NULL;
|
||||
break;
|
||||
case 'B':
|
||||
case 'I':
|
||||
stringtype=BIT_STRING;
|
||||
goto stringcopy;
|
||||
case 'A':
|
||||
|
||||
@@ -25,19 +25,26 @@ size_t scan_asn1generic(const char* src,const char* max,const char* fmt,...) {
|
||||
case '?': // ? = rest is optional (until end of sequence)
|
||||
optional=1;
|
||||
break;
|
||||
case 'B': // B = BOOLEAN
|
||||
case 'i': // i = INTEGER
|
||||
{
|
||||
long* dest=va_arg(args,long*);
|
||||
*dest=0;
|
||||
curlen=scan_asn1int(src,maxstack[curmax],&tc,&tt,&tag,dest);
|
||||
int* bdest=(int*)dest;
|
||||
long l;
|
||||
if (*fmt=='B') *bdest=0; else *dest=0;
|
||||
curlen=scan_asn1int(src,maxstack[curmax],&tc,&tt,&tag,&l);
|
||||
if (application) {
|
||||
if (tc!=APPLICATION) return 0;
|
||||
*application=tag;
|
||||
} else {
|
||||
if (tc!=UNIVERSAL || tt!=PRIMITIVE || tag!=INTEGER)
|
||||
if (tc!=UNIVERSAL || tt!=PRIMITIVE || tag!=(*fmt=='B'?BOOLEAN:INTEGER))
|
||||
return 0;
|
||||
}
|
||||
if (!curlen) { if (optional) break; else return 0; }
|
||||
if (*fmt=='B')
|
||||
*bdest=l;
|
||||
else
|
||||
*dest=l;
|
||||
src+=curlen;
|
||||
application=NULL;
|
||||
break;
|
||||
|
||||
@@ -16,6 +16,7 @@ size_t scan_asn1length(const char* src,const char* max,size_t* value) {
|
||||
l=(unsigned char)src[1];
|
||||
if (l==0) return 0; /* not minimally encoded: 0x81 0x00 instead of 0x00 */
|
||||
if (c>sizeof(l)) return 0; /* too many bytes, does not fit into target integer type */
|
||||
if (c+1>len) return 0; /* not enough data in input buffer */
|
||||
for (i=2; i<=c; ++i)
|
||||
l=l*256+(unsigned char)src[i];
|
||||
if (l<0x7f) return 0; /* not minimally encoded: 0x81 0x70 instead of 0x70 */
|
||||
|
||||
@@ -270,20 +270,22 @@ size_t scan_certificate(const char* cert, size_t l, struct x509cert* C, char** f
|
||||
printf("public exponent %lu\n",publicExponent[1]);
|
||||
else
|
||||
printf("public exponent is larger than a word?!\n");
|
||||
printf("modulus: ");
|
||||
printf("modulus:\n ");
|
||||
for (i=1; i<=modulus[0]; ++i) {
|
||||
size_t j,k;
|
||||
for (j=0, k=modulus[i]; j<sizeof(modulus[0]); ++j) {
|
||||
printf("%02lx:",(k>>((sizeof(modulus[0])*8)-(j+1)*8))&0xff);
|
||||
printf("%02lx%s",(k>>((sizeof(modulus[0])*8)-(j+1)*8))&0xff,i==modulus[0] && j==sizeof(modulus[0])-1?"":":");
|
||||
}
|
||||
if ((i-1)%4==3 || i==modulus[0]) printf("\n");
|
||||
if ((i-1)%4==3)
|
||||
if (i==modulus[0])
|
||||
printf("\n");
|
||||
else
|
||||
printf("\n ");
|
||||
}
|
||||
} else
|
||||
printf("bignum scanning failed!\n");
|
||||
}
|
||||
free(modulus); free(publicExponent);
|
||||
/* for RSA, bits is actually another sequence with two integers, modulus and publicExponent */
|
||||
printf("pubkeyparams len %lu, bits len %lu\n",pubkeyparams.l,bits.l);
|
||||
}
|
||||
} else {
|
||||
unsigned long temp[100];
|
||||
@@ -298,6 +300,53 @@ size_t scan_certificate(const char* cert, size_t l, struct x509cert* C, char** f
|
||||
|
||||
} else
|
||||
printf("could not parse public key part!\n");
|
||||
|
||||
// parse x.509v3 extensions
|
||||
if (version!=2 && extensions.l) {
|
||||
printf("Not X.509v3 but extensions present!?\n");
|
||||
} else if (extensions.l) {
|
||||
const char* c=extensions.s;
|
||||
const char* max=extensions.s+extensions.l;
|
||||
struct string extoid,extval;
|
||||
unsigned long noextensions;
|
||||
if (c!=max) {
|
||||
size_t n=scan_asn1generic(c,max,"c{!}}!",&noextensions,&extensions,&extval);
|
||||
if (n==0 || extval.l>0) {
|
||||
printf("failed to parse X.509v3 extensions!\n");
|
||||
c=max;
|
||||
} else {
|
||||
c=extensions.s;
|
||||
max=extensions.s+extensions.l;
|
||||
}
|
||||
}
|
||||
while (c<max) {
|
||||
size_t n=scan_asn1generic(c,max,"{os}",&extoid,&extval);
|
||||
if (n) {
|
||||
size_t i=lookupoid(extoid.s,extoid.l);
|
||||
if (i!=(size_t)-1) {
|
||||
printf("X.509 extension %s\n",oid2string[i].name);
|
||||
} else {
|
||||
unsigned long temp[100];
|
||||
size_t len=100;
|
||||
if (scan_asn1rawoid(extoid.s,extoid.s+extoid.l,temp,&len)) {
|
||||
printf("Unknown X.509v3 extension (oid ");
|
||||
for (i=0; i<len; ++i)
|
||||
printf("%lu%s",temp[i],i+1<len?".":")\n");
|
||||
} else
|
||||
printf("Failed to parse X.509v3 extension OID\n");
|
||||
}
|
||||
c+=n;
|
||||
} else {
|
||||
printf("X.509v3 extension parse error!\n");
|
||||
printasn1(c,max);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
&extensions,
|
||||
&oidsig, &sigrest, &sigdata))) {
|
||||
*/
|
||||
}
|
||||
|
||||
return n;
|
||||
|
||||
Reference in New Issue
Block a user