X-Git-Url: https://git.saurik.com/apple/security.git/blobdiff_plain/80e2389990082500d76eb566d4946be3e786c3ef..d8f41ccd20de16f8ebe2ccc84d47bf1cb2b26bbb:/SecurityTests/clxutils/NISCC/TLS_SSL/certDecode/certDecode.cpp?ds=sidebyside diff --git a/SecurityTests/clxutils/NISCC/TLS_SSL/certDecode/certDecode.cpp b/SecurityTests/clxutils/NISCC/TLS_SSL/certDecode/certDecode.cpp new file mode 100644 index 00000000..22c80bfc --- /dev/null +++ b/SecurityTests/clxutils/NISCC/TLS_SSL/certDecode/certDecode.cpp @@ -0,0 +1,163 @@ +/* + * Attempt to decode either one file, or every file in cwd, + * as a cert. Used to study vulnerability to NISCC cert DOS attacks. + */ +#include +#include +#include +#include +#include +#include +#include +#include + +static void usage(char **argv) +{ + printf("usage: %s [-l(oop))] [certFile]\n", argv[0]); + exit(1); +} + +/* + * Known file names to NOT parse + */ +static const char *skipTheseFiles[] = +{ + /* standard entries */ + ".", + "..", + "CVS", + ".cvsignore", + /* the certs we know crash */ + #if 0 + "00000668", + "00000681", + "00001980", + "00002040", + "00002892", + "00007472", + "00008064", + "00008656", + "00009840", + "00010432", + "00011614", // trouble somewhere in this neighborhood + "00011615", + "00011616", + #endif + NULL +}; + +/* returns false if specified fileName is in skipTheseFiles[] */ +static bool shouldWeParse( + const char *fileName) // C string +{ + for(const char **stf=skipTheseFiles; *stf!=NULL; stf++) { + const char *tf = *stf; + if(!strcmp(fileName, *stf)) { + return false; + } + } + return true; +} + +/* + * Just try to decode - if SecAsn1Decode returns, good 'nuff. + * Returns true if it does (i.e. ignore decode error; we're trying + * to detect a crash when the decoder should return an error). + */ +bool decodeCert( + const void *certData, + size_t certDataLen) +{ + SecAsn1CoderRef coder = NULL; + NSS_Certificate nssCert; + NSS_SignedCertOrCRL certOrCrl; + + SecAsn1CoderCreate(&coder); + + /* first the full decode */ + memset(&nssCert, 0, sizeof(nssCert)); + SecAsn1Decode(coder, certData, certDataLen, kSecAsn1SignedCertTemplate, &nssCert); + + /* now the "just TBS and sig" decode - this is actually harder + * due to nested SEC_ASN1_SAVE ops */ + memset(&certOrCrl, 0, sizeof(NSS_SignedCertOrCRL)); + SecAsn1Decode(coder, certData, certDataLen, kSecAsn1SignedCertOrCRLTemplate, &certOrCrl); + + SecAsn1CoderRelease(coder); + return true; +} + +int main(int argc, char **argv) +{ + bool quiet = false; + unsigned char *certData; + unsigned certDataLen; + bool loop = false; + int filearg = 1; + + if(argc > 3 ) { + usage(argv); + } + if((argc > 1) && (argv[1][0] == '-')) { + switch(argv[1][1]) { + case 'l': + loop = true; + break; + default: + usage(argv); + } + filearg++; + argc--; + } + if(argc == 2) { + /* read & parse one file */ + char *oneFile = argv[filearg]; + if(readFile(oneFile, &certData, &certDataLen)) { + printf("\n***Error reading file %s. Aborting.\n", oneFile); + exit(1); + } + do { + if(!quiet) { + printf("...%s", oneFile); + fflush(stdout); + } + if(!decodeCert(certData, certDataLen)) { + printf("\n***GOT AN EXCEPTION ON %s\n", oneFile); + exit(1); + } + } while(loop); + free(certData); + exit(0); + } + DIR *dir = opendir("."); + if(dir == NULL) { + printf("Huh? Can't open . as a directory.\n"); + exit(1); + } + struct dirent *de = readdir(dir); + while(de != NULL) { + char filename[MAXNAMLEN + 1]; + memmove(filename, de->d_name, de->d_namlen); + filename[de->d_namlen] = '\0'; + if(shouldWeParse(filename)) { + if(!quiet) { + printf("...%s", filename); + fflush(stdout); + } + if(readFile(filename, &certData, &certDataLen)) { + printf("\n***Error reading file %s. Aborting.\n", filename); + exit(1); + } + if(!decodeCert(certData, certDataLen)) { + printf("\n***GOT AN EXCEPTION ON %s\n", filename); + exit(1); + } + free(certData); + } + de = readdir(dir); + } + closedir(dir); + printf("\ncertDecode did not crash.\n"); + return 0; +} +