ad93795072fb5542ee856531baffea42acb2966f
[platform/core/csapi/tizenfx.git] / src / Tizen.Security.TEEC / Tizen.Security.TEEC / Libteec.cs
1 /*
2  *  Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  *  Licensed under the Apache License, Version 2.0 (the "License");
5  *  you may not use this file except in compliance with the License.
6  *  You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  *  Unless required by applicable law or agreed to in writing, software
11  *  distributed under the License is distributed on an "AS IS" BASIS,
12  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  *  See the License for the specific language governing permissions and
14  *  limitations under the License
15  */
16
17 using System;
18 using System.Collections.Generic;
19 using System.Runtime.InteropServices;
20 using System.Threading;
21 using System.Threading.Tasks;
22 using System.Runtime.CompilerServices;
23 using System.IO;
24
25 namespace Tizen.Security.TEEC
26 {
27     /// <summary>
28     /// This type denotes the Session Login Method used in OpenSession.
29     /// </summary>
30     /// <since_tizen> 3 </since_tizen>
31     public class LoginMethod
32     {
33         /// <summary>No login data is provided.</summary>
34         /// <since_tizen> 3 </since_tizen>
35         public const uint Public      = 0x00000000;
36         /// <summary>Login data about the user running the client application process is provided.</summary>
37         /// <since_tizen> 3 </since_tizen>
38         public const uint User        = 0x00000001;
39         /// <summary>Login data about the group running the client application process is provided.</summary>
40         /// <since_tizen> 3 </since_tizen>
41         public const uint Group       = 0x00000002;
42         /// <summary>Login data about the running client application itself is provided.</summary>
43         /// <since_tizen> 3 </since_tizen>
44         public const uint Application = 0x00000003;
45     }
46
47     /// <summary>
48     /// This type denotes the Value parameter.
49     /// </summary>
50     /// <since_tizen> 3 </since_tizen>
51     public enum TEFValueType : UInt32
52     {
53         /// <summary>The parameter is a ValueType tagged as the input.</summary>
54         Input  = 0x00000001,
55         /// <summary>The parameter is a ValueType tagged as the output.</summary>
56         Output = 0x00000002,
57         /// <summary>The parameter is a ValueType tagged as both the input and the output.</summary>
58         InOut  = 0x00000003,
59     }
60
61     /// <summary>
62     /// This type denotes the TempMemoryReference parameter
63     /// describing a region of memory which needs to be temporarily registered for the duration of the operation.
64     /// </summary>
65     /// <since_tizen> 3 </since_tizen>
66     public enum TEFTempMemoryType : UInt32
67     {
68         /// <summary>The parameter is a TempMemoryType and is tagged as the input.</summary>
69         Input  = 0x00000005,
70         /// <summary>Same as the input, but the Memory Reference is tagged as the output.</summary>
71         Output = 0x00000006,
72         /// <summary>A Temporary Memory Reference tagged as both the input and the output.</summary>
73         InOut  = 0x00000007,
74     }
75
76     /// <summary>
77     /// This type denotes the SharedMemoryReference parameter.
78     /// </summary>
79     /// <since_tizen> 3 </since_tizen>
80     public enum TEFRegisteredMemoryType : UInt32
81     {
82         /// <summary>The parameter is a registered memory reference that refers to the entirety of its parent shared memory block.</summary>
83         Whole         = 0x0000000C,
84         /// <summary>A registered memory reference structure that refers to a partial region of its parent shared mMemory block and is tagged as the input.</summary>
85         PartialInput  = 0x0000000D,
86         /// <summary>A registered memory reference structure that refers to a partial region of its parent shared memory block and is tagged as the output.</summary>
87         PartialOutput = 0x0000000E,
88         /// <summary>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.</summary>
89         PartialInOut  = 0x0000000F,
90     }
91
92     /// <summary>
93     /// This type denotes the SharedMemory access direction.
94     /// </summary>
95     /// <since_tizen> 3 </since_tizen>
96     [Flags]
97     public enum SharedMemoryFlags : UInt32
98     {
99         /// <summary>A flag indicates the shared memory can be read.</summary>
100         Input  = 0x00000001,
101         /// <summary>A flag indicates the shared memory can be written.</summary>
102         Output = 0x00000002,
103         /// <summary>A flag indicates the shared memory can be read and written.</summary>
104         InOut = Input | Output,
105     }
106
107     /// <summary>
108     /// This type denotes a shared memory block which has been either registered
109     /// with the implementation or allocated by it.
110     /// </summary>
111     /// <since_tizen> 3 </since_tizen>
112     public sealed class SharedMemory
113     {
114         internal Interop.TEEC_SharedMemory shm;
115         internal IntPtr shmptr;
116         internal SharedMemory(ref Interop.TEEC_SharedMemory shm)
117         {
118             this.shm=shm;
119             shmptr = Marshal.AllocHGlobal(Marshal.SizeOf(shm));
120             Marshal.StructureToPtr(shm, shmptr, false);
121         }
122         ~SharedMemory()
123         {
124             Marshal.FreeHGlobal(shmptr);
125         }
126         /// <summary>
127         /// This property represents the shared memory size in bytes.
128         /// </summary>
129         /// <since_tizen> 3 </since_tizen>
130         /// <privilege>http://tizen.org/privilege/tee.client</privilege>
131         /// <privlevel>partner</privlevel>
132         public UInt32 Size
133         {
134             get { return shm.size.ToUInt32(); }
135         }
136         /// <summary>
137         /// This property represents the start address of the shared memory block.
138         /// </summary>
139         /// <since_tizen> 3 </since_tizen>
140         /// <privilege>http://tizen.org/privilege/tee.client</privilege>
141         /// <privlevel>partner</privlevel>
142         public IntPtr Address
143         {
144             get { return shm.buffer; }
145         }
146
147         /// <summary>
148         /// This function makes a copy and is designed for convenient operations on small buffers.
149         /// For large buffers, the direct address should be used.
150         /// </summary>
151         /// <since_tizen> 3 </since_tizen>
152         /// <privilege>http://tizen.org/privilege/tee.client</privilege>
153         /// <privlevel>partner</privlevel>
154         /// <param name="data">The source data buffer to copy data from.</param>
155         /// <param name="dstOffs">The starting offset in the destination shared memory.</param>
156         /// <exception cref="InvalidOperationException">The operation is invalid.</exception>
157         public void SetData(byte[] data, int dstOffs)
158         {
159             Marshal.Copy(data, 0, shm.buffer + dstOffs, data.Length);
160         }
161         /// <summary>
162         /// This function makes a copy and is designed for convenient operations on small buffers.
163         /// For large buffers, the direct address should be used.
164         /// </summary>
165         /// <since_tizen> 3 </since_tizen>
166         /// <privilege>http://tizen.org/privilege/tee.client</privilege>
167         /// <privlevel>partner</privlevel>
168         /// <param name="data">The destination data buffer to copy data into.</param>
169         /// <param name="srcOffs">The starting offset in the source shared memory.</param>
170         /// <exception cref="InvalidOperationException">The operation is invalid.</exception>
171         public void GetData(byte[] data, int srcOffs)
172         {
173             Marshal.Copy(shm.buffer + srcOffs, data, 0, data.Length);
174         }
175     };
176
177     /// <summary>
178     /// This type defines the payload of either an open session operation or an invoke command operation. It is
179     /// also used for cancelation of operations, which may be desirable even if no payload is passed.
180     /// Parameters are used to exchange data between CA and TA.
181     /// </summary>
182     /// <since_tizen> 3 </since_tizen>
183     public abstract class Parameter
184     {
185         internal Parameter(uint t)
186         {
187             this.NativeType = t;
188         }
189         internal uint NativeType { get; }
190     };
191
192     /// <summary>
193     /// This type defines a template for the parameter types.
194     /// </summary>
195     /// <since_tizen> 3 </since_tizen>
196     public abstract class BaseParameter<TEnum> : Parameter where TEnum : struct, IComparable, IFormattable, IConvertible // as close to Enum as possible
197     {
198         internal BaseParameter(TEnum t) : base((uint)(object)t)
199         {
200             Type = t;
201         }
202
203         /// <summary>
204         /// This property represents the access type to this parameter.
205         /// </summary>
206         /// <since_tizen> 3 </since_tizen>
207         public TEnum Type { get; }
208     }
209
210     /// <summary>
211     /// This type defines a temporary memory reference.
212     /// </summary>
213     /// <since_tizen> 3 </since_tizen>
214     public sealed class TempMemoryReference : BaseParameter<TEFTempMemoryType>
215     {
216         /// <summary>
217         /// Constructs a parameter object which holds information about the temporary memory copied to or from TA.
218         /// </summary>
219         /// <since_tizen> 3 </since_tizen>
220         /// <param name="buffer">The address of the allocated memory buffer.</param>
221         /// <param name="size">The size of the buffer.</param>
222         /// <param name="type">The kind of access allowed for TA <see cref="TEFTempMemoryType"/>.</param>
223         public TempMemoryReference(IntPtr buffer, uint size, TEFTempMemoryType type) :
224                 base(type)
225         {
226             this.Buffer = buffer;
227             this.Size = size;
228         }
229         /// <summary>
230         /// This property represents the memory address of the buffer.
231         /// </summary>
232         /// <since_tizen> 3 </since_tizen>
233         public IntPtr Buffer { get; }
234         /// <summary>
235         /// This property represents the size of the buffer.
236         /// </summary>
237         /// <since_tizen> 3 </since_tizen>
238         public uint Size { get; internal set; }
239     };
240
241     /// <summary>
242     /// This type defines a memory reference that uses a pre-registered or pre-allocated shared memory block.
243     /// </summary>
244     /// <since_tizen> 3 </since_tizen>
245     public sealed class RegisteredMemoryReference : BaseParameter<TEFRegisteredMemoryType>
246     {
247         /// <summary>
248         /// Constructs a parameter object which holds information about the registered memory shared with TA.
249         /// </summary>
250         /// <since_tizen> 3 </since_tizen>
251         /// <privilege>http://tizen.org/privilege/tee.client</privilege>
252         /// <privlevel>partner</privlevel>
253         /// <param name="parent">The shared memory - registered or allocated.</param>
254         /// <param name="size">The size of the buffer part.</param>
255         /// <param name="offset">The offset of the buffer in the shared memory.</param>
256         /// <param name="type">The kind of access allowed for TA <see cref="TEFRegisteredMemoryType"/>.</param>
257         public RegisteredMemoryReference(SharedMemory parent, uint size, uint offset, TEFRegisteredMemoryType type) :
258                 base(type)
259         {
260             this.Parent = parent;
261             if (type == TEFRegisteredMemoryType.Whole) {
262                 this.Size = parent.Size;
263                 this.Offset = 0;
264             }
265             else {
266                 this.Size = size;
267                 this.Offset = offset;
268             }
269         }
270
271         /// <summary>
272         /// This property represents the shared memory that is referred to.
273         /// </summary>
274         /// <since_tizen> 3 </since_tizen>
275         /// <privilege>http://tizen.org/privilege/tee.client</privilege>
276         /// <privlevel>partner</privlevel>
277         public SharedMemory Parent { get; }
278         /// <summary>
279         /// This property represents the size (in bytes) of the shared memory.
280         /// </summary>
281         /// <since_tizen> 3 </since_tizen>
282         /// <privilege>http://tizen.org/privilege/tee.client</privilege>
283         /// <privlevel>partner</privlevel>
284         public uint Size { get; internal set; }
285         /// <summary>
286         /// This property represents the offset (in bytes) from the start of the shared memory.
287         /// </summary>
288         /// <since_tizen> 3 </since_tizen>
289         /// <privilege>http://tizen.org/privilege/tee.client</privilege>
290         /// <privlevel>partner</privlevel>
291         public uint Offset { get; }
292     };
293
294     /// <summary>
295     /// This type defines a parameter that is not referencing the shared memory, but carries instead small raw data
296     /// passed by a value.
297     /// </summary>
298     /// <since_tizen> 3 </since_tizen>
299     public sealed class Value : BaseParameter<TEFValueType>
300     {
301         /// <summary>
302         /// Constructs a parameter object which holds information about integer values copied to or from TA.
303         /// </summary>
304         /// <since_tizen> 3 </since_tizen>
305         /// <param name="a">User paramter A.</param>
306         /// <param name="b">User paramter B.</param>
307         /// <param name="type">The kind of access allowed for TA <see cref="TEFValueType"/>.</param>
308         public Value(uint a, uint b, TEFValueType type) :
309                 base(type)
310         {
311             this.A = a;
312             this.B = b;
313         }
314         /// <summary>
315         /// This property represents an unsigned integer A.
316         /// </summary>
317         /// <since_tizen> 3 </since_tizen>
318         public uint A { get; internal set; }
319         /// <summary>
320         /// This property represents an unsigned integer B.
321         /// </summary>
322         /// <since_tizen> 3 </since_tizen>
323         public uint B { get; internal set; }
324     };
325
326
327     /// <summary>
328     /// This type denotes a TEE Session, the logical container linking a client application with a particular trusted application.
329     /// </summary>
330     /// <since_tizen> 3 </since_tizen>
331     public sealed class Session : IDisposable
332     {
333         private bool disposed = false;
334         private bool opened = false;
335         private Context context;
336         private IntPtr session_imp;
337         private IntPtr opptr;
338         private SharedMemory[] shm = new SharedMemory[4];
339
340         internal Session(Context context) {
341             this.context = context;
342             this.session_imp = Marshal.AllocHGlobal(Marshal.SizeOf<Interop.TEEC_Session>());
343             this.opptr = Marshal.AllocHGlobal(Marshal.SizeOf<Interop.TEEC_Operation64>());
344             for (int i=0; i < 4; ++i) shm[i] = null;
345         }
346
347         // internal since class is sealed
348         internal void Dispose(bool disposing)
349         {
350             if (disposed) {
351                 return ;
352             }
353             if (opened) {
354                 Interop.Libteec.CloseSession(session_imp);
355                 opened = false;
356             }
357             Marshal.FreeHGlobal(this.opptr);
358             Marshal.FreeHGlobal(this.session_imp);
359             this.opptr = IntPtr.Zero;
360             this.session_imp = IntPtr.Zero;
361             disposed = true;
362         }
363
364         /// <summary>
365         /// Destructor of the class.
366         /// </summary>
367         ~Session()
368         {
369             Dispose(false);
370         }
371
372         /// <summary>
373         /// Disposable interface implememtation.
374         /// </summary>
375         public void Dispose()
376         {
377             Close();
378         }
379
380         internal UInt32 InitParam(ref Interop.TEEC_Parameter32[] dst, int i, Parameter src)
381         {
382             if (IntPtr.Size != 4) throw new Exception("wrong arch - not 32bit");
383             UInt32 rType = src.NativeType;
384             switch (src.NativeType) {
385                 case (int)TEFValueType.Input:
386                 case (int)TEFValueType.Output:
387                 case (int)TEFValueType.InOut:
388                     dst[i].value.a = ((Value)src).A;
389                     dst[i].value.b = ((Value)src).B;
390                     break;
391
392                 case (int)TEFTempMemoryType.Input:
393                 case (int)TEFTempMemoryType.Output:
394                 case (int)TEFTempMemoryType.InOut:
395                     byte[] mem = new byte[(uint)((TempMemoryReference)src).Size];
396                     Marshal.Copy(((TempMemoryReference)src).Buffer, mem, 0, mem.Length);
397                     shm[i] = context.AllocateSharedMemory((uint)mem.Length, SharedMemoryFlags.InOut);
398                     Marshal.Copy(mem, 0, shm[i].shm.buffer, mem.Length);
399                     dst[i].tmpref.size = (uint)mem.Length;
400                     dst[i].tmpref.buffer = shm[i].shm.buffer.ToInt32();
401                     break;
402
403                 case (int)TEFRegisteredMemoryType.Whole:
404                     RegisteredMemoryReference rmrw = (RegisteredMemoryReference)src;
405                     rType = ((int)TEFRegisteredMemoryType.PartialInput & (int)TEFRegisteredMemoryType.PartialOutput) | rmrw.Parent.shm.flags;
406                     dst[i].memref.parent = rmrw.Parent.shmptr.ToInt32();
407                     dst[i].memref.size = rmrw.Size;
408                     dst[i].memref.offset = rmrw.Offset;
409                     break;
410
411                 case (int)TEFRegisteredMemoryType.PartialInput:
412                 case (int)TEFRegisteredMemoryType.PartialOutput:
413                 case (int)TEFRegisteredMemoryType.PartialInOut:
414                     RegisteredMemoryReference rmr = (RegisteredMemoryReference)src;
415                     dst[i].memref.parent = rmr.Parent.shmptr.ToInt32();
416                     dst[i].memref.size = rmr.Size;
417                     dst[i].memref.offset = rmr.Offset;
418                     break;
419
420                 default: return 0;
421             }
422             return rType;
423         }
424
425         internal void UpdateParam(Interop.TEEC_Parameter32 src, ref Parameter[] dst, int i)
426         {
427             if (IntPtr.Size != 4) throw new Exception("wrong arch - not 32bit");
428             switch (dst[i].NativeType) {
429                 case (int)TEFValueType.Input:
430                 case (int)TEFValueType.Output:
431                 case (int)TEFValueType.InOut:
432                     ((Value)dst[i]).A = src.value.a;
433                     ((Value)dst[i]).B = src.value.b;
434                     break;
435
436                 case (int)TEFTempMemoryType.Input:
437                 case (int)TEFTempMemoryType.Output:
438                 case (int)TEFTempMemoryType.InOut:
439                     byte[] mem = new byte[src.tmpref.size];
440                     Marshal.Copy(shm[i].shm.buffer, mem, 0, mem.Length);
441                     Marshal.Copy(mem, 0, ((TempMemoryReference)dst[i]).Buffer, mem.Length);
442                     ((TempMemoryReference)dst[i]).Size = src.tmpref.size;
443                     break;
444
445                 case (int)TEFRegisteredMemoryType.Whole:
446                 case (int)TEFRegisteredMemoryType.PartialInput:
447                 case (int)TEFRegisteredMemoryType.PartialOutput:
448                 case (int)TEFRegisteredMemoryType.PartialInOut:
449                     ((RegisteredMemoryReference)dst[i]).Size = src.memref.size;
450                     break;
451
452                 default: break;
453             }
454         }
455
456         static internal Interop.TEEC_Operation32 Create_TEEC_Operation32() {
457             Interop.TEEC_Operation32 op = new Interop.TEEC_Operation32();
458             op.started=0;
459             op.paramTypes=0;
460             op.paramlist = new Interop.TEEC_Parameter32[4];
461             return op;
462         }
463
464         internal UInt32 InitParam(ref Interop.TEEC_Parameter64[] dst, int i, Parameter src)
465         {
466             if (IntPtr.Size != 8) throw new Exception("wrong arch - not 64bit");
467             UInt32 rType = src.NativeType;
468             switch (src.NativeType) {
469                 case (int)TEFValueType.Input:
470                 case (int)TEFValueType.Output:
471                 case (int)TEFValueType.InOut:
472                     dst[i].value.a = ((Value)src).A;
473                     dst[i].value.b = ((Value)src).B;
474                     break;
475
476                 case (int)TEFTempMemoryType.Input:
477                 case (int)TEFTempMemoryType.Output:
478                 case (int)TEFTempMemoryType.InOut:
479                     byte[] mem = new byte[(uint)((TempMemoryReference)src).Size];
480                     Marshal.Copy(((TempMemoryReference)src).Buffer, mem, 0, mem.Length);
481                     shm[i] = context.AllocateSharedMemory((uint)mem.Length, SharedMemoryFlags.InOut);
482                     Marshal.Copy(mem, 0, shm[i].shm.buffer, mem.Length);
483                     dst[i].tmpref.size = (UInt64)mem.Length;
484                     dst[i].tmpref.buffer = shm[i].shm.buffer.ToInt64();
485                     break;
486
487                 case (int)TEFRegisteredMemoryType.Whole:
488                     RegisteredMemoryReference rmrw = (RegisteredMemoryReference)src;
489                     rType = ((int)TEFRegisteredMemoryType.PartialInput & (int)TEFRegisteredMemoryType.PartialOutput) | rmrw.Parent.shm.flags;
490                     dst[i].memref.parent = rmrw.Parent.shmptr.ToInt64();
491                     dst[i].memref.size = rmrw.Size;
492                     dst[i].memref.offset = rmrw.Offset;
493                     break;
494
495                 case (int)TEFRegisteredMemoryType.PartialInput:
496                 case (int)TEFRegisteredMemoryType.PartialOutput:
497                 case (int)TEFRegisteredMemoryType.PartialInOut:
498                     RegisteredMemoryReference rmr = (RegisteredMemoryReference)src;
499                     dst[i].memref.parent = rmr.Parent.shmptr.ToInt64();
500                     dst[i].memref.size = rmr.Size;
501                     dst[i].memref.offset = rmr.Offset;
502                     break;
503
504                 default:
505                     break;
506             }
507             return rType;
508         }
509
510         internal void UpdateParam(Interop.TEEC_Parameter64 src, ref Parameter[] dst, int i)
511         {
512             if (IntPtr.Size != 8) throw new Exception("wrong arch - not 64bit");
513             switch (dst[i].NativeType) {
514                case (int)TEFValueType.Input:
515                case (int)TEFValueType.Output:
516                case (int)TEFValueType.InOut:
517                    ((Value)dst[i]).A = src.value.a;
518                    ((Value)dst[i]).B = src.value.b;
519                    break;
520
521                case (int)TEFTempMemoryType.Input:
522                case (int)TEFTempMemoryType.Output:
523                case (int)TEFTempMemoryType.InOut:
524                     byte[] mem = new byte[src.tmpref.size];
525                     Marshal.Copy(shm[i].shm.buffer, mem, 0, mem.Length);
526                     Marshal.Copy(mem, 0, ((TempMemoryReference)dst[i]).Buffer, mem.Length);
527                    ((TempMemoryReference)dst[i]).Size = (uint)src.tmpref.size;
528                    break;
529
530                case (int)TEFRegisteredMemoryType.Whole:
531                case (int)TEFRegisteredMemoryType.PartialInput:
532                case (int)TEFRegisteredMemoryType.PartialOutput:
533                case (int)TEFRegisteredMemoryType.PartialInOut:
534                    ((RegisteredMemoryReference)dst[i]).Size = (uint)src.memref.size;
535                    break;
536
537                default: break;
538             }
539         }
540
541         static internal Interop.TEEC_Operation64 Create_TEEC_Operation64() {
542             Interop.TEEC_Operation64 op = new Interop.TEEC_Operation64();
543             op.started=0;
544             op.paramTypes=0;
545             op.paramlist = new Interop.TEEC_Parameter64[4];
546             return op;
547         }
548
549         internal void Open32(Guid destination, uint loginMethod, byte[] connectionData, Parameter[] paramlist)
550         {
551             Interop.TEEC_UUID uuid = Interop.TEEC_UUID.ToTeecUuid(destination);
552
553             int ret;
554             uint ro;
555             if (paramlist != null) {
556                 Interop.TEEC_Operation32 op = Create_TEEC_Operation32();
557                 for (int i=0; i < 4 && i < paramlist.Length; ++i) {
558                     op.paramTypes |= InitParam(ref op.paramlist, i, paramlist[i]) << (8*i);
559                 }
560                 Marshal.StructureToPtr(op, opptr, false);
561                 ret = Interop.Libteec.OpenSession(context.context_imp, session_imp, ref uuid, loginMethod, connectionData, opptr, out ro);
562                 op = Marshal.PtrToStructure<Interop.TEEC_Operation32>(opptr);
563                 for (int i=0; i < 4 && i < paramlist.Length; ++i) {
564                     UpdateParam(op.paramlist[i], ref paramlist, i);
565                 }
566             }
567             else {
568                 ret = Interop.Libteec.OpenSession(context.context_imp, session_imp, ref uuid, loginMethod, connectionData, IntPtr.Zero, out ro);
569             }
570
571             for (int i=0; i < 4; ++i) {
572                 if (shm[i] != null) {
573                     context.ReleaseSharedMemory(shm[i]);
574                     shm[i] = null;
575                 }
576             }
577
578             //MAYBE map origin of return code to specyfic Exception
579             Interop.CheckNThrowException(ret, string.Format("OpenSession('{0}')", destination));
580             opened = true;
581         }
582         internal void Open64(Guid destination, uint loginMethod, byte[] connectionData, Parameter[] paramlist)
583         {
584             Interop.TEEC_UUID uuid = Interop.TEEC_UUID.ToTeecUuid(destination);
585
586             int ret;
587             uint ro;
588             if (paramlist != null) {
589                 Interop.TEEC_Operation64 op = Create_TEEC_Operation64();
590                 for (int i=0; i < 4 && i < paramlist.Length; ++i) {
591                     op.paramTypes |= InitParam(ref op.paramlist, i, paramlist[i]) << (8*i);
592                 }
593                 Marshal.StructureToPtr(op, opptr, false);
594                 ret = Interop.Libteec.OpenSession(context.context_imp, session_imp, ref uuid, loginMethod, connectionData, opptr, out ro);
595                 op = Marshal.PtrToStructure<Interop.TEEC_Operation64>(opptr);
596                 for (int i=0; i < 4 && i < paramlist.Length; ++i) {
597                     UpdateParam(op.paramlist[i], ref paramlist, i);
598                 }
599             }
600             else {
601                 ret = Interop.Libteec.OpenSession(context.context_imp, session_imp, ref uuid, loginMethod, connectionData, IntPtr.Zero, out ro);
602             }
603
604             for (int i=0; i < 4; ++i) {
605                 if (shm[i] != null) {
606                     context.ReleaseSharedMemory(shm[i]);
607                     shm[i] = null;
608                 }
609             }
610
611             //MAYBE map origin of return code to specyfic Exception
612             Interop.CheckNThrowException(ret, string.Format("OpenSession('{0}')", destination));
613             opened = true;
614         }
615
616         /// <summary>
617         /// This function closes a session which has been opened with a trusted application.
618         /// All commands within the session must be completed before this function can be called.
619         /// </summary>
620         /// <since_tizen> 3 </since_tizen>
621         /// <privilege>http://tizen.org/privilege/tee.client</privilege>
622         /// <privlevel>partner</privlevel>
623         /// <feature>http://tizen.org/feature/security.tee</feature>
624         /// <exception cref="UnauthorizedAccessException">Thrown when an application does not have the privilege to access this method.</exception>
625         /// <exception cref="NotSupportedException">The required feature is not supported.</exception>
626         /// <exception cref="InvalidOperationException">The operation is invalid.</exception>
627         public void Close() {
628             Dispose(true);
629             GC.SuppressFinalize(this);
630         }
631
632         /// <summary>
633         /// This function invokes a command within the specified session.
634         /// The parameter commandID is an identifier that is used to indicate which of the exposed trusted
635         /// application functions should be invoked. The supported command identifier values are defined by the
636         /// trusted application's protocol.
637         /// There can be up to four parameter objects given in the <paramref name="paramlist"/> array.
638         /// </summary>
639         /// <since_tizen> 3 </since_tizen>
640         /// <param name="commandID">The command.</param>
641         /// <param name="paramlist">The array of parameters.</param>
642         /// <privilege>http://tizen.org/privilege/tee.client</privilege>
643         /// <privlevel>partner</privlevel>
644         /// <feature>http://tizen.org/feature/security.tee</feature>
645         /// <exception cref="UnauthorizedAccessException">Thrown when an application does not have the privilege to access this method.</exception>
646         /// <exception cref="NotSupportedException">The required feature is not supported.</exception>
647         /// <exception cref="InvalidOperationException">The operation is invalid.</exception>
648         /// <exception cref="ArgumentException">The argument <paramref name="paramlist"/> is wrong.</exception>
649         public void InvokeCommand(uint commandID, Parameter[] paramlist)
650         {
651             int ret;
652             uint ro;
653             if (paramlist != null) {
654                 if (IntPtr.Size == 4) {
655                     Interop.TEEC_Operation32 op = Create_TEEC_Operation32();
656                     for (int i=0; i < 4 && i < paramlist.Length; ++i) {
657                         op.paramTypes |= InitParam(ref op.paramlist, i, paramlist[i]) << (8*i);
658                     }
659                     Marshal.StructureToPtr(op, opptr, false);
660                     ret = Interop.Libteec.InvokeCommand(session_imp, commandID, opptr, out ro);
661                     op = Marshal.PtrToStructure<Interop.TEEC_Operation32>(opptr);
662                     for (int i=0; i < 4 && i < paramlist.Length; ++i) {
663                         UpdateParam(op.paramlist[i], ref paramlist, i);
664                     }
665                 }
666                 else {
667                     Interop.TEEC_Operation64 op = Create_TEEC_Operation64();
668                     for (int i=0; i < 4 && i < paramlist.Length; ++i) {
669                         op.paramTypes |= InitParam(ref op.paramlist, i, paramlist[i]) << (8*i);
670                     }
671                     Marshal.StructureToPtr(op, opptr, false);
672                     ret = Interop.Libteec.InvokeCommand(session_imp, commandID, opptr, out ro);
673                     op = Marshal.PtrToStructure<Interop.TEEC_Operation64>(opptr);
674                     for (int i=0; i < 4 && i < paramlist.Length; ++i) {
675                         UpdateParam(op.paramlist[i], ref paramlist, i);
676                     }
677                 }
678             }
679             else {
680                 ret = Interop.Libteec.InvokeCommand(session_imp, commandID, IntPtr.Zero, out ro);
681             }
682
683             for (int i=0; i < 4; ++i) {
684                 if (shm[i] != null) {
685                     context.ReleaseSharedMemory(shm[i]);
686                     shm[i] = null;
687                 }
688             }
689
690             //MAYBE map origin of return code to specific Exception
691             Interop.CheckNThrowException(ret, string.Format("InvokeCommand({0})", commandID));
692         }
693
694         /// <summary>
695         /// The asynchronous version of the InvokeCommand.
696         /// </summary>
697         /// <since_tizen> 3 </since_tizen>
698         /// <param name="commandID">The command.</param>
699         /// <param name="paramlist">The array of parameters.</param>
700         /// <param name="token">The token for task manipulation.</param>
701         /// <returns>Returns a task executing an invoke command in the background.</returns>
702         /// <privilege>http://tizen.org/privilege/tee.client</privilege>
703         /// <privlevel>partner</privlevel>
704         /// <feature>http://tizen.org/feature/security.tee</feature>
705         /// <exception cref="UnauthorizedAccessException">Thrown when an application does not have the privilege to access this method.</exception>
706         /// <exception cref="NotSupportedException">The required feature is not supported.</exception>
707         /// <exception cref="InvalidOperationException">The operation is invalid.</exception>
708         /// <exception cref="ArgumentException">One of the arguments is wrong.</exception>
709         public async Task InvokeCommandAsync(uint commandID, Parameter[] paramlist, CancellationToken token = default(CancellationToken))
710         {
711             await Task.Factory.StartNew(() => InvokeCommand(commandID, paramlist));
712         }
713
714     };
715
716     /// <summary>
717     /// This type denotes a TEE Context, the main logical container linking a Client Application with a particular TEE.
718     /// </summary>
719     /// <since_tizen> 3 </since_tizen>
720     public sealed class Context : IDisposable
721     {
722         private bool disposed = false;
723         private bool initialized = false;
724         internal IntPtr context_imp;
725
726         /// <summary>
727         /// This function (constructor) initializes a new TEE Context, forming a connection between this client application and the
728         /// TEE identified by the string identifier name (empty or null name denotes a default TEE).
729         /// </summary>
730         /// <since_tizen> 3 </since_tizen>
731         /// <param name="name">The TEE name.</param>
732         /// <privilege>http://tizen.org/privilege/tee.client</privilege>
733         /// <privlevel>partner</privlevel>
734         /// <feature>http://tizen.org/feature/security.tee</feature>
735         /// <exception cref="UnauthorizedAccessException">Thrown when an application does not have the privilege to access this method.</exception>
736         /// <exception cref="NotSupportedException">The required feature is not supported.</exception>
737         /// <exception cref="InvalidOperationException">The operation is invalid.</exception>
738         public Context(string name)
739         {
740             context_imp = Marshal.AllocHGlobal(Marshal.SizeOf<Interop.TEEC_Context>());
741             if (name != null && name.Length == 0)
742                 name = null;
743             try {
744                 int ret = Interop.Libteec.InitializeContext(name, context_imp);
745                 Interop.CheckNThrowException(ret, string.Format("InititalizeContext('{0}')", name));
746                                 initialized = true;
747             }
748             catch (global::System.DllNotFoundException e)
749             {
750                 unchecked {
751                     Interop.CheckNThrowException((int)Interop.LibteecError.NotImplemented, "Not found: " + e.Message);
752                 }
753             }
754         }
755
756         // internal since class is sealed
757         internal void Dispose(bool disposing)
758         {
759             if (disposed) {
760                 return ;
761             }
762             if (initialized) {
763                 Interop.Libteec.FinalizeContext(context_imp);
764             }
765             Marshal.FreeHGlobal(context_imp);
766             context_imp = IntPtr.Zero;
767             disposed = true;
768         }
769
770         /// <summary>
771         /// Destructor of the class.
772         /// </summary>
773         ~Context()
774         {
775             Dispose(false);
776         }
777
778         /// <summary>
779         /// This function implements the IDisposable interface.
780         /// </summary>
781         /// <since_tizen> 3 </since_tizen>
782         /// <privilege>http://tizen.org/privilege/tee.client</privilege>
783         /// <privlevel>partner</privlevel>
784         /// <feature>http://tizen.org/feature/security.tee</feature>
785         public void Dispose() {
786             Dispose(true);
787             GC.SuppressFinalize(this);
788         }
789
790         /// <summary>
791         /// This function opens a new session between the client application and the specified trusted application.
792         /// The target trusted application is identified by an UUID passed in the parameter destination.
793         /// There can be up to four parameter objects given in the <paramref name="paramlist"/> array.
794         /// </summary>
795         /// <since_tizen> 3 </since_tizen>
796         /// <param name="destination">The UUID of the destination TA.</param>
797         /// <param name="loginMethod">The authentication algorithm <see cref="LoginMethod" />.</param>
798         /// <param name="connectionData">The data to be verified by a given login method.</param>
799         /// <param name="paramlist">The parameters to be passed to TA open-session-callback.</param>
800         /// <returns>Returns opened session.</returns>
801         /// <privilege>http://tizen.org/privilege/tee.client</privilege>
802         /// <privlevel>partner</privlevel>
803         /// <feature>http://tizen.org/feature/security.tee</feature>
804         /// <exception cref="UnauthorizedAccessException">Thrown when an application does not have the privilege to access this method.</exception>
805         /// <exception cref="NotSupportedException">The required feature is not supported.</exception>
806         /// <exception cref="InvalidOperationException">The operation is invalid.</exception>
807         /// <exception cref="ArgumentException">One of the arguments is wrong.</exception>
808         public Session OpenSession(Guid destination, uint loginMethod, byte[] connectionData, Parameter[] paramlist)
809         {
810             Session ses = new Session(this);
811             if (IntPtr.Size == 4)
812                 ses.Open32(destination, loginMethod, connectionData, paramlist);
813             else if (IntPtr.Size == 8)
814                 ses.Open64(destination, loginMethod, connectionData, paramlist);
815             else throw new NotSupportedException("unsupported arch");
816             return ses;
817         }
818         /// <summary>
819         /// @see OpenSession (Guid destination, uint connectionMethod, byte[] connectionData, Parameter[] paramlist, CancellationToken token).
820         /// </summary>
821         /// <since_tizen> 3 </since_tizen>
822         /// <param name="destination">The UUID of the destination TA.</param>
823         /// <returns>Returns opened session.</returns>
824         /// <privilege>http://tizen.org/privilege/tee.client</privilege>
825         /// <privlevel>partner</privlevel>
826         /// <feature>http://tizen.org/feature/security.tee</feature>
827         /// <exception cref="UnauthorizedAccessException">Thrown when an application does not have the privilege to access this method.</exception>
828         /// <exception cref="NotSupportedException">The required feature is not supported.</exception>
829         /// <exception cref="InvalidOperationException">The operation is invalid.</exception>
830         public Session OpenSession(Guid destination)
831         {
832             Session ses = new Session(this);
833             if (IntPtr.Size == 4)
834                 ses.Open32(destination, LoginMethod.Public, null, null);
835             else if (IntPtr.Size == 8)
836                 ses.Open64(destination, LoginMethod.Public, null, null);
837             else throw new NotSupportedException("unsupported arch");
838             return ses;
839         }
840
841         /// <summary>
842         /// The asynchronous version of the OpenSession.
843         /// @see OpenSession (Guid destination, uint connectionMethod, byte[] connectionData, Parameter[] paramlist, CancellationToken token).
844         /// </summary>
845         /// <since_tizen> 3 </since_tizen>
846         /// <param name="destination">The UUID of the destination TA.</param>
847         /// <param name="loginMethod">The authentication algorithm <see cref="LoginMethod" />.</param>
848         /// <param name="connectionData">The data to be verified by a given login method.</param>
849         /// <param name="paramlist">The parameters to be passed to the TA open-session-callback.</param>
850         /// <param name="token">The token for the task manipulation.</param>
851         /// <returns>Returns a Task executing the session open in the background.</returns>
852         /// <privilege>http://tizen.org/privilege/tee.client</privilege>
853         /// <privlevel>partner</privlevel>
854         /// <feature>http://tizen.org/feature/security.tee</feature>
855         /// <exception cref="UnauthorizedAccessException">Thrown when an application does not have the privilege to access this method.</exception>
856         /// <exception cref="NotSupportedException">The required feature is not supported.</exception>
857         /// <exception cref="InvalidOperationException">The operation is invalid.</exception>
858         /// <exception cref="ArgumentException">One of the arguments is wrong.</exception>
859         public async Task<Session> OpenSessionAsync(Guid destination, uint loginMethod, byte[] connectionData, Parameter[] paramlist, CancellationToken token = default(CancellationToken))
860         {
861             Task<Session> task = Task<Session>.Factory.StartNew(() =>
862             {
863                 return OpenSession(destination, loginMethod, connectionData, paramlist);
864             });
865             return await task;
866         }
867         /// <summary>
868         /// The asynchronous version of the OpenSession.
869         /// @see OpenSession (Guid destination, uint connectionMethod, byte[] connectionData, Parameter[] paramlist, CancellationToken token).
870         /// </summary>
871         /// <since_tizen> 3 </since_tizen>
872         /// <param name="destination">The UUID of the destination TA.</param>
873         /// <param name="token">The token for a task manipulation.</param>
874         /// <returns>Returns a task executing session open in the background.</returns>
875         /// <privilege>http://tizen.org/privilege/tee.client</privilege>
876         /// <privlevel>partner</privlevel>
877         /// <feature>http://tizen.org/feature/security.tee</feature>
878         /// <exception cref="UnauthorizedAccessException">Thrown when an application does not have the privilege to access this method.</exception>
879         /// <exception cref="NotSupportedException">The required feature is not supported.</exception>
880         /// <exception cref="InvalidOperationException">The operation is invalid.</exception>
881         public async Task<Session> OpenSessionAsync(Guid destination, CancellationToken token = default(CancellationToken))
882         {
883             Task<Session> task = Task<Session>.Factory.StartNew(() =>
884             {
885                 return OpenSession(destination);
886             });
887             return await task;
888         }
889
890         /// <summary>
891         /// This function registers a block of the existing client application memory as a block of shared memory within
892         /// the scope of the specified context, in accordance with the parameters.
893         /// The input <paramref name="memaddr"/> must point to the shared memory region to register.
894         /// </summary>
895         /// <since_tizen> 3 </since_tizen>
896         /// <param name="memaddr">The address of the shared memory.</param>
897         /// <param name="size">The size of the shared memory.</param>
898         /// <param name="flags">The flags describing the access modes (Input and/or Output).</param>
899         /// <returns>Returns the SharedMemory handler.</returns>
900         /// <privilege>http://tizen.org/privilege/tee.client</privilege>
901         /// <privlevel>partner</privlevel>
902         /// <feature>http://tizen.org/feature/security.tee</feature>
903         /// <exception cref="UnauthorizedAccessException">Thrown when an application does not have the privilege to access this method.</exception>
904         /// <exception cref="NotSupportedException">The required feature is not supported.</exception>
905         /// <exception cref="InvalidOperationException">The operation is invalid.</exception>
906         /// <exception cref="ArgumentException">The argument <paramref name="memaddr"/> is wrong.</exception>
907         public SharedMemory RegisterSharedMemory(IntPtr memaddr, UInt32 size, SharedMemoryFlags flags)
908         {
909             Interop.TEEC_SharedMemory shm = new Interop.TEEC_SharedMemory();
910             shm.buffer = memaddr;
911             shm.size = new UIntPtr(size);
912             shm.flags = (UInt32)flags;
913             int ret = Interop.Libteec.RegisterSharedMemory(context_imp, ref shm);
914             Interop.CheckNThrowException(ret, "RegisterSharedMemory");
915             return new SharedMemory(ref shm);
916         }
917
918         /// <summary>
919         /// This function allocates a new block of memory as a block of shared memory within the scope of the
920         /// specified context, in accordance with the parameters.
921         /// </summary>
922         /// <since_tizen> 3 </since_tizen>
923         /// <param name="size">The size of shared memory.</param>
924         /// <param name="flags">The flags describing access modes (Input and/or Output).</param>
925         /// <returns>Returns the Shared Memory handler.</returns>
926         /// <privilege>http://tizen.org/privilege/tee.client</privilege>
927         /// <privlevel>partner</privlevel>
928         /// <feature>http://tizen.org/feature/security.tee</feature>
929         /// <exception cref="UnauthorizedAccessException">Thrown when an application does not have the privilege to access this method.</exception>
930         /// <exception cref="NotSupportedException">The required feature is not supported.</exception>
931         /// <exception cref="InvalidOperationException">The operation is invalid.</exception>
932         public SharedMemory AllocateSharedMemory(UInt32 size, SharedMemoryFlags flags)
933         {
934             Interop.TEEC_SharedMemory shm = new Interop.TEEC_SharedMemory();
935             shm.size = new UIntPtr(size);
936             shm.flags = (UInt32)flags;
937             int ret = Interop.Libteec.AllocateSharedMemory(context_imp, ref shm);
938             Interop.CheckNThrowException(ret, "AllocateSharedMemory");
939             return new SharedMemory(ref shm);
940         }
941
942         /// <summary>
943         /// This function deregisters or deallocates a previously initialized block of the shared memory.
944         /// </summary>
945         /// <remarks>
946         /// For a memory buffer allocated using AllocateSharedMemory, the implementation must free the
947         /// underlying memory and the client application must not access this region after this function has been
948         /// called. In this case, the implementation must clear the buffer and size fields of the shared memory
949         /// structure before returning.
950         /// For memory registered using RegisterSharedMemory, the implementation must deregister the
951         /// underlying memory from the TEE, but the memory region will stay available to the client application for
952         /// other purposes as the memory is owned by it.
953         /// </remarks>
954         /// <since_tizen> 3 </since_tizen>
955         /// <param name="shm">The shared memory object returned by RegisterSharedMemory or AllocateSharedMemory.</param>
956         /// <privilege>http://tizen.org/privilege/tee.client</privilege>
957         /// <privlevel>partner</privlevel>
958         /// <feature>http://tizen.org/feature/security.tee</feature>
959         /// <exception cref="UnauthorizedAccessException">Thrown when an application does not have the privilege to access this method.</exception>
960         /// <exception cref="NotSupportedException">The required feature is not supported.</exception>
961         /// <exception cref="InvalidOperationException">The operation is invalid.</exception>
962         /// <exception cref="ArgumentException">The argument is wrong.</exception>
963         public void ReleaseSharedMemory(SharedMemory shm)
964         {
965             Interop.Libteec.ReleaseSharedMemory(ref shm.shm);
966         }
967     };
968
969 }