unsigned int DSIGAlgorithmHandlerDefault::signToSafeBuffer()

in xsec/dsig/DSIGAlgorithmHandlerDefault.cpp [262:411]


unsigned int DSIGAlgorithmHandlerDefault::signToSafeBuffer(
        TXFMChain* inputBytes,
        const XMLCh* URI,
        const XSECCryptoKey* key,
        unsigned int outputLength,
        safeBuffer& result) const {

    XSECCryptoHash::HashType hashType;

    // Map to internal constants

    if (!XSECAlgorithmSupport::evalSignatureMethod(URI, key, hashType)) {
        safeBuffer sb;
        sb.sbTranscodeIn("DSIGAlgorithmHandlerDefault - Unknown or key-incompatible 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(
            hashType,
            (key->getKeyType() == XSECCryptoKey::KEY_HMAC ? key : NULL),
            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) :

        b64Len = ((XSECCryptoKeyDSA *) key)->signBase64Signature(
            hash,
            hashLen,
            (char *) b64Buf,
            MAXB64BUFSIZE);

        if (b64Len <= 0) {
            throw XSECException(XSECException::AlgorithmMapperError,
                "Unknown error occurred 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) :

        b64Len = ((XSECCryptoKeyRSA *) key)->signSHA1PKCS1Base64Signature(
            hash,
            hashLen,
            (char *) b64Buf,
            MAXB64BUFSIZE,
            hashType);

        if (b64Len <= 0) {
            throw XSECException(XSECException::AlgorithmMapperError,
                "Unknown error occurred 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) :

        b64Len = ((XSECCryptoKeyEC *) key)->signBase64SignatureDSA(
            hash,
            hashLen,
            (char *) b64Buf,
            MAXB64BUFSIZE);

        if (b64Len <= 0) {
            throw XSECException(XSECException::AlgorithmMapperError,
                "Unknown error occurred 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) :

        // Signature already created, so just translate to base 64 and enter string

        // FIX: CVE-2009-0217
        if (outputLength > 0 && (outputLength > (unsigned int)hashLen || outputLength < 80 || outputLength < (unsigned int)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);
}