diff options
| author | auth12 <[email protected]> | 2020-07-22 08:34:12 -0700 |
|---|---|---|
| committer | auth12 <[email protected]> | 2020-07-22 08:34:12 -0700 |
| commit | 5015ddb9b1eee748efc24056e46f81888c975f7a (patch) | |
| tree | a810f6ee90f8bfe0e934fdd9142198e6b3862957 /wolfcrypt/src/port/devcrypto/devcrypto_aes.c | |
| download | wolfssl_windows-5015ddb9b1eee748efc24056e46f81888c975f7a.tar.xz wolfssl_windows-5015ddb9b1eee748efc24056e46f81888c975f7a.zip | |
Initial commit
Diffstat (limited to 'wolfcrypt/src/port/devcrypto/devcrypto_aes.c')
| -rw-r--r-- | wolfcrypt/src/port/devcrypto/devcrypto_aes.c | 384 |
1 files changed, 384 insertions, 0 deletions
diff --git a/wolfcrypt/src/port/devcrypto/devcrypto_aes.c b/wolfcrypt/src/port/devcrypto/devcrypto_aes.c new file mode 100644 index 0000000..1f6d09d --- /dev/null +++ b/wolfcrypt/src/port/devcrypto/devcrypto_aes.c @@ -0,0 +1,384 @@ +/* devcrypto_aes.c + * + * Copyright (C) 2006-2020 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * 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 + */ + + +#ifdef HAVE_CONFIG_H + #include <config.h> +#endif + +#include <wolfssl/wolfcrypt/settings.h> +#include <wolfssl/wolfcrypt/error-crypt.h> + +#if !defined(NO_AES) && defined(WOLFSSL_DEVCRYPTO) + +#include <wolfssl/wolfcrypt/aes.h> +#include <wolfssl/wolfcrypt/logging.h> +#include <wolfssl/wolfcrypt/port/devcrypto/wc_devcrypto.h> + +#ifdef NO_INLINE + #include <wolfssl/wolfcrypt/misc.h> +#else + #define WOLFSSL_MISC_INCLUDED + #include <wolfcrypt/src/misc.c> +#endif + + +#if defined(HAVE_AES_CBC) && defined(WOLFSSL_DEVCRYPTO_CBC) +int wc_AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) +{ + struct crypt_op crt; + int ret; + + if (aes == NULL || out == NULL || in == NULL) { + return BAD_FUNC_ARG; + } + + /* encrypt only up to AES block size of date */ + sz = sz - (sz % AES_BLOCK_SIZE); + if (aes->ctx.cfd == -1) { + ret = wc_DevCryptoCreate(&aes->ctx, CRYPTO_AES_CBC, + (byte*)aes->devKey, aes->keylen); + if (ret != 0) + return ret; + } + wc_SetupCryptSym(&crt, &aes->ctx, (byte*)in, sz, out, (byte*)aes->reg, + COP_ENCRYPT); + ret = ioctl(aes->ctx.cfd, CIOCCRYPT, &crt); + if (ret != 0) { + return WC_DEVCRYPTO_E; + } + + /* store iv for next call */ + XMEMCPY(aes->reg, out + sz - AES_BLOCK_SIZE, AES_BLOCK_SIZE); + + return 0; +} + +#ifdef HAVE_AES_DECRYPT +int wc_AesCbcDecrypt(Aes* aes, byte* out, const byte* in, word32 sz) +{ + struct crypt_op crt; + int ret; + + if (aes == NULL || out == NULL || in == NULL || sz % AES_BLOCK_SIZE != 0) { + return BAD_FUNC_ARG; + } + + XMEMCPY(aes->tmp, in + sz - AES_BLOCK_SIZE, AES_BLOCK_SIZE); + if (aes->ctx.cfd == -1) { + ret = wc_DevCryptoCreate(&aes->ctx, CRYPTO_AES_CBC, + (byte*)aes->devKey, aes->keylen); + if (ret != 0) + return ret; + } + wc_SetupCryptSym(&crt, &aes->ctx, (byte*)in, sz, out, (byte*)aes->reg, + COP_DECRYPT); + ret = ioctl(aes->ctx.cfd, CIOCCRYPT, &crt); + if (ret != 0) { + return WC_DEVCRYPTO_E; + } + + XMEMCPY(aes->reg, aes->tmp, AES_BLOCK_SIZE); + return 0; +} +#endif /* HAVE_AES_DECRYPT */ +#endif /* HAVE_AES_CBC && WOLFSSL_DEVCRYPTO_CBC */ + + +#ifdef WOLFSSL_DEVCRYPTO_AES /* all AES algorithms supported */ +int wc_AesSetKey(Aes* aes, const byte* userKey, word32 keylen, + const byte* iv, int dir) +{ +#if defined(AES_MAX_KEY_SIZE) + const word32 max_key_len = (AES_MAX_KEY_SIZE / 8); +#endif + + if (aes == NULL || + !((keylen == 16) || (keylen == 24) || (keylen == 32))) { + return BAD_FUNC_ARG; + } + +#if defined(AES_MAX_KEY_SIZE) + /* Check key length */ + if (keylen > max_key_len) { + return BAD_FUNC_ARG; + } +#endif + aes->keylen = keylen; + aes->rounds = keylen/4 + 6; + +#ifdef WOLFSSL_AES_COUNTER + aes->left = 0; +#endif + aes->ctx.cfd = -1; + XMEMCPY(aes->devKey, userKey, keylen); + + (void)dir; + return wc_AesSetIV(aes, iv); +} + + +/* AES-DIRECT */ +#if defined(WOLFSSL_AES_DIRECT) || defined(HAVE_AES_ECB) + +/* common code between ECB encrypt and decrypt + * returns 0 on success */ +static int wc_DevCrypto_AesDirect(Aes* aes, byte* out, const byte* in, + word32 sz, int dir) +{ + int ret; + struct crypt_op crt; + + if (aes == NULL || out == NULL || in == NULL) { + return BAD_FUNC_ARG; + } + + if (aes->ctx.cfd == -1) { + ret = wc_DevCryptoCreate(&aes->ctx, CRYPTO_AES_ECB, (byte*)aes->devKey, + aes->keylen); + if (ret != 0) + return ret; + } + + wc_SetupCryptSym(&crt, &aes->ctx, (byte*)in, sz, out, NULL, dir); + ret = ioctl(aes->ctx.cfd, CIOCCRYPT, &crt); + if (ret != 0) { + return WC_DEVCRYPTO_E; + } + return 0; +} +#endif + + +#if defined(WOLFSSL_AES_DIRECT) || defined(HAVE_AESCCM) +void wc_AesEncryptDirect(Aes* aes, byte* out, const byte* in) +{ + wc_DevCrypto_AesDirect(aes, out, in, AES_BLOCK_SIZE, COP_ENCRYPT); +} + + +void wc_AesDecryptDirect(Aes* aes, byte* out, const byte* in) +{ + wc_DevCrypto_AesDirect(aes, out, in, AES_BLOCK_SIZE, COP_DECRYPT); +} + + +int wc_AesSetKeyDirect(Aes* aes, const byte* userKey, word32 keylen, + const byte* iv, int dir) +{ + return wc_AesSetKey(aes, userKey, keylen, iv, dir); +} +#endif + + +/* AES-CTR */ +#if defined(WOLFSSL_AES_COUNTER) + +/* Increment AES counter */ +static WC_INLINE void IncrementAesCounter(byte* inOutCtr) +{ + /* in network byte order so start at end and work back */ + int i; + for (i = AES_BLOCK_SIZE - 1; i >= 0; i--) { + if (++inOutCtr[i]) /* we're done unless we overflow */ + return; + } +} + +int wc_AesCtrEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) +{ + int ret; + struct crypt_op crt; + byte* tmp; + + if (aes == NULL || out == NULL || in == NULL) { + return BAD_FUNC_ARG; + } + + /* consume any unused bytes left in aes->tmp */ + tmp = (byte*)aes->tmp + AES_BLOCK_SIZE - aes->left; + while (aes->left && sz) { + *(out++) = *(in++) ^ *(tmp++); + aes->left--; + sz--; + } + + if (aes->ctx.cfd == -1) { + ret = wc_DevCryptoCreate(&aes->ctx, CRYPTO_AES_CTR, (byte*)aes->devKey, + aes->keylen); + if (ret != 0) + return ret; + } + + if (sz > 0) { + /* clear previously leftover data */ + tmp = (byte*)aes->tmp; + XMEMSET(tmp, 0, AES_BLOCK_SIZE); + + /* update IV */ + wc_SetupCryptSym(&crt, &aes->ctx, (byte*)in, sz, out, (byte*)aes->reg, + COP_ENCRYPT); + ret = ioctl(aes->ctx.cfd, CIOCCRYPT, &crt); + if (ret != 0) { + return WC_DEVCRYPTO_E; + } + + /* adjust counter after call to hardware */ + while (sz >= AES_BLOCK_SIZE) { + IncrementAesCounter((byte*)aes->reg); + sz -= AES_BLOCK_SIZE; + out += AES_BLOCK_SIZE; + in += AES_BLOCK_SIZE; + } + } + + /* create key stream for later if needed */ + if (sz > 0) { + Aes tmpAes; + wc_AesSetKey(&tmpAes, (byte*)aes->devKey, aes->keylen, (byte*)aes->reg, + AES_ENCRYPTION); + wc_AesEncryptDirect(&tmpAes, (byte*)aes->tmp, (const byte*)aes->reg); + wc_AesFree(&tmpAes); + IncrementAesCounter((byte*)aes->reg); + + aes->left = AES_BLOCK_SIZE - (sz % AES_BLOCK_SIZE); + } + + return 0; +} +#endif /* WOLFSSL_AES_COUNTER */ + + +#ifdef HAVE_AESGCM + +int wc_AesGcmSetKey(Aes* aes, const byte* key, word32 len) +{ + return wc_AesSetKey(aes, key, len, NULL, AES_ENCRYPTION); +} + + + +/* common code for AES-GCM encrypt/decrypt */ +static int wc_DevCrypto_AesGcm(Aes* aes, byte* out, byte* in, word32 sz, + const byte* iv, word32 ivSz, + byte* authTag, word32 authTagSz, + const byte* authIn, word32 authInSz, + int dir) +{ + struct crypt_auth_op crt = {0}; + int ret; + byte scratch[AES_BLOCK_SIZE]; + + /* argument checks */ + if (aes == NULL || authTagSz > AES_BLOCK_SIZE) { + return BAD_FUNC_ARG; + } + + /* Account for NULL in/out buffers. Up to tag size is still written into + * in/out buffers */ + if (out == NULL) + out = scratch; + if (in == NULL) + in = scratch; + + XMEMSET(scratch, 0, AES_BLOCK_SIZE); + if (aes->ctx.cfd == -1) { + ret = wc_DevCryptoCreate(&aes->ctx, CRYPTO_AES_GCM, (byte*)aes->devKey, + aes->keylen); + if (ret != 0) + return ret; + } + + /* if decrypting then the tag is expected to be at the end of "in" buffer */ + if (dir == COP_DECRYPT) { + XMEMCPY(in + sz, authTag, authTagSz); + sz += authTagSz; + } + else{ + /* get full tag from hardware */ + authTagSz = AES_BLOCK_SIZE; + } + wc_SetupCryptAead(&crt, &aes->ctx, (byte*)in, sz, out, (byte*)iv, ivSz, + dir, (byte*)authIn, authInSz, authTag, authTagSz); + ret = ioctl(aes->ctx.cfd, CIOCAUTHCRYPT, &crt); + if (ret != 0) { + if (dir == COP_DECRYPT) { + return AES_GCM_AUTH_E; + } + else { + return WC_DEVCRYPTO_E; + } + } + + /* after encryption the tag has been placed at the end of "out" buffer */ + if (dir == COP_ENCRYPT) { + XMEMCPY(authTag, out + sz, authTagSz); + } + return 0; +} + + +/* it is assumed that "out" buffer has enough room for cipher text + tag */ +int wc_AesGcmEncrypt(Aes* aes, byte* out, const byte* in, word32 sz, + const byte* iv, word32 ivSz, + byte* authTag, word32 authTagSz, + const byte* authIn, word32 authInSz) +{ + if (authTagSz < WOLFSSL_MIN_AUTH_TAG_SZ) { + WOLFSSL_MSG("GcmEncrypt authTagSz too small error"); + return BAD_FUNC_ARG; + } + + return wc_DevCrypto_AesGcm(aes, out, (byte*)in, sz, iv, ivSz, + authTag, authTagSz, authIn, authInSz, + COP_ENCRYPT); +} + +#if defined(HAVE_AES_DECRYPT) || defined(HAVE_AESGCM_DECRYPT) +/* it is assumed that "in" buffer has enough room for cipher text + tag */ +int wc_AesGcmDecrypt(Aes* aes, byte* out, const byte* in, word32 sz, + const byte* iv, word32 ivSz, + const byte* authTag, word32 authTagSz, + const byte* authIn, word32 authInSz) +{ + return wc_DevCrypto_AesGcm(aes, out, (byte*)in, sz, iv, ivSz, + (byte*)authTag, authTagSz, authIn, authInSz, + COP_DECRYPT); +} +#endif /* HAVE_AES_DECRYPT || HAVE_AESGCM_DECRYPT */ +#endif /* HAVE_AESGCM */ + + +#ifdef HAVE_AES_ECB +int wc_AesEcbEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) +{ + return wc_DevCrypto_AesDirect(aes, out, in, sz, COP_ENCRYPT); +} + + +int wc_AesEcbDecrypt(Aes* aes, byte* out, const byte* in, word32 sz) +{ + return wc_DevCrypto_AesDirect(aes, out, in, sz, COP_DECRYPT); +} +#endif /* HAVE_AES_ECB */ +#endif /* WOLFSSL_DEVCRYPTO_AES */ +#endif /* !NO_AES && WOLFSSL_DEVCRYPTO */ + |