https://bugs.freedesktop.org/show_bug.cgi?id=87030

--- Comment #7 from Tor Lillqvist <t...@iki.fi> ---
For what it's worth, I distilled the code for signing down to a minimal
freestanding test program, and get the same error, "CryptSignHash failed:
Keyset does not exist". (Build with "cl -MD sign.c" in a "VS2013 x64 Native
Tools Command Prompt".)

#include <cassert>
#include <iostream>

#include <windows.h>
#include <wincrypt.h>

#define SAL_WARN(tag,stream) std::cerr << stream << std::endl
#define SAL_INFO(tag,stream) std::cerr << stream << std::endl

#define OUString(s) s

static char *WindowsError(DWORD nErrorCode)
{
    LPSTR pMsgBuf;

    if (FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM,
                       NULL,
                       nErrorCode,
                       MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
                       (LPSTR)&pMsgBuf,
                       0,
                       NULL) == 0)
      return "unknown";

    if (pMsgBuf[strlen(pMsgBuf)-1] == '\n')
        pMsgBuf[strlen(pMsgBuf)-1] = '\0';

    return pMsgBuf;
}

static bool
foo ()
{
    HCERTSTORE hCertStore = CertOpenSystemStore(NULL, "MY");
    if (!hCertStore)
    {
        SAL_WARN("vcl.pdfwriter", "CertOpenSystemStore failed: " <<
WindowsError(GetLastError()));
        return false;
    }

    PCCERT_CONTEXT pCertContext = CertFindCertificateInStore(hCertStore,
X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0, CERT_FIND_SUBJECT_STR, (const
void*) L"collabora-dev-softto...@wilhelmtux.ch" , NULL);
    if (pCertContext == NULL)
    {
        SAL_WARN("vcl.pdfwriter", "CertFindCertificateInStore failed: " <<
WindowsError(GetLastError()));
        return false;
    }

    DWORD nProperty(0);
    bool first(true);
    while ((nProperty = CertEnumCertificateContextProperties(pCertContext,
nProperty)) != 0)
    {
        if (first)
            SAL_INFO("vcl.pdfwriter", "Certificate context properties:");
        first = false;
#if 0
        DWORD nSize(0);
        if (!CertGetCertificateContextProperty(pCertContext, nProperty, NULL,
&nSize))
            SAL_INFO("vcl.pdfwriter", "  " << "(missing?) " << std::hex <<
nProperty);
        else
        {
            boost::scoped_array<char> aData(new char[nSize]);
            if (!CertGetCertificateContextProperty(pCertContext, nProperty,
aData.get(), &nSize))
                SAL_INFO("vcl.pdfwriter", "  " << "(missing?) " << std::hex::
<< nProperty);
            else
                SAL_INFO("vcl.pdfwriter", "  " <<
CertificatePropertyNameAndData(nProperty, aData, nSize));
        }
#else
        SAL_INFO("vcl.pdfwriter", "  " << nProperty);
#endif
    }

    HCRYPTPROV hCryptProvider;
    if (!CryptAcquireContext(&hCryptProvider, NULL, MS_ENH_RSA_AES_PROV,
PROV_RSA_AES, CRYPT_VERIFYCONTEXT))
    {
        SAL_WARN("vcl.pdfwriter", "CryptAcquireContext failed: " <<
WindowsError(GetLastError()));
        CertFreeCertificateContext(pCertContext);
        return false;
    }

    HCRYPTHASH hHash;
    if (!CryptCreateHash(hCryptProvider, CALG_SHA1, 0, 0, &hHash))
    {
        SAL_WARN("vcl.pdfwriter", "CryptCreateHash failed: " <<
WindowsError(GetLastError()));
        CryptReleaseContext(hCryptProvider, 0);
        CertFreeCertificateContext(pCertContext);
        return false;
    }

    DWORD nHashSize;
    DWORD nHashSizeLen(sizeof(DWORD));
    if (!CryptGetHashParam(hHash, HP_HASHSIZE, reinterpret_cast<BYTE
*>(&nHashSize), &nHashSizeLen, 0))
    {
        SAL_WARN("vcl.pdfwriter", "CryptGetHashParam failed: " <<
WindowsError(GetLastError()));
        CryptDestroyHash(hHash);
        CryptReleaseContext(hCryptProvider, 0);
        CertFreeCertificateContext(pCertContext);
        return false;
    }

    assert(nHashSizeLen == sizeof(DWORD));
    assert(nHashSize == 20);

    //FIXME: Check if SHA1 is calculated from the correct byterange
    if (!CryptHashData(hHash, reinterpret_cast<const BYTE *>(foo), 2000, 0))
    {
        SAL_WARN("vcl.pdfwriter", "CryptHashData failed: " <<
WindowsError(GetLastError()));
        CryptDestroyHash(hHash);
        CryptReleaseContext(hCryptProvider, 0);
        CertFreeCertificateContext(pCertContext);
        return false;
    }

#if 0 // We don't actualy need the hash bytes
    unsigned char aHash[20];
    if (!CryptGetHashParam(hHash, HP_HASHVAL, aHash, &nHashSize, 0))
    {
        SAL_WARN("vcl.pdfwriter", "CryptGetHashParam failed: " <<
WindowsError(GetLastError()));
        CryptDestroyHash(hHash);
        CryptReleaseContext(hCryptProvider, 0);
        CertFreeCertificateContext(pCertContext);
        return false;
    }

    if (nHashSize != 20)
    {
        SAL_WARN("vcl.pdfwriter", "CryptGetHashParam returned unexpected size
hash value: " << nHashSize);
        CryptDestroyHash(hHash);
        CryptReleaseContext(hCryptProvider, 0);
        CertFreeCertificateContext(pCertContext);
        return false;
    }
#endif

    HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProvOrNCryptKey;
    DWORD nKeySpecType;
    BOOL bMustFree;
    if (!CryptAcquireCertificatePrivateKey(pCertContext, 0, NULL,
&hCryptProvOrNCryptKey, &nKeySpecType, &bMustFree))
    {
        SAL_WARN("vcl.pdfwriter", "CryptAcquireCertificatePrivateKey failed: "
<< WindowsError(GetLastError()));
        CryptDestroyHash(hHash);
        CryptReleaseContext(hCryptProvider, 0);
        CertFreeCertificateContext(pCertContext);
        return false;
    }

    SAL_INFO("vcl.pdfwriter", "Certificate has private key that is " <<
             (nKeySpecType == AT_KEYEXCHANGE ? OUString("for key exchange") :
              (nKeySpecType == AT_SIGNATURE ? OUString("for signatures") :
               (nKeySpecType == CERT_NCRYPT_KEY_SPEC ? OUString("a CNG key,
whatever that is") :
                OUString("unknown type")))));

    DWORD nSigLen(0);
    if (!CryptSignHash(hHash, nKeySpecType, NULL, CRYPT_NOHASHOID, NULL,
&nSigLen))
    {
        SAL_WARN("vcl.pdfwriter", "CryptSignHash failed: " <<
WindowsError(GetLastError()));
        CryptDestroyHash(hHash);
        CryptReleaseContext(hCryptProvider, 0);
        CertFreeCertificateContext(pCertContext);
        return false;
    }

    auto pSig(new BYTE[nSigLen]);
    if (!CryptSignHash(hHash, nKeySpecType, NULL, CRYPT_NOHASHOID, pSig,
&nSigLen))
    {
        SAL_WARN("vcl.pdfwriter", "CryptSignHash failed: " <<
WindowsError(GetLastError()));
        CryptDestroyHash(hHash);
        CryptReleaseContext(hCryptProvider, 0);
        CertFreeCertificateContext(pCertContext);
        return false;
    }

    // Release resources
    CryptDestroyHash(hHash);
    CryptReleaseContext(hCryptProvider, 0);
    CertFreeCertificateContext(pCertContext);

  return true;
}

int
main (int argc, char **argv)
{
  return foo() ? 0 : 1;
}

-- 
You are receiving this mail because:
You are the assignee for the bug.
_______________________________________________
Libreoffice-bugs mailing list
Libreoffice-bugs@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/libreoffice-bugs

Reply via email to