return ret;
}
+
+TEE_Result KM_ExecCmdWrapConcatenatedData(TEE_Param param[4])
+{
+ TEE_Result ret = TEE_SUCCESS;
+ TEE_ObjectHandle wkey = TEE_HANDLE_NULL;
+ TEE_ObjectInfo wkey_info;
+
+ KM_BinaryData wkey_id = {0, NULL}; // wkey = wrapping key
+ KM_BinaryData ktw_id = {0, NULL}; // ktw = key to wrap
+ KM_BinaryData ktw_data = {0, NULL};
+ KM_BinaryData wrapped_key = {0, NULL};
+ KM_BinaryData user_data = {0, NULL};
+ KM_BinaryData concatenated = {0, NULL};
+ KM_PwdData wkey_pwd_data;
+ KM_PwdData ktw_pwd_data;
+ uint32_t with_wkey_pwd = 0;
+ uint32_t with_ktw_pwd = 0;
+ uint32_t algo = 0;
+ uint32_t tee_enc_mode = TEE_MODE_ENCRYPT;
+ uint32_t oaep_hash = HASH_SHA1;
+
+ 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;
+
+ // Deserialize from REE buffer
+ if (KM_DeserializeBinaryData(&in_buffer, &in_size_guard, &wkey_id)) {
+ LOG("Error in deserialization");
+ return TEE_ERROR_BAD_PARAMETERS;
+ }
+
+ ret = KM_DeserializeFlagAndPw(&in_buffer, &in_size_guard, &with_wkey_pwd, &wkey_pwd_data);
+ if (ret != TEE_SUCCESS) {
+ LOG("Error in deserialization");
+ return TEE_ERROR_BAD_PARAMETERS;
+ }
+
+ if (KM_DeserializeFlag(&in_buffer, &in_size_guard, &algo)) {
+ LOG("Failed to deserialize algo flag");
+ return TEE_ERROR_BAD_PARAMETERS;
+ }
+
+ if (algo == ALGO_RSA) {
+ if (KM_DeserializeFlag(&in_buffer, &in_size_guard, &oaep_hash)) {
+ LOG("Failed to deserialize oaep_hash flag");
+ return TEE_ERROR_BAD_PARAMETERS;
+ }
+ } else {
+ return TEE_ERROR_BAD_PARAMETERS;
+ }
+
+ if (KM_DeserializeBinaryData(&in_buffer, &in_size_guard, &ktw_id)) {
+ LOG("Error in deserialization");
+ return TEE_ERROR_BAD_PARAMETERS;
+ }
+
+ ret = KM_DeserializeFlagAndPw(&in_buffer, &in_size_guard, &with_ktw_pwd, &ktw_pwd_data);
+ if (ret != TEE_SUCCESS) {
+ LOG("Error in deserialization");
+ return TEE_ERROR_BAD_PARAMETERS;
+ }
+
+ if (KM_DeserializeBinaryData(&in_buffer, &in_size_guard, &user_data)) {
+ LOG("Error in deserialization");
+ return TEE_ERROR_BAD_PARAMETERS;
+ }
+
+ // Get Wrapping Key Handle
+ ret = KM_GetWrappingKeyHandle(&wkey_id, algo, with_wkey_pwd, &wkey_pwd_data, &wkey);
+ if (ret != TEE_SUCCESS) {
+ LOG("Error in KM_OpenKey()");
+ goto clean;
+ }
+ TEE_GetObjectInfo(wkey, &wkey_info);
+
+ if (!KM_CheckAlgoKeyType(KM_Algo2TeeAlgoWithHash(algo, oaep_hash), wkey_info.objectType) ) {
+ LOG("Invalid algo & objectType. algo=%x,objectType=%x", KM_Algo2TeeAlgo(algo), wkey_info.objectType);
+ ret = TEE_ERROR_BAD_PARAMETERS;
+ goto clean;
+ }
+
+ ret = KM_GetSecretValue(&ktw_id, &ktw_data, with_ktw_pwd, &ktw_pwd_data);
+ if (TEE_SUCCESS != ret) {
+ LOG("Failed to get TEE_ATTR_SECRET_VALUE from key to wrap.");
+ goto clean;
+ }
+
+ // Concatenate key|data
+ concatenated.data_size = ktw_data.data_size + user_data.data_size;
+ concatenated.data = TEE_Malloc(concatenated.data_size, 0);
+ if (concatenated.data == NULL) {
+ LOG("Failed to allocate buffer");
+ ret = TEE_ERROR_OUT_OF_MEMORY;
+ goto clean;
+ }
+ memcpy(concatenated.data, ktw_data.data, ktw_data.data_size);
+ memcpy(concatenated.data + ktw_data.data_size, user_data.data, user_data.data_size);
+
+ // Do wrapping
+ // Get Wrapping Key. The Wrapping Key can be RSA Public Key.
+ ret = KM_DoCipherWrappedKeyWithRsa(wkey, algo, tee_enc_mode, oaep_hash, &concatenated, &wrapped_key);
+ if (TEE_SUCCESS != ret) {
+ LOG("Failed to encrypt a key for wrapping. ret=%x", ret);
+ goto clean;
+ }
+
+ // Serialize to REE buffer
+ if (KM_Serialize(&out_buffer, &out_size_guard, wrapped_key.data, wrapped_key.data_size)) {
+ LOG("Error in serialization");
+ ret = TEE_ERROR_BAD_PARAMETERS;
+ goto clean;
+ }
+
+clean:
+ TEE_CloseObject(wkey);
+ TEE_Free(wrapped_key.data);
+ TEE_Free(ktw_data.data);
+ TEE_Free(concatenated.data);
+ return ret;
+}
+
+TEE_Result KM_ExecCmdUnwrapConcatenatedData(TEE_Param param[4])
+{
+ TEE_Result ret = TEE_SUCCESS;
+ TEE_ObjectHandle wkey = TEE_HANDLE_NULL;
+ TEE_ObjectHandle key = TEE_HANDLE_NULL;
+ TEE_ObjectInfo wkey_info;
+
+ KM_BinaryData wkey_id = {0, NULL}; // wkey = wrapping key
+ KM_BinaryData enc_key = {0, NULL};
+ KM_BinaryData ekey_id = {0, NULL}; // ekey = enc key
+ KM_BinaryData ekey_data = {0, NULL};
+ KM_BinaryData ekey_data_enc = {0, NULL};
+ KM_BinaryData tag = {0, NULL};
+ KM_BinaryData skey = {0, NULL};
+ KM_BinaryData user_data = {0, NULL};
+ KM_PwdData wkey_pwd_data;
+ KM_PwdData ekey_pwd_data;
+ uint32_t with_wkey_pwd = 0;
+ uint32_t with_ekey_pwd = 0;
+ uint32_t algo = 0;
+ uint32_t enc_key_type = 0;
+ uint32_t tee_enc_key_type = 0;
+ uint32_t tee_enc_mode = TEE_MODE_DECRYPT;
+ uint32_t oaep_hash = HASH_SHA1;
+ uint32_t key_size = 0;
+
+ 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;
+
+ // Deserialize from REE buffer
+ if (KM_DeserializeBinaryData(&in_buffer, &in_size_guard, &wkey_id)) {
+ LOG("Error in deserialization");
+ return TEE_ERROR_BAD_PARAMETERS;
+ }
+
+ ret = KM_DeserializeFlagAndPw(&in_buffer, &in_size_guard, &with_wkey_pwd, &wkey_pwd_data);
+ if (ret != TEE_SUCCESS) {
+ LOG("Error in deserialization");
+ return TEE_ERROR_BAD_PARAMETERS;
+ }
+
+ if (KM_DeserializeFlag(&in_buffer, &in_size_guard, &algo)) {
+ LOG("Failed to deserialize algo flag");
+ return TEE_ERROR_BAD_PARAMETERS;
+ }
+
+ if (algo == ALGO_RSA) {
+ if (KM_DeserializeFlag(&in_buffer, &in_size_guard, &oaep_hash)) {
+ LOG("Failed to deserialize oaep_hash flag");
+ return TEE_ERROR_BAD_PARAMETERS;
+ }
+ } else {
+ return TEE_ERROR_BAD_PARAMETERS;
+ }
+
+ if (KM_DeserializeFlag(&in_buffer, &in_size_guard, &enc_key_type)) {
+ LOG("Failed to deserialize key type flag");
+ return TEE_ERROR_BAD_PARAMETERS;
+ }
+
+ if (KM_DeserializeBinaryData(&in_buffer, &in_size_guard, &enc_key)) {
+ LOG("Error in deserialization");
+ return TEE_ERROR_BAD_PARAMETERS;
+ }
+
+ ret = KM_DeserializeFlagAndPw(&in_buffer, &in_size_guard, &with_ekey_pwd, &ekey_pwd_data);
+ if (ret != TEE_SUCCESS) {
+ LOG("Error in deserialization");
+ return TEE_ERROR_BAD_PARAMETERS;
+ }
+
+ if (KM_DeserializeBinaryData(&in_buffer, &in_size_guard, &ekey_id)) {
+ LOG("Error in deserialization");
+ return TEE_ERROR_BAD_PARAMETERS;
+ }
+
+ if (KM_DeserializeFlag(&in_buffer, &in_size_guard, &key_size)) {
+ LOG("Failed to deserialize key_size flag");
+ return TEE_ERROR_BAD_PARAMETERS;
+ }
+
+ // Parameter Check:
+ // For now, only TYPE_SKEY is allowed. And the TYPE_SKEY is trasnalted into TEE_TYPE_AES
+ if (enc_key_type != TYPE_SKEY) {
+ LOG("Unsupported Key Type. Only TYPE_SKEY is supported. Key Type = %d", enc_key_type);
+ return TEE_ERROR_BAD_PARAMETERS;
+ }
+ tee_enc_key_type = TEE_TYPE_AES;
+
+ // Get Wrapping Key Handle
+ ret = KM_GetWrappingKeyHandle(&wkey_id, algo, with_wkey_pwd, &wkey_pwd_data, &wkey);
+ if (ret != TEE_SUCCESS) {
+ LOG("Error in KM_OpenKey()");
+ goto clean;
+ }
+ TEE_GetObjectInfo(wkey, &wkey_info);
+
+ if (!KM_CheckAlgoKeyType(KM_Algo2TeeAlgoWithHash(algo, oaep_hash), wkey_info.objectType) ) {
+ LOG("Invalid algo & objectType. algo=%x,objectType=%x", KM_Algo2TeeAlgo(algo), wkey_info.objectType);
+ ret = TEE_ERROR_BAD_PARAMETERS;
+ goto clean;
+ }
+
+ // Do unwrapping
+ ret = KM_DoCipherWrappedKeyWithRsa(wkey, algo, tee_enc_mode, oaep_hash, &enc_key, &ekey_data);
+ if (TEE_SUCCESS != ret) {
+ LOG("Failed to decrypt a key for unwrapping. ret=%x", ret);
+ goto clean;
+ }
+
+ // Split key|data
+ skey.data_size = key_size/8;
+ skey.data = TEE_Malloc(skey.data_size, 0);
+ if (skey.data == NULL) {
+ LOG("Failed to allocate buffer");
+ ret = TEE_ERROR_OUT_OF_MEMORY;
+ goto clean;
+ }
+ memcpy(skey.data, ekey_data.data, skey.data_size);
+
+ user_data.data_size = ekey_data.data_size - skey.data_size;
+ user_data.data = TEE_Malloc(user_data.data_size, 0);
+ if (user_data.data == NULL) {
+ LOG("Failed to allocate buffer");
+ ret = TEE_ERROR_OUT_OF_MEMORY;
+ goto clean;
+ }
+ memcpy(user_data.data, ekey_data.data + skey.data_size, user_data.data_size);
+
+ // Serialize to REE buffer.
+ if (KM_Serialize(&out_buffer, &out_size_guard, user_data.data, user_data.data_size)) {
+ LOG("Error in serialization");
+ ret = TEE_ERROR_BAD_PARAMETERS;
+ goto clean;
+ }
+
+ // Encrypt & Save
+ if (with_ekey_pwd) {
+ ret = KM_EncryptBinary(&ekey_pwd_data, &skey, &ekey_data_enc, &tag);
+ if (TEE_SUCCESS != ret) {
+ LOG("Failed to encrypt new key");
+ goto clean;
+ }
+ // Serialize to REE buffer. If needed, also the tag ID
+ if (KM_Serialize(&out_buffer, &out_size_guard, tag.data, tag.data_size)) {
+ LOG("Error in serialization");
+ ret = TEE_ERROR_BAD_PARAMETERS;
+ }
+ ret = KM_CreateKey(tee_enc_key_type, ekey_data_enc.data_size * 8, ekey_data_enc.data, &key);
+ } else {
+ ret = KM_CreateKey(tee_enc_key_type, skey.data_size * 8, skey.data, &key);
+ }
+ if (ret != TEE_SUCCESS) {
+ if (ret == TEE_ERROR_NOT_SUPPORTED)
+ ret = TEE_ERROR_BAD_PARAMETERS;
+ LOG("Failed to create key");
+ goto clean;
+ }
+
+ ret = KM_SaveKey(NULL, 0, key, ekey_id.data, ekey_id.data_size);
+ if (TEE_SUCCESS != ret) {
+ LOG("Failed to save generated key");
+ goto clean;
+ }
+
+clean:
+ TEE_CloseObject(wkey);
+ TEE_CloseObject(key);
+ TEE_Free(tag.data);
+ TEE_Free(ekey_data.data);
+ TEE_Free(ekey_data_enc.data);
+ TEE_Free(skey.data);
+ TEE_Free(user_data.data);
+ return ret;
+}