Add support for encryption, decryption and signinig with
non-zero key saving backward compatibility.

Signed-off-by: Svyatoslav Ryhel <clamo...@gmail.com>
---
 arch/arm/include/asm/arch-tegra/crypto.h | 47 ++++++++++++++++++
 arch/arm/mach-tegra/crypto.c             | 63 +++++++++++++++++-------
 arch/arm/mach-tegra/crypto.h             | 19 -------
 3 files changed, 91 insertions(+), 38 deletions(-)
 create mode 100644 arch/arm/include/asm/arch-tegra/crypto.h
 delete mode 100644 arch/arm/mach-tegra/crypto.h

diff --git a/arch/arm/include/asm/arch-tegra/crypto.h 
b/arch/arm/include/asm/arch-tegra/crypto.h
new file mode 100644
index 0000000000..7646163b97
--- /dev/null
+++ b/arch/arm/include/asm/arch-tegra/crypto.h
@@ -0,0 +1,47 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (c) 2011 The Chromium OS Authors.
+ * (C) Copyright 2010 - 2011 NVIDIA Corporation <www.nvidia.com>
+ */
+
+#ifndef _CRYPTO_H_
+#define _CRYPTO_H_
+
+/**
+ * Sign a block of data
+ *
+ * \param source       Source data
+ * \param length       Size of source data
+ * \param signature    Destination address for signature, AES_KEY_LENGTH bytes
+ */
+int sign_data_block(u8 *source, unsigned int length, u8 *signature);
+
+/**
+ * Sign an encrypted block of data
+ *
+ * \param source       Source data
+ * \param length       Size of source data
+ * \param signature    Destination address for signature, AES_KEY_LENGTH bytes
+ * \param key          AES128 encryption key
+ */
+int sign_enc_data_block(u8 *source, unsigned int length, u8 *signature, u8 
*key);
+
+/**
+ * Encrypt a block of data
+ *
+ * \param source       Source data
+ * \param length       Size of source data
+ * \param key          AES128 encryption key
+ */
+int encrypt_data_block(u8 *source, unsigned int length, u8 *key);
+
+/**
+ * Decrypt a block of data
+ *
+ * \param source       Source data
+ * \param length       Size of source data
+ * \param key          AES128 encryption key
+ */
+int decrypt_data_block(u8 *source, unsigned int length, u8 *key);
+
+#endif /* #ifndef _CRYPTO_H_ */
diff --git a/arch/arm/mach-tegra/crypto.c b/arch/arm/mach-tegra/crypto.c
index 1efaa5c3ec..893da35e0b 100644
--- a/arch/arm/mach-tegra/crypto.c
+++ b/arch/arm/mach-tegra/crypto.c
@@ -7,7 +7,7 @@
 #include <common.h>
 #include <log.h>
 #include <linux/errno.h>
-#include "crypto.h"
+#include <asm/arch-tegra/crypto.h>
 #include "uboot_aes.h"
 
 static u8 zero_key[16];
@@ -17,6 +17,7 @@ static u8 zero_key[16];
 enum security_op {
        SECURITY_SIGN           = 1 << 0,       /* Sign the data */
        SECURITY_ENCRYPT        = 1 << 1,       /* Encrypt the data */
+       SECURITY_DECRYPT        = 1 << 2,       /* Dectypt the data */
 };
 
 /**
@@ -54,7 +55,7 @@ static void sign_object(u8 *key, u8 *key_schedule, u8 *src, 
u8 *dst,
        u8 left[AES128_KEY_LENGTH];
        u8 k1[AES128_KEY_LENGTH];
        u8 *cbc_chain_data;
-       unsigned i;
+       unsigned int i;
 
        cbc_chain_data = zero_key;      /* Convenient array of 0's for IV */
 
@@ -92,7 +93,7 @@ static void sign_object(u8 *key, u8 *key_schedule, u8 *src, 
u8 *dst,
 }
 
 /**
- * Encrypt and sign a block of data (depending on security mode).
+ * Decrypt, encrypt or sign a block of data (depending on security mode).
  *
  * \param key          Input AES key, length AES128_KEY_LENGTH
  * \param oper         Security operations mask to perform (enum security_op)
@@ -100,44 +101,68 @@ static void sign_object(u8 *key, u8 *key_schedule, u8 
*src, u8 *dst,
  * \param length       Size of source data
  * \param sig_dst      Destination address for signature, AES128_KEY_LENGTH 
bytes
  */
