Allocating memory for modulus and exponent
[aaf/sshsm.git] / TPM2-Plugin / lib / tpm2_plugin_api.c
1 /* Copyright 2018 Intel Corporation, Inc
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *       http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include <sapi/tpm20.h>
17 #include <stdbool.h>
18 #include <errno.h>
19 #include <unistd.h>
20 #include "tpm2_plugin_api.h"
21 #ifdef HAVE_TCTI_DEV
22 #include <tcti/tcti_device.h>
23 #endif
24 #ifdef HAVE_TCTI_SOCK
25 #include <tcti/tcti_socket.h>
26 #endif
27 #ifdef HAVE_TCTI_TABRMD
28 #include <tcti/tcti-tabrmd.h>
29 #endif
30 #define ARRAY_LEN(x) (sizeof(x)/sizeof(x[0]))
31
32 bool output_enabled = true;
33 bool hexPasswd = false;
34 TPM_HANDLE handle2048rsa;
35 const char *tcti_path="libtss2-tcti-device.so";
36
37 static void tcti_teardown(TSS2_TCTI_CONTEXT *tcti_context)
38 {
39     if (tcti_context == NULL)
40         return;
41     tss2_tcti_finalize (tcti_context);
42     free (tcti_context);
43 }
44
45 static void sapi_teardown(TSS2_SYS_CONTEXT *sapi_context)
46 {
47     if (sapi_context == NULL)
48         return;
49     Tss2_Sys_Finalize (sapi_context);
50     free (sapi_context);
51 }
52
53 static void sapi_teardown_full (TSS2_SYS_CONTEXT *sapi_context)
54 {
55     TSS2_TCTI_CONTEXT *tcti_context = NULL;
56     TSS2_RC rc;
57
58     rc = Tss2_Sys_GetTctiContext (sapi_context, &tcti_context);
59     if (rc != TSS2_RC_SUCCESS)
60         return;
61     sapi_teardown (sapi_context);
62     tcti_teardown (tcti_context);
63 }
64
65 int tpm2_plugin_init()
66 {
67     printf("Init API done for TPM plugin ! \n");
68     return 0;
69 }
70
71 int tpm2_plugin_uninit()
72 {
73     printf("UnInit API done for TPM plugin ! \n");
74     return 0;
75 }
76
77 TPM_HANDLE srk_handle;
78 int tpm2_plugin_activate(SSHSM_HW_PLUGIN_ACTIVATE_LOAD_IN_INFO_t *activate_in_info)
79 {
80     /*
81     */
82     char *handle;
83     printf("number of buffers %d ! \n", activate_in_info->num_buffers);
84     if (activate_in_info->num_buffers!=1){
85         printf("activate failed ! \n");
86         return 1;
87     }
88     printf("number of buffers %d ! \n", activate_in_info->num_buffers);
89     handle = malloc(activate_in_info->buffer_info[0]->length_of_buffer);
90     memcpy(handle, activate_in_info->buffer_info[0]->buffer, activate_in_info->buffer_info[0]->length_of_buffer);
91     srk_handle = strtol(handle, NULL, 16);
92     printf("Activate API done for TPM plugin ! \n");
93     return 0;
94 }
95
96 TPMI_DH_OBJECT handle_load;
97
98 #ifdef HAVE_TCTI_DEV
99 TSS2_TCTI_CONTEXT*
100 tcti_device_init (char const *device_file)
101 {
102     TCTI_DEVICE_CONF conf = {
103         .device_path = device_file,
104         .logCallback = NULL,
105         .logData     = NULL,
106     };
107     size_t size;
108     TSS2_RC rc;
109     TSS2_TCTI_CONTEXT *tcti_ctx;
110
111     rc = InitDeviceTcti (NULL, &size, 0);
112     if (rc != TSS2_RC_SUCCESS) {
113         fprintf (stderr,
114                  "Failed to get allocation size for device tcti context: "
115                  "0x%x\n", rc);
116         return NULL;
117     }
118     tcti_ctx = (TSS2_TCTI_CONTEXT*)calloc (1, size);
119     if (tcti_ctx == NULL) {
120         fprintf (stderr,
121                  "Allocation for device TCTI context failed: %s\n",
122                  strerror (errno));
123         return NULL;
124     }
125     rc = InitDeviceTcti (tcti_ctx, &size, &conf);
126     if (rc != TSS2_RC_SUCCESS) {
127         fprintf (stderr,
128                  "Failed to initialize device TCTI context: 0x%x\n",
129                  rc);
130         free (tcti_ctx);
131         return NULL;
132     }
133     return tcti_ctx;
134 }
135 #endif
136
137
138 #ifdef HAVE_TCTI_SOCK
139 TSS2_TCTI_CONTEXT* tcti_socket_init (char const *address, uint16_t port)
140 {
141     TCTI_SOCKET_CONF conf = {
142         .hostname          = address,
143         .port              = port,
144         .logCallback       = NULL,
145         .logBufferCallback = NULL,
146         .logData           = NULL,
147     };
148     size_t size;
149     TSS2_RC rc;
150     TSS2_TCTI_CONTEXT *tcti_ctx;
151
152     rc = InitSocketTcti (NULL, &size, &conf, 0);
153     if (rc != TSS2_RC_SUCCESS) {
154         fprintf (stderr, "Faled to get allocation size for tcti context: "
155                  "0x%x\n", rc);
156         return NULL;
157     }
158     tcti_ctx = (TSS2_TCTI_CONTEXT*)calloc (1, size);
159     if (tcti_ctx == NULL) {
160         fprintf (stderr, "Allocation for tcti context failed: %s\n",
161                  strerror (errno));
162         return NULL;
163     }
164     rc = InitSocketTcti (tcti_ctx, &size, &conf, 0);
165     if (rc != TSS2_RC_SUCCESS) {
166         fprintf (stderr, "Failed to initialize tcti context: 0x%x\n", rc);
167         free (tcti_ctx);
168         return NULL;
169     }
170     return tcti_ctx;
171 }
172 #endif
173 #ifdef HAVE_TCTI_TABRMD
174 TSS2_TCTI_CONTEXT *tcti_tabrmd_init (void)
175 {
176     TSS2_TCTI_CONTEXT *tcti_ctx;
177     TSS2_RC rc;
178     size_t size;
179
180     rc = tss2_tcti_tabrmd_init(NULL, &size);
181     if (rc != TSS2_RC_SUCCESS) {
182         printf("Failed to get size for TABRMD TCTI context: 0x%x", rc);
183         return NULL;
184     }
185     tcti_ctx = (TSS2_TCTI_CONTEXT*)calloc (1, size);
186     if (tcti_ctx == NULL) {
187         printf("Allocation for TABRMD TCTI context failed: %s", strerror (errno));
188         return NULL;
189     }
190     rc = tss2_tcti_tabrmd_init (tcti_ctx, &size);
191     if (rc != TSS2_RC_SUCCESS) {
192         printf("Failed to initialize TABRMD TCTI context: 0x%x", rc);
193         free(tcti_ctx);
194         return NULL;
195     }
196     return tcti_ctx;
197 }
198 #endif
199 TSS2_TCTI_CONTEXT *tcti_init_from_options(common_opts_t *options)
200 {
201     switch (options->tcti_type) {
202 #ifdef HAVE_TCTI_DEV
203     case DEVICE_TCTI:
204         return tcti_device_init (options->device_file);
205 #endif
206 #ifdef HAVE_TCTI_SOCK
207     case SOCKET_TCTI:
208         return tcti_socket_init (options->socket_address,
209                                  options->socket_port);
210 #endif
211 #ifdef HAVE_TCTI_TABRMD
212     case TABRMD_TCTI:
213         return tcti_tabrmd_init ();
214 #endif
215     default:
216         return NULL;
217     }
218 }
219
220 static TSS2_SYS_CONTEXT *sapi_ctx_init (TSS2_TCTI_CONTEXT *tcti_ctx)
221 {
222     TSS2_SYS_CONTEXT *sapi_ctx;
223     TSS2_RC rc;
224     size_t size;
225     TSS2_ABI_VERSION abi_version = {
226         .tssCreator = TSSWG_INTEROP,
227         .tssFamily  = TSS_SAPI_FIRST_FAMILY,
228         .tssLevel   = TSS_SAPI_FIRST_LEVEL,
229         .tssVersion = TSS_SAPI_FIRST_VERSION,
230     };
231
232     size = Tss2_Sys_GetContextSize (0);
233     sapi_ctx = (TSS2_SYS_CONTEXT*)calloc (1, size);
234     if (sapi_ctx == NULL) {
235         fprintf (stderr,
236                  "Failed to allocate 0x%zx bytes for the SAPI context\n",
237                  size);
238         return NULL;
239     }
240     rc = Tss2_Sys_Initialize (sapi_ctx, size, tcti_ctx, &abi_version);
241     if (rc != TSS2_RC_SUCCESS) {
242         fprintf (stderr, "Failed to initialize SAPI context: 0x%x\n", rc);
243         free (sapi_ctx);
244         return NULL;
245     }
246     return sapi_ctx;
247 }
248
249 #define BUFFER_SIZE(type, field) (sizeof((((type *)NULL)->t.field)))
250 #define TPM2B_TYPE_INIT(type, field) { .t = { .size = BUFFER_SIZE(type, field), }, }
251 TPMS_AUTH_COMMAND sessionData;
252 int hex2ByteStructure(const char *inStr, UINT16 *byteLength, BYTE *byteBuffer)
253 {
254     int strLength;//if the inStr likes "1a2b...", no prefix "0x"
255     int i = 0;
256     if(inStr == NULL || byteLength == NULL || byteBuffer == NULL)
257         return -1;
258     strLength = strlen(inStr);
259     if(strLength%2)
260         return -2;
261     for(i = 0; i < strLength; i++)
262     {
263         if(!isxdigit(inStr[i]))
264             return -3;
265     }
266
267     if(*byteLength < strLength/2)
268         return -4;
269
270     *byteLength = strLength/2;
271
272     for(i = 0; i < *byteLength; i++)
273     {
274         char tmpStr[4] = {0};
275         tmpStr[0] = inStr[i*2];
276         tmpStr[1] = inStr[i*2+1];
277         byteBuffer[i] = strtol(tmpStr, NULL, 16);
278     }
279     return 0;
280 }
281 int load_key(TSS2_SYS_CONTEXT *sapi_context,
282              TPMI_DH_OBJECT    parentHandle,
283              TPM2B_PUBLIC     *inPublic,
284              TPM2B_PRIVATE    *inPrivate,
285              int               P_flag)
286 {
287     UINT32 rval;
288     TPMS_AUTH_RESPONSE sessionDataOut;
289     TSS2_SYS_CMD_AUTHS sessionsData;
290     TSS2_SYS_RSP_AUTHS sessionsDataOut;
291     TPMS_AUTH_COMMAND *sessionDataArray[1];
292     TPMS_AUTH_RESPONSE *sessionDataOutArray[1];
293
294     TPM2B_NAME nameExt = TPM2B_TYPE_INIT(TPM2B_NAME, name);
295
296     sessionDataArray[0] = &sessionData;
297     sessionDataOutArray[0] = &sessionDataOut;
298
299     sessionsDataOut.rspAuths = &sessionDataOutArray[0];
300     sessionsData.cmdAuths = &sessionDataArray[0];
301
302     sessionsDataOut.rspAuthsCount = 1;
303     sessionsData.cmdAuthsCount = 1;
304
305     sessionData.sessionHandle = TPM_RS_PW;
306     sessionData.nonce.t.size = 0;
307
308     if(P_flag == 0)
309         sessionData.hmac.t.size = 0;
310
311     *((UINT8 *)((void *)&sessionData.sessionAttributes)) = 0;
312     if (sessionData.hmac.t.size > 0 && hexPasswd)
313     {
314         sessionData.hmac.t.size = sizeof(sessionData.hmac) - 2;
315         if (hex2ByteStructure((char *)sessionData.hmac.t.buffer,
316                               &sessionData.hmac.t.size,
317                               sessionData.hmac.t.buffer) != 0)
318         {
319             printf( "Failed to convert Hex format password for parent Passwd.\n");
320             return -1;
321         }
322     }
323
324     rval = Tss2_Sys_Load (sapi_context,
325                           parentHandle,
326                           &sessionsData,
327                           inPrivate,
328                           inPublic,
329                           &handle2048rsa,
330                           &nameExt,
331                           &sessionsDataOut);
332     if(rval != TPM_RC_SUCCESS)
333     {
334         printf("\nLoad Object Failed ! ErrorCode: 0x%0x\n\n",rval);
335         return -1;
336     }
337     printf("\nLoad succ.\nLoadedHandle: 0x%08x\n\n",handle2048rsa);
338
339     return 0;
340 }
341
342 int read_public(TSS2_SYS_CONTEXT *sapi_context,
343                 TPM_HANDLE handle,
344                 SSHSM_HW_PLUGIN_IMPORT_PUBLIC_KEY_INFO_t *importkey_info)
345 {
346
347     TPMS_AUTH_RESPONSE session_out_data;
348     TSS2_SYS_RSP_AUTHS sessions_out_data;
349     TPMS_AUTH_RESPONSE *session_out_data_array[1];
350
351     TPM2B_PUBLIC public = {
352             { 0, }
353     };
354
355     TPM2B_NAME name = TPM2B_TYPE_INIT(TPM2B_NAME, name);
356
357     TPM2B_NAME qualified_name = TPM2B_TYPE_INIT(TPM2B_NAME, name);
358
359     session_out_data_array[0] = &session_out_data;
360     sessions_out_data.rspAuths = &session_out_data_array[0];
361     sessions_out_data.rspAuthsCount = ARRAY_LEN(session_out_data_array);
362
363     TPM_RC rval = Tss2_Sys_ReadPublic(sapi_context, handle, 0,
364             &public, &name, &qualified_name, &sessions_out_data);
365     if (rval != TPM_RC_SUCCESS) {
366         printf("TPM2_ReadPublic error: rval = 0x%0x", rval);
367         return false;
368     }
369
370     printf("\nTPM2_ReadPublic OutPut: \n");
371     printf("name: \n");
372     UINT16 i;
373     for (i = 0; i < name.t.size; i++)
374         printf("%02x ", name.t.name[i]);
375     printf("\n");
376
377     printf("qualified_name: \n");
378     for (i = 0; i < qualified_name.t.size; i++)
379         printf("%02x ", qualified_name.t.name[i]);
380     printf("\n");
381
382     printf("public.t.publicArea.parameters.rsaDetail.keyBits = %d \n", public.t.publicArea.parameters.rsaDetail.keyBits);
383     printf("public.t.publicArea.parameters.rsaDetail.exponent = %d \n", public.t.publicArea.parameters.rsaDetail.exponent);
384
385     importkey_info->modulus_size = public.t.publicArea.unique.rsa.t.size;
386     printf("importkey_info->modulus_size = %ld \n", importkey_info->modulus_size);
387     importkey_info->modulus = (unsigned char *) malloc(importkey_info->modulus_size);
388     if (importkey_info->modulus != NULL) {
389         memcpy(importkey_info->modulus, &public.t.publicArea.unique.rsa.t.buffer, importkey_info->modulus_size);
390     }
391
392     importkey_info->exponent_size = sizeof(public.t.publicArea.parameters.rsaDetail.exponent);
393     printf("importkey_info->exponent_size = %ld \n", importkey_info->exponent_size);
394     importkey_info->exponent = (unsigned char *) malloc(importkey_info->exponent_size);
395     if (importkey_info->exponent != NULL) {
396         memcpy(importkey_info->exponent, &public.t.publicArea.parameters.rsaDetail.exponent, importkey_info->exponent_size);
397     }
398
399     //*importkey_info->exponent = public.t.publicArea.parameters.rsaDetail.exponent;
400
401     return 0;
402 }
403
404 TPMS_CONTEXT loaded_key_context;
405
406 int load_key_execute(SSHSM_HW_PLUGIN_ACTIVATE_LOAD_IN_INFO_t *loadkey_in_info,
407                      void **keyHandle, TSS2_SYS_CONTEXT *sapi_context,
408                      SSHSM_HW_PLUGIN_IMPORT_PUBLIC_KEY_INFO_t *importkey_info)
409 {
410
411     TPMI_DH_OBJECT parentHandle;
412     TPM2B_PUBLIC  inPublic;
413     TPM2B_PRIVATE inPrivate;
414     UINT16 size;
415     int returnVal = 0;
416
417     memset(&inPublic,0,sizeof(TPM2B_PUBLIC));
418     memset(&inPrivate,0,sizeof(TPM2B_SENSITIVE));
419
420     setbuf(stdout, NULL);
421     setvbuf (stdout, NULL, _IONBF, BUFSIZ);
422
423     //parentHandle = 0x81000011;
424     parentHandle = srk_handle;
425
426     if (loadkey_in_info->num_buffers != 2)
427         return -1;
428     memcpy(&inPublic, loadkey_in_info->buffer_info[0]->buffer,
429            loadkey_in_info->buffer_info[0]->length_of_buffer);
430     memcpy(&inPrivate, loadkey_in_info->buffer_info[1]->buffer,
431            loadkey_in_info->buffer_info[1]->length_of_buffer);
432
433     returnVal = load_key (sapi_context,
434                           parentHandle,
435                           &inPublic,
436                           &inPrivate,
437                           0);
438     returnVal = read_public(sapi_context,
439                             handle2048rsa,
440                             importkey_info);
441
442     TPM_RC rval = Tss2_Sys_ContextSave(sapi_context, handle2048rsa, &loaded_key_context);
443     if (rval != TPM_RC_SUCCESS) {
444         printf("Tss2_Sys_ContextSave: Saving handle 0x%x context failed. TPM Error:0x%x", handle2048rsa, rval);
445         return -1;
446     }
447     *keyHandle = &handle2048rsa;
448     return 0;
449 }
450
451 int tpm2_plugin_load_key(SSHSM_HW_PLUGIN_ACTIVATE_LOAD_IN_INFO_t *loadkey_in_info,
452                          void **keyHandle,
453                          SSHSM_HW_PLUGIN_IMPORT_PUBLIC_KEY_INFO_t *importkey_info)
454 {
455     int ret = 1;
456     common_opts_t opts = COMMON_OPTS_INITIALIZER;
457     TSS2_TCTI_CONTEXT *tcti_ctx;
458     tcti_ctx = tcti_init_from_options(&opts);
459     if (tcti_ctx == NULL)
460         return -1;
461
462     TSS2_SYS_CONTEXT *sapi_context = NULL;
463     if (tcti_ctx) {
464         sapi_context = sapi_ctx_init(tcti_ctx);
465         if (!sapi_context) {
466             free(tcti_ctx);
467             return -1;
468         }
469     }
470
471     ret = load_key_execute(loadkey_in_info, keyHandle, sapi_context, importkey_info);
472     if (ret !=0)
473         printf("Load key API failed in TPM plugin ! \n");
474
475     sapi_teardown_full(sapi_context);
476
477     printf("Load key API successful in TPM plugin ! \n");
478     return 0;
479
480 }
481
482 typedef struct tpm_sign_ctx tpm_sign_ctx;
483 struct tpm_sign_ctx {
484     TPMT_TK_HASHCHECK validation;
485     TPMS_AUTH_COMMAND sessionData;
486     TPMI_DH_OBJECT keyHandle;
487     TPMI_ALG_HASH halg;
488     char outFilePath[PATH_MAX];
489     BYTE *msg;
490     UINT16 length;
491     TSS2_SYS_CONTEXT *sapi_context;
492 };
493
494 int tpm2_plugin_rsa_sign_init(
495         void *keyHandle,
496         unsigned long mechanism,
497         void *param,
498         int len)
499 {
500     printf("rsa_sign_init API mechanism is %lx \n", mechanism);
501     printf("rsa_sign_init API done for tpm2_plugin... \n");
502     return 0;
503 }
504
505 UINT32 tpm_hash(TSS2_SYS_CONTEXT *sapi_context, TPMI_ALG_HASH hashAlg,
506         UINT16 size, BYTE *data, TPM2B_DIGEST *result) {
507     TPM2B_MAX_BUFFER dataSizedBuffer;
508
509     dataSizedBuffer.t.size = size;
510     memcpy(dataSizedBuffer.t.buffer, data, size);
511     return Tss2_Sys_Hash(sapi_context, 0, &dataSizedBuffer, hashAlg,
512             TPM_RH_NULL, result, 0, 0);
513 }
514
515 static TPM_RC hash_sequence_ex(TSS2_SYS_CONTEXT *sapi_context,
516
517     TPMI_ALG_HASH hashAlg, UINT32 numBuffers, TPM2B_MAX_BUFFER *bufferList,
518     TPM2B_DIGEST *result) {
519     TPM_RC rval;
520     TPM2B_AUTH nullAuth;
521     TPMI_DH_OBJECT sequenceHandle;
522     TPM2B emptyBuffer;
523     TPMT_TK_HASHCHECK validation;
524
525     TPMS_AUTH_COMMAND cmdAuth;
526     TPMS_AUTH_COMMAND *cmdSessionArray[1] = { &cmdAuth };
527     TSS2_SYS_CMD_AUTHS cmdAuthArray = { 1, &cmdSessionArray[0] };
528
529     nullAuth.t.size = 0;
530     emptyBuffer.size = 0;
531
532     // Set result size to 0, in case any errors occur
533     result->b.size = 0;
534
535     // Init input sessions struct
536     cmdAuth.sessionHandle = TPM_RS_PW;
537     cmdAuth.nonce.t.size = 0;
538     *((UINT8 *) ((void *) &cmdAuth.sessionAttributes)) = 0;
539     cmdAuth.hmac.t.size = 0;
540
541     rval = Tss2_Sys_HashSequenceStart(sapi_context, 0, &nullAuth, hashAlg,
542             &sequenceHandle, 0);
543     if (rval != TPM_RC_SUCCESS) {
544         return rval;
545     }
546
547     unsigned i;
548     for (i = 0; i < numBuffers; i++) {
549         rval = Tss2_Sys_SequenceUpdate(sapi_context, sequenceHandle,
550                 &cmdAuthArray, &bufferList[i], 0);
551
552         if (rval != TPM_RC_SUCCESS) {
553             return rval;
554         }
555     }
556
557     rval = Tss2_Sys_SequenceComplete(sapi_context, sequenceHandle,
558             &cmdAuthArray, (TPM2B_MAX_BUFFER *) &emptyBuffer,
559             TPM_RH_PLATFORM, result, &validation, 0);
560
561     if (rval != TPM_RC_SUCCESS) {
562         return rval;
563     }
564
565     return rval;
566 }
567
568 int tpm_hash_compute_data(TSS2_SYS_CONTEXT *sapi_context, BYTE *buffer,
569         UINT16 length, TPMI_ALG_HASH halg, TPM2B_DIGEST *result) {
570
571     if (length <= MAX_DIGEST_BUFFER) {
572         if (tpm_hash(sapi_context, halg, length, buffer,
573                 result) == TPM_RC_SUCCESS)
574             return 0;
575         else
576             return -1;
577     }
578
579     UINT8 numBuffers = (length - 1) / MAX_DIGEST_BUFFER + 1;
580
581     TPM2B_MAX_BUFFER *bufferList = (TPM2B_MAX_BUFFER *) calloc(numBuffers,
582             sizeof(TPM2B_MAX_BUFFER));
583     if (bufferList == NULL)
584         return -2;
585
586     UINT32 i;
587     for (i = 0; i < (UINT32)(numBuffers - 1); i++) {
588         bufferList[i].t.size = MAX_DIGEST_BUFFER;
589         memcpy(bufferList[i].t.buffer, buffer + i * MAX_DIGEST_BUFFER,
590                 MAX_DIGEST_BUFFER);
591     }
592     bufferList[i].t.size = length - i * MAX_DIGEST_BUFFER;
593     memcpy(bufferList[i].t.buffer, buffer + i * MAX_DIGEST_BUFFER,
594             bufferList[i].t.size);
595
596     TPM_RC rval = hash_sequence_ex(sapi_context, halg, numBuffers, bufferList, result);
597     free(bufferList);
598     return rval == TPM_RC_SUCCESS ? 0 : -3;
599 }
600
601
602 static bool get_key_type(TSS2_SYS_CONTEXT *sapi_context, TPMI_DH_OBJECT objectHandle,
603         TPMI_ALG_PUBLIC *type) {
604
605     TPMS_AUTH_RESPONSE session_data_out;
606
607     TPMS_AUTH_RESPONSE *session_data_out_array[1] = {
608             &session_data_out
609     };
610
611     TSS2_SYS_RSP_AUTHS sessions_data_out = {
612             1,
613             &session_data_out_array[0]
614     };
615
616     TPM2B_PUBLIC out_public = {
617             { 0, }
618     };
619
620     TPM2B_NAME name = TPM2B_TYPE_INIT(TPM2B_NAME, name);
621
622     TPM2B_NAME qaulified_name = TPM2B_TYPE_INIT(TPM2B_NAME, name);
623
624     TPM_RC rval = Tss2_Sys_ReadPublic(sapi_context, objectHandle, 0, &out_public, &name,
625             &qaulified_name, &sessions_data_out);
626     if (rval != TPM_RC_SUCCESS) {
627         printf("Sys_ReadPublic failed, error code: 0x%x", rval);
628         return false;
629     }
630     *type = out_public.t.publicArea.type;
631     return true;
632 }
633
634 static bool set_scheme(TSS2_SYS_CONTEXT *sapi_context, TPMI_DH_OBJECT keyHandle,
635         TPMI_ALG_HASH halg, TPMT_SIG_SCHEME *inScheme) {
636
637     TPM_ALG_ID type;
638     bool result = get_key_type(sapi_context, keyHandle, &type);
639     if (!result) {
640         return false;
641     }
642
643     switch (type) {
644     case TPM_ALG_RSA :
645         inScheme->scheme = TPM_ALG_RSASSA;
646         inScheme->details.rsassa.hashAlg = halg;
647         break;
648     case TPM_ALG_KEYEDHASH :
649         inScheme->scheme = TPM_ALG_HMAC;
650         inScheme->details.hmac.hashAlg = halg;
651         break;
652     case TPM_ALG_ECC :
653         inScheme->scheme = TPM_ALG_ECDSA;
654         inScheme->details.ecdsa.hashAlg = halg;
655         break;
656     case TPM_ALG_SYMCIPHER :
657     default:
658         printf("Unknown key type, got: 0x%x", type);
659         return false;
660     }
661
662     return true;
663 }
664 static bool sign_and_save(tpm_sign_ctx *ctx,  unsigned char *sig, int *sig_len) {
665     TPM2B_DIGEST digest = TPM2B_TYPE_INIT(TPM2B_DIGEST, buffer);
666
667     TPMT_SIG_SCHEME in_scheme;
668     TPMT_SIGNATURE signature;
669     int signature_len;
670     TSS2_SYS_CMD_AUTHS sessions_data;
671     TPMS_AUTH_RESPONSE session_data_out;
672     TSS2_SYS_RSP_AUTHS sessions_data_out;
673     TPMS_AUTH_COMMAND *session_data_array[1];
674     TPMS_AUTH_RESPONSE *session_data_out_array[1];
675
676     session_data_array[0] = &ctx->sessionData;
677     sessions_data.cmdAuths = &session_data_array[0];
678     session_data_out_array[0] = &session_data_out;
679     sessions_data_out.rspAuths = &session_data_out_array[0];
680     sessions_data_out.rspAuthsCount = 1;
681     sessions_data.cmdAuthsCount = 1;
682
683     int rc = tpm_hash_compute_data(ctx->sapi_context, ctx->msg, ctx->length, ctx->halg, &digest);
684     if (rc) {
685         printf("Compute message hash failed!");
686         return false;
687     }
688
689     bool result = set_scheme(ctx->sapi_context, ctx->keyHandle, ctx->halg, &in_scheme);
690     if (!result) {
691         return false;
692     }
693
694     TPM_RC rval = Tss2_Sys_Sign(ctx->sapi_context, ctx->keyHandle,
695                                 &sessions_data, &digest, &in_scheme,
696                                 &ctx->validation, &signature,
697                                 &sessions_data_out);
698
699     if (rval != TPM_RC_SUCCESS) {
700         printf("Sys_Sign failed, error code: 0x%x", rval);
701         return false;
702     }
703     signature_len = sizeof(signature);
704     sig_len = &signature_len;
705     sig = (unsigned char *)&signature;
706
707     return true;
708 }
709
710 int tpm2_plugin_rsa_sign(
711         void  *keyHandle,
712         unsigned long mechanism,
713         unsigned char *msg,
714         int msg_len,
715         unsigned char *sig,
716         int *sig_len)
717 {
718     TPM_RC rval;
719     common_opts_t opts = COMMON_OPTS_INITIALIZER;
720     TSS2_TCTI_CONTEXT *tcti_ctx;
721     tcti_ctx = tcti_init_from_options(&opts);
722     if (tcti_ctx == NULL)
723         return -1;
724
725     TSS2_SYS_CONTEXT *sapi_context = NULL;
726     if (tcti_ctx) {
727        sapi_context = sapi_ctx_init(tcti_ctx);
728        if (!sapi_context) {
729            free(tcti_ctx);
730            return -1;
731        }
732     }
733
734     tpm_sign_ctx ctx = {
735             .msg = NULL,
736             .sessionData = { 0 },
737             .halg = 0,
738             .keyHandle = 0,
739             .validation = { 0 },
740             .sapi_context = sapi_context
741     };
742     
743     printf("rsa_sign API mechanism is %lx \n", mechanism);
744     ctx.sessionData.sessionHandle = TPM_RS_PW;
745     ctx.validation.tag = TPM_ST_HASHCHECK;
746     ctx.validation.hierarchy = TPM_RH_NULL;
747     ctx.halg = TPM_ALG_SHA256;
748     ctx.keyHandle = *(TPMI_DH_OBJECT *)keyHandle;
749
750     rval = Tss2_Sys_ContextLoad(ctx.sapi_context, &loaded_key_context, &ctx.keyHandle);
751     if (rval != TPM_RC_SUCCESS) {
752         printf("ContextLoad Error in RSA Sign API. TPM Error:0x%x", rval);
753         goto out;
754     }
755     ctx.length = msg_len;
756     ctx.msg = msg;
757
758     if (!sign_and_save(&ctx, sig, sig_len)){
759         printf("RSA sign failed\n");
760         goto out;
761     }
762
763     printf("RSA sign API successful in TPM plugin ! \n");
764
765 out:
766     sapi_teardown_full(sapi_context);
767
768     return 0;
769
770 }
771
772