#include "dk_cmd_external_authenticate.h"

DK_Result external_authenticate(scp_context* ctx, byte* apdu, size_t* apdu_len, byte* wrapped_apdu, size_t* wrapped_apdu_len, byte cla) {
    int rc = gen_apdu_scp_03_external_authenticate(ctx, apdu, apdu_len, wrapped_apdu, wrapped_apdu_len, cla);
    
    return rc;
}

DK_Result gen_apdu_scp_03_external_authenticate(scp_context* ctx, byte* apdu, size_t* apdu_len, byte* wrapped_apdu, size_t* wrapped_apdu_len, byte cla) {
    if (cla < (byte) 0x84 || cla > (byte) 0x87) {
        return DK_ERROR_GENERIC;
    }
    if (!ctx) {
        return DK_ERROR_GENERIC;
    }

    byte curr_seclevel = ctx->security_level;
    if (curr_seclevel != SCP03_SEC_C_DECRYPTION_R_ENCRYPTION_C_MAC_R_MAC &&
        curr_seclevel != SCP03_SEC_C_DECRYPTION_C_MAC_R_MAC &&
        curr_seclevel != SCP03_SEC_C_MAC_R_RMAC &&
        curr_seclevel != SCP03_SEC_C_DECRYPTION_C_MAC &&
        curr_seclevel != SCP03_SEC_C_MAC &&
        curr_seclevel != SCP03_SEC_NO_SECURITY_LEVEL) {
            return DK_ERROR_GENERIC;
    }
    // if ((curr_seclevel == SCP_SEC_C_DECRYPTION_R_ENCRYPTION_C_MAC_R_MAC) ||
    //         (curr_seclevel == SCP_SEC_C_DECRYPTION_C_MAC_R_MAC) ||
    //         (curr_seclevel == SCP_SEC_C_MAC_R_RMAC)) {

        // TODO: depends on how is it going to be set in initialize update
        // byte[] keyInfo = getKeyInformation();

        // if (keyInfo[INDEX_i_BITMAP] == byteI_NO_R_MAC_R_ENCRYPTION) {
        //     return DK_ERROR_GENERIC;
        // }
        // if (keyInfo[INDEX_i_BITMAP] == byteI_R_MAC_NO_R_ENCRYPTION) {
        //     return DK_ERROR_GENERIC;
        // }
    // }
    if (!apdu) {
        return DK_ERROR_GENERIC;
    }

    apdu[APDU_OFFSET_CLA] = cla;
    apdu[APDU_OFFSET_INS] = SCP03_EXT_AUTHENTICATE_INS;
    apdu[APDU_OFFSET_P1] = curr_seclevel;
    apdu[APDU_OFFSET_P2] = SCP03_EXT_AUTHENTICATE_P2;
    apdu[APDU_OFFSET_LC] = SCP03_EXT_AUTHENTICATE_LC;
    dk_memcpy(apdu + APDU_OFFSET_CDATA, ctx->host_cryptogram, CRYPTOGRAM_SIZE);
    *apdu_len = APDU_OFFSET_CDATA + CRYPTOGRAM_SIZE;

    // we need to do this because we are not authenticated yet and this is the first MAC generation
    if (is_cmac_on(ctx->security_level)) {
        int rc = scp_generate_apdu_cmac(ctx, apdu, *apdu_len, wrapped_apdu, wrapped_apdu_len);
        return rc;
    }
    dk_memcpy(wrapped_apdu, apdu, *apdu_len);
    *wrapped_apdu_len = *apdu_len;

    return DK_SUCCESS;
}

DK_Result handle_external_authenticate_rpdu(byte* rpdu, size_t* rpdu_len) {
    byte sw[APDU_SW_SIZE] = {0};
    sw[APDU_OFFSET_SW1] = rpdu[*rpdu_len - 2];
    sw[APDU_OFFSET_SW2] = rpdu[*rpdu_len - 1];

    if ((sw[APDU_OFFSET_SW1] << 8 | sw[APDU_OFFSET_SW2]) != RPDU_STATUS_SUCCESS) {
        DK_LOG_ERR("error after transmit()");
        return DK_ERROR_GENERIC;
    }
    
    return DK_SUCCESS;
}