wolfssl-examples/ccb_vaultic/ccb_vaultic.c

1151 lines
33 KiB
C

/*
* ccb_vaultic.c
*
* Copyright (C) 2023 wolfSSL Inc.
*
* wolfSSL is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* wolfSSL is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
/*
* Compilation options:
*
* HAVE_CCBVAULTIC
* Enable actual callbacks. This depends on VaultIC hardware libraries
*
* Defined options when HAVE_CCBVAULTIC is set:
*
* WOLF_CRYPTO_CB_CMD
* Enable delayed hardware initialization using Register and Unregister
* callback commands
*
* CCBVAULTIC_DEBUG: Print useful callback info using XPRINTF
* CCBVAULTIC_DEBUG_TIMING: Print useful timing info using XPRINTF
* CCBVAULTIC_DEBUG_ALL: Print copious info using XPRINTF
*
* CCBVAULTIC_NO_SHA: Do not handle SHA256 callback
* CCBVAULTIC_NO_RSA: Do not handle RSA callback
* CCBVAULTIC_NO_AES: Do not handle AES callback
*
* Expected wolfSSL/wolfCrypt defines from wolfcrypt/types.h or settings.h:
* XMALLOC: malloc() equivalent
* XREALLOC: realloc() equivalent
* XFREE: free() equivalent
* XMEMCPY: memcpy() equivalent
* XMEMSET: memset() equivalent
* XMEMCMP: memcmp() equivalent
*
* Overrideable defines:
* XPRINTF: printf() equivalent
* XNOW: clock_gettime(CLOCK_MONOTONIC) converted to uint64_t ns
*/
#ifdef HAVE_CCBVAULTIC
/* wolfSSL configuration */
#ifndef WOLFSSL_USER_SETTINGS
#include "wolfssl/options.h"
#endif
#include "wolfssl/wolfcrypt/settings.h"
/* wolfCrypt includes */
#include "wolfssl/wolfcrypt/cryptocb.h" /* For wc_cryptInfo */
#include "wolfssl/wolfcrypt/error-crypt.h" /* For error values */
/* Local include */
#include "ccb_vaultic.h"
/* Debug defines */
#ifdef CCBVAULTIC_DEBUG_ALL
#ifndef CCBVAULTIC_DEBUG
#define CCBVAULTIC_DEBUG
#endif
#ifndef CCBVAULTIC_DEBUG_TIMING
#define CCBVAULTIC_DEBUG_TIMING
#endif
#endif
#if defined(CCBVAULTIC_DEBUG) || defined(CCBVAULTIC_DEBUG_TIMING)
#ifndef XPRINTF
#define XPRINTF(...) printf(__VA_ARGS__)
#endif
#endif
/* wolfcrypt includes */
#include "wolfssl/wolfcrypt/types.h" /* types and X-defines */
#ifndef CCBVAULTIC_NO_SHA
#include "wolfssl/wolfcrypt/hash.h" /* For HASH_FLAGS and types */
#endif
#ifndef CCBVAULTIC_NO_RSA
#include "wolfssl/wolfcrypt/rsa.h" /* For RSA_MAX_SIZE and types */
#endif
#ifndef CCBVAULTIC_NO_AES
#include "wolfssl/wolfcrypt/aes.h" /* For AES_BLOCK_SIZE and types */
#endif
#ifdef CCBVAULTIC_DEBUG_TIMING
#ifndef XNOW
#include <time.h>
#include <stdint.h>
#define XNOW(...) _now(__VA_ARGS__)
static uint64_t _now(void)
{
struct timespec t;
if (clock_gettime(CLOCK_MONOTONIC, &t) < 0)
/* Return 0 on error */
return 0;
return (uint64_t)t.tv_sec * 1000000000ull + t.tv_nsec;
}
#endif
#endif
/* WiseKey VaultIC includes */
#include "vaultic_tls.h"
#include "vaultic_config.h"
#include "vaultic_common.h"
#include "vaultic_api.h"
#include "vaultic_structs.h"
/* Key/Group ID's to support temporary wolfSSL usage */
#define CCBVAULTIC_WOLFSSL_GRPID 0xBB
#define CCBVAULTIC_TMPAES_KEYID 0x01
#define CCBVAULTIC_TMPHMAC_KEYID 0x02
#define CCBVAULTIC_TMPRSA_KEYID 0x03
/* Key attributes */
#define VAULTIC_KP_ALL 0xFF /* Allow all users all key privileges */
#define VAULTIC_PKV_ASSURED VLT_PKV_ASSURED_EXPLICIT_VALIDATION
#ifdef CCBVAULTIC_DEBUG
/* Helper to provide simple hexdump */
static void hexdump(const unsigned char* p, size_t len)
{
XPRINTF(" HD:%p for %lu bytes\n",p, len);
if ( (p == NULL) || (len == 0))
return;
size_t off = 0;
for (off = 0; off < len; off++)
{
if ((off % 16) == 0)
XPRINTF(" ");
XPRINTF("%02X ", p[off]);
if ((off % 16) == 15)
XPRINTF("\n");
}
if ( (off%16) != 15)
XPRINTF("\n");
}
#endif
/* Helper to translate vlt return codes to wolfSSL code */
static int translateError(int vlt_rc)
{
/* vlt return codes are defined in src/common/vaultic_err.h */
switch (vlt_rc) {
case VLT_OK:
return 0;
default:
/* Default to point to hardware */
return WC_HW_E;
}
}
static void clearContext(ccbVaultIc_Context *c)
{
XMEMSET(c, 0, sizeof(*c));
c->m = NULL;
c->aescbc_key = NULL;
}
int ccbVaultIc_Init(ccbVaultIc_Context *c)
{
int rc = 0;
if (c == NULL) {
rc = BAD_FUNC_ARG;
}
/* Already Initialized? */
if ((rc == 0) && (c->initialized >0)) {
/* Increment use count */
c->initialized++;
return 0;
}
if (rc == 0) {
clearContext(c);
/* Open the hardware and authenticate */
c->vlt_rc = vlt_tls_init();
rc = translateError(c->vlt_rc);
}
if (rc == 0) {
c->initialized = 1;
}
else {
/* Override with an init error */
rc = WC_INIT_E;
}
#ifdef CCBVAULTIC_DEBUG
XPRINTF("ccbVaultIc_Init: c:%p c->initialized:%d rc:%d vlt_rc:%d\n",
c,
(c == NULL) ? -1 : c->initialized,
rc,
(c == NULL) ? -1 : c->vlt_rc);
#endif
return rc;
}
void ccbVaultIc_Cleanup(ccbVaultIc_Context *c)
{
#ifdef CCBVAULTIC_DEBUG
XPRINTF("ccbVaultIc_Cleanup c:%p c->initialized:%d\n", c,
(c == NULL) ? -1 : c->initialized);
#endif
/* Invalid context or not initialized? */
if ((c == NULL) ||
(c->initialized == 0)) {
return;
}
/* Decrement use count */
c->initialized--;
if (c->initialized > 0)
return;
/* Free allocated buffers */
if (c->m != NULL)
XFREE(c->m, NULL, NULL);
if (c->aescbc_key != NULL)
XFREE(c->aescbc_key, NULL, NULL);
clearContext(c);
/* Set the return value in the struct */
/* Close the hardware */
c->vlt_rc = vlt_tls_close();
}
#ifdef WOLF_CRYPTO_CB
/* Forward declarations */
static int HandlePkCallback(int devId, wc_CryptoInfo* info,
ccbVaultIc_Context *c);
static int HandleHashCallback(int devId, wc_CryptoInfo* info,
ccbVaultIc_Context *c);
static int HandleCipherCallback(int devId, wc_CryptoInfo* info,
ccbVaultIc_Context *c);
#ifdef WOLF_CRYPTO_CB_CMD
/* Provide global singleton context to avoid allocation */
static ccbVaultIc_Context localContext = CCBVAULTIC_CONTEXT_INITIALIZER;
static int HandleCmdCallback(int devId, wc_CryptoInfo* info,
ccbVaultIc_Context *c);
#endif
int ccbVaultIc_CryptoCb(int devId,
wc_CryptoInfo* info,
void* ctx)
{
(void)devId;
ccbVaultIc_Context* c = (ccbVaultIc_Context*)ctx;
int rc = CRYPTOCB_UNAVAILABLE;
/* Allow null/uninitialized context for ALGO_TYPE_NUNE */
if ( (info == NULL) ||
((info->algo_type != WC_ALGO_TYPE_NONE) &&
((c == NULL) || (c->initialized == 0)))) {
/* Invalid info or context */
#if defined(CCBVAULTIC_DEBUG)
XPRINTF("Invalid callback. info:%p c:%p c->init:%d\n",
info, c, c ? c->initialized : -1);
#endif
return BAD_FUNC_ARG;
}
switch(info->algo_type) {
case WC_ALGO_TYPE_NONE:
#ifdef WOLF_CRYPTO_CB_CMD
#if defined(CCBVAULTIC_DEBUG)
XPRINTF(" CryptoDevCb NONE-Command: %d %p\n",
info->cmd.type, info->cmd.ctx);
#endif
rc = HandleCmdCallback(devId, info, ctx);
#else
#if defined(CCBVAULTIC_DEBUG)
XPRINTF(" CryptoDevCb NONE:\n");
#endif
/* Nothing to do */
#endif
break;
case WC_ALGO_TYPE_HASH:
#if defined(CCBVAULTIC_DEBUG_ALL)
XPRINTF(" CryptoDevCb HASH: Type:%d\n", info->hash.type);
#endif
#if !defined(NO_SHA) || !defined(NO_SHA256)
/* Perform a hash */
rc = HandleHashCallback(devId, info, ctx);
#endif
break;
case WC_ALGO_TYPE_CIPHER:
#if defined(CCBVAULTIC_DEBUG_ALL)
XPRINTF(" CryptoDevCb CIPHER: Type:%d\n", info->cipher.type);
#endif
#if !defined(NO_AES)
/* Perform a symmetric cipher */
rc = HandleCipherCallback(devId, info, ctx);
#endif
break;
case WC_ALGO_TYPE_PK:
#if defined(CCBVAULTIC_DEBUG_ALL)
XPRINTF(" CryptoDevCb PK: Type:%d\n", info->pk.type);
#endif
#if !defined(NO_RSA) || defined(HAVE_ECC)
/* Perform a PKI operation */
rc = HandlePkCallback(devId,info,ctx);
#endif /* !defined(NO_RSA) || defined(HAVE_ECC) */
break;
case WC_ALGO_TYPE_RNG:
#if defined(CCBVAULTIC_DEBUG_ALL)
XPRINTF(" CryptoDevCb RNG: Out:%p Sz:%d\n",
info->rng.out, info->rng.sz);
#endif
#if !defined(WC_NO_RNG)
/* Put info->rng.sz random bytes into info->rng.out*/
/* TODO rc = VaultIC_Random(); */
#endif
break;
case WC_ALGO_TYPE_SEED:
#if defined(CCBVAULTIC_DEBUG_ALL)
XPRINTF(" CryptoDevCb SEED: Seed:%p Sz:%d\n", info->seed.seed,
info->seed.sz);
#endif
#if !defined(WC_NO_RNG)
/* Get info->seed.sz seed bytes from info->seed.seed*/
/* TODO rc = VaultIC_Seed(); */
#endif
break;
case WC_ALGO_TYPE_HMAC:
#if defined(CCBVAULTIC_DEBUG_ALL)
XPRINTF(" CryptoDevCb HMAC:\n");
#endif
break;
case WC_ALGO_TYPE_CMAC:
#if defined(CCBVAULTIC_DEBUG_ALL)
XPRINTF(" CryptoDevCb CMAC:\n");
#endif
break;
default:
#if defined(CCBVAULTIC_DEBUG_ALL)
XPRINTF(" CryptoDevCb UNKNOWN: %d\n", info->algo_type);
#endif
break;
}
return rc;
}
#ifdef WOLF_CRYPTO_CB_CMD
static int HandleCmdCallback(int devId, wc_CryptoInfo* info,
ccbVaultIc_Context *c)
{
int rc = CRYPTOCB_UNAVAILABLE;
/* Ok to have null context at this point*/
switch(info->cmd.type) {
case WC_CRYPTOCB_CMD_TYPE_REGISTER:
{
/* Is the context nonnull already? Nothing to do */
if (c != NULL)
break;
rc = ccbVaultIc_Init(&localContext);
if (rc == 0) {
/* Update the info struct to use localContext */
info->cmd.ctx = &localContext;
}
}; break;
case WC_CRYPTOCB_CMD_TYPE_UNREGISTER:
{
/* Is the current context not set? Nothing to do*/
if (c == NULL)
break;
ccbVaultIc_Cleanup(c);
/* Return success */
rc = 0;
}; break;
default:
break;
}
return rc;
}
#endif
static int HandlePkCallback(int devId, wc_CryptoInfo* info,
ccbVaultIc_Context *c)
{
int rc = CRYPTOCB_UNAVAILABLE;
switch(info->pk.type) {
case WC_PK_TYPE_NONE:
{
#if defined(CCBVAULTIC_DEBUG_ALL)
XPRINTF(" HandlePkCallback NONE\n");
#endif
}; break;
case WC_PK_TYPE_RSA:
{
#if defined(CCBVAULTIC_DEBUG_ALL)
XPRINTF(" HandlePkCallback RSA: Type:%d\n",info->pk.rsa.type);
#endif
#if !defined(CCBVAULTIC_NO_RSA)
switch(info->pk.rsa.type) {
case RSA_PUBLIC_DECRYPT: /* RSA Verify */
case RSA_PUBLIC_ENCRYPT: /* RSA Encrypt */
{ /* Handle RSA Pub Key op */
byte e[sizeof(uint32_t)];
byte e_pad[sizeof(e)];
byte n[RSA_MAX_SIZE / 8];
word32 eSz = sizeof(e);
word32 nSz = sizeof(n);
VLT_U32 out_len = 0;
VLT_FILE_PRIVILEGES keyPrivileges;
VLT_KEY_OBJECT tmpRsaKey;
VLT_ALGO_PARAMS rsapub_algo_params;
#ifdef CCBVAULTIC_DEBUG_TIMING
uint64_t ts[6];
XMEMSET(ts, 0, sizeof(ts));
#endif
/* Extract key values from RSA context */
rc = wc_RsaFlattenPublicKey(info->pk.rsa.key, e, &eSz, n, &nSz);
if (rc != 0)
break;
/* VaultIC requires e to be MSB-padded to 4-byte multiples*/
XMEMSET(e_pad, 0, sizeof(e_pad));
XMEMCPY(&e_pad[(sizeof(e_pad)-eSz)], e, eSz);
#if defined(CCBVAULTIC_DEBUG_ALL)
XPRINTF(" RSA Flatten Pub Key:%d, eSz:%u nSz:%u\n",
rc, eSz, nSz);
hexdump(e,sizeof(e));
hexdump(e_pad,sizeof(e_pad));
hexdump(n,sizeof(n));
#endif
/* Set tmpRsaKey privileges */
keyPrivileges.u8Read = VAULTIC_KP_ALL;
keyPrivileges.u8Write = VAULTIC_KP_ALL;
keyPrivileges.u8Delete = VAULTIC_KP_ALL;
keyPrivileges.u8Execute = VAULTIC_KP_ALL;
/* Set tmpRsaKey values for public key */
tmpRsaKey.enKeyID = VLT_KEY_RSAES_PUB;
tmpRsaKey.data.RsaPubKey.u16NLen = nSz;
tmpRsaKey.data.RsaPubKey.pu8N = n;
tmpRsaKey.data.RsaPubKey.u16ELen = sizeof(e_pad);
tmpRsaKey.data.RsaPubKey.pu8E = e_pad;
tmpRsaKey.data.RsaPubKey.enAssurance = VAULTIC_PKV_ASSURED;
/* Set algo to Raw RSA ES*/
rsapub_algo_params.u8AlgoID = VLT_ALG_CIP_RSAES_X509;
#ifdef CCBVAULTIC_DEBUG_TIMING
ts[0] = XNOW();
#endif
/* Try to delete the tmp rsa key. Ignore errors here */
VltDeleteKey(
CCBVAULTIC_WOLFSSL_GRPID,
CCBVAULTIC_TMPRSA_KEYID);
#ifdef CCBVAULTIC_DEBUG_TIMING
ts[1] = XNOW();
#endif
c->vlt_rc = VltPutKey(
CCBVAULTIC_WOLFSSL_GRPID,
CCBVAULTIC_TMPRSA_KEYID,
&keyPrivileges,
&tmpRsaKey);
#if defined(CCBVAULTIC_DEBUG_ALL)
XPRINTF(" VLT PutKey:%x\n", c->vlt_rc);
#endif
rc = translateError(c->vlt_rc);
if (rc != 0)
break;
#ifdef CCBVAULTIC_DEBUG_TIMING
ts[2] = XNOW();
#endif
/* Initialize Algo for RSA Pub Encrypt */
c->vlt_rc = VltInitializeAlgorithm(
CCBVAULTIC_WOLFSSL_GRPID,
CCBVAULTIC_TMPRSA_KEYID,
VLT_ENCRYPT_MODE,
&rsapub_algo_params);
#if defined(CCBVAULTIC_DEBUG_ALL)
XPRINTF(" VLT InitAlgo:%x\n", c->vlt_rc);
#endif
rc = translateError(c->vlt_rc);
if (rc != 0)
break;
#ifdef CCBVAULTIC_DEBUG_TIMING
ts[3] = XNOW();
#endif
/* Perform the RSA pub key encrypt */
c->vlt_rc = VltEncrypt(
info->pk.rsa.inLen,
info->pk.rsa.in,
&out_len,
info->pk.rsa.inLen,
info->pk.rsa.out);
if (info->pk.rsa.outLen)
*(info->pk.rsa.outLen) = out_len;
#if defined(CCBVAULTIC_DEBUG_ALL)
XPRINTF(" VLT Encrypt:%x inSz:%u outSz:%lu\n",
c->vlt_rc, info->pk.rsa.inLen, out_len);
#endif
rc = translateError(c->vlt_rc);
if (rc != 0)
break;
#ifdef CCBVAULTIC_DEBUG_TIMING
ts[4] = XNOW();
XPRINTF(" RSA Encrypt Times(us): DltKey:%lu PutKey:%lu "
"InitAlgo:%lu Encrypt:%lu InSize:%u OutSize:%lu "
"KeySize:%u\n",
(ts[1]-ts[0])/1000,
(ts[2]-ts[1])/1000,
(ts[3]-ts[2])/1000,
(ts[4]-ts[3])/1000,
info->pk.rsa.inLen, out_len,nSz);
#endif
};break; /* Handle RSA Pub Key op */
case RSA_PRIVATE_ENCRYPT: /* RSA Sign */
case RSA_PRIVATE_DECRYPT: /* RSA Decrypt */
default:
/* Not supported */
break;
}
#endif
}; break;
case WC_PK_TYPE_DH:
#if defined(CCBVAULTIC_DEBUG_ALL)
XPRINTF(" HandlePkCallback DH\n");
#endif
break;
case WC_PK_TYPE_ECDH:
#if defined(CCBVAULTIC_DEBUG_ALL)
XPRINTF(" HandlePkCallback ECDH\n");
#endif
break;
case WC_PK_TYPE_ECDSA_SIGN:
#if defined(CCBVAULTIC_DEBUG_ALL)
XPRINTF(" HandlePkCallback ECDSA_SIGN\n");
#endif
break;
case WC_PK_TYPE_ECDSA_VERIFY:
#if defined(CCBVAULTIC_DEBUG_ALL)
XPRINTF(" HandlePkCallback ECDSA_VERIFY\n");
#endif
break;
case WC_PK_TYPE_ED25519_SIGN:
#if defined(CCBVAULTIC_DEBUG_ALL)
XPRINTF(" HandlePkCallback ED25519_SIGN\n");
#endif
break;
case WC_PK_TYPE_CURVE25519:
#if defined(CCBVAULTIC_DEBUG_ALL)
XPRINTF(" HandlePkCallback CURVE25519\n");
#endif
break;
case WC_PK_TYPE_RSA_KEYGEN:
#if defined(CCBVAULTIC_DEBUG_ALL)
XPRINTF(" HandlePkCallback RSA_KEYGEN\n");
#endif
break;
case WC_PK_TYPE_EC_KEYGEN:
#if defined(CCBVAULTIC_DEBUG_ALL)
XPRINTF(" HandlePkCallback EC_KEYGEN\n");
#endif
break;
case WC_PK_TYPE_RSA_CHECK_PRIV_KEY:
#if defined(CCBVAULTIC_DEBUG_ALL)
XPRINTF(" HandlePkCallback RSA_CHECK_PRIV_KEY\n");
#endif
break;
case WC_PK_TYPE_EC_CHECK_PRIV_KEY:
#if defined(CCBVAULTIC_DEBUG_ALL)
XPRINTF(" HandlePkCallback EC_CHECK_PRIV_KEY\n");
#endif
break;
case WC_PK_TYPE_ED448:
#if defined(CCBVAULTIC_DEBUG_ALL)
XPRINTF(" HandlePkCallback ED448\n");
#endif
break;
case WC_PK_TYPE_CURVE448:
#if defined(CCBVAULTIC_DEBUG_ALL)
XPRINTF(" HandlePkCallback CRUVE448\n");
#endif
break;
case WC_PK_TYPE_ED25519_VERIFY:
#if defined(CCBVAULTIC_DEBUG_ALL)
XPRINTF(" HandlePkCallback ED25519_VERIFY\n");
#endif
break;
case WC_PK_TYPE_ED25519_KEYGEN:
#if defined(CCBVAULTIC_DEBUG_ALL)
XPRINTF(" HandlePkCallback ED25519_KEYGEN\n");
#endif
break;
case WC_PK_TYPE_CURVE25519_KEYGEN:
#if defined(CCBVAULTIC_DEBUG_ALL)
XPRINTF(" HandlePkCallback CURVE25519_KEYGEN\n");
#endif
break;
case WC_PK_TYPE_RSA_GET_SIZE:
#if defined(CCBVAULTIC_DEBUG)
XPRINTF(" HandlePkCallback RSA_GET_SIZE\n");
#endif
break;
default:
#if defined(CCBVAULTIC_DEBUG_ALL)
XPRINTF(" HandlePkCallback UNKNOWN: %d\n",info->pk.type);
#endif
break;
}
return rc;
}
static int HandleHashCallback(int devId, wc_CryptoInfo* info,
ccbVaultIc_Context *c)
{
int rc = CRYPTOCB_UNAVAILABLE;
switch(info->hash.type) {
case WC_HASH_TYPE_NONE:
#if defined(CCBVAULTIC_DEBUG_ALL)
XPRINTF(" HandleHashCallback NONE\n");
#endif
break;
case WC_HASH_TYPE_SHA:
#if defined(CCBVAULTIC_DEBUG_ALL)
XPRINTF(" HandleHashCallback SHA\n");
#endif
break;
case WC_HASH_TYPE_SHA224:
#if defined(CCBVAULTIC_DEBUG_ALL)
XPRINTF(" HandleHashCallback SHA224\n");
#endif
break;
case WC_HASH_TYPE_SHA256:
{
#if defined(CCBVAULTIC_DEBUG_ALL)
XPRINTF(" HandleHashCallback SHA256. In:%p InSz:%u Digest:%p "
"c->m:%p c->m_len:%lu c->t:%d\n",
info->hash.in, info->hash.inSz, info->hash.digest,
c->m, c->m_len, c->hash_type);
#endif
#if !defined(CCBVAULTIC_NO_SHA)
/*
* info->hash.flag | WC_HASH_FLAGS_WILL_COPY --> Buffer entire message
* info->hash.in != NULL --> Update
* info->hash.digest != NULL --> Final
*/
#ifdef CCBVAULTIC_DEBUG_TIMING
uint64_t ts[3];
XMEMSET(ts, 0, sizeof(ts));
#endif
/* New/different hashtype than last time? */
if (c->hash_type != info->hash.type) {
/* New/different hash than last time. Erase state */
#if defined(CCBVAULTIC_DEBUG_ALL)
XPRINTF(" New Hash\n");
#endif
if (c->m != NULL)
XFREE(c->m, NULL, NULL);
c->m = NULL;
c->m_len = 0;
c->hash_type = info->hash.type;
}
/* Update needed? */
/* III Buffering ALL messages, not just WILL_COPY */
if ( (info->hash.in != NULL) &&
(info->hash.inSz > 0)) {
/* Buffer data */
if (c->m == NULL) {
c->m = XMALLOC(info->hash.inSz, NULL, NULL);
if (c->m == NULL) {
/* Failure to allocate. Must return error */
#if defined(CCBVAULTIC_DEBUG)
XPRINTF(" Failed to alloc. Size:%u\n",
info->hash.inSz);
#endif
rc = MEMORY_E;
break;
}
c->m_len = 0;
#if defined(CCBVAULTIC_DEBUG_ALL)
XPRINTF(" Alloc to %p. Size:%u\n", c->m, info->hash.inSz);
#endif
} else {
/* Realloc and add new data in */
void *new_buf = XREALLOC(c->m, c->m_len + info->hash.inSz,
NULL, NULL);
if (new_buf == NULL) {
/* Failure to realloc. Must return error */
#if defined(CCBVAULTIC_DEBUG)
XPRINTF(" Failed to XREALLOC. New size:%lu\n",
c->m_len + info->hash.inSz);
#endif
rc = MEMORY_E;
break;
}
c->m = new_buf;
#if defined(CCBVAULTIC_DEBUG_ALL)
XPRINTF(" Realloc to %p. New size:%lu\n",
c->m, c->m_len + info->hash.inSz);
#endif
}
/* Copy new data into the buffer */
XMEMCPY(c->m + c->m_len, info->hash.in, info->hash.inSz);
c->m_len += info->hash.inSz;
#if defined(CCBVAULTIC_DEBUG_ALL)
XPRINTF(" Buffered to %p. Buffer size:%lu\n", c->m, c->m_len);
#endif
/* Successful update */
rc = 0;
} /* End of Update */
/* Finalize needed? */
if (info->hash.digest != NULL) {
/* Initialize for Hashing */
VLT_U8 sha_out_len = 0;
VLT_ALGO_PARAMS sha256_algo_params;
sha256_algo_params.u8AlgoID = VLT_ALG_DIG_SHA256;
#ifdef CCBVAULTIC_DEBUG_TIMING
ts[0] = XNOW();
#endif
c->vlt_rc = VltInitializeAlgorithm(
0,
0,
VLT_DIGEST_MODE,
&sha256_algo_params);
#if defined(CCBVAULTIC_DEBUG_ALL)
XPRINTF(" VltInit SHA256:%x\n", c->vlt_rc);
#endif
rc = translateError(c->vlt_rc);
if (rc != 0)
break;
#ifdef CCBVAULTIC_DEBUG_TIMING
ts[1] = XNOW();
#endif
/* No data buffered? Likely test case. Needs 2 steps */
if (c->m == NULL)
{
c->vlt_rc = VltUpdateMessageDigest(
c->m_len,
c->m);
#if defined(CCBVAULTIC_DEBUG_ALL)
XPRINTF(" VltUpdate SHA256:%x\n", c->vlt_rc);
#endif
rc = translateError(c->vlt_rc);
if (rc != 0)
break;
c->vlt_rc = VltComputeMessageDigestFinal(
&sha_out_len,
WC_SHA256_DIGEST_SIZE,
info->hash.digest);
#if defined(CCBVAULTIC_DEBUG_ALL)
XPRINTF(" VltFinal SHA256:%x\n", c->vlt_rc);
#endif
rc = translateError(c->vlt_rc);
if (rc != 0)
break;
}
else {
c->vlt_rc = VltComputeMessageDigest(
c->m_len,
c->m,
&sha_out_len,
WC_SHA256_DIGEST_SIZE,
info->hash.digest);
#if defined(CCBVAULTIC_DEBUG_ALL)
XPRINTF(" VltCompute SHA256:%x\n", c->vlt_rc);
hexdump(info->hash.digest, WC_SHA256_DIGEST_SIZE);
#endif
rc = translateError(c->vlt_rc);
if (rc != 0)
break;
}
#ifdef CCBVAULTIC_DEBUG_TIMING
ts[2] = XNOW();
XPRINTF(" SHA256 Compute Times(us): InitAlgo:%lu Digest:%lu "
"InSize:%lu OutSize:%u\n",
(ts[1]-ts[0])/1000,
(ts[2]-ts[1])/1000,
c->m_len, sha_out_len);
#endif
/* Deallocate/clear if this hash was NOT a copy*/
#if defined(CCBVAULTIC_DEBUG_ALL)
XPRINTF(" Hash flags:%x\n",
(info->hash.sha256 != NULL) ?
info->hash.sha256->flags :
-1);
#endif
/* If there are no flags OR if flags say its a copy then... */
if ((info->hash.sha256 == NULL) ||
!(info->hash.sha256->flags & WC_HASH_FLAG_ISCOPY)) {
#if defined(CCBVAULTIC_DEBUG_ALL)
XPRINTF(" Freeing hash state\n");
#endif
if (c->m != NULL)
XFREE(c->m, NULL, NULL);
c->m = NULL;
c->m_len = 0;
c->hash_type = WC_HASH_TYPE_NONE;
}
/* Successful finalize */
rc = 0;
} /* End of finalize */
#endif
}; break;
case WC_HASH_TYPE_SHA384:
#if defined(CCBVAULTIC_DEBUG_ALL)
XPRINTF(" HandleHashCallback SHA384\n");
#endif
break;
case WC_HASH_TYPE_SHA512:
#if defined(CCBVAULTIC_DEBUG_ALL)
XPRINTF(" HandleHashCallback SHA512\n");
#endif
break;
default:
break;
}
return rc;
}
static int HandleCipherCallback(int devId, wc_CryptoInfo* info,
ccbVaultIc_Context *c)
{
int rc = CRYPTOCB_UNAVAILABLE;
switch(info->cipher.type) {
case WC_CIPHER_NONE:
#if defined(CCBVAULTIC_DEBUG_ALL)
XPRINTF(" HandleCipherCallback NONE\n");
#endif
break;
case WC_CIPHER_AES:
#if defined(CCBVAULTIC_DEBUG_ALL)
XPRINTF(" HandleCipherCallback AES\n");
#endif
break;
case WC_CIPHER_AES_CBC:
{
#if defined(CCBVAULTIC_DEBUG_ALL)
XPRINTF(" HandleCipherCallback AES_CBC\n");
#endif
#if !defined(CCBVAULTIC_NO_AES)
Aes* aes = info->cipher.aescbc.aes;
int encrypt = info->cipher.enc;
unsigned int blocks = 0;
const byte *last_block;
VLT_U32 out_len = 0;
VLT_FILE_PRIVILEGES keyPrivileges;
VLT_KEY_OBJECT tmpAesKey;
VLT_ALGO_PARAMS aescbc_algo_params;
int vlt_mode = 0;
#ifdef CCBVAULTIC_DEBUG_TIMING
uint64_t ts[6];
XMEMSET(ts, 0, sizeof(ts));
#endif
/* Invalid incoming context? Return error*/
if (aes == NULL)
rc = BAD_FUNC_ARG;
break;
/* Only support AES128 */
if (aes->keylen != AES_128_KEY_SIZE)
break;
/* Check number of blocks */
blocks = info->cipher.aescbc.sz / AES_BLOCK_SIZE;
if (blocks == 0) {
/* Success! Nothing to do */
rc = 0;
break;
}
/* Initialize Algo for AES-CBC */
aescbc_algo_params.u8AlgoID = VLT_ALG_CIP_AES;
aescbc_algo_params.data.SymCipher.enMode = BLOCK_MODE_CBC;
aescbc_algo_params.data.SymCipher.enPadding = PADDING_NONE;
aescbc_algo_params.data.SymCipher.u8IvLength = AES_BLOCK_SIZE;
/* Copy in the previous cipher block */
XMEMCPY(aescbc_algo_params.data.SymCipher.u8Iv,
aes->reg, AES_BLOCK_SIZE);
if (encrypt) {
/* Last cipher text block is within out */
last_block = info->cipher.aescbc.out +
(blocks - 1) * AES_BLOCK_SIZE;
vlt_mode = VLT_ENCRYPT_MODE;
}
else {
/* Last cipher text block is within in */
last_block = info->cipher.aescbc.in +
(blocks - 1) * AES_BLOCK_SIZE;
vlt_mode = VLT_DECRYPT_MODE;
}
/* Check if key is not the same as last time */
if ((c->aescbc_key == NULL) ||
(c->aescbc_keylen != aes->keylen) ||
(XMEMCMP(c->aescbc_key, aes->devKey, aes->keylen))) {
#if defined(CCBVAULTIC_DEBUG_ALL)
XPRINTF(" New AES Key: ckey:%p clen:%lu akey:%p alen:%u\n",
c->aescbc_key,c->aescbc_keylen, aes->devKey, aes->keylen);
hexdump((void*)aes->devKey, aes->keylen);
#endif
/* Free the current key buffer if necessary */
if (c->aescbc_key != NULL) {
XFREE(c->aescbc_key, NULL, NULL);
c->aescbc_key = NULL;
c->aescbc_keylen = 0;
}
/* Allocate key buffer */
c->aescbc_key = XMALLOC(aes->keylen, NULL, NULL);
if (c->aescbc_key == NULL) {
#if defined(CCBVAULTIC_DEBUG)
XPRINTF(" Failed to allocate new AES Key of size:%u\n",
aes->keylen);
#endif
break;
}
/* Copy key into buffer */
c->aescbc_keylen = aes->keylen;
XMEMCPY(c->aescbc_key, aes->devKey, aes->keylen);
/* Set tmpAesKey privileges */
keyPrivileges.u8Read = VAULTIC_KP_ALL;
keyPrivileges.u8Write = VAULTIC_KP_ALL;
keyPrivileges.u8Delete = VAULTIC_KP_ALL;
keyPrivileges.u8Execute = VAULTIC_KP_ALL;
/* Set tmpAesKey data values */
tmpAesKey.enKeyID = VLT_KEY_AES_128;
tmpAesKey.data.SecretKey.u8Mask = 0;
tmpAesKey.data.SecretKey.u16KeyLength = c->aescbc_keylen;
tmpAesKey.data.SecretKey.pu8Key = (VLT_PU8)(c->aescbc_key);
#ifdef CCBVAULTIC_DEBUG_TIMING
ts[0] = XNOW();
#endif
/* Try to delete the tmp aes key. Ignore errors here */
VltDeleteKey(
CCBVAULTIC_WOLFSSL_GRPID,
CCBVAULTIC_TMPAES_KEYID);
#ifdef CCBVAULTIC_DEBUG_TIMING
ts[1] = XNOW();
#endif
/* Putkey aes->devKey, aes->keylen */
c->vlt_rc = VltPutKey(
CCBVAULTIC_WOLFSSL_GRPID,
CCBVAULTIC_TMPAES_KEYID,
&keyPrivileges,
&tmpAesKey);
#if defined(CCBVAULTIC_DEBUG_ALL)
XPRINTF(" VLT PutKey:%x\n", c->vlt_rc);
hexdump(c->aescbc_key, c->aescbc_keylen);
#endif
rc = translateError(c->vlt_rc);
if (rc != 0)
break;
}
#ifdef CCBVAULTIC_DEBUG_TIMING
ts[2] = XNOW();
#endif
c->vlt_rc = VltInitializeAlgorithm(
CCBVAULTIC_WOLFSSL_GRPID,
CCBVAULTIC_TMPAES_KEYID,
vlt_mode,
&aescbc_algo_params);
#if defined(CCBVAULTIC_DEBUG_ALL)
XPRINTF(" VLT InitAlgo:%x\n", c->vlt_rc);
#endif
rc = translateError(c->vlt_rc);
if (rc != 0)
break;
#ifdef CCBVAULTIC_DEBUG_TIMING
ts[3] = XNOW();
#endif
/* Perform encrypt/decrypt*/
if (encrypt) {
c->vlt_rc = VltEncrypt(
info->cipher.aescbc.sz,
info->cipher.aescbc.in,
&out_len,
info->cipher.aescbc.sz,
info->cipher.aescbc.out);
#if defined(CCBVAULTIC_DEBUG_ALL)
XPRINTF(" VLT Encrypt:%x\n", c->vlt_rc);
#endif
} else {
c->vlt_rc = VltDecrypt(
info->cipher.aescbc.sz,
info->cipher.aescbc.in,
&out_len,
info->cipher.aescbc.sz,
info->cipher.aescbc.out);
#if defined(CCBVAULTIC_DEBUG_ALL)
XPRINTF(" VLT Decrypt:%x\n", c->vlt_rc);
#endif
}
rc = translateError(c->vlt_rc);
if (rc != 0)
break;
/* Update state in AES CBC */
XMEMCPY(aes->reg, last_block, AES_BLOCK_SIZE);
#ifdef CCBVAULTIC_DEBUG_TIMING
ts[4] = XNOW();
XPRINTF(" AES Encrypt(%d) Times(us): DltKey:%lu PutKey:%lu "
"InitAlgo:%lu Encrypt:%lu InSize:%u OutSize:%lu\n",
encrypt,
(ts[1]-ts[0])/1000,
(ts[2]-ts[1])/1000,
(ts[3]-ts[2])/1000,
(ts[4]-ts[3])/1000,
info->cipher.aescbc.sz, out_len);
#endif
#endif /* CCBVAULTIC_NO_AES */
}; break;
case WC_CIPHER_AES_GCM:
#if defined(CCBVAULTIC_DEBUG_ALL)
XPRINTF(" HandleCipherCallback AES_GCM\n");
#endif
break;
case WC_CIPHER_AES_CTR:
#if defined(CCBVAULTIC_DEBUG_ALL)
XPRINTF(" HandleCipherCallback AES_CTR\n");
#endif
break;
case WC_CIPHER_AES_XTS:
#if defined(CCBVAULTIC_DEBUG_ALL)
XPRINTF(" HandleCipherCallback AES_XTS\n");
#endif
break;
case WC_CIPHER_AES_CFB:
#if defined(CCBVAULTIC_DEBUG_ALL)
XPRINTF(" HandleCipherCallback AES_CFB\n");
#endif
break;
case WC_CIPHER_AES_CCM:
#if defined(CCBVAULTIC_DEBUG_ALL)
XPRINTF(" HandleCipherCallback AES_CCM\n");
#endif
break;
case WC_CIPHER_AES_ECB:
#if defined(CCBVAULTIC_DEBUG_ALL)
XPRINTF(" HandleCipherCallback AES_ECB\n");
#endif
break;
default:
#if defined(CCBVAULTIC_DEBUG_ALL)
XPRINTF(" HandleCipherCallback UNKNOWN\n");
#endif
break;
}
return rc;
}
#endif /* WOLF_CRYPTO_CB */
#endif /* HAVE_CCBVAULTIC */