ultimatepp/uppsrc/plugin/wincert/util.cpp
rylek e5a6d9d07f +Draw/, Report/, PdfDraw/, DocTypes/: minimalistic PDF/A support
+plugin/wincert: basic Win32 certificate manipulation and PDF digital signing

git-svn-id: svn://ultimatepp.org/upp/trunk@3715 f0d560ea-af0d-0410-9eb7-867de7ffcac7
2011-07-27 09:23:37 +00:00

163 lines
5 KiB
C++

#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<byte> 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<char> 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<char> 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<byte> 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<char> 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<const BYTE *>& sections, Vector<DWORD>& 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<const BYTE *>& sections, Vector<DWORD>& 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<byte> 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<const BYTE *> sections;
Vector<DWORD> sizes;
sections.SetCount(1, (const BYTE *)message.Begin());
sizes.SetCount(1, message.GetLength());
return CertSign(context, sections, sizes);
}
Array<CertInfo> CertEnum(HCERTSTORE store)
{
Array<CertInfo> 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);
}