Make X509Certificate_MSCryptImpl::getCertificateUsage() actually work

According to MSDN, calling CryptDecodeObject() with X509_KEY_USAGE
fills in a CRYPT_BIT_BLOB struct, not a CERT_KEY_USAGE_RESTRICTION_INFO
one.

Avoid potential complications of using CRYPT_DECODE_NOCOPY_FLAG.
Instead, just follow the normal pattern of first finding out the size
of buffer needed, allocate a such buffer, and then call the API again,
passing that buffer. When called without CRYPT_DECODE_NOCOPY_FLAG, at
least, it's what pbData points to that contains the usage bits, not
the pointer value itself.

Add SAL_WARNs for cleartext error messages in all error cases.

Change-Id: I9b9f7d08d6013753d127c723dedd959109a85c97
diff --git a/xmlsecurity/source/xmlsec/mscrypt/x509certificate_mscryptimpl.cxx b/xmlsecurity/source/xmlsec/mscrypt/x509certificate_mscryptimpl.cxx
index 797cf9a..4c975a2 100644
--- a/xmlsecurity/source/xmlsec/mscrypt/x509certificate_mscryptimpl.cxx
+++ b/xmlsecurity/source/xmlsec/mscrypt/x509certificate_mscryptimpl.cxx
@@ -21,6 +21,7 @@

#include <sal/config.h>
#include <comphelper/servicehelper.hxx>
#include <comphelper/windowserrorstring.hxx>
#include "x509certificate_mscryptimpl.hxx"
#include "certificateextension_xmlsecimpl.hxx"
#include "sanextension_mscryptimpl.hxx"
@@ -31,6 +32,7 @@
#include <osl/nlsupport.h>
#include <osl/process.h>
#include <utility>
#include <vector>
#include <tools/time.hxx>

// Needed only for Windows XP.
@@ -622,21 +624,38 @@ sal_Int32 SAL_CALL X509Certificate_MSCryptImpl::getCertificateUsage(  )

        if (pExtn != NULL)
        {
            CERT_KEY_USAGE_RESTRICTION_INFO keyUsage;
            DWORD length = sizeof(CERT_KEY_USAGE_RESTRICTION_INFO);

            DWORD length = 0;
            bool rc = CryptDecodeObject(
                X509_ASN_ENCODING,
                X509_KEY_USAGE,
                pExtn->Value.pbData,
                pExtn->Value.cbData,
                CRYPT_DECODE_NOCOPY_FLAG,
                (void *)&keyUsage,
                0,
                NULL,
                &length);

            if (rc && keyUsage.RestrictedKeyUsage.cbData!=0)
            if (!rc)
                SAL_WARN("xmlsecurity.xmlsec", "CryptDecodeObject failed: " << WindowsErrorString(GetLastError()));
            else
            {
                usage = (sal_Int32)keyUsage.RestrictedKeyUsage.pbData;
                std::vector<char>buffer(length);

                rc = CryptDecodeObject(
                    X509_ASN_ENCODING,
                    X509_KEY_USAGE,
                    pExtn->Value.pbData,
                    pExtn->Value.cbData,
                    0,
                    (void *)buffer.data(),
                    &length);

                CRYPT_BIT_BLOB *blob = (CRYPT_BIT_BLOB*)buffer.data();
                if (!rc)
                    SAL_WARN("xmlsecurity.xmlsec", "CryptDecodeObject failed: " << WindowsErrorString(GetLastError()));
                else if (blob->cbData == 1)
                    usage = blob->pbData[0];
                else
                    SAL_WARN("xmlsecurity.xmlsec", "CryptDecodeObject(X509_KEY_USAGE) returned unexpected amount of data: " << blob->cbData);
            }
        }
    }