Beispiel #1
0
int
qat_rsa_decrypt(CpaCyRsaDecryptOpData * dec_op_data, int rsa_len,
                CpaFlatBuffer * output_buf)
{
    /* Used for RSA Decrypt and RSA Sign */
    struct op_done op_done;
    CpaStatus sts = CPA_STATUS_FAIL;
    CpaInstanceHandle instance_handle = NULL;
    int job_ret = 0;
    int sync_mode_ret = 0;
    int pthread_kill_ret;

    DEBUG("- Started\n");

    if (qat_use_signals()) {
        qat_atomic_inc(num_requests_in_flight);
        pthread_kill_ret = pthread_kill(timer_poll_func_thread, SIGUSR1);
        if (pthread_kill_ret != 0) {
            WARN("pthread_kill error\n");
            QATerr(QAT_F_QAT_RSA_DECRYPT, ERR_R_INTERNAL_ERROR);
            qat_atomic_dec(num_requests_in_flight);
            return 0;
        }
    }
    qat_init_op_done(&op_done);
    if (op_done.job != NULL) {
        if (qat_setup_async_event_notification(0) == 0) {
            WARN("Failed to setup async event notifications\n");
            QATerr(QAT_F_QAT_RSA_DECRYPT, ERR_R_INTERNAL_ERROR);
            qat_cleanup_op_done(&op_done);
            qat_atomic_dec_if_polling(num_requests_in_flight);
            return 0;
        }
    } else {
        /*
         *  Sync mode
         */
        qat_cleanup_op_done(&op_done);
        sync_mode_ret = qat_rsa_decrypt_CRT(dec_op_data, rsa_len, output_buf);
        qat_atomic_dec_if_polling(num_requests_in_flight);
        return sync_mode_ret;
    }
    /*
     * cpaCyRsaDecrypt() is the function called for RSA Sign in the API.
     * For that particular case the dec_op_data [IN] contains both the
     * private key value and the message (hash) value. The output_buf [OUT]
     * stores the signature as the output once the request is fully completed.
     * The sts return value contains 0 (CPA_STATUS_SUCCESS) if the request
     * was successfully submitted.
     */
    CRYPTO_QAT_LOG("- RSA\n");
    do {
        if (NULL == (instance_handle = get_next_inst())) {
            WARN("Failed to get an instance\n");
            QATerr(QAT_F_QAT_RSA_DECRYPT, ERR_R_INTERNAL_ERROR);
            qat_clear_async_event_notification();
            qat_cleanup_op_done(&op_done);
            qat_atomic_dec_if_polling(num_requests_in_flight);
            return 0;
        }
        DUMP_RSA_DECRYPT(instance_handle, &op_done, dec_op_data, output_buf);
        sts = cpaCyRsaDecrypt(instance_handle, qat_rsaCallbackFn, &op_done,
                              dec_op_data, output_buf);
        if (sts == CPA_STATUS_RETRY) {
            if ((qat_wake_job(op_done.job, 0) == 0) ||
                (qat_pause_job(op_done.job, 0) == 0)) {
                WARN("qat_wake_job or qat_pause_job failed\n");
                break;
            }
        }
    }
    while (sts == CPA_STATUS_RETRY);

    if (sts != CPA_STATUS_SUCCESS) {
        WARN("Failed to submit request to qat - status = %d\n", sts);
        QATerr(QAT_F_QAT_RSA_DECRYPT, ERR_R_INTERNAL_ERROR);
        qat_clear_async_event_notification();
        qat_cleanup_op_done(&op_done);
        qat_atomic_dec_if_polling(num_requests_in_flight);
        return 0;
    }

    do {
        /* If we get a failure on qat_pause_job then we will
           not flag an error here and quit because we have
           an asynchronous request in flight.
           We don't want to start cleaning up data
           structures that are still being used. If
           qat_pause_job fails we will just yield and
           loop around and try again until the request
           completes and we can continue. */
        if ((job_ret = qat_pause_job(op_done.job, 0)) == 0)
            pthread_yield();
    }
    while (!op_done.flag ||
           QAT_CHK_JOB_RESUMED_UNEXPECTEDLY(job_ret));

    DUMP_RSA_DECRYPT_OUTPUT(output_buf);
    qat_cleanup_op_done(&op_done);
    qat_atomic_dec_if_polling(num_requests_in_flight);

    if (op_done.verifyResult != CPA_TRUE) {
        WARN("Verification of result failed\n");
        QATerr(QAT_F_QAT_RSA_DECRYPT, ERR_R_INTERNAL_ERROR);
        return 0;
    }

    DEBUG("- Finished\n");
    return 1;
}
/*****************************************************************************
 * @ingroup IKE_RSA
 *
 * @description
 *      This function sets up the QA API asymmetric functions of an IKE
 *      transaction using RSA to sign/verify DH generated keys
 ******************************************************************************/
