388 lines
9.4 KiB
C
388 lines
9.4 KiB
C
/*
|
|
* Copyright (C) 2020-2021 Artinchip Technology Co., Ltd.
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*
|
|
* Authors: Wu Dehuang <dehuang.wu@artinchip.com>
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <openssl/crypto.h>
|
|
#include "hardware_engine.h"
|
|
|
|
static int aic_cipher_init(EVP_CIPHER_CTX *ctx, const unsigned char *key,
|
|
const unsigned char *iv, int enc);
|
|
static int aic_do_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
|
|
const unsigned char *in, size_t inl);
|
|
static int aic_cipher_cleanup(EVP_CIPHER_CTX *ctx);
|
|
|
|
static struct aic_cipher sk_ciphers[] = {
|
|
{
|
|
.nid = NID_aes_128_ecb,
|
|
.flags = EVP_CIPH_ECB_MODE,
|
|
.block_size = AES_BLOCK_SIZE,
|
|
.key_len = AES_KEY_SIZE_128,
|
|
.ctx_size = sizeof(struct aic_ossl_cipher_ctx),
|
|
.init = aic_cipher_init,
|
|
.do_cipher = aic_do_cipher,
|
|
.cleanup = aic_cipher_cleanup,
|
|
},
|
|
{
|
|
.nid = NID_aes_192_ecb,
|
|
.flags = EVP_CIPH_ECB_MODE,
|
|
.block_size = AES_BLOCK_SIZE,
|
|
.key_len = AES_KEY_SIZE_192,
|
|
.ctx_size = sizeof(struct aic_ossl_cipher_ctx),
|
|
.init = aic_cipher_init,
|
|
.do_cipher = aic_do_cipher,
|
|
.cleanup = aic_cipher_cleanup,
|
|
},
|
|
{
|
|
.nid = NID_aes_256_ecb,
|
|
.flags = EVP_CIPH_ECB_MODE,
|
|
.block_size = AES_BLOCK_SIZE,
|
|
.key_len = AES_KEY_SIZE_256,
|
|
.ctx_size = sizeof(struct aic_ossl_cipher_ctx),
|
|
.init = aic_cipher_init,
|
|
.do_cipher = aic_do_cipher,
|
|
.cleanup = aic_cipher_cleanup,
|
|
},
|
|
{
|
|
.nid = NID_aes_128_cbc,
|
|
.flags = EVP_CIPH_CBC_MODE,
|
|
.block_size = AES_BLOCK_SIZE,
|
|
.key_len = AES_KEY_SIZE_128,
|
|
.iv_len = AES_IV_LEN,
|
|
.ctx_size = sizeof(struct aic_ossl_cipher_ctx),
|
|
.init = aic_cipher_init,
|
|
.do_cipher = aic_do_cipher,
|
|
.cleanup = aic_cipher_cleanup,
|
|
},
|
|
{
|
|
.nid = NID_aes_192_cbc,
|
|
.flags = EVP_CIPH_CBC_MODE,
|
|
.block_size = AES_BLOCK_SIZE,
|
|
.key_len = AES_KEY_SIZE_192,
|
|
.iv_len = AES_IV_LEN,
|
|
.ctx_size = sizeof(struct aic_ossl_cipher_ctx),
|
|
.init = aic_cipher_init,
|
|
.do_cipher = aic_do_cipher,
|
|
.cleanup = aic_cipher_cleanup,
|
|
},
|
|
{
|
|
.nid = NID_aes_256_cbc,
|
|
.flags = EVP_CIPH_CBC_MODE,
|
|
.block_size = AES_BLOCK_SIZE,
|
|
.key_len = AES_KEY_SIZE_256,
|
|
.iv_len = AES_IV_LEN,
|
|
.ctx_size = sizeof(struct aic_ossl_cipher_ctx),
|
|
.init = aic_cipher_init,
|
|
.do_cipher = aic_do_cipher,
|
|
.cleanup = aic_cipher_cleanup,
|
|
},
|
|
{
|
|
.nid = NID_aes_128_ctr,
|
|
.flags = EVP_CIPH_CTR_MODE | EVP_CIPH_NO_PADDING,
|
|
.block_size = 1,
|
|
.key_len = AES_KEY_SIZE_128,
|
|
.iv_len = AES_IV_LEN,
|
|
.ctx_size = sizeof(struct aic_ossl_cipher_ctx),
|
|
.init = aic_cipher_init,
|
|
.do_cipher = aic_do_cipher,
|
|
.cleanup = aic_cipher_cleanup,
|
|
},
|
|
{
|
|
.nid = NID_aes_192_ctr,
|
|
.flags = EVP_CIPH_CTR_MODE | EVP_CIPH_NO_PADDING,
|
|
.block_size = 1,
|
|
.key_len = AES_KEY_SIZE_192,
|
|
.iv_len = AES_IV_LEN,
|
|
.ctx_size = sizeof(struct aic_ossl_cipher_ctx),
|
|
.init = aic_cipher_init,
|
|
.do_cipher = aic_do_cipher,
|
|
.cleanup = aic_cipher_cleanup,
|
|
},
|
|
{
|
|
.nid = NID_aes_256_ctr,
|
|
.flags = EVP_CIPH_CTR_MODE | EVP_CIPH_NO_PADDING,
|
|
.block_size = 1,
|
|
.key_len = AES_KEY_SIZE_256,
|
|
.iv_len = AES_IV_LEN,
|
|
.ctx_size = sizeof(struct aic_ossl_cipher_ctx),
|
|
.init = aic_cipher_init,
|
|
.do_cipher = aic_do_cipher,
|
|
.cleanup = aic_cipher_cleanup,
|
|
},
|
|
{
|
|
.nid = NID_aes_128_xts,
|
|
.flags = EVP_CIPH_XTS_MODE,
|
|
.block_size = AES_BLOCK_SIZE,
|
|
.key_len = AES_KEY_SIZE_128,
|
|
.iv_len = AES_IV_LEN,
|
|
.ctx_size = sizeof(struct aic_ossl_cipher_ctx),
|
|
.init = aic_cipher_init,
|
|
.do_cipher = aic_do_cipher,
|
|
.cleanup = aic_cipher_cleanup,
|
|
},
|
|
{
|
|
.nid = NID_aes_256_xts,
|
|
.flags = EVP_CIPH_XTS_MODE,
|
|
.block_size = AES_BLOCK_SIZE,
|
|
.key_len = AES_KEY_SIZE_256,
|
|
.iv_len = AES_IV_LEN,
|
|
.init = aic_cipher_init,
|
|
.do_cipher = aic_do_cipher,
|
|
.cleanup = aic_cipher_cleanup,
|
|
},
|
|
{
|
|
.nid = NID_des_ecb,
|
|
.flags = EVP_CIPH_ECB_MODE,
|
|
.block_size = DES_BLOCK_SIZE,
|
|
.key_len = DES_KEY_SIZE_64,
|
|
.ctx_size = sizeof(struct aic_ossl_cipher_ctx),
|
|
.init = aic_cipher_init,
|
|
.do_cipher = aic_do_cipher,
|
|
.cleanup = aic_cipher_cleanup,
|
|
},
|
|
{
|
|
.nid = NID_des_cbc,
|
|
.flags = EVP_CIPH_CBC_MODE,
|
|
.block_size = DES_BLOCK_SIZE,
|
|
.key_len = DES_KEY_SIZE_64,
|
|
.iv_len = DES_IV_LEN,
|
|
.ctx_size = sizeof(struct aic_ossl_cipher_ctx),
|
|
.init = aic_cipher_init,
|
|
.do_cipher = aic_do_cipher,
|
|
.cleanup = aic_cipher_cleanup,
|
|
},
|
|
{
|
|
.nid = NID_des_ede3_ecb,
|
|
.flags = EVP_CIPH_ECB_MODE,
|
|
.block_size = DES_BLOCK_SIZE,
|
|
.key_len = DES_KEY_SIZE_192,
|
|
.init = aic_cipher_init,
|
|
.do_cipher = aic_do_cipher,
|
|
.cleanup = aic_cipher_cleanup,
|
|
},
|
|
{
|
|
.nid = NID_des_ede3_cbc,
|
|
.flags = EVP_CIPH_CBC_MODE,
|
|
.block_size = DES_BLOCK_SIZE,
|
|
.key_len = DES_KEY_SIZE_192,
|
|
.iv_len = DES_IV_LEN,
|
|
.ctx_size = sizeof(struct aic_ossl_cipher_ctx),
|
|
.init = aic_cipher_init,
|
|
.do_cipher = aic_do_cipher,
|
|
.cleanup = aic_cipher_cleanup,
|
|
},
|
|
};
|
|
|
|
static int known_cipher_nids[OSSL_NELEM(sk_ciphers)];
|
|
|
|
static int aic_cipher_init(EVP_CIPHER_CTX *ctx, const unsigned char *key,
|
|
const unsigned char *iv, int enc)
|
|
{
|
|
struct aic_ossl_cipher_ctx *c;
|
|
int nid, ivlen, keylen;
|
|
char *cipher_name;
|
|
|
|
cipher_name = NULL;
|
|
if (ctx == NULL || key == NULL) {
|
|
fprintf(stderr, "Null Parameter\n");
|
|
return 0;
|
|
}
|
|
if (EVP_CIPHER_CTX_cipher(ctx) == NULL) {
|
|
fprintf(stderr, "Cipher object NULL\n");
|
|
return 0;
|
|
}
|
|
|
|
c = EVP_CIPHER_CTX_get_cipher_data(ctx);
|
|
nid= EVP_CIPHER_CTX_nid(ctx);
|
|
keylen = 0;
|
|
switch (nid) {
|
|
case NID_aes_128_ecb:
|
|
keylen = AES_KEY_SIZE_128;
|
|
cipher_name = "ecb(aes)";
|
|
break;
|
|
case NID_aes_192_ecb:
|
|
keylen = AES_KEY_SIZE_192;
|
|
cipher_name = "ecb(aes)";
|
|
break;
|
|
case NID_aes_256_ecb:
|
|
keylen = AES_KEY_SIZE_256;
|
|
cipher_name = "ecb(aes)";
|
|
break;
|
|
case NID_aes_128_cbc:
|
|
keylen = AES_KEY_SIZE_128;
|
|
cipher_name = "cbc(aes)";
|
|
break;
|
|
case NID_aes_192_cbc:
|
|
keylen = AES_KEY_SIZE_192;
|
|
cipher_name = "cbc(aes)";
|
|
break;
|
|
case NID_aes_256_cbc:
|
|
keylen = AES_KEY_SIZE_256;
|
|
cipher_name = "cbc(aes)";
|
|
break;
|
|
case NID_aes_128_ctr:
|
|
keylen = AES_KEY_SIZE_128;
|
|
cipher_name = "ctr(aes)";
|
|
break;
|
|
case NID_aes_192_ctr:
|
|
keylen = AES_KEY_SIZE_192;
|
|
cipher_name = "ctr(aes)";
|
|
break;
|
|
case NID_aes_256_ctr:
|
|
keylen = AES_KEY_SIZE_256;
|
|
cipher_name = "ctr(aes)";
|
|
break;
|
|
case NID_aes_128_xts:
|
|
keylen = AES_KEY_SIZE_128;
|
|
cipher_name = "xts(aes)";
|
|
break;
|
|
case NID_aes_256_xts:
|
|
keylen = AES_KEY_SIZE_256;
|
|
cipher_name = "xts(aes)";
|
|
break;
|
|
case NID_des_ecb:
|
|
keylen = DES_KEY_SIZE_64;
|
|
cipher_name = "ecb(des)";
|
|
break;
|
|
case NID_des_cbc:
|
|
keylen = DES_KEY_SIZE_64;
|
|
cipher_name = "cbc(des)";
|
|
break;
|
|
case NID_des_ede3_ecb:
|
|
keylen = DES_KEY_SIZE_192;
|
|
cipher_name = "ecb(des3_ede)";
|
|
break;
|
|
case NID_des_ede3_cbc:
|
|
keylen = DES_KEY_SIZE_192;
|
|
cipher_name = "cbc(des3_ede)";
|
|
break;
|
|
default:
|
|
fprintf(stderr, "Not supported NID %d\n", nid);
|
|
return 0;
|
|
}
|
|
|
|
ivlen = EVP_CIPHER_CTX_iv_length(ctx);
|
|
if (ivlen && iv) {
|
|
memcpy(c->iv, iv, ivlen);
|
|
c->ivlen = ivlen;
|
|
} else if (ivlen) {
|
|
memcpy(c->iv, EVP_CIPHER_CTX_iv(ctx), ivlen);
|
|
c->ivlen = ivlen;
|
|
}
|
|
|
|
if (kcapi_cipher_init(&c->handle, cipher_name, 0)) {
|
|
fprintf(stderr, "Failed to allocate cipher %s \n", cipher_name);
|
|
return 0;
|
|
}
|
|
kcapi_cipher_setkey(c->handle, key, keylen);
|
|
|
|
c->enc = enc;
|
|
return 1;
|
|
}
|
|
|
|
static int aic_do_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
|
|
const unsigned char *in, size_t inlen)
|
|
{
|
|
struct aic_ossl_cipher_ctx *c = EVP_CIPHER_CTX_get_cipher_data(ctx);
|
|
ssize_t processed;
|
|
|
|
if (c->enc)
|
|
processed = kcapi_cipher_encrypt(c->handle, in, inlen, c->iv,
|
|
out, inlen, 0);
|
|
else
|
|
processed = kcapi_cipher_decrypt(c->handle, in, inlen, c->iv,
|
|
out, inlen, 0);
|
|
if ( processed < 0 || processed != inlen)
|
|
return 0;
|
|
return 1;
|
|
}
|
|
|
|
static int aic_cipher_cleanup(EVP_CIPHER_CTX *ctx)
|
|
{
|
|
struct aic_ossl_cipher_ctx *c = EVP_CIPHER_CTX_get_cipher_data(ctx);
|
|
|
|
kcapi_cipher_destroy(c->handle);
|
|
c->handle = 0;
|
|
return 1;
|
|
}
|
|
|
|
static EVP_CIPHER *aic_cipher_alloc(struct aic_cipher *c)
|
|
{
|
|
int flags = c->flags;
|
|
int block_size = c->block_size;
|
|
EVP_CIPHER *cipher;
|
|
|
|
if (c->cipher)
|
|
return c->cipher;
|
|
|
|
switch (flags & EVP_CIPH_MODE) {
|
|
case EVP_CIPH_CTR_MODE:
|
|
OPENSSL_assert(block_size == 1);
|
|
OPENSSL_assert(flags & EVP_CIPH_NO_PADDING);
|
|
break;
|
|
default:
|
|
OPENSSL_assert(block_size != 1);
|
|
OPENSSL_assert(!(flags & EVP_CIPH_NO_PADDING));
|
|
}
|
|
|
|
if (!(cipher = EVP_CIPHER_meth_new(c->nid, block_size, c->key_len)) ||
|
|
!EVP_CIPHER_meth_set_iv_length(cipher, c->iv_len) ||
|
|
!EVP_CIPHER_meth_set_flags(cipher, flags) ||
|
|
!EVP_CIPHER_meth_set_init(cipher, c->init) ||
|
|
!EVP_CIPHER_meth_set_do_cipher(cipher, c->do_cipher) ||
|
|
!EVP_CIPHER_meth_set_cleanup(cipher, c->cleanup) ||
|
|
!EVP_CIPHER_meth_set_impl_ctx_size(cipher, c->ctx_size) ||
|
|
!EVP_CIPHER_meth_set_set_asn1_params(cipher,
|
|
c->set_asn1_parameters) ||
|
|
!EVP_CIPHER_meth_set_get_asn1_params(cipher,
|
|
c->get_asn1_parameters) ||
|
|
!EVP_CIPHER_meth_set_ctrl(cipher, c->ctrl)) {
|
|
EVP_CIPHER_meth_free(cipher);
|
|
cipher = NULL;
|
|
}
|
|
c->cipher = cipher;
|
|
return c->cipher;
|
|
}
|
|
|
|
void aic_skciphers_free(void)
|
|
{
|
|
EVP_CIPHER *cipher;
|
|
int i;
|
|
|
|
for (i = 0; i < OSSL_NELEM(sk_ciphers); i++) {
|
|
cipher = sk_ciphers[i].cipher;
|
|
if (cipher)
|
|
EVP_CIPHER_meth_free(cipher);
|
|
sk_ciphers[i].cipher = NULL;
|
|
}
|
|
}
|
|
|
|
int aic_skciphers(ENGINE *e, const EVP_CIPHER **cipher, const int **nids,
|
|
int nid)
|
|
{
|
|
int i;
|
|
|
|
if (!cipher) {
|
|
int *n = known_cipher_nids;
|
|
|
|
*nids = n;
|
|
for (i = 0; i < OSSL_NELEM(sk_ciphers); i++)
|
|
*n++ = sk_ciphers[i].nid;
|
|
return i;
|
|
}
|
|
|
|
for (i = 0; i < OSSL_NELEM(sk_ciphers); i++) {
|
|
if (nid == sk_ciphers[i].nid) {
|
|
*cipher = aic_cipher_alloc(&sk_ciphers[i]);
|
|
return 1;
|
|
}
|
|
}
|
|
*cipher = NULL;
|
|
return 0;
|
|
}
|