void bdoc::Signature::checkSignatureValue() { X509Cert cert(getSigningCertificate()); const dsig::SignatureMethodType::AlgorithmType& algorithmType = getSignatureMethodAlgorithmType(); const char* algorithmUri = algorithmType.c_str(); // Get hash method URI from signature method URI. signatureMethod sm; hashMethod hm; safeBuffer hashMethodUri; if (!XSECmapURIToSignatureMethods(XMLString::transcode(algorithmUri), sm, hm) || !hashMethod2URI(hashMethodUri, hm)) { THROW_STACK_EXCEPTION("Couldn't extract hash method from " "signature method URI '%s'.", algorithmUri); } std::auto_ptr<Digest> calc = Digest::create(hashMethodUri.rawCharBuffer()); std::vector<unsigned char> digest = calcDigestOnNode(calc.get(), DSIG_NAMESPACE, "SignedInfo"); std::vector<unsigned char> signatureValue = getSignatureValue(); if (!cert.verifySignature(calc->getMethod(), calc->getSize(), digest, signatureValue)) { THROW_STACK_EXCEPTION("Signature is not valid."); } }
bool DSIGAlgorithmHandlerDefault::appendSignatureHashTxfm(TXFMChain * inputBytes, const XMLCh * URI, XSECCryptoKey * key) { signatureMethod sm; hashMethod hm; // Map to internal constants if (!XSECmapURIToSignatureMethods(URI, sm, hm)) { safeBuffer sb; sb.sbTranscodeIn("DSIGAlgorithmHandlerDefault - Unknown URI : "); sb.sbXMLChCat(URI); throw XSECException(XSECException::AlgorithmMapperError, sb.rawXMLChBuffer()); } // Now append the appropriate hash transform onto the end of the chain // If this is an HMAC of some kind - this function will add the appropriate key TXFMBase * htxfm = addHashTxfm(sm, hm, key, inputBytes->getLastTxfm()->getDocument()); inputBytes->appendTxfm(htxfm); return true; }
// -------------------------------------------------------------------------------- // Verify // -------------------------------------------------------------------------------- bool DSIGAlgorithmHandlerDefault::verifyBase64Signature( TXFMChain * inputBytes, const XMLCh * URI, const char * sig, unsigned int outputLength, XSECCryptoKey * key) { signatureMethod sm; hashMethod hm; // Map to internal constants if (!XSECmapURIToSignatureMethods(URI, sm, hm)) { safeBuffer sb; sb.sbTranscodeIn("DSIGAlgorithmHandlerDefault - Unknown URI : "); sb.sbXMLChCat(URI); throw XSECException(XSECException::AlgorithmMapperError, sb.rawXMLChBuffer()); } // Now append the appropriate hash transform onto the end of the chain // If this is an HMAC of some kind - this function will add the appropriate key TXFMBase * htxfm = addHashTxfm(sm, hm, key, inputBytes->getLastTxfm()->getDocument()); inputBytes->appendTxfm(htxfm); unsigned char hash[4096]; int hashLen = inputBytes->getLastTxfm()->readBytes((XMLByte *) hash, 4096); // Now check the calculated hash bool sigVfyRet = false; switch (key->getKeyType()) { case (XSECCryptoKey::KEY_DSA_PUBLIC) : case (XSECCryptoKey::KEY_DSA_PAIR) : if (sm != SIGNATURE_DSA) { throw XSECException(XSECException::AlgorithmMapperError, "Key type does not match <SignedInfo> signature type"); } sigVfyRet = ((XSECCryptoKeyDSA *) key)->verifyBase64Signature( hash, hashLen, (char *) sig, (unsigned int) strlen(sig)); break; case (XSECCryptoKey::KEY_RSA_PUBLIC) : case (XSECCryptoKey::KEY_RSA_PAIR) : if (sm != SIGNATURE_RSA) { throw XSECException(XSECException::AlgorithmMapperError, "Key type does not match <SignedInfo> signature type"); } sigVfyRet = ((XSECCryptoKeyRSA *) key)->verifySHA1PKCS1Base64Signature( hash, hashLen, sig, (unsigned int) strlen(sig), hm); break; case (XSECCryptoKey::KEY_EC_PUBLIC) : case (XSECCryptoKey::KEY_EC_PAIR) : if (sm != SIGNATURE_ECDSA) { throw XSECException(XSECException::AlgorithmMapperError, "Key type does not match <SignedInfo> signature type"); } sigVfyRet = ((XSECCryptoKeyEC *) key)->verifyBase64SignatureDSA( hash, hashLen, (char *) sig, (unsigned int) strlen(sig)); break; case (XSECCryptoKey::KEY_HMAC) : // Already done - just compare calculated value with read value // FIX: CVE-2009-0217 if (outputLength > 0 && (outputLength > hashLen || outputLength < 80 || outputLength < hashLen / 2)) { throw XSECException(XSECException::AlgorithmMapperError, "HMACOutputLength set to unsafe value."); } sigVfyRet = compareBase64StringToRaw(sig, hash, hashLen, outputLength); break; default : throw XSECException(XSECException::AlgorithmMapperError, "Key found, but don't know how to check the signature using it"); } return sigVfyRet; }
unsigned int DSIGAlgorithmHandlerDefault::signToSafeBuffer( TXFMChain * inputBytes, const XMLCh * URI, XSECCryptoKey * key, unsigned int outputLength, safeBuffer & result) { signatureMethod sm; hashMethod hm; // Map to internal constants if (!XSECmapURIToSignatureMethods(URI, sm, hm)) { safeBuffer sb; sb.sbTranscodeIn("DSIGAlgorithmHandlerDefault - Unknown URI : "); sb.sbXMLChCat(URI); throw XSECException(XSECException::AlgorithmMapperError, sb.rawXMLChBuffer()); } // Now append the appropriate hash transform onto the end of the chain // If this is an HMAC of some kind - this function will add the appropriate key TXFMBase * htxfm = addHashTxfm(sm, hm, key, inputBytes->getLastTxfm()->getDocument()); inputBytes->appendTxfm(htxfm); unsigned char hash[4096]; int hashLen = inputBytes->getLastTxfm()->readBytes((XMLByte *) hash, 4096); // Now check the calculated hash // For now, use a fixed length buffer, but expand it, // and detect if the signature size exceeds what we can // handle. char b64Buf[MAXB64BUFSIZE]; unsigned int b64Len; safeBuffer b64SB; switch (key->getKeyType()) { case (XSECCryptoKey::KEY_DSA_PRIVATE) : case (XSECCryptoKey::KEY_DSA_PAIR) : if (sm != SIGNATURE_DSA) { throw XSECException(XSECException::AlgorithmMapperError, "Key type does not match <SignedInfo> signature type"); } b64Len = ((XSECCryptoKeyDSA *) key)->signBase64Signature( hash, hashLen, (char *) b64Buf, MAXB64BUFSIZE); if (b64Len <= 0) { throw XSECException(XSECException::AlgorithmMapperError, "Unknown error occured during a DSA Signing operation"); } else if (b64Len >= MAXB64BUFSIZE) { throw XSECException(XSECException::AlgorithmMapperError, "DSA Signing operation exceeded size of buffer"); } if (b64Buf[b64Len-1] == '\n') b64Buf[b64Len-1] = '\0'; else b64Buf[b64Len] = '\0'; break; case (XSECCryptoKey::KEY_RSA_PRIVATE) : case (XSECCryptoKey::KEY_RSA_PAIR) : if (sm != SIGNATURE_RSA) { throw XSECException(XSECException::AlgorithmMapperError, "Key type does not match <SignedInfo> signature type"); } b64Len = ((XSECCryptoKeyRSA *) key)->signSHA1PKCS1Base64Signature( hash, hashLen, (char *) b64Buf, MAXB64BUFSIZE, hm); if (b64Len <= 0) { throw XSECException(XSECException::AlgorithmMapperError, "Unknown error occured during a RSA Signing operation"); } else if (b64Len >= MAXB64BUFSIZE) { throw XSECException(XSECException::AlgorithmMapperError, "RSA Signing operation exceeded size of buffer"); } // Clean up some "funnies" and make sure the string is NULL terminated if (b64Buf[b64Len-1] == '\n') b64Buf[b64Len-1] = '\0'; else b64Buf[b64Len] = '\0'; break; case (XSECCryptoKey::KEY_EC_PRIVATE) : case (XSECCryptoKey::KEY_EC_PAIR) : if (sm != SIGNATURE_ECDSA) { throw XSECException(XSECException::AlgorithmMapperError, "Key type does not match <SignedInfo> signature type"); } b64Len = ((XSECCryptoKeyEC *) key)->signBase64SignatureDSA( hash, hashLen, (char *) b64Buf, MAXB64BUFSIZE); if (b64Len <= 0) { throw XSECException(XSECException::AlgorithmMapperError, "Unknown error occured during an ECDSA Signing operation"); } else if (b64Len >= MAXB64BUFSIZE) { throw XSECException(XSECException::AlgorithmMapperError, "ECDSA Signing operation exceeded size of buffer"); } if (b64Buf[b64Len-1] == '\n') b64Buf[b64Len-1] = '\0'; else b64Buf[b64Len] = '\0'; break; case (XSECCryptoKey::KEY_HMAC) : if (sm != SIGNATURE_HMAC) { throw XSECException(XSECException::AlgorithmMapperError, "Key type does not match <SignedInfo> signature type"); } // Signature already created, so just translate to base 64 and enter string // FIX: CVE-2009-0217 if (outputLength > 0 && (outputLength > hashLen || outputLength < 80 || outputLength < hashLen / 2)) { throw XSECException(XSECException::AlgorithmMapperError, "HMACOutputLength set to unsafe value."); } convertRawToBase64String(b64SB, hash, hashLen, outputLength); strncpy(b64Buf, (char *) b64SB.rawBuffer(), MAXB64BUFSIZE); break; default : throw XSECException(XSECException::AlgorithmMapperError, "Key found, but don't know how to sign the document using it"); } result = b64Buf; return (unsigned int) strlen(b64Buf); }