incubator-nuttx/drivers/crypto/pnt/pnt_se05x_api.c

345 lines
11 KiB
C

/****************************************************************************
* drivers/crypto/pnt/pnt_se05x_api.c
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
/* Copyright 2023 NXP */
/****************************************************************************
* Included Files
****************************************************************************/
#include "pnt_se05x_api.h"
#include "../se05x_internal.h"
#include "pnt_util.h"
#include "scp03_keys.h"
#include <nuttx/kmalloc.h>
#include <phNxpEse_Internal.h>
#include <se05x_APDU_apis.h>
#include <smCom.h>
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#define SCP03_KEY_SIZE 16
#define DATA_CHUNK_SIZE 100
/****************************************************************************
* Private Types
****************************************************************************/
struct pnt_handle
{
Se05xSession_t session;
};
/****************************************************************************
* Private Data
****************************************************************************/
static const SE05x_ECSignatureAlgo_t
signature_algorithm_mapping[SE05X_ALGORITHM_SIZE] =
{
kSE05x_ECSignatureAlgo_NA, kSE05x_ECSignatureAlgo_PLAIN,
kSE05x_ECSignatureAlgo_SHA, kSE05x_ECSignatureAlgo_SHA_224,
kSE05x_ECSignatureAlgo_SHA_256, kSE05x_ECSignatureAlgo_SHA_384,
kSE05x_ECSignatureAlgo_SHA_512
};
static const uint8_t scp03_enc_key[SCP03_KEY_SIZE] = SCP03_ENC_KEY;
static const uint8_t scp03_mac_key[SCP03_KEY_SIZE] = SCP03_MAC_KEY;
static const uint8_t scp03_dek_key[SCP03_KEY_SIZE] = SCP03_DEK_KEY;
/****************************************************************************
* Private Functions
****************************************************************************/
static bool set_enable_pin(FAR struct se05x_dev_s *se05x, bool state)
{
if (se05x->config->set_enable_pin == NULL)
{
return FALSE;
}
return se05x->config->set_enable_pin(state);
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Public Functions
****************************************************************************/
int pnt_se05x_open(FAR struct se05x_dev_s *se05x)
{
se05x->pnt = kmm_malloc(sizeof(struct pnt_handle));
int ret = se05x->pnt != NULL ? 0 : -EIO;
if (ret == 0)
{
memset(&(se05x->pnt->session), 0, sizeof(Se05xSession_t));
se05x->pnt->session.pScp03_enc_key = (FAR uint8_t *)scp03_enc_key;
se05x->pnt->session.pScp03_mac_key = (FAR uint8_t *)scp03_mac_key;
se05x->pnt->session.pScp03_dek_key = (FAR uint8_t *)scp03_dek_key;
se05x->pnt->session.scp03_enc_key_len = SCP03_KEY_SIZE;
se05x->pnt->session.scp03_mac_key_len = SCP03_KEY_SIZE;
se05x->pnt->session.scp03_dek_key_len = SCP03_KEY_SIZE;
ret = set_enable_pin(se05x, true) ? 0 : -EIO;
}
if (ret == 0)
{
se05x->pnt->session.skip_applet_select = 0;
se05x->pnt->session.session_resume = 0;
smStatus_t status =
Se05x_API_SessionOpen(&(se05x->pnt->session), se05x);
ret = status == SM_OK ? 0 : -EIO;
}
/* if error */
if (ret < 0)
{
if (se05x->pnt->session.conn_context != NULL)
{
kmm_free(se05x->pnt->session.conn_context);
}
if (se05x->pnt != NULL)
{
kmm_free(se05x->pnt);
}
}
return ret;
}
void pnt_se05x_close(FAR struct se05x_dev_s *se05x)
{
Se05x_API_SessionClose(&(se05x->pnt->session));
(void)set_enable_pin(se05x, FALSE);
kmm_free(se05x->pnt);
}
int pnt_se05x_get_info(FAR struct se05x_dev_s *se05x,
FAR struct se05x_info_s *se05x_info)
{
bool result = select_card_manager(&(se05x->pnt->session));
identify_rsp_t identify_response;
if (result)
{
result = se05x_identify(&(se05x->pnt->session), &identify_response);
}
if (result)
{
se05x_info->oef_id = (identify_response.configuration_id[2] << 8) +
identify_response.configuration_id[3];
}
return result ? 0 : -EIO;
}
int pnt_se05x_get_uid(FAR struct se05x_dev_s *se05x,
FAR struct se05x_uid_s *uid)
{
SE05x_Result_t dummy = kSE05x_Result_NA;
size_t uid_size = SE050_MODULE_UNIQUE_ID_LEN;
smStatus_t status = Se05x_API_CheckObjectExists(
&(se05x->pnt->session), KSE05X_APPLETRESID_UNIQUE_ID, &dummy);
int result = status == SM_OK ? 0 : -ENODATA;
if (result == 0)
{
status = Se05x_API_ReadObject(&(se05x->pnt->session),
KSE05X_APPLETRESID_UNIQUE_ID, 0,
(uint16_t)uid_size, uid->uid, &uid_size);
result = status == SM_OK ? 0 : -EIO;
}
return result;
}
int pnt_se05x_generate_keypair(
FAR struct se05x_dev_s *se05x,
FAR struct se05x_generate_keypair_s *generate_keypair_args)
{
smStatus_t status = Se05x_API_WriteECKey(
&(se05x->pnt->session), NULL, 0, generate_keypair_args->id,
kSE05x_ECCurve_NIST_P256, NULL, 0, NULL, 0, kSE05x_INS_NA,
kSE05x_KeyPart_Pair);
return status == SM_OK ? 0 : -EIO;
}
int pnt_se05x_set_public_key(
FAR struct se05x_dev_s *se05x,
FAR struct se05x_key_transmission_s *set_publickey_args)
{
smStatus_t status = Se05x_API_WriteECKey(
&(se05x->pnt->session), NULL, 0, set_publickey_args->entry.id,
kSE05x_ECCurve_NIST_P256, NULL, 0, set_publickey_args->content.buffer,
set_publickey_args->content.buffer_size, kSE05x_INS_NA,
kSE05x_KeyPart_Public);
return status == SM_OK ? 0 : -EIO;
}
int pnt_se05x_set_data(
FAR struct se05x_dev_s *se05x,
FAR struct se05x_key_transmission_s *set_publickey_args)
{
size_t remainder = set_publickey_args->content.buffer_size;
smStatus_t status = SM_OK;
uint16_t offset = 0;
bool first_cycle = TRUE;
while ((remainder > 0) && (status == SM_OK))
{
size_t chunk_size =
remainder > DATA_CHUNK_SIZE ? DATA_CHUNK_SIZE : remainder;
status = Se05x_API_WriteBinary(
&(se05x->pnt->session), NULL, set_publickey_args->entry.id, offset,
first_cycle ? set_publickey_args->content.buffer_size : 0,
set_publickey_args->content.buffer + offset, chunk_size);
remainder -= chunk_size;
offset += chunk_size;
first_cycle = FALSE;
}
return status == SM_OK ? 0 : -EIO;
}
int pnt_se05x_get_key(FAR struct se05x_dev_s *se05x,
FAR struct se05x_key_transmission_s *get_key_args)
{
get_key_args->content.buffer_content_size =
get_key_args->content.buffer_size;
smStatus_t status =
Se05x_API_ReadObject(&(se05x->pnt->session), get_key_args->entry.id, 0,
0, get_key_args->content.buffer,
&get_key_args->content.buffer_content_size);
return status == SM_OK ? 0 : -EIO;
}
int pnt_se05x_get_data(FAR struct se05x_dev_s *se05x,
FAR struct se05x_key_transmission_s *get_key_args)
{
uint16_t remainder;
smStatus_t status = Se05x_API_ReadSize(&(se05x->pnt->session),
get_key_args->entry.id, &remainder);
if (remainder > get_key_args->content.buffer_size)
{
status = SM_NOT_OK;
}
uint16_t offset = 0;
while ((remainder > 0) && (status == SM_OK))
{
size_t chunk_size =
remainder > DATA_CHUNK_SIZE ? DATA_CHUNK_SIZE : remainder;
status = Se05x_API_ReadObject(
&(se05x->pnt->session), get_key_args->entry.id, offset, chunk_size,
get_key_args->content.buffer + offset, &chunk_size);
remainder -= chunk_size;
offset += chunk_size;
}
get_key_args->content.buffer_content_size = offset;
return status == SM_OK ? 0 : -EIO;
}
int pnt_se05x_delete_key(FAR struct se05x_dev_s *se05x, uint32_t key_id)
{
smStatus_t status =
Se05x_API_DeleteSecureObject(&(se05x->pnt->session), key_id);
return status == SM_OK ? 0 : -EIO;
}
int pnt_se05x_derive_key(FAR struct se05x_dev_s *se05x,
FAR struct se05x_derive_key_s *derive_key_args)
{
uint8_t public_key[65];
size_t public_key_size = sizeof(public_key);
smStatus_t status = Se05x_API_ReadObject(&(se05x->pnt->session),
derive_key_args->public_key_id, 0,
0, public_key, &public_key_size);
if (status == SM_OK)
{
derive_key_args->content.buffer_content_size =
derive_key_args->content.buffer_size;
status = Se05x_API_ECDHGenerateSharedSecret(
&(se05x->pnt->session), derive_key_args->private_key_id,
public_key, public_key_size, derive_key_args->content.buffer,
&derive_key_args->content.buffer_content_size);
}
return status == SM_OK ? 0 : -EIO;
}
int pnt_se05x_create_signature(
FAR struct se05x_dev_s *se05x,
FAR struct se05x_signature_s *create_signature_args)
{
create_signature_args->signature.buffer_content_size =
create_signature_args->signature.buffer_size;
int result =
Se05x_API_ECDSASign(
&(se05x->pnt->session), create_signature_args->key_id,
signature_algorithm_mapping[create_signature_args->algorithm],
create_signature_args->tbs.buffer,
create_signature_args->tbs.buffer_content_size,
create_signature_args->signature.buffer,
&create_signature_args->signature.buffer_content_size) == SM_OK
? 0
: -EIO;
return result;
}
int pnt_se05x_verify_signature(
FAR struct se05x_dev_s *se05x,
FAR struct se05x_signature_s *verify_signature_args)
{
SE05x_Result_t se05x_result;
int result =
Se05x_API_ECDSAVerify(
&(se05x->pnt->session), verify_signature_args->key_id,
signature_algorithm_mapping[verify_signature_args->algorithm],
verify_signature_args->tbs.buffer,
verify_signature_args->tbs.buffer_content_size,
verify_signature_args->signature.buffer,
verify_signature_args->signature.buffer_content_size,
&se05x_result) == SM_OK
? 0
: -EACCES;
if ((result == 0) && (se05x_result != kSE05x_Result_SUCCESS))
{
result = -EIO;
}
return result;
}