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