#include "vectorutils.h" #include "stringutils.h" #include "debug.h" #include "findcert.h" #include "asn1decode.h" #include #include #ifdef _WIN32 #include #else #include #endif #include #include #ifndef _NO_MMAP #include #include #endif #include "util/rw/MmapReader.h" #include typedef std::map Asn1Dict; struct signature_info { ByteVector issuerserial; ByteVector signerdigest; Asn1Dict issuername; Asn1Dict authattrs; }; typedef std::vector signature_list; struct certificate_info { ByteVector serial; ByteVector rsamod; ByteVector rsaexp; ByteVector signature; Asn1Dict issuer; Asn1Dict subject; }; typedef std::vector certificate_list; certificate_list certs; signature_list sigs; std::string dictstring(const Asn1Dict& dict) { std::string str; std::for_each(dict.begin(), dict.end(), [&str](const Asn1Dict::value_type& kv) { str += '/'; str += vhexdump(kv.first); str += '='; str += std::string((char*)&*kv.second.begin(), (char*)&*kv.second.end()); }); return str; } #define PATHPAIR(x) (x), ((x)+sizeof(x)/sizeof(*(x))) void processfile(const std::string& filename) { uint16_t version; uint16_t type; uint32_t offset; ByteVector sig; try { if (!GetFileSignature(filename, sig, version, type, offset)) return; } catch (const char*msg) { debug("ERROR: %s\n", msg); return ; } catch(...) { debug("ERROR\n"); return; } printf("@%08x %04x %04x %s\n", offset, type, version, filename.c_str()); //dumpasn1(sig.begin(), sig.end()); // .... old style asn1dump // SignedData ( see rfc2315 - section 9.1 ) // 0.1.0.0 - version // 0.1.0.1 - SET of digestAlgorithm // 0.1.0.2 - contentInfo // 0.1.0.3 - [0]certificates : ExtendedCertificatesAndCertificates // 0.1.0.? - [1]crls : CertificateRevocationLists // 0.1.0.4 - SET of SignerInfo ( see rfc2315 - section 9.2 ) // .0.0 - version // .0.1 - issuerAndSeralNumber // .0.2 - digestAlgorithm // .0.3 - [0]authenticatedAttributes // .0.4 - digestEncryptionAlgorithm // .0.5 - encryptedDigest // .0.? - [1]unauthenticatedAttributes // .... new style asn1dump // SignedData ( see rfc2315 - section 9.1 ) // 0=0.0.0 - version // 0=0.0.1 - SET of digestAlgorithm // 0=0.0.2 - contentInfo // -> .0=0.0.2=0.0.0.1=0=2=0 == to be signed hash of content // 0=0.0=0 - [0]certificates : ExtendedCertificatesAndCertificates // 0=0.0=1 - [1]crls : CertificateRevocationLists // 0=0.0.3 - SET of SignerInfo ( see rfc2315 - section 9.2 ) // .0.0 - version // .0.1 - issuerAndSerialNumber // -> dict: { key: 0.1.0.*.0.0 => val: 0.1.0.*.0.1 } // -> 0.1.1 == serial // .0.2 - digestAlgorithm // .0=0 - [0]authenticatedAttributes // -> dict: { key: 0=0.*.0 => val: 0=0.*.1.0 } // .0.3 - digestEncryptionAlgorithm // .0.4 - encryptedDigest // .0=? - [1]unauthenticatedAttributes const char certnode[]= { 0,-1,0,-1 }; ByteVector::iterator cert0, cert1; if (!decodeasn1(sig.begin(), sig.end(), (version==0x100?2:0)+PATHPAIR(certnode), cert0, cert1)) { debug("ERROR: no 0=0.0=0 in signature [ certs ]\n"); } // oldstyle certificate properties // 0.0.0 - version // 0.0.1 - certid // 0.0.2 - sha1withrsaencryption // 0.0.3 - issuer subject 0.0.3.*.0.0 = 0.0.3.*.0.1 // 0.0.4 - validity period // 0.0.5 - subject // 0.0.6 - rsaenc { modulus + exponent } // 0.0.7 // // newstyle certificate properties // 0.0=0 - version // 0.0.0 - serialNumber // 0.0.1 - signature algorithm // 0.0.2 - issuer // dict: {key: .0.0.2.*.0.0, val: .0.0.2.*.0.1 } // 0.0.3 - validity period // 0.0.4 - subject // dict: {key: .0.0.4.*.0.0, val: .0.0.4.*.0.1 } // 0.0.5 - rsaenc { modulus + exponent } // 0.0=3 extended attrs // 0.1 sha1withRSAEnc // 0.2 signature //printf("certs: %s\n", hexdump(&*cert0, cert1-cert0).c_str()); const char p_serialnumber[]= {0,0,0}; const char p_issuer[]= {0,0,2}; const char p_subject[]= {0,0,4}; const char p_rsamod[]= {0,0,5,1,0,0}; const char p_rsaexp[]= {0,0,5,1,0,1}; const char p_signature[]= {0,2}; const char p_ckey[]= {0,0}; const char p_cval[]= {0,1}; ByteVector::iterator hdr, body, end; int tag, cls; bool cons; ByteVector::iterator pcert= cert0; while (nextasn1(pcert, cert1, hdr, body, end, tag, cons, cls)) { certs.resize(certs.size()+1); certificate_info& cert= certs.back(); ByteVector::iterator s0, s1; if (decodeasn1(hdr, end, PATHPAIR(p_serialnumber), s0, s1)) { cert.serial.insert(cert.serial.end(), s0, s1); } if (decodeasn1(hdr, end, PATHPAIR(p_rsamod), s0, s1)) { cert.rsamod.insert(cert.rsamod.end(), s0, s1); } if (decodeasn1(hdr, end, PATHPAIR(p_rsaexp), s0, s1)) { cert.rsaexp.insert(cert.rsaexp.end(), s0, s1); } if (decodeasn1(hdr, end, PATHPAIR(p_signature), s0, s1)) { cert.signature.insert(cert.signature.end(), s0, s1); } if (decodeasn1(hdr, end, PATHPAIR(p_issuer), s0, s1)) { getasn1dict(s0, s1, PATHPAIR(p_ckey), PATHPAIR(p_cval), cert.issuer); } if (decodeasn1(hdr, end, PATHPAIR(p_subject), s0, s1)) { getasn1dict(s0, s1, PATHPAIR(p_ckey), PATHPAIR(p_cval), cert.subject); } pcert= end; } ByteVector::iterator signer0, signer1; const char signerinfo[]= { 0,-1,0,3 }; if (!decodeasn1(sig.begin(), sig.end(), (version==0x100?2:0)+PATHPAIR(signerinfo), signer0, signer1)) { debug("ERROR: no 0=0.0=3 in signature [ signerinfo ]\n"); } const char issuerserial[]= {0,1,1}; const char issuername[]= {0,1,0}; const char signerdigest[]= {0,4 }; ByteVector::iterator psigner= signer0; while (nextasn1(psigner, signer1, hdr, body, end, tag, cons, cls)) { sigs.resize(sigs.size()+1); signature_info& sig= sigs.back(); ByteVector::iterator s0, s1; if (decodeasn1(hdr, end, PATHPAIR(issuerserial), s0, s1)) { sig.issuerserial.insert(sig.issuerserial.end(), s0, s1); } if (decodeasn1(hdr, end, PATHPAIR(signerdigest), s0, s1)) { sig.signerdigest.insert(sig.signerdigest.end(), s0, s1); } if (decodeasn1(hdr, end, PATHPAIR(issuername), s0, s1)) { getasn1dict(s0, s1, PATHPAIR(p_ckey), PATHPAIR(p_cval), sig.issuername); } // todo: authattr psigner= end; } } template void processarg(const std::string& arg, ACTION act) { if (arg[0]=='@') { // if name starts with '@' -> read list from file MmapReader rl(arg.substr(1), MmapReader::readonly); rl.line_enumerator([act](const char *first, const char*last) { processarg(std::string(first, last-first), act); return true; }); } else switch (GetFileInfo(arg)) { case AT_ISDIRECTORY: // if is a directory -> add all files in that directory dir_iterator(arg, act, [](const std::string& dirname)->bool { printf("NOTE: not processing subdirectory %s\n", dirname.c_str()); return false; } ); break; case AT_ISFILE: try { act(arg); } catch(const char*msg) { printf("ERROR in %s : %s\n", arg.c_str(), msg); } catch(...) { printf("UNKOWNERROR in %s\n", arg.c_str()); } break; default: printf("WARNING: %s does not exist\n", arg.c_str()); } } int main(int argc, char **argv) { DebugStdOut(); StringList files; for (int i=1 ; i create map { hash(rsamod) => certinfo } // check for consistency // todo: check cert + sig dependency tree return 0; }