int
aagPtkPrf(v_U32_t cryptHandle,
          v_U8_t result[AAG_PRF_MAX_OUTPUT_SIZE],
          v_U32_t prfLen,
          tAniPacket *pmk, 
          tAniMacAddr authAddr,
          tAniMacAddr suppAddr,
          v_U8_t aNonce[ANI_EAPOL_KEY_RSN_NONCE_SIZE],
          v_U8_t sNonce[ANI_EAPOL_KEY_RSN_NONCE_SIZE])
{
    v_U8_t *lowMac;
    v_U8_t *highMac;
    v_U8_t *lowNonce;
    v_U8_t *highNonce;

    v_U8_t *keyBytes;
    int keyLen;

    v_U8_t text[AAG_PTK_PRF_TEXT_LEN];

    
    if (vos_mem_compare2(authAddr, suppAddr, sizeof(tAniMacAddr)) < 0) {
        lowMac = authAddr;
        highMac = suppAddr;
    } else {
        lowMac = suppAddr;
        highMac = authAddr;
    }

    if (vos_mem_compare2(aNonce, sNonce, ANI_EAPOL_KEY_RSN_NONCE_SIZE) < 0) {
        lowNonce = aNonce;
        highNonce = sNonce;
    } else {
        lowNonce = sNonce;
        highNonce = aNonce;
    }

    vos_mem_copy(text + AAG_PTK_PRF_LM_POS, lowMac, sizeof(tAniMacAddr));
    vos_mem_copy(text + AAG_PTK_PRF_HM_POS, highMac, sizeof(tAniMacAddr));
    vos_mem_copy(text + AAG_PTK_PRF_LN_POS, lowNonce, ANI_EAPOL_KEY_RSN_NONCE_SIZE);
    vos_mem_copy(text + AAG_PTK_PRF_HN_POS, highNonce, ANI_EAPOL_KEY_RSN_NONCE_SIZE);

    keyLen = aniAsfPacketGetBytes(pmk, &keyBytes);
    if( !ANI_IS_STATUS_SUCCESS( keyLen ) )
    {
        return keyLen;
    }

    return aagPrf(cryptHandle,
                  result, 
                  keyBytes, keyLen, 
                  (v_U8_t *)AAG_PTK_PRF_CONST, AAG_PTK_PRF_CONST_LEN,
                  text, sizeof(text),
                  prfLen);
}
/**
 * aniSsmReplayCtrCmp
 *
 * Used to check if the passed in value is greater
 * than, less than, or the same as the previous value. 
 *
 * Can be used on the TX side to determine if the response to a
 * request contains the same counter as the one in the request.
 *
 * Can be used on the RX side to determine if the request has a
 * counter greater than the previous request, or if this is a
 * retransmission of the previous request. The application should
 * special-case the first time this is called on the RX side.
 *
 * @param ctr the current replay counter
 * @param value the value to check against
 *
 * @return a negative value if current ctr is less than the
 * given value, zero if they are the same, and a positive value if the
 * current counter is greater than that of the given value.
 */
int
aniSsmReplayCtrCmp(tAniSsmReplayCtr *ctr, v_U8_t *value)
{
    return vos_mem_compare2(ctr->buf, value, ctr->size);
}
/**
 * Implements the AES Key Unwrap algorithm described in RFC 3394.
 * If (n+1) is the number of blocks in cipherText, of size
 * ANI_SSM_AES_KEY_WRAP_BLOCK_SIZE, then the output value is (n+1)
 * blocks. The actual plaintext consists of n blocks that start at the
 * second block. Note: It is the caller's responsibility to free the
 * returned value.
 *
 * @param cipherText the cipertext data to unwrap
 * @param len the length of the ciphertext, which must be a multiple of
 * ANI_SSM_AES_KEY_WRAP_BLOCK_SIZE.
 * @param keyEncKey the encryption key
 * @param keyEncKeyLen the length of keyEncKey
 * @param plainTextPtr is set to a newly allocated array containing
 * the result if the operation succeeds. It is the caller's
 * responsibility to free this.
 *
 * @return ANI_OK if the operation succeeds
 */
int
aniSsmAesKeyUnwrap(v_U32_t cryptHandle, tANI_U8 *cipherText, tANI_U32 len,
                   tANI_U8 *keyEncKey, tANI_U32 keyEncKeyLen,
                   tANI_U8 **plainTextPtr)
{
    int i, j;
    int retVal;

    tANI_U8 a[ANI_SSM_AES_KEY_WRAP_BLOCK_SIZE];
    tANI_U8 *r = NULL;
    tANI_U32 n;
    tANI_U32 t;

    tANI_U8 b[ANI_SSM_AES_KEY_WRAP_BLOCK_SIZE*2];

    n = len / ANI_SSM_AES_KEY_WRAP_BLOCK_SIZE - 1;
    if ((len % ANI_SSM_AES_KEY_WRAP_BLOCK_SIZE) != 0) {
        VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
                   "Illegal number of input bytes to AES Key Unwrap!");
        return ANI_E_ILLEGAL_ARG;
    }

    // Allocate enough storage for 'A' as well as 'R'
    r = vos_mem_malloc((n + 1) *  ANI_SSM_AES_KEY_WRAP_BLOCK_SIZE);
    if (r == NULL) {
        VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
                   "Could not allocate space for R");
        return ANI_E_MALLOC_FAILED;
    }

    vos_mem_copy(a, cipherText, sizeof(a));
    vos_mem_copy(r + ANI_SSM_AES_KEY_WRAP_BLOCK_SIZE,
           cipherText + ANI_SSM_AES_KEY_WRAP_BLOCK_SIZE,
           len - ANI_SSM_AES_KEY_WRAP_BLOCK_SIZE);

    for (j = 5; j >= 0; j--) {
        for (i = n; i >= 1; i--) {

            t = n*j + i;
            xor(a, t);
            retVal = aes_1(cryptHandle, keyEncKey, keyEncKeyLen,
                           a,
                           r + i*ANI_SSM_AES_KEY_WRAP_BLOCK_SIZE,
                           b);
           if( !ANI_IS_STATUS_SUCCESS( retVal) ) goto error;

            vos_mem_copy(a, b, ANI_SSM_AES_KEY_WRAP_BLOCK_SIZE);
            vos_mem_copy(r + i*ANI_SSM_AES_KEY_WRAP_BLOCK_SIZE,
                   b + sizeof(b) - ANI_SSM_AES_KEY_WRAP_BLOCK_SIZE,
                   ANI_SSM_AES_KEY_WRAP_BLOCK_SIZE);
        }
    }

    if (vos_mem_compare2(a, gAniSsmAesKeyWrapIv, ANI_SSM_AES_KEY_WRAP_BLOCK_SIZE) != 0) {
        retVal = ANI_E_MIC_FAILED;
        goto error;
    }

    *plainTextPtr = r;

    return ANI_OK;

 error:
    if (r != NULL)
        vos_mem_free(r);

    return retVal;
}