/*
* Copyright (c) 2016 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
*/
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
namespace Tizen.Security.TEEC
{
///
/// This type denotes the Session Login Method used in OpenSession.
///
/// 3
public class LoginMethod
{
/// No login data is provided.
public const uint Public = 0x00000000;
/// Login data about the user running the client application process is provided.
public const uint User = 0x00000001;
/// Login data about the group running the client application process is provided.
public const uint Group = 0x00000002;
/// Login data about the running client application itself is provided.
public const uint Application = 0x00000003;
}
///
/// This type denotes the Value parameter.
///
/// 3
public enum TEFValueType : UInt32
{
/// The parameter is a ValueType tagged as the input.
Input = 0x00000001,
/// The parameter is a ValueType tagged as the output.
Output = 0x00000002,
/// The parameter is a ValueType tagged as both the input and the output.
InOut = 0x00000003,
}
///
/// This type denotes the TempMemoryReference parameter
/// describing a region of memory which needs to be temporarily registered for the duration of the operation.
///
/// 3
public enum TEFTempMemoryType : UInt32
{
/// The parameter is a TempMemoryType and is tagged as the input.
Input = 0x00000005,
/// Same as the input, but the Memory Reference is tagged as the output.
Output = 0x00000006,
/// A Temporary Memory Reference tagged as both the input and the output.
InOut = 0x00000007,
}
///
/// This type denotes the SharedMemoryReference parameter.
///
/// 3
public enum TEFRegisteredMemoryType : UInt32
{
/// The parameter is a registered memory reference that refers to the entirety of its parent shared memory block.
Whole = 0x0000000C,
/// A registered memory reference structure that refers to a partial region of its parent shared mMemory block and is tagged as the input.
PartialInput = 0x0000000D,
/// A registered memory reference structure that refers to a partial region of its parent shared memory block and is tagged as the output.
PartialOutput = 0x0000000E,
/// A registered memory reference structure that refers to a partial region of its parent shared memory block and is tagged as both the input and the output.
PartialInOut = 0x0000000F,
}
///
/// This type denotes the SharedMemory access direction.
///
/// 3
[Flags]
public enum SharedMemoryFlags : UInt32
{
/// A flag indicates the shared memory can be read.
Input = 0x00000001,
/// A flag indicates the shared memory can be written.
Output = 0x00000002,
/// A flag indicates the shared memory can be read and written.
InOut = Input | Output,
}
///
/// This type denotes a shared memory block which has been either registered
/// with the implementation or allocated by it.
///
/// 3
public sealed class SharedMemory
{
internal Interop.TEEC_SharedMemory shm;
internal SharedMemory(Interop.TEEC_SharedMemory shm)
{
this.shm=shm;
}
///
/// This property represents the shared memory size in bytes.
///
/// 3
public UInt32 Size
{
get { return shm.size; }
}
///
/// This property represents the start address of the shared memory block.
///
/// 3
public IntPtr Address
{
get { return shm.buffer; }
}
///
/// This function makes a copy and is designed for convenient operations on small buffers.
/// For large buffers, the direct address should be used.
///
/// 3
/// The source data buffer to copy data from.
/// The starting offset in the destination shared memory.
/// The operation is invalid.
public void SetData(byte[] data, int dstOffs)
{
if ((shm.flags & (uint)SharedMemoryFlags.Output) == 0) throw new InvalidOperationException("No write access");
Marshal.Copy(data, 0, shm.buffer + dstOffs, data.Length);
}
///
/// This function makes a copy and is designed for convenient operations on small buffers.
/// For large buffers, the direct address should be used.
///
/// 3
/// The destination data buffer to copy data into.
/// The starting offset in the source shared memory.
/// The operation is invalid.
public void GetData(byte[] data, int srcOffs)
{
if ((shm.flags & (uint)SharedMemoryFlags.Input) == 0) throw new InvalidOperationException("No read access");
Marshal.Copy(shm.buffer + srcOffs, data, 0, data.Length);
}
};
///
/// This type defines the payload of either an open session operation or an invoke command operation. It is
/// also used for cancelation of operations, which may be desirable even if no payload is passed.
/// Parameters are used to exchange data between CA and TA.
///
/// 3
public abstract class Parameter
{
internal Parameter(uint t)
{
this.NativeType = t;
}
internal uint NativeType { get; }
};
///
/// This type defines a template for the parameter types.
///
/// 3
public abstract class BaseParameter : Parameter where TEnum : struct, IComparable, IFormattable, IConvertible // as close to Enum as possible
{
internal BaseParameter(TEnum t) : base((uint)(object)t)
{
Type = t;
}
///
/// This property represents the access type to this parameter.
///
/// 3
public TEnum Type { get; }
}
///
/// This type defines a temporary memory reference.
///
/// 3
public sealed class TempMemoryReference : BaseParameter
{
///
/// Constructs a parameter object which holds information about the temporary memory copied to or from TA.
///
/// 3
/// The address of the allocated memory buffer.
/// The size of the buffer.
/// The kind of access allowed for TA .
public TempMemoryReference(IntPtr buffer, uint size, TEFTempMemoryType type) :
base(type)
{
this.Buffer = buffer;
this.Size = size;
}
///
/// This property represents the memory address of the buffer.
///
/// 3
public IntPtr Buffer { get; }
///
/// This property represents the size of the buffer.
///
/// 3
public uint Size { get; }
};
///
/// This type defines a memory reference that uses a pre-registered or pre-allocated shared memory block.
///
/// 3
public sealed class RegisteredMemoryReference : BaseParameter
{
///
/// Constructs a parameter object which holds information about the registered memory shared with TA.
///
/// 3
/// The shared memory - registered or allocated.
/// The size of the buffer part.
/// The offset of the buffer in the shared memory.
/// The kind of access allowed for TA .
public RegisteredMemoryReference(SharedMemory parent, uint size, uint offset, TEFRegisteredMemoryType type) :
base(type)
{
this.Parent = parent;
this.Size = size;
this.Offset = offset;
}
///
/// This property represents the shared memory that is referred to.
///
/// 3
public SharedMemory Parent { get; }
///
/// This property represents the size (in bytes) of the shared memory.
///
/// 3
public uint Size { get; }
///
/// This property represents the offset (in bytes) from the start of the shared memory.
///
/// 3
public uint Offset { get; }
};
///
/// This type defines a parameter that is not referencing the shared memory, but carries instead small raw data
/// passed by a value.
///
/// 3
public sealed class Value : BaseParameter
{
///
/// Constructs a parameter object which holds information about integer values copied to or from TA.
///
/// 3
/// User paramter A.
/// User paramter B.
/// The kind of access allowed for TA .
public Value(uint a, uint b, TEFValueType type) :
base(type)
{
this.A = a;
this.B = b;
}
///
/// This property represents an unsigned integer A.
///
/// 3
public uint A { get; }
///
/// This property represents an unsigned integer B.
///
/// 3
public uint B { get; }
};
///
/// This type denotes a TEE Session, the logical container linking a client application with a particular trusted application.
///
/// 3
public sealed class Session
{
private Interop.TEEC_Context context;
private Interop.TEEC_Session session;
internal Session(Interop.TEEC_Context context) {
this.context = context;
this.session = new Interop.TEEC_Session();
}
~Session()
{
Close();
}
internal void Open(Guid destination, uint loginMethod, byte[] connectionData, Parameter[] paramlist)
{
Interop.TEEC_UUID uuid = Interop.TEEC_UUID.ToTeecUuid(destination);
Interop.TEEC_Operation op = new Interop.TEEC_Operation();
uint ro;
int ret = Interop.Libteec.OpenSession(ref context, ref session, ref uuid, loginMethod, connectionData, ref op, out ro);
//MAYBE map origin of return code to specyfic Exception
Interop.CheckNThrowException(ret, string.Format("OpenSession('{0}')", destination));
}
///
/// This function closes a session which has been opened with a trusted application.
/// All commands within the session must be completed before this function can be called.
///
/// 3
/// http://tizen.org/privilege/tee.client
/// partner
/// http://tizen.org/feature/security.tee
/// Thrown when an application does not have the privilege to access this method.
/// The required feature is not supported.
/// The operation is invalid.
public void Close() {
Interop.Libteec.CloseSession(ref session);
//session = null;
}
///
/// This function invokes a command within the specified session.
/// The parameter commandID is an identifier that is used to indicate which of the exposed trusted
/// application functions should be invoked. The supported command identifier values are defined by the
/// trusted application's protocol.
/// There can be up to four parameter objects given in the array.
///
/// 3
/// The command.
/// The array of parameters.
/// http://tizen.org/privilege/tee.client
/// partner
/// http://tizen.org/feature/security.tee
/// Thrown when an application does not have the privilege to access this method.
/// The required feature is not supported.
/// The operation is invalid.
/// The argument is wrong.
public void InvokeCommand(uint commandID, Parameter[] paramlist)
{
Interop.TEEC_Operation op = new Interop.TEEC_Operation();
op.started=0;
op.paramTypes=0;
for (int i=0; i < 4; ++i) {
Parameter p = paramlist[i];
//TODO fill TEEC_Operation struct
}
uint ro;
int ret = Interop.Libteec.InvokeCommand(ref session, commandID, ref op, out ro);
//MAYBE map origin of return code to specific Exception
Interop.CheckNThrowException(ret, string.Format("InvokeCommand({0})", commandID));
}
///
/// The asynchronous version of the InvokeCommand.
///
/// 3
/// The command.
/// The array of parameters.
/// The token for task manipulation.
/// Returns a task executing an invoke command in the background.
/// http://tizen.org/privilege/tee.client
/// partner
/// http://tizen.org/feature/security.tee
/// Thrown when an application does not have the privilege to access this method.
/// The required feature is not supported.
/// The operation is invalid.
/// One of the arguments is wrong.
public async Task InvokeCommandAsync(uint commandID, Parameter[] paramlist, CancellationToken token = default(CancellationToken))
{
await Task.Factory.StartNew(() => InvokeCommand(commandID, paramlist));
}
};
///
/// This type denotes a TEE Context, the main logical container linking a Client Application with a particular TEE.
///
/// 3
public sealed class Context : IDisposable
{
private Interop.TEEC_Context context;
///
/// This function (constructor) initializes a new TEE Context, forming a connection between this client application and the
/// TEE identified by the string identifier name (empty or null name denotes a default TEE).
///
/// 3
/// The TEE name.
/// http://tizen.org/privilege/tee.client
/// partner
/// http://tizen.org/feature/security.tee
/// Thrown when an application does not have the privilege to access this method.
/// The required feature is not supported.
/// The operation is invalid.
public Context(string name)
{
context = new Interop.TEEC_Context();
if (name != null && name.Length == 0)
name = null;
int ret = Interop.Libteec.InitializeContext(name, ref context);
Interop.CheckNThrowException(ret, string.Format("InititalizeContext('{0}')", name));
}
~Context()
{
Dispose();
}
///
/// This function implements the IDisposable interface.
///
/// 3
/// http://tizen.org/privilege/tee.client
/// partner
/// http://tizen.org/feature/security.tee
public void Dispose() {
Interop.Libteec.FinalizeContext(ref context);
//context.imp = null;
}
///
/// This function opens a new session between the client application and the specified trusted application.
/// The target trusted application is identified by an UUID passed in the parameter destination.
/// There can be up to four parameter objects given in the array.
///
/// 3
/// The UUID of the destination TA.
/// The authentication algorithm .
/// The data to be verified by a given login method.
/// The parameters to be passed to TA open-session-callback.
/// Returns opened session.
/// http://tizen.org/privilege/tee.client
/// partner
/// http://tizen.org/feature/security.tee
/// Thrown when an application does not have the privilege to access this method.
/// The required feature is not supported.
/// The operation is invalid.
/// One of the arguments is wrong.
public Session OpenSession(Guid destination, uint loginMethod, byte[] connectionData, Parameter[] paramlist)
{
Session ses = new Session(context);
ses.Open(destination, loginMethod, connectionData, paramlist);
return ses;
}
///
/// @see OpenSession (Guid destination, uint connectionMethod, byte[] connectionData, Parameter[] paramlist, CancellationToken token).
///
/// 3
/// The UUID of the destination TA.
/// Returns opened session.
/// http://tizen.org/privilege/tee.client
/// partner
/// http://tizen.org/feature/security.tee
/// Thrown when an application does not have the privilege to access this method.
/// The required feature is not supported.
/// The operation is invalid.
public Session OpenSession(Guid destination)
{
Session ses = new Session(context);
ses.Open(destination, LoginMethod.Public, null, null);
return ses;
}
///
/// The asynchronous version of the OpenSession.
/// @see OpenSession (Guid destination, uint connectionMethod, byte[] connectionData, Parameter[] paramlist, CancellationToken token).
///
/// 3
/// The UUID of the destination TA.
/// The authentication algorithm .
/// The data to be verified by a given login method.
/// The parameters to be passed to the TA open-session-callback.
/// The token for the task manipulation.
/// Returns a Task executing the session open in the background.
/// http://tizen.org/privilege/tee.client
/// partner
/// http://tizen.org/feature/security.tee
/// Thrown when an application does not have the privilege to access this method.
/// The required feature is not supported.
/// The operation is invalid.
/// One of the arguments is wrong.
public async Task OpenSessionAsync(Guid destination, uint loginMethod, byte[] connectionData, Parameter[] paramlist, CancellationToken token = default(CancellationToken))
{
Task task = Task.Factory.StartNew(() =>
{
return OpenSession(destination, loginMethod, connectionData, paramlist);
});
return await task;
}
///
/// The asynchronous version of the OpenSession.
/// @see OpenSession (Guid destination, uint connectionMethod, byte[] connectionData, Parameter[] paramlist, CancellationToken token).
///
/// 3
/// The UUID of the destination TA.
/// The token for a task manipulation.
/// Returns a task executing session open in the background.
/// http://tizen.org/privilege/tee.client
/// partner
/// http://tizen.org/feature/security.tee
/// Thrown when an application does not have the privilege to access this method.
/// The required feature is not supported.
/// The operation is invalid.
public async Task OpenSessionAsync(Guid destination, CancellationToken token = default(CancellationToken))
{
Task task = Task.Factory.StartNew(() =>
{
return OpenSession(destination);
});
return await task;
}
///
/// This function registers a block of the existing client application memory as a block of shared memory within
/// the scope of the specified context, in accordance with the parameters.
/// The input must point to the shared memory region to register.
///
/// 3
/// The address of the shared memory.
/// The size of the shared memory.
/// The flags describing the access modes (Input and/or Output).
/// Returns the SharedMemory handler.
/// http://tizen.org/privilege/tee.client
/// partner
/// http://tizen.org/feature/security.tee
/// Thrown when an application does not have the privilege to access this method.
/// The required feature is not supported.
/// The operation is invalid.
/// The argument is wrong.
public SharedMemory RegisterSharedMemory(IntPtr memaddr, UInt32 size, SharedMemoryFlags flags)
{
Interop.TEEC_SharedMemory shm = new Interop.TEEC_SharedMemory();
shm.buffer = memaddr;
shm.size = size;
shm.flags = (UInt32)flags;
int ret = Interop.Libteec.RegisterSharedMemory(ref context, ref shm);
Interop.CheckNThrowException(ret, "RegisterSharedMemory");
return new SharedMemory(shm);
}
///
/// This function allocates a new block of memory as a block of shared memory within the scope of the
/// specified context, in accordance with the parameters.
///
/// 3
/// The size of shared memory.
/// The flags describing access modes (Input and/or Output).
/// Returns the Shared Memory handler.
/// http://tizen.org/privilege/tee.client
/// partner
/// http://tizen.org/feature/security.tee
/// Thrown when an application does not have the privilege to access this method.
/// The required feature is not supported.
/// The operation is invalid.
public SharedMemory AllocateSharedMemory(UInt32 size, SharedMemoryFlags flags)
{
Interop.TEEC_SharedMemory shm = new Interop.TEEC_SharedMemory();
shm.size = size;
shm.flags = (UInt32)flags;
int ret = Interop.Libteec.AllocateSharedMemory(ref context, ref shm);
Interop.CheckNThrowException(ret, "AllocateSharedMemory");
return new SharedMemory(shm);
}
///
/// This function deregisters or deallocates a previously initialized block of the shared memory.
///
///
/// For a memory buffer allocated using AllocateSharedMemory, the implementation must free the
/// underlying memory and the client application must not access this region after this function has been
/// called. In this case, the implementation must clear the buffer and size fields of the shared memory
/// structure before returning.
/// For memory registered using RegisterSharedMemory, the implementation must deregister the
/// underlying memory from the TEE, but the memory region will stay available to the client application for
/// other purposes as the memory is owned by it.
///
/// 3
/// The shared memory object returned by RegisterSharedMemory or AllocateSharedMemory.
/// http://tizen.org/privilege/tee.client
/// partner
/// http://tizen.org/feature/security.tee
/// Thrown when an application does not have the privilege to access this method.
/// The required feature is not supported.
/// The operation is invalid.
/// The argument is wrong.
public void ReleaseSharedMemory(SharedMemory shm)
{
Interop.Libteec.ReleaseSharedMemory(ref shm.shm);
}
};
}