in xsec/enc/WinCAPI/WinCAPICryptoKeyDSA.cpp [291:418]
bool WinCAPICryptoKeyDSA::verifyBase64Signature(unsigned char * hashBuf,
unsigned int hashLen,
char * base64Signature,
unsigned int sigLen) const {
// Use the currently loaded key to validate the Base64 encoded signature
if (m_key == 0) {
// Try to import from the parameters
importKey();
if (m_key == 0) {
throw XSECCryptoException(XSECCryptoException::DSAError,
"WinCAPI:DSA - Attempt to validate signature with empty key");
}
}
// Decode the signature
unsigned char * rawSig;
DWORD rawSigLen;
XSECnew(rawSig, BYTE [sigLen]);
ArrayJanitor<BYTE> j_rawSig(rawSig);
// Decode the signature
XSCryptCryptoBase64 b64;
b64.decodeInit();
rawSigLen = b64.decode((unsigned char *) base64Signature, sigLen, rawSig, sigLen);
rawSigLen += b64.decodeFinish(&rawSig[rawSigLen], sigLen - rawSigLen);
// Reverse the sig - Windows stores integers as octet streams in little endian
// order. The I2OSP algorithm used by XMLDSig to store integers is big endian
BYTE rawSigFinal[40];
BYTE * j, *k, *l, *m;
unsigned char rb[20];
unsigned char sb[20];
if (rawSigLen == 40) {
j = rawSig;
k = rawSig + 20;
} else if (rawSigLen == 46 && ASN2DSASig(rawSig, rb, sb) == true) {
j = rb;
k = sb;
} else {
throw XSECCryptoException(XSECCryptoException::DSAError,
"WinCAPI:DSA::VerifyBase64Signature - Expect 40 bytes in a DSA signature");
}
l = rawSigFinal + 19;
m = rawSigFinal + 39;
while (l >= rawSigFinal) {
*l-- = *j++;
*m-- = *k++;
}
// Have to create a Windows hash object and feed in the hash
BOOL fResult;
HCRYPTHASH h;
fResult = CryptCreateHash(m_p,
CALG_SHA1,
0,
0,
&h);
if (!fResult) {
throw XSECCryptoException(XSECCryptoException::DSAError,
"WinCAPI:DSA - Error creating Windows Hash Object");
}
// Feed the hash value into the newly created hash object
fResult = CryptSetHashParam(
h,
HP_HASHVAL,
hashBuf,
0);
if (!fResult) {
if (h)
CryptDestroyHash(h);
throw XSECCryptoException(XSECCryptoException::DSAError,
"WinCAPI:DSA - Error Setting Hash Value in Windows Hash object");
}
// Now validate
fResult = CryptVerifySignature(
h,
rawSigFinal,
40,
m_key,
NULL,
0);
if (!fResult) {
DWORD error = GetLastError();
/* For some reason, the default Microsoft DSS provider generally returns
* NTE_FAIL (which denotes an internal failure in the provider) for a
* failed signature rather than NTE_BAD_SIGNATURE
*/
if (error != NTE_BAD_SIGNATURE && error != NTE_FAIL) {
if (h)
CryptDestroyHash(h);
throw XSECCryptoException(XSECCryptoException::DSAError,
"WinCAPI:DSA - Error occurred in DSA validation");
}
if (h)
CryptDestroyHash(h);
return false;
}
if (h)
CryptDestroyHash(h);
return true;
}