-static int encrypt_and_sign(u8 *key, enum security_op oper, u8 *src,
-                           u32 length, u8 *sig_dst)
+static int tegra_crypto_core(u8 *key, enum security_op oper, u8 *src,
+                            u32 length, u8 *sig_dst)
 {
        u32 num_aes_blocks;
        u8 key_schedule[AES128_EXPAND_KEY_LENGTH];
        u8 iv[AES128_KEY_LENGTH] = {0};
 
-       debug("encrypt_and_sign: length = %d\n", length);
+       debug("%s: length = %d\n", __func__, length);
 
-       /*
-        * The only need for a key is for signing/checksum purposes, so
-        * if not encrypting, expand a key of 0s.
-        */
-       aes_expand_key(oper & SECURITY_ENCRYPT ? key : zero_key,
-                      AES128_KEY_LENGTH, key_schedule);
+       aes_expand_key(key, AES128_KEY_LENGTH, key_schedule);
 
        num_aes_blocks = (length + AES128_KEY_LENGTH - 1) / AES128_KEY_LENGTH;
 
+       if (oper & SECURITY_DECRYPT) {
+               /* Perform this in place, resulting in src being decrypted. */
+               debug("%s: begin decryption\n", __func__);
+               aes_cbc_decrypt_blocks(AES128_KEY_LENGTH, key_schedule, iv, src,
+                                      src, num_aes_blocks);
+               debug("%s: end decryption\n", __func__);
+       }
+
        if (oper & SECURITY_ENCRYPT) {
                /* Perform this in place, resulting in src being encrypted. */
-               debug("encrypt_and_sign: begin encryption\n");
+               debug("%s: begin encryption\n", __func__);
                aes_cbc_encrypt_blocks(AES128_KEY_LENGTH, key_schedule, iv, src,
                                       src, num_aes_blocks);
-               debug("encrypt_and_sign: end encryption\n");
+               debug("%s: end encryption\n", __func__);
        }
 
        if (oper & SECURITY_SIGN) {
                /* encrypt the data, overwriting the result in signature. */
-               debug("encrypt_and_sign: begin signing\n");
+               debug("%s: begin signing\n", __func__);
                sign_object(key, key_schedule, src, sig_dst, num_aes_blocks);
-               debug("encrypt_and_sign: end signing\n");
+               debug("%s: end signing\n", __func__);
        }
 
        return 0;
 }
 
-int sign_data_block(u8 *source, unsigned length, u8 *signature)
+/**
+ * Tegra crypto group
+ */
+int sign_data_block(u8 *source, unsigned int length, u8 *signature)
+{
+       return tegra_crypto_core(zero_key, SECURITY_SIGN, source,
+                                length, signature);
+}
+
+int sign_enc_data_block(u8 *source, unsigned int length, u8 *signature, u8 
*key)
+{
+       return tegra_crypto_core(key, SECURITY_SIGN, source,
+                                length, signature);
+}
+
+int encrypt_data_block(u8 *source, unsigned int length, u8 *key)
+{
+       return tegra_crypto_core(key, SECURITY_ENCRYPT, source,
+                                length, NULL);
+}
+
+int decrypt_data_block(u8 *source, unsigned int length, u8 *key)
 {
-       return encrypt_and_sign(zero_key, SECURITY_SIGN, source,
-                               length, signature);
+       return tegra_crypto_core(key, SECURITY_DECRYPT, source,
+                                length, NULL);
 }
diff --git a/arch/arm/mach-tegra/crypto.h b/arch/arm/mach-tegra/crypto.h
deleted file mode 100644
index a773d03fc7..0000000000
--- a/arch/arm/mach-tegra/crypto.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * Copyright (c) 2011 The Chromium OS Authors.
- * (C) Copyright 2010 - 2011 NVIDIA Corporation <www.nvidia.com>
- */
-
-#ifndef _CRYPTO_H_
-#define _CRYPTO_H_
-
-/**
- * Sign a block of data
- *
- * \param source       Source data
- * \param length       Size of source data
- * \param signature    Destination address for signature, AES_KEY_LENGTH bytes
- */
-int sign_data_block(u8 *source, unsigned length, u8 *signature);
-
-#endif /* #ifndef _CRYPTO_H_ */
-- 
2.37.2

Reply via email to