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