static CpaStatus ikeRsaPerform(asym_test_params_t* setup)
{
    CpaStatus status = CPA_STATUS_SUCCESS;
    Cpa32U i = 0;
    Cpa32U innerLoop = 0;
    ike_rsa_client_data_t alice = {0};
    ike_rsa_client_data_t bob = {0};
    CpaCyRsaPrivateKey    **pPrivateKey = NULL;
    CpaCyRsaPublicKey     **pPublicKey = NULL;
    Cpa32U node = 0;
    /*functions called in this code over writes the performanceStats->response,
     * so we use a local counter to count responses */
    Cpa32U responses = 0;

    status = sampleCodeCyGetNode(setup->cyInstanceHandle, &node);
    if(CPA_STATUS_SUCCESS != status)
    {
        PRINT_ERR("sampleCodeCyGetNode failed with status %u\n", status);
        return status;
    }
    /************************************************************************/
    /* Allocate all the memory for DH and RSA operations                    */
    /************************************************************************/
    /*these macros internally free memory return fail if they fail*/
   status = allocArrayOfPointers(
            setup->cyInstanceHandle,
            (void**)&pPrivateKey,
            setup->numBuffers);
    if(CPA_STATUS_SUCCESS != status)
    {
        return CPA_STATUS_FAIL;
    }

    status = allocArrayOfPointers(
            setup->cyInstanceHandle,
            (void**)&pPublicKey,
            setup->numBuffers);
    if(CPA_STATUS_SUCCESS != status)
    {
        qaeMemFreeNUMA((void**)&pPrivateKey);
        return CPA_STATUS_FAIL;
    }

    /*Allocate for Alice*/
    if(CPA_STATUS_SUCCESS != allocClientMem(setup, &alice))
    {
        PRINT_ERR("allocClientMem error\n");
        ikeRsaMemFree(setup, &alice, &bob, pPrivateKey, pPublicKey);
        return CPA_STATUS_FAIL;
    }
    /*Allocate for Bob*/
    if(CPA_STATUS_SUCCESS != allocClientMem(setup, &bob))
    {
        PRINT_ERR("allocClientMem error\n");
        ikeRsaMemFree(setup, &alice, &bob, pPrivateKey, pPublicKey);
        return CPA_STATUS_FAIL;
    }
    /* *************************************************************************
     * STEP 1. Alice & Bob generate public & private RSA keys
     * ************************************************************************/
    status = genKeyArray(setup, pPrivateKey, pPublicKey);
    if(status != CPA_STATUS_SUCCESS)
    {
        PRINT_ERR("Error, failed genKeyArray, status: %d\n",
                status);
        ikeRsaMemFree(setup, &alice, &bob, pPrivateKey, pPublicKey);
        return status;
    }
    /**************************************************************************
    * STEP 2. Alice & Bob agree on a p & g and generate secret random x
     **************************************************************************/
    status = dhPhase1Setup(setup, alice.ppPhase1, bob.ppPhase1,
            alice.ppPublicValues, bob.ppPublicValues, pPublicKey);
    if(status != CPA_STATUS_SUCCESS)
    {
        PRINT_ERR("Error, failed dhPhase1Setup, status: %d\n",
                status);
        ikeRsaMemFree(setup, &alice, &bob, pPrivateKey, pPublicKey);
        return status;
    }
    /**************************************************************************
     * STEP 3. Alice & Bob Perform DH Phase1 to produce Public Value -
     * PV = g^x mod p
     **************************************************************************/
    status = dhPhase1(alice.ppPhase1, alice.ppPublicValues, setup,
            setup->numBuffers, ONE_LOOP);
    if(status !=CPA_STATUS_SUCCESS)
    {
        PRINT_ERR("Error, failed to complete dhPhase1 for Alice, status: %d\n",
                status);
        ikeRsaMemFree(setup, &alice, &bob, pPrivateKey, pPublicKey);
        return status;
    }
    /**************************************************************************/
    /*Perform DH phase1 for Bob                                               */
    /**************************************************************************/
    status = dhPhase1(bob.ppPhase1,bob.ppPublicValues, setup,
            setup->numBuffers, ONE_LOOP);
    if(CPA_STATUS_SUCCESS != status)
    {
        PRINT_ERR("Error, failed to complete dhPhase1 for Bob, status: %d\n",
                status);
        ikeRsaMemFree(setup, &alice, &bob, pPrivateKey, pPublicKey);
        return status;
    }

    /**************************************************************************/
    /*Perform Phase2 setup for Bob                                            */
    /**************************************************************************/
    status = dhPhase2Setup(bob.ppSecretKeys, bob.ppPhase1, bob.ppPhase2,
                alice.ppPublicValues, setup);
    if(CPA_STATUS_SUCCESS != status)
    {
        PRINT_ERR("Error, failed to setup phase2 for Bob, status: %d\n",
                status);
        ikeRsaMemFree(setup, &alice, &bob, pPrivateKey, pPublicKey);
        return status;
    }
    /**************************************************************************/
    /*Calculate Bobs secret keys                                            */
    /**************************************************************************/
    status = dhPhase2Perform(bob.ppSecretKeys, bob.ppPhase2,
            setup, setup->numBuffers, ONE_LOOP);
    if(CPA_STATUS_SUCCESS != status)
    {
        PRINT_ERR("Error, failed to perform phase2 for Bob, status: %d\n",
                status);
        ikeRsaMemFree(setup, &alice, &bob, pPrivateKey, pPublicKey);
        return status;
    }

    /***************************************************************************
     * STEP 5. Sign Bobs Public Value using peers public key ->
     * Bobs Signature = RSA decrypt bobsPV
     * ************************************************************************/
    /**************************************************************************/
    /*Setup the RSA decrypt structure                                         */
    /**************************************************************************/
    status = rsaDecryptDataSetup(bob.ppPublicValues, bob.ppDecryptOpData,
            bob.ppSignatures, setup);
    if(CPA_STATUS_SUCCESS != status)
    {
        PRINT_ERR("Error, failed rsaDecryptDataSetup for Bob, status: %d\n",
                status);
        ikeRsaMemFree(setup, &alice, &bob, pPrivateKey, pPublicKey);
        return status;
    }
    /**************************************************************************
     * setup encryption, we need an encryptOpData structure, because the
     * rsaSetOpDataKeys generates a public key and needs to copy it into
     * an encryptOpData structure
    **************************************************************************/
    status = rsaEncryptDataSetup(bob.ppSignatures, bob.ppEncryptOpData,
            bob.ppPVverifier, setup);
    if(CPA_STATUS_SUCCESS != status)
    {
        PRINT_ERR("Error, failed rsaEncryptDataSetup for Bob, status: %d\n",
                        status);
        ikeRsaMemFree(setup, &alice, &bob, pPrivateKey, pPublicKey);
        return status;
    }
    status = rsaEncryptDataSetup(bob.ppSignatures, bob.ppEncryptOpData2,
            bob.ppPVverifier2, setup);
    if(CPA_STATUS_SUCCESS != status)
    {
        PRINT_ERR("Error, failed rsaEncryptDataSetup for Bob, status: %d\n",
                        status);
        ikeRsaMemFree(setup, &alice, &bob, pPrivateKey, pPublicKey);
        return status;
    }
    /**************************************************************************/
    /* Setup decryption opData structure with RSA key                         */
    /**************************************************************************/
    rsaSetOpDataKeys(setup, bob.ppDecryptOpData, bob.ppEncryptOpData,
            pPrivateKey,pPublicKey);
    rsaSetOpDataKeys(setup, bob.ppDecryptOpData, bob.ppEncryptOpData2,
            pPrivateKey,pPublicKey);
    /**************************************************************************/
    /* Sign all of Bobs public value buffers, but loop only once              */
    /**************************************************************************/
    status = sampleRsaDecrypt(setup,
            bob.ppDecryptOpData,
            bob.ppSignatures,
            setup->numBuffers,
            ONE_LOOP);
    if(CPA_STATUS_SUCCESS != status)
    {
        PRINT_ERR("Error, failed sampleRsaDecrypt for Bob, status: %d\n",
                        status);
        ikeRsaMemFree(setup, &alice, &bob, pPrivateKey, pPublicKey);
        return status;
    }
    /* Copy the RSADecrypt output into the Encrypt Op structure
     * in the performance loop we verify bobs signature. Bobs signature is
     * the input the the encrypt operation*/
    for(i=0;i<setup->numBuffers;i++)
    {
        /*check that the signature is the expected length*/
        if(bob.ppEncryptOpData[i]->inputData.dataLenInBytes !=
            bob.ppSignatures[i]->dataLenInBytes)
        {
            PRINT_ERR("encrypt data len does not match the signature len\n");
            ikeRsaMemFree(setup, &alice, &bob, pPrivateKey, pPublicKey);
            return status;
        }
        memcpy(bob.ppEncryptOpData[i]->inputData.pData,
                bob.ppSignatures[i]->pData,
                bob.ppEncryptOpData[i]->inputData.dataLenInBytes);
        /*check that the signature is the expected length*/
        if(bob.ppEncryptOpData2[i]->inputData.dataLenInBytes !=
            bob.ppSignatures[i]->dataLenInBytes)
        {
            PRINT_ERR("encrypt data len does not match the signature len\n");
            ikeRsaMemFree(setup, &alice, &bob, pPrivateKey, pPublicKey);
            return status;
        }
        memcpy(bob.ppEncryptOpData2[i]->inputData.pData,
                bob.ppSignatures[i]->pData,
                bob.ppEncryptOpData2[i]->inputData.dataLenInBytes);
    }
    /***************************************************************************
     * STEP 6. Setup Alices Decrypt and Diffie Hellman Data for performance Loop
     * ************************************************************************/
    /**************************************************************************/
    /* Setup the RSA decrypt structure*/
    /**************************************************************************/
    status = rsaDecryptDataSetup(alice.ppPublicValues, alice.ppDecryptOpData,
            alice.ppSignatures, setup);
    if(CPA_STATUS_SUCCESS != status)
    {
        PRINT_ERR("Error, failed rsaDecryptDataSetup for Alice, status: %d\n",
                                status);
        ikeRsaMemFree(setup, &alice, &bob, pPrivateKey, pPublicKey);
        return CPA_STATUS_FAIL;
    }
    /**************************************************************************
     * Setup encryption: we need an encryptOpData structure, because the
     * rsaSetOpDataKeys generates a public key and needs to copy it into
     * an encryptOpData structure
    **************************************************************************/
    status = rsaEncryptDataSetup(alice.ppSignatures, alice.ppEncryptOpData,
            alice.ppPVverifier, setup);
    if(CPA_STATUS_SUCCESS != status)
    {
        PRINT_ERR("Error, failed rsaEncryptDataSetup for Alice, status: %d\n",
                                status);
        ikeRsaMemFree(setup, &alice, &bob, pPrivateKey, pPublicKey);
        return CPA_STATUS_FAIL;
    }
    /**************************************************************************/
    /*setup decryption opData structure with RSA key                          */
    /**************************************************************************/
    rsaSetOpDataKeys(setup, alice.ppDecryptOpData, alice.ppEncryptOpData,
            pPrivateKey,pPublicKey);

    /**************************************************************************/
    /* Perform Phase2 setup for Alice                                         */
    /**************************************************************************/
    status = dhPhase2Setup(alice.ppSecretKeys, alice.ppPhase1, alice.ppPhase2,
                bob.ppPVverifier, setup);
    if(CPA_STATUS_SUCCESS != status)
    {
        PRINT_ERR("Error, failed to setup phase2 for Alice, status: %d\n",
                status);
        ikeRsaMemFree(setup, &alice, &bob, pPrivateKey, pPublicKey);
        return status;
    }

    /***************************************************************************
     * STEP 7 IKE main mode Asymmetric steps
     **************************************************************************/

    if(CPA_STATUS_SUCCESS != status)
    {
        PRINT_ERR("Error, failed to allcate ppPVverifier2, status: %d\n",
                status);
        ikeRsaMemFree(setup, &alice, &bob, pPrivateKey, pPublicKey);
        return status;
    }
    /*this barrier will wait until all threads get to this point*/
    sampleCodeBarrier();
    memset(setup->performanceStats,0, sizeof(perf_data_t));
    setup->performanceStats->startCyclesTimestamp = sampleCodeTimestamp();

    /*pre-set the number of ops we plan to submit*/
    /*number of responses equals the number of QA APIs we have chained together
     * multiplied by the number of buffers and how many times we have looped
     * over the buffers */
    setup->performanceStats->numOperations = (Cpa64U)NUMBER_OF_CHAINED_OPS *
                         setup->numBuffers * setup->numLoops;
    setup->performanceStats->averagePacketSizeInBytes =
                                     setup->modulusSizeInBytes;
    setup->performanceStats->responses=0;
    /* Completion used in callback */
    sampleCodeSemaphoreInit(&setup->performanceStats->comp, 0);

    for(i = 0; i < setup->numLoops; i++)
    {
        for(innerLoop = 0; innerLoop < setup->numBuffers; innerLoop++)
        {
            /******************************************************************/
            /* Step 7a Perform DH phase1 for Alice
             * This step, performs setup->NumBuffers DH Phase1 Operations to
             * Calculate setup->numBuffers Public Values for Alice*/
            /******************************************************************/
            do
            {
            /*****************************************************************/
            /* ikeRsaCallback  : used in asynchronous mode
             * performanceStats: Opaque user data
             * ppPhase1        : Structure containing p, g and x
             * ppPublicValues  : Public value (output) */
            /******************************************************************/

                status = cpaCyDhKeyGenPhase1(setup->cyInstanceHandle,
                        NULL/*ikeRsaCallback*/,
                        setup->performanceStats,
                        alice.ppPhase1[innerLoop],
                        alice.ppPublicValues[innerLoop]);

                /*this is a back off mechanism to stop the code
                 * continually submitting requests. Without this the CPU
                 * can report a soft lockup if it continually loops
                 * on busy*/
                if(status == CPA_STATUS_RETRY)
                {
                    setup->performanceStats->retries++;
                    AVOID_SOFTLOCKUP;
                }
            } while (CPA_STATUS_RETRY == status);

            if(CPA_STATUS_SUCCESS != status)
            {
                PRINT_ERR("Failed to complete dhPhase1 for Alice, status: %d\n",
                        status);
                break;
            }
            /******************************************************************/
            /* Step 7b Perform RSA verify of third party...normally this is done
             *  on at third party to verify that bob is who he says he is, but
             *  here we are performing a second RSA encrypt on Bobs signature to
             *  test the sequence of calls                                    */
            /******************************************************************/
            do
            {
               status = cpaCyRsaEncrypt(
                  setup->cyInstanceHandle,
                  NULL/*ikeRsaCallback*/,
                  setup->performanceStats,
                  bob.ppEncryptOpData[innerLoop],
                  bob.ppPVverifier[innerLoop]);
               if(status == CPA_STATUS_RETRY)
               {
                 setup->performanceStats->retries++;
                 AVOID_SOFTLOCKUP;
               }
            } while (CPA_STATUS_RETRY == status);

            if (CPA_STATUS_SUCCESS != status)
            {
                PRINT_ERR("Failed on RsaVerify for Bob using buffer=%d \n",
                        innerLoop);
                break;
            }

            /***************************************************************
             * Step 7c Perform RSA verify of Bobs signed public values.
             * Bobs Public values and Bobs RSA Signature have been
             * pre-calculated Bobs signature is in the EncryptOpData
             * structure, the verifier value should match bobsPublic value,
             * but in this code we dont check if they match
             **************************************************************/
            do
            {
                status = cpaCyRsaEncrypt(
                    setup->cyInstanceHandle,
                    NULL/*ikeRsaCallback*/,
                    setup->performanceStats,
                    bob.ppEncryptOpData2[innerLoop],
                    bob.ppPVverifier2[innerLoop]);
                if(status == CPA_STATUS_RETRY)
                {
                    setup->performanceStats->retries++;
                    AVOID_SOFTLOCKUP;
                }
            } while (CPA_STATUS_RETRY == status);

            if (CPA_STATUS_SUCCESS != status)
            {
                PRINT_ERR("Failed on RsaVerify for Bob using buffer=%d \n ",
                        innerLoop);
                break;
            }

            /******************************************************************
             * Step 7d Sign all of Alices public value buffers,
             * Alices Public Value is in the Decrypt opData setup, the signature
             *  is placed in alices signature
            ******************************************************************/
            do
            {
               status = cpaCyRsaDecrypt(
                  setup->cyInstanceHandle,
                  NULL/*ikeRsaCallback*/,
                  setup->performanceStats,
                  alice.ppDecryptOpData[innerLoop],
                  alice.ppSignatures[innerLoop]);
               if(status == CPA_STATUS_RETRY)
               {
                   setup->performanceStats->retries++;
                   AVOID_SOFTLOCKUP;
               }
            } while (CPA_STATUS_RETRY == status);

            if (CPA_STATUS_SUCCESS != status)
            {
                PRINT_ERR("Failed to complete RsaSign for Alice, status: %d\n",
                  innerLoop);
                break;
            }
            /******************************************************************/
            /* Step 7e Perform the DH phase2 operation for Alice,
             * using Bobs verified Public values                              */

            do
            {
                status = cpaCyDhKeyGenPhase2Secret(setup->cyInstanceHandle,
                        NULL/*ikeRsaCallback*/,
                        setup->performanceStats,
                        alice.ppPhase2[innerLoop],
                        alice.ppSecretKeys[innerLoop]);

                /*this is a back off mechanism to stop the code
                * continually calling the Decrypt operation when the
                * acceleration units are busy. Without this the CPU
                * can report a soft lockup if it continually loops
                * on busy*/
                if(status == CPA_STATUS_RETRY)
                {
                    setup->performanceStats->retries++;
                    AVOID_SOFTLOCKUP;
                }
            } while (CPA_STATUS_RETRY == status);

            if (CPA_STATUS_SUCCESS != status)
            {
                PRINT_ERR("Diffie Hellman Phase2 for Alice, status: %d\n",
                        status);
                break;
            }
            /*At this point Bob and Alice should have created the same shared
             * secret key*/
            responses++;
        } /*end innerLoop*/
        if (CPA_STATUS_SUCCESS != status)
        {
          break;
        }

    } /*end numLoops*/
    setup->performanceStats->endCyclesTimestamp = sampleCodeTimestamp();
    /*if (CPA_STATUS_SUCCESS == status)
    {
        if(sampleCodeSemaphoreWait(&setup->performanceStats->comp,
                SAMPLE_CODE_WAIT_FOREVER) != CPA_STATUS_SUCCESS)
        {
           PRINT_ERR("interruption in ike rsa Loop\n");
           status = CPA_STATUS_FAIL;
        }
    }*/

    sampleCodeSemaphoreDestroy(&setup->performanceStats->comp);

    if(CPA_STATUS_SUCCESS != status)
    {
        ikeRsaMemFree(setup, &alice, &bob, pPrivateKey, pPublicKey);
        return status;
    }

    ikeRsaMemFree(setup, &alice, &bob, pPrivateKey, pPublicKey);
    /*set the total number of responses and requests. */
    setup->performanceStats->numOperations = (Cpa64U)responses * NUMBER_OF_CHAINED_OPS;
    setup->performanceStats->responses = responses * NUMBER_OF_CHAINED_OPS;
    if(CPA_STATUS_SUCCESS != setup->performanceStats->threadReturnStatus)
    {
        status = CPA_STATUS_FAIL;
    }
    return status;
}