Support for initial values decryption 16/190416/7
authorBartlomiej Grzelewski <b.grzelewski@samsung.com>
Mon, 1 Oct 2018 17:07:15 +0000 (19:07 +0200)
committerBartlomiej Grzelewski <b.grzelewski@samsung.com>
Fri, 5 Oct 2018 16:01:24 +0000 (18:01 +0200)
Change-Id: I5b5086a7db69e7677eda93ade1dd2500255a3f20

data/secret_key.h [new file with mode: 0644]
packaging/key-manager-ta.spec
ta/CMakeLists.txt
ta/include/base64.h [new file with mode: 0644]
ta/include/internal.h
ta/include/km_ta_defines.h
ta/src/base64.c [new file with mode: 0644]
ta/src/cmd_exec.c
ta/src/internal.c

diff --git a/data/secret_key.h b/data/secret_key.h
new file mode 100644 (file)
index 0000000..90ce81a
--- /dev/null
@@ -0,0 +1,4 @@
+#ifndef __SECRET_KEY_H_
+#define __SECRET_KEY_H_
+#define SECRET_KEY "THIS/STRING/MUST/BE/REPLACED/IN/REAL/DEVICE="
+#endif
index c561ab9338eece33659bc7cd836fffc963bdaf4c..52be431d2e5f799488b443a2699448a0333f81d3 100644 (file)
@@ -3,6 +3,27 @@
 
 %define ta_name %{unified_ta_devkit_get_ta_name 00000000000000000000666666555555}
 
+%define attach_product_key OFF
+%define attach_test_key OFF
+
+%define secret_ta_key_enable OFF
+
+%if %{attach_product_key} == ON && %{attach_test_key} == ON
+    %{error: You cannot attach product key and test key in one build}
+%endif
+
+%if %{attach_product_key} == ON
+    %if 0%{!?secret_ta_key_delivery_method:1}
+        %{error: You must define macro secret_ta_key_delivery_method}
+    %endif
+    %define secret_ta_key_enable ON
+%endif
+
+%if %{attach_test_key} == ON
+    %define secret_ta_key_enable ON
+    %define secret_ta_key_delivery_method "cp data/secret_key.h ta/include/"
+%endif
+
 Name:       key-manager-ta
 Summary:    Central Key Manager Trusted Application
 Version:    0.1.24
@@ -52,6 +73,11 @@ cp -a %{SOURCE1} .
 cp -a %{SOURCE2} .
 
 %build
+
+%if 0%{?secret_ta_key_delivery_method:1}
+    /bin/bash -c %{secret_ta_key_delivery_method}
+%endif
+
 %{unified_ta_devkit_export}
 %ifarch %{arm} aarch64
 %{?asan:%gcc_unforce_options}
@@ -63,7 +89,8 @@ cd build
     -DTASTORE_DIR=%{_tastoredir} \
     -DINCLUDE_DIR=%{include_dir} \
     -DLIB_DIR=%{lib_dir} \
-    -DTA_NAME=%{ta_name}
+    -DTA_NAME=%{ta_name} \
+    -DSECRET_KEY_ENABLE=%{secret_ta_key_enable}
 make %{?jobs:-j%jobs}
 
 %install
index bb3a6cbe367acbe6cbbb470f679fb3a132cd7c00..f5eb2c68d754ce42d3b2f04e7be70fe1174eeeb2 100644 (file)
@@ -34,6 +34,7 @@ SET(KEY_MANAGER_TA_SOURCES
     ${KEY_MANAGER_TA_PATH}/src/internal.c
     ${KEY_MANAGER_TA_PATH}/src/log.c
     ${KEY_MANAGER_TA_PATH}/src/km_ta.c
+    ${KEY_MANAGER_TA_PATH}/src/base64.c
     ${KEY_MANAGER_TA_SERIALIZATION_PATH}/src/km_serialization.c
     )
 
@@ -53,6 +54,10 @@ ADD_EXECUTABLE(${TARGET_KEY_MANAGER_TA}
     ${KEY_MANAGER_TA_SOURCES}
     )
 
+IF(SECRET_KEY_ENABLE)
+    TARGET_COMPILE_OPTIONS(${TARGET_KEY_MANAGER_TA} PRIVATE -DSECRET_KEY_ENABLE)
+ENDIF(SECRET_KEY_ENABLE)
+
 TARGET_LINK_LIBRARIES(${TARGET_KEY_MANAGER_TA}
     ${KEY_MANAGER_TA_DEPS_LIBRARIES}
     ${KEY_MANAGER_TA_DEPS_STATIC_LIBRARIES}
diff --git a/ta/include/base64.h b/ta/include/base64.h
new file mode 100644 (file)
index 0000000..8da8a23
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2014, STMicroelectronics International N.V.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. 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.
+ *
+ * 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 BASE64_H
+#define BASE64_H
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <stddef.h>
+
+bool base64_enc(const void *data, size_t size, char *buf, size_t *blen);
+bool base64_dec(const char *data, size_t size, void *buf, size_t *blen);
+size_t base64_enc_len(size_t size);
+
+#endif /* BASE64_H */
index 7535d457471f5abf789a435cfcc97c4cfe5f16ef..0250a3b2033c654b6dc16f81af3cf8626064a2af 100644 (file)
@@ -43,6 +43,9 @@ TEE_Result KM_EncryptDataWithPwd(KM_PwdData *pwd, void *in, size_t in_size,
 TEE_Result KM_EncryptKey(TEE_ObjectHandle keyHndl, KM_PwdData *pwd, TEE_ObjectHandle *encKeyHndl,
                                                void *tag, uint32_t *tag_size);
 
+TEE_Result KM_DecryptImportedData(KM_BinaryData *iv, KM_BinaryData *tag,
+                                               KM_BinaryData *input, KM_BinaryData *output);
+
 TEE_Result KM_DecryptDataWithPwd(KM_PwdData* pwd, void *in, size_t in_size,
                                                                void *out, uint32_t *out_size);
 
index 999879807b7765b52d083c86bc3f8e8ef546b067..180001069c5cb0d56945aef6b002b9cc7a06ebb0 100644 (file)
@@ -174,6 +174,7 @@ typedef enum {
                             ///<        KM_BinaryData with binary data or symetric key
                             ///<        uint32_t binary data size in bits
                             ///<        KM_BinaryData IV for decryption with built-in key
+                            ///<        KM_BinaryData tag for data verificaiton after gcm decryption
                             ///<        uint32_t boolean value - true if password is provided
                             ///<        KM_PwdData with password (optional)
                             ///< Output:
diff --git a/ta/src/base64.c b/ta/src/base64.c
new file mode 100644 (file)
index 0000000..0567aa6
--- /dev/null
@@ -0,0 +1,154 @@
+/*
+ * Copyright (c) 2014, STMicroelectronics International N.V.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. 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.
+ *
+ * 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 "base64.h"
+
+static const char base64_table[] =
+       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+size_t base64_enc_len(size_t size)
+{
+       return 4 * ((size + 2) / 3) + 1;
+}
+
+bool base64_enc(const void *data, size_t dlen, char *buf, size_t *blen)
+{
+       size_t n;
+       size_t boffs = 0;
+       const char *d = data;
+
+       n = base64_enc_len(dlen);
+       if (*blen < n) {
+               *blen = n;
+               return false;
+       }
+
+       for (n = 0; n < dlen; n += 3) {
+               uint32_t igrp;
+
+               igrp = d[n];
+               igrp <<= 8;
+
+               if ((n + 1) < dlen)
+                       igrp |= d[n + 1];
+               igrp <<= 8;
+
+               if ((n + 2) < dlen)
+                       igrp |= d[n + 2];
+
+               buf[boffs] = base64_table[(igrp >> 18) & 0x3f];
+               buf[boffs + 1] = base64_table[(igrp >> 12) & 0x3f];
+               if ((n + 1) < dlen)
+                       buf[boffs + 2] = base64_table[(igrp >> 6) & 0x3f];
+               else
+                       buf[boffs + 2] = '=';
+               if ((n + 2) < dlen)
+                       buf[boffs + 3] = base64_table[igrp & 0x3f];
+               else
+                       buf[boffs + 3] = '=';
+
+               boffs += 4;
+       }
+       buf[boffs++] = '\0';
+
+       *blen = boffs;
+       return true;
+}
+
+static bool get_idx(char ch, uint8_t *idx)
+{
+       size_t n;
+
+       for (n = 0; base64_table[n] != '\0'; n++) {
+               if (ch == base64_table[n]) {
+                       *idx = n;
+                       return true;
+               }
+       }
+       return false;
+}
+
+bool base64_dec(const char *data, size_t size, void *buf, size_t *blen)
+{
+       size_t n;
+       uint8_t idx;
+       uint8_t *b = buf;
+       size_t m = 0;
+       size_t s = 0;
+
+       for (n = 0; n < size && data[n] != '\0'; n++) {
+               if (data[n] == '=')
+                       break;  /* Reached pad characters, we're done */
+
+               if (!get_idx(data[n], &idx))
+                       continue;
+
+               if (m > *blen)
+                       b = NULL;
+
+               switch (s) {
+               case 0:
+                       if (b)
+                               b[m] = idx << 2;
+                       s++;
+                       break;
+               case 1:
+                       if (b)
+                               b[m] |= idx >> 4;
+                       m++;
+                       if (m > *blen)
+                               b = NULL;
+                       if (b)
+                               b[m] = (idx & 0xf) << 4;
+                       s++;
+                       break;
+               case 2:
+                       if (b)
+                               b[m] |= idx >> 2;
+                       m++;
+                       if (m > *blen)
+                               b = NULL;
+                       if (b)
+                               b[m] = (idx & 0x3) << 6;
+                       s++;
+                       break;
+               case 3:
+                       if (b)
+                               b[m] |= idx;
+                       m++;
+                       s = 0;
+                       break;
+               default:
+                       return false;   /* "Can't happen" */
+               }
+       }
+       /* We don't detect if input was bad, but that's OK with the spec. */
+       *blen = m;
+       if (b)
+               return true;
+       else
+               return false;
+}
index 3582d4da872a2ed400cdd659fc777f2a6491bedf..08f3ffd099171c494853f05f246ae3c6272b539b 100644 (file)
@@ -865,8 +865,8 @@ TEE_Result KM_ExecCmdSaveData(TEE_Param param[4])
        TEE_ObjectHandle key = TEE_HANDLE_NULL;
        TEE_ObjectHandle oldKey = TEE_HANDLE_NULL;
        KM_BinaryData dataToSave;
-       KM_BinaryData dataEncIV;                   // IV used to decrypt dataToSave with built-in key
-       KM_BinaryData encData;                     // Used during encyption with password
+       KM_BinaryData dataEncIV;                   // IV used to decrypt dataToSave with build-in key
+       KM_BinaryData dataEncTag;                  // TAG used to data verfication after gcm decryption
        KM_BinaryData objId;                       // Random ID of object
        KM_BinaryData tag;
        KM_PwdData pwdData;
@@ -874,12 +874,15 @@ TEE_Result KM_ExecCmdSaveData(TEE_Param param[4])
        uint32_t dataSizeBits_flag;
        uint32_t dataTypeFlag;                     // representation of tz_data_type
 
+       KM_BinaryData plainData;                   // Used during decryption with build-in key
+       KM_BinaryData encData;                     // Used during encyption with password
+
        void *in_buffer = param[1].memref.buffer;
        void *out_buffer = param[2].memref.buffer;
        uint32_t in_size_guard = param[1].memref.size;
        uint32_t out_size_guard = param[2].memref.size;
 
-       encData.data = objId.data = tag.data = NULL;
+       plainData.data = encData.data = objId.data = tag.data = NULL;
 
        if (KM_DeserializeFlag(&in_buffer, &in_size_guard, &dataTypeFlag)) {
                LOG("Error in deserialization");
@@ -905,6 +908,12 @@ TEE_Result KM_ExecCmdSaveData(TEE_Param param[4])
                goto clean;
        }
 
+       if (KM_DeserializeBinaryData(&in_buffer, &in_size_guard, &dataEncTag)) {
+               LOG("Error in deserialization");
+               ret = TEE_ERROR_BAD_PARAMETERS;
+               goto clean;
+       }
+
        if (KM_DeserializeFlag(&in_buffer, &in_size_guard, &with_pwd)) {
                LOG("Error in deserialization");
                ret = TEE_ERROR_BAD_PARAMETERS;
@@ -931,8 +940,27 @@ TEE_Result KM_ExecCmdSaveData(TEE_Param param[4])
        // ObjectID generation
        TEE_GenerateRandom(objId.data, objId.data_size);
 
+       // Decryption
+       if (dataEncIV.data_size) {
+               plainData.data_size = (dataToSave.data_size * 32 + 31)/32;
+               plainData.data = malloc(plainData.data_size);
+               if (plainData.data == NULL) {
+                       LOG("Failed to allocate object buffer for decryption data");
+                       ret = TEE_ERROR_OUT_OF_MEMORY;
+                       goto clean;
+               }
+
+               ret = KM_DecryptImportedData(&dataEncIV, &dataEncTag, &dataToSave, &plainData);
+               if (ret != TEE_SUCCESS) {
+                       LOG("Failed to decrypt initial values");
+                       goto clean;
+               }
+
+               dataToSave = plainData;
+       }
+
+       // Let's save data
        if (dataTypeFlag == TYPE_GENERIC_SECRET) {
-               // TODO support for decryption with dataEncIV
                if (with_pwd) {
                        tag.data_size = pwdData.tag_len_bits / 8;
                        tag.data = malloc(tag.data_size);
@@ -972,7 +1000,6 @@ TEE_Result KM_ExecCmdSaveData(TEE_Param param[4])
                        LOG("Failed to save data to storage");
                }
        } else if (dataTypeFlag == TYPE_SKEY) {
-               // TODO support for decryption with dataEncIV
                if (!KM_CheckAlgoKeySize(TEE_TYPE_AES, dataSizeBits_flag)) {
                        LOG("Unsupported key size provided: %u", dataSizeBits_flag);
                        ret = TEE_ERROR_BAD_PARAMETERS;
@@ -1032,6 +1059,7 @@ TEE_Result KM_ExecCmdSaveData(TEE_Param param[4])
 clean:
        TEE_CloseObject(oldKey);
        TEE_CloseObject(key);
+       free(plainData.data);
        free(objId.data);
        free(encData.data);
        free(tag.data);
index d9ebeef671bb177fc72f4985151ee74170666177..80e169ed315f5b2272fdc2718f5d87646ecac6ae 100644 (file)
 #include <crypto_symmetric.h>
 #include <crypto_auth.h>
 
+#ifdef SECRET_KEY_ENABLE
+#include <base64.h>
+#include <secret_key.h>
+#endif
+
 #ifndef TEE_DATA_FLAG_OVERWRITE
 #define TEE_DATA_FLAG_OVERWRITE TEE_DATA_FLAG_EXCLUSIVE
 #endif
@@ -218,6 +223,76 @@ out:
        return ret;
 }
 
+#ifdef SECRET_KEY_ENABLE
+TEE_Result KM_DecryptImportedData(
+               KM_BinaryData *iv,
+               KM_BinaryData *tag,
+               KM_BinaryData *input,
+               KM_BinaryData *output)
+{
+       TEE_Result ret = TEE_SUCCESS;
+       TEE_ObjectHandle key = TEE_HANDLE_NULL;
+       TEE_OperationHandle op = TEE_HANDLE_NULL;
+
+       const char base64key[] = SECRET_KEY;
+       char buff[40];
+       size_t buff_size = sizeof(buff);
+
+       if (!base64_dec(base64key, sizeof(base64key), buff, &buff_size)) {
+               LOG("Failed to decode built-in key");
+               ret = TEE_ERROR_BAD_PARAMETERS;
+               goto out;
+       }
+
+       ret = KM_CreateKey(TEE_TYPE_AES, buff_size*8, buff, &key);
+       if (ret != TEE_SUCCESS) {
+               LOG("Failed to create built-in key");
+               goto out;
+       }
+
+       ret = KM_CreateOperation(key, TEE_ALG_AES_GCM, TEE_MODE_DECRYPT, &op);
+       if (ret != TEE_SUCCESS) {
+               LOG("Failed to create operation: %x", ret);
+               goto out;
+       }
+
+       ret = KM_AuthDecrypt(
+                               op,
+                               iv->data,
+                               iv->data_size,
+                               tag->data_size*8,
+                               0,
+                               input->data,
+                               input->data_size,
+                               NULL,
+                               0,
+                               tag->data,
+                               tag->data_size,
+                               output->data,
+                               &(output->data_size));
+
+       if (ret != TEE_SUCCESS) {
+               LOG("Failed to decrypt key: %x", ret);
+               goto out;
+       }
+
+out:
+       if (op != TEE_HANDLE_NULL) TEE_FreeOperation(op);
+       TEE_FreeTransientObject(key);
+       return ret;
+}
+#else
+TEE_Result KM_DecryptImportedData(
+               KM_BinaryData *iv,
+               KM_BinaryData *tag,
+               KM_BinaryData *input,
+               KM_BinaryData *output)
+{
+       LOG("This version of key-manager-ta application does not support import of encrypted values.");
+       return TEE_ERROR_NOT_SUPPORTED;
+}
+#endif
+
 TEE_Result KM_DecryptDataWithPwd(KM_PwdData* pwd, void *in, size_t in_size,
                                                                void *out, uint32_t *out_size)
 {