SET(KEY_MANAGER_TA_PATH ${KEY_MANAGER_TA_ROOT_PATH}/ta)
SET(KEY_MANAGER_TA_SERIALIZATION_PATH ${KEY_MANAGER_TA_ROOT_PATH}/serialization)
+IF(${CMAKE_BUILD_TYPE} MATCHES "DEBUG")
+ ADD_DEFINITIONS("-DDEBUG")
+ENDIF(${CMAKE_BUILD_TYPE} MATCHES "DEBUG")
+
############# TA #############
SET(KEY_MANAGER_TA_SOURCES
${KEY_MANAGER_TA_PATH}/src/crypto_auth.c
${KEY_MANAGER_TA_PATH}/src/crypto_derive.c
${KEY_MANAGER_TA_PATH}/src/crypto_digest.c
+ ${KEY_MANAGER_TA_PATH}/src/crypto_padding.c
${KEY_MANAGER_TA_PATH}/src/crypto_symmetric.c
${KEY_MANAGER_TA_PATH}/src/internal.c
${KEY_MANAGER_TA_PATH}/src/log.c
mkdir -p build
cd build
%cmake .. \
+ -DCMAKE_BUILD_TYPE=%{?build_type:%build_type}%{!?build_type:RELEASE} \
-DTEF_BUILD_TYPE=%{tef_build_type} \
-DTASTORE_DIR=%{tastore_dir} \
-DINCLUDE_DIR=%{include_dir} \
typedef struct AEData_ {
Data aad;
uint32_t tagLen;
- uint32_t AADLen;
uint32_t payloadLen;
} AEData;
int KM_ParamsDeserializeKey(SymmetricInput *self, Key **out);
int KM_ParamsDeserializeKeyId(SymmetricInput *self, KeyId **out);
-int KM_ParamsSerializationInit(void *buffer, size_t buffer_size, SymmetricInput **out);
-int KM_ParamsSerializeInputData(SymmetricInput *self, const void *data, size_t data_size);
-int KM_ParamsSerializeIVData(SymmetricInput *self, const void *data, size_t data_size);
-int KM_ParamsSerializeAEData(SymmetricInput *self, uint32_t tagLen, uint32_t AADLen,
- uint32_t payloadLen, const void *aad, size_t aad_size);
-int KM_ParamsSerializeOutData(SymmetricInput *self, const void *data, size_t data_size);
+int KM_ParamsSerializationInit(void *buffer, uint32_t buffer_size, SymmetricInput **out);
+int KM_ParamsSerializeInputData(SymmetricInput *self, const void *data, uint32_t data_size);
+int KM_ParamsSerializeIVData(SymmetricInput *self, const void *data, uint32_t data_size);
+int KM_ParamsSerializeAEData(SymmetricInput *self, uint32_t tagLen, uint32_t payloadLen,
+ const void *aad, uint32_t aad_size);
+int KM_ParamsSerializeOutData(SymmetricInput *self, const void *data, uint32_t data_size);
int KM_ParamsSerializeTagData(SymmetricInput *self, const void *data, size_t data_size);
LOG("Input=%p, input_size=%d", input_data->data, input_data->data_size);
}
if (ae_data) {
- LOG("aad.data=%p, aad.size=%d, tagLen=%d, AADLen=%d, payloadLen=%d", ae_data->aad.data,
- ae_data->aad.data_size, ae_data->tagLen, ae_data->AADLen, ae_data->payloadLen);
+ LOG("aad.data=%p, aad.size=%d, tagLen=%d, payloadLen=%d", ae_data->aad.data,
+ ae_data->aad.data_size, ae_data->tagLen, ae_data->payloadLen);
}
if (out_data) {
LOG("Out=%p, out_size=%d", out_data->data, out_data->data_size);
size += sizeof(IVData) + addAlignment(iv_size);
if (with_ae_data > 0)
- size += sizeof(AEData) + addAlignment(aad_size);
+ size += sizeof(AEData) + sizeof(Data) + addAlignment(aad_size);
if (out_size > 0)
size += sizeof(OutData) + addAlignment(out_size);
return 0;
}
-int KM_ParamsSerializeAEData(SymmetricInput *self, uint32_t tagLen, uint32_t AADLen,
- uint32_t payloadLen, const void *aad, size_t aad_size)
+int KM_ParamsSerializeAEData(SymmetricInput *self, uint32_t tagLen, uint32_t payloadLen,
+ const void *aad, uint32_t aad_size)
{
AEData *ptr = NULL;
uint32_t ret = 0;
}
ptr->tagLen = tagLen;
- ptr->AADLen = AADLen;
ptr->payloadLen = payloadLen;
self->ae_data_offset = self->global_offset;
TEE_Result KM_ExecCmdGenerateKeyPwd(TEE_Param param[4]);
+TEE_Result KM_ExecCmdImportKey(TEE_Param param[4]);
+
TEE_Result KM_ExecCmdSymmetric(uint32_t commandID, TEE_Param param[4]);
TEE_Result KM_ExecCmdAuth(uint32_t commandID, TEE_Param param[4]);
#include <tee_internal_api.h>
TEE_Result KM_AuthEncrypt(TEE_OperationHandle hndl, void *iv, uint32_t iv_size, uint32_t tagLen,
- uint32_t AADLen, uint32_t payloadLen, void *data, uint32_t data_size,
- void *out, uint32_t *out_size, void *tag, uint32_t *tag_size);
+ uint32_t payloadLen, void *data, uint32_t data_size,
+ void *aad, uint32_t aad_size, void *out, uint32_t *out_size,
+ void *tag, uint32_t *tag_size);
TEE_Result KM_AuthDecrypt(TEE_OperationHandle hndl, void *iv, uint32_t iv_size, uint32_t tagLen,
- uint32_t AADLen, uint32_t payloadLen, void *data, uint32_t data_size,
- void *tag, uint32_t tag_size, void *out, uint32_t *out_size);
-
+ uint32_t payloadLen, void *data, uint32_t data_size,
+ void *aad, uint32_t aad_size, void *tag, uint32_t tag_size,
+ void *out, uint32_t *out_size);
#endif // __CRYPTO_AUTH_H__
--- /dev/null
+/*
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+/*
+ * @file crypto_padding.c
+ * @author Lukasz Kostyra (l.kostyra@samsung.com)
+ * @version 1.0
+ * @brief Implementation of Global Platform Internal API usage (padding)
+ */
+
+#ifndef _CRYPTO_PADDING_H_
+#define _CRYPTO_PADDING_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+typedef enum
+{
+ KM_PADDING_ZERO = 1, // not reversable - should be used only for hashes/keys, not for data
+ KM_PADDING_PKCS7,
+} PaddingMode;
+
+uint32_t KM_CalculatePaddedSize(PaddingMode padding, uint32_t block_size, uint32_t data_size);
+int KM_PadBuffer(PaddingMode padding, uint32_t block_size, void *in, uint32_t in_size,
+ void *out, uint32_t *out_size);
+int KM_UnpadBuffer(PaddingMode padding, void *buffer, uint32_t *buffer_size);
+
+#endif // _CRYPTO_PADDING_H_
\ No newline at end of file
#include <crypto_auth.h>
#include <crypto_derive.h>
#include <crypto_digest.h>
+#include <crypto_padding.h>
#include <km_serialization.h>
#include <cmd_exec.h>
#include <log.h>
const uint32_t AES_BLOCK_SIZE = 16; // in bytes
const uint32_t RSA_BLOCK_SIZE = 512; // in bytes, assumes max RSA key size 4096 bits
const uint32_t PBKDF2_ITERATIONS = 1024;
+const PaddingMode PADDING_MODE = KM_PADDING_PKCS7;
+
static uint32_t KM_AlgoType2TeeType(int algo)
{
static uint32_t KM_Cmd2TeeMode(int cmd)
{
switch (cmd) {
- case CMD_ENCRYPT:
- return TEE_MODE_ENCRYPT;
- case CMD_DECRYPT:
- return TEE_MODE_DECRYPT;
- default:
- return 0;
+ case CMD_ENCRYPT: return TEE_MODE_ENCRYPT;
+ case CMD_DECRYPT: return TEE_MODE_DECRYPT;
+ default: return 0;
}
- return 0;
}
static uint32_t KM_Algo2TeeAlgo(int algo)
case ALGO_AES_CBC: return TEE_ALG_AES_CBC_NOPAD;
case ALGO_AES_CFB: return KM_TA_ALG_AES_CFB;
case ALGO_AES_GCM: return TEE_ALG_AES_GCM;
- case ALGO_RSA: return TEE_ALG_RSA_NOPAD;
+ case ALGO_RSA: return TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA1;
default: return 0;
}
}
}
}
- KM_ParamsDump(*input, *input_data, *iv_data, *key_data, *key_id_data, *ae_data, NULL, *tag_data);
-
if (*input_data == NULL) {
LOG("No InputData in input buffer");
return TEE_ERROR_BAD_PARAMETERS;
}
}
+static uint32_t KM_CheckAESKeySize(uint32_t type, uint32_t key_size)
+{
+ switch (type) {
+ case TEE_TYPE_AES:
+ switch (key_size) {
+ case 128:
+ case 192:
+ case 256:
+ return 1;
+ default:
+ return 0;
+ }
+ case TEE_TYPE_RSA_KEYPAIR:
+ case TEE_TYPE_DSA_KEYPAIR: {
+ switch (key_size) {
+ case 512:
+ case 1024:
+ case 2048:
+ case 3072:
+ case 4096:
+ return 1;
+ default:
+ return 0;
+ }
+ }
+ default:
+ LOG("Invalid key type provided: %x", type);
+ return 0;
+ }
+}
+
static uint32_t KM_AlgoHash2SignVerifyAlgo(int algo, int hash)
{
switch (algo) {
goto clean;
}
- if (type == 0) {
- LOG("Unsupported key type provided: %u", type);
+ if (!KM_CheckAESKeySize(type, key_bits_size)) {
+ LOG("Unsupported key size provided: %u", key_bits_size);
ret = TEE_ERROR_BAD_PARAMETERS;
goto clean;
}
goto clean;
}
- ret = KM_SaveKey(NULL, 0, hndl, objId, objId_size);
- if (TEE_SUCCESS != ret) {
- LOG("Failed to save generated key");
- goto clean;
- }
+ // ObjectID generation
+ TEE_GenerateRandom(objId, objId_size);
if (0 != KM_ParamsSerializationInit(param[1].memref.buffer, param[1].memref.size,
- &input) || 0 != KM_ParamsSerializeKeyId(input, objId, objId_size)) {
+ &input) || 0 != KM_ParamsSerializeKeyId(input, objId, objId_size)) {
LOG("Failed to serialize key to output buffer");
ret = TEE_ERROR_BAD_PARAMETERS;
+ goto clean;
+ }
+
+ ret = KM_SaveKey(NULL, 0, hndl, objId, objId_size);
+ if (TEE_SUCCESS != ret) {
+ LOG("Failed to save generated key");
+ goto clean;
}
clean:
&input, &input_data, &iv_data, NULL, NULL, NULL, NULL);
if (ret != TEE_SUCCESS) {
LOG("Failed to deserialize data from input buffer");
- return TEE_ERROR_BAD_PARAMETERS;
+ ret = TEE_ERROR_BAD_PARAMETERS;
+ goto clean;
}
goto clean;
}
+ // ObjectID generation
+ TEE_GenerateRandom(objId, objId_size);
+
if (KM_ParamsSerializationInit(param[2].memref.buffer, param[2].memref.size,
- &input != 0) ||
- KM_ParamsSerializeKeyId(input, objId, objId_size) != 0) {
+ &input) != 0 || KM_ParamsSerializeKeyId(input, objId, objId_size) != 0) {
LOG("Failed to serialize output data");
ret = TEE_ERROR_BAD_PARAMETERS;
+ goto clean;
}
ret = KM_SaveKey(NULL, 0, derivedKey, objId, objId_size);
return ret;
}
+TEE_Result KM_ExecCmdImportKey(TEE_Param param[4])
+{
+ TEE_Result ret = TEE_ERROR_NOT_IMPLEMENTED;
+
+ return ret;
+}
+
TEE_Result KM_ExecCmdSymmetric(uint32_t commandID, TEE_Param param[4])
{
TEE_Result ret = TEE_SUCCESS;
IVData *iv_data = NULL;
KeyId *key_id_data = NULL;
Key *key_data = NULL;
- char ownIVFlag = 0;
- uint32_t *iv = NULL;
- uint32_t iv_size = 0;
+ void *in_padded = NULL;
+ uint32_t in_padded_size = 0;
void *out = NULL;
uint32_t out_size = 0;
- uint32_t out_size_pad = 0;
uint32_t type = 0;
uint32_t algo = KM_Algo2TeeAlgo(param[0].value.a);
return TEE_ERROR_BAD_PARAMETERS;
}
- out_size_pad = AES_BLOCK_SIZE - (input_data->data_size % AES_BLOCK_SIZE);
- out_size = input_data->data_size + out_size_pad;
+ out_size = KM_CalculatePaddedSize(KM_PADDING_PKCS7, AES_BLOCK_SIZE, input_data->data_size);
out = malloc(out_size);
if (out == NULL) {
LOG("Failed to allocate output buffer");
goto clean;
}
- if (iv_data) {
- iv = iv_data->data;
- iv_size = iv_data->data_size;
- } else {
- // create empty (zeroed) IV based on AES block size
- ownIVFlag = 1;
- iv_size = AES_BLOCK_SIZE;
- iv = (uint32_t*)malloc(iv_size);
- if (iv == NULL) {
- LOG("Failed to allocate IV buffer");
+ // GCM and CTR modes does not need to be padded
+ if (CMD_ENCRYPT == commandID &&
+ TEE_ALG_AES_GCM != algo && TEE_ALG_AES_CTR_NOPAD != algo) {
+ in_padded_size = out_size;
+ in_padded = malloc(in_padded_size);
+ if (in_padded == NULL) {
+ LOG("Failed to allocate input buffer for padded data");
ret = TEE_ERROR_OUT_OF_MEMORY;
goto clean;
}
- memset(iv, 0x00, iv_size);
+
+ if (KM_PadBuffer(PADDING_MODE, AES_BLOCK_SIZE, input_data->data, input_data->data_size,
+ in_padded, &in_padded_size)) {
+ LOG("Error during padding operation");
+ ret = TEE_ERROR_GENERIC;
+ goto clean;
+ }
}
if (algo == KM_TA_ALG_AES_CFB) {
- ret = KM_SymmetricCrypt_AES_CFB(key_id_data->data, key_id_data->data_size, mode, iv, iv_size,
- input_data->data, input_data->data_size, out, &out_size);
+ if (CMD_ENCRYPT == commandID) {
+ ret = KM_SymmetricCrypt_AES_CFB(key_id_data->data, key_id_data->data_size, mode,
+ iv_data->data, iv_data->data_size,
+ in_padded, in_padded_size, out, &out_size);
+ } else {
+ ret = KM_SymmetricCrypt_AES_CFB(key_id_data->data, key_id_data->data_size, mode,
+ iv_data->data, iv_data->data_size,
+ input_data->data, input_data->data_size, out, &out_size);
+ }
} else {
if (key_id_data) {
ret = KM_CreateOperationWithKeyId(key_id_data->data, key_id_data->data_size, mode, algo, &operation);
goto clean;
}
- ret = KM_SymmetricCrypt(operation, iv, iv_size, input_data->data, input_data->data_size,
- out, &out_size);
+ if (CMD_ENCRYPT == commandID && TEE_ALG_AES_GCM != algo && TEE_ALG_AES_CTR_NOPAD != algo) {
+ ret = KM_SymmetricCrypt(operation, iv_data->data, iv_data->data_size,
+ in_padded, in_padded_size, out, &out_size);
+ } else {
+ ret = KM_SymmetricCrypt(operation, iv_data->data, iv_data->data_size,
+ input_data->data, input_data->data_size, out, &out_size);
+ }
}
if (TEE_SUCCESS != ret) {
goto clean;
}
+ if (CMD_DECRYPT == commandID && TEE_ALG_AES_GCM != algo && TEE_ALG_AES_CTR_NOPAD != algo) {
+ if (KM_UnpadBuffer(PADDING_MODE, out, &out_size)) {
+ LOG("Error during unpadding operation");
+ ret = TEE_ERROR_GENERIC;
+ goto clean;
+ }
+ }
+
if (0 != KM_ParamsSerializationInit(param[2].memref.buffer, param[2].memref.size, &input)
|| 0 != KM_ParamsSerializeOutData(input, out, out_size)) {
ret = TEE_ERROR_BAD_PARAMETERS;
}
clean:
+ free(in_padded);
free(out);
- if (ownIVFlag) free(iv);
if (operation != TEE_HANDLE_NULL) TEE_FreeOperation(operation);
return ret;
}
uint32_t algo = KM_Algo2TeeAlgo(param[0].value.a);
uint32_t mode = KM_Cmd2TeeMode(commandID);
- if (ALGO_AES_GCM != param[0].value.a) {
+ if (param[0].value.a != ALGO_AES_GCM) {
LOG("Invalid key type: %d.", param[0].value.a);
return TEE_ERROR_BAD_PARAMETERS;
}
return TEE_ERROR_BAD_PARAMETERS;
}
- if (KM_CheckAESMode(algo, ae_data->tagLen)) {
+ if (!KM_CheckAESMode(algo, ae_data->tagLen)) {
LOG("Tag has invalid length. (tagLen=%d)", ae_data->tagLen);
return TEE_ERROR_BAD_PARAMETERS;
}
algo, key_data->key_bits_size, &hndl);
}
if (TEE_SUCCESS != ret) {
- return ret;
+ goto clean;
}
- out_size = input_data->data_size + AES_BLOCK_SIZE;
+ out_size = KM_CalculatePaddedSize(KM_PADDING_PKCS7, AES_BLOCK_SIZE, input_data->data_size);
out = malloc(out_size);
- if (out == NULL) {
- LOG("Failed to allocate output buffer");
- ret = TEE_ERROR_OUT_OF_MEMORY;
- goto clean;
- }
if (CMD_ENCRYPT == commandID) {
tag_size = ae_data->tagLen / 8; // convert tag size to bytes
goto clean;
}
ret = KM_AuthEncrypt(hndl, iv_data->data, iv_data->data_size, ae_data->tagLen,
- ae_data->AADLen, ae_data->payloadLen, input_data->data,
- input_data->data_size, out, &out_size, tag, &tag_size);
+ ae_data->payloadLen, input_data->data,
+ input_data->data_size, ae_data->aad.data,
+ ae_data->aad.data_size, out, &out_size, tag, &tag_size);
} else {
ret = KM_AuthDecrypt(hndl, iv_data->data, iv_data->data_size, ae_data->tagLen,
- ae_data->AADLen, ae_data->payloadLen, input_data->data,
- input_data->data_size, tag_data->data, tag_data->data_size,
+ ae_data->payloadLen, input_data->data,
+ input_data->data_size, ae_data->aad.data,
+ ae_data->aad.data_size, tag_data->data, tag_data->data_size,
out, &out_size);
}
{
TEE_Result ret = TEE_SUCCESS;
- LOG("Asym encrypt");
+ LOG("LKDEBUG Asym encrypt");
ret = TEE_AsymmetricEncrypt(hndl, NULL, 0, input, input_size, output, output_size);
if (TEE_SUCCESS != ret) {
LOG("TEE_AsymmetricEncrypt has failed with=%x.", ret);
return ret;
}
- LOG("Asym encrypt done");
+ LOG("LKDEBUG Asym encrypt done");
return ret;
}
{
TEE_Result ret = TEE_SUCCESS;
- LOG("Asym decrypt");
+ LOG("LKDEBUG Asym decrypt");
ret = TEE_AsymmetricDecrypt(hndl, NULL, 0, input, input_size, output, output_size);
if (TEE_SUCCESS != ret) {
LOG("TEE_AsymmetricEncrypt has failed with=%x.", ret);
return ret;
}
- LOG("Asym encrypt done");
+ LOG("LKDEBUG Asym decrypt done");
return ret;
}
{
TEE_Result ret = TEE_SUCCESS;
- LOG("Asym sign");
+ LOG("LKDEBUG Asym sign");
ret = TEE_AsymmetricSignDigest(hndl, NULL, 0, digest, digest_size, signature, sig_size);
if (TEE_SUCCESS != ret) {
LOG("TEE_AsymmetricSignDigest has failed with=%x.", ret);
return ret;
}
- LOG("Asym sign done");
+ LOG("LKDEBUG Asym sign done");
return ret;
}
{
TEE_Result ret = TEE_SUCCESS;
- LOG("Asym verify");
+ LOG("LKDEBUG Asym verify");
ret = TEE_AsymmetricVerifyDigest(hndl, NULL, 0, digest, digest_size, signature, sig_size);
if (TEE_SUCCESS != ret && TEE_ERROR_SIGNATURE_INVALID != ret) {
LOG("TEE_AsymmetricVerifyDigest has failed with=%x.", ret);
return ret;
}
- LOG("Asym verify done");
+ LOG("LKDEBUG Asym verify done");
return ret;
}
\ No newline at end of file
#include <log.h>
TEE_Result KM_AuthEncrypt(TEE_OperationHandle hndl, void *iv, uint32_t iv_size, uint32_t tagLen,
- uint32_t AADLen, uint32_t payloadLen, void *data, uint32_t data_size,
- void *out, uint32_t *out_size, void *tag, uint32_t *tag_size)
+ uint32_t payloadLen, void *data, uint32_t data_size,
+ void *aad, uint32_t aad_size, void *out, uint32_t *out_size,
+ void *tag, uint32_t *tag_size)
{
TEE_Result ret = TEE_SUCCESS;
- ret = TEE_AEInit(hndl, iv, (size_t) iv_size, tagLen, AADLen, payloadLen);
+ if (iv == NULL || iv_size < 12) {
+ LOG("Provided IV is not big enough (%d bytes)", iv_size);
+ return TEE_ERROR_NOT_SUPPORTED;
+ }
+
+ ret = TEE_AEInit(hndl, iv, (size_t) iv_size, tagLen, aad_size, payloadLen);
if (TEE_SUCCESS != ret) {
LOG("TEE_AEInit failed with error=%x.", ret);
return ret;
}
+ // AAD is not obligatory, so no error returned here if we don't have it
+ if (aad != NULL && aad_size > 0) {
+ TEE_AEUpdateAAD(hndl, aad, aad_size);
+ }
+
ret = TEE_AEEncryptFinal(hndl, data, data_size, out, out_size, tag, tag_size);
if (TEE_SUCCESS != ret) {
LOG("TEE_AEEncryptFinal failed with error=%x.", ret);
}
TEE_Result KM_AuthDecrypt(TEE_OperationHandle hndl, void *iv, uint32_t iv_size, uint32_t tagLen,
- uint32_t AADLen, uint32_t payloadLen, void *data, uint32_t data_size,
- void *tag, uint32_t tag_size, void *out, uint32_t *out_size)
+ uint32_t payloadLen, void *data, uint32_t data_size,
+ void *aad, uint32_t aad_size, void *tag, uint32_t tag_size,
+ void *out, uint32_t *out_size)
{
TEE_Result ret = TEE_SUCCESS;
- ret = TEE_AEInit(hndl, iv, (size_t) iv_size, tagLen, AADLen, payloadLen);
+ ret = TEE_AEInit(hndl, iv, (size_t) iv_size, tagLen, aad_size, payloadLen);
if (TEE_SUCCESS != ret) {
LOG("TEE_AEInit failed with error=%x.", ret);
return ret;
}
+
+ if (aad != NULL && aad_size > 0) {
+ TEE_AEUpdateAAD(hndl, aad, aad_size);
+ }
+
ret = TEE_AEDecryptFinal(hndl, data, data_size, out, out_size, tag, tag_size);
if (TEE_SUCCESS != ret) {
LOG("TEE_AEDecryptFinal failed with error=%x.", ret);
*/
#include <crypto_derive.h>
+#include <crypto_padding.h>
#include <internal.h>
#include <log.h>
#include <stdlib.h>
uint32_t b = 0, i = 0, j = 0, b_be = 0;
uint32_t currentKeyBlock = 0;
uint32_t bytesToCopy = 0;
+ char *hmacKeyBuffer = NULL;
char *hmacInBuffer = NULL; // temporary to keep HMAC result
char *blockBuffer = NULL; // actual buffer to keep the result of HMAC iterations
char *keyBuffer = NULL; // buffer for derived key data
char hmacOutBuffer[SHA1_SIZE_BYTES]; // temporary to keep HMAC output
+ size_t hmacKeySize = pwd_size;
size_t hmacInBufferSize = salt_size + 4; // max buffer size for hmac's input
size_t hmacOutBufferSize = SHA1_SIZE_BYTES;
size_t blockBufferSize = SHA1_SIZE_BYTES;
uint32_t keyBytesSize = key_bits_size / 8;
- char *pwdptr = (char*)pwd;
- if (pwd_size < 10 || pwd_size > 64) {
- LOG("Unsupported password size - cannot derive");
+ if (hmacKeySize > 64) {
+ LOG("Too long password (%d bytes) - cannot derive", hmacKeySize);
return TEE_ERROR_NOT_SUPPORTED;
}
+ if (hmacKeySize < 10) {
+ hmacKeySize = 10;
+ }
+ hmacKeyBuffer = (char*)malloc(hmacKeySize);
+ if (pwd_size < 10) {
+ KM_PadBuffer(KM_PADDING_ZERO, 10, pwd, pwd_size, hmacKeyBuffer, &hmacKeySize);
+ } else {
+ memcpy(hmacKeyBuffer, pwd, pwd_size);
+ }
+
if (out_key == NULL) {
LOG("Incorrect key handle provided");
- return TEE_ERROR_BAD_PARAMETERS;
+ ret = TEE_ERROR_BAD_PARAMETERS;
+ goto end;
}
- ret = KM_CreateOperationWithKey(pwd, pwd_size, TEE_TYPE_HMAC_SHA1, TEE_MODE_MAC,
- TEE_ALG_HMAC_SHA1, pwd_size * 8, &hmacOp);
+ ret = KM_CreateOperationWithKey(hmacKeyBuffer, hmacKeySize, TEE_TYPE_HMAC_SHA1, TEE_MODE_MAC,
+ TEE_ALG_HMAC_SHA1, hmacKeySize * 8, &hmacOp);
if (ret != TEE_SUCCESS) {
LOG("Failed to create HMAC operation: %x", ret);
goto end;
*out_key = keyHandle;
end:
+ free(hmacKeyBuffer);
free(hmacInBuffer);
free(blockBuffer);
free(keyBuffer);
--- /dev/null
+/*
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+/*
+ * @file crypto_padding.c
+ * @author Lukasz Kostyra (l.kostyra@samsung.com)
+ * @version 1.0
+ * @brief Implementation of Global Platform Internal API usage (padding)
+ */
+
+#include "crypto_padding.h"
+#include "log.h"
+
+
+uint32_t KM_CalculatePaddedSize(PaddingMode padding, uint32_t block_size, uint32_t data_size)
+{
+ uint32_t toPad = 0;
+
+ switch (padding) {
+ case KM_PADDING_ZERO: {
+ toPad = block_size - (data_size % block_size);
+ return data_size + toPad;
+ }
+ case KM_PADDING_PKCS7: {
+ toPad = block_size - (data_size % block_size);
+ if (toPad == 0) toPad = block_size;
+ return data_size + toPad;
+ }
+ default: {
+ LOG("Unsupported padding type %d", padding);
+ return 0;
+ }
+ }
+}
+
+void KM_PadBuffer_Zero(void *in, uint32_t in_size, void *out, unsigned char to_pad)
+{
+ memcpy(out, in, in_size);
+ memset(&((unsigned char*)out)[in_size], 0x0, to_pad);
+}
+
+void KM_PadBuffer_PKCS7(void *in, uint32_t in_size, void *out, unsigned char to_pad)
+{
+ memcpy(out, in, in_size);
+ memset(&((unsigned char*)out)[in_size], to_pad, to_pad);
+}
+
+int KM_PadBuffer(PaddingMode padding, uint32_t block_size, void *in, uint32_t in_size,
+ void *out, uint32_t *out_size)
+{
+ uint32_t outputSize = 0;
+
+ if (in == NULL) {
+ LOG("Input data incorrect");
+ return -1;
+ }
+
+ if (out == NULL || out_size == NULL) {
+ LOG("Output buffer incorrect");
+ return -1;
+ }
+
+ outputSize = KM_CalculatePaddedSize(padding, block_size, in_size);
+ if (outputSize == 0) {
+ LOG("Unsupported padding type");
+ return -1;
+ }
+
+ if (outputSize > *out_size) {
+ LOG("Output buffer too small");
+ return -1;
+ }
+
+ switch (padding) {
+ case KM_PADDING_ZERO: {
+ KM_PadBuffer_Zero(in, in_size, out, outputSize - in_size);
+ }
+ case KM_PADDING_PKCS7: {
+ KM_PadBuffer_PKCS7(in, in_size, out, outputSize - in_size);
+ break;
+ }
+ default: {
+ LOG("Unsupported padding requested");
+ return -1;
+ }
+ }
+
+ *out_size = outputSize;
+ return 0;
+}
+
+void KM_UnpadBuffer_PKCS7(void *buffer, size_t buffer_size, size_t *was_padded)
+{
+ *was_padded = ((unsigned char*)buffer)[buffer_size - 1];
+}
+
+int KM_UnpadBuffer(PaddingMode padding, void *buffer, size_t *buffer_size)
+{
+ uint32_t wasPadded = 0;
+
+ if (buffer == NULL || buffer_size == NULL) {
+ LOG("Output buffer incorrect");
+ return -1;
+ }
+
+ switch (padding) {
+ case KM_PADDING_PKCS7:
+ KM_UnpadBuffer_PKCS7(buffer, *buffer_size, &wasPadded);
+ break;
+ default:
+ LOG("Unsupported padding requested");
+ return -1;
+ }
+
+ *buffer_size -= wasPadded;
+ return 0;
+}
\ No newline at end of file
{
TEE_Result ret = TEE_SUCCESS;
+ if (iv_size != 16) {
+ LOG("Incorrect IV provided (%d bytes)", iv_size);
+ return TEE_ERROR_BAD_PARAMETERS;
+ }
+
LOG("Cipher init");
TEE_CipherInit(hndl, iv, iv_size);
int KM_CheckAESMode(uint32_t algo, uint32_t tagLen)
{
- switch (tagLen) {
- case 128:
- return 0;
- case 120:
- return algo != TEE_ALG_AES_GCM;
- case 112:
- return 0;
- case 104:
- return algo != TEE_ALG_AES_GCM;
- case 96:
- return 0;
- case 64:
- return algo != TEE_ALG_AES_CCM;
- case 48:
- return algo != TEE_ALG_AES_CCM;
- case 32:
- return algo != TEE_ALG_AES_CCM;
- default:
- return 1;
+ switch (algo) {
+ case TEE_ALG_AES_GCM: {
+ switch (tagLen) {
+ case 128:
+ case 120:
+ case 112:
+ case 104:
+ case 96:
+ return 1;
+ default:
+ return 0;
+ }
+ }
+ case TEE_ALG_AES_CCM: {
+ switch (tagLen) {
+ case 128:
+ case 112:
+ case 96:
+ case 64:
+ case 48:
+ case 32:
+ return 1;
+ default:
+ return 0;
+ }
+ }
+ default: {
+ return 0;
+ }
}
}
uint32_t flags =
TEE_DATA_FLAG_ACCESS_READ | TEE_DATA_FLAG_ACCESS_WRITE | TEE_DATA_FLAG_OVERWRITE;
- TEE_GenerateRandom(objId, objId_size);
-
ret = TEE_CreatePersistentObject(TEE_STORAGE_PRIVATE, objId, objId_size, flags, key, data,
data_size, &pers_handl);
TEE_CloseObject(pers_handl);
switch (commandID) {
case CMD_GENERATE_KEY: {
LOGD("!!! Generate key !!!");
+ LOGD("Alg: %x", param[0].value.a);
ret = KM_ExecCmdGenerateKey(param);
break;
}
}
case CMD_GENERATE_KEY_PWD: {
LOGD("!!! Generate Key from PWD !!!");
+ LOGD("Alg: %x", param[0].value.a);
ret = KM_ExecCmdGenerateKeyPwd(param);
break;
}
case CMD_ENCRYPT:
case CMD_DECRYPT: {
LOGD("!!! %scrypt !!!", (commandID == CMD_ENCRYPT) ? "En" : "De");
+ LOGD("Alg: %x", param[0].value.a);
if (ALGO_AES_CTR != param[0].value.a &&
ALGO_AES_CBC != param[0].value.a &&