summaryrefslogtreecommitdiff
path: root/arch/arm/mach-tegra/nvddk
diff options
context:
space:
mode:
authorGary King <gking@nvidia.com>2010-06-07 09:46:21 -0700
committerGary King <gking@nvidia.com>2010-06-07 12:35:55 -0700
commit4dcd7a1c7fc8a02c93f9bdf954dda9eab6cad44f (patch)
treef27737f0bd8b03a11902e0ce7dc8ac9627362723 /arch/arm/mach-tegra/nvddk
parent5ce1e0a1a36b2034708366a47a88fce38ef4a252 (diff)
[ARM/tegra] add cryptographic engine (AES) driver
Supports CBC & ECB encryption/decryption, AnsiX9.31 RNG, SSK/SBK/User Key, fine-grain uid/gid access control and ability for privileged user to reset the engine. A device node (/dev/nvaes) is provided to enable access from user-land. based on work done by David Le Tacon (dletacon@nvidia.com) Change-Id: I1a9c29b964ca15e6fec70389c2000306ef604086 Reviewed-on: http://git-master/r/2216 Reviewed-by: David Le Tacon <dletacon@nvidia.com> Reviewed-by: Gary King <gking@nvidia.com> Tested-by: Gary King <gking@nvidia.com>
Diffstat (limited to 'arch/arm/mach-tegra/nvddk')
-rw-r--r--arch/arm/mach-tegra/nvddk/Makefile8
-rw-r--r--arch/arm/mach-tegra/nvddk/NvDdkAES_Dispatch.c92
-rw-r--r--arch/arm/mach-tegra/nvddk/nvddk_aes.c2669
-rw-r--r--arch/arm/mach-tegra/nvddk/nvddk_aes_core_ap20.c617
-rw-r--r--arch/arm/mach-tegra/nvddk/nvddk_aes_core_ap20.h229
-rw-r--r--arch/arm/mach-tegra/nvddk/nvddk_aes_dispatch.c715
-rw-r--r--arch/arm/mach-tegra/nvddk/nvddk_aes_hw.h154
-rw-r--r--arch/arm/mach-tegra/nvddk/nvddk_aes_intf_ap20.c701
-rw-r--r--arch/arm/mach-tegra/nvddk/nvddk_aes_priv.h436
9 files changed, 5620 insertions, 1 deletions
diff --git a/arch/arm/mach-tegra/nvddk/Makefile b/arch/arm/mach-tegra/nvddk/Makefile
index 17d78897e5c6..e6cd0acf9f15 100644
--- a/arch/arm/mach-tegra/nvddk/Makefile
+++ b/arch/arm/mach-tegra/nvddk/Makefile
@@ -10,4 +10,10 @@ obj-y += nvddk_usbphy.o
obj-y += nvddk_usbphy_ap20.o
endif
-obj-$(CONFIG_TEGRA_FUSE) += nvddk_fuse_ap20.o \ No newline at end of file
+obj-$(CONFIG_TEGRA_FUSE) += nvddk_fuse_ap20.o
+
+obj-$(CONFIG_TEGRA_AES) += nvddk_aes_intf_ap20.o
+obj-$(CONFIG_TEGRA_AES_USER) += NvDdkAES_Dispatch.o
+obj-$(CONFIG_TEGRA_AES) += nvddk_aes_core_ap20.o
+obj-$(CONFIG_TEGRA_AES) += nvddk_aes.o
+obj-$(CONFIG_TEGRA_AES_USER) += nvddk_aes_dispatch.o
diff --git a/arch/arm/mach-tegra/nvddk/NvDdkAES_Dispatch.c b/arch/arm/mach-tegra/nvddk/NvDdkAES_Dispatch.c
new file mode 100644
index 000000000000..fe98e7028f5d
--- /dev/null
+++ b/arch/arm/mach-tegra/nvddk/NvDdkAES_Dispatch.c
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2007-2009 NVIDIA Corporation.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of the NVIDIA Corporation nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "nvcommon.h"
+#include "nvos.h"
+#include "nvassert.h"
+#include "nvidlcmd.h"
+#include "nvreftrack.h"
+#include "nvddk_aes.h"
+NvError nvddk_aes_Dispatch( NvU32 function, void *InBuffer, NvU32 InSize, void *OutBuffer, NvU32 OutSize, NvDispatchCtx* Ctx );
+
+// NvDdkAesCommon Package
+typedef enum
+{
+ NvDdkAesCommon_Invalid = 0,
+ NvDdkAesCommon_nvddk_aes_common,
+ NvDdkAesCommon_Num,
+ NvDdkAesCommon_Force32 = 0x7FFFFFFF,
+} NvDdkAesCommon;
+
+// NvDdkAes Package
+typedef enum
+{
+ NvDdkAes_Invalid = 0,
+ NvDdkAes_nvddk_aes,
+ NvDdkAes_Num,
+ NvDdkAes_Force32 = 0x7FFFFFFF,
+} NvDdkAes;
+
+typedef NvError (* NvIdlDispatchFunc)( NvU32 function, void *InBuffer, NvU32 InSize, void *OutBuffer, NvU32 OutSize, NvDispatchCtx* Ctx );
+
+typedef struct NvIdlDispatchTableRec
+{
+ NvU32 PackageId;
+ NvIdlDispatchFunc DispFunc;
+} NvIdlDispatchTable;
+
+static NvIdlDispatchTable gs_DispatchTable[] =
+{
+ { NvDdkAes_nvddk_aes, nvddk_aes_Dispatch },
+ { 0, 0 },
+};
+
+NvError NvDdkAes_Dispatch( void *InBuffer, NvU32 InSize, void *OutBuffer, NvU32 OutSize, NvDispatchCtx* Ctx )
+{
+ NvU32 packid_;
+ NvU32 funcid_;
+ NvIdlDispatchTable *table_;
+
+ NV_ASSERT( InBuffer );
+ NV_ASSERT( OutBuffer );
+
+ packid_ = ((NvU32 *)InBuffer)[0];
+ funcid_ = ((NvU32 *)InBuffer)[1];
+ table_ = gs_DispatchTable;
+
+ if ( packid_-1 >= NV_ARRAY_SIZE(gs_DispatchTable) ||
+ !table_[packid_ - 1].DispFunc )
+ return NvError_IoctlFailed;
+
+ return table_[packid_ - 1].DispFunc( funcid_, InBuffer, InSize,
+ OutBuffer, OutSize, Ctx );
+}
diff --git a/arch/arm/mach-tegra/nvddk/nvddk_aes.c b/arch/arm/mach-tegra/nvddk/nvddk_aes.c
new file mode 100644
index 000000000000..76736c7325a8
--- /dev/null
+++ b/arch/arm/mach-tegra/nvddk/nvddk_aes.c
@@ -0,0 +1,2669 @@
+/*
+ * Copyright (c) 2007-2009 NVIDIA Corporation.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of the NVIDIA Corporation nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "nvos.h"
+#include "nvassert.h"
+#include "nvrm_power.h"
+#include "nvrm_hardware_access.h"
+#include "nvrm_module.h"
+#include "nvrm_xpc.h"
+#if NV_OAL
+#include "nvbl_virtual.h"
+#endif
+#include "nvddk_aes.h"
+#include "nvddk_aes_priv.h"
+
+#include <linux/interrupt.h>
+#include <linux/proc_fs.h>
+
+// RFC3394 key wrap block size is 64 bites which is equal to 8 bytes
+#define AES_RFC_3394_KEY_WRAP_BLOCK_SIZE_BYTES 8
+
+// Number of RFC3394 key wrap blocks for 128 bit key
+#define AES_RFC_3394_NUM_OF_BLOCKS_FOR_128BIT_KEY 2
+
+static void AesCoreRequestHwAccess(void);
+static void AesCoreReleaseHwAccess(void);
+static void AesCoreDeAllocateRmMemory(AesHwContext *const pAesHwCtxt);
+static void AesCoreFreeUpEngine(AesCoreEngine *const pAesCoreEngine);
+static void AesCorePowerUp(const AesCoreEngine *const pAesCoreEngine);
+static void AesCorePowerDown(const AesCoreEngine *const pAesCoreEngine);
+static void AesCoreDeInitializeEngineSpace(const AesHwContext *const pAesHwCtxt);
+
+static NvError AesCoreAllocateRmMemory(AesHwContext *const pAesHwCtxt);
+static NvError AesCoreLoadSskToSecureScratchAndLock(const AesHwContext *const pAesHwCtxt, const NvU8 *const pKey);
+static NvError AesCoreDfsBusyHint(const NvRmDeviceHandle hRmDevice, const NvU32 PowerClientId, const NvBool IsDfsOn);
+static NvError AesCoreInitializeEngineSpace(const NvRmDeviceHandle hRmDevice, AesHwContext *const pAesHwCtxt);
+static NvError AesCoreInitEngine(const NvRmDeviceHandle hRmDevice);
+static NvError AesCoreGetCapabilities(const NvRmDeviceHandle hRmDevice, AesHwCapabilities **const ppCaps);
+static NvError AesCoreClearUserKey(const NvDdkAes *const pAesClient);
+static NvError
+AesCoreWrapKey(
+ const NvDdkAes *const pAesClient,
+ const NvU8 *const pOrgKey,
+ const NvU8 *const pOrgIv,
+ NvU8 *const pWrappedKey,
+ NvU8 *const pWrappedIv);
+static NvError
+AesCoreUnWrapKey(
+ const NvDdkAes *const pAesClient,
+ const NvU8 *const pWrappedKey,
+ const NvU8 *const pWrappedIv,
+ NvU8 *const pOrgKey,
+ NvU8 *const pOrgIv);
+static NvError
+AesCoreGetFreeSlot(
+ const AesCoreEngine *const pAesCoreEngine,
+ AesHwEngine *const pEngine,
+ AesHwKeySlot *const pKeySlot);
+static NvError
+AesCoreSetKey(
+ const NvDdkAesKeyType KeyType,
+ const NvBool IsDedicatedSlot,
+ const NvU8 *const pKeyData,
+ NvDdkAes *const pAesClient);
+static NvError
+AesCoreProcessBuffer(
+ const NvU32 SkipOffset,
+ const NvU32 SrcBufferSize,
+ const NvU32 DestBufferSize,
+ NvDdkAes *const pAesClient,
+ const NvU8 *pSrcBuffer,
+ NvU8 *pDestBuffer);
+static NvError
+AesCoreEcbProcessBuffer(
+ const NvDdkAes *const pAesClient,
+ const NvU8 *const pInputBuffer,
+ const NvU32 BufSize,
+ const NvBool IsEncrypt,
+ NvU8 *const pOutputBuffer);
+
+static NvBool
+AesCoreIsUserKeyCleared(
+ const AesHwEngine Engine,
+ const AesHwKeySlot KeySlot,
+ AesHwContext *const pAesHwCtxt);
+static NvBool
+AesCoreIsSbkCleared(
+ const AesHwEngine Engine,
+ const AesHwKeySlot EncryptSlot,
+ const AesHwKeySlot DecryptSlot,
+ AesHwContext *const pAesHwCtxt);
+static NvBool
+AesCoreIsSskLocked(
+ const AesHwEngine Engine,
+ const AesHwKeySlot EncryptSlot,
+ const AesHwKeySlot DecryptSlot,
+ AesHwContext *const pAesHwCtxt);
+
+static AesCoreEngine *gs_pAesCoreEngine = NULL;
+static NvOsMutexHandle gs_hAesCoreEngineMutex = {0};
+
+// Original IV of size 8 byte which is used in RFC 3394 key wrap algorithm
+static NvU8 gs_OriginalIV[AES_RFC_IV_LENGTH_BYTES] =
+{
+ 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6
+};
+
+extern NvRmDeviceHandle s_hRmGlobal;
+
+#define NVDDK_AES_CHECK_INPUT_PARAMS(parm) \
+ do \
+ { \
+ if ((!pAesClient) || (!parm)) \
+ return NvError_BadParameter; \
+ } while (0)
+
+#define NVDDK_AES_CHECK_ROOT_PERMISSION \
+ do \
+ { \
+ if ((0 != pAesClient->uid) || (0 != pAesClient->gid)) \
+ return NvError_AesPermissionDenied; \
+ } while (0)
+
+#define NVDDK_AES_CHECK_USER_IDENTITY \
+ do \
+ { \
+ if ((pAesClient->uid != current->cred->uid) || (pAesClient->gid != current->cred->gid)) \
+ return NvError_AesPermissionDenied; \
+ } while (0)
+
+#define NVDDK_AES_CHECK_INTERFACE(ctxt, engine) \
+ do \
+ { \
+ NV_ASSERT(ctxt); \
+ NV_ASSERT(ctxt->ppEngineCaps); \
+ NV_ASSERT(ctxt->ppEngineCaps[engine]); \
+ NV_ASSERT(ctxt->ppEngineCaps[engine]->pAesInterf); \
+ } while (0)
+
+#define NVDDK_AES_CHECK_INTERFACE_FUNC(ctxt, engine, func) \
+ do \
+ { \
+ NV_ASSERT(ctxt->ppEngineCaps[engine]->pAesInterf->func); \
+ } while (0)
+
+NvError NvDdkAesOpen(NvU32 InstanceId, NvDdkAesHandle *phAes)
+{
+ NvError e = NvSuccess;
+ NvDdkAes *pAes = NULL;
+ NvOsMutexHandle hMutex = NULL;
+
+ if (!phAes)
+ return NvError_BadParameter;
+
+ // Create mutex (if not already done)
+ if (NULL == gs_hAesCoreEngineMutex)
+ {
+ e = NvOsMutexCreate(&hMutex);
+ if (NvSuccess != e)
+ return e;
+ if (0 != NvOsAtomicCompareExchange32((NvS32*)&gs_hAesCoreEngineMutex, 0, (NvS32)hMutex))
+ NvOsMutexDestroy(hMutex);
+ }
+
+ NvOsMutexLock(gs_hAesCoreEngineMutex);
+
+ // Create client record
+ pAes = NvOsAlloc(sizeof(NvDdkAes));
+ if (!pAes)
+ {
+ e = NvError_InsufficientMemory;
+ goto fail;
+ }
+ NvOsMemset(pAes, 0, sizeof(NvDdkAes));
+
+ if (NULL == gs_pAesCoreEngine)
+ {
+ // Init engine
+ NV_CHECK_ERROR_CLEANUP(AesCoreInitEngine(s_hRmGlobal));
+ // Power up
+ AesCorePowerUp(gs_pAesCoreEngine);
+ }
+
+ // Add client
+ gs_pAesCoreEngine->OpenCount++;
+
+ pAes->pAesCoreEngine = gs_pAesCoreEngine;
+
+ // Store uid & gid
+ pAes->uid = current->cred->uid;
+ pAes->gid = current->cred->gid;
+
+ *phAes = pAes;
+ NvOsMutexUnlock(gs_hAesCoreEngineMutex);
+ return NvSuccess;
+
+fail:
+ NvDdkAesClose(pAes);
+ NvOsMutexUnlock(gs_hAesCoreEngineMutex);
+ return e;
+}
+
+void NvDdkAesClose(NvDdkAesHandle hAes)
+{
+ NvDdkAes *pAesClient = (NvDdkAes *)hAes;
+
+ if (!hAes)
+ return;
+
+ if ((pAesClient->uid != current->cred->uid) || (pAesClient->gid != current->cred->gid))
+ return;
+
+ if (pAesClient->pAesCoreEngine)
+ {
+ NvOsMutexLock(gs_hAesCoreEngineMutex);
+
+ // Check if client is using USER key with dedicated slot then free the associated client slot
+ if ((NV_TRUE == pAesClient->IsDedicatedSlot) &&
+ (NvDdkAesKeyType_UserSpecified == pAesClient->KeyType))
+ {
+ // Client is using USER key with dedicated slot. So
+ // clear the key in hardware slot and free the associated client slot
+ if (!AesCoreClearUserKey(pAesClient))
+ {
+ NV_ASSERT(!"Failed to clear User Key");
+ }
+ pAesClient->pAesCoreEngine->IsKeySlotUsed[pAesClient->Engine][pAesClient->KeySlot] = NV_FALSE;
+ }
+
+ // Free up engine if no other clients
+ if (pAesClient->pAesCoreEngine->OpenCount)
+ {
+ // Decrement the Open count
+ pAesClient->pAesCoreEngine->OpenCount--;
+
+ if (0 == pAesClient->pAesCoreEngine->OpenCount)
+ {
+ // Power down
+ AesCorePowerDown(pAesClient->pAesCoreEngine);
+
+ // Free up resources
+ AesCoreFreeUpEngine(pAesClient->pAesCoreEngine);
+
+ NvOsFree(gs_pAesCoreEngine);
+ gs_pAesCoreEngine = NULL;
+ }
+ }
+ NvOsMutexUnlock(gs_hAesCoreEngineMutex);
+ }
+
+ NvOsMemset(pAesClient, 0, sizeof(NvDdkAes));
+ NvOsFree(pAesClient);
+}
+
+NvError NvDdkAesSelectKey(NvDdkAesHandle hAes, const NvDdkAesKeyInfo *pKeyInfo)
+{
+ NvDdkAes *pAesClient = (NvDdkAes*)hAes;
+
+ NVDDK_AES_CHECK_INPUT_PARAMS(pKeyInfo);
+
+ NVDDK_AES_CHECK_USER_IDENTITY;
+
+ switch (pKeyInfo->KeyLength)
+ {
+ case NvDdkAesKeySize_128Bit:
+ return AesCoreSetKey(
+ pKeyInfo->KeyType,
+ pKeyInfo->IsDedicatedKeySlot,
+ pKeyInfo->Key,
+ pAesClient);
+ break;
+ case NvDdkAesKeySize_192Bit:
+ case NvDdkAesKeySize_256Bit:
+ default:
+ return NvError_NotSupported;
+ }
+}
+
+NvError NvDdkAesSelectOperation(NvDdkAesHandle hAes, const NvDdkAesOperation *pOperation)
+{
+ NvDdkAes *pAesClient = (NvDdkAes*)hAes;
+
+ NVDDK_AES_CHECK_INPUT_PARAMS(pOperation);
+
+ NVDDK_AES_CHECK_USER_IDENTITY;
+
+ switch (pOperation->OpMode)
+ {
+ case NvDdkAesOperationalMode_Cbc:
+ case NvDdkAesOperationalMode_Ecb:
+ pAesClient->IsEncryption = pOperation->IsEncrypt;
+ break;
+ case NvDdkAesOperationalMode_AnsiX931:
+ pAesClient->IsEncryption = NV_TRUE;
+ break;
+ default:
+ return NvError_NotSupported;
+ }
+
+ pAesClient->OpMode = pOperation->OpMode;
+ return NvSuccess;
+}
+
+NvError NvDdkAesSetInitialVector(NvDdkAesHandle hAes, const NvU8 *pInitialVector, NvU32 VectorSize)
+{
+ NvDdkAes *pAesClient = (NvDdkAes*)hAes;
+
+ NVDDK_AES_CHECK_INPUT_PARAMS(pInitialVector);
+
+ NVDDK_AES_CHECK_USER_IDENTITY;
+
+ if (NvDdkAesOperationalMode_Ecb == pAesClient->OpMode)
+ return NvError_NotSupported;
+
+ if (VectorSize < NvDdkAesConst_IVLengthBytes)
+ return NvError_BadParameter;
+
+ // Set the IV and store it with client
+ NvOsMemcpy(pAesClient->Iv, pInitialVector, NvDdkAesConst_IVLengthBytes);
+
+ return NvSuccess;
+}
+
+NvError NvDdkAesGetInitialVector(NvDdkAesHandle hAes, NvU32 VectorSize, NvU8 *pInitialVector)
+{
+ NvDdkAes *pAesClient = (NvDdkAes*)hAes;
+
+ NVDDK_AES_CHECK_INPUT_PARAMS(pInitialVector);
+
+ NVDDK_AES_CHECK_USER_IDENTITY;
+
+ if (VectorSize < NvDdkAesConst_IVLengthBytes)
+ return NvError_BadParameter;
+
+ NvOsMemcpy(pInitialVector, pAesClient->Iv, NvDdkAesConst_IVLengthBytes);
+
+ return NvSuccess;
+}
+
+NvError
+NvDdkAesProcessBuffer(
+ NvDdkAesHandle hAes,
+ NvU32 SrcBufferSize,
+ NvU32 DestBufferSize,
+ const NvU8 *pSrcBuffer,
+ NvU8 *pDestBuffer)
+{
+ if ((!hAes) || (!pSrcBuffer) || (!pDestBuffer))
+ return NvError_BadParameter;
+
+ return AesCoreProcessBuffer(0, SrcBufferSize, DestBufferSize, (NvDdkAes*)hAes, pSrcBuffer, pDestBuffer);
+}
+
+NvError NvDdkAesClearSecureBootKey(NvDdkAesHandle hAes)
+{
+ NvError e = NvSuccess;
+ NvDdkAes *pAesClient = (NvDdkAes*)hAes;
+ AesHwContext *pAesHwCtxt = NULL;
+ AesHwEngine Engine;
+
+ if (!hAes)
+ return NvError_BadParameter;
+
+ NVDDK_AES_CHECK_USER_IDENTITY;
+
+ NVDDK_AES_CHECK_ROOT_PERMISSION;
+
+ NvOsMutexLock(gs_hAesCoreEngineMutex);
+
+ // Get the AES H/W context
+ NV_ASSERT(pAesClient->pAesCoreEngine);
+ pAesHwCtxt = &pAesClient->pAesCoreEngine->AesHwCtxt;
+
+ for (Engine = AesHwEngine_A; Engine < AesHwEngine_Num; Engine++)
+ {
+ AesHwEngine SbkEngine = pAesClient->pAesCoreEngine->SbkEngine[Engine];
+ AesHwKeySlot DecryptSlot = pAesClient->pAesCoreEngine->SbkDecryptSlot;
+ AesHwKeySlot EncryptSlot = pAesClient->pAesCoreEngine->SbkEncryptSlot;
+
+ if (SbkEngine < AesHwEngine_Num)
+ {
+ NVDDK_AES_CHECK_INTERFACE(pAesHwCtxt, SbkEngine);
+
+ AesCoreRequestHwAccess();
+
+ // Clear the SBK encrypt key
+ NVDDK_AES_CHECK_INTERFACE_FUNC(pAesHwCtxt, SbkEngine, AesHwClearKeyAndIv);
+ pAesHwCtxt->ppEngineCaps[SbkEngine]->pAesInterf->AesHwClearKeyAndIv(SbkEngine, EncryptSlot, pAesHwCtxt);
+
+ // Clear the SBK decrypt key
+ pAesHwCtxt->ppEngineCaps[SbkEngine]->pAesInterf->AesHwClearKeyAndIv(SbkEngine, DecryptSlot, pAesHwCtxt);
+
+ AesCoreReleaseHwAccess();
+
+ if (!AesCoreIsSbkCleared(SbkEngine, EncryptSlot, DecryptSlot, pAesHwCtxt))
+ {
+ // Return error if SB clear check fails
+ e = NvError_AesClearSbkFailed;
+ }
+ }
+ }
+
+ NvOsMutexUnlock(gs_hAesCoreEngineMutex);
+ return e;
+}
+
+NvError NvDdkAesLockSecureStorageKey(NvDdkAesHandle hAes)
+{
+ NvError e = NvSuccess;
+ NvDdkAes *pAesClient = (NvDdkAes*)hAes;
+ AesHwContext *pAesHwCtxt = NULL;
+ AesHwEngine Engine;
+
+ if (!hAes)
+ return NvError_BadParameter;
+
+ NVDDK_AES_CHECK_USER_IDENTITY;
+
+ NVDDK_AES_CHECK_ROOT_PERMISSION;
+
+ NvOsMutexLock(gs_hAesCoreEngineMutex);
+
+ // Get the AES H/W context
+ NV_ASSERT(pAesClient->pAesCoreEngine);
+ pAesHwCtxt = &pAesClient->pAesCoreEngine->AesHwCtxt;
+
+ for (Engine = AesHwEngine_A; Engine < AesHwEngine_Num; Engine++)
+ {
+ AesHwEngine SskEngine = pAesClient->pAesCoreEngine->SskEngine[Engine];
+ AesHwKeySlot DecryptSlot = pAesClient->pAesCoreEngine->SskDecryptSlot;
+ AesHwKeySlot EncryptSlot = pAesClient->pAesCoreEngine->SskEncryptSlot;
+
+ if (SskEngine < AesHwEngine_Num)
+ {
+ NVDDK_AES_CHECK_INTERFACE(pAesHwCtxt, SskEngine);
+
+ AesCoreRequestHwAccess();
+
+ // Disable permissions to the SSK key slot in the AES engine
+ NVDDK_AES_CHECK_INTERFACE_FUNC(pAesHwCtxt, SskEngine, AesHwLockSskReadWrites);
+ pAesHwCtxt->ppEngineCaps[SskEngine]->pAesInterf->AesHwLockSskReadWrites(pAesHwCtxt, SskEngine);
+
+ AesCoreReleaseHwAccess();
+
+ if (!AesCoreIsSskLocked(SskEngine, EncryptSlot, DecryptSlot, pAesHwCtxt))
+ {
+ e = NvError_AesLockSskFailed;
+ goto fail;
+ }
+
+ // Also, lock the Secure scratch registers
+ NV_CHECK_ERROR_CLEANUP(AesCoreLoadSskToSecureScratchAndLock(pAesHwCtxt, NULL));
+ }
+ }
+
+fail:
+ NvOsMutexUnlock(gs_hAesCoreEngineMutex);
+ return e;
+}
+
+NvError
+NvDdkAesSetAndLockSecureStorageKey(
+ NvDdkAesHandle hAes,
+ NvDdkAesKeySize KeyLength,
+ const NvU8 *pSecureStorageKey)
+{
+ NvError e = NvSuccess;
+ NvDdkAes *pAesClient = (NvDdkAes*)hAes;
+ AesHwContext *pAesHwCtxt = NULL;
+ AesHwIv Iv;
+ AesHwEngine Engine;
+
+ NVDDK_AES_CHECK_INPUT_PARAMS(pSecureStorageKey);
+
+ NVDDK_AES_CHECK_USER_IDENTITY;
+
+ NVDDK_AES_CHECK_ROOT_PERMISSION;
+
+ switch (KeyLength)
+ {
+ case NvDdkAesKeySize_128Bit:
+ break;
+ case NvDdkAesKeySize_192Bit:
+ case NvDdkAesKeySize_256Bit:
+ default:
+ return NvError_NotSupported;
+ }
+
+ NvOsMutexLock(gs_hAesCoreEngineMutex);
+
+ // Get the AES H/W context
+ NV_ASSERT(pAesClient->pAesCoreEngine);
+ pAesHwCtxt = &pAesClient->pAesCoreEngine->AesHwCtxt;
+
+ for (Engine = AesHwEngine_A; Engine < AesHwEngine_Num; Engine++)
+ {
+ AesHwEngine SskEngine = pAesClient->pAesCoreEngine->SskEngine[Engine];
+ AesHwKeySlot DecryptSlot = pAesClient->pAesCoreEngine->SskDecryptSlot;
+ AesHwKeySlot EncryptSlot = pAesClient->pAesCoreEngine->SskEncryptSlot;
+
+ if (SskEngine < AesHwEngine_Num)
+ {
+ // Setup the SSK with Zero IV
+ NvOsMemset(&Iv, 0, NvDdkAesConst_IVLengthBytes);
+
+ NVDDK_AES_CHECK_INTERFACE(pAesHwCtxt, SskEngine);
+
+ AesCoreRequestHwAccess();
+
+ // Setup SSK Key table for encryption
+ NVDDK_AES_CHECK_INTERFACE_FUNC(pAesHwCtxt, SskEngine, AesHwSetKeyAndIv);
+ pAesHwCtxt->ppEngineCaps[SskEngine]->pAesInterf->AesHwSetKeyAndIv(
+ SskEngine,
+ EncryptSlot,
+ (AesHwKey*)pSecureStorageKey,
+ &Iv,
+ NV_TRUE,
+ pAesHwCtxt);
+
+ // Setup SSK Key table for decryption
+ pAesHwCtxt->ppEngineCaps[SskEngine]->pAesInterf->AesHwSetKeyAndIv(
+ SskEngine,
+ DecryptSlot,
+ (AesHwKey*)pSecureStorageKey,
+ &Iv,
+ NV_FALSE,
+ pAesHwCtxt);
+
+ // Disable the read / write access
+ NVDDK_AES_CHECK_INTERFACE_FUNC(pAesHwCtxt, SskEngine, AesHwLockSskReadWrites);
+ pAesHwCtxt->ppEngineCaps[SskEngine]->pAesInterf->AesHwLockSskReadWrites(pAesHwCtxt, SskEngine);
+
+ AesCoreReleaseHwAccess();
+
+ if (!AesCoreIsSskLocked(SskEngine, EncryptSlot, DecryptSlot, pAesHwCtxt))
+ {
+ e = NvError_AesLockSskFailed;
+ goto fail;
+ }
+
+ // Store the SSK in the Secure scratch and lock
+ NV_CHECK_ERROR_CLEANUP(AesCoreLoadSskToSecureScratchAndLock(pAesHwCtxt, pSecureStorageKey));
+ }
+ }
+
+fail:
+ NvOsMutexUnlock(gs_hAesCoreEngineMutex);
+ return e;
+}
+
+NvError NvDdkAesDisableCrypto(NvDdkAesHandle hAes)
+{
+ NvError e = NvSuccess;
+ NvDdkAes *pAesClient = (NvDdkAes*)hAes;
+ AesHwContext *pAesHwCtxt = NULL;
+ AesHwEngine Engine;
+
+ if (!hAes)
+ return NvError_BadParameter;
+
+ NVDDK_AES_CHECK_USER_IDENTITY;
+
+ NVDDK_AES_CHECK_ROOT_PERMISSION;
+
+ NvOsMutexLock(gs_hAesCoreEngineMutex);
+
+ // Get the AES H/W context
+ NV_ASSERT(pAesClient->pAesCoreEngine);
+ pAesHwCtxt = &pAesClient->pAesCoreEngine->AesHwCtxt;
+
+ AesCoreRequestHwAccess();
+
+ for (Engine = AesHwEngine_A; Engine < AesHwEngine_Num; Engine++)
+ {
+ NVDDK_AES_CHECK_INTERFACE(pAesHwCtxt, Engine);
+ NVDDK_AES_CHECK_INTERFACE_FUNC(pAesHwCtxt, Engine, AesHwDisableEngine);
+
+ if (NvSuccess != pAesHwCtxt->ppEngineCaps[Engine]->pAesInterf->AesHwDisableEngine(pAesHwCtxt, Engine))
+ e = NvError_AesDisableCryptoFailed;
+ }
+
+ AesCoreReleaseHwAccess();
+
+ if (NvSuccess == e)
+ {
+ // Mark engine as disabled
+ pAesClient->pAesCoreEngine->IsEngineDisabled = NV_TRUE;
+ }
+
+ NvOsMutexUnlock(gs_hAesCoreEngineMutex);
+ return e;
+}
+
+NvError NvDdkAesGetCapabilities(NvDdkAesHandle hAes, NvDdkAesCapabilities *pCapabilities)
+{
+ NvDdkAes *pAesClient = (NvDdkAes*)hAes;
+
+ NVDDK_AES_CHECK_INPUT_PARAMS(pCapabilities);
+
+ NVDDK_AES_CHECK_USER_IDENTITY;
+
+ pCapabilities->OptimalBufferAlignment = 1;
+
+ return NvSuccess;
+}
+
+/**
+ * Request access to HW.
+ */
+void AesCoreRequestHwAccess(void)
+{
+#if !NV_OAL
+ NvRmXpcModuleAcquire(NvRmModuleID_Vde);
+ NvRmXpcModuleAcquire(NvRmModuleID_BseA);
+#endif
+}
+
+/**
+ * Release access to HW.
+ */
+void AesCoreReleaseHwAccess(void)
+{
+#if !NV_OAL
+ NvRmXpcModuleRelease(NvRmModuleID_BseA);
+ NvRmXpcModuleRelease(NvRmModuleID_Vde);
+#endif
+}
+
+#if NV_OAL
+
+/**
+ * Allocate the RM memory for key table and dma buffers.
+ *
+ * @param pAesHwCtxt Pointer to the AES H/W engine context.
+ *
+ * @retval NvError_Success if memory is allocated successfully.
+ * @retval NvError_InsufficientMemory if memory is not allocated successfully.
+ */
+NvError AesCoreAllocateRmMemory(AesHwContext *const pAesHwCtxt)
+{
+ NvError e;
+ NvU8 *pKeyTabVirtAddr = NULL;
+ NvRmPhysAddr KeyTabPhyAddr = NVBL_AES_KEY_TABLE_ADDR;
+ NvU8 *pDmaVirtAddr = NULL;
+ NvRmPhysAddr DmaPhyAddr = 0;
+ AesHwEngine Engine;
+ NvU32 size = 0;
+
+ NV_ASSERT(pAesHwCtxt);
+
+ NvOsMutexLock(gs_hAesCoreEngineMutex);
+
+ // Calculate total size needed
+ for (Engine = AesHwEngine_A; Engine < AesHwEngine_Num; Engine++)
+ size += (pAesHwCtxt->KeyTableSize[Engine] + NvDdkAesKeySize_128Bit);
+
+ // Get virtual address
+ NV_ASSERT_SUCCESS(NvOsPhysicalMemMap(
+ KeyTabPhyAddr,
+ size,
+ NvOsMemAttribute_Uncached,
+ NVOS_MEM_READ_WRITE,
+ (void*)&pKeyTabVirtAddr));
+
+ size = 0;
+ for (Engine = AesHwEngine_A; Engine < AesHwEngine_Num; Engine++)
+ {
+ pAesHwCtxt->KeyTablePhyAddr[Engine] = KeyTabPhyAddr + size;
+ pAesHwCtxt->pKeyTableVirAddr[Engine] = pKeyTabVirtAddr + size;
+ size = pAesHwCtxt->KeyTableSize[Engine] + NvDdkAesKeySize_128Bit;
+ }
+
+ // Allocate DMA buffer for both the engines
+ size = AES_HW_DMA_BUFFER_SIZE_BYTES * AesHwEngine_Num;
+ NV_CHECK_ERROR_CLEANUP(NvRmMemHandleCreate(pAesHwCtxt->hRmDevice, &pAesHwCtxt->hDmaMemBuf, size));
+
+ NV_CHECK_ERROR_CLEANUP(NvRmMemAlloc(
+ pAesHwCtxt->hDmaMemBuf,
+ NULL,
+ 0,
+ AES_HW_DMA_ADDR_ALIGNMENT,
+ NvOsMemAttribute_Uncached));
+
+ // Get the virtual address
+ pDmaVirtAddr = (NvU8 *)NvRmMemPin((NvRmMemHandle)pAesHwCtxt->hDmaMemBuf);
+
+ // Get the physical address
+ DmaPhyAddr = NvBlVaToPa(pDmaVirtAddr);
+ if (NVBL_INVALID_PA == DmaPhyAddr)
+ {
+ NV_ASSERT(0);
+ e = NvError_InvalidAddress;
+ goto fail;
+ }
+
+ // Get a uncached alias to the buffer
+ if (NvOsPhysicalMemMap(DmaPhyAddr, size, NvOsMemAttribute_Uncached, NVOS_MEM_READ_WRITE, (void **)&pDmaVirtAddr) !=
+ NvError_Success)
+ {
+ NV_ASSERT(0);
+ e = NvError_InvalidAddress;
+ goto fail;
+ }
+
+ for (Engine = AesHwEngine_A; Engine < AesHwEngine_Num; Engine++)
+ {
+ pAesHwCtxt->DmaPhyAddr[Engine] = DmaPhyAddr + (Engine * AES_HW_DMA_BUFFER_SIZE_BYTES);
+ pAesHwCtxt->pDmaVirAddr[Engine] = pDmaVirtAddr + (Engine * AES_HW_DMA_BUFFER_SIZE_BYTES);
+ }
+
+ NvOsMutexUnlock(gs_hAesCoreEngineMutex);
+ return NvError_Success;
+
+fail:
+ AesCoreDeAllocateRmMemory(pAesHwCtxt);
+ NvOsMutexUnlock(gs_hAesCoreEngineMutex);
+ return e;
+}
+
+/**
+ * De-allocate the RM memory allocated with .AesAllocateRmMemory().
+ *
+ * @param pAesHwCtxt Pointer to the AES Hw engine context.
+ *
+ * @retval None.
+ */
+void AesCoreDeAllocateRmMemory(AesHwContext *const pAesHwCtxt);
+{
+ NV_ASSERT(pAesHwCtxt);
+
+ NvOsMutexLock(gs_hAesCoreEngineMutex);
+
+ if (pAesHwCtxt->hKeyTableMemBuf)
+ {
+ NvRmMemUnpin(pAesHwCtxt->hKeyTableMemBuf);
+ NvRmMemHandleFree(pAesHwCtxt->hKeyTableMemBuf);
+ pAesHwCtxt->hKeyTableMemBuf = NULL;
+ }
+
+ if (pAesHwCtxt->hDmaMemBuf)
+ {
+ NvRmMemUnpin(pAesHwCtxt->hDmaMemBuf);
+ NvRmMemHandleFree(pAesHwCtxt->hDmaMemBuf);
+ pAesHwCtxt->hDmaMemBuf = NULL;
+ }
+
+ NvOsMutexUnlock(gs_hAesCoreEngineMutex);
+}
+
+#else
+
+/**
+ * Allocate the RM memory for key table and dma buffers.
+ *
+ * @param pAesHwCtxt Pointer to the AES H/W engine context.
+ *
+ * @retval NvError_Success if memory is allocated successfully.
+ * @retval NvError_InsufficientMemory if memory is not allocated successfully.
+ */
+NvError AesCoreAllocateRmMemory(AesHwContext *const pAesHwCtxt)
+{
+ NvError e;
+ static const NvRmHeap s_Heaps[] = {NvRmHeap_IRam};
+ NvU8 *pKeyTabVirtAddr = NULL;
+ NvRmPhysAddr KeyTabPhyAddr = 0;
+ NvU8 * pDmaVirtAddr = NULL;
+ NvRmPhysAddr DmaPhyAddr = 0;
+ // Allocate key table memory for both the engines
+ NvU32 size = NVBL_AES_KEY_TABLE_OFFSET;
+ AesHwEngine Engine;
+
+ NV_ASSERT(pAesHwCtxt);
+
+ NvOsMutexLock(gs_hAesCoreEngineMutex);
+
+ // Calculate total size needed
+ for (Engine = AesHwEngine_A; Engine < AesHwEngine_Num; Engine++)
+ size += (pAesHwCtxt->KeyTableSize[Engine] + NvDdkAesKeySize_128Bit);
+
+ NV_CHECK_ERROR(NvRmMemHandleCreate(pAesHwCtxt->hRmDevice, &pAesHwCtxt->hKeyTableMemBuf, size));
+
+ if (!pAesHwCtxt->hKeyTableMemBuf)
+ {
+ e = NvError_InsufficientMemory;
+ goto fail;
+ }
+
+ NV_CHECK_ERROR_CLEANUP(NvRmMemAlloc(
+ pAesHwCtxt->hKeyTableMemBuf,
+ s_Heaps,
+ NV_ARRAY_SIZE(s_Heaps),
+ AES_HW_KEY_TABLE_ADDR_ALIGNMENT,
+ NvOsMemAttribute_Uncached));
+
+ KeyTabPhyAddr = NvRmMemPin(pAesHwCtxt->hKeyTableMemBuf) + NVBL_AES_KEY_TABLE_OFFSET;
+
+ NV_CHECK_ERROR_CLEANUP(NvRmPhysicalMemMap(
+ KeyTabPhyAddr,
+ (size - NVBL_AES_KEY_TABLE_OFFSET),
+ NVOS_MEM_READ_WRITE,
+ NvOsMemAttribute_Uncached,
+ (void **)&pKeyTabVirtAddr));
+
+ size = 0;
+ for (Engine = AesHwEngine_A; Engine < AesHwEngine_Num; Engine++)
+ {
+ pAesHwCtxt->KeyTablePhyAddr[Engine] = KeyTabPhyAddr + size;
+ pAesHwCtxt->pKeyTableVirAddr[Engine] = pKeyTabVirtAddr + size;
+ size = pAesHwCtxt->KeyTableSize[Engine] + NvDdkAesKeySize_128Bit;
+ }
+
+ // Allocate DMA buffer for both the engines
+ size = AES_HW_DMA_BUFFER_SIZE_BYTES * AesHwEngine_Num;
+
+ NV_CHECK_ERROR_CLEANUP(NvRmMemHandleCreate(pAesHwCtxt->hRmDevice, &pAesHwCtxt->hDmaMemBuf, size));
+
+ NV_CHECK_ERROR_CLEANUP(NvRmMemAlloc(
+ pAesHwCtxt->hDmaMemBuf,
+ NULL,
+ 0,
+ AES_HW_DMA_ADDR_ALIGNMENT,
+ NvOsMemAttribute_Uncached));
+
+ DmaPhyAddr = NvRmMemPin(pAesHwCtxt->hDmaMemBuf);
+
+ NV_CHECK_ERROR_CLEANUP(NvRmMemMap(pAesHwCtxt->hDmaMemBuf, 0, size, NVOS_MEM_READ_WRITE, (void **)&pDmaVirtAddr));
+
+ for (Engine = AesHwEngine_A; Engine < AesHwEngine_Num; Engine++)
+ {
+ pAesHwCtxt->DmaPhyAddr[Engine] = DmaPhyAddr + (Engine * AES_HW_DMA_BUFFER_SIZE_BYTES);
+ pAesHwCtxt->pDmaVirAddr[Engine] = pDmaVirtAddr + (Engine * AES_HW_DMA_BUFFER_SIZE_BYTES);
+ }
+
+ NvOsMutexUnlock(gs_hAesCoreEngineMutex);
+ return NvSuccess;
+
+fail:
+ AesCoreDeAllocateRmMemory(pAesHwCtxt);
+ NvOsMutexUnlock(gs_hAesCoreEngineMutex);
+ return e;
+}
+
+/**
+ * De-allocate the RM memory allocated with .AesAllocateRmMemory().
+ *
+ * @param pAesHwCtxt Pointer to the AES Hw engine context.
+ *
+ * @retval None.
+ */
+void AesCoreDeAllocateRmMemory(AesHwContext *const pAesHwCtxt)
+{
+ NV_ASSERT(pAesHwCtxt);
+
+ NvOsMutexLock(gs_hAesCoreEngineMutex);
+
+ if (pAesHwCtxt->hKeyTableMemBuf)
+ {
+ AesHwEngine Engine;
+ NvU32 size = 0;
+
+ for (Engine = AesHwEngine_A; Engine < AesHwEngine_Num; Engine++)
+ size += (pAesHwCtxt->KeyTableSize[Engine] + NvDdkAesKeySize_128Bit);
+
+ NvRmPhysicalMemUnmap(pAesHwCtxt->pKeyTableVirAddr[0], size);
+ NvRmMemUnpin(pAesHwCtxt->hKeyTableMemBuf);
+ NvRmMemHandleFree(pAesHwCtxt->hKeyTableMemBuf);
+ pAesHwCtxt->hKeyTableMemBuf = NULL;
+ }
+
+ if (pAesHwCtxt->hDmaMemBuf)
+ {
+ NvRmMemUnmap(
+ pAesHwCtxt->hDmaMemBuf,
+ pAesHwCtxt->pDmaVirAddr[0],
+ AES_HW_DMA_BUFFER_SIZE_BYTES * AesHwEngine_Num);
+ NvRmMemUnpin(pAesHwCtxt->hDmaMemBuf);
+ NvRmMemHandleFree(pAesHwCtxt->hDmaMemBuf);
+ pAesHwCtxt->hDmaMemBuf = NULL;
+ }
+
+ NvOsMutexUnlock(gs_hAesCoreEngineMutex);
+}
+
+#endif // NV_OAL
+
+/**
+ * Select the key specified by the client in the AES engine.
+ *
+
+ * @param KeyType Key type.
+ * @param IsDedicatedSlot NV_TRUE if slot is dedicated, NV_FALSE if not.
+ * @param pKeyData Pointer to the key data.
+ * @param pAesClient Pointer to AES client.
+ *
+ * @retval NvSuccess if successfully completed.
+ * @retval NvError_NotSupported if operation is not supported.
+ */
+NvError
+AesCoreSetKey(
+ const NvDdkAesKeyType KeyType,
+ const NvBool IsDedicatedSlot,
+ const NvU8 *const pKeyData,
+ NvDdkAes *const pAesClient)
+{
+ NvError e = NvSuccess;
+ AesHwContext *pAesHwCtxt = NULL;
+ AesHwEngine Engine;
+ AesHwKeySlot KeySlot;
+
+ NV_ASSERT(pAesClient);
+
+ if ((NvDdkAesKeyType_SecureBootKey == KeyType) || (NvDdkAesKeyType_SecureStorageKey == KeyType))
+ {
+ NVDDK_AES_CHECK_ROOT_PERMISSION;
+ }
+
+ pAesClient->IsDedicatedSlot = NV_FALSE;
+
+ NvOsMutexLock(gs_hAesCoreEngineMutex);
+
+ // Get the AES H/W context
+ NV_ASSERT(pAesClient->pAesCoreEngine);
+ pAesHwCtxt = &pAesClient->pAesCoreEngine->AesHwCtxt;
+
+ switch (KeyType)
+ {
+ case NvDdkAesKeyType_SecureBootKey:
+ pAesClient->Engine = pAesClient->pAesCoreEngine->SbkEngine[0];
+ pAesClient->KeySlot = pAesClient->IsEncryption ?
+ pAesClient->pAesCoreEngine->SbkEncryptSlot : pAesClient->pAesCoreEngine->SbkDecryptSlot;
+ break;
+ case NvDdkAesKeyType_SecureStorageKey:
+ pAesClient->Engine = pAesClient->pAesCoreEngine->SskEngine[0];
+ pAesClient->KeySlot = pAesClient->IsEncryption ?
+ pAesClient->pAesCoreEngine->SskEncryptSlot : pAesClient->pAesCoreEngine->SskDecryptSlot;
+ break;
+ case NvDdkAesKeyType_UserSpecified:
+ pAesClient->IsDedicatedSlot = IsDedicatedSlot;
+ if (!IsDedicatedSlot)
+ {
+ // It is not dedicated slot => obfuscate the key
+ // Wrap the key using RFC3394 key wrapping algorithm
+ // The wrapped key and RFCwrapped IV will be stored in client handle
+ NV_CHECK_ERROR_CLEANUP(AesCoreWrapKey(
+ pAesClient,
+ pKeyData,
+ gs_OriginalIV,
+ pAesClient->Key,
+ pAesClient->WrappedIv));
+ goto done;
+ }
+ // It is dedicated slot
+ NV_CHECK_ERROR_CLEANUP(AesCoreGetFreeSlot(pAesClient->pAesCoreEngine, &Engine, &KeySlot));
+ pAesClient->pAesCoreEngine->IsKeySlotUsed[Engine][KeySlot] = NV_TRUE;
+ pAesClient->Engine = Engine;
+ pAesClient->KeySlot = KeySlot;
+
+ // Initialize IV to zeros
+ NvOsMemset(pAesClient->Iv, 0, NvDdkAesConst_IVLengthBytes);
+ NVDDK_AES_CHECK_INTERFACE(pAesHwCtxt, Engine);
+
+ AesCoreRequestHwAccess();
+
+ // Setup Key table
+ NVDDK_AES_CHECK_INTERFACE_FUNC(pAesHwCtxt, Engine, AesHwSetKeyAndIv);
+ pAesHwCtxt->ppEngineCaps[pAesClient->Engine]->pAesInterf->AesHwSetKeyAndIv(
+ pAesClient->Engine,
+ pAesClient->KeySlot,
+ (AesHwKey *)pKeyData,
+ (AesHwIv *)pAesClient->Iv,
+ pAesClient->IsEncryption,
+ pAesHwCtxt);
+
+ AesCoreReleaseHwAccess();
+ break;
+ default:
+ goto fail;
+ }
+
+ NVDDK_AES_CHECK_INTERFACE(pAesHwCtxt, pAesClient->Engine);
+
+ AesCoreRequestHwAccess();
+
+ // Select Key slot
+ NVDDK_AES_CHECK_INTERFACE_FUNC(pAesHwCtxt, pAesClient->Engine, AesHwSelectKeyIvSlot);
+ pAesHwCtxt->ppEngineCaps[pAesClient->Engine]->pAesInterf->AesHwSelectKeyIvSlot(
+ pAesClient->Engine,
+ pAesClient->KeySlot,
+ pAesHwCtxt);
+
+ // Get the IV and store it with client
+ NVDDK_AES_CHECK_INTERFACE_FUNC(pAesHwCtxt, pAesClient->Engine, AesHwGetIv);
+ pAesHwCtxt->ppEngineCaps[pAesClient->Engine]->pAesInterf->AesHwGetIv(
+ pAesHwCtxt,
+ pAesClient->Engine,
+ pAesClient->KeySlot,
+ (AesHwIv *)pAesClient->Iv);
+
+ AesCoreReleaseHwAccess();
+
+done:
+ // Store the Key Type for this client
+ pAesClient->KeyType = KeyType;
+
+fail:
+ NvOsMutexUnlock(gs_hAesCoreEngineMutex);
+ return e;
+}
+
+/**
+ * Load the SSK into the secure scratch and disables the write permissions.
+ * Note: If Key is not specified then this API locks the Secure Scratch registers.
+ *
+ * @param pAesHwCtxt Pointer to AES H/W context.
+ * @param pKey Pointer to the key. If pKey == NULL then key will not be set to the
+ * secure scratch registers, but locks the Secure scratch register.
+ *
+ * @retval NvSuccess if successfully completed.
+ */
+NvError AesCoreLoadSskToSecureScratchAndLock(const AesHwContext *const pAesHwCtxt, const NvU8 *const pKey)
+{
+ NvError e = NvSuccess;
+ NvRmPhysAddr PhysAdr;
+ NvU32 BankSize;
+ NvU32 RmPwrClientId = 0;
+
+ NVDDK_AES_CHECK_INTERFACE(pAesHwCtxt, 0);
+
+ // Get the secure scratch base address
+ NvRmModuleGetBaseAddress(pAesHwCtxt->hRmDevice, NVRM_MODULE_ID(NvRmModuleID_Pmif, 0), &PhysAdr, &BankSize);
+
+ // Register with Power Manager
+ RmPwrClientId = NVRM_POWER_CLIENT_TAG('A','E','S','2');
+
+ NV_CHECK_ERROR_CLEANUP(NvRmPowerRegister(pAesHwCtxt->hRmDevice, NULL, &RmPwrClientId));
+
+ // Enable the Voltage
+ NV_CHECK_ERROR_CLEANUP(NvRmPowerVoltageControl(
+ pAesHwCtxt->hRmDevice,
+ NvRmModuleID_Pmif,
+ RmPwrClientId,
+ NvRmVoltsUnspecified,
+ NvRmVoltsUnspecified,
+ NULL,
+ 0,
+ NULL));
+
+ // Emable the clock to the PMIC
+ NV_CHECK_ERROR_CLEANUP(NvRmPowerModuleClockControl(pAesHwCtxt->hRmDevice, NvRmModuleID_Pmif, RmPwrClientId, NV_TRUE));
+
+ // Store SSK and lock the secure scratch -- engine doesn't matter here
+ // since the key is being provided and not really read from the key table of an engine .here
+ // If pKey == NULL this call will disable the write permissions to the scratch registers.
+ AesCoreRequestHwAccess();
+
+ NVDDK_AES_CHECK_INTERFACE_FUNC(pAesHwCtxt, 0, AesHwLoadSskToSecureScratchAndLock);
+ pAesHwCtxt->ppEngineCaps[0]->pAesInterf->AesHwLoadSskToSecureScratchAndLock(PhysAdr, (AesHwKey *)pKey, BankSize);
+
+ AesCoreReleaseHwAccess();
+
+fail:
+ // Disable the clock to the PMIC
+ NV_ASSERT_SUCCESS(NvRmPowerModuleClockControl(pAesHwCtxt->hRmDevice, NvRmModuleID_Pmif, RmPwrClientId, NV_FALSE));
+
+ // Disable the Voltage
+ NV_ASSERT_SUCCESS(NvRmPowerVoltageControl(
+ pAesHwCtxt->hRmDevice,
+ NvRmModuleID_Pmif,
+ RmPwrClientId,
+ NvRmVoltsOff,
+ NvRmVoltsOff,
+ NULL,
+ 0,
+ NULL));
+
+ // Unregister driver from Power Manager
+ NvRmPowerUnRegister(pAesHwCtxt->hRmDevice, RmPwrClientId);
+ return e;
+}
+
+/**
+ * Check the SBK clear by encrypting / decrypting the known data.
+ *
+ * @param Engine Engine on which encryption and decryption need to be performed
+ * @param EncryptSlot Key slot where encrypt key is located.
+ * @param DecryptSlot Key slot where decrypt key is located.
+ * @param pAesHwCtxt Pointer to AES H/W context.
+ *
+ * @retval NV_TRUE if successfully encryption and decryption is done else NV_FALSE.
+ */
+NvBool AesCoreIsSbkCleared(
+ const AesHwEngine Engine,
+ const AesHwKeySlot EncryptSlot,
+ const AesHwKeySlot DecryptSlot,
+ AesHwContext *const pAesHwCtxt)
+{
+ NvError e = NvSuccess;
+ AesHwIv ZeroIv;
+ NvU32 i;
+
+ // Known Good data
+ static NvU8 s_GoldData[NvDdkAesConst_BlockLengthBytes] =
+ {
+ 0x00, 0x01, 0x02, 0x03,
+ 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0A, 0x0B,
+ 0x0C, 0x0D, 0x0E, 0x0F
+ };
+
+ // Encrypted data for above known data with Zero key and Zero IV
+ static NvU8 s_EncryptDataWithZeroKeyTable[NvDdkAesConst_BlockLengthBytes] =
+ {
+ 0x7A, 0xCA, 0x0F, 0xD9,
+ 0xBC, 0xD6, 0xEC, 0x7C,
+ 0x9F, 0x97, 0x46, 0x66,
+ 0x16, 0xE6, 0xA2, 0x82
+ };
+
+ // Encrypted data for above known data with Zero key and Zero IV
+ static NvU8 s_EncryptDataWithZeroKeySchedule[NvDdkAesConst_BlockLengthBytes] =
+ {
+ 0x18, 0x9D, 0x19, 0xEA,
+ 0xDB, 0xA7, 0xE3, 0x0E,
+ 0xD9, 0x72, 0x80, 0x8F,
+ 0x3F, 0x2B, 0xA0, 0x30
+ };
+
+ NvU8 *pEncryptData = NULL;
+ NvU8 EncryptBuffer[NvDdkAesConst_BlockLengthBytes];
+ NvU8 DecryptBuffer[NvDdkAesConst_BlockLengthBytes];
+
+ NVDDK_AES_CHECK_INTERFACE(pAesHwCtxt, Engine);
+
+ NvOsMutexLock(gs_hAesCoreEngineMutex);
+
+ if (pAesHwCtxt->ppEngineCaps[Engine]->IsHwKeySchedGenSupported)
+ pEncryptData = s_EncryptDataWithZeroKeyTable;
+ else
+ pEncryptData = s_EncryptDataWithZeroKeySchedule;
+
+ NvOsMemset(EncryptBuffer, 0, NvDdkAesConst_BlockLengthBytes);
+ NvOsMemset(DecryptBuffer, 0, NvDdkAesConst_BlockLengthBytes);
+ NvOsMemset(&ZeroIv, 0, sizeof(AesHwIv));
+
+ AesCoreRequestHwAccess();
+
+ // Select Encrypt Key slot
+ NVDDK_AES_CHECK_INTERFACE_FUNC(pAesHwCtxt, Engine, AesHwSelectKeyIvSlot);
+ pAesHwCtxt->ppEngineCaps[Engine]->pAesInterf->AesHwSelectKeyIvSlot(Engine, EncryptSlot, pAesHwCtxt);
+
+ // Set the Zero IV for test data
+ NVDDK_AES_CHECK_INTERFACE_FUNC(pAesHwCtxt, Engine, AesHwSetIv);
+ NV_CHECK_ERROR_CLEANUP(pAesHwCtxt->ppEngineCaps[Engine]->pAesInterf->AesHwSetIv(
+ Engine,
+ EncryptSlot,
+ &ZeroIv,
+ pAesHwCtxt));
+
+ // Process the buffer for encryption
+ NVDDK_AES_CHECK_INTERFACE_FUNC(pAesHwCtxt, Engine, AesHwStartEngine);
+ NV_CHECK_ERROR_CLEANUP(pAesHwCtxt->ppEngineCaps[Engine]->pAesInterf->AesHwStartEngine(
+ Engine,
+ NvDdkAesConst_BlockLengthBytes,
+ s_GoldData,
+ NV_TRUE,
+ NvDdkAesOperationalMode_Cbc,
+ EncryptBuffer,
+ pAesHwCtxt));
+
+ // Select Decrypt Key slot
+ NVDDK_AES_CHECK_INTERFACE_FUNC(pAesHwCtxt, Engine, AesHwSelectKeyIvSlot);
+ pAesHwCtxt->ppEngineCaps[Engine]->pAesInterf->AesHwSelectKeyIvSlot(Engine, DecryptSlot, pAesHwCtxt);
+
+ // Set the Zero IV for test data
+ NVDDK_AES_CHECK_INTERFACE_FUNC(pAesHwCtxt, Engine, AesHwSetIv);
+ NV_CHECK_ERROR_CLEANUP(pAesHwCtxt->ppEngineCaps[Engine]->pAesInterf->AesHwSetIv(
+ Engine,
+ DecryptSlot,
+ &ZeroIv,
+ pAesHwCtxt));
+
+ // Process the buffer for encryption
+ NVDDK_AES_CHECK_INTERFACE_FUNC(pAesHwCtxt, Engine, AesHwStartEngine);
+ NV_CHECK_ERROR_CLEANUP(pAesHwCtxt->ppEngineCaps[Engine]->pAesInterf->AesHwStartEngine(
+ Engine,
+ NvDdkAesConst_BlockLengthBytes,
+ EncryptBuffer,
+ NV_FALSE,
+ NvDdkAesOperationalMode_Cbc,
+ DecryptBuffer,
+ pAesHwCtxt));
+
+ // Clear the IV in the engine before we leave
+ NVDDK_AES_CHECK_INTERFACE_FUNC(pAesHwCtxt, Engine, AesHwClearIv);
+ pAesHwCtxt->ppEngineCaps[Engine]->pAesInterf->AesHwClearIv(Engine, EncryptSlot, pAesHwCtxt);
+ pAesHwCtxt->ppEngineCaps[Engine]->pAesInterf->AesHwClearIv(Engine, DecryptSlot, pAesHwCtxt);
+
+ // Clear the DMA buffer before we leave from this operation.
+ NvOsMemset(pAesHwCtxt->pDmaVirAddr[Engine], 0, AES_HW_DMA_BUFFER_SIZE_BYTES);
+
+ for (i = 0; i < NvDdkAesConst_BlockLengthBytes; i++)
+ {
+ if ((pEncryptData[i] != EncryptBuffer[i]) || (s_GoldData[i] != DecryptBuffer[i]))
+ goto fail;
+ }
+
+ AesCoreReleaseHwAccess();
+ NvOsMutexUnlock(gs_hAesCoreEngineMutex);
+ return NV_TRUE;
+
+fail:
+ // Clear the DMA buffer before we leave from this operation
+ NvOsMemset(pAesHwCtxt->pDmaVirAddr[Engine], 0, AES_HW_DMA_BUFFER_SIZE_BYTES);
+ AesCoreReleaseHwAccess();
+ NvOsMutexUnlock(gs_hAesCoreEngineMutex);
+ return NV_FALSE;
+}
+
+/**
+ * Check the SSK lock is successfully done or not by writing zero key into SSK.
+ *
+ * @param Engine Engine where SSK is set.
+ * @param EncryptSlot Key slot where encrypt key is located.
+ * @param DecryptSlot Key slot where decrypt key is located.
+ * @param pAesHwCtxt Pointer to AES H/W context.
+ *
+ * @retval NV_TRUE if successfully SSK is locked else NV_FALSE.
+ */
+NvBool
+AesCoreIsSskLocked(
+ const AesHwEngine Engine,
+ const AesHwKeySlot EncryptSlot,
+ const AesHwKeySlot DecryptSlot,
+ AesHwContext *const pAesHwCtxt)
+{
+ NvError e = NvSuccess;
+ AesHwIv ZeroIv;
+ AesHwKey ZeroKey;
+ NvU32 i;
+
+ static NvU8 s_GoldData[NvDdkAesConst_BlockLengthBytes] =
+ {
+ 0x00, 0x11, 0x22, 0x33,
+ 0x44, 0x55, 0x66, 0x77,
+ 0x88, 0x99, 0xAA, 0xBB,
+ 0xCC, 0xDD, 0xEE, 0xFF
+ };
+
+ NvU8 EncryptBuffer1[NvDdkAesConst_BlockLengthBytes];
+ NvU8 DecryptBuffer1[NvDdkAesConst_BlockLengthBytes];
+ NvU8 EncryptBuffer2[NvDdkAesConst_BlockLengthBytes];
+ NvU8 DecryptBuffer2[NvDdkAesConst_BlockLengthBytes];
+
+ NVDDK_AES_CHECK_INTERFACE(pAesHwCtxt, Engine);
+
+ NvOsMemset(EncryptBuffer1, 0, NvDdkAesConst_BlockLengthBytes);
+ NvOsMemset(DecryptBuffer1, 0, NvDdkAesConst_BlockLengthBytes);
+ NvOsMemset(EncryptBuffer2, 0, NvDdkAesConst_BlockLengthBytes);
+ NvOsMemset(DecryptBuffer2, 0, NvDdkAesConst_BlockLengthBytes);
+ NvOsMemset(&ZeroIv, 0, sizeof(AesHwIv));
+ NvOsMemset(&ZeroKey, 0, sizeof(AesHwKey));
+
+ NvOsMutexLock(gs_hAesCoreEngineMutex);
+
+ AesCoreRequestHwAccess();
+
+ // Select Encrypt Key slot
+ NVDDK_AES_CHECK_INTERFACE_FUNC(pAesHwCtxt, Engine, AesHwSelectKeyIvSlot);
+ pAesHwCtxt->ppEngineCaps[Engine]->pAesInterf->AesHwSelectKeyIvSlot(Engine, EncryptSlot, pAesHwCtxt);
+
+ // Set the Zero IV for test data
+ NVDDK_AES_CHECK_INTERFACE_FUNC(pAesHwCtxt, Engine, AesHwSetIv);
+ NV_CHECK_ERROR_CLEANUP(pAesHwCtxt->ppEngineCaps[Engine]->pAesInterf->AesHwSetIv(
+ Engine,
+ EncryptSlot,
+ &ZeroIv,
+ pAesHwCtxt));
+
+ // Process the buffer for encryption
+ NVDDK_AES_CHECK_INTERFACE_FUNC(pAesHwCtxt, Engine, AesHwStartEngine);
+ NV_CHECK_ERROR_CLEANUP(pAesHwCtxt->ppEngineCaps[Engine]->pAesInterf->AesHwStartEngine(
+ Engine,
+ NvDdkAesConst_BlockLengthBytes,
+ s_GoldData,
+ NV_TRUE,
+ NvDdkAesOperationalMode_Cbc,
+ EncryptBuffer1,
+ pAesHwCtxt));
+
+ // Select Decrypt Key slot
+ NVDDK_AES_CHECK_INTERFACE_FUNC(pAesHwCtxt, Engine, AesHwSelectKeyIvSlot);
+ pAesHwCtxt->ppEngineCaps[Engine]->pAesInterf->AesHwSelectKeyIvSlot(Engine, DecryptSlot, pAesHwCtxt);
+
+ // Set the Zero IV for test data
+ NVDDK_AES_CHECK_INTERFACE_FUNC(pAesHwCtxt, Engine, AesHwSetIv);
+ NV_CHECK_ERROR_CLEANUP(pAesHwCtxt->ppEngineCaps[Engine]->pAesInterf->AesHwSetIv(
+ Engine,
+ DecryptSlot,
+ &ZeroIv,
+ pAesHwCtxt));
+
+ // Process the buffer for encryption
+ NVDDK_AES_CHECK_INTERFACE_FUNC(pAesHwCtxt, Engine, AesHwStartEngine);
+ NV_CHECK_ERROR_CLEANUP(pAesHwCtxt->ppEngineCaps[Engine]->pAesInterf->AesHwStartEngine(
+ Engine,
+ NvDdkAesConst_BlockLengthBytes,
+ s_GoldData,
+ NV_FALSE,
+ NvDdkAesOperationalMode_Cbc,
+ DecryptBuffer1,
+ pAesHwCtxt));
+
+ // Set Zero key to the SSK slot and try encryption / decryption with
+ // known data and check data after encryption and decryption are same with SSK
+
+ // Setup SSK Key table for encryption
+ NVDDK_AES_CHECK_INTERFACE_FUNC(pAesHwCtxt, Engine, AesHwSetKeyAndIv);
+ pAesHwCtxt->ppEngineCaps[Engine]->pAesInterf->AesHwSetKeyAndIv(
+ Engine,
+ EncryptSlot,
+ &ZeroKey,
+ &ZeroIv,
+ NV_TRUE,
+ pAesHwCtxt);
+
+ // Setup SSK Key table for encryption
+ NVDDK_AES_CHECK_INTERFACE_FUNC(pAesHwCtxt, Engine, AesHwSetKeyAndIv);
+ pAesHwCtxt->ppEngineCaps[Engine]->pAesInterf->AesHwSetKeyAndIv(
+ Engine,
+ DecryptSlot,
+ &ZeroKey,
+ &ZeroIv,
+ NV_FALSE,
+ pAesHwCtxt);
+
+ // Select Encrypt Key slot
+ NVDDK_AES_CHECK_INTERFACE_FUNC(pAesHwCtxt, Engine, AesHwSelectKeyIvSlot);
+ pAesHwCtxt->ppEngineCaps[Engine]->pAesInterf->AesHwSelectKeyIvSlot(Engine, EncryptSlot, pAesHwCtxt);
+
+ // Set the Zero IV for test data
+ NVDDK_AES_CHECK_INTERFACE_FUNC(pAesHwCtxt, Engine, AesHwSetIv);
+ NV_CHECK_ERROR_CLEANUP(pAesHwCtxt->ppEngineCaps[Engine]->pAesInterf->AesHwSetIv(
+ Engine,
+ EncryptSlot,
+ &ZeroIv,
+ pAesHwCtxt));
+
+ // Process the buffer for encryption
+ NVDDK_AES_CHECK_INTERFACE_FUNC(pAesHwCtxt, Engine, AesHwStartEngine);
+ NV_CHECK_ERROR_CLEANUP(pAesHwCtxt->ppEngineCaps[Engine]->pAesInterf->AesHwStartEngine(
+ Engine,
+ NvDdkAesConst_BlockLengthBytes,
+ s_GoldData,
+ NV_TRUE,
+ NvDdkAesOperationalMode_Cbc,
+ EncryptBuffer2,
+ pAesHwCtxt));
+
+ // Select Decrypt Key slot
+ NVDDK_AES_CHECK_INTERFACE_FUNC(pAesHwCtxt, Engine, AesHwSelectKeyIvSlot);
+ pAesHwCtxt->ppEngineCaps[Engine]->pAesInterf->AesHwSelectKeyIvSlot(Engine, DecryptSlot, pAesHwCtxt);
+
+ // Set the Zero IV for test data
+ NVDDK_AES_CHECK_INTERFACE_FUNC(pAesHwCtxt, Engine, AesHwSetIv);
+ NV_CHECK_ERROR_CLEANUP(pAesHwCtxt->ppEngineCaps[Engine]->pAesInterf->AesHwSetIv(
+ Engine,
+ DecryptSlot,
+ &ZeroIv,
+ pAesHwCtxt));
+
+ // Process the buffer for encryption
+ NVDDK_AES_CHECK_INTERFACE_FUNC(pAesHwCtxt, Engine, AesHwStartEngine);
+ NV_CHECK_ERROR_CLEANUP(pAesHwCtxt->ppEngineCaps[Engine]->pAesInterf->AesHwStartEngine(
+ Engine,
+ NvDdkAesConst_BlockLengthBytes,
+ s_GoldData,
+ NV_FALSE,
+ NvDdkAesOperationalMode_Cbc,
+ DecryptBuffer2,
+ pAesHwCtxt));
+
+ // Clear the IV in the engine before we leave
+ NVDDK_AES_CHECK_INTERFACE_FUNC(pAesHwCtxt, Engine, AesHwClearIv);
+ pAesHwCtxt->ppEngineCaps[Engine]->pAesInterf->AesHwClearIv(Engine, EncryptSlot, pAesHwCtxt);
+ pAesHwCtxt->ppEngineCaps[Engine]->pAesInterf->AesHwClearIv(Engine, DecryptSlot, pAesHwCtxt);
+
+ // Clear the DMA buffer before we leave from this operation.
+ NvOsMemset(pAesHwCtxt->pDmaVirAddr[Engine], 0, AES_HW_DMA_BUFFER_SIZE_BYTES);
+
+ // Check encrypt and decrypt output is same before and after zero key set to SSK
+ // If both encrypt and decrypt data match then SSK lock is OK
+ for (i = 0; i < NvDdkAesConst_BlockLengthBytes; i++)
+ {
+ if ((EncryptBuffer1[i] != EncryptBuffer2[i]) || (DecryptBuffer1[i] != DecryptBuffer2[i]))
+ goto fail;
+ }
+
+ AesCoreReleaseHwAccess();
+ NvOsMutexUnlock(gs_hAesCoreEngineMutex);
+ return NV_TRUE;
+
+fail:
+ // Clear the DMA buffer before we leave from this operation.
+ NvOsMemset(pAesHwCtxt->pDmaVirAddr[Engine], 0, AES_HW_DMA_BUFFER_SIZE_BYTES);
+ AesCoreReleaseHwAccess();
+ NvOsMutexUnlock(gs_hAesCoreEngineMutex);
+ return NV_FALSE;
+}
+
+/**
+ * Add the Busy hints to boost or reduce the CPU, System and EMC frequencies.
+ *
+ * @param hRmDevice RM device handle.
+ * @param PowerClientId The client ID obtained during Power registration.
+ * @param IsDfsOn Indicator to boost the frequency, if set to NV_TRUE. Cancel the
+ * DFS busy hint if set to NV_FALSE.
+ *
+ * @retval NvSuccess if busy hint request completed successfully.
+ * @retval NvError_NotSupported if DFS is disabled.
+ * @retval NvError_BadValue if specified client ID is not registered.
+ * @retval NvError_InsufficientMemory if failed to allocate memory for busy hints.
+ */
+NvError AesCoreDfsBusyHint(const NvRmDeviceHandle hRmDevice, const NvU32 PowerClientId, const NvBool IsDfsOn)
+{
+ #define AES_EMC_BOOST_FREQ_KHZ 100000
+ #define AES_SYS_BOOST_FREQ_KHZ 100000
+
+ NvRmDfsBusyHint AesBusyHintOn[] =
+ {
+ {NvRmDfsClockId_Emc, NV_WAIT_INFINITE, AES_EMC_BOOST_FREQ_KHZ, NV_TRUE},
+ {NvRmDfsClockId_System, NV_WAIT_INFINITE, AES_SYS_BOOST_FREQ_KHZ, NV_TRUE}
+ };
+
+ NvRmDfsBusyHint AesBusyHintOff[] =
+ {
+ {NvRmDfsClockId_Emc, 0, 0, NV_TRUE},
+ {NvRmDfsClockId_System, 0, 0, NV_TRUE}
+ };
+
+ NV_ASSERT(hRmDevice);
+
+ if (IsDfsOn)
+ {
+ return NvRmPowerBusyHintMulti(
+ hRmDevice,
+ PowerClientId,
+ AesBusyHintOn,
+ NV_ARRAY_SIZE(AesBusyHintOn),
+ NvRmDfsBusyHintSyncMode_Async);
+ }
+ else
+ {
+ return NvRmPowerBusyHintMulti(
+ hRmDevice,
+ PowerClientId,
+ AesBusyHintOff,
+ NV_ARRAY_SIZE(AesBusyHintOff),
+ NvRmDfsBusyHintSyncMode_Async);
+ }
+}
+
+/**
+ * Populate the structure for AES context with the engine base address.
+ *
+ * @param hRmDevice Rm device handle.
+ * @param pAesHwCtxt Pointer to AES H/W context.
+ *
+ * @retval NvSuccess if successfully completed.
+ *
+ */
+NvError AesCoreInitializeEngineSpace(const NvRmDeviceHandle hRmDevice, AesHwContext *const pAesHwCtxt)
+{
+ NvError e = NvSuccess;
+ AesHwEngine Engine;
+
+ NV_ASSERT(hRmDevice);
+ NV_ASSERT(pAesHwCtxt);
+
+ NvOsMutexLock(gs_hAesCoreEngineMutex);
+
+ for (Engine = AesHwEngine_A; Engine < AesHwEngine_Num; Engine++)
+ {
+ switch (Engine)
+ {
+ case AesHwEngine_A:
+ // Get the controller base address
+ NvRmModuleGetBaseAddress(
+ hRmDevice,
+ NVRM_MODULE_ID(NvRmModuleID_Vde, 0),
+ &pAesHwCtxt->PhysAdr[Engine],
+ &pAesHwCtxt->BankSize[Engine]);
+ break;
+ case AesHwEngine_B:
+ // Get the controller base address
+ NvRmModuleGetBaseAddress(
+ hRmDevice,
+ NVRM_MODULE_ID(NvRmModuleID_BseA, 0),
+ &pAesHwCtxt->PhysAdr[Engine],
+ &pAesHwCtxt->BankSize[Engine]);
+ break;
+ default:
+ break;
+ }
+
+ // Map the physical memory to virtual memory
+ NV_CHECK_ERROR_CLEANUP(NvRmPhysicalMemMap(
+ pAesHwCtxt->PhysAdr[Engine],
+ pAesHwCtxt->BankSize[Engine],
+ NVOS_MEM_READ_WRITE,
+ NvOsMemAttribute_Uncached,
+ (void **)&pAesHwCtxt->pVirAdr[Engine]));
+ }
+
+ NvOsMutexUnlock(gs_hAesCoreEngineMutex);
+ return NvSuccess;
+
+fail:
+ NvOsMutexUnlock(gs_hAesCoreEngineMutex);
+ return e;
+}
+
+/**
+ * Unmap all engine space.
+ *
+ * @param pAesHwCtxt Pointer to AES H/W context.
+ *
+ * @retval None.
+ *
+ */
+void AesCoreDeInitializeEngineSpace(const AesHwContext *const pAesHwCtxt)
+{
+ AesHwEngine Engine;
+
+ NV_ASSERT(pAesHwCtxt);
+
+ NvOsMutexLock(gs_hAesCoreEngineMutex);
+
+ // Clean up resources
+ for (Engine = AesHwEngine_A; Engine < AesHwEngine_Num; Engine++)
+ {
+ // UnMap the virtual Address
+ NvRmPhysicalMemUnmap(pAesHwCtxt->pVirAdr[Engine], pAesHwCtxt->BankSize[Engine]);
+ }
+
+ NvOsMutexUnlock(gs_hAesCoreEngineMutex);
+}
+
+/**
+ * Find the unused key slot.
+ *
+ * @param pAesCoreEngine Pointer to AES core engine.
+ * @param pEngine Pointer to the engine.
+ * @param pKeySlot Pointer to the key slot.
+ *
+ * @retval NvSuccess if successfully completed.
+ * @retval NvError_AlreadyAllocated if all slots are allocated.
+ */
+NvError
+AesCoreGetFreeSlot(
+ const AesCoreEngine *const pAesCoreEngine,
+ AesHwEngine *const pEngine,
+ AesHwKeySlot *const pKeySlot)
+{
+ AesHwEngine Engine;
+ AesHwKeySlot KeySlot;
+ const AesHwContext *pAesHwCtxt;
+
+ NV_ASSERT(pAesCoreEngine);
+ NV_ASSERT(pEngine);
+ NV_ASSERT(pKeySlot);
+
+ NvOsMutexLock(gs_hAesCoreEngineMutex);
+
+ // Get the AES H/W context
+ pAesHwCtxt = &pAesCoreEngine->AesHwCtxt;
+
+ // Get the free slot
+ for (Engine = AesHwEngine_A; Engine < AesHwEngine_Num; Engine++)
+ {
+ NV_ASSERT(pAesHwCtxt->ppEngineCaps);
+ NV_ASSERT(pAesHwCtxt->ppEngineCaps[Engine]);
+ for (KeySlot = AesHwKeySlot_0;
+ KeySlot < (NvU32)(pAesHwCtxt->ppEngineCaps[Engine]->NumSlotsSupported);
+ KeySlot++)
+ {
+ if (!pAesCoreEngine->IsKeySlotUsed[Engine][KeySlot])
+ {
+ *pEngine = Engine;
+ *pKeySlot = KeySlot;
+
+ NvOsMutexUnlock(gs_hAesCoreEngineMutex);
+ return NvSuccess;
+ }
+ }
+ }
+
+ NvOsMutexUnlock(gs_hAesCoreEngineMutex);
+ return NvError_AlreadyAllocated;
+}
+
+/**
+ * Init AES engine.
+ *
+ * @param hRmDevice Resource Manager Handle.
+ *
+ * @retval NvSuccess if successful.
+ */
+NvError AesCoreInitEngine(const NvRmDeviceHandle hRmDevice)
+{
+ NvError e = NvSuccess;
+ AesHwContext *pAesHwCtxt = NULL;
+ AesHwEngine Engine;
+
+ NV_ASSERT(hRmDevice);
+
+ gs_pAesCoreEngine = NvOsAlloc(sizeof(AesCoreEngine));
+ if (NULL == gs_pAesCoreEngine)
+ return NvError_InsufficientMemory;
+
+ // Clear the memory initially
+ NvOsMemset(gs_pAesCoreEngine, 0, sizeof(AesCoreEngine));
+
+ // Get the AES H/W context
+ pAesHwCtxt = &gs_pAesCoreEngine->AesHwCtxt;
+
+ // Store the RM handle for future use
+ pAesHwCtxt->hRmDevice = hRmDevice;
+
+ pAesHwCtxt->ppEngineCaps = (AesHwCapabilities **)NvOsAlloc(sizeof(AesHwCapabilities) * AesHwEngine_Num);
+ if (NULL == pAesHwCtxt->ppEngineCaps)
+ {
+ NvOsFree(gs_pAesCoreEngine);
+ gs_pAesCoreEngine = NULL;
+ return NvError_InsufficientMemory;
+ }
+ AesCoreGetCapabilities(hRmDevice, pAesHwCtxt->ppEngineCaps);
+
+ for (Engine = AesHwEngine_A; Engine < AesHwEngine_Num; Engine++)
+ {
+ NV_ASSERT(pAesHwCtxt->ppEngineCaps[Engine]);
+ pAesHwCtxt->KeyTableSize[Engine] = pAesHwCtxt->ppEngineCaps[Engine]->HwKeySchedLengthBytes;
+ }
+
+ NV_CHECK_ERROR(AesCoreInitializeEngineSpace(hRmDevice, pAesHwCtxt));
+
+ // Allocate memories required for H/W operation
+ NV_CHECK_ERROR(AesCoreAllocateRmMemory(pAesHwCtxt));
+
+ // Create mutex to guard the H/W engine
+ for (Engine = AesHwEngine_A; Engine < AesHwEngine_Num; Engine++)
+ {
+ NV_CHECK_ERROR(NvOsMutexCreate(&pAesHwCtxt->Mutex[Engine]));
+
+ // Register with Power Manager
+ gs_pAesCoreEngine->RmPwrClientId[Engine] = NVRM_POWER_CLIENT_TAG('A','E','S','1');
+
+ NV_CHECK_ERROR(NvRmPowerRegister(hRmDevice, NULL, &gs_pAesCoreEngine->RmPwrClientId[Engine]));
+
+ // Enable the voltage
+ NV_CHECK_ERROR(NvRmPowerVoltageControl(
+ hRmDevice,
+ (AesHwEngine_A == Engine) ?
+ NvRmModuleID_Vde : NvRmModuleID_BseA,
+ gs_pAesCoreEngine->RmPwrClientId[Engine],
+ NvRmVoltsUnspecified,
+ NvRmVoltsUnspecified,
+ NULL,
+ 0,
+ NULL));
+
+ // Enable clock
+ NV_CHECK_ERROR(NvRmPowerModuleClockControl(
+ hRmDevice,
+ (AesHwEngine_A == Engine) ?
+ NvRmModuleID_Vde : NvRmModuleID_BseA,
+ gs_pAesCoreEngine->RmPwrClientId[Engine],
+ NV_TRUE));
+ }
+
+ // Request the H/W semaphore before accessing the AES H/W
+ AesCoreRequestHwAccess();
+
+ // Reset the BSEV and BSEA engines
+ NvRmModuleReset(hRmDevice, NvRmModuleID_Vde);
+ NvRmModuleReset(hRmDevice, NvRmModuleID_BseA);
+
+ for (Engine = AesHwEngine_A; Engine < AesHwEngine_Num; Engine++)
+ {
+ NVDDK_AES_CHECK_INTERFACE(pAesHwCtxt, Engine);
+ NVDDK_AES_CHECK_INTERFACE_FUNC(pAesHwCtxt, Engine, AesHwIsEngineDisabled);
+
+ gs_pAesCoreEngine->IsEngineDisabled =
+ pAesHwCtxt->ppEngineCaps[Engine]->pAesInterf->AesHwIsEngineDisabled(pAesHwCtxt, Engine);
+ }
+
+ // If engine is not disabled then set the SBK & SSK
+ if (!gs_pAesCoreEngine->IsEngineDisabled)
+ {
+ // The slots already dedicated don't depend on which engine is being used but
+ // on the capabilities the engines can provide. Basic assumption: both engines have
+ // same capabilities.
+ NVDDK_AES_CHECK_INTERFACE_FUNC(pAesHwCtxt, 0, AesGetUsedSlots);
+ pAesHwCtxt->ppEngineCaps[0]->pAesInterf->AesHwGetUsedSlots(gs_pAesCoreEngine);
+ }
+
+ // Get the Iv read permissions
+ for (Engine = AesHwEngine_A; Engine < AesHwEngine_Num; Engine++)
+ {
+ NVDDK_AES_CHECK_INTERFACE(pAesHwCtxt, Engine);
+ NVDDK_AES_CHECK_INTERFACE_FUNC(pAesHwCtxt, Engine, GetIvReadPermissions);
+ pAesHwCtxt->ppEngineCaps[Engine]->pAesInterf->AesHwGetIvReadPermissions(Engine, pAesHwCtxt);
+ }
+
+ // Release the H/W semaphore
+ AesCoreReleaseHwAccess();
+
+ // Disable clocks after AES init
+ for (Engine = AesHwEngine_A; Engine < AesHwEngine_Num; Engine++)
+ {
+ // Disable clock
+ NV_CHECK_ERROR(NvRmPowerModuleClockControl(
+ pAesHwCtxt->hRmDevice,
+ (AesHwEngine_A == Engine) ?
+ NvRmModuleID_Vde : NvRmModuleID_BseA,
+ gs_pAesCoreEngine->RmPwrClientId[Engine],
+ NV_FALSE));
+
+ // Disable the voltage
+ NV_CHECK_ERROR(NvRmPowerVoltageControl(
+ pAesHwCtxt->hRmDevice,
+ (AesHwEngine_A == Engine) ?
+ NvRmModuleID_Vde : NvRmModuleID_BseA,
+ gs_pAesCoreEngine->RmPwrClientId[Engine],
+ NvRmVoltsOff,
+ NvRmVoltsOff,
+ NULL,
+ 0,
+ NULL));
+ }
+ return e;
+}
+
+/**
+ * Free up resources.
+ *
+ * @retval None.
+ */
+void AesCoreFreeUpEngine(AesCoreEngine *const pAesCoreEngine)
+{
+ AesHwEngine Engine;
+ AesHwContext *pAesHwCtxt;
+
+ NV_ASSERT(pAesCoreEngine);
+
+ // Get the AES H/W context
+ pAesHwCtxt = &pAesCoreEngine->AesHwCtxt;
+
+ AesCoreDeInitializeEngineSpace(pAesHwCtxt);
+
+ // Deallocate the memory
+ AesCoreDeAllocateRmMemory(pAesHwCtxt);
+
+ // Destroy mutex
+ for (Engine = AesHwEngine_A; Engine < AesHwEngine_Num; Engine++)
+ {
+ NvOsMutexDestroy(pAesHwCtxt->Mutex[Engine]);
+ // Unregister driver from Power Manager
+ NvRmPowerUnRegister(pAesHwCtxt->hRmDevice, pAesCoreEngine->RmPwrClientId[Engine]);
+ if (pAesHwCtxt->ppEngineCaps[Engine]->pAesInterf)
+ {
+ NvOsFree(pAesHwCtxt->ppEngineCaps[Engine]->pAesInterf);
+ pAesHwCtxt->ppEngineCaps[Engine]->pAesInterf = NULL;
+ }
+ }
+ if (pAesHwCtxt->ppEngineCaps)
+ {
+ NvOsFree(pAesHwCtxt->ppEngineCaps);
+ pAesHwCtxt->ppEngineCaps = NULL;
+ }
+}
+
+/**
+ * Power up the AES core engine.
+ *
+ * @param pAesCoreEngine Pointer to the AesCoreEngine argument.
+ *
+ * @retval None.
+ */
+void AesCorePowerUp(const AesCoreEngine *const pAesCoreEngine)
+{
+ AesHwEngine Engine;
+ const AesHwContext *pAesHwCtxt;
+
+ NV_ASSERT(pAesCoreEngine);
+
+ // Get the Aes Hw context
+ pAesHwCtxt = &pAesCoreEngine->AesHwCtxt;
+
+ for (Engine = AesHwEngine_A; Engine < AesHwEngine_Num; Engine++)
+ {
+ // DFS busy hints On
+ NV_ASSERT_SUCCESS(AesCoreDfsBusyHint(pAesHwCtxt->hRmDevice, pAesCoreEngine->RmPwrClientId[Engine], NV_TRUE));
+
+ // Enable the voltage
+ NV_ASSERT_SUCCESS(NvRmPowerVoltageControl(
+ pAesHwCtxt->hRmDevice,
+ (AesHwEngine_A == Engine) ? NvRmModuleID_Vde : NvRmModuleID_BseA,
+ pAesCoreEngine->RmPwrClientId[Engine],
+ NvRmVoltsUnspecified,
+ NvRmVoltsUnspecified,
+ NULL,
+ 0,
+ NULL));
+
+ // Enable clock
+ NV_ASSERT_SUCCESS(NvRmPowerModuleClockControl(
+ pAesHwCtxt->hRmDevice,
+ (AesHwEngine_A == Engine) ? NvRmModuleID_Vde : NvRmModuleID_BseA,
+ pAesCoreEngine->RmPwrClientId[Engine],
+ NV_TRUE));
+ }
+}
+
+/**
+ * Power down the AES core engine.
+ *
+ * @param pAesCoreEngine Pointer to the AesCoreEngine argument.
+ *
+ * @retval None.
+ */
+void AesCorePowerDown(const AesCoreEngine *const pAesCoreEngine)
+{
+ AesHwEngine Engine;
+ const AesHwContext *pAesHwCtxt;
+
+ NV_ASSERT(pAesCoreEngine);
+
+ // Get the AES H/W context
+ pAesHwCtxt = &pAesCoreEngine->AesHwCtxt;
+
+ for (Engine = AesHwEngine_A; Engine < AesHwEngine_Num; Engine++)
+ {
+ // Disable clock
+ NV_ASSERT_SUCCESS(NvRmPowerModuleClockControl(
+ pAesHwCtxt->hRmDevice,
+ (AesHwEngine_A == Engine) ? NvRmModuleID_Vde : NvRmModuleID_BseA,
+ pAesCoreEngine->RmPwrClientId[Engine],
+ NV_FALSE));
+
+ // Disable the voltage
+ NV_ASSERT_SUCCESS(NvRmPowerVoltageControl(
+ pAesHwCtxt->hRmDevice,
+ (AesHwEngine_A == Engine) ? NvRmModuleID_Vde : NvRmModuleID_BseA,
+ pAesCoreEngine->RmPwrClientId[Engine],
+ NvRmVoltsOff,
+ NvRmVoltsOff,
+ NULL,
+ 0,
+ NULL));
+
+ // DFS busy hints Off
+ NV_ASSERT_SUCCESS(AesCoreDfsBusyHint(pAesHwCtxt->hRmDevice, pAesCoreEngine->RmPwrClientId[Engine], NV_FALSE));
+ }
+}
+
+/**
+ * Process the buffers for encryption or decryption.
+ *
+ * @param SkipOffset Skip initial SkipOffset bytes of SrcBuffer before beginning cipher.
+ * @param SrcBufferSize Size of src buffer in bytes.
+ * @param DestBufferSize Size of dest buffer in bytes.
+ * @param pAesClient Pointer to AES client.
+ * @param pSrcBuffer Pointer to src buffer.
+ * @param pDestBuffer Pointer to dest buffer.
+ *
+ * @retval NvSuccess if successfully completed.
+ */
+NvError
+AesCoreProcessBuffer(
+ const NvU32 SkipOffset,
+ const NvU32 SrcBufferSize,
+ const NvU32 DestBufferSize,
+ NvDdkAes *const pAesClient,
+ const NvU8 *pSrcBuffer,
+ NvU8 *pDestBuffer)
+{
+ NvError e = NvSuccess;
+ AesHwContext *pAesHwCtxt = NULL;
+ AesHwEngine Engine;
+ AesHwKeySlot KeySlot;
+ NvU32 TotalBytesToProcess = 0;
+ NvU32 BytesToProcess = 0;
+
+ NV_ASSERT(pAesClient);
+ NV_ASSERT(pSrcBuffer);
+ NV_ASSERT(pDestBuffer);
+
+ NVDDK_AES_CHECK_USER_IDENTITY;
+
+ // Check type of operation supported for the process buffer
+ switch (pAesClient->OpMode)
+ {
+ case NvDdkAesOperationalMode_Cbc:
+ case NvDdkAesOperationalMode_Ecb:
+ case NvDdkAesOperationalMode_AnsiX931:
+ break;
+ default:
+ return NvError_InvalidState;
+ }
+
+ if (DestBufferSize % NvDdkAesConst_BlockLengthBytes)
+ return NvError_InvalidSize;
+
+ // Check if client has already assigned key for this process if not return
+ if ((NvDdkAesKeyType_Invalid == pAesClient->KeyType) || (pAesClient->KeyType >= NvDdkAesKeyType_Num))
+ return NvError_InvalidState;
+
+ // Get the AES H/W context
+ NV_ASSERT(pAesClient->pAesCoreEngine);
+ pAesHwCtxt = &pAesClient->pAesCoreEngine->AesHwCtxt;
+
+ TotalBytesToProcess = DestBufferSize;
+
+ NvOsMutexLock(gs_hAesCoreEngineMutex);
+
+ NVDDK_AES_CHECK_INTERFACE(pAesHwCtxt, pAesClient->Engine);
+
+ while (TotalBytesToProcess)
+ {
+ // Request the H/W semaphore before accesing the AES H/W
+ AesCoreRequestHwAccess();
+
+ // In the bootloader version entire buffer is processed for AES operation
+#if NV_OAL
+ BytesToProcess = TotalBytesToProcess;
+ TotalBytesToProcess = 0;
+#else
+ // At OS level only AES_HW_MAX_PROCESS_SIZE_BYTES will be processed.
+ // Once the AES H/W lock is acquired again then remaining bytes or maximum of
+ // AES_HW_MAX_PROCESS_SIZE_BYTES will be processed.
+ if (TotalBytesToProcess > AES_HW_MAX_PROCESS_SIZE_BYTES)
+ BytesToProcess = AES_HW_MAX_PROCESS_SIZE_BYTES;
+ else
+ BytesToProcess = TotalBytesToProcess;
+#endif
+
+ if ((!pAesClient->IsDedicatedSlot) && (NvDdkAesKeyType_UserSpecified == pAesClient->KeyType))
+ {
+ // If it is not dedicated slot, unwrap the key
+ NvU8 UnWrappedRFCIv[AES_RFC_IV_LENGTH_BYTES];
+
+ NV_CHECK_ERROR_CLEANUP(AesCoreGetFreeSlot(pAesClient->pAesCoreEngine, &Engine, &KeySlot));
+ pAesClient->Engine = Engine;
+ pAesClient->KeySlot = KeySlot;
+
+ // Unwrap the key
+ NV_CHECK_ERROR_CLEANUP(AesCoreUnWrapKey(
+ pAesClient,
+ pAesClient->Key,
+ pAesClient->WrappedIv,
+ pAesHwCtxt->pKeyTableVirAddr[Engine] + pAesHwCtxt->KeyTableSize[Engine],
+ UnWrappedRFCIv));
+ // Check whether the key unwrap is success or not by comparing the unwrapped RFC IV with original RFC IV
+ if (NvOsMemcmp(UnWrappedRFCIv, gs_OriginalIV, sizeof(gs_OriginalIV)))
+ {
+ // Unwrap key failed
+ e = NvError_AesKeyUnWrapFailed;
+ goto fail;
+ }
+
+ // Setup Key table
+ NVDDK_AES_CHECK_INTERFACE_FUNC(pAesHwCtxt, pAesClient->Engine, AesHwSetKeyAndIv);
+ pAesHwCtxt->ppEngineCaps[pAesClient->Engine]->pAesInterf->AesHwSetKeyAndIv(
+ pAesClient->Engine,
+ pAesClient->KeySlot,
+ (AesHwKey *)(pAesHwCtxt->pKeyTableVirAddr[Engine] + pAesHwCtxt->KeyTableSize[Engine]),
+ (AesHwIv *)pAesClient->Iv,
+ pAesClient->IsEncryption,
+ pAesHwCtxt);
+
+ // Memset the local variable to zeros where the key is stored
+ NvOsMemset(
+ (pAesHwCtxt->pKeyTableVirAddr[Engine] + pAesHwCtxt->KeyTableSize[Engine]),
+ 0,
+ NvDdkAesKeySize_128Bit);
+ }
+ else
+ {
+ // Select Key slot
+ NVDDK_AES_CHECK_INTERFACE_FUNC(pAesHwCtxt, pAesClient->Engine, AesHwSelectKeyIvSlot);
+ pAesHwCtxt->ppEngineCaps[pAesClient->Engine]->pAesInterf->AesHwSelectKeyIvSlot(
+ pAesClient->Engine,
+ pAesClient->KeySlot,
+ pAesHwCtxt);
+
+ // Set the last IV operated with this client
+ NVDDK_AES_CHECK_INTERFACE_FUNC(pAesHwCtxt, pAesClient->Engine, AesHwSetIv);
+ NV_CHECK_ERROR_CLEANUP(pAesHwCtxt->ppEngineCaps[pAesClient->Engine]->pAesInterf->AesHwSetIv(
+ pAesClient->Engine,
+ pAesClient->KeySlot,
+ (AesHwIv *)pAesClient->Iv,
+ pAesHwCtxt));
+ }
+
+ // Process the buffer for encryption/decryption
+ NVDDK_AES_CHECK_INTERFACE_FUNC(pAesHwCtxt, pAesClient->Engine, AesHwStartEngine);
+ e = pAesHwCtxt->ppEngineCaps[pAesClient->Engine]->pAesInterf->AesHwStartEngine(
+ pAesClient->Engine,
+ BytesToProcess,
+ pSrcBuffer,
+ pAesClient->IsEncryption,
+ pAesClient->OpMode,
+ pDestBuffer,
+ pAesHwCtxt);
+ if (NvSuccess != e)
+ {
+ // If the key is user specified and not in dedicated slot, clear it
+ if ((!pAesClient->IsDedicatedSlot) && (NvDdkAesKeyType_UserSpecified == pAesClient->KeyType))
+ {
+ // Clear key
+ NVDDK_AES_CHECK_INTERFACE_FUNC(pAesHwCtxt, pAesClient->Engine, AesHwClearKeyAndIv);
+ pAesHwCtxt->ppEngineCaps[pAesClient->Engine]->pAesInterf->AesHwClearKeyAndIv(
+ pAesClient->Engine,
+ pAesClient->KeySlot,
+ pAesHwCtxt);
+ }
+ goto fail;
+ }
+
+ // Store the last IV operated with this client
+ NVDDK_AES_CHECK_INTERFACE_FUNC(pAesHwCtxt, pAesClient->Engine, AesHwGetIv);
+ pAesHwCtxt->ppEngineCaps[pAesClient->Engine]->pAesInterf->AesHwGetIv(
+ pAesHwCtxt,
+ pAesClient->Engine,
+ pAesClient->KeySlot,
+ (AesHwIv *)pAesClient->Iv);
+
+ // If the key is user specified and not in dedicated slot, clear it
+ if ((!pAesClient->IsDedicatedSlot) && (NvDdkAesKeyType_UserSpecified == pAesClient->KeyType))
+ {
+ // Clear key
+ NVDDK_AES_CHECK_INTERFACE_FUNC(pAesHwCtxt, pAesClient->Engine, AesHwClearKeyAndIv);
+ pAesHwCtxt->ppEngineCaps[pAesClient->Engine]->pAesInterf->AesHwClearKeyAndIv(
+ pAesClient->Engine,
+ pAesClient->KeySlot,
+ pAesHwCtxt);
+ }
+ else
+ {
+ // Clear the IV in the engine
+ NVDDK_AES_CHECK_INTERFACE_FUNC(pAesHwCtxt, pAesClient->Engine, AesHwClearIv);
+ pAesHwCtxt->ppEngineCaps[pAesClient->Engine]->pAesInterf->AesHwClearIv(
+ pAesClient->Engine,
+ pAesClient->KeySlot,
+ pAesHwCtxt);
+ }
+
+#if !NV_OAL
+ pSrcBuffer += BytesToProcess;
+ pDestBuffer += BytesToProcess;
+ TotalBytesToProcess -= BytesToProcess;
+#endif
+
+ // Release the H/W semaphore
+ AesCoreReleaseHwAccess();
+ }
+
+ // Clear the DMA buffer before we leave from this operation
+ NvOsMemset(pAesHwCtxt->pDmaVirAddr[pAesClient->Engine], 0, AES_HW_DMA_BUFFER_SIZE_BYTES);
+ NvOsMutexUnlock(gs_hAesCoreEngineMutex);
+ return NvSuccess;
+
+fail:
+ // Release the H/W semaphore
+ AesCoreReleaseHwAccess();
+ // Clear the DMA buffer before we leave from this operation
+ NvOsMemset(pAesHwCtxt->pDmaVirAddr[pAesClient->Engine], 0, AES_HW_DMA_BUFFER_SIZE_BYTES);
+ NvOsMutexUnlock(gs_hAesCoreEngineMutex);
+ return e;
+}
+
+/**
+ * Clear the User Key.
+ *
+ * @param pAesClient Pointer to AES client.
+ *
+ * @retval NvSuccess if User key is cleared, NV_FALSE otherwise.
+ */
+NvError AesCoreClearUserKey(const NvDdkAes *const pAesClient)
+{
+ AesHwContext *pAesHwCtxt = NULL;
+ NvBool IsSuccess = NV_TRUE;
+
+ NV_ASSERT(pAesClient);
+
+ NvOsMutexLock(gs_hAesCoreEngineMutex);
+
+ // Get the AES H/W context
+ NV_ASSERT(pAesClient->pAesCoreEngine);
+ pAesHwCtxt = &pAesClient->pAesCoreEngine->AesHwCtxt;
+
+ NVDDK_AES_CHECK_INTERFACE(pAesHwCtxt, pAesClient->Engine);
+
+ AesCoreRequestHwAccess();
+
+ // Clear the key and IV
+ NVDDK_AES_CHECK_INTERFACE_FUNC(pAesHwCtxt, pAesClient->Engine, AesHwClearKeyAndIv);
+ pAesHwCtxt->ppEngineCaps[pAesClient->Engine]->pAesInterf->AesHwClearKeyAndIv(
+ pAesClient->Engine,
+ pAesClient->KeySlot,
+ pAesHwCtxt);
+
+ AesCoreReleaseHwAccess();
+
+ IsSuccess = AesCoreIsUserKeyCleared(pAesClient->Engine, pAesClient->KeySlot, pAesHwCtxt);
+
+ NvOsMutexUnlock(gs_hAesCoreEngineMutex);
+ return IsSuccess;
+}
+
+/**
+ * Check the user key clear by encrypting the known data.
+ *
+ * @param Engine Engine on which encryption need to be performed.
+ * @param KeySlot Key slot where encrypt key is located.
+ * @param pAesHw Pointer to AES H/W context.
+ *
+ * @retval NV_TRUE if encryption and decryption is successfully done else NV_FALSE
+ */
+NvBool
+AesCoreIsUserKeyCleared(
+ const AesHwEngine Engine,
+ const AesHwKeySlot KeySlot,
+ AesHwContext *const pAesHwCtxt)
+{
+ NvError e = NvSuccess;
+ AesHwIv ZeroIv;
+ NvU32 i;
+
+ // Known Good data
+ static NvU8 s_GoldData[NvDdkAesConst_BlockLengthBytes] =
+ {
+ 0x00, 0x01, 0x02, 0x03,
+ 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0A, 0x0B,
+ 0x0C, 0x0D, 0x0E, 0x0F
+ };
+
+ // Encrypted data for above known data with Zero key and Zero IV
+ static NvU8 s_EncryptDataWithZeroKeyTable[NvDdkAesConst_BlockLengthBytes] =
+ {
+ 0x7A, 0xCA, 0x0F, 0xD9,
+ 0xBC, 0xD6, 0xEC, 0x7C,
+ 0x9F, 0x97, 0x46, 0x66,
+ 0x16, 0xE6, 0xA2, 0x82
+ };
+
+ // Encrypted data for above known data with Zero key and Zero IV
+ static NvU8 s_EncryptDataWithZeroKeySchedule[NvDdkAesConst_BlockLengthBytes] =
+ {
+ 0x18, 0x9D, 0x19, 0xEA,
+ 0xDB, 0xA7, 0xE3, 0x0E,
+ 0xD9, 0x72, 0x80, 0x8F,
+ 0x3F, 0x2B, 0xA0, 0x30
+ };
+
+ NvU8 *pEncryptData;
+ NvU8 EncryptBuffer[NvDdkAesConst_BlockLengthBytes];
+
+ NvOsMutexLock(gs_hAesCoreEngineMutex);
+
+ NVDDK_AES_CHECK_INTERFACE(pAesHwCtxt, Engine);
+
+ if (pAesHwCtxt->ppEngineCaps[Engine]->IsHwKeySchedGenSupported)
+ pEncryptData = s_EncryptDataWithZeroKeyTable;
+ else
+ pEncryptData = s_EncryptDataWithZeroKeySchedule;
+
+ NvOsMemset(EncryptBuffer, 0, NvDdkAesConst_BlockLengthBytes);
+ NvOsMemset(&ZeroIv, 0, sizeof(AesHwIv));
+
+ AesCoreRequestHwAccess();
+
+ // Select Encrypt Key slot
+ NVDDK_AES_CHECK_INTERFACE_FUNC(pAesHwCtxt, Engine, AesHwSelectKeyIvSlot);
+ pAesHwCtxt->ppEngineCaps[Engine]->pAesInterf->AesHwSelectKeyIvSlot(Engine, KeySlot, pAesHwCtxt);
+
+ // Set the Zero IV for test data
+ NVDDK_AES_CHECK_INTERFACE_FUNC(pAesHwCtxt, Engine, AesHwSetIv);
+ NV_CHECK_ERROR_CLEANUP(pAesHwCtxt->ppEngineCaps[Engine]->pAesInterf->AesHwSetIv(
+ Engine,
+ KeySlot,
+ &ZeroIv,
+ pAesHwCtxt));
+
+ // Process the buffer for encryption
+ NVDDK_AES_CHECK_INTERFACE_FUNC(pAesHwCtxt, Engine, AesHwStartEngine);
+ NV_CHECK_ERROR_CLEANUP(pAesHwCtxt->ppEngineCaps[Engine]->pAesInterf->AesHwStartEngine(
+ Engine,
+ NvDdkAesConst_BlockLengthBytes,
+ s_GoldData,
+ NV_TRUE,
+ NvDdkAesOperationalMode_Cbc,
+ EncryptBuffer,
+ pAesHwCtxt));
+
+ // Clear the IV in the engine before we leave
+ NVDDK_AES_CHECK_INTERFACE_FUNC(pAesHwCtxt, Engine, AesHwClearIv);
+ pAesHwCtxt->ppEngineCaps[Engine]->pAesInterf->AesHwClearIv(Engine, KeySlot, pAesHwCtxt);
+
+ AesCoreReleaseHwAccess();
+
+ // Clear the DMA buffer before we leave from this operation
+ NvOsMemset(pAesHwCtxt->pDmaVirAddr[Engine], 0, AES_HW_DMA_BUFFER_SIZE_BYTES);
+
+ for (i = 0; i < NvDdkAesConst_BlockLengthBytes; i++)
+ {
+ if (pEncryptData[i] != EncryptBuffer[i])
+ goto fail;
+ }
+
+ NvOsMutexUnlock(gs_hAesCoreEngineMutex);
+ return NV_TRUE;
+
+fail:
+ // Clear the DMA buffer before we leave from this operation
+ NvOsMemset(pAesHwCtxt->pDmaVirAddr[Engine], 0, AES_HW_DMA_BUFFER_SIZE_BYTES);
+ NvOsMutexUnlock(gs_hAesCoreEngineMutex);
+ return NV_FALSE;
+}
+
+/**
+ * Return the AES module capabilities.
+ *
+ * @param hRmDevice Rm Device handle.
+ * @param ppCaps Pointer to pointer to capbilities structure.
+ *
+ * @retval NvSuccess if capabilities could be returned successfully.
+ *
+ */
+NvError AesCoreGetCapabilities(const NvRmDeviceHandle hRmDevice, AesHwCapabilities **const ppCaps)
+{
+ NvError e = NvSuccess;
+
+ static AesHwCapabilities s_Caps1;
+ static AesHwCapabilities s_Caps2;
+
+ static NvRmModuleCapability s_EngineA_Caps[] =
+ {
+ {1, 0, 0, &s_Caps1},
+ {1, 1, 0, &s_Caps1},
+ {1, 2, 0, &s_Caps2},
+ {1, 3, 0, &s_Caps2}
+ };
+
+ static NvRmModuleCapability s_engineB_caps[] =
+ {
+ {1, 0, 0, &s_Caps1},
+ {1, 1, 0, &s_Caps2},
+ {1, 2, 0, &s_Caps2}
+ };
+
+ NV_ASSERT(hRmDevice);
+ NV_ASSERT(ppCaps);
+
+ NvOsMemset(&s_Caps1, 0, sizeof(s_Caps1));
+ NvOsMemset(&s_Caps2, 0, sizeof(s_Caps2));
+
+ s_Caps1.IsHashSupported = NV_FALSE;
+ s_Caps1.IsHwKeySchedGenSupported = NV_FALSE;
+ s_Caps1.MinBufferAlignment = 16;
+ s_Caps1.MinKeyTableAlignment = 256;
+ s_Caps1.NumSlotsSupported = AesHwKeySlot_Num;
+ s_Caps1.pAesInterf = NULL;
+
+ s_Caps2.IsHashSupported = NV_FALSE;
+ s_Caps2.IsHwKeySchedGenSupported = NV_TRUE;
+ s_Caps2.HwKeySchedLengthBytes = 80;
+ s_Caps2.MinBufferAlignment = 16;
+ s_Caps2.MinKeyTableAlignment = 4;
+ s_Caps2.NumSlotsSupported = AesHwKeySlot_NumExt;
+ s_Caps2.pAesInterf = NULL;
+
+ NV_CHECK_ERROR_CLEANUP(NvRmModuleGetCapabilities(
+ hRmDevice,
+ NvRmModuleID_Vde,
+ s_EngineA_Caps,
+ NV_ARRAY_SIZE(s_EngineA_Caps),
+ (void **)&(ppCaps[AesHwEngine_A])));
+
+ if (ppCaps[AesHwEngine_A] == &s_Caps2)
+ {
+ if (NULL == s_Caps2.pAesInterf)
+ {
+ s_Caps2.pAesInterf = NvOsAlloc(sizeof(AesHwInterface));
+ if (NULL == s_Caps2.pAesInterf)
+ goto fail;
+ NvAesIntfAp20GetHwInterface(s_Caps2.pAesInterf);
+ }
+ }
+
+ NV_CHECK_ERROR_CLEANUP(NvRmModuleGetCapabilities(
+ hRmDevice,
+ NvRmModuleID_BseA,
+ s_engineB_caps,
+ NV_ARRAY_SIZE(s_engineB_caps),
+ (void **)&(ppCaps[AesHwEngine_B])));
+
+ if (ppCaps[AesHwEngine_B] == &s_Caps2)
+ {
+ if (NULL == s_Caps2.pAesInterf)
+ {
+ s_Caps2.pAesInterf = NvOsAlloc(sizeof(AesHwInterface));
+ if (NULL == s_Caps2.pAesInterf)
+ goto fail;
+ NvAesIntfAp20GetHwInterface(s_Caps2.pAesInterf);
+ }
+ }
+
+fail:
+ return e;
+}
+
+/**
+ * Encrypt/Decrypt the given input buffer using Electronic CodeBook (ECB) mode.
+ *
+ * @param pAesClient Pointer to AES client.
+ * @param pInputBuffer Pointer to input bufffer.
+ * @param BufSize Buffer size.
+ * @param IsEncrypt If set to NV_TRUE, encrypt the input buffer else decrypt it.
+ * @param pOutputBuffer Pointer to output buffer.
+ *
+ * @retval NvSuccess if successfully completed.
+ */
+NvError
+AesCoreEcbProcessBuffer(
+ const NvDdkAes *const pAesClient,
+ const NvU8 *const pInputBuffer,
+ const NvU32 BufSize,
+ const NvBool IsEncrypt,
+ NvU8 *const pOutputBuffer)
+{
+ NvError e = NvSuccess;
+ AesHwEngine SskEngine;
+ AesHwKeySlot SskKeySlot;
+ AesHwContext *pAesHwCtxt;
+
+ NV_ASSERT(pAesClient);
+ NV_ASSERT(pInputBuffer);
+ NV_ASSERT(pOutputBuffer);
+
+ // Get the AES H/W context
+ NV_ASSERT(pAesClient->pAesCoreEngine);
+ pAesHwCtxt = &pAesClient->pAesCoreEngine->AesHwCtxt;
+
+ SskEngine = pAesClient->pAesCoreEngine->SskEngine[0];
+ SskKeySlot = (IsEncrypt ? pAesClient->pAesCoreEngine->SskEncryptSlot : pAesClient->pAesCoreEngine->SskDecryptSlot);
+
+ NVDDK_AES_CHECK_INTERFACE(pAesHwCtxt, SskEngine);
+
+ AesCoreRequestHwAccess();
+
+ // Select SSK key for processing
+ NVDDK_AES_CHECK_INTERFACE_FUNC(pAesHwCtxt, SskEngine, AesHwSelectKeyIvSlot);
+ pAesHwCtxt->ppEngineCaps[SskEngine]->pAesInterf->AesHwSelectKeyIvSlot(SskEngine, SskKeySlot, pAesHwCtxt);
+
+ // Process the buffer
+ NVDDK_AES_CHECK_INTERFACE_FUNC(pAesHwCtxt, SskEngine, AesHwStartEngine);
+ e = pAesHwCtxt->ppEngineCaps[SskEngine]->pAesInterf->AesHwStartEngine(
+ SskEngine,
+ BufSize,
+ pInputBuffer,
+ IsEncrypt,
+ NvDdkAesOperationalMode_Ecb,
+ pOutputBuffer,
+ pAesHwCtxt);
+
+ AesCoreReleaseHwAccess();
+ return e;
+}
+
+/**
+ * Wrap the given key data using RFC 3394 algoritham.
+ *
+ * Follwing is RFC3394 key wrap algoritham.
+ * Inputs: Plaintext, n 64-bit values {P1, P2, ..., Pn}, and
+ * Key, K (the KEK).
+ * Outputs: Ciphertext, (n+1) 64-bit values {C0, C1, ..., Cn}.
+
+ * 1) Initialize variables.
+ * Set A = IV, an initial value (see 2.2.3)
+ * For i = 1 to n
+ * R[i] = P[i]
+ * 2) Calculate intermediate values.
+ * For j = 0 to 5
+ * For i=1 to n
+ * B = AES(K, A | R[i])
+ * A = MSB(64, B) ^ t where t = (n*j)+i
+ * R[i] = LSB(64, B)
+ * 3) Output the results.
+ * Set C[0] = A
+ * For i = 1 to n
+ * C[i] = R[i]
+ *
+ * @param pAesClient Pointer to AES client.
+ * @param pOrgKey Pointer to Original Key.
+ * @param pOrgIv Pointer to Original Iv which is used in RFC3394 algorithm.
+ * @param pWrappedKey Pointer to wrapped key.
+ * @param pWrappedIv Pointer to wrapped Iv.
+ *
+ */
+NvError
+AesCoreWrapKey(
+ const NvDdkAes *const pAesClient,
+ const NvU8 *const pOrgKey,
+ const NvU8 *const pOrgIv,
+ NvU8 *const pWrappedKey,
+ NvU8 *const pWrappedIv)
+{
+ NvError e = NvSuccess;
+ NvU8 n = AES_RFC_3394_NUM_OF_BLOCKS_FOR_128BIT_KEY, i, j, k, t;
+ NvU8 *A, *B;
+ NvU8 **R;
+ AesHwContext *pAesHwCtxt;
+
+ NV_ASSERT(pAesClient);
+ NV_ASSERT(pOrgKey);
+ NV_ASSERT(pOrgIv);
+ NV_ASSERT(pWrappedKey);
+ NV_ASSERT(pWrappedIv);
+
+ // Get the AES H/W context
+ NV_ASSERT(pAesClient->pAesCoreEngine);
+ pAesHwCtxt = &pAesClient->pAesCoreEngine->AesHwCtxt;
+
+ // Local buffers which are used for processing should be in IRAM.
+ // Use KeyTable buffer which is in IRAM.
+ // The local variables should be of following format and sizes.
+ // NvU8 A[AES_RFC_3394_KEY_WRAP_BLOCK_SIZE_BYTES];
+ // NvU8 B[AES_RFC_3394_KEY_WRAP_BLOCK_SIZE_BYTES * AES_RFC_3394_NUM_OF_BLOCKS_FOR_128BIT_KEY];
+ // NvU8 R[AES_RFC_3394_NUM_OF_BLOCKS_FOR_128BIT_KEY][AES_RFC_3394_KEY_WRAP_BLOCK_SIZE_BYTES];
+
+ A = pAesHwCtxt->pKeyTableVirAddr[0];
+ B = A + AES_RFC_3394_KEY_WRAP_BLOCK_SIZE_BYTES;
+
+ R = (NvU8 **)(B + (AES_RFC_3394_NUM_OF_BLOCKS_FOR_128BIT_KEY * AES_RFC_3394_KEY_WRAP_BLOCK_SIZE_BYTES));
+ for(i = 0; i < AES_RFC_3394_NUM_OF_BLOCKS_FOR_128BIT_KEY; i++)
+ {
+ R[i] = ((B + (AES_RFC_3394_NUM_OF_BLOCKS_FOR_128BIT_KEY * AES_RFC_3394_KEY_WRAP_BLOCK_SIZE_BYTES)) +
+ (AES_RFC_3394_KEY_WRAP_BLOCK_SIZE_BYTES * sizeof(NvU8 *)) +
+ (i * AES_RFC_3394_KEY_WRAP_BLOCK_SIZE_BYTES));
+ }
+
+ // Set A = IV
+ for (i = 0; i < AES_RFC_3394_KEY_WRAP_BLOCK_SIZE_BYTES; i++)
+ A[i] = pOrgIv[i];
+
+ //For i = 1 to n R[i] = P[i]
+ for (i = 0; i < n; i++)
+ {
+ for (j = 0; j < AES_RFC_3394_KEY_WRAP_BLOCK_SIZE_BYTES; j++)
+ R[i][j] = pOrgKey[j + (i *AES_RFC_3394_KEY_WRAP_BLOCK_SIZE_BYTES)];
+ }
+
+ // Calculate intermediate values.
+ // For j = 0 to 5
+ // For i=1 to n
+ // B = AES(K, A | R[i])
+ // A = MSB(64, B) ^ t where t = (n*j)+i
+ // R[i] = LSB(64, B)
+ for (j = 0; j <= 5; j++)
+ {
+ for (i = 0; i < n; i++)
+ {
+ for (k = 0; k < AES_RFC_3394_KEY_WRAP_BLOCK_SIZE_BYTES; k++)
+ {
+ B[k] = A[k];
+ B[AES_RFC_3394_KEY_WRAP_BLOCK_SIZE_BYTES+k] = R[i][k];
+ }
+ NV_CHECK_ERROR(AesCoreEcbProcessBuffer(pAesClient, B, NvDdkAesKeySize_128Bit, NV_TRUE, B));
+ for (k = 0; k < AES_RFC_3394_KEY_WRAP_BLOCK_SIZE_BYTES; k++)
+ {
+ A[k] = B[k];
+ R[i][k] = B[AES_RFC_3394_KEY_WRAP_BLOCK_SIZE_BYTES + k];
+ }
+ t = (n * j) + (i+1);
+ A[AES_RFC_3394_KEY_WRAP_BLOCK_SIZE_BYTES-1] ^= t;
+ }
+ }
+
+ // Output the results.
+ // Set C[0] = A
+ // For i = 1 to n
+ // C[i] = R[i]
+ for (k = 0; k < AES_RFC_3394_KEY_WRAP_BLOCK_SIZE_BYTES; k++) {
+ pWrappedIv[k] = A[k];
+ }
+ for (i = 0; i < n; i++)
+ {
+ for (k = 0; k < AES_RFC_3394_KEY_WRAP_BLOCK_SIZE_BYTES; k++)
+ {
+ pWrappedKey[(AES_RFC_3394_KEY_WRAP_BLOCK_SIZE_BYTES*i) + k] = R[i][k];
+ }
+ }
+
+ // Clear the buffers.
+ NvOsMemset(pAesHwCtxt->pKeyTableVirAddr[0], 0, pAesHwCtxt->KeyTableSize[0]);
+ return e;
+}
+
+/**
+ * UnWrapKey the given key data using RFC 3394 algorithm.
+ *
+ * Follwing is RFC3394 key unwrap algoritham.
+ * Inputs: Ciphertext, (n+1) 64-bit values {C0, C1, ..., Cn}, and
+ * Key, K (the KEK).
+ * Outputs: Plaintext, n 64-bit values {P0, P1, K, Pn}.
+ *
+ * 1) Initialize variables.
+ * Set A = C[0]
+ * For i = 1 to n
+ * R[i] = C[i]
+ * 2) Compute intermediate values.
+ * For j = 5 to 0
+ * For i = n to 1
+ * B = AES-1(K, (A ^ t) | R[i]) where t = n*j+i
+ * A = MSB(64, B)
+ * R[i] = LSB(64, B)
+ * 3) Output results.
+ * If A is an appropriate initial value (see 2.2.3),
+ * Then
+ * For i = 1 to n
+ * P[i] = R[i]
+ * Else
+ * Return an error
+ *
+ * @param pAesClient Pointer to AES client.
+ * @param pWrappedKey Pointer to wrapped key
+ * @param pWrappedIv Pointer to wrapped Iv
+ * @param pOrgKey Pointer to Original Key.
+ * @param pOrgIv Pointer to Original Iv which is used in RFC3394 algorithm.
+ *
+ */
+NvError
+AesCoreUnWrapKey(
+ const NvDdkAes *const pAesClient,
+ const NvU8 *const pWrappedKey,
+ const NvU8 *const pWrappedIv,
+ NvU8 *const pOrgKey,
+ NvU8 *const pOrgIv)
+{
+ NvError e = NvSuccess;
+ NvS32 n = AES_RFC_3394_NUM_OF_BLOCKS_FOR_128BIT_KEY, i, j, k, t;
+ NvU8 *A, *B;
+ NvU8 **R;
+ AesHwContext *pAesHwCtxt;
+
+ NV_ASSERT(pAesClient);
+ NV_ASSERT(pWrappedKey);
+ NV_ASSERT(pWrappedIv);
+ NV_ASSERT(pOrgKey);
+ NV_ASSERT(pOrgIv);
+
+ // Get the AES H/W context
+ NV_ASSERT(pAesClient->pAesCoreEngine);
+ pAesHwCtxt = &pAesClient->pAesCoreEngine->AesHwCtxt;
+
+ // Local buffers which are used for processing should in IRAM.
+ // Use KeyTable buffer which is in IRAM.
+ // The local variables should be of following format and sizes.
+ // NvU8 A[AES_RFC_3394_KEY_WRAP_BLOCK_SIZE_BYTES];
+ // NvU8 B[AES_RFC_3394_KEY_WRAP_BLOCK_SIZE_BYTES * AES_RFC_3394_NUM_OF_BLOCKS_FOR_128BIT_KEY];
+ // NvU8 R[AES_RFC_3394_NUM_OF_BLOCKS_FOR_128BIT_KEY][AES_RFC_3394_KEY_WRAP_BLOCK_SIZE_BYTES];
+
+ A = pAesHwCtxt->pKeyTableVirAddr[0];
+ B = A + AES_RFC_3394_KEY_WRAP_BLOCK_SIZE_BYTES;
+ R = (NvU8 **)(B + (AES_RFC_3394_NUM_OF_BLOCKS_FOR_128BIT_KEY * AES_RFC_3394_KEY_WRAP_BLOCK_SIZE_BYTES));
+ for(i = 0; i < AES_RFC_3394_NUM_OF_BLOCKS_FOR_128BIT_KEY; i++)
+ {
+ R[i] = ((B + (AES_RFC_3394_NUM_OF_BLOCKS_FOR_128BIT_KEY * AES_RFC_3394_KEY_WRAP_BLOCK_SIZE_BYTES)) +
+ (AES_RFC_3394_KEY_WRAP_BLOCK_SIZE_BYTES * sizeof(NvU8 *)) +
+ (i * AES_RFC_3394_KEY_WRAP_BLOCK_SIZE_BYTES));
+ }
+
+ // Set A = C[0]
+ for (i = 0; i < AES_RFC_3394_KEY_WRAP_BLOCK_SIZE_BYTES; i++)
+ A[i] = pWrappedIv[i];
+
+ // For i = 1 to n R[i] = C[i]
+ for (i = 0; i < n; i++) {
+ for (j = 0; j < AES_RFC_3394_KEY_WRAP_BLOCK_SIZE_BYTES; j++)
+ R[i][j] = pWrappedKey[j + (i *AES_RFC_3394_KEY_WRAP_BLOCK_SIZE_BYTES)];
+ }
+
+ // Compute intermediate values.
+ // For j = 5 to 0
+ // For i = n to 1
+ // B = AES-1(K, (A ^ t) | R[i]) where t = n*j+i
+ // A = MSB(64, B)
+ // R[i] = LSB(64, B)
+ for (j = 5; j >= 0; j--)
+ {
+ for (i = n; i > 0; i--)
+ {
+ t = (n * j) + (i);
+ A[AES_RFC_3394_KEY_WRAP_BLOCK_SIZE_BYTES-1] ^= t;
+ for (k = 0; k < AES_RFC_3394_KEY_WRAP_BLOCK_SIZE_BYTES; k++)
+ {
+ B[k] = A[k];
+ B[AES_RFC_3394_KEY_WRAP_BLOCK_SIZE_BYTES+k] = R[i-1][k];
+ }
+ NV_CHECK_ERROR(AesCoreEcbProcessBuffer(pAesClient, B, NvDdkAesKeySize_128Bit, NV_FALSE, B));
+ for (k = 0; k < AES_RFC_3394_KEY_WRAP_BLOCK_SIZE_BYTES; k++)
+ {
+ A[k] = B[k];
+ R[i-1][k] = B[AES_RFC_3394_KEY_WRAP_BLOCK_SIZE_BYTES + k];
+ }
+ }
+ }
+
+ // Output results.
+ // For i = 1 to n
+ // P[i] = R[i]
+ for (k = 0; k < AES_RFC_3394_KEY_WRAP_BLOCK_SIZE_BYTES; k++)
+ {
+ pOrgIv[k] = A[k];
+ }
+
+ for (i = 0; i < n; i++)
+ {
+ for (k = 0; k < AES_RFC_3394_KEY_WRAP_BLOCK_SIZE_BYTES; k++)
+ {
+ pOrgKey[(AES_RFC_3394_KEY_WRAP_BLOCK_SIZE_BYTES*i) + k] = R[i][k];
+ }
+ }
+
+ // Clear the buffers.
+ NvOsMemset(pAesHwCtxt->pKeyTableVirAddr[0], 0, pAesHwCtxt->KeyTableSize[0]);
+ return e;
+}
diff --git a/arch/arm/mach-tegra/nvddk/nvddk_aes_core_ap20.c b/arch/arm/mach-tegra/nvddk/nvddk_aes_core_ap20.c
new file mode 100644
index 000000000000..1e24deb90c2e
--- /dev/null
+++ b/arch/arm/mach-tegra/nvddk/nvddk_aes_core_ap20.c
@@ -0,0 +1,617 @@
+/*
+ * Copyright (c) 2007-2009 NVIDIA Corporation.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of the NVIDIA Corporation nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "nvos.h"
+#include "nvassert.h"
+#include "nvrm_drf.h"
+#include "nvrm_hardware_access.h"
+#include "ap20/arvde_bsev_aes.h"
+#include "ap20/aravp_bsea_aes.h"
+#include "ap20/arapbpm.h"
+#include "nvddk_aes_common.h"
+#include "nvddk_aes_priv.h"
+#include "nvddk_aes_hw.h"
+#include "nvddk_aes_core_ap20.h"
+
+#define SECURE_HW_REGR(engine, viraddr, reg, value) \
+{ \
+ if (AesHwEngine_A == engine) \
+ { \
+ (value) = NV_READ32((NvU32)(viraddr) + (ARVDE_BSEV_##reg##_0)); \
+ } \
+ else if (AesHwEngine_B == engine) \
+ { \
+ (value) = NV_READ32((NvU32)(viraddr) + (AVPBSEA_##reg##_0)); \
+ } \
+}
+
+#define SECURE_HW_REGW(engine, viraddr, reg, data) \
+{ \
+ if (AesHwEngine_A == engine) \
+ { \
+ NV_WRITE32((NvU32)(viraddr) + (ARVDE_BSEV_##reg##_0), (data)); \
+ } \
+ else if (AesHwEngine_B == engine) \
+ { \
+ NV_WRITE32((NvU32)(viraddr) + (AVPBSEA_##reg##_0), (data)); \
+ } \
+}
+
+#define SECURE_DRF_SET_VAL(engine, reg, field, newData, value) \
+{ \
+ if (AesHwEngine_A == engine) \
+ { \
+ value = NV_FLD_SET_DRF_NUM(ARVDE_BSEV, reg, field, newData, value); \
+ } \
+ else if (AesHwEngine_B == engine) \
+ { \
+ value = NV_FLD_SET_DRF_NUM(AVPBSEA, reg, field, newData, value); \
+ } \
+}
+
+#define SECURE_DRF_READ_VAL(engine, reg, field, regData, value) \
+{ \
+ if (AesHwEngine_A == engine) \
+ { \
+ value = NV_DRF_VAL(ARVDE_BSEV, reg, field, regData); \
+ } \
+ else if (AesHwEngine_B == engine) \
+ { \
+ value = NV_DRF_VAL(AVPBSEA, reg, field, regData); \
+ } \
+}
+
+#define SECURE_DRF_NUM(engine, reg, field, num) \
+ NV_DRF_NUM(ARVDE_BSEV, reg, field, num) \
+
+#define SECURE_INDEXED_REGR(engine, viraddr, reg, index,value) \
+{ \
+ if (AesHwEngine_A == engine) \
+ { \
+ (value) = NV_READ32((NvU32)(viraddr) + (ARVDE_BSEV_##reg##_##0) + index * 4); \
+ } \
+ else if (AesHwEngine_B == engine) \
+ { \
+ (value) = NV_READ32((NvU32)(viraddr) + (AVPBSEA_##reg##_##0) + index * 4 ); \
+ } \
+}
+
+#define NV_ADDRESS_MAP_IRAM_A_BASE 0x40000000
+
+static NvBool NvAesCoreAp20IsEngineBusy(const AesHwEngine Engine, const NvU32 *const pEngineVirAddr);
+
+/**
+ * Define Ucq opcodes required for AES operation.
+ */
+typedef enum
+{
+ // Opcode for Block Start Engine command
+ AesUcqOpcode_BlockStartEngine = 0x0E,
+ // Opcode for Dma setup command
+ AesUcqOpcode_DmaSetup = 0x10,
+ // Opcode for Dma Finish Command
+ AesUcqOpcode_DmaFinish = 0x11,
+ // Opcode for Table setup command
+ AesUcqOpcode_SetupTable = 0x15,
+ AesUcqOpcode_Force32 = 0x7FFFFFFF
+} AesUcqOpcode;
+
+/**
+ * Define Aes command values.
+ */
+typedef enum
+{
+ // Command value for AES Table select
+ AesUcqCommand_TableSelect = 0x3,
+ // Command value for Keytable selection
+ AesUcqCommand_KeyTableSelect = 0x8,
+ // Command value for KeySchedule selection
+ AesUcqCommand_KeySchedTableSelect = 0x4,
+ // Command mask for ketable address mask
+ AesUcqCommand_KeyTableAddressMask = 0x1FFFF,
+ AesUcqCommand_Force32 = 0x7FFFFFFF
+} AesUcqCommand;
+
+/**
+ * @brief Define AES Interactive command Queue commands Bit positions.
+ */
+typedef enum
+{
+ // Define bit position for command Queue Opcode
+ AesIcqBitShift_Opcode = 26,
+ // Define bit position for AES Table select
+ AesIcqBitShift_TableSelect = 24,
+ // Define bit position for AES Key Table select
+ AesIcqBitShift_KeyTableId = 17,
+ // Define bit position for AES Key Table Address
+ AesIcqBitShift_KeyTableAddr = 0,
+ // Define bit position for 128 bit blocks count
+ AesIcqBitShift_BlockCount = 0,
+ AesIcqBitShift_Force32 = 0x7FFFFFFF
+} AesIcqBitShift;
+
+NvError NvAesCoreAp20DisableEngine(const AesHwEngine Engine, const NvU32 *const pEngineVirAddr)
+{
+ NvU32 RegValue = 0;
+
+ // Disable the AES engine
+ SECURE_HW_REGR(Engine, pEngineVirAddr, SECURE_SECURITY, RegValue);
+ SECURE_DRF_SET_VAL(Engine, SECURE_SECURITY, SECURE_ENG_DIS, 1, RegValue);
+ SECURE_HW_REGW(Engine, pEngineVirAddr, SECURE_SECURITY, RegValue);
+
+ SECURE_HW_REGW(Engine, pEngineVirAddr, SECURE_SECURITY, 0);
+ SECURE_HW_REGR(Engine, pEngineVirAddr, SECURE_SECURITY, RegValue);
+
+ if (RegValue == SECURE_DRF_NUM(Engine, SECURE_SECURITY, SECURE_ENG_DIS, 1))
+ return NvSuccess;
+ return NvError_AesDisableCryptoFailed;
+}
+
+NvBool NvAesCoreAp20IsEngineDisabled(const AesHwEngine Engine, const NvU32 *const pEngineVirAddr)
+{
+ NvU32 RegValue = 0;
+ NvU32 EngineStatus = 0;
+
+ SECURE_HW_REGR(Engine, pEngineVirAddr, SECURE_SECURITY, RegValue);
+ SECURE_DRF_READ_VAL(Engine, SECURE_SECURITY, SECURE_ENG_DIS, RegValue, EngineStatus);
+
+ return (NvBool)EngineStatus;
+}
+
+/**
+ * Query the status of the engine.
+ *
+ * @param Engine The engine for which status is required.
+ * @param pEngineVirAddr AES engine virtual address.
+ *
+ * @retval NV_TRUE if the engine is busy.
+ * @retval NV_FALSE if the engine is not busy.
+ */
+NvBool NvAesCoreAp20IsEngineBusy(const AesHwEngine Engine, const NvU32 *const pEngineVirAddr)
+{
+ NvU32 RegValue = 0;
+ NvU32 EngBusy = 0;
+ NvU32 IcqEmpty = 0;
+ NvU32 DmaBusy = 0;
+
+ SECURE_HW_REGR(Engine, pEngineVirAddr, INTR_STATUS, RegValue);
+
+ // Extract the EngBusy, IcqEmpty and DmaBusy status
+ SECURE_DRF_READ_VAL(Engine, INTR_STATUS, ENGINE_BUSY, RegValue, EngBusy);
+ SECURE_DRF_READ_VAL(Engine, INTR_STATUS, ICQ_EMPTY, RegValue, IcqEmpty);
+ SECURE_DRF_READ_VAL(Engine, INTR_STATUS, DMA_BUSY, RegValue, DmaBusy);
+
+ // Check for engine busy, ICQ not empty and DMA busy
+ if ((EngBusy) || (!IcqEmpty) || (DmaBusy))
+ {
+ // Return TRUE if any of the condition is true
+ return NV_TRUE;
+ }
+
+ // Return FALSE if engine is not doing anything
+ return NV_FALSE;
+}
+
+void NvAesCoreAp20WaitTillEngineIdle(const AesHwEngine Engine, const NvU32 *const pEngineVirAddr)
+{
+ while (NvAesCoreAp20IsEngineBusy(Engine, pEngineVirAddr));
+}
+
+void
+NvAesCoreAp20SetupTable(
+ const AesHwEngine Engine,
+ const NvU32 *const pEngineVirAddr,
+ const NvU32 KeyTablePhyAddr,
+ const NvU32 Slot)
+{
+ NvU32 SetupTableCmd = ((AesUcqOpcode_SetupTable << AesIcqBitShift_Opcode) |
+ (AesUcqCommand_TableSelect << AesIcqBitShift_TableSelect) |
+ ((AesUcqCommand_KeyTableSelect | Slot) << AesIcqBitShift_KeyTableId) |
+ ((KeyTablePhyAddr & AesUcqCommand_KeyTableAddressMask) <<
+ AesIcqBitShift_KeyTableAddr));
+
+ NvAesCoreAp20WaitTillEngineIdle(Engine, pEngineVirAddr);
+
+ // Issue the ICQ command to update the table to H/W registers
+ SECURE_HW_REGW(Engine, pEngineVirAddr, ICMDQUE_WR, SetupTableCmd);
+
+ NvAesCoreAp20WaitTillEngineIdle(Engine, pEngineVirAddr);
+}
+
+void NvAesCoreAp20SelectKeyIvSlot(const AesHwEngine Engine, const NvU32 *const pEngineVirAddr, const NvU32 Slot)
+{
+ NvU32 RegValue = 0;
+
+ // Select the KEY slot for updating the IV vectors
+ SECURE_HW_REGR(Engine, pEngineVirAddr, SECURE_CONFIG, RegValue);
+ // 2-bit index to select between the 4- keys
+ SECURE_DRF_SET_VAL(Engine, SECURE_CONFIG, SECURE_KEY_INDEX, Slot, RegValue);
+ // Update the AES config register
+ SECURE_HW_REGW(Engine, pEngineVirAddr, SECURE_CONFIG, RegValue);
+}
+
+void
+NvAesCoreAp20SetIv(
+ const AesHwEngine Engine,
+ const NvU32 *const pEngineVirAddr,
+ const NvU32 Slot,
+ const NvU32 Start,
+ const NvU32 End,
+ const NvU32 *const pKeyTable,
+ const NvU32 KeyTableSize,
+ const NvU32 *const pIvAddress)
+{
+ // Setting the iv will be done through decryption of Iv
+ // because Iv can't be written without overwriting the key
+ // especially in cases when key is not readable.
+}
+
+void
+NvAesCoreAp20GetIv(
+ const AesHwEngine Engine,
+ const NvU32 *const pEngineVirAddr,
+ const NvU32 Slot,
+ const NvU32 Start,
+ const NvU32 End,
+ const NvU32 *const pIvAddress)
+{
+ // The Iv is preserved within the driver because read permission is locked
+ // down for dedicated key slots
+}
+
+void
+NvAesCoreAp20ControlKeyScheduleGeneration(
+ const AesHwEngine Engine,
+ const NvU32 *const pEngineVirAddr,
+ const NvBool IsEnabled)
+{
+ NvU32 RegValue = 0;
+
+ // Disable key schedule generation in hardware
+ SECURE_HW_REGR(Engine, pEngineVirAddr, SECURE_CONFIG_EXT, RegValue);
+ SECURE_DRF_SET_VAL(Engine, SECURE_CONFIG_EXT, SECURE_KEY_SCH_DIS, (IsEnabled ? 0 : 1), RegValue);
+ SECURE_HW_REGW(Engine, pEngineVirAddr, SECURE_CONFIG_EXT, RegValue);
+}
+
+void NvAesCoreAp20LockSskReadWrites(const AesHwEngine Engine, const NvU32 *const pEngineVirAddr)
+{
+ NvU32 RegValue = 0;
+
+ SECURE_HW_REGR(Engine, pEngineVirAddr, SECURE_SEC_SEL4, RegValue);
+ SECURE_DRF_SET_VAL(Engine, SECURE_SEC_SEL4, KEYREAD_ENB4, 0, RegValue);
+ SECURE_DRF_SET_VAL(Engine, SECURE_SEC_SEL4, KEYUPDATE_ENB4, 0, RegValue);
+ SECURE_HW_REGW(Engine, pEngineVirAddr, SECURE_SEC_SEL4, RegValue);
+}
+
+static void
+AesHwPrivProcessBuffer(
+ const AesHwEngine Engine,
+ const NvU32 *const pEngineVirAddr,
+ const NvU32 SrcPhyAddress,
+ const NvU32 DestPhyAddress,
+ const NvU32 NumBlocks,
+ const NvBool IsEncryption,
+ const NvDdkAesOperationalMode OpMode)
+{
+ NvU32 CommandQueueData[AES_HW_MAX_ICQ_LENGTH];
+ NvU32 CommandQueueLength = 0;
+ NvU32 RegValue = 0;
+ NvU32 EngBusy = 0;
+ NvU32 IcqEmpty = 0;
+ NvU32 i;
+
+ // Setup DMA command
+ CommandQueueData[CommandQueueLength++] = (AesUcqOpcode_DmaSetup << AesIcqBitShift_Opcode);
+ CommandQueueData[CommandQueueLength++] = SrcPhyAddress;
+
+ // Setup Block Start Engine Command
+ CommandQueueData[CommandQueueLength++] =
+ ((AesUcqOpcode_BlockStartEngine << AesIcqBitShift_Opcode) |
+ ((NumBlocks - 1) << AesIcqBitShift_BlockCount));
+
+ // Setup DMA finish command
+ CommandQueueData[CommandQueueLength++] = (AesUcqOpcode_DmaFinish << AesIcqBitShift_Opcode);
+
+ // Wait for engine to become idle
+ NvAesCoreAp20WaitTillEngineIdle(Engine, pEngineVirAddr);
+
+ // Configure command Queue control register
+ SECURE_HW_REGR(Engine, pEngineVirAddr, CMDQUE_CONTROL, RegValue);
+
+ if (AesHwEngine_A == Engine)
+ {
+ RegValue |=
+ // Source Stream interface select,
+ // (SRC_STM_SEL = 0: through CIF (SDRAM)),
+ // and (SRC_STM_SEL = 1: through AHB (SDRAM/IRAM)).
+ SECURE_DRF_NUM(Engine, CMDQUE_CONTROL, SRC_STM_SEL, (SrcPhyAddress & NV_ADDRESS_MAP_IRAM_A_BASE) ? 1 : 0) |
+ // Destination Stream interface select,
+ // (DST_STM_SEL = 0: through CIF (SDRAM)),
+ // and (DST_STM_SEL = 1: through AHB (SDRAM/IRAM)).
+ SECURE_DRF_NUM(Engine, CMDQUE_CONTROL, DST_STM_SEL, (DestPhyAddress& NV_ADDRESS_MAP_IRAM_A_BASE) ? 1 : 0);
+ }
+ else
+ {
+ RegValue |=
+ // Source Stream interface select,
+ // (SRC_STM_SEL = 1: through AHB (SDRAM/IRAM)).
+ SECURE_DRF_NUM(Engine, CMDQUE_CONTROL, SRC_STM_SEL, 1) |
+ // Destination Stream interface select,
+ // (DST_STM_SEL = 1: through AHB (SDRAM/IRAM)).
+ SECURE_DRF_NUM(Engine, CMDQUE_CONTROL, DST_STM_SEL, 1);
+ }
+
+ // Update the Command Queue control register
+ SECURE_HW_REGW(Engine, pEngineVirAddr, CMDQUE_CONTROL, RegValue);
+
+ RegValue = SECURE_DRF_NUM(Engine, BSE_CONFIG, BSE_MODE_SEL, 0) |
+ // Endian conversion enable for the bit stream
+ // (ENDIAN_ENB = 1: little Endian stream)
+ SECURE_DRF_NUM(Engine, BSE_CONFIG, ENDIAN_ENB, 1);
+
+ // Update the BSE config register
+ SECURE_HW_REGW(Engine, pEngineVirAddr, BSE_CONFIG, RegValue);
+
+ // Read the AES config register
+ SECURE_HW_REGR(Engine, pEngineVirAddr, SECURE_CONFIG_EXT, RegValue);
+
+ // Set counter offset to '0'
+ SECURE_DRF_SET_VAL(Engine, SECURE_CONFIG_EXT, SECURE_OFFSET_CNT, 0, RegValue);
+ SECURE_HW_REGW(Engine, pEngineVirAddr, SECURE_CONFIG_EXT, RegValue);
+
+ // Configure the AES extension register for KEY and IV select
+ SECURE_HW_REGR(Engine, pEngineVirAddr, SECURE_INPUT_SELECT, RegValue);
+ SECURE_DRF_SET_VAL(Engine, SECURE_INPUT_SELECT, SECURE_IV_SELECT, 1, RegValue);
+
+ // Select AES operation mode for configuring the AES config register
+ //////////////////////////////////////////////////////////////////////////
+ switch (OpMode)
+ {
+ case NvDdkAesOperationalMode_Cbc:
+ // Configuration for CBC mode of operation:
+ // ----------------------------------------------------------------------
+ // | Encryption | Decryption
+ //-----------------------------------------------------------------------
+ // SECURE_XOR_POS | 10b (top) | 11b (bottom)
+ // SECURE_INPUT_SEL | 00b (AHB) | 00b (AHB)
+ // SECURE_VCTRAM_SEL | 10b (IV + AES Output) | 11b (IV_PreAHB)
+ // SECURE_CORE_SEL | 1b (AES) | 0b (inverse AES)
+ //////////////////////////////////////////////////////////////////////////
+ /* AES configuration for Encryption/Decryption */
+ // AES XOR position 10b = '2': top, before AES
+ // AES XOR position 11b = '3': bottom, after AES
+ SECURE_DRF_SET_VAL(Engine, SECURE_INPUT_SELECT, SECURE_XOR_POS, (IsEncryption ? 2 : 3), RegValue);
+ // AES input select 0?b = '00' or '01': From AHB input vector
+ SECURE_DRF_SET_VAL(Engine, SECURE_INPUT_SELECT, SECURE_INPUT_SEL, 0, RegValue);
+ // Vector RAM select 10b = '2': Init Vector for first round and AES
+ // output for the rest rounds.
+ // Vector RAM select 11b = '3': Init Vector for the first round
+ // and previous AHB input for the rest rounds
+ SECURE_DRF_SET_VAL(Engine, SECURE_INPUT_SELECT, SECURE_VCTRAM_SEL, (IsEncryption ? 2 : 3), RegValue);
+ // AES core selection 1b = '1': Encryption
+ // Inverse AES core selection 0b = '0': Decryption
+ SECURE_DRF_SET_VAL(Engine, SECURE_INPUT_SELECT, SECURE_CORE_SEL, (IsEncryption ? 1 : 0), RegValue);
+ // Disable the random number generator
+ SECURE_DRF_SET_VAL(Engine, SECURE_INPUT_SELECT, SECURE_RNG_ENB, 0, RegValue);
+ break;
+ case NvDdkAesOperationalMode_Ecb:
+ // Configuration for ECB mode of operation:
+ // ----------------------------------------------------------------------
+ // | Encryption | Decryption
+ //-----------------------------------------------------------------------
+ // SECURE_XOR_POS | 0X (bypass) | 0X (bypass)
+ // SECURE_INPUT_SEL | 00b (AHB) | 00b (AHB)
+ // SECURE_VCTRAM_SEL | XX(don’t care) | XX(don’t care)
+ // SECURE_CORE_SEL | 1b (AES) | 0b (inverse AES)
+ //////////////////////////////////////////////////////////////////////////
+ /* AES configuration for Encryption/Decryption */
+ // For ECB mode, XOR position shoud be bypassed
+ SECURE_DRF_SET_VAL(Engine, SECURE_INPUT_SELECT, SECURE_XOR_POS, 0, RegValue);
+ // AES input select is zero
+ SECURE_DRF_SET_VAL(Engine, SECURE_INPUT_SELECT, SECURE_INPUT_SEL, 0, RegValue);
+ // AES core selection 1b = '1': Encryption
+ // Inverse AES core selection 0b = '0': Decryption
+ SECURE_DRF_SET_VAL(Engine, SECURE_INPUT_SELECT, SECURE_CORE_SEL, (IsEncryption ? 1 : 0), RegValue);
+ // Disable the random number generator
+ SECURE_DRF_SET_VAL(Engine, SECURE_INPUT_SELECT, SECURE_RNG_ENB, 0, RegValue);
+ break;
+ case NvDdkAesOperationalMode_AnsiX931:
+ // For ECB mode, XOR position shoud be bypassed
+ SECURE_DRF_SET_VAL(Engine, SECURE_INPUT_SELECT, SECURE_XOR_POS, 0, RegValue);
+ // AES input select is zero
+ SECURE_DRF_SET_VAL(Engine, SECURE_INPUT_SELECT, SECURE_INPUT_SEL, 0, RegValue);
+ // AES core selection 1b = '1': Encryption
+ // Inverse AES core selection 0b = '0': Decryption
+ SECURE_DRF_SET_VAL(Engine, SECURE_INPUT_SELECT, SECURE_CORE_SEL, (IsEncryption ? 1 : 0), RegValue);
+ // To generate a random number, enable the random number generator
+ SECURE_DRF_SET_VAL(Engine, SECURE_INPUT_SELECT, SECURE_RNG_ENB, 1, RegValue);
+ break;
+ default:
+ return;
+ }
+
+ SECURE_DRF_SET_VAL(Engine, SECURE_INPUT_SELECT, SECURE_HASH_ENB, 0, RegValue);
+ SECURE_HW_REGW(Engine, pEngineVirAddr, SECURE_INPUT_SELECT, RegValue);
+
+ // Update the AES destination physical address
+ SECURE_HW_REGW(Engine, pEngineVirAddr, SECURE_DEST_ADDR, DestPhyAddress);
+
+ // Issue the AES commands to the ICQ
+ for (i = 0; i < CommandQueueLength; i++)
+ {
+ // Wait till engine becomes IDLE before issuing any command
+ do
+ {
+ SECURE_HW_REGR(Engine, pEngineVirAddr, INTR_STATUS, RegValue);
+ SECURE_DRF_READ_VAL(Engine, INTR_STATUS, ENGINE_BUSY, RegValue, EngBusy);
+ SECURE_DRF_READ_VAL(Engine, INTR_STATUS, ICQ_EMPTY, RegValue, IcqEmpty);
+ } while ((EngBusy) && ~(IcqEmpty));
+ // Write the command to the ICQ register
+ SECURE_HW_REGW(Engine, pEngineVirAddr, ICMDQUE_WR, CommandQueueData[i]);
+ }
+
+ // Wait for engine to become idle
+ NvAesCoreAp20WaitTillEngineIdle(Engine, pEngineVirAddr);
+}
+
+void
+NvAesCoreAp20ProcessBuffer(
+ const AesHwEngine Engine,
+ const NvU32 *const pEngineVirAddr,
+ const NvU32 SrcPhyAddress,
+ const NvU32 DestPhyAddress,
+ const NvU32 DataSize,
+ const NvU32 DmaPhyAddr,
+ const NvBool IsEncryption,
+ const NvU32 OpMode)
+{
+ NvU32 TotalBytes = DataSize;
+ NvU32 BytesToProcess = 0;
+ NvU32 *pSrcVirAddr = NULL;
+ NvU32 *pDestVirAddr = NULL;
+ NvU32 *pDmaVirAddr = NULL;
+ NvU32 NumBlocks = 0;
+ NvError e = NvRmPhysicalMemMap(
+ SrcPhyAddress,
+ DataSize,
+ NVOS_MEM_READ_WRITE,
+ NvOsMemAttribute_Uncached,
+ (void **)&pSrcVirAddr);
+ if (e != NvSuccess)
+ return;
+
+ e = NvRmPhysicalMemMap(
+ DestPhyAddress,
+ DataSize,
+ NVOS_MEM_READ_WRITE,
+ NvOsMemAttribute_Uncached,
+ (void **)&pDestVirAddr);
+ if (e != NvSuccess)
+ {
+ NvRmPhysicalMemUnmap(pSrcVirAddr, DataSize);
+ return;
+ }
+
+ NV_CHECK_ERROR_CLEANUP(NvRmPhysicalMemMap(
+ DmaPhyAddr,
+ AES_HW_DMA_BUFFER_SIZE_BYTES,
+ NVOS_MEM_READ_WRITE,
+ NvOsMemAttribute_Uncached,
+ (void **)&pDmaVirAddr));
+
+ while (TotalBytes)
+ {
+ if (TotalBytes > AES_HW_DMA_BUFFER_SIZE_BYTES)
+ BytesToProcess = AES_HW_DMA_BUFFER_SIZE_BYTES;
+ else
+ BytesToProcess = TotalBytes;
+
+ // Copy data to the DMA buffer from the client buffer
+ NvOsMemcpy((void *)pDmaVirAddr, (void *)pSrcVirAddr, BytesToProcess);
+
+ NumBlocks = BytesToProcess / NvDdkAesConst_BlockLengthBytes;
+
+ AesHwPrivProcessBuffer(Engine, pEngineVirAddr, DmaPhyAddr, DmaPhyAddr, NumBlocks, IsEncryption, OpMode);
+
+ // Copy data from the DMA buffer to the client buffer
+ NvOsMemcpy((void *)pDestVirAddr, (void *)pDmaVirAddr, BytesToProcess);
+
+ // Increment the buffer pointer
+ pSrcVirAddr += BytesToProcess;
+ pDestVirAddr += BytesToProcess;
+ TotalBytes -= BytesToProcess;
+ }
+
+ // UnMap the virtual address
+ NvRmPhysicalMemUnmap(pDmaVirAddr, DataSize);
+
+fail:
+ NvRmPhysicalMemUnmap(pDestVirAddr, DataSize);
+ NvRmPhysicalMemUnmap(pSrcVirAddr, DataSize);
+}
+
+void
+NvAesCoreAp20LoadSskToSecureScratchAndLock(
+ const NvU32 PmicBaseAddr,
+ const NvU32 *const pKey,
+ const size_t Size)
+{
+ NvU32 *pSecureScratch = NULL;
+ NvU32 *pPmicBaseAddr = NULL;
+
+ NvRmPhysicalMemMap(
+ PmicBaseAddr,
+ Size,
+ NVOS_MEM_READ_WRITE,
+ NvOsMemAttribute_Uncached,
+ (void **)&pPmicBaseAddr);
+
+ // Get the secure scratch base address
+ pSecureScratch = pPmicBaseAddr + (APBDEV_PMC_SECURE_SCRATCH0_0 / 4);
+
+ // If key is supplied then load it into the scratch registers
+ if (pKey)
+ {
+ NvU32 i;
+
+ // Load the SSK into the secure scratch registers
+ for (i = 0; i < AES_HW_KEY_LENGTH; i++)
+ {
+ NV_WRITE32(pSecureScratch, pKey[i]);
+ pSecureScratch++;
+ }
+ }
+
+ // Disable write access to the secure scratch register
+ NV_WRITE32((pPmicBaseAddr) + (APBDEV_PMC_SEC_DISABLE_0 / 4), (NV_DRF_DEF(APBDEV_PMC, SEC_DISABLE, WRITE, ON)));
+
+ // UnMap the virtual address
+ NvRmPhysicalMemUnmap(pPmicBaseAddr, Size);
+}
+
+void
+NvAesCoreAp20GetIvReadPermissions(
+ const AesHwEngine Engine,
+ const NvU32 *const pEngineVirAddr,
+ NvBool *const pReadPermissions)
+{
+ AesHwKeySlot KeySlot;
+ NvU32 RegValue = 0;
+
+ NV_ASSERT(pReadPermissions);
+
+ for (KeySlot = AesHwKeySlot_0; KeySlot < AesHwKeySlot_NumExt; KeySlot++)
+ {
+ SECURE_INDEXED_REGR(Engine, pEngineVirAddr, SECURE_SEC_SEL0, KeySlot,RegValue);
+ SECURE_DRF_READ_VAL(Engine, SECURE_SEC_SEL0, IVREAD_ENB0, RegValue, pReadPermissions[KeySlot]);
+ }
+}
diff --git a/arch/arm/mach-tegra/nvddk/nvddk_aes_core_ap20.h b/arch/arm/mach-tegra/nvddk/nvddk_aes_core_ap20.h
new file mode 100644
index 000000000000..3840efd41bed
--- /dev/null
+++ b/arch/arm/mach-tegra/nvddk/nvddk_aes_core_ap20.h
@@ -0,0 +1,229 @@
+/*
+ * Copyright (c) 2007-2009 NVIDIA Corporation.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of the NVIDIA Corporation nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef INCLUDED_NVDDK_AES_CORE_AP20_H
+#define INCLUDED_NVDDK_AES_CORE_AP20_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Disable the selected AES engine. No further operations can be
+ * performed using the AES engine until the entire chip is reset.
+ *
+ * @param Engine AES engine to disable.
+ * @param pEngineVirAddr AES engine virtual address.
+ *
+ * @retval NvSuccess if engine successfully disabled else NvError_AesDisableCryptoFailed.
+ */
+NvError NvAesCoreAp20DisableEngine(const AesHwEngine Engine, const NvU32 *const pEngineVirAddr);
+
+/**
+ * Read the AES engine disable status.
+ *
+ * @param Engine AES engine to disable.
+ * @param pEngineVirAddr AES engine virtual address.
+ *
+ * @retval NV_TRUE if engine is disabled else NV_FALSE.
+ */
+NvBool NvAesCoreAp20IsEngineDisabled(const AesHwEngine Engine, const NvU32 *const pEngineVirAddr);
+
+/**
+ * Wait till the engine is idle.
+ *
+ * @param Engine The engine which needs to be in idle state.
+ * @param pEngineVirAddr AES engine virtual address.
+ *
+ * @retval None.
+ */
+void NvAesCoreAp20WaitTillEngineIdle(const AesHwEngine Engine, const NvU32 *const pEngineVirAddr);
+
+/**
+ * Set up the key table.
+ *
+ * @param Engine The AES engine to setup the Key table.
+ * @param pEngineVirAddr AES engine virtual address.
+ * @param KeyTablePhyAddr The physical address of the keytable.
+ * @param Slot AES Key slot to use for setting up the key table.
+ *
+ * @retval None.
+ */
+void
+NvAesCoreAp20SetupTable(
+ const AesHwEngine Engine,
+ const NvU32 *const pEngineVirAddr,
+ const NvU32 KeyTablePhyAddr,
+ const NvU32 Slot);
+
+/**
+ * Select the Key slot for updating the IV vectors.
+ *
+ * @param Engine The AES engine to be used.
+ * @param pEngineVirAddr AES engine virtual address.
+ * @param Slot The slot to be selected.
+ *
+ * @retval None.
+ */
+void NvAesCoreAp20SelectKeyIvSlot(const AesHwEngine Engine, const NvU32 *const pEngineVirAddr, const NvU32 Slot);
+
+/**
+ * Set the IV in key table.
+ *
+ * @param Engine The AES engine to be used.
+ * @param pEngineVirAddr AES engine virtual address.
+ * @param Slot The slot of the engine to be used.
+ * @param Start The start location within the keytable.
+ * @param End The end location of keytable.
+ * @param pKeyTable The physical address of the engine keytable.
+ * @param KeyTableSize Size of key table in bytes.
+ * @param pIvAddress The IV to set, if NULL then the IV is cleared.
+ *
+ * @retval None.
+ */
+void
+NvAesCoreAp20SetIv(
+ const AesHwEngine Engine,
+ const NvU32 *const pEngineVirAddr,
+ const NvU32 Slot,
+ const NvU32 Start,
+ const NvU32 End,
+ const NvU32 *const pKeyTable,
+ const NvU32 KeyTableSize,
+ const NvU32 *const pIvAddress);
+
+/**
+ * Get the IV.
+ *
+ * @param Engine The AES engine to be used.
+ * @param pEngineVirAddr AES engine virtual address.
+ * @param Slot The slot of the engine to be used.
+ * @param Start The start location within the keytable.
+ * @param End The end location of keytable.
+ * @param pIvAddress The pointer to the location where the IV will be stored.
+ *
+ * @retval None.
+ */
+void
+NvAesCoreAp20GetIv(
+ const AesHwEngine Engine,
+ const NvU32 *const pEngineVirAddr,
+ const NvU32 Slot,
+ const NvU32 Start,
+ const NvU32 End,
+ const NvU32 *const pIvAddress);
+
+/**
+ * Enable/Disable the key schedule generation in hardware.
+ *
+ * @param Engine The engine for which the key generation needs to be disabled.
+ * @param pEngineVirAddr AES engine virtual address.
+ * @param IsEnabled NV_TRUE to enable the key schedule generation, NV_FALSE otherwise.
+ *
+ * @retval None.
+ */
+void
+NvAesCoreAp20ControlKeyScheduleGeneration(
+ const AesHwEngine Engine,
+ const NvU32 *const pEngineVirAddr,
+ const NvBool IsEnabled);
+
+/**
+ * Lock down the permissions for SSK.
+ *
+ * @param Engine The engine which needs to be locked.
+ * @param pEngineVirAddr AES engine virtual address.
+ *
+ * @retval None.
+ */
+void NvAesCoreAp20LockSskReadWrites(const AesHwEngine Engine, const NvU32 *const pEngineVirAddr);
+
+/**
+ * Encrypt/Decrypt blocks of data.
+ *
+ * @param Engine The engine to be used.
+ * @param pEngineVirAddr AES engine virtual address.
+ * @param SrcPhyAddress The physical address of source buffer.
+ * @param DestPhyAddress The physical address of destination buffer.
+ * @param DataSize The size of buffer.
+ * @param DmaPhyAddr The physical address of the DMA.
+ * @param IsEncryption NV_TRUE if encryption else NV_FALSE.
+ * @param OpMode Specifies the AES operational mode.
+ *
+ * @retval None.
+ */
+void
+NvAesCoreAp20ProcessBuffer(
+ const AesHwEngine Engine,
+ const NvU32 *const pEngineVirAddr,
+ const NvU32 SrcPhyAddress,
+ const NvU32 DestPhyAddress,
+ const NvU32 DataSize,
+ const NvU32 DmaPhyAddr,
+ const NvBool IsEncryption,
+ const NvU32 OpMode);
+
+/**
+ * Load the SSK key into secure scratch resgister and disables the write permissions.
+ *
+ * @param pPmicBaseAddr Pointer to the PMIC base address.
+ * @param pKey Pointer to the key.
+ * @param Size Length of the aperture in bytes.
+ *
+ * @retval None.
+ */
+void
+NvAesCoreAp20LoadSskToSecureScratchAndLock(
+ const NvU32 PmicBaseAddr,
+ const NvU32 *const pKey,
+ const size_t Size);
+
+/**
+ * Get the read permissions for IV for each key slot of an engine.
+ *
+ * @param Engine AES Engine for which Iv permissions for an engine are sought.
+ * @param pEngineVirAddr AES engine virtual address.
+ * @param pReadPermissions Pointer to read permissions.
+ *
+ * @retval None.
+ */
+void
+NvAesCoreAp20GetIvReadPermissions(
+ const AesHwEngine Engine,
+ const NvU32 *const pEngineVirAddr,
+ NvBool *const pReadPermissions);
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif // #define INCLUDED_NVDDK_AES_CORE_AP20_H
diff --git a/arch/arm/mach-tegra/nvddk/nvddk_aes_dispatch.c b/arch/arm/mach-tegra/nvddk/nvddk_aes_dispatch.c
new file mode 100644
index 000000000000..983597a3677f
--- /dev/null
+++ b/arch/arm/mach-tegra/nvddk/nvddk_aes_dispatch.c
@@ -0,0 +1,715 @@
+
+#define NV_IDL_IS_DISPATCH
+
+/*
+ * Copyright (c) 2007-2009 NVIDIA Corporation.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of the NVIDIA Corporation nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "nvcommon.h"
+#include "nvos.h"
+#include "nvassert.h"
+#include "nvreftrack.h"
+#include "nvidlcmd.h"
+#include "nvddk_aes.h"
+
+#define OFFSET( s, e ) (NvU32)(void *)(&(((s*)0)->e))
+
+
+typedef struct NvDdkAesDisableCrypto_in_t
+{
+ NvU32 package_;
+ NvU32 function_;
+ NvDdkAesHandle hAes;
+} NV_ALIGN(4) NvDdkAesDisableCrypto_in;
+
+typedef struct NvDdkAesDisableCrypto_inout_t
+{
+ NvU32 dummy_;
+} NV_ALIGN(4) NvDdkAesDisableCrypto_inout;
+
+typedef struct NvDdkAesDisableCrypto_out_t
+{
+ NvError ret_;
+} NV_ALIGN(4) NvDdkAesDisableCrypto_out;
+
+typedef struct NvDdkAesDisableCrypto_params_t
+{
+ NvDdkAesDisableCrypto_in in;
+ NvDdkAesDisableCrypto_inout inout;
+ NvDdkAesDisableCrypto_out out;
+} NvDdkAesDisableCrypto_params;
+
+typedef struct NvDdkAesSetAndLockSecureStorageKey_in_t
+{
+ NvU32 package_;
+ NvU32 function_;
+ NvDdkAesHandle hAes;
+ NvDdkAesKeySize KeyLength;
+ NvU8 * pSecureStorageKey;
+} NV_ALIGN(4) NvDdkAesSetAndLockSecureStorageKey_in;
+
+typedef struct NvDdkAesSetAndLockSecureStorageKey_inout_t
+{
+ NvU32 dummy_;
+} NV_ALIGN(4) NvDdkAesSetAndLockSecureStorageKey_inout;
+
+typedef struct NvDdkAesSetAndLockSecureStorageKey_out_t
+{
+ NvError ret_;
+} NV_ALIGN(4) NvDdkAesSetAndLockSecureStorageKey_out;
+
+typedef struct NvDdkAesSetAndLockSecureStorageKey_params_t
+{
+ NvDdkAesSetAndLockSecureStorageKey_in in;
+ NvDdkAesSetAndLockSecureStorageKey_inout inout;
+ NvDdkAesSetAndLockSecureStorageKey_out out;
+} NvDdkAesSetAndLockSecureStorageKey_params;
+
+typedef struct NvDdkAesLockSecureStorageKey_in_t
+{
+ NvU32 package_;
+ NvU32 function_;
+ NvDdkAesHandle hAes;
+} NV_ALIGN(4) NvDdkAesLockSecureStorageKey_in;
+
+typedef struct NvDdkAesLockSecureStorageKey_inout_t
+{
+ NvU32 dummy_;
+} NV_ALIGN(4) NvDdkAesLockSecureStorageKey_inout;
+
+typedef struct NvDdkAesLockSecureStorageKey_out_t
+{
+ NvError ret_;
+} NV_ALIGN(4) NvDdkAesLockSecureStorageKey_out;
+
+typedef struct NvDdkAesLockSecureStorageKey_params_t
+{
+ NvDdkAesLockSecureStorageKey_in in;
+ NvDdkAesLockSecureStorageKey_inout inout;
+ NvDdkAesLockSecureStorageKey_out out;
+} NvDdkAesLockSecureStorageKey_params;
+
+typedef struct NvDdkAesClearSecureBootKey_in_t
+{
+ NvU32 package_;
+ NvU32 function_;
+ NvDdkAesHandle hAes;
+} NV_ALIGN(4) NvDdkAesClearSecureBootKey_in;
+
+typedef struct NvDdkAesClearSecureBootKey_inout_t
+{
+ NvU32 dummy_;
+} NV_ALIGN(4) NvDdkAesClearSecureBootKey_inout;
+
+typedef struct NvDdkAesClearSecureBootKey_out_t
+{
+ NvError ret_;
+} NV_ALIGN(4) NvDdkAesClearSecureBootKey_out;
+
+typedef struct NvDdkAesClearSecureBootKey_params_t
+{
+ NvDdkAesClearSecureBootKey_in in;
+ NvDdkAesClearSecureBootKey_inout inout;
+ NvDdkAesClearSecureBootKey_out out;
+} NvDdkAesClearSecureBootKey_params;
+
+typedef struct NvDdkAesGetCapabilities_in_t
+{
+ NvU32 package_;
+ NvU32 function_;
+ NvDdkAesHandle hAes;
+} NV_ALIGN(4) NvDdkAesGetCapabilities_in;
+
+typedef struct NvDdkAesGetCapabilities_inout_t
+{
+ NvDdkAesCapabilities pCapabilities;
+} NV_ALIGN(4) NvDdkAesGetCapabilities_inout;
+
+typedef struct NvDdkAesGetCapabilities_out_t
+{
+ NvError ret_;
+} NV_ALIGN(4) NvDdkAesGetCapabilities_out;
+
+typedef struct NvDdkAesGetCapabilities_params_t
+{
+ NvDdkAesGetCapabilities_in in;
+ NvDdkAesGetCapabilities_inout inout;
+ NvDdkAesGetCapabilities_out out;
+} NvDdkAesGetCapabilities_params;
+
+typedef struct NvDdkAesProcessBuffer_in_t
+{
+ NvU32 package_;
+ NvU32 function_;
+ NvDdkAesHandle hAes;
+ NvU32 SrcBufferSize;
+ NvU32 DestBufferSize;
+ NvU8 * pSrcBuffer;
+ NvU8 * pDestBuffer;
+} NV_ALIGN(4) NvDdkAesProcessBuffer_in;
+
+typedef struct NvDdkAesProcessBuffer_inout_t
+{
+ NvU32 dummy_;
+} NV_ALIGN(4) NvDdkAesProcessBuffer_inout;
+
+typedef struct NvDdkAesProcessBuffer_out_t
+{
+ NvError ret_;
+} NV_ALIGN(4) NvDdkAesProcessBuffer_out;
+
+typedef struct NvDdkAesProcessBuffer_params_t
+{
+ NvDdkAesProcessBuffer_in in;
+ NvDdkAesProcessBuffer_inout inout;
+ NvDdkAesProcessBuffer_out out;
+} NvDdkAesProcessBuffer_params;
+
+typedef struct NvDdkAesGetInitialVector_in_t
+{
+ NvU32 package_;
+ NvU32 function_;
+ NvDdkAesHandle hAes;
+ NvU32 VectorSize;
+ NvU8 * pInitialVector;
+} NV_ALIGN(4) NvDdkAesGetInitialVector_in;
+
+typedef struct NvDdkAesGetInitialVector_inout_t
+{
+ NvU32 dummy_;
+} NV_ALIGN(4) NvDdkAesGetInitialVector_inout;
+
+typedef struct NvDdkAesGetInitialVector_out_t
+{
+ NvError ret_;
+} NV_ALIGN(4) NvDdkAesGetInitialVector_out;
+
+typedef struct NvDdkAesGetInitialVector_params_t
+{
+ NvDdkAesGetInitialVector_in in;
+ NvDdkAesGetInitialVector_inout inout;
+ NvDdkAesGetInitialVector_out out;
+} NvDdkAesGetInitialVector_params;
+
+typedef struct NvDdkAesSetInitialVector_in_t
+{
+ NvU32 package_;
+ NvU32 function_;
+ NvDdkAesHandle hAes;
+ NvU8 * pInitialVector;
+ NvU32 VectorSize;
+} NV_ALIGN(4) NvDdkAesSetInitialVector_in;
+
+typedef struct NvDdkAesSetInitialVector_inout_t
+{
+ NvU32 dummy_;
+} NV_ALIGN(4) NvDdkAesSetInitialVector_inout;
+
+typedef struct NvDdkAesSetInitialVector_out_t
+{
+ NvError ret_;
+} NV_ALIGN(4) NvDdkAesSetInitialVector_out;
+
+typedef struct NvDdkAesSetInitialVector_params_t
+{
+ NvDdkAesSetInitialVector_in in;
+ NvDdkAesSetInitialVector_inout inout;
+ NvDdkAesSetInitialVector_out out;
+} NvDdkAesSetInitialVector_params;
+
+typedef struct NvDdkAesSelectOperation_in_t
+{
+ NvU32 package_;
+ NvU32 function_;
+ NvDdkAesHandle hAes;
+ NvDdkAesOperation pOperation;
+} NV_ALIGN(4) NvDdkAesSelectOperation_in;
+
+typedef struct NvDdkAesSelectOperation_inout_t
+{
+ NvU32 dummy_;
+} NV_ALIGN(4) NvDdkAesSelectOperation_inout;
+
+typedef struct NvDdkAesSelectOperation_out_t
+{
+ NvError ret_;
+} NV_ALIGN(4) NvDdkAesSelectOperation_out;
+
+typedef struct NvDdkAesSelectOperation_params_t
+{
+ NvDdkAesSelectOperation_in in;
+ NvDdkAesSelectOperation_inout inout;
+ NvDdkAesSelectOperation_out out;
+} NvDdkAesSelectOperation_params;
+
+typedef struct NvDdkAesSelectKey_in_t
+{
+ NvU32 package_;
+ NvU32 function_;
+ NvDdkAesHandle hAes;
+ NvDdkAesKeyInfo pKeyInfo;
+} NV_ALIGN(4) NvDdkAesSelectKey_in;
+
+typedef struct NvDdkAesSelectKey_inout_t
+{
+ NvU32 dummy_;
+} NV_ALIGN(4) NvDdkAesSelectKey_inout;
+
+typedef struct NvDdkAesSelectKey_out_t
+{
+ NvError ret_;
+} NV_ALIGN(4) NvDdkAesSelectKey_out;
+
+typedef struct NvDdkAesSelectKey_params_t
+{
+ NvDdkAesSelectKey_in in;
+ NvDdkAesSelectKey_inout inout;
+ NvDdkAesSelectKey_out out;
+} NvDdkAesSelectKey_params;
+
+typedef struct NvDdkAesClose_in_t
+{
+ NvU32 package_;
+ NvU32 function_;
+ NvDdkAesHandle hAes;
+} NV_ALIGN(4) NvDdkAesClose_in;
+
+typedef struct NvDdkAesClose_inout_t
+{
+ NvU32 dummy_;
+} NV_ALIGN(4) NvDdkAesClose_inout;
+
+typedef struct NvDdkAesClose_out_t
+{
+ NvU32 dummy_;
+} NV_ALIGN(4) NvDdkAesClose_out;
+
+typedef struct NvDdkAesClose_params_t
+{
+ NvDdkAesClose_in in;
+ NvDdkAesClose_inout inout;
+ NvDdkAesClose_out out;
+} NvDdkAesClose_params;
+
+typedef struct NvDdkAesOpen_in_t
+{
+ NvU32 package_;
+ NvU32 function_;
+ NvU32 InstanceId;
+} NV_ALIGN(4) NvDdkAesOpen_in;
+
+typedef struct NvDdkAesOpen_inout_t
+{
+ NvU32 dummy_;
+} NV_ALIGN(4) NvDdkAesOpen_inout;
+
+typedef struct NvDdkAesOpen_out_t
+{
+ NvError ret_;
+ NvDdkAesHandle phAes;
+} NV_ALIGN(4) NvDdkAesOpen_out;
+
+typedef struct NvDdkAesOpen_params_t
+{
+ NvDdkAesOpen_in in;
+ NvDdkAesOpen_inout inout;
+ NvDdkAesOpen_out out;
+} NvDdkAesOpen_params;
+
+static NvError NvDdkAesDisableCrypto_dispatch_( void *InBuffer, NvU32 InSize, void *OutBuffer, NvU32 OutSize, NvDispatchCtx* Ctx )
+{
+ NvError err_ = NvSuccess;
+ NvDdkAesDisableCrypto_in *p_in;
+ NvDdkAesDisableCrypto_out *p_out;
+
+ p_in = (NvDdkAesDisableCrypto_in *)InBuffer;
+ p_out = (NvDdkAesDisableCrypto_out *)((NvU8 *)OutBuffer + OFFSET(NvDdkAesDisableCrypto_params, out) - OFFSET(NvDdkAesDisableCrypto_params, inout));
+
+
+ p_out->ret_ = NvDdkAesDisableCrypto( p_in->hAes );
+
+ return err_;
+}
+
+static NvError NvDdkAesSetAndLockSecureStorageKey_dispatch_( void *InBuffer, NvU32 InSize, void *OutBuffer, NvU32 OutSize, NvDispatchCtx* Ctx )
+{
+ NvError err_ = NvSuccess;
+ NvDdkAesSetAndLockSecureStorageKey_in *p_in;
+ NvDdkAesSetAndLockSecureStorageKey_out *p_out;
+ NvU8 *pSecureStorageKey = NULL;
+
+ p_in = (NvDdkAesSetAndLockSecureStorageKey_in *)InBuffer;
+ p_out = (NvDdkAesSetAndLockSecureStorageKey_out *)((NvU8 *)OutBuffer + OFFSET(NvDdkAesSetAndLockSecureStorageKey_params, out) - OFFSET(NvDdkAesSetAndLockSecureStorageKey_params, inout));
+
+ if( p_in->KeyLength && p_in->pSecureStorageKey )
+ {
+ pSecureStorageKey = (NvU8 *)NvOsAlloc( p_in->KeyLength * sizeof( NvU8 ) );
+ if( !pSecureStorageKey )
+ {
+ err_ = NvError_InsufficientMemory;
+ goto clean;
+ }
+ if( p_in->pSecureStorageKey )
+ {
+ err_ = NvOsCopyIn( pSecureStorageKey, p_in->pSecureStorageKey, p_in->KeyLength * sizeof( NvU8 ) );
+ if( err_ != NvSuccess )
+ {
+ err_ = NvError_BadParameter;
+ goto clean;
+ }
+ }
+ }
+
+ p_out->ret_ = NvDdkAesSetAndLockSecureStorageKey( p_in->hAes, p_in->KeyLength, pSecureStorageKey );
+
+clean:
+ NvOsFree( pSecureStorageKey );
+ return err_;
+}
+
+static NvError NvDdkAesLockSecureStorageKey_dispatch_( void *InBuffer, NvU32 InSize, void *OutBuffer, NvU32 OutSize, NvDispatchCtx* Ctx )
+{
+ NvError err_ = NvSuccess;
+ NvDdkAesLockSecureStorageKey_in *p_in;
+ NvDdkAesLockSecureStorageKey_out *p_out;
+
+ p_in = (NvDdkAesLockSecureStorageKey_in *)InBuffer;
+ p_out = (NvDdkAesLockSecureStorageKey_out *)((NvU8 *)OutBuffer + OFFSET(NvDdkAesLockSecureStorageKey_params, out) - OFFSET(NvDdkAesLockSecureStorageKey_params, inout));
+
+
+ p_out->ret_ = NvDdkAesLockSecureStorageKey( p_in->hAes );
+
+ return err_;
+}
+
+static NvError NvDdkAesClearSecureBootKey_dispatch_( void *InBuffer, NvU32 InSize, void *OutBuffer, NvU32 OutSize, NvDispatchCtx* Ctx )
+{
+ NvError err_ = NvSuccess;
+ NvDdkAesClearSecureBootKey_in *p_in;
+ NvDdkAesClearSecureBootKey_out *p_out;
+
+ p_in = (NvDdkAesClearSecureBootKey_in *)InBuffer;
+ p_out = (NvDdkAesClearSecureBootKey_out *)((NvU8 *)OutBuffer + OFFSET(NvDdkAesClearSecureBootKey_params, out) - OFFSET(NvDdkAesClearSecureBootKey_params, inout));
+
+
+ p_out->ret_ = NvDdkAesClearSecureBootKey( p_in->hAes );
+
+ return err_;
+}
+
+static NvError NvDdkAesGetCapabilities_dispatch_( void *InBuffer, NvU32 InSize, void *OutBuffer, NvU32 OutSize, NvDispatchCtx* Ctx )
+{
+ NvError err_ = NvSuccess;
+ NvDdkAesGetCapabilities_in *p_in;
+ NvDdkAesGetCapabilities_inout *p_inout;
+ NvDdkAesGetCapabilities_out *p_out;
+ NvDdkAesGetCapabilities_inout inout;
+
+ p_in = (NvDdkAesGetCapabilities_in *)InBuffer;
+ p_inout = (NvDdkAesGetCapabilities_inout *)((NvU8 *)InBuffer + OFFSET(NvDdkAesGetCapabilities_params, inout));
+ p_out = (NvDdkAesGetCapabilities_out *)((NvU8 *)OutBuffer + OFFSET(NvDdkAesGetCapabilities_params, out) - OFFSET(NvDdkAesGetCapabilities_params, inout));
+
+ (void)inout;
+ inout.pCapabilities = p_inout->pCapabilities;
+
+ p_out->ret_ = NvDdkAesGetCapabilities( p_in->hAes, &inout.pCapabilities );
+
+
+ p_inout = (NvDdkAesGetCapabilities_inout *)OutBuffer;
+ p_inout->pCapabilities = inout.pCapabilities;
+ return err_;
+}
+
+static NvError NvDdkAesProcessBuffer_dispatch_( void *InBuffer, NvU32 InSize, void *OutBuffer, NvU32 OutSize, NvDispatchCtx* Ctx )
+{
+ NvError err_ = NvSuccess;
+ NvDdkAesProcessBuffer_in *p_in;
+ NvDdkAesProcessBuffer_out *p_out;
+ NvU8 *pSrcBuffer = NULL;
+ NvU8 *pDestBuffer = NULL;
+
+ p_in = (NvDdkAesProcessBuffer_in *)InBuffer;
+ p_out = (NvDdkAesProcessBuffer_out *)((NvU8 *)OutBuffer + OFFSET(NvDdkAesProcessBuffer_params, out) - OFFSET(NvDdkAesProcessBuffer_params, inout));
+
+ if( p_in->SrcBufferSize && p_in->pSrcBuffer )
+ {
+ pSrcBuffer = (NvU8 *)NvOsAlloc( p_in->SrcBufferSize * sizeof( NvU8 ) );
+ if( !pSrcBuffer )
+ {
+ err_ = NvError_InsufficientMemory;
+ goto clean;
+ }
+ if( p_in->pSrcBuffer )
+ {
+ err_ = NvOsCopyIn( pSrcBuffer, p_in->pSrcBuffer, p_in->SrcBufferSize * sizeof( NvU8 ) );
+ if( err_ != NvSuccess )
+ {
+ err_ = NvError_BadParameter;
+ goto clean;
+ }
+ }
+ }
+ if( p_in->DestBufferSize && p_in->pDestBuffer )
+ {
+ pDestBuffer = (NvU8 *)NvOsAlloc( p_in->DestBufferSize * sizeof( NvU8 ) );
+ if( !pDestBuffer )
+ {
+ err_ = NvError_InsufficientMemory;
+ goto clean;
+ }
+ if( p_in->pDestBuffer )
+ {
+ err_ = NvOsCopyIn( pDestBuffer, p_in->pDestBuffer, p_in->DestBufferSize * sizeof( NvU8 ) );
+ if( err_ != NvSuccess )
+ {
+ err_ = NvError_BadParameter;
+ goto clean;
+ }
+ }
+ }
+
+ p_out->ret_ = NvDdkAesProcessBuffer( p_in->hAes, p_in->SrcBufferSize, p_in->DestBufferSize, pSrcBuffer, pDestBuffer );
+
+ if(p_in->pDestBuffer && pDestBuffer)
+ {
+ err_ = NvOsCopyOut( p_in->pDestBuffer, pDestBuffer, p_in->DestBufferSize * sizeof( NvU8 ) );
+ if( err_ != NvSuccess )
+ {
+ err_ = NvError_BadParameter;
+ }
+ }
+clean:
+ NvOsFree( pSrcBuffer );
+ NvOsFree( pDestBuffer );
+ return err_;
+}
+
+static NvError NvDdkAesGetInitialVector_dispatch_( void *InBuffer, NvU32 InSize, void *OutBuffer, NvU32 OutSize, NvDispatchCtx* Ctx )
+{
+ NvError err_ = NvSuccess;
+ NvDdkAesGetInitialVector_in *p_in;
+ NvDdkAesGetInitialVector_out *p_out;
+ NvU8 *pInitialVector = NULL;
+
+ p_in = (NvDdkAesGetInitialVector_in *)InBuffer;
+ p_out = (NvDdkAesGetInitialVector_out *)((NvU8 *)OutBuffer + OFFSET(NvDdkAesGetInitialVector_params, out) - OFFSET(NvDdkAesGetInitialVector_params, inout));
+
+ if( p_in->VectorSize && p_in->pInitialVector )
+ {
+ pInitialVector = (NvU8 *)NvOsAlloc( p_in->VectorSize * sizeof( NvU8 ) );
+ if( !pInitialVector )
+ {
+ err_ = NvError_InsufficientMemory;
+ goto clean;
+ }
+ if( p_in->pInitialVector )
+ {
+ err_ = NvOsCopyIn( pInitialVector, p_in->pInitialVector, p_in->VectorSize * sizeof( NvU8 ) );
+ if( err_ != NvSuccess )
+ {
+ err_ = NvError_BadParameter;
+ goto clean;
+ }
+ }
+ }
+
+ p_out->ret_ = NvDdkAesGetInitialVector( p_in->hAes, p_in->VectorSize, pInitialVector );
+
+ if(p_in->pInitialVector && pInitialVector)
+ {
+ err_ = NvOsCopyOut( p_in->pInitialVector, pInitialVector, p_in->VectorSize * sizeof( NvU8 ) );
+ if( err_ != NvSuccess )
+ {
+ err_ = NvError_BadParameter;
+ }
+ }
+clean:
+ NvOsFree( pInitialVector );
+ return err_;
+}
+
+static NvError NvDdkAesSetInitialVector_dispatch_( void *InBuffer, NvU32 InSize, void *OutBuffer, NvU32 OutSize, NvDispatchCtx* Ctx )
+{
+ NvError err_ = NvSuccess;
+ NvDdkAesSetInitialVector_in *p_in;
+ NvDdkAesSetInitialVector_out *p_out;
+ NvU8 *pInitialVector = NULL;
+
+ p_in = (NvDdkAesSetInitialVector_in *)InBuffer;
+ p_out = (NvDdkAesSetInitialVector_out *)((NvU8 *)OutBuffer + OFFSET(NvDdkAesSetInitialVector_params, out) - OFFSET(NvDdkAesSetInitialVector_params, inout));
+
+ if( p_in->VectorSize && p_in->pInitialVector )
+ {
+ pInitialVector = (NvU8 *)NvOsAlloc( p_in->VectorSize * sizeof( NvU8 ) );
+ if( !pInitialVector )
+ {
+ err_ = NvError_InsufficientMemory;
+ goto clean;
+ }
+ if( p_in->pInitialVector )
+ {
+ err_ = NvOsCopyIn( pInitialVector, p_in->pInitialVector, p_in->VectorSize * sizeof( NvU8 ) );
+ if( err_ != NvSuccess )
+ {
+ err_ = NvError_BadParameter;
+ goto clean;
+ }
+ }
+ }
+
+ p_out->ret_ = NvDdkAesSetInitialVector( p_in->hAes, pInitialVector, p_in->VectorSize );
+
+clean:
+ NvOsFree( pInitialVector );
+ return err_;
+}
+
+static NvError NvDdkAesSelectOperation_dispatch_( void *InBuffer, NvU32 InSize, void *OutBuffer, NvU32 OutSize, NvDispatchCtx* Ctx )
+{
+ NvError err_ = NvSuccess;
+ NvDdkAesSelectOperation_in *p_in;
+ NvDdkAesSelectOperation_out *p_out;
+
+ p_in = (NvDdkAesSelectOperation_in *)InBuffer;
+ p_out = (NvDdkAesSelectOperation_out *)((NvU8 *)OutBuffer + OFFSET(NvDdkAesSelectOperation_params, out) - OFFSET(NvDdkAesSelectOperation_params, inout));
+
+
+ p_out->ret_ = NvDdkAesSelectOperation( p_in->hAes, &p_in->pOperation );
+
+ return err_;
+}
+
+static NvError NvDdkAesSelectKey_dispatch_( void *InBuffer, NvU32 InSize, void *OutBuffer, NvU32 OutSize, NvDispatchCtx* Ctx )
+{
+ NvError err_ = NvSuccess;
+ NvDdkAesSelectKey_in *p_in;
+ NvDdkAesSelectKey_out *p_out;
+
+ p_in = (NvDdkAesSelectKey_in *)InBuffer;
+ p_out = (NvDdkAesSelectKey_out *)((NvU8 *)OutBuffer + OFFSET(NvDdkAesSelectKey_params, out) - OFFSET(NvDdkAesSelectKey_params, inout));
+
+
+ p_out->ret_ = NvDdkAesSelectKey( p_in->hAes, &p_in->pKeyInfo );
+
+ return err_;
+}
+
+static NvError NvDdkAesClose_dispatch_( void *InBuffer, NvU32 InSize, void *OutBuffer, NvU32 OutSize, NvDispatchCtx* Ctx )
+{
+ NvError err_ = NvSuccess;
+ NvDdkAesClose_in *p_in;
+
+ p_in = (NvDdkAesClose_in *)InBuffer;
+
+ if (p_in->hAes != NULL) NvRtFreeObjRef(Ctx, NvRtObjType_NvDdkAes_NvDdkAesHandle, p_in->hAes);
+
+ NvDdkAesClose( p_in->hAes );
+
+ return err_;
+}
+
+static NvError NvDdkAesOpen_dispatch_( void *InBuffer, NvU32 InSize, void *OutBuffer, NvU32 OutSize, NvDispatchCtx* Ctx )
+{
+ NvError err_ = NvSuccess;
+ NvDdkAesOpen_in *p_in;
+ NvDdkAesOpen_out *p_out;
+ NvRtObjRefHandle ref_phAes = 0;
+
+ p_in = (NvDdkAesOpen_in *)InBuffer;
+ p_out = (NvDdkAesOpen_out *)((NvU8 *)OutBuffer + OFFSET(NvDdkAesOpen_params, out) - OFFSET(NvDdkAesOpen_params, inout));
+
+ err_ = NvRtAllocObjRef(Ctx, &ref_phAes);
+ if (err_ != NvSuccess)
+ {
+ goto clean;
+ }
+
+ p_out->ret_ = NvDdkAesOpen( p_in->InstanceId, &p_out->phAes );
+
+ if ( p_out->ret_ == NvSuccess )
+ {
+ NvRtStoreObjRef(Ctx, ref_phAes, NvRtObjType_NvDdkAes_NvDdkAesHandle, p_out->phAes);
+ ref_phAes = 0;
+ }
+clean:
+ if (ref_phAes) NvRtDiscardObjRef(Ctx, ref_phAes);
+ return err_;
+}
+
+NvError nvddk_aes_Dispatch( NvU32 function, void *InBuffer, NvU32 InSize, void *OutBuffer, NvU32 OutSize, NvDispatchCtx* Ctx );
+NvError nvddk_aes_Dispatch( NvU32 function, void *InBuffer, NvU32 InSize, void *OutBuffer, NvU32 OutSize, NvDispatchCtx* Ctx )
+{
+ NvError err_ = NvSuccess;
+
+ switch( function ) {
+ case 11:
+ err_ = NvDdkAesDisableCrypto_dispatch_( InBuffer, InSize, OutBuffer, OutSize, Ctx );
+ break;
+ case 10:
+ err_ = NvDdkAesSetAndLockSecureStorageKey_dispatch_( InBuffer, InSize, OutBuffer, OutSize, Ctx );
+ break;
+ case 9:
+ err_ = NvDdkAesLockSecureStorageKey_dispatch_( InBuffer, InSize, OutBuffer, OutSize, Ctx );
+ break;
+ case 8:
+ err_ = NvDdkAesClearSecureBootKey_dispatch_( InBuffer, InSize, OutBuffer, OutSize, Ctx );
+ break;
+ case 7:
+ err_ = NvDdkAesGetCapabilities_dispatch_( InBuffer, InSize, OutBuffer, OutSize, Ctx );
+ break;
+ case 6:
+ err_ = NvDdkAesProcessBuffer_dispatch_( InBuffer, InSize, OutBuffer, OutSize, Ctx );
+ break;
+ case 5:
+ err_ = NvDdkAesGetInitialVector_dispatch_( InBuffer, InSize, OutBuffer, OutSize, Ctx );
+ break;
+ case 4:
+ err_ = NvDdkAesSetInitialVector_dispatch_( InBuffer, InSize, OutBuffer, OutSize, Ctx );
+ break;
+ case 3:
+ err_ = NvDdkAesSelectOperation_dispatch_( InBuffer, InSize, OutBuffer, OutSize, Ctx );
+ break;
+ case 2:
+ err_ = NvDdkAesSelectKey_dispatch_( InBuffer, InSize, OutBuffer, OutSize, Ctx );
+ break;
+ case 1:
+ err_ = NvDdkAesClose_dispatch_( InBuffer, InSize, OutBuffer, OutSize, Ctx );
+ break;
+ case 0:
+ err_ = NvDdkAesOpen_dispatch_( InBuffer, InSize, OutBuffer, OutSize, Ctx );
+ break;
+ default:
+ err_ = NvError_BadParameter;
+ break;
+ }
+
+ return err_;
+}
diff --git a/arch/arm/mach-tegra/nvddk/nvddk_aes_hw.h b/arch/arm/mach-tegra/nvddk/nvddk_aes_hw.h
new file mode 100644
index 000000000000..bbdb2750a106
--- /dev/null
+++ b/arch/arm/mach-tegra/nvddk/nvddk_aes_hw.h
@@ -0,0 +1,154 @@
+/*
+ * Copyright (c) 2007-2009 NVIDIA Corporation.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of the NVIDIA Corporation nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef INCLUDED_NVDDK_AES_HW_H
+#define INCLUDED_NVDDK_AES_HW_H
+
+#include "nverror.h"
+#include "nvcommon.h"
+
+#ifndef NV_OAL
+#define NV_OAL 0
+#endif
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+/**
+ * The key table length is 64 bytes.
+ * (This includes first upto 32 bytes key + 16 bytes original initial
+ * vector and 16 bytes updated initial vector)
+ */
+enum {AES_HW_KEY_TABLE_LENGTH_BYTES = 64};
+
+/**
+ * Keytable array, this must be in the IRAM.
+ */
+enum {AES_HW_KEY_TABLE_ADDR_ALIGNMENT = 256};
+
+/**
+ * The key Table length is 256 bytes = 64 words, (32 bit each word).
+ * (This includes first 16 bytes key + 224 bytes
+ * Key expantion data + 16 bytes Initial vector)
+ */
+enum {AES_HW_KEY_SCHEDULE_LENGTH = 64};
+
+/**
+ * The key Table length is 64 bytes = 16 words, (32 bit each word).
+ */
+enum {AES_HW_KEY_TABLE_LENGTH = 16};
+
+#if NV_OAL
+/*
+ * Key table address must be in the IRAM.
+ */
+enum {NVBL_AES_KEY_TABLE_ADDR = 0x40001d00};
+
+/**
+ * DMA Buffer size for processing the encryption and decryption with H/W.
+ * Each engine is allocated 4 Kilo Bytes buffer for data processing.
+ * This buffer is shared for both input data and out put data.
+ */
+enum {AES_HW_DMA_BUFFER_SIZE_BYTES = 0x1000};
+
+#else
+
+/*
+ * Key table address must be in the IRAM.
+ */
+enum {NVBL_AES_KEY_TABLE_OFFSET = 0x1d00};
+
+/**
+ * DMA Buffer size for processing the encryption and decryption with H/W.
+ * Each engine is allocated 32 Kilo Bytes buffer for data processing.
+ * This buffer is shared for both input data and out put data.
+ */
+enum {AES_HW_DMA_BUFFER_SIZE_BYTES = 0x8000};
+
+/**
+ * Define AES engine Max process bytes size in one go, which takes 1 msec.
+ * AES engine spends about 176 cycles/16-bytes or 11 cycles/byte
+ * The duration CPU can use the BSE to 1 msec, then the number of available
+ * cycles of AVP/BSE is 216K. In this duration, AES can process 216/11 ~= 19 KBytes
+ * Based on this AES_HW_MAX_PROCESS_SIZE_BYTES is configured to 16KB.
+ */
+enum {AES_HW_MAX_PROCESS_SIZE_BYTES = 0x4000};
+
+#endif // NV_OAL
+
+/**
+ * DMA data buffer address alignment.
+ */
+enum {AES_HW_DMA_ADDR_ALIGNMENT = 16};
+
+/**
+ * The Initial Vector length in the 32 bit words. (128 bits = 4 words)
+ */
+enum {AES_HW_IV_LENGTH = 4};
+
+/**
+ * The Initial Vector length in the 32 bit words. (128 bits = 4 words)
+ */
+enum {AES_HW_KEY_LENGTH = 4};
+
+/**
+ * Define AES block length in the 32 bit words (128-bits = 4 words)
+ */
+enum {AES_HW_BLOCK_LENGTH = 4};
+
+/**
+ * Define AES block length in log2 bytes = 2^4 = 16 bytes.
+ */
+enum {AES_HW_BLOCK_LENGTH_LOG2 = 4};
+
+/**
+ * AES Key (128 bits).
+ */
+typedef struct AesHwKeyRec
+{
+ NvU32 key[AES_HW_KEY_LENGTH];
+} AesHwKey;
+
+/**
+ * AES Initial Vector (128 bits).
+ */
+typedef struct AesHwIvRec
+{
+ NvU32 iv[AES_HW_IV_LENGTH];
+} AesHwIv;
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif // INCLUDED_AES_HW_H
diff --git a/arch/arm/mach-tegra/nvddk/nvddk_aes_intf_ap20.c b/arch/arm/mach-tegra/nvddk/nvddk_aes_intf_ap20.c
new file mode 100644
index 000000000000..2e86e6e0ae27
--- /dev/null
+++ b/arch/arm/mach-tegra/nvddk/nvddk_aes_intf_ap20.c
@@ -0,0 +1,701 @@
+/*
+ * Copyright (c) 2007-2009 NVIDIA Corporation.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of the NVIDIA Corporation nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "nvos.h"
+#include "nvassert.h"
+#include "nvrm_drf.h"
+#include "nvrm_hardware_access.h"
+#include "nvrm_init.h"
+#include "ap20/arvde_bsev_aes.h"
+#include "ap20/aravp_bsea_aes.h"
+#include "nvddk_aes_common.h"
+#include "nvddk_aes_priv.h"
+#include "nvddk_aes_core_ap20.h"
+
+/**
+ * SBK and SSK settings.
+ */
+enum {AES_SBK_ENGINE_A = AesHwEngine_A};
+enum {AES_SBK_ENGINE_B = AesHwEngine_B};
+enum {AES_SBK_ENCRYPT_SLOT = AesHwKeySlot_0};
+enum {AES_SBK_DECRYPT_SLOT = AES_SBK_ENCRYPT_SLOT};
+
+enum {AES_SSK_ENGINE_A = AesHwEngine_A};
+enum {AES_SSK_ENGINE_B = AesHwEngine_B};
+enum {AES_SSK_ENCRYPT_SLOT = AesHwKeySlot_4};
+enum {AES_SSK_DECRYPT_SLOT = AES_SSK_ENCRYPT_SLOT};
+
+static void
+Ap20AesSetupTable(
+ const AesHwEngine Engine,
+ const AesHwKeySlot Slot,
+ AesHwContext *const pAesHwCtxt);
+static void
+Ap20AesHwSelectKeyIvSlot(
+ const AesHwEngine Engine,
+ const AesHwKeySlot Slot,
+ AesHwContext *const pAesHwCtxt);
+static void
+Ap20AesHwClearKeyAndIv(
+ const AesHwEngine Engine,
+ const AesHwKeySlot Slot,
+ AesHwContext *const pAesHwCtxt);
+static void
+Ap20AesHwClearIv(
+ const AesHwEngine Engine,
+ const AesHwKeySlot Slot,
+ AesHwContext *const pAesHwCtxt);
+static void
+Ap20AesHwGetIv(
+ const AesHwContext *const pAesHwCtxt,
+ const AesHwEngine Engine,
+ const AesHwKeySlot Slot,
+ AesHwIv *const pIv);
+static void
+Ap20AesHwLockSskReadWrites(
+ const AesHwContext *const pAesHwCtxt,
+ const AesHwEngine SskEngine);
+static void
+Ap20AesHwLoadSskToSecureScratchAndLock(
+ const NvRmPhysAddr PmicBaseAddr,
+ const AesHwKey *const pKey,
+ const size_t Size);
+static void Ap20AesHwGetUsedSlots(AesCoreEngine *const pAesCoreEngine);
+static void Ap20AesHwGetIvReadPermissions(const AesHwEngine Engine, AesHwContext *const pAesHwCtxt);
+static void
+Ap20AesHwSetKeyAndIv(
+ const AesHwEngine Engine,
+ const AesHwKeySlot Slot,
+ const AesHwKey *const pKey,
+ const AesHwIv *const pIv,
+ const NvBool IsEncryption,
+ AesHwContext *const pAesHwCtxt);
+
+static NvBool Ap20AesHwIsEngineDisabled(const AesHwContext *const pAesHwCtxt, const AesHwEngine Engine);
+
+static NvError Ap20AesHwDisableEngine(const AesHwContext *const pAesHwCtxt, const AesHwEngine Engine);
+static NvError
+Ap20AesHwStartEngine(
+ const AesHwEngine Engine,
+ const NvU32 DataSize,
+ const NvU8 *const pSrc,
+ const NvBool IsEncryption,
+ const NvDdkAesOperationalMode OpMode,
+ NvU8 *const pDest,
+ AesHwContext *const pAesHwCtxt);
+static NvError
+Ap20AesHwSetIv(
+ const AesHwEngine Engine,
+ const AesHwKeySlot Slot,
+ const AesHwIv *const pIv,
+ AesHwContext *const pAesHwCtxt);
+
+/**
+ * Set the Setup Table command required for the AES engine.
+ *
+ * @param Engine AES engine to setup the Key table.
+ * @param Slot AES Key slot to use for setting up the key table.
+ * @param pAesHwCtxt Pointer to the AES H/W context.
+ *
+ * @retval None.
+ */
+void
+Ap20AesSetupTable(
+ const AesHwEngine Engine,
+ const AesHwKeySlot Slot,
+ AesHwContext *const pAesHwCtxt)
+{
+ NV_ASSERT(pAesHwCtxt);
+
+ NvAesCoreAp20SetupTable(Engine, pAesHwCtxt->pVirAdr[Engine], pAesHwCtxt->KeyTablePhyAddr[Engine], Slot);
+
+ NvOsMemcpy(&pAesHwCtxt->IvContext[Engine].CurIv[Slot],
+ (void *)(&pAesHwCtxt->pKeyTableVirAddr[Engine][AES_HW_KEY_TABLE_LENGTH - AES_HW_IV_LENGTH]),
+ NvDdkAesConst_BlockLengthBytes);
+
+ // Clear key table in the memory after updating the H/W
+ NvOsMemset(pAesHwCtxt->pKeyTableVirAddr[Engine], 0, pAesHwCtxt->KeyTableSize[Engine]);
+}
+
+/**
+ * Select the key and iv from the internal key table for a specified key slot.
+ *
+ * @param Engine AES engine.
+ * @param Slot Key slot for which key and IV needs to be selected.
+ * @param pAesHwCtxt Pointer to the AES H/W context.
+ *
+ * @retval None.
+ */
+void
+Ap20AesHwSelectKeyIvSlot(
+ const AesHwEngine Engine,
+ const AesHwKeySlot Slot,
+ AesHwContext *const pAesHwCtxt)
+{
+ NV_ASSERT(pAesHwCtxt);
+
+ NvOsMutexLock(pAesHwCtxt->Mutex[Engine]);
+
+ // Wait till engine becomes IDLE
+ NvAesCoreAp20WaitTillEngineIdle(Engine, pAesHwCtxt->pVirAdr[Engine]);
+
+ // Allow or disallow X9.31 operations
+ pAesHwCtxt->IsX931OpsDisallowed = !pAesHwCtxt->IvContext[Engine].IsIvReadable[Slot];
+
+ // Select the KEY slot for updating the IV vectors
+ NvAesCoreAp20SelectKeyIvSlot(Engine, pAesHwCtxt->pVirAdr[Engine], Slot);
+
+ pAesHwCtxt->IvContext[Engine].CurKeySlot = Slot;
+
+ NvOsMutexUnlock(pAesHwCtxt->Mutex[Engine]);
+}
+
+/**
+ * Disable the selected AES engine. No further operations can be
+ * performed using the AES engine until the entire chip is reset.
+ *
+ * @param pAesHwCtxt Pointer to the AES H/W context.
+ * @param Engine AES engine to disable.
+ *
+ * @retval NvSuccess if engine successfully disabled else NvError_AesDisableCryptoFailed.
+ */
+NvError Ap20AesHwDisableEngine(const AesHwContext *const pAesHwCtxt, const AesHwEngine Engine)
+{
+ NvError e;
+
+ NV_ASSERT(pAesHwCtxt);
+
+ NvOsMutexLock(pAesHwCtxt->Mutex[Engine]);
+
+ // Wait till engine becomes IDLE
+ NvAesCoreAp20WaitTillEngineIdle(Engine, pAesHwCtxt->pVirAdr[Engine]);
+
+ e = NvAesCoreAp20DisableEngine(Engine, pAesHwCtxt->pVirAdr[Engine]);
+
+ NvOsMutexUnlock(pAesHwCtxt->Mutex[Engine]);
+
+ return e;
+}
+
+/**
+ * Over-write the key schedule and Initial Vector in the in the specified
+ * key slot with zeroes. Convenient for preventing subsequent callers from
+ * gaining access to a previously-used key.
+ *
+ * @param Engine AES engine.
+ * @param Slot key slot to clear.
+ * @param pAesHwCtxt Pointer to the AES H/W context.
+ *
+ * @retval None.
+ */
+void
+Ap20AesHwClearKeyAndIv(
+ const AesHwEngine Engine,
+ const AesHwKeySlot Slot,
+ AesHwContext *const pAesHwCtxt)
+{
+ NV_ASSERT(pAesHwCtxt);
+
+ NvOsMutexLock(pAesHwCtxt->Mutex[Engine]);
+
+ // Wait till engine becomes IDLE
+ NvAesCoreAp20WaitTillEngineIdle(Engine, pAesHwCtxt->pVirAdr[Engine]);
+
+ // Clear Key table this clears both Key Schedule and IV in key table
+ NvOsMemset(pAesHwCtxt->pKeyTableVirAddr[Engine], 0, pAesHwCtxt->KeyTableSize[Engine]);
+
+ // Setup the key table with Zero key and Zero Iv
+ Ap20AesHwSelectKeyIvSlot(Engine, Slot, pAesHwCtxt);
+ Ap20AesSetupTable(Engine, Slot, pAesHwCtxt);
+
+ NvOsMutexUnlock(pAesHwCtxt->Mutex[Engine]);
+}
+
+/**
+ * Over-write the initial vector in the specified AES engine with zeroes.
+ * Convenient to prevent subsequent callers from gaining access to a
+ * previously-used initial vector.
+ *
+ * @param Engine AES engine.
+ * @param Slot Key slot for which Iv needs to be cleared.
+ * @param pAesHwCtxt Pointer to the AES H/W context.
+ *
+ * @retval None.
+ */
+void
+Ap20AesHwClearIv(
+ const AesHwEngine Engine,
+ const AesHwKeySlot Slot,
+ AesHwContext *const pAesHwCtxt)
+{
+ NV_ASSERT(pAesHwCtxt);
+ NV_ASSERT(pAesHwCtxt->pKeyTableVirAddr[Engine]);
+
+ NvOsMemset((void *)pAesHwCtxt->pKeyTableVirAddr[Engine], 0, NvDdkAesConst_IVLengthBytes);
+
+ Ap20AesHwStartEngine(
+ Engine,
+ NvDdkAesConst_IVLengthBytes,
+ pAesHwCtxt->pKeyTableVirAddr[Engine],
+ NV_FALSE,
+ NvDdkAesOperationalMode_Cbc,
+ pAesHwCtxt->pKeyTableVirAddr[Engine],
+ pAesHwCtxt);
+}
+
+/**
+ * Compute key schedule for the given key, then load key schedule and
+ * initial vector into the specified key slot.
+ *
+ * @param Engine AES engine.
+ * @param Slot Key slot to load.
+ * @param pKey Pointer to the key.
+ * @param pIv Pointer to the iv.
+ * @param IsEncryption If set to NV_TRUE indicates key schedule computation
+ * is for encryption else for decryption.
+ * @param pAesHwCtxt Pointer to the AES H/W context.
+ *
+ * @retval None.
+ */
+void
+Ap20AesHwSetKeyAndIv(
+ const AesHwEngine Engine,
+ const AesHwKeySlot Slot,
+ const AesHwKey *const pKey,
+ const AesHwIv *const pIv,
+ const NvBool IsEncryption,
+ AesHwContext *const pAesHwCtxt)
+{
+ NV_ASSERT(pAesHwCtxt);
+ NV_ASSERT(pKey);
+ NV_ASSERT(pIv);
+
+ NvOsMutexLock(pAesHwCtxt->Mutex[Engine]);
+
+ // Wait till engine becomes IDLE
+ NvAesCoreAp20WaitTillEngineIdle(Engine, pAesHwCtxt->pVirAdr[Engine]);
+
+ NvAesCoreAp20ControlKeyScheduleGeneration(Engine, pAesHwCtxt->pVirAdr[Engine], NV_TRUE);
+
+ Ap20AesHwSelectKeyIvSlot(Engine, Slot, pAesHwCtxt);
+ // Clear key table first before expanding the Key
+ NvOsMemset(pAesHwCtxt->pKeyTableVirAddr[Engine], 0, AES_HW_KEY_TABLE_LENGTH_BYTES);
+ NvOsMemcpy(&pAesHwCtxt->pKeyTableVirAddr[Engine][0], &pKey->key[0], sizeof(AesHwKey));
+
+ NvOsMemcpy(
+ &pAesHwCtxt->pKeyTableVirAddr[Engine][NvDdkAesConst_MaxKeyLengthBytes + NvDdkAesConst_IVLengthBytes],
+ &pIv->iv[0],
+ sizeof(AesHwIv));
+
+ Ap20AesSetupTable(Engine, Slot, pAesHwCtxt);
+
+ NvOsMutexUnlock(pAesHwCtxt->Mutex[Engine]);
+}
+
+/**
+ * Load an initial vector into the specified AES engine for using it
+ * during encryption or decryption.
+ *
+ * @param Engine AES engine.
+ * @param Slot Key slot for which Iv needs to be set.
+ * @param pIv Pointer to the initial vector.
+ * @param pAesHwCtxt Pointer to the AES H/W context.
+ *
+ * @retval NvSuccess if Iv was set correctly.
+ * NvError_InvalidState if operation is not allowed.
+ */
+NvError
+Ap20AesHwSetIv(
+ const AesHwEngine Engine,
+ const AesHwKeySlot Slot,
+ const AesHwIv *const pIv,
+ AesHwContext *const pAesHwCtxt)
+{
+ NvError e;
+
+ NV_ASSERT(pAesHwCtxt);
+ NV_ASSERT(pIv);
+
+ e = Ap20AesHwStartEngine(
+ Engine,
+ NvDdkAesConst_IVLengthBytes,
+ (NvU8 *)(&pIv->iv[0]),
+ NV_FALSE,
+ NvDdkAesOperationalMode_Cbc,
+ pAesHwCtxt->pKeyTableVirAddr[Engine],
+ pAesHwCtxt);
+
+ NV_ASSERT(pAesHwCtxt->pKeyTableVirAddr[Engine]);
+
+ NvOsMemset((void *)pAesHwCtxt->pKeyTableVirAddr[Engine], 0, AES_HW_KEY_TABLE_LENGTH);
+
+ return e;
+}
+
+/**
+ * Retrieve the initial vector for the specified AES engine.
+ *
+ * @param pAesHwCtxt Pointer to the AES H/W context.
+ * @param Engine AES engine.
+ * @param Slot Key slot for which Iv is to be retrieved.
+ * @param pIv Pointer to the initial vector.
+ *
+ * @retval None.
+ */
+void
+Ap20AesHwGetIv(
+ const AesHwContext *const pAesHwCtxt,
+ const AesHwEngine Engine,
+ const AesHwKeySlot Slot,
+ AesHwIv *const pIv)
+{
+ NV_ASSERT(pAesHwCtxt);
+ NV_ASSERT(pIv);
+
+ NvOsMutexLock(pAesHwCtxt->Mutex[Engine]);
+
+ NvOsMemcpy(&pIv->iv[0], &pAesHwCtxt->IvContext[Engine].CurIv[Slot], NvDdkAesConst_BlockLengthBytes);
+
+ NvOsMutexUnlock(pAesHwCtxt->Mutex[Engine]);
+}
+
+/**
+ * Lock the Secure Session Key (SSK) slots.
+ * This API disables the read/write permissions to the secure key slots.
+ *
+ * @param pAesHwCtxt Pointer to the AES H/W context.
+ * @param SskEngine SSK engine number.
+ *
+ * @retval None.
+ */
+void
+Ap20AesHwLockSskReadWrites(
+ const AesHwContext *const pAesHwCtxt,
+ const AesHwEngine SskEngine)
+{
+ NV_ASSERT(pAesHwCtxt);
+
+ NvOsMutexLock(pAesHwCtxt->Mutex[SskEngine]);
+
+ NvAesCoreAp20LockSskReadWrites(SskEngine, pAesHwCtxt->pVirAdr[SskEngine]);
+
+ NvOsMutexUnlock(pAesHwCtxt->Mutex[SskEngine]);
+}
+
+/**
+ * Encrypt/Decrypt a specified number of blocks of cyphertext using
+ * Cipher Block Chaining (CBC) mode. A block is 16 bytes.
+ * This is non-blocking API and need to call AesHwEngineIdle()
+ * to check the engine status to confirm the AES engine operation is
+ * done and comes out of the BUSY state.
+ * Also make sure before calling this API engine must be IDLE.
+ *
+ * @param Engine AES engine.
+ * @param DataSize Number of blocks of ciphertext to process.
+ * One block is 16 bytes. Max number of blocks possible = 0xFFFFF.
+ * @param pSrc Pointer to nblock blocks of ciphertext/plaintext depending on the
+ * IsEncryption status; ciphertext/plaintext is not modified (input).
+ * @param IsEncryption If set to NV_TRUE indicates AES engine to start
+ * encryption on the source data to give cipher text else starts
+ * decryption on the source cipher data to give plain text.
+ * @param OpMode Specifies the AES operational mode.
+ * @param pDest Pointer to nblock blocks of cleartext/ciphertext (output)
+ * depending on the IsEncryption.
+ * @param pAesHwCtxt Pointer to the AES H/W context.
+ *
+ * @retval NvSuccess if AES operation is successful.
+ * @retval NvError_InvalidState if operation mode is not supported.
+ */
+NvError
+Ap20AesHwStartEngine(
+ const AesHwEngine Engine,
+ const NvU32 DataSize,
+ const NvU8 *const pSrc,
+ const NvBool IsEncryption,
+ const NvDdkAesOperationalMode OpMode,
+ NvU8 *const pDest,
+ AesHwContext *const pAesHwCtxt)
+{
+ NvRmMemHandle hSrcMemBuf = NULL;
+ NvRmMemHandle hDestMemBuf = NULL;
+ NvRmPhysAddr SrcBufferPhyAddr = 0;
+ NvRmPhysAddr DestBufferPhyAddr = 0;
+ NvU32 *pSrcBufferVirtAddr = NULL;
+ NvU32 *pDestBufferVirtAddr = NULL;
+ NvError e;
+
+ NV_ASSERT(pAesHwCtxt);
+ NV_ASSERT(pSrc);
+ NV_ASSERT(pDest);
+
+ switch (OpMode)
+ {
+ case NvDdkAesOperationalMode_AnsiX931:
+ {
+ // If Iv is not readable, don't allow operations to be performed.
+ // Since setting the Iv also uses this API, it should be enough to
+ // disallow operations here.
+ if (pAesHwCtxt->IsX931OpsDisallowed)
+ return NvError_InvalidState;
+ }
+ case NvDdkAesOperationalMode_Cbc:
+ case NvDdkAesOperationalMode_Ecb:
+ break;
+ default:
+ return NvError_InvalidState;
+ }
+
+ NV_CHECK_ERROR_CLEANUP(NvRmMemHandleCreate(pAesHwCtxt->hRmDevice, &hSrcMemBuf, DataSize));
+ if (!hSrcMemBuf)
+ {
+ goto fail;
+ }
+
+ e = NvRmMemHandleCreate(pAesHwCtxt->hRmDevice, &hDestMemBuf, DataSize);
+ if (!hDestMemBuf || (e != NvSuccess))
+ {
+ goto fail1;
+ }
+
+ e = NvRmMemAlloc(hSrcMemBuf,0, 0, 4, NvOsMemAttribute_Uncached);
+ if (e != NvSuccess)
+ {
+ goto fail2;
+ }
+
+ e = NvRmMemAlloc(hDestMemBuf,0, 0, 4, NvOsMemAttribute_Uncached);
+ if (e != NvSuccess)
+ {
+ goto fail2;
+ }
+
+ SrcBufferPhyAddr = NvRmMemPin(hSrcMemBuf);
+ DestBufferPhyAddr = NvRmMemPin(hDestMemBuf);
+
+ e = NvRmPhysicalMemMap(
+ SrcBufferPhyAddr,
+ DataSize,
+ NVOS_MEM_READ_WRITE,
+ NvOsMemAttribute_Uncached,
+ (void **)&pSrcBufferVirtAddr);
+ if (e != NvSuccess)
+ {
+ goto fail3;
+ }
+
+ e = NvRmPhysicalMemMap(
+ DestBufferPhyAddr,
+ DataSize,
+ NVOS_MEM_READ_WRITE,
+ NvOsMemAttribute_Uncached,
+ (void **)&pDestBufferVirtAddr);
+ if (e != NvSuccess)
+ {
+ goto fail4;
+ }
+
+ NvOsMutexLock(pAesHwCtxt->Mutex[Engine]);
+
+ NvOsMemcpy((NvU8 *)pSrcBufferVirtAddr, pSrc, DataSize);
+
+ if (DataSize && (!IsEncryption))
+ {
+ NvOsMemcpy(&pAesHwCtxt->IvContext[Engine].CurIv[pAesHwCtxt->IvContext[Engine].CurKeySlot],
+ (pSrc + DataSize - NvDdkAesConst_BlockLengthBytes),
+ NvDdkAesConst_BlockLengthBytes);
+ }
+
+ NvAesCoreAp20ProcessBuffer(
+ Engine,
+ pAesHwCtxt->pVirAdr[Engine],
+ SrcBufferPhyAddr,
+ DestBufferPhyAddr,
+ DataSize,
+ pAesHwCtxt->DmaPhyAddr[Engine],
+ IsEncryption,
+ OpMode);
+
+ NvOsMemcpy(pDest, (NvU8 *)pDestBufferVirtAddr, DataSize);
+
+ /**
+ * If DataSize is zero, Iv would remain unchanged.
+ * For an encryption operation, the current Iv will be the last block of
+ * ciphertext.
+ */
+ if (DataSize && IsEncryption)
+ {
+ NvOsMemcpy(&pAesHwCtxt->IvContext[Engine].CurIv[pAesHwCtxt->IvContext[Engine].CurKeySlot],
+ (pDest + DataSize - NvDdkAesConst_BlockLengthBytes),
+ NvDdkAesConst_BlockLengthBytes);
+ }
+
+ NvOsMutexUnlock(pAesHwCtxt->Mutex[Engine]);
+
+ NvOsMemset(pSrcBufferVirtAddr, 0, DataSize);
+ NvOsMemset(pDestBufferVirtAddr, 0, DataSize);
+
+ // Unpinning the Memory
+ NvRmPhysicalMemUnmap(pDestBufferVirtAddr, DataSize);
+
+fail4:
+ NvRmPhysicalMemUnmap(pSrcBufferVirtAddr, DataSize);
+
+fail3:
+ // Unpinning the Memory
+ NvRmMemUnpin(hSrcMemBuf);
+
+ // Unpinning the Memory
+ NvRmMemUnpin(hDestMemBuf);
+
+fail2:
+ NvRmMemHandleFree(hDestMemBuf);
+fail1:
+ NvRmMemHandleFree(hSrcMemBuf);
+fail:
+ return e;
+}
+
+/**
+ * Load the SSK key into secure scratch resgister and disables the write permissions.
+ * Note: If Key is not specified then this API locks the Secure Scratch registers.
+ *
+ * @param PmicBaseAddr PMIC base address.
+ * @param pKey Pointer to the key. If pKey=NULL then key will not be set to the
+ * secure scratch registers, but locks the Secure scratch register.
+ * @param Size Length of the aperture in bytes.
+ *
+ * @retval None.
+ */
+void
+Ap20AesHwLoadSskToSecureScratchAndLock(
+ const NvRmPhysAddr PmicBaseAddr,
+ const AesHwKey *const pKey,
+ const size_t Size)
+{
+ NV_ASSERT(pKey);
+ NvAesCoreAp20LoadSskToSecureScratchAndLock(PmicBaseAddr, (pKey ? pKey->key : 0), Size);
+}
+
+/**
+ * Mark all dedicated slots as used.
+ *
+ * @param pAesCoreEngine Pointer to AES Core Engine.
+ *
+ * @retval None.
+ */
+void Ap20AesHwGetUsedSlots(AesCoreEngine *const pAesCoreEngine)
+{
+ NV_ASSERT(pAesCoreEngine);
+
+ // For ap20, SBK and SSK reside on both engines
+ pAesCoreEngine->SbkEngine[0] = AES_SBK_ENGINE_A;
+ pAesCoreEngine->SbkEncryptSlot = AES_SBK_ENCRYPT_SLOT;
+ pAesCoreEngine->SbkDecryptSlot = AES_SBK_DECRYPT_SLOT;
+ pAesCoreEngine->IsKeySlotUsed[AES_SBK_ENGINE_A][AES_SBK_ENCRYPT_SLOT] = NV_TRUE;
+
+ pAesCoreEngine->SbkEngine[1] = AES_SBK_ENGINE_B;
+ pAesCoreEngine->IsKeySlotUsed[AES_SBK_ENGINE_B][AES_SBK_DECRYPT_SLOT] = NV_TRUE;
+
+ pAesCoreEngine->SskEngine[0] = AES_SSK_ENGINE_A;
+ pAesCoreEngine->SskEncryptSlot = AES_SSK_ENCRYPT_SLOT;
+ pAesCoreEngine->SskDecryptSlot = AES_SSK_DECRYPT_SLOT;
+ pAesCoreEngine->IsKeySlotUsed[AES_SSK_ENGINE_A][AES_SSK_ENCRYPT_SLOT] = NV_TRUE;
+
+ pAesCoreEngine->SskEngine[1] = AES_SSK_ENGINE_B;
+ pAesCoreEngine->IsKeySlotUsed[AES_SSK_ENGINE_B][AES_SSK_DECRYPT_SLOT] = NV_TRUE;
+}
+
+/**
+ * Read the AES engine disable status.
+ *
+ * @param pAesHwCtxt Pointer to the AES H/W context.
+ * @param Engine AES engine to disable.
+ *
+ * @return NV_TRUE if engine is disabled else NV_FALSE.
+ *
+ */
+NvBool Ap20AesHwIsEngineDisabled(const AesHwContext *const pAesHwCtxt, const AesHwEngine Engine)
+{
+ NvBool IsEngineDisabled = NV_FALSE;
+
+ NV_ASSERT(pAesHwCtxt);
+
+ NvOsMutexLock(pAesHwCtxt->Mutex[Engine]);
+
+ IsEngineDisabled = NvAesCoreAp20IsEngineDisabled(Engine, pAesHwCtxt->pVirAdr[Engine]);
+
+ NvOsMutexUnlock(pAesHwCtxt->Mutex[Engine]);
+
+ return IsEngineDisabled;
+}
+
+/**
+ * Get the read permissions for IV for each key slot of an engine.
+ *
+ * @param Engine AES Engine for which Iv permissions for an engine are sought.
+ * @param pAesHwCtxt Pointer to the AES H/W context.
+ *
+ * @retval None.
+ *
+ */
+void Ap20AesHwGetIvReadPermissions(const AesHwEngine Engine, AesHwContext *const pAesHwCtxt)
+{
+ NV_ASSERT(pAesHwCtxt);
+
+ NvOsMutexLock(pAesHwCtxt->Mutex[Engine]);
+
+ NvAesCoreAp20GetIvReadPermissions(
+ Engine,
+ pAesHwCtxt->pVirAdr[Engine],
+ &pAesHwCtxt->IvContext[Engine].IsIvReadable[0]);
+
+ NvOsMutexUnlock(pAesHwCtxt->Mutex[Engine]);
+}
+
+void NvAesIntfAp20GetHwInterface(AesHwInterface *const pAp20AesHw)
+{
+ NV_ASSERT(pAp20AesHw);
+
+ pAp20AesHw->AesHwDisableEngine = Ap20AesHwDisableEngine;
+ pAp20AesHw->AesHwClearKeyAndIv = Ap20AesHwClearKeyAndIv;
+ pAp20AesHw->AesHwClearIv = Ap20AesHwClearIv;
+ pAp20AesHw->AesHwSetKeyAndIv = Ap20AesHwSetKeyAndIv;
+ pAp20AesHw->AesHwSetIv = Ap20AesHwSetIv;
+ pAp20AesHw->AesHwGetIv = Ap20AesHwGetIv;
+ pAp20AesHw->AesHwLockSskReadWrites = Ap20AesHwLockSskReadWrites;
+ pAp20AesHw->AesHwSelectKeyIvSlot = Ap20AesHwSelectKeyIvSlot;
+ pAp20AesHw->AesHwStartEngine = Ap20AesHwStartEngine;
+ pAp20AesHw->AesHwLoadSskToSecureScratchAndLock = Ap20AesHwLoadSskToSecureScratchAndLock;
+ pAp20AesHw->AesHwGetUsedSlots = Ap20AesHwGetUsedSlots;
+ pAp20AesHw->AesHwIsEngineDisabled = Ap20AesHwIsEngineDisabled;
+ pAp20AesHw->AesHwGetIvReadPermissions = Ap20AesHwGetIvReadPermissions;
+}
diff --git a/arch/arm/mach-tegra/nvddk/nvddk_aes_priv.h b/arch/arm/mach-tegra/nvddk/nvddk_aes_priv.h
new file mode 100644
index 000000000000..bebbebe1900d
--- /dev/null
+++ b/arch/arm/mach-tegra/nvddk/nvddk_aes_priv.h
@@ -0,0 +1,436 @@
+/*
+ * Copyright (c) 2007-2009 NVIDIA Corporation.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of the NVIDIA Corporation nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef INCLUDED_NVDDK_AES_PRIV_H
+#define INCLUDED_NVDDK_AES_PRIV_H
+
+#include "nverror.h"
+#include "nvcommon.h"
+#include "nvrm_memmgr.h"
+#include "nvddk_aes_hw.h"
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+// As of now only 5 commands are used for AES encryption/decryption
+#define AES_HW_MAX_ICQ_LENGTH 5
+
+// AES RFC 3394 initial vector length, in bytes
+#define AES_RFC_IV_LENGTH_BYTES 8
+
+/**
+ * AES Engine instances.
+ */
+typedef enum
+{
+ // AES Engine "A" BSEV
+ AesHwEngine_A,
+ // AES Engine "B" BSEA
+ AesHwEngine_B,
+ AesHwEngine_Num,
+ AesHwEngine_Force32 = 0x7FFFFFFF
+} AesHwEngine;
+
+/**
+ * AES Key Slot instances (per AES engine).
+ */
+typedef enum
+{
+ AesHwKeySlot_0,
+ AesHwKeySlot_1,
+ AesHwKeySlot_2,
+ AesHwKeySlot_3,
+ AesHwKeySlot_Num,
+ AesHwKeySlot_4 = AesHwKeySlot_Num,
+ AesHwKeySlot_5,
+ AesHwKeySlot_6,
+ AesHwKeySlot_7,
+ AesHwKeySlot_NumExt,
+ AesHwKeySlot_Force32 = 0x7FFFFFFF
+} AesHwKeySlot;
+
+// Iv Context
+typedef struct AesIvContextRec
+{
+ // Updated/current Iv for each key slot
+ NvU32 CurIv[AesHwKeySlot_NumExt][AES_HW_IV_LENGTH];
+ // Iv read permissions for each key slot
+ NvBool IsIvReadable[AesHwKeySlot_NumExt];
+ // The current key slot in use
+ AesHwKeySlot CurKeySlot;
+} AesIvContext;
+
+typedef struct AesHwInterfaceRec AesHwInterface;
+
+// AES engine capabilities
+typedef struct AesHwCapabilitiesRec
+{
+ // Number of slots supported in each AES instance
+ AesHwKeySlot NumSlotsSupported;
+ // Key schedule generation in hardware to be supported
+ NvBool IsHwKeySchedGenSupported;
+ // Size needed for key scheduling
+ NvU32 HwKeySchedLengthBytes;
+ // Hashing to be supported within the engine
+ NvBool IsHashSupported;
+ // Minimum Alignment for the key table/schedule buffer in IRAM or VRAM
+ NvU32 MinKeyTableAlignment;
+ // Min Input/Output buffer alignment for AES
+ NvU32 MinBufferAlignment;
+ // Pointer to the AES engine low level interface
+ AesHwInterface *pAesInterf;
+} AesHwCapabilities;
+
+// H/W Context
+typedef struct AesHwContextRec
+{
+ // Capabilities
+ AesHwCapabilities **ppEngineCaps;
+ // Mutex to support concurrent operation on the AES engine
+ NvOsMutexHandle Mutex[AesHwEngine_Num];
+ // RM device handle
+ NvRmDeviceHandle hRmDevice;
+ // Controller registers physical base address
+ NvRmPhysAddr PhysAdr[AesHwEngine_Num];
+ // Holds the virtual address for accessing registers
+ NvU32 *pVirAdr[AesHwEngine_Num];
+ // Holds the register map size
+ NvU32 BankSize[AesHwEngine_Num];
+ // Memory handle to the key table
+ NvRmMemHandle hKeyTableMemBuf;
+ // Pointer to the key table virtual buffer
+ NvU8 *pKeyTableVirAddr[AesHwEngine_Num];
+ // Key table physical addr
+ NvRmPhysAddr KeyTablePhyAddr[AesHwEngine_Num];
+ // Key table size in bytes
+ NvU32 KeyTableSize[AesHwEngine_Num];
+ // Memory handle to the AES H/W Buffer
+ NvRmMemHandle hDmaMemBuf;
+ // Contains the physical Address of the H/W buffer
+ NvRmPhysAddr DmaPhyAddr[AesHwEngine_Num];
+ // Virtual pointer to the AES buffer
+ NvU8 *pDmaVirAddr[AesHwEngine_Num];
+ // Icq commands length
+ NvU32 CommandQueueLength[AesHwEngine_Num];
+ // Holds the Icq commands for the AES operation
+ NvU32 CommandQueueData[AesHwEngine_Num][AES_HW_MAX_ICQ_LENGTH];
+ // Iv Context for each AES engine
+ AesIvContext IvContext[AesHwEngine_Num];
+ // Indicates whether X9.31 operations are allowed or not
+ NvBool IsX931OpsDisallowed;
+} AesHwContext;
+
+// AES Core Engine record
+typedef struct AesCoreEngineRec
+{
+ // Keeps the count of open handles
+ NvU32 OpenCount;
+ // Id returned from driver's registration with Power Manager
+ NvU32 RmPwrClientId[AesHwEngine_Num];
+ // Indicates whether key slot is used or not
+ NvBool IsKeySlotUsed[AesHwEngine_Num][AesHwKeySlot_NumExt];
+ // SSK engine where SSK is stored
+ AesHwEngine SskEngine[AesHwEngine_Num];
+ // SSK encrypt key slot
+ AesHwKeySlot SskEncryptSlot;
+ // SSK Decrypt key slot
+ AesHwKeySlot SskDecryptSlot;
+ // SBK engine where SBK is stored
+ AesHwEngine SbkEngine[AesHwEngine_Num];
+ // SBK encrypt key slot
+ AesHwKeySlot SbkEncryptSlot;
+ // SSK Decrypt key slot
+ AesHwKeySlot SbkDecryptSlot;
+ // Aes H/W Engine context
+ AesHwContext AesHwCtxt;
+ // Indicates whether engine is disabled or not
+ NvBool IsEngineDisabled;
+} AesCoreEngine;
+
+// Set of function pointers to be used to access the hardware interface for
+// the AES engines.
+struct AesHwInterfaceRec
+{
+ /**
+ * Disable the selected AES engine. No further operations can be
+ * performed using the AES engine until the entire chip is reset.
+ *
+ * @param pAesHwCtxt Pointer to the AES H/W context.
+ * @param Engine AES engine to disable.
+ *
+ * @retval NvSuccess if engine successfully disabled else NvError_AesDisableCryptoFailed.
+ */
+ NvError (*AesHwDisableEngine)(
+ const AesHwContext *const pAesHwCtxt,
+ const AesHwEngine Engine);
+
+ /**
+ * Over-write the key schedule and Initial Vector in the in the specified
+ * key slot with zeroes.Convenient for preventing subsequent callers from
+ * gaining access to a previously-used key.
+ *
+ * @param Engine AES engine.
+ * @param Slot key slot to clear.
+ * @param pAesHwCtxt Pointer to the AES H/W context.
+ *
+ * @retval None.
+ */
+ void (*AesHwClearKeyAndIv)(
+ const AesHwEngine Engine,
+ const AesHwKeySlot Slot,
+ AesHwContext *const pAesHwCtxt);
+
+ /**
+ * Over-write the initial vector in the specified AES engine with zeroes.
+ * Convenient to prevent subsequent callers from gaining access to a
+ * previously-used initial vector.
+ *
+ * @param Engine AES engine.
+ * @param Slot Key slot for which Iv needs to be cleared.
+ * @param pAesHwCtxt Pointer to the AES H/W context.
+ *
+ * @retval None.
+ */
+ void (*AesHwClearIv)(
+ const AesHwEngine Engine,
+ const AesHwKeySlot Slot,
+ AesHwContext *const pAesHwCtxt);
+
+ /**
+ * Compute key schedule for the given key, then load key schedule and
+ * initial vector into the specified key slot.
+ *
+ * @param Engine AES engine.
+ * @param Slot Key slot to load.
+ * @param pKey Pointer to the key.
+ * @param pIv Pointer to the iv.
+ * @param IsEncryption If set to NV_TRUE indicates key schedule computation
+ * is for encryption else for decryption.
+ * @param pAesHwCtxt Pointer to the AES H/W context.
+ *
+ * @retval None.
+ */
+ void (*AesHwSetKeyAndIv)(
+ const AesHwEngine Engine,
+ const AesHwKeySlot Slot,
+ const AesHwKey *const pKey,
+ const AesHwIv *const pIv,
+ const NvBool IsEncryption,
+ AesHwContext *const pAesHwCtxt);
+
+ /**
+ * Load an initial vector into the specified AES engine for using it
+ * during encryption or decryption.
+ *
+ * @param Engine AES engine.
+ * @param Slot Key slot for which Iv needs to be set.
+ * @param pIv Pointer to the initial vector.
+ * @param pAesHwCtxt Pointer to the AES H/W context.
+ *
+ * @retval NvSuccess if Iv was set correctly.
+ * NvError_InvalidState if operation is not allowed.
+ */
+ NvError (*AesHwSetIv)(
+ const AesHwEngine Engine,
+ const AesHwKeySlot Slot,
+ const AesHwIv *const pIv,
+ AesHwContext *const pAesHwCtxt);
+
+ /**
+ * Retrieve the initial vector for the specified AES engine.
+ *
+ * @param pAesHwCtxt Pointer to the AES H/W context.
+ * @param Engine AES engine.
+ * @param Slot Key slot for which Iv is to be retrieved.
+ * @param pIv Pointer to the initial vector.
+ *
+ * @retval None.
+ */
+ void (*AesHwGetIv)(
+ const AesHwContext *const pAesHwCtxt,
+ const AesHwEngine Engine,
+ const AesHwKeySlot Slot,
+ AesHwIv *const pIv);
+
+ /**
+ * Lock the Secure Session Key (SSK) slots.
+ * This API disables the read/write permissions to the secure key slots.
+ *
+ * @param pAesHwCtxt Pointer to the AES H/W context.
+ * @param SskEngine SSK engine number.
+ *
+ * @retval None.
+ */
+ void (*AesHwLockSskReadWrites)(
+ const AesHwContext *const pAesHwCtxt,
+ const AesHwEngine SskEngine);
+
+ /**
+ * Select the key and iv from the internal key table for a specified key slot.
+ *
+ * @param Engine AES engine.
+ * @param Slot Key slot for which key and IV needs to be selected.
+ * @param pAesHwCtxt Pointer to the AES H/W context.
+ *
+ * @retval None.
+ */
+ void (*AesHwSelectKeyIvSlot)(
+ const AesHwEngine Engine,
+ const AesHwKeySlot Slot,
+ AesHwContext *const pAesHwCtxt);
+
+ /**
+ * Encrypt/Decrypt a specified number of blocks of cyphertext using
+ * Cipher Block Chaining (CBC) mode. A block is 16 bytes.
+ * This is non-blocking API and need to call AesHwEngineIdle()
+ * to check the engine status to confirm the AES engine operation is
+ * done and comes out of the BUSY state.
+ * Also make sure before calling this API engine must be IDLE.
+ *
+ * @param Engine AES engine.
+ * @param DataSize Number of blocks of ciphertext to process.
+ * One block is 16 bytes. Max number of blocks possible = 0xFFFFF.
+ * @param pSrc Pointer to nblock blocks of ciphertext/plaintext depending on the
+ * IsEncryption status; ciphertext/plaintext is not modified (input).
+ * @param IsEncryption If set to NV_TRUE indicates AES engine to start
+ * encryption on the source data to give cipher text else starts
+ * decryption on the source cipher data to give plain text.
+ * @param OpMode Specifies the AES operational mode.
+ * @param pDest Pointer to nblock blocks of cleartext/ciphertext (output)
+ * depending on the IsEncryption.
+ * @param pAesHwCtxt Pointer to the AES H/W context.
+ *
+ * @retval NvSuccess if AES operation is successful.
+ * @retval NvError_InvalidState if operation mode is not supported.
+ */
+ NvError (*AesHwStartEngine)(
+ const AesHwEngine Engine,
+ const NvU32 DataSize,
+ const NvU8 *const pSrc,
+ const NvBool IsEncryption,
+ const NvDdkAesOperationalMode OpMode,
+ NvU8 *const pDest,
+ AesHwContext *const pAesHwCtxt);
+
+ /**
+ * Load the SSK key into secure scratch resgister and disable the write permissions.
+ * Note: If Key is not specified then this API locks the Secure Scratch registers.
+ *
+ * @param PmicBaseAddr PMIC base address.
+ * @param pKey Pointer to the key. If pKey=NULL then key will not be set to the
+ * secure scratch registers, but locks the Secure scratch register.
+ * @param Size Length of the aperture in bytes.
+ *
+ * @retval None.
+ */
+ void (*AesHwLoadSskToSecureScratchAndLock)(
+ const NvRmPhysAddr PmicBaseAddr,
+ const AesHwKey *const pKey,
+ const size_t Size);
+
+ /**
+ * Mark all dedicated slots as used.
+ *
+ * @param pAesCoreEngine Pointer to AES Core Engine.
+ *
+ * @retval None.
+ */
+ void (*AesHwGetUsedSlots)(AesCoreEngine *const pAesCoreEngine);
+
+ /**
+ * Read the AES engine disable status.
+ *
+ * @param pAesHwCtxt Pointer to the AES H/W context.
+ * @param Engine AES engine to disable.
+ *
+ * @return NV_TRUE if engine is disabled else NV_FALSE.
+ */
+ NvBool (*AesHwIsEngineDisabled)(const AesHwContext *const pAesHwCtxt, const AesHwEngine Engine);
+
+ /**
+ * Get the read permissions for IV for each key slot of an engine.
+ *
+ * @param Engine AES Engine for which Iv permissions for an engine are sought.
+ * @param pAesHwCtxt Pointer to the AES H/W context.
+ *
+ * @retval None.
+ */
+ void (*AesHwGetIvReadPermissions)(const AesHwEngine Engine, AesHwContext *const pAesHwCtxt);
+};
+
+// AES client state: this structure is common to all clients
+typedef struct NvDdkAesRec
+{
+ // Algorithm type set for this client
+ NvDdkAesOperationalMode OpMode;
+ // Select key type -- SBK, SSK or user-specified
+ NvDdkAesKeyType KeyType;
+ // AES key length; must be 128Bit for SBK or SSK
+ NvDdkAesKeySize KeySize;
+ // Specified AES key value if KeyType is user-specified; else ignored
+ NvU8 Key[NvDdkAesConst_MaxKeyLengthBytes];
+ // Initial vector to use when encrypting/decrypting last IV will be stored
+ NvU8 Iv[NvDdkAesConst_IVLengthBytes];
+ // Initial vector to use in RFC3394 key unwrapping
+ NvU8 WrappedIv[AES_RFC_IV_LENGTH_BYTES];
+ // Client selected AES engine, depends on the key slot selected
+ AesHwEngine Engine;
+ // Client selected Key slot
+ AesHwKeySlot KeySlot;
+ // Operation type selected
+ NvBool IsEncryption;
+ // If user key is specified client can tell to use the dedicated slot
+ // If set to NV_TRUE then key slot is dedicated else shared with other keys
+ NvBool IsDedicatedSlot;
+ // Pointer to the AES core engine
+ AesCoreEngine *pAesCoreEngine;
+ // Client's user id
+ uid_t uid;
+ // Client's group id
+ gid_t gid;
+} NvDdkAes;
+
+/**
+ * Return the interface to be used for AP20 AES engine.
+ *
+ * @param pAp20AesHw Pointer to the interface.
+ *
+ * @retval None.
+ */
+void NvAesIntfAp20GetHwInterface(AesHwInterface *const pAp20AesHw);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif // INCLUDED_NVDDK_AES_PRIV_H