#include "wincert.h" String CertGetProperty(PCCERT_CONTEXT cert_context, DWORD propertyID) { dword len = 0; if(!CertGetCertificateContextProperty(cert_context, propertyID, NULL, &len)) return String::GetVoid(); Buffer prop(len); if(!CertGetCertificateContextProperty(cert_context, propertyID, prop, &len)) return String::GetVoid(); return String(~prop, len); } String CertGetName(PCCERT_CONTEXT cert_context, DWORD dwType, DWORD flags) { dword len = CertGetNameString(cert_context, dwType, flags, NULL, NULL, NULL); if(!len) return String::GetVoid(); Buffer name(len); if(!(len = CertGetNameString(cert_context, dwType, flags, NULL, name, len))) return String::GetVoid(); return String(name, len - 1); } String CertGetNameAttr(PCCERT_CONTEXT cert_context, const char *attrOID) { dword len = CertGetNameString(cert_context, CERT_NAME_ATTR_TYPE, 0, (void *)attrOID, NULL, NULL); if(!len) return String::GetVoid(); Buffer name(len); if(!(len = CertGetNameString(cert_context, CERT_NAME_ATTR_TYPE, 0, (void *)attrOID, name, len))) return String::GetVoid(); return String(name, len - 1); } /* String CertGetHash(PCCERT_CONTEXT cert_context) { dword hash_len = 0; CertGetCertificateContextProperty(cert_context, CERT_HASH_PROP_ID, NULL, &hash_len); Buffer hash(hash_len); CertGetCertificateContextProperty(cert_context, CERT_HASH_PROP_ID, hash, &hash_len); String cert_hash(~hash, hash_len); return cert_hash; } */ /* String CertGetName(PCCERT_CONTEXT cert_context) { dword type; dword len = CertGetNameString(cert_context, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0, &type, NULL, NULL); Buffer name(len); CertGetNameString(cert_context, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0, &type, name, len); String cert_name(name, len ? len - 1 : 0); return cert_name; } */ CertInfo CertGetInfo(PCCERT_CONTEXT cert_context) { CertInfo out; out.hash = CertGetProperty(cert_context, CERT_HASH_PROP_ID); out.common_name = CertGetNameAttr(cert_context, szOID_COMMON_NAME); out.organization = CertGetNameAttr(cert_context, szOID_ORGANIZATION_NAME); out.organizational_unit = CertGetNameAttr(cert_context, szOID_ORGANIZATIONAL_UNIT_NAME); out.email = CertGetNameAttr(cert_context, szOID_RSA_emailAddr); out.issuer = CertGetName(cert_context, CERT_NAME_FRIENDLY_DISPLAY_TYPE, CERT_NAME_ISSUER_FLAG); out.valid_from = Time(cert_context->pCertInfo->NotBefore); out.valid_until = Time(cert_context->pCertInfo->NotAfter); // out.valid_until = Cert return out; } static void _sCertSignSet(PCCERT_CONTEXT cert_context, CRYPT_SIGN_MESSAGE_PARA& sign) { Zero(sign); sign.cbSize = sizeof(sign); sign.dwMsgEncodingType = X509_ASN_ENCODING | PKCS_7_ASN_ENCODING; sign.pSigningCert = cert_context; sign.HashAlgorithm.pszObjId = szOID_RSA_SHA1RSA; sign.HashAlgorithm.Parameters.cbData = NULL; sign.cMsgCert = 1; sign.rgpMsgCert = &sign.pSigningCert; sign.cAuthAttr = 0; sign.dwInnerContentType = 0; sign.cMsgCrl = 0; sign.cUnauthAttr = 0; sign.dwFlags = 0; sign.pvHashAuxInfo = NULL; sign.rgAuthAttr = NULL; } int CertSignLength(PCCERT_CONTEXT cert_context, Vector& sections, Vector& sizes) { ASSERT(sections.GetCount() == sizes.GetCount()); CRYPT_SIGN_MESSAGE_PARA sign; _sCertSignSet(cert_context, sign); const BYTE **psect = sections.Begin(); DWORD *psize = sizes.Begin(); DWORD out_size = 0; if(!CryptSignMessage(&sign, TRUE, sections.GetCount(), psect, psize, NULL, &out_size)) return 0; return out_size; } String CertSign(PCCERT_CONTEXT cert_context, Vector& sections, Vector& sizes) { ASSERT(sections.GetCount() == sizes.GetCount()); CRYPT_SIGN_MESSAGE_PARA sign; _sCertSignSet(cert_context, sign); const BYTE **psect = sections.Begin(); DWORD *psize = sizes.Begin(); DWORD out_size = 0; if(!CryptSignMessage(&sign, TRUE, sections.GetCount(), psect, psize, NULL, &out_size)) return String::GetVoid(); Buffer out_data(out_size); if(!CryptSignMessage(&sign, TRUE, sections.GetCount(), psect, psize, out_data, &out_size)) return String::GetVoid(); return String(~out_data, out_size); } String CertSign(PCCERT_CONTEXT context, const String& message) { Vector sections; Vector sizes; sections.SetCount(1, (const BYTE *)message.Begin()); sizes.SetCount(1, message.GetLength()); return CertSign(context, sections, sizes); } Array CertEnum(HCERTSTORE store) { Array out_list; RLOG("store = " << FormatIntHex(store)); PCCERT_CONTEXT cert_context = NULL; while(cert_context = CertEnumCertificatesInStore(store, cert_context)) { out_list.Add() = CertGetInfo(cert_context); } return out_list; } PCCERT_CONTEXT CertFind(HCERTSTORE store, const String& hash) { CRYPT_HASH_BLOB hash_blob; hash_blob.pbData = (BYTE *)hash.Begin(); hash_blob.cbData = hash.GetLength(); return CertFindCertificateInStore(store, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0, CERT_FIND_HASH, &hash_blob, NULL); }