Beispiel #1
0
static void setup_cmd_rsp_buffers(struct qseecom_handle *handle, void **cmd,
		int *cmd_len, void **resp, int *resp_len)
{
	*cmd = handle->sbuf;
	if (*cmd_len & QSEECOM_ALIGN_MASK)
		*cmd_len = QSEECOM_ALIGN(*cmd_len);

	*resp = handle->sbuf + *cmd_len;
	if (*resp_len & QSEECOM_ALIGN_MASK)
		*resp_len = QSEECOM_ALIGN(*resp_len);
}
int derive_keys_from_session_key(struct qcom_wv_handle* handle, int ctx_id,
                                 uint32_t enc_session_key_length,
                                 uint32_t mac_key_context_length,
                                 uint32_t enc_key_context_length) {

    //Initializing the request and response buffers
    uint32_t cmd_req_size = QSEECOM_ALIGN(61460);
    uint32_t cmd_resp_size = QSEECOM_ALIGN(8);
    uint32_t* cmd_req = malloc(cmd_req_size);
    uint32_t* cmd_resp = malloc(cmd_resp_size);
    memset(cmd_req, 0, cmd_req_size);
    memset(cmd_resp, 0, cmd_resp_size);

    cmd_req[0] = OEMCrypto_DeriveKeysFromSessionKey;
    cmd_req[1] = ctx_id;                                       //ctxId
    cmd_req[0x5008/sizeof(uint32_t)] = enc_session_key_length; //enc_session_key_length
    cmd_req[0xA00C/sizeof(uint32_t)] = mac_key_context_length; //mac_key_context_length
    cmd_req[0xF010/sizeof(uint32_t)] = enc_key_context_length; //enc_key_context_length

    int res = (*handle->QSEECom_set_bandwidth)(handle->qseecom, true);
    if (res < 0) {
        free(cmd_req);
        free(cmd_resp);
        perror("[-] Unable to enable clks");
        return -errno;
    }
    
    res = (*handle->QSEECom_send_cmd)(handle->qseecom,
                                      cmd_req,
                                      cmd_req_size,
                                      cmd_resp,
                                      cmd_resp_size);

    if ((*handle->QSEECom_set_bandwidth)(handle->qseecom, false)) {
        perror("[-] Import key command: (unable to disable clks)");
    }
    
    res = (int)cmd_resp[1];

    free(cmd_req);
    free(cmd_resp);
    
    return res;

}
int generate_nonce(struct qcom_wv_handle* handle, int ctx_id, uint32_t* nonce) {
    
    //Initializing the request and response buffers
    uint32_t cmd_req_size = QSEECOM_ALIGN(0x8);
    uint32_t cmd_resp_size = QSEECOM_ALIGN(0xC);
    uint32_t* cmd_req = malloc(cmd_req_size);
    uint32_t* cmd_resp = malloc(cmd_resp_size);
    memset(cmd_req, 0, cmd_req_size);
    memset(cmd_resp, 0, cmd_resp_size);

    cmd_req[0] = OEMCrypto_GenerateNonce;
    cmd_req[1] = ctx_id;

    int res = (*handle->QSEECom_set_bandwidth)(handle->qseecom, true);
    if (res < 0) {
        free(cmd_req);
        free(cmd_resp);
        perror("[-] Unable to enable clks");
        return -errno;
    }

    res = (*handle->QSEECom_send_cmd)(handle->qseecom,
                                      cmd_req,
                                      cmd_req_size,
                                      cmd_resp,
                                      cmd_resp_size);

    if ((*handle->QSEECom_set_bandwidth)(handle->qseecom, false)) {
        perror("[-] Import key command: (unable to disable clks)");
    }

    res = (int)cmd_resp[2];
    *nonce = cmd_resp[1];

    free(cmd_req);
    free(cmd_resp);

    return res;

}
int send_cmd_1026(struct qcom_wv_handle* handle) {
    
    //Initializing the request and response buffers
    uint32_t cmd_req_size = QSEECOM_ALIGN(4);
    uint32_t cmd_resp_size = QSEECOM_ALIGN(0xC);
    uint32_t* cmd_req = malloc(cmd_req_size);
    uint32_t* cmd_resp = malloc(cmd_resp_size);
    memset(cmd_req, 0, cmd_req_size);
    memset(cmd_resp, 0, cmd_resp_size);

    cmd_req[0] = 1026;

    int res = (*handle->QSEECom_set_bandwidth)(handle->qseecom, true);
    if (res < 0) {
        free(cmd_req);
        free(cmd_resp);
        perror("[-] Unable to enable clks");
        return -errno;
    }

    res = (*handle->QSEECom_send_cmd)(handle->qseecom,
                                      cmd_req,
                                      cmd_req_size,
                                      cmd_resp,
                                      cmd_resp_size);

    if ((*handle->QSEECom_set_bandwidth)(handle->qseecom, false)) {
        perror("[-] Import key command: (unable to disable clks)");
    }

    res = (int)cmd_resp[1];

    free(cmd_req);
    free(cmd_resp);

    return res;

}
int close_session(struct qcom_wv_handle* handle, int ctx_id) {

    //Initializing the request and response buffers
    uint32_t cmd_req_size = QSEECOM_ALIGN(8);
    uint32_t cmd_resp_size = QSEECOM_ALIGN(8);
    uint32_t* cmd_req = malloc(cmd_req_size);
    uint32_t* cmd_resp = malloc(cmd_resp_size);
    memset(cmd_req, 0, cmd_req_size);
    memset(cmd_resp, 0, cmd_resp_size);

    //Filling in the data in the request buffer
    cmd_req[0] = OEMCrypto_CloseSession;
    cmd_req[1] = ctx_id;  //ctxId

    int res = (*handle->QSEECom_set_bandwidth)(handle->qseecom, true);
    if (res < 0) {
        free(cmd_req);
        free(cmd_resp);
        perror("[-] Unable to enable clks");
        return -errno;
    }
    
    res = (*handle->QSEECom_send_cmd)(handle->qseecom,
                                      cmd_req,
                                      cmd_req_size,
                                      cmd_resp,
                                      cmd_resp_size);

    if ((*handle->QSEECom_set_bandwidth)(handle->qseecom, false)) {
        perror("[-] Import key command: (unable to disable clks)");
    }
    
    free(cmd_req);
    free(cmd_resp);
    return res;

}
static int qcom_km_verify_data(const keymaster_device_t* dev,
        const void* params,
        const uint8_t* keyBlob, const size_t keyBlobLength,
        const uint8_t* signedData, const size_t signedDataLength,
        const uint8_t* signature, const size_t signatureLength)
{
    if (dev->context == NULL) {
        ALOGE("qcom_km_verify_data: Context  == NULL");
        return -1;
    }

    if (signedData == NULL || signature == NULL) {
        ALOGE("data or signature buffers == NULL");
        return -1;
    }

    keymaster_rsa_sign_params_t* sign_params = (keymaster_rsa_sign_params_t*) params;
    if (sign_params->digest_type != DIGEST_NONE) {
        ALOGE("Cannot handle digest type %d", sign_params->digest_type);
        return -1;
    } else if (sign_params->padding_type != PADDING_NONE) {
        ALOGE("Cannot handle padding type %d", sign_params->padding_type);
        return -1;
    } else if (signatureLength != signedDataLength) {
        ALOGE("signed data length must be signature length");
        return -1;
    }

    struct QSEECom_handle *handle = NULL;
    keymaster_verify_data_cmd_t *send_cmd = NULL;
    keymaster_verify_data_resp_t  *resp = NULL;

    struct QSEECom_ion_fd_info  ion_fd_info;
    struct qcom_km_ion_info_t ihandle;
    struct qcom_keymaster_handle *km_handle =(struct qcom_keymaster_handle *)dev->context;
    int ret = 0;

    handle = (struct QSEECom_handle *)(km_handle->qseecom);
    ihandle.ion_fd = 0;
    ihandle.ion_alloc_handle.handle = NULL;
    if (qcom_km_ION_memalloc(&ihandle, signedDataLength + signatureLength) <0) {
        ALOGE("ION allocation  failed");
        return -1;
    }
    memset(&ion_fd_info, 0, sizeof(struct QSEECom_ion_fd_info));

    /* Populate the send data structure */
    ion_fd_info.data[0].fd = ihandle.ifd_data_fd;
    ion_fd_info.data[0].cmd_buf_offset = sizeof(enum keymaster_cmd_t) +
        sizeof(qcom_km_key_blob_t ) + sizeof(keymaster_rsa_sign_params_t);

    send_cmd = (keymaster_verify_data_cmd_t *)handle->ion_sbuffer;
    resp = (keymaster_verify_data_resp_t *)((char *)handle->ion_sbuffer +
                               sizeof(keymaster_verify_data_cmd_t));
    send_cmd->cmd_id = KEYMASTER_VERIFY_DATA ;
    send_cmd->sign_param.digest_type = sign_params->digest_type;
    send_cmd->sign_param.padding_type = sign_params->padding_type;
    memcpy((unsigned char *)(&send_cmd->key_blob), keyBlob, keyBlobLength);

    send_cmd->signed_data = (uint32_t)ihandle.ion_sbuffer;
    send_cmd->signed_dlen = signedDataLength;
    memcpy((unsigned char *)ihandle.ion_sbuffer, signedData, signedDataLength);

    send_cmd->signature = signedDataLength;
    send_cmd->slen = signatureLength;
    memcpy(((unsigned char *)ihandle.ion_sbuffer + signedDataLength),
                                  signature, signatureLength);
    resp->status = KEYMASTER_FAILURE;

    ret = (*km_handle->QSEECom_set_bandwidth)(handle, true);
    if (ret < 0) {
        ALOGE("Verify data  command failed (unable to enable clks) ret =%d", ret);
        qcom_km_ion_dealloc(&ihandle);
        return -1;
    }

    ret = (*km_handle->QSEECom_send_modified_cmd)(handle, send_cmd,
                               QSEECOM_ALIGN(sizeof(*send_cmd)), resp,
                               QSEECOM_ALIGN(sizeof(*resp)), &ion_fd_info);

    if((*km_handle->QSEECom_set_bandwidth)(handle, false))
        ALOGE("Verify data  command: (unable to disable clks)");

    if ( (ret < 0)  ||  (resp->status  < 0)) {
        ALOGE("Verify data command failed resp->status = %d ret =%d", resp->status, ret);
        qcom_km_ion_dealloc(&ihandle);
        return -1;
    }
    qcom_km_ion_dealloc(&ihandle);
    return 0;
}
static int qcom_km_sign_data(const keymaster_device_t* dev,
        const void* params,
        const uint8_t* keyBlob, const size_t keyBlobLength,
        const uint8_t* data, const size_t dataLength,
        uint8_t** signedData, size_t* signedDataLength)
{
    if (dev->context == NULL) {
        ALOGE("qcom_km_sign_data: Context  == NULL");
        return -1;
    }
    if (dataLength > KM_KEY_SIZE_MAX) {
        ALOGE("Input data to be signed is too long %d bytes", dataLength);
        return -1;
    }
    if (data == NULL) {
        ALOGE("input data to sign == NULL");
        return -1;
    } else if (signedData == NULL || signedDataLength == NULL) {
        ALOGE("Output signature buffer == NULL");
        return -1;
    }
    keymaster_rsa_sign_params_t* sign_params = (keymaster_rsa_sign_params_t*) params;
    if (sign_params->digest_type != DIGEST_NONE) {
        ALOGE("Cannot handle digest type %d", sign_params->digest_type);
        return -1;
    } else if (sign_params->padding_type != PADDING_NONE) {
        ALOGE("Cannot handle padding type %d", sign_params->padding_type);
        return -1;
    }

    struct QSEECom_handle *handle = NULL;
    keymaster_sign_data_cmd_t *send_cmd = NULL;
    keymaster_sign_data_resp_t  *resp = NULL;
    struct QSEECom_ion_fd_info  ion_fd_info;
    struct qcom_km_ion_info_t ihandle;
    struct qcom_keymaster_handle *km_handle =(struct qcom_keymaster_handle *)dev->context;
    int ret = 0;

    handle = (struct QSEECom_handle *)(km_handle->qseecom);
    ihandle.ion_fd = 0;
    ihandle.ion_alloc_handle.handle = NULL;
    if (qcom_km_ION_memalloc(&ihandle, dataLength) < 0) {
        ALOGE("ION allocation  failed");
        return -1;
    }
    memset(&ion_fd_info, 0, sizeof(struct QSEECom_ion_fd_info));

    /* Populate the send data structure */
    ion_fd_info.data[0].fd = ihandle.ifd_data_fd;
    ion_fd_info.data[0].cmd_buf_offset = sizeof(enum keymaster_cmd_t) +
         sizeof(qcom_km_key_blob_t) + sizeof(keymaster_rsa_sign_params_t);

    send_cmd = (keymaster_sign_data_cmd_t *)handle->ion_sbuffer;
    resp = (keymaster_sign_data_resp_t *)(handle->ion_sbuffer +
                            QSEECOM_ALIGN(sizeof(keymaster_sign_data_cmd_t)));
    send_cmd->cmd_id = KEYMASTER_SIGN_DATA ;
    send_cmd->sign_param.digest_type = sign_params->digest_type;
    send_cmd->sign_param.padding_type = sign_params->padding_type;
    memcpy((unsigned char *)(&send_cmd->key_blob), keyBlob, keyBlobLength);
    memcpy((unsigned char *)ihandle.ion_sbuffer, data, dataLength);

    send_cmd->data = (uint32_t)ihandle.ion_sbuffer;
    send_cmd->dlen = dataLength;
    resp->sig_len = KM_KEY_SIZE_MAX;
    resp->status = KEYMASTER_FAILURE;

    ret = (*km_handle->QSEECom_set_bandwidth)(handle, true);
    if (ret < 0) {
        ALOGE("Sign data command failed (unable to enable clks) ret =%d", ret);
        qcom_km_ion_dealloc(&ihandle);
        return -1;
    }

    ret = (*km_handle->QSEECom_send_modified_cmd)(handle, send_cmd,
                               QSEECOM_ALIGN(sizeof(*send_cmd)), resp,
                               QSEECOM_ALIGN(sizeof(*resp)), &ion_fd_info);

    if((*km_handle->QSEECom_set_bandwidth)(handle, false))
        ALOGE("Sign data command: (unable to disable clks)");

    if ( (ret < 0)  ||  (resp->status  < 0)) {
        ALOGE("Sign data command failed resp->status = %d ret =%d", resp->status, ret);
        qcom_km_ion_dealloc(&ihandle);
        return -1;
    } else {
        UniquePtr<uint8_t> signedDataPtr(reinterpret_cast<uint8_t*>(malloc(resp->sig_len)));
        if (signedDataPtr.get() == NULL) {
            ALOGE("Sign data memory allocation failed");
            qcom_km_ion_dealloc(&ihandle);
            return -1;
        }
        unsigned char* p = signedDataPtr.get();
        memcpy(p, (unsigned char *)(&resp->signed_data), resp->sig_len);

        *signedDataLength = resp->sig_len;
        *signedData = signedDataPtr.release();
    }
    qcom_km_ion_dealloc(&ihandle);
    return 0;
}
static int qcom_km_import_keypair(const keymaster_device_t* dev,
        const uint8_t* key, const size_t key_length,
        uint8_t** keyBlob, size_t* keyBlobLength)
{
    if (dev->context == NULL) {
        ALOGE("qcom_km_import_keypair: Context  == NULL");
        return -1;
    }

    if (key == NULL) {
        ALOGE("Input key == NULL");
        return -1;
    } else if (keyBlob == NULL || keyBlobLength == NULL) {
        ALOGE("Output key blob or length == NULL");
        return -1;
    }

    struct QSEECom_ion_fd_info  ion_fd_info;
    struct qcom_km_ion_info_t ihandle;
    int ret = 0;

    ihandle.ion_fd = 0;
    ihandle.ion_alloc_handle.handle = NULL;
    if (qcom_km_ION_memalloc(&ihandle, QSEECOM_ALIGN(key_length)) < 0) {
        ALOGE("ION allocation  failed");
        return -1;
    }
    memset(&ion_fd_info, 0, sizeof(struct QSEECom_ion_fd_info));

    /* Populate the send data structure */
    ion_fd_info.data[0].fd = ihandle.ifd_data_fd;
    ion_fd_info.data[0].cmd_buf_offset = sizeof(enum keymaster_cmd_t);


    struct QSEECom_handle *handle = NULL;
    keymaster_import_keypair_cmd_t *send_cmd = NULL;
    keymaster_import_keypair_resp_t  *resp = NULL;
    struct qcom_keymaster_handle *km_handle =(struct qcom_keymaster_handle *)dev->context;

    handle = (struct QSEECom_handle *)(km_handle->qseecom);
    send_cmd = (keymaster_import_keypair_cmd_t *)handle->ion_sbuffer;
    resp = (keymaster_import_keypair_resp_t *)(handle->ion_sbuffer +
                                        QSEECOM_ALIGN(sizeof(keymaster_import_keypair_cmd_t)));
    send_cmd->cmd_id = KEYMASTER_IMPORT_KEYPAIR;
    send_cmd->pkcs8_key = (uint32_t)ihandle.ion_sbuffer;

    memcpy((unsigned char *)ihandle.ion_sbuffer, key, key_length);

    send_cmd->pkcs8_key_len = key_length;
    resp->status = KEYMASTER_FAILURE;
    resp->key_blob_len =  sizeof(qcom_km_key_blob_t);

    ret = (*km_handle->QSEECom_set_bandwidth)(handle, true);
    if (ret < 0) {
        ALOGE("Import key command failed (unable to enable clks) ret =%d", ret);
        qcom_km_ion_dealloc(&ihandle);
        return -1;
    }
    ret = (*km_handle->QSEECom_send_modified_cmd)(handle, send_cmd,
                               QSEECOM_ALIGN(sizeof(*send_cmd)), resp,
                               QSEECOM_ALIGN(sizeof(*resp)), &ion_fd_info);

    if((*km_handle->QSEECom_set_bandwidth)(handle, false))
        ALOGE("Import key command: (unable to disable clks)");

    if ( (ret < 0)  ||  (resp->status  < 0)) {
        ALOGE("Import key command failed resp->status = %d ret =%d", resp->status, ret);
        qcom_km_ion_dealloc(&ihandle);
        return -1;
    } else {
        UniquePtr<unsigned char[]> keydata(new unsigned char[resp->key_blob_len]);
        if (keydata.get() == NULL) {
            ALOGE("could not allocate memory for key blob");
            return -1;
        }
        unsigned char* p = keydata.get();
        memcpy(p, (unsigned char *)(&resp->key_blob), resp->key_blob_len);
        *keyBlob = keydata.release();
        *keyBlobLength = resp->key_blob_len;

    }
    qcom_km_ion_dealloc(&ihandle);
    return 0;
}
static int qcom_km_generate_keypair(const keymaster_device_t* dev,
        const keymaster_keypair_t key_type, const void* key_params,
        uint8_t** keyBlob, size_t* keyBlobLength) {

    if (dev->context == NULL) {
        ALOGE("qcom_km_generate_keypair: Context == NULL");
        return -1;
    }

    if (key_type != TYPE_RSA) {
        ALOGE("Unsupported key type %d", key_type);
        return -1;
    } else if (key_params == NULL) {
        ALOGE("key_params == null");
        return -1;
    }
    if (keyBlob == NULL || keyBlobLength == NULL) {
        ALOGE("output key blob or length == NULL");
        return -1;
    }
    keymaster_rsa_keygen_params_t* rsa_params = (keymaster_rsa_keygen_params_t*) key_params;

    keymaster_gen_keypair_cmd_t *send_cmd = NULL;
    keymaster_gen_keypair_resp_t  *resp = NULL;
    struct QSEECom_handle *handle = NULL;
    struct qcom_keymaster_handle *km_handle =(struct qcom_keymaster_handle *)dev->context;
    int ret = 0;

    handle = (struct QSEECom_handle *)(km_handle->qseecom);
    send_cmd = (keymaster_gen_keypair_cmd_t *)handle->ion_sbuffer;
    resp = (keymaster_gen_keypair_resp_t *)(handle->ion_sbuffer +
                               QSEECOM_ALIGN(sizeof(keymaster_gen_keypair_cmd_t)));
    send_cmd->cmd_id = KEYMASTER_GENERATE_KEYPAIR;
    send_cmd->key_type = key_type;
    send_cmd->rsa_params.modulus_size = rsa_params->modulus_size;
    send_cmd->rsa_params.public_exponent = rsa_params->public_exponent;
    resp->status = KEYMASTER_FAILURE;
    resp->key_blob_len =  sizeof(qcom_km_key_blob_t);

    ret = (*km_handle->QSEECom_set_bandwidth)(handle, true);
    if (ret < 0) {
        ALOGE("Generate key command failed (unable to enable clks) ret =%d", ret);
        return -1;
    }

    ret = (*km_handle->QSEECom_send_cmd)(handle, send_cmd,
                               QSEECOM_ALIGN(sizeof(keymaster_gen_keypair_cmd_t)), resp,
                               QSEECOM_ALIGN(sizeof(keymaster_gen_keypair_resp_t)));

    if((*km_handle->QSEECom_set_bandwidth)(handle, false))
        ALOGE("Import key command: (unable to disable clks)");

    if ( (ret < 0)  ||  (resp->status  < 0)) {
        ALOGE("Generate key command failed resp->status = %d ret =%d", resp->status, ret);
        return -1;
    } else {
        UniquePtr<unsigned char[]> keydata(new unsigned char[resp->key_blob_len]);
        if (keydata.get() == NULL) {
            ALOGE("could not allocate memory for key blob");
            return -1;
        }
        unsigned char* p = keydata.get();
        memcpy(p, (unsigned char *)(&resp->key_blob), resp->key_blob_len);
        *keyBlob = keydata.release();
        *keyBlobLength = resp->key_blob_len;
    }
    return 0;
}