in xsec/enc/OpenSSL/OpenSSLCryptoKeyRSA.cpp [438:556]
bool OpenSSLCryptoKeyRSA::verifySHA1PKCS1Base64Signature(
const unsigned char* hashBuf,
unsigned int hashLen,
const char * base64Signature,
unsigned int sigLen,
XSECCryptoHash::HashType type) const {
// Use the currently loaded key to validate the Base64 encoded signature
if (mp_rsaKey == NULL) {
throw XSECCryptoException(XSECCryptoException::RSAError,
"OpenSSL:RSA - Attempt to validate signature with empty key");
}
XSECCryptoKey::KeyType keyType = getKeyType();
if (keyType != KEY_RSA_PAIR && keyType != KEY_RSA_PUBLIC) {
throw XSECCryptoException(XSECCryptoException::RSAError,
"OpenSSL:RSA - Attempt to validate signature without public key");
}
char* cleanedBase64Signature;
unsigned int cleanedBase64SignatureLen = 0;
cleanedBase64Signature =
XSECCryptoBase64::cleanBuffer(base64Signature, sigLen, cleanedBase64SignatureLen);
ArrayJanitor<char> j_cleanedBase64Signature(cleanedBase64Signature);
int sigValLen;
unsigned char* sigVal = new unsigned char[sigLen + 1];
ArrayJanitor<unsigned char> j_sigVal(sigVal);
EvpEncodeCtxRAII dctx;
if (!dctx.of()) {
throw XSECCryptoException(XSECCryptoException::RSAError,
"OpenSSL:RSA - allocation fail during Context Creation");
}
EVP_DecodeInit(dctx.of());
int rc = EVP_DecodeUpdate(dctx.of(),
sigVal,
&sigValLen,
(unsigned char *) cleanedBase64Signature,
cleanedBase64SignatureLen);
if (rc < 0) {
throw XSECCryptoException(XSECCryptoException::RSAError,
"OpenSSL:RSA - Error during Base64 Decode");
}
int t = 0;
EVP_DecodeFinal(dctx.of(), &sigVal[sigValLen], &t);
sigValLen += t;
// OpenSSL allows the signature size to be less than the key size.
// Java does not and the spec requires that this fail, so we have to
// perform this check.
int keySize = RSA_size(mp_rsaKey);
if (keySize != sigValLen) {
throw XSECCryptoException(XSECCryptoException::RSAError,
"OpenSSL:RSA - Signature size does not match key size");
}
// Now decrypt
unsigned char* decryptBuf;
// Decrypt will always be longer than (RSA_len(key) - 11)
decryptBuf = new unsigned char[RSA_size(mp_rsaKey)];
ArrayJanitor<unsigned char> j_decryptBuf(decryptBuf);
// Note at this time only supports PKCS1 padding
// As that is what is defined in the standard.
// If this ever changes we will need to pass some paramaters
// into this function to allow it to determine what the
// padding should be and what the message digest OID should
// be.
int decryptSize = RSA_public_decrypt(sigValLen,
sigVal,
decryptBuf,
mp_rsaKey,
RSA_PKCS1_PADDING);
if (decryptSize < 0) {
// Really - this is a failed signature check, not an exception!
return false;
}
/* Check the OID */
int oidLen = 0;
unsigned char * oid = getRSASigOID(type, oidLen);
if (oid == NULL) {
throw XSECCryptoException(XSECCryptoException::RSAError,
"OpenSSL:RSA::verify() - Unsupported HASH algorithm for RSA");
}
if (decryptSize != (int) (oidLen + hashLen) || hashLen != oid[oidLen-1]) {
return false;
}
for (t = 0; t < oidLen; ++t) {
if (oid[t] != decryptBuf[t]) {
return false;
}
}
for (;t < decryptSize; ++t) {
if (hashBuf[t-oidLen] != decryptBuf[t]) {
return false;
}
}
// All OK
return true;
}