VOID testRsaRunAlgs()

in unittest/lib/old-testRsa.cpp [859:977]


VOID testRsaRunAlgs()
{
    BYTE    rbInput[TEST_RSA_MAX_NUMOF_BYTES] = { 0 };
    SIZE_T  cbInput = 0;

    BYTE    rbOutput[TEST_RSA_MAX_NUMOF_BYTES] = { 0 };
    SIZE_T  cbOutput = 0;

    BYTE    rbExtra[TEST_RSA_MAX_NUMOF_BYTES] = { 0 };
    SIZE_T  cbExtra = 0;

    PSYMCRYPT_HASH pHashAlgorithm = NULL;

    FuncRandFn randFunc = NULL;
    FuncDataFn queryFn = NULL;      // Encryption/Sign function
    FuncDataFn replyFn = NULL;      // Decryption/Verify function

    UINT32 iImplFrom = 0;
    UINT32 iImplTo = 0;

    vprint( g_verbose, "\n");

    for( std::vector<AlgorithmImplementation *>::iterator i = g_AlgList.begin(); i != g_AlgList.end(); i++ )
    {
        iImplFrom = ImplToInd( *i );

        vprint( g_verbose,  "    > Algorithm: %s From: %s\n", (*i)->m_algorithmName.c_str(), g_ImplNames[iImplFrom] );

        randFunc = ((FunctionalRsaImplementation *)(*i))->m_funcRandFunction;
        CHECK( randFunc != NULL, "TestRsa: No randomizing function.\n");

        queryFn = ((FunctionalRsaImplementation *)(*i))->m_funcQueryFunction;
        CHECK( queryFn != NULL, "TestRsa: No encryption / signing function.\n");

        for( std::vector<AlgorithmImplementation *>::iterator j = g_AlgList.begin(); j != g_AlgList.end(); j++ )
        {
            // Run tests if the algorithms are the same and at least one implementation is SymCrypt
            if (( (*i)->m_algorithmName == (*j)->m_algorithmName ) &&
                ( ((*i)->m_implementationName == ImpSc::name) || ((*j)->m_implementationName == ImpSc::name) ))
            {
                // If the algorithm is sign PKCS1 and the verifying implementation is CNG then
                // there is a bug in CNG's verification code in the case of small key, big hash algorithm,
                // and second OID in the list (e.g. 732 bits / SHA512 / 2nd OID of size 0xb bytes).
                // Then the first OID in the list with size 0xd bytes overflows the buffer and CNG
                // aborts (erroneously) the verification without checking the second OID. Therefore
                // we skip the scenario SymCrypt Signing => Cng Verification.
                if ( ((*i)->m_algorithmName == AlgRsaSignPkcs1::name) &&
                     ((*i)->m_implementationName == ImpSc::name) &&
                     ((*j)->m_implementationName == ImpCng::name) )
                {
                    continue;
                }

                iImplTo = ImplToInd( *j );

                replyFn = ((FunctionalRsaImplementation *)(*j))->m_funcReplyFunction;
                CHECK( replyFn != NULL, "TestRsa: No decryption/verify function.\n");

                vprint( g_verbose,  "    >>>> To: %s\n", g_ImplNames[iImplTo] );

                for (UINT32 entry = 0; entry < TEST_RSA_NUMOF_ENTRIES; entry++)
                {
                    // If the algorithm is sign PSS and the bitsize is not a multiple of 8, then
                    // Cng cannot process it (due to the Cng PSS padding accepting only byte aligned values).
                    // In these cases skip the tests.
                    if ( ((*i)->m_algorithmName == AlgRsaSignPss::name) &&
                         (g_KeyEntries[entry].bitSize % 8 != 0) &&
                         ( ((*i)->m_implementationName == ImpCng::name) || ((*j)->m_implementationName == ImpCng::name) ) )
                    {
                        continue;
                    }

                    for (UINT32 nTries = 0; nTries<TEST_RSA_NUMOF_RANDOM_TRIES; nTries++)
                    {
                        // For all algorithm pass in the bitsize of the modulus in cbExtra.
                        // Currently, raw encrypt and sign PSS use it:
                        // For raw encrypt the randomizing function can create an input that is at the edge of the
                        // modulus' bits.
                        // For PSS sign it can pick a salt size that is at the edge of the available buffer.
                        cbExtra = g_KeyEntries[entry].bitSize;

                        (*randFunc)(
                            g_KeyEntries[entry].keySize,
                            rbInput,
                            &cbInput,
                            &cbOutput,
                            rbExtra,
                            &cbExtra,
                            &pHashAlgorithm );

                        (*queryFn)(
                            g_KeyEntries[entry].keySize,
                            g_KeyEntries[entry].pKeys[iImplFrom],
                            rbInput,
                            cbInput,
                            rbOutput,
                            cbOutput,
                            rbExtra,
                            cbExtra,
                            pHashAlgorithm );

                        (*replyFn)(
                            g_KeyEntries[entry].keySize,
                            g_KeyEntries[entry].pKeys[iImplTo],
                            rbInput,
                            cbInput,
                            rbOutput,
                            cbOutput,
                            rbExtra,
                            cbExtra,
                            pHashAlgorithm );

                        (*i)->m_nResults ++;
                    }
                }
            }
        }
    }
}