Пример #1
0
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);

}