bool XENCAlgorithmHandlerDefault::doRSAEncryptToSafeBuffer()

in xsec/xenc/impl/XENCAlgorithmHandlerDefault.cpp [859:971]


bool XENCAlgorithmHandlerDefault::doRSAEncryptToSafeBuffer(
        TXFMChain* plainText,
        XENCEncryptionMethod* encryptionMethod,
        const XSECCryptoKey* key,
        XERCES_CPP_NAMESPACE_QUALIFIER DOMDocument* doc,
        safeBuffer& result
        ) const {

    // Only works with RSA_PRIVATE or PAIR
    if (key->getKeyType() == XSECCryptoKey::KEY_RSA_PRIVATE) {
        throw XSECException(XSECException::CipherError,
            "XENCAlgorithmHandlerDefault - RSA Encrypt must use public key");
    }

    XSECCryptoKeyRSA* rsa = (XSECCryptoKeyRSA*) key;

    // Allocate an output buffer
    unsigned char* encBuf;
    XSECnew(encBuf, unsigned char[rsa->getLength()]);
    ArrayJanitor<unsigned char> j_encBuf(encBuf);

    // Input
    TXFMBase* b = plainText->getLastTxfm();
    safeBuffer plainSB;
    plainSB.isSensitive();

    XMLByte buf[1024];
    unsigned int offset = 0;

    unsigned int bytesRead = (unsigned int) b->readBytes(buf, 1024);
    while (bytesRead > 0) {
        plainSB.sbMemcpyIn(offset, buf, bytesRead);
        offset += bytesRead;
        bytesRead = (unsigned int) b->readBytes(buf, 1024);
    }

    unsigned int encryptLen;

    // Do encrypt
    if (strEquals(encryptionMethod->getAlgorithm(), DSIGConstants::s_unicodeStrURIRSA_1_5)) {
        encryptLen = rsa->publicEncrypt(plainSB.rawBuffer(),
                                                  encBuf,
                                                  offset,
                                                  rsa->getLength(),
                                                  XSECCryptoKeyRSA::PAD_PKCS_1_5);
    }

    else if (strEquals(encryptionMethod->getAlgorithm(), DSIGConstants::s_unicodeStrURIRSA_OAEP_MGFP1) ||
            strEquals(encryptionMethod->getAlgorithm(), DSIGConstants::s_unicodeStrURIRSA_OAEP)) {

        const XMLCh* digmeth = encryptionMethod->getDigestMethod();
        if (!digmeth || !*digmeth) {
            digmeth = DSIGConstants::s_unicodeStrURISHA1;
        }

        const XMLCh* mgfalg = encryptionMethod->getMGF();
        if (!mgfalg || !*mgfalg) {
            mgfalg = DSIGConstants::s_unicodeStrURIMGF1_SHA1;
        }

        // Read out any OAEP params
        unsigned char* oaepParamsBuf = NULL;
        unsigned int oaepParamsLen = 0;

        const XMLCh* oaepParams = encryptionMethod->getOAEPparams();
        if (oaepParams != NULL) {
            XSECAutoPtrChar oaepParamsStr(oaepParams);

            unsigned int bufLen = (unsigned int) strlen(oaepParamsStr.get());
            oaepParamsBuf = new unsigned char[bufLen];

            XSECCryptoBase64* b64 = XSECPlatformUtils::g_cryptoProvider->base64();
            Janitor<XSECCryptoBase64> j_b64(b64);

            b64->decodeInit();
            oaepParamsLen = b64->decode((unsigned char*) oaepParamsStr.get(), bufLen, oaepParamsBuf, bufLen);
            oaepParamsLen += b64->decodeFinish(&oaepParamsBuf[oaepParamsLen], bufLen - oaepParamsLen);
        }

        ArrayJanitor<unsigned char> j_oaepParamsBuf(oaepParamsBuf);

        encryptLen = rsa->publicEncrypt(plainSB.rawBuffer(),
                                          encBuf,
                                          offset,
                                          rsa->getLength(),
                                          XSECCryptoKeyRSA::PAD_OAEP,
                                          digmeth,
                                          mgfalg,
                                          oaepParamsBuf,
                                          oaepParamsLen);
    }
    else {
        throw XSECException(XSECException::CipherError,
            "XENCAlgorithmHandlerDefault::doRSAEncryptToSafeBuffer - Unknown padding type");
    }

    // Now need to base64 encode
    XSECCryptoBase64* b64 =
        XSECPlatformUtils::g_cryptoProvider->base64();
    Janitor<XSECCryptoBase64> j_b64(b64);

    b64->encodeInit();
    encryptLen = b64->encode(encBuf, encryptLen, buf, 1024);
    result.sbMemcpyIn(buf, encryptLen);
    unsigned int finalLen = b64->encodeFinish(buf, 1024);
    result.sbMemcpyIn(encryptLen, buf, finalLen);
    result[encryptLen + finalLen] = '\0';

    // This is a string, so set the buffer correctly
    result.setBufferType(safeBuffer::BUFFER_CHAR);

    return true;
}