356ce7be1e3aa70c84833d7590ef6794873310f3
[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     memcpy(importkey_info->modulus, &public.t.publicArea.unique.rsa.t.buffer, importkey_info->modulus_size);
388
389     importkey_info->exponent_size = sizeof(public.t.publicArea.parameters.rsaDetail.exponent);
390     printf("importkey_info->exponent_size = %ld \n", importkey_info->exponent_size);
391     memcpy(importkey_info->exponent, &public.t.publicArea.parameters.rsaDetail.exponent, importkey_info->exponent_size);
392     //*importkey_info->exponent = public.t.publicArea.parameters.rsaDetail.exponent;
393
394     return 0;
395 }
396
397 TPMS_CONTEXT loaded_key_context;
398
399 int load_key_execute(SSHSM_HW_PLUGIN_ACTIVATE_LOAD_IN_INFO_t *loadkey_in_info,
400                      void **keyHandle, TSS2_SYS_CONTEXT *sapi_context,
401                      SSHSM_HW_PLUGIN_IMPORT_PUBLIC_KEY_INFO_t *importkey_info)
402 {
403
404     TPMI_DH_OBJECT parentHandle;
405     TPM2B_PUBLIC  inPublic;
406     TPM2B_PRIVATE inPrivate;
407     UINT16 size;
408     int returnVal = 0;
409
410     memset(&inPublic,0,sizeof(TPM2B_PUBLIC));
411     memset(&inPrivate,0,sizeof(TPM2B_SENSITIVE));
412
413     setbuf(stdout, NULL);
414     setvbuf (stdout, NULL, _IONBF, BUFSIZ);
415
416     //parentHandle = 0x81000011;
417     parentHandle = srk_handle;
418
419     if (loadkey_in_info->num_buffers != 2)
420         return -1;
421     memcpy(&inPublic, loadkey_in_info->buffer_info[0]->buffer,
422            loadkey_in_info->buffer_info[0]->length_of_buffer);
423     memcpy(&inPrivate, loadkey_in_info->buffer_info[1]->buffer,
424            loadkey_in_info->buffer_info[1]->length_of_buffer);
425
426     returnVal = load_key (sapi_context,
427                           parentHandle,
428                           &inPublic,
429                           &inPrivate,
430                           0);
431     returnVal = read_public(sapi_context,
432                             handle2048rsa,
433                             importkey_info);
434
435     TPM_RC rval = Tss2_Sys_ContextSave(sapi_context, handle2048rsa, &loaded_key_context);
436     if (rval != TPM_RC_SUCCESS) {
437         printf("Tss2_Sys_ContextSave: Saving handle 0x%x context failed. TPM Error:0x%x", handle2048rsa, rval);
438         return -1;
439     }
440     *keyHandle = &handle2048rsa;
441     return 0;
442 }
443
444 int tpm2_plugin_load_key(SSHSM_HW_PLUGIN_ACTIVATE_LOAD_IN_INFO_t *loadkey_in_info,
445                          void **keyHandle,
446                          SSHSM_HW_PLUGIN_IMPORT_PUBLIC_KEY_INFO_t *importkey_info)
447 {
448     int ret = 1;
449     common_opts_t opts = COMMON_OPTS_INITIALIZER;
450     TSS2_TCTI_CONTEXT *tcti_ctx;
451     tcti_ctx = tcti_init_from_options(&opts);
452     if (tcti_ctx == NULL)
453         return -1;
454
455     TSS2_SYS_CONTEXT *sapi_context = NULL;
456     if (tcti_ctx) {
457         sapi_context = sapi_ctx_init(tcti_ctx);
458         if (!sapi_context) {
459             free(tcti_ctx);
460             return -1;
461         }
462     }
463
464     ret = load_key_execute(loadkey_in_info, keyHandle, sapi_context, importkey_info);
465     if (ret !=0)
466         printf("Load key API failed in TPM plugin ! \n");
467
468     sapi_teardown_full(sapi_context);
469
470     printf("Load key API successful in TPM plugin ! \n");
471     return 0;
472
473 }
474
475 typedef struct tpm_sign_ctx tpm_sign_ctx;
476 struct tpm_sign_ctx {
477     TPMT_TK_HASHCHECK validation;
478     TPMS_AUTH_COMMAND sessionData;
479     TPMI_DH_OBJECT keyHandle;
480     TPMI_ALG_HASH halg;
481     char outFilePath[PATH_MAX];
482     BYTE *msg;
483     UINT16 length;
484     TSS2_SYS_CONTEXT *sapi_context;
485 };
486
487 int tpm2_plugin_rsa_sign_init(
488         void *keyHandle,
489         unsigned long mechanism,
490         void *param,
491         int len)
492 {
493     printf("rsa_sign_init API mechanism is %lx \n", mechanism);
494     printf("rsa_sign_init API done for tpm2_plugin... \n");
495     return 0;
496 }
497
498 UINT32 tpm_hash(TSS2_SYS_CONTEXT *sapi_context, TPMI_ALG_HASH hashAlg,
499         UINT16 size, BYTE *data, TPM2B_DIGEST *result) {
500     TPM2B_MAX_BUFFER dataSizedBuffer;
501
502     dataSizedBuffer.t.size = size;
503     memcpy(dataSizedBuffer.t.buffer, data, size);
504     return Tss2_Sys_Hash(sapi_context, 0, &dataSizedBuffer, hashAlg,
505             TPM_RH_NULL, result, 0, 0);
506 }
507
508 static TPM_RC hash_sequence_ex(TSS2_SYS_CONTEXT *sapi_context,
509
510     TPMI_ALG_HASH hashAlg, UINT32 numBuffers, TPM2B_MAX_BUFFER *bufferList,
511     TPM2B_DIGEST *result) {
512     TPM_RC rval;
513     TPM2B_AUTH nullAuth;
514     TPMI_DH_OBJECT sequenceHandle;
515     TPM2B emptyBuffer;
516     TPMT_TK_HASHCHECK validation;
517
518     TPMS_AUTH_COMMAND cmdAuth;
519     TPMS_AUTH_COMMAND *cmdSessionArray[1] = { &cmdAuth };
520     TSS2_SYS_CMD_AUTHS cmdAuthArray = { 1, &cmdSessionArray[0] };
521
522     nullAuth.t.size = 0;
523     emptyBuffer.size = 0;
524
525     // Set result size to 0, in case any errors occur
526     result->b.size = 0;
527
528     // Init input sessions struct
529     cmdAuth.sessionHandle = TPM_RS_PW;
530     cmdAuth.nonce.t.size = 0;
531     *((UINT8 *) ((void *) &cmdAuth.sessionAttributes)) = 0;
532     cmdAuth.hmac.t.size = 0;
533
534     rval = Tss2_Sys_HashSequenceStart(sapi_context, 0, &nullAuth, hashAlg,
535             &sequenceHandle, 0);
536     if (rval != TPM_RC_SUCCESS) {
537         return rval;
538     }
539
540     unsigned i;
541     for (i = 0; i < numBuffers; i++) {
542         rval = Tss2_Sys_SequenceUpdate(sapi_context, sequenceHandle,
543                 &cmdAuthArray, &bufferList[i], 0);
544
545         if (rval != TPM_RC_SUCCESS) {
546             return rval;
547         }
548     }
549
550     rval = Tss2_Sys_SequenceComplete(sapi_context, sequenceHandle,
551             &cmdAuthArray, (TPM2B_MAX_BUFFER *) &emptyBuffer,
552             TPM_RH_PLATFORM, result, &validation, 0);
553
554     if (rval != TPM_RC_SUCCESS) {
555         return rval;
556     }
557
558     return rval;
559 }
560
561 int tpm_hash_compute_data(TSS2_SYS_CONTEXT *sapi_context, BYTE *buffer,
562         UINT16 length, TPMI_ALG_HASH halg, TPM2B_DIGEST *result) {
563
564     if (length <= MAX_DIGEST_BUFFER) {
565         if (tpm_hash(sapi_context, halg, length, buffer,
566                 result) == TPM_RC_SUCCESS)
567             return 0;
568         else
569             return -1;
570     }
571
572     UINT8 numBuffers = (length - 1) / MAX_DIGEST_BUFFER + 1;
573
574     TPM2B_MAX_BUFFER *bufferList = (TPM2B_MAX_BUFFER *) calloc(numBuffers,
575             sizeof(TPM2B_MAX_BUFFER));
576     if (bufferList == NULL)
577         return -2;
578
579     UINT32 i;
580     for (i = 0; i < (UINT32)(numBuffers - 1); i++) {
581         bufferList[i].t.size = MAX_DIGEST_BUFFER;
582         memcpy(bufferList[i].t.buffer, buffer + i * MAX_DIGEST_BUFFER,
583                 MAX_DIGEST_BUFFER);
584     }
585     bufferList[i].t.size = length - i * MAX_DIGEST_BUFFER;
586     memcpy(bufferList[i].t.buffer, buffer + i * MAX_DIGEST_BUFFER,
587             bufferList[i].t.size);
588
589     TPM_RC rval = hash_sequence_ex(sapi_context, halg, numBuffers, bufferList, result);
590     free(bufferList);
591     return rval == TPM_RC_SUCCESS ? 0 : -3;
592 }
593
594
595 static bool get_key_type(TSS2_SYS_CONTEXT *sapi_context, TPMI_DH_OBJECT objectHandle,
596         TPMI_ALG_PUBLIC *type) {
597
598     TPMS_AUTH_RESPONSE session_data_out;
599
600     TPMS_AUTH_RESPONSE *session_data_out_array[1] = {
601             &session_data_out
602     };
603
604     TSS2_SYS_RSP_AUTHS sessions_data_out = {
605             1,
606             &session_data_out_array[0]
607     };
608
609     TPM2B_PUBLIC out_public = {
610             { 0, }
611     };
612
613     TPM2B_NAME name = TPM2B_TYPE_INIT(TPM2B_NAME, name);
614
615     TPM2B_NAME qaulified_name = TPM2B_TYPE_INIT(TPM2B_NAME, name);
616
617     TPM_RC rval = Tss2_Sys_ReadPublic(sapi_context, objectHandle, 0, &out_public, &name,
618             &qaulified_name, &sessions_data_out);
619     if (rval != TPM_RC_SUCCESS) {
620         printf("Sys_ReadPublic failed, error code: 0x%x", rval);
621         return false;
622     }
623     *type = out_public.t.publicArea.type;
624     return true;
625 }
626
627 static bool set_scheme(TSS2_SYS_CONTEXT *sapi_context, TPMI_DH_OBJECT keyHandle,
628         TPMI_ALG_HASH halg, TPMT_SIG_SCHEME *inScheme) {
629
630     TPM_ALG_ID type;
631     bool result = get_key_type(sapi_context, keyHandle, &type);
632     if (!result) {
633         return false;
634     }
635
636     switch (type) {
637     case TPM_ALG_RSA :
638         inScheme->scheme = TPM_ALG_RSASSA;
639         inScheme->details.rsassa.hashAlg = halg;
640         break;
641     case TPM_ALG_KEYEDHASH :
642         inScheme->scheme = TPM_ALG_HMAC;
643         inScheme->details.hmac.hashAlg = halg;
644         break;
645     case TPM_ALG_ECC :
646         inScheme->scheme = TPM_ALG_ECDSA;
647         inScheme->details.ecdsa.hashAlg = halg;
648         break;
649     case TPM_ALG_SYMCIPHER :
650     default:
651         printf("Unknown key type, got: 0x%x", type);
652         return false;
653     }
654
655     return true;
656 }
657 static bool sign_and_save(tpm_sign_ctx *ctx,  unsigned char *sig, int *sig_len) {
658     TPM2B_DIGEST digest = TPM2B_TYPE_INIT(TPM2B_DIGEST, buffer);
659
660     TPMT_SIG_SCHEME in_scheme;
661     TPMT_SIGNATURE signature;
662     int signature_len;
663     TSS2_SYS_CMD_AUTHS sessions_data;
664     TPMS_AUTH_RESPONSE session_data_out;
665     TSS2_SYS_RSP_AUTHS sessions_data_out;
666     TPMS_AUTH_COMMAND *session_data_array[1];
667     TPMS_AUTH_RESPONSE *session_data_out_array[1];
668
669     session_data_array[0] = &ctx->sessionData;
670     sessions_data.cmdAuths = &session_data_array[0];
671     session_data_out_array[0] = &session_data_out;
672     sessions_data_out.rspAuths = &session_data_out_array[0];
673     sessions_data_out.rspAuthsCount = 1;
674     sessions_data.cmdAuthsCount = 1;
675
676     int rc = tpm_hash_compute_data(ctx->sapi_context, ctx->msg, ctx->length, ctx->halg, &digest);
677     if (rc) {
678         printf("Compute message hash failed!");
679         return false;
680     }
681
682     bool result = set_scheme(ctx->sapi_context, ctx->keyHandle, ctx->halg, &in_scheme);
683     if (!result) {
684         return false;
685     }
686
687     TPM_RC rval = Tss2_Sys_Sign(ctx->sapi_context, ctx->keyHandle,
688                                 &sessions_data, &digest, &in_scheme,
689                                 &ctx->validation, &signature,
690                                 &sessions_data_out);
691
692     if (rval != TPM_RC_SUCCESS) {
693         printf("Sys_Sign failed, error code: 0x%x", rval);
694         return false;
695     }
696     signature_len = sizeof(signature);
697     sig_len = &signature_len;
698     sig = (unsigned char *)&signature;
699
700     return true;
701 }
702
703 int tpm2_plugin_rsa_sign(
704         void  *keyHandle,
705         unsigned long mechanism,
706         unsigned char *msg,
707         int msg_len,
708         unsigned char *sig,
709         int *sig_len)
710 {
711     TPM_RC rval;
712     common_opts_t opts = COMMON_OPTS_INITIALIZER;
713     TSS2_TCTI_CONTEXT *tcti_ctx;
714     tcti_ctx = tcti_init_from_options(&opts);
715     if (tcti_ctx == NULL)
716         return -1;
717
718     TSS2_SYS_CONTEXT *sapi_context = NULL;
719     if (tcti_ctx) {
720        sapi_context = sapi_ctx_init(tcti_ctx);
721        if (!sapi_context) {
722            free(tcti_ctx);
723            return -1;
724        }
725     }
726
727     tpm_sign_ctx ctx = {
728             .msg = NULL,
729             .sessionData = { 0 },
730             .halg = 0,
731             .keyHandle = 0,
732             .validation = { 0 },
733             .sapi_context = sapi_context
734     };
735     
736     printf("rsa_sign API mechanism is %lx \n", mechanism);
737     ctx.sessionData.sessionHandle = TPM_RS_PW;
738     ctx.validation.tag = TPM_ST_HASHCHECK;
739     ctx.validation.hierarchy = TPM_RH_NULL;
740     ctx.halg = TPM_ALG_SHA256;
741     ctx.keyHandle = *(TPMI_DH_OBJECT *)keyHandle;
742
743     rval = Tss2_Sys_ContextLoad(ctx.sapi_context, &loaded_key_context, &ctx.keyHandle);
744     if (rval != TPM_RC_SUCCESS) {
745         printf("ContextLoad Error in RSA Sign API. TPM Error:0x%x", rval);
746         goto out;
747     }
748     ctx.length = msg_len;
749     ctx.msg = msg;
750
751     if (!sign_and_save(&ctx, sig, sig_len)){
752         printf("RSA sign failed\n");
753         goto out;
754     }
755
756     printf("RSA sign API successful in TPM plugin ! \n");
757
758 out:
759     sapi_teardown_full(sapi_context);
760
761     return 0;
762
763 }
764
765