mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-05-16 06:05:58 -06:00
+plugin/wincert: basic Win32 certificate manipulation and PDF digital signing git-svn-id: svn://ultimatepp.org/upp/trunk@3715 f0d560ea-af0d-0410-9eb7-867de7ffcac7
163 lines
5 KiB
C++
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);
|
|
}
|