1 /* Copyright 2018 Intel Corporation, Inc
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
7 * http://www.apache.org/licenses/LICENSE-2.0
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.
16 #include <sapi/tpm20.h>
20 #include "tpm2_plugin_api.h"
22 #include <tcti/tcti_device.h>
25 #include <tcti/tcti_socket.h>
27 #ifdef HAVE_TCTI_TABRMD
28 #include <tcti/tcti-tabrmd.h>
30 bool output_enabled = true;
31 bool hexPasswd = false;
32 TPM_HANDLE handle2048rsa;
33 const char *tcti_path="libtss2-tcti-device.so";
35 static void tcti_teardown(TSS2_TCTI_CONTEXT *tcti_context)
37 if (tcti_context == NULL)
39 tss2_tcti_finalize (tcti_context);
43 static void sapi_teardown(TSS2_SYS_CONTEXT *sapi_context)
45 if (sapi_context == NULL)
47 Tss2_Sys_Finalize (sapi_context);
51 static void sapi_teardown_full (TSS2_SYS_CONTEXT *sapi_context)
53 TSS2_TCTI_CONTEXT *tcti_context = NULL;
56 rc = Tss2_Sys_GetTctiContext (sapi_context, &tcti_context);
57 if (rc != TSS2_RC_SUCCESS)
59 sapi_teardown (sapi_context);
60 tcti_teardown (tcti_context);
63 int tpm2_plugin_init()
65 printf("Init API done for TPM plugin ! \n");
69 int tpm2_plugin_uninit()
71 printf("UnInit API done for TPM plugin ! \n");
75 TPM_HANDLE srk_handle;
76 int tpm2_plugin_activate(SSHSM_HW_PLUGIN_ACTIVATE_LOAD_IN_INFO_t *activate_in_info)
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");
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");
94 TPMI_DH_OBJECT handle_load;
98 tcti_device_init (char const *device_file)
100 TCTI_DEVICE_CONF conf = {
101 .device_path = device_file,
107 TSS2_TCTI_CONTEXT *tcti_ctx;
109 rc = InitDeviceTcti (NULL, &size, 0);
110 if (rc != TSS2_RC_SUCCESS) {
112 "Failed to get allocation size for device tcti context: "
116 tcti_ctx = (TSS2_TCTI_CONTEXT*)calloc (1, size);
117 if (tcti_ctx == NULL) {
119 "Allocation for device TCTI context failed: %s\n",
123 rc = InitDeviceTcti (tcti_ctx, &size, &conf);
124 if (rc != TSS2_RC_SUCCESS) {
126 "Failed to initialize device TCTI context: 0x%x\n",
136 #ifdef HAVE_TCTI_SOCK
137 TSS2_TCTI_CONTEXT* tcti_socket_init (char const *address, uint16_t port)
139 TCTI_SOCKET_CONF conf = {
143 .logBufferCallback = NULL,
148 TSS2_TCTI_CONTEXT *tcti_ctx;
150 rc = InitSocketTcti (NULL, &size, &conf, 0);
151 if (rc != TSS2_RC_SUCCESS) {
152 fprintf (stderr, "Faled to get allocation size for tcti context: "
156 tcti_ctx = (TSS2_TCTI_CONTEXT*)calloc (1, size);
157 if (tcti_ctx == NULL) {
158 fprintf (stderr, "Allocation for tcti context failed: %s\n",
162 rc = InitSocketTcti (tcti_ctx, &size, &conf, 0);
163 if (rc != TSS2_RC_SUCCESS) {
164 fprintf (stderr, "Failed to initialize tcti context: 0x%x\n", rc);
171 #ifdef HAVE_TCTI_TABRMD
172 TSS2_TCTI_CONTEXT *tcti_tabrmd_init (void)
174 TSS2_TCTI_CONTEXT *tcti_ctx;
178 rc = tss2_tcti_tabrmd_init(NULL, &size);
179 if (rc != TSS2_RC_SUCCESS) {
180 printf("Failed to get size for TABRMD TCTI context: 0x%x", rc);
183 tcti_ctx = (TSS2_TCTI_CONTEXT*)calloc (1, size);
184 if (tcti_ctx == NULL) {
185 printf("Allocation for TABRMD TCTI context failed: %s", strerror (errno));
188 rc = tss2_tcti_tabrmd_init (tcti_ctx, &size);
189 if (rc != TSS2_RC_SUCCESS) {
190 printf("Failed to initialize TABRMD TCTI context: 0x%x", rc);
197 TSS2_TCTI_CONTEXT *tcti_init_from_options(common_opts_t *options)
199 switch (options->tcti_type) {
202 return tcti_device_init (options->device_file);
204 #ifdef HAVE_TCTI_SOCK
206 return tcti_socket_init (options->socket_address,
207 options->socket_port);
209 #ifdef HAVE_TCTI_TABRMD
211 return tcti_tabrmd_init ();
218 static TSS2_SYS_CONTEXT *sapi_ctx_init (TSS2_TCTI_CONTEXT *tcti_ctx)
220 TSS2_SYS_CONTEXT *sapi_ctx;
223 TSS2_ABI_VERSION abi_version = {
224 .tssCreator = TSSWG_INTEROP,
225 .tssFamily = TSS_SAPI_FIRST_FAMILY,
226 .tssLevel = TSS_SAPI_FIRST_LEVEL,
227 .tssVersion = TSS_SAPI_FIRST_VERSION,
230 size = Tss2_Sys_GetContextSize (0);
231 sapi_ctx = (TSS2_SYS_CONTEXT*)calloc (1, size);
232 if (sapi_ctx == NULL) {
234 "Failed to allocate 0x%zx bytes for the SAPI context\n",
238 rc = Tss2_Sys_Initialize (sapi_ctx, size, tcti_ctx, &abi_version);
239 if (rc != TSS2_RC_SUCCESS) {
240 fprintf (stderr, "Failed to initialize SAPI context: 0x%x\n", rc);
247 #define BUFFER_SIZE(type, field) (sizeof((((type *)NULL)->t.field)))
248 #define TPM2B_TYPE_INIT(type, field) { .t = { .size = BUFFER_SIZE(type, field), }, }
249 TPMS_AUTH_COMMAND sessionData;
250 int hex2ByteStructure(const char *inStr, UINT16 *byteLength, BYTE *byteBuffer)
252 int strLength;//if the inStr likes "1a2b...", no prefix "0x"
254 if(inStr == NULL || byteLength == NULL || byteBuffer == NULL)
256 strLength = strlen(inStr);
259 for(i = 0; i < strLength; i++)
261 if(!isxdigit(inStr[i]))
265 if(*byteLength < strLength/2)
268 *byteLength = strLength/2;
270 for(i = 0; i < *byteLength; i++)
272 char tmpStr[4] = {0};
273 tmpStr[0] = inStr[i*2];
274 tmpStr[1] = inStr[i*2+1];
275 byteBuffer[i] = strtol(tmpStr, NULL, 16);
279 int load_key(TSS2_SYS_CONTEXT *sapi_context,
280 TPMI_DH_OBJECT parentHandle,
281 TPM2B_PUBLIC *inPublic,
282 TPM2B_PRIVATE *inPrivate,
286 TPMS_AUTH_RESPONSE sessionDataOut;
287 TSS2_SYS_CMD_AUTHS sessionsData;
288 TSS2_SYS_RSP_AUTHS sessionsDataOut;
289 TPMS_AUTH_COMMAND *sessionDataArray[1];
290 TPMS_AUTH_RESPONSE *sessionDataOutArray[1];
292 TPM2B_NAME nameExt = TPM2B_TYPE_INIT(TPM2B_NAME, name);
294 sessionDataArray[0] = &sessionData;
295 sessionDataOutArray[0] = &sessionDataOut;
297 sessionsDataOut.rspAuths = &sessionDataOutArray[0];
298 sessionsData.cmdAuths = &sessionDataArray[0];
300 sessionsDataOut.rspAuthsCount = 1;
301 sessionsData.cmdAuthsCount = 1;
303 sessionData.sessionHandle = TPM_RS_PW;
304 sessionData.nonce.t.size = 0;
307 sessionData.hmac.t.size = 0;
309 *((UINT8 *)((void *)&sessionData.sessionAttributes)) = 0;
310 if (sessionData.hmac.t.size > 0 && hexPasswd)
312 sessionData.hmac.t.size = sizeof(sessionData.hmac) - 2;
313 if (hex2ByteStructure((char *)sessionData.hmac.t.buffer,
314 &sessionData.hmac.t.size,
315 sessionData.hmac.t.buffer) != 0)
317 printf( "Failed to convert Hex format password for parent Passwd.\n");
322 rval = Tss2_Sys_Load (sapi_context,
330 if(rval != TPM_RC_SUCCESS)
332 printf("\nLoad Object Failed ! ErrorCode: 0x%0x\n\n",rval);
335 printf("\nLoad succ.\nLoadedHandle: 0x%08x\n\n",handle2048rsa);
340 TPMS_CONTEXT loaded_key_context;
342 int load_key_execute(SSHSM_HW_PLUGIN_ACTIVATE_LOAD_IN_INFO_t *loadkey_in_info,
343 void **keyHandle, TSS2_SYS_CONTEXT *sapi_context)
346 TPMI_DH_OBJECT parentHandle;
347 TPM2B_PUBLIC inPublic;
348 TPM2B_PRIVATE inPrivate;
352 memset(&inPublic,0,sizeof(TPM2B_PUBLIC));
353 memset(&inPrivate,0,sizeof(TPM2B_SENSITIVE));
355 setbuf(stdout, NULL);
356 setvbuf (stdout, NULL, _IONBF, BUFSIZ);
358 //parentHandle = 0x81000011;
359 parentHandle = srk_handle;
361 if (loadkey_in_info->num_buffers != 2)
363 memcpy(&inPublic, loadkey_in_info->buffer_info[0]->buffer,
364 loadkey_in_info->buffer_info[0]->length_of_buffer);
365 memcpy(&inPrivate, loadkey_in_info->buffer_info[1]->buffer,
366 loadkey_in_info->buffer_info[1]->length_of_buffer);
368 printf("we are here now\n");
369 returnVal = load_key (sapi_context,
375 TPM_RC rval = Tss2_Sys_ContextSave(sapi_context, handle2048rsa, &loaded_key_context);
376 if (rval != TPM_RC_SUCCESS) {
377 printf("Tss2_Sys_ContextSave: Saving handle 0x%x context failed. TPM Error:0x%x", handle2048rsa, rval);
380 *keyHandle = &handle2048rsa;
384 int tpm2_plugin_load_key(SSHSM_HW_PLUGIN_ACTIVATE_LOAD_IN_INFO_t *loadkey_in_info,
388 common_opts_t opts = COMMON_OPTS_INITIALIZER;
389 TSS2_TCTI_CONTEXT *tcti_ctx;
390 tcti_ctx = tcti_init_from_options(&opts);
391 if (tcti_ctx == NULL)
394 TSS2_SYS_CONTEXT *sapi_context = NULL;
396 sapi_context = sapi_ctx_init(tcti_ctx);
403 ret = load_key_execute(loadkey_in_info, keyHandle, sapi_context);
405 printf("Load key API failed in TPM plugin ! \n");
407 sapi_teardown_full(sapi_context);
409 printf("Load key API successful in TPM plugin ! \n");
414 typedef struct tpm_sign_ctx tpm_sign_ctx;
415 struct tpm_sign_ctx {
416 TPMT_TK_HASHCHECK validation;
417 TPMS_AUTH_COMMAND sessionData;
418 TPMI_DH_OBJECT keyHandle;
420 char outFilePath[PATH_MAX];
423 TSS2_SYS_CONTEXT *sapi_context;
426 int tpm2_plugin_rsa_sign_init(
428 unsigned long mechanism,
432 printf("rsa_sign_init API mechanism is %lx \n", mechanism);
433 printf("rsa_sign_init API done for tpm2_plugin... \n");
437 UINT32 tpm_hash(TSS2_SYS_CONTEXT *sapi_context, TPMI_ALG_HASH hashAlg,
438 UINT16 size, BYTE *data, TPM2B_DIGEST *result) {
439 TPM2B_MAX_BUFFER dataSizedBuffer;
441 dataSizedBuffer.t.size = size;
442 memcpy(dataSizedBuffer.t.buffer, data, size);
443 return Tss2_Sys_Hash(sapi_context, 0, &dataSizedBuffer, hashAlg,
444 TPM_RH_NULL, result, 0, 0);
447 static TPM_RC hash_sequence_ex(TSS2_SYS_CONTEXT *sapi_context,
449 TPMI_ALG_HASH hashAlg, UINT32 numBuffers, TPM2B_MAX_BUFFER *bufferList,
450 TPM2B_DIGEST *result) {
453 TPMI_DH_OBJECT sequenceHandle;
455 TPMT_TK_HASHCHECK validation;
457 TPMS_AUTH_COMMAND cmdAuth;
458 TPMS_AUTH_COMMAND *cmdSessionArray[1] = { &cmdAuth };
459 TSS2_SYS_CMD_AUTHS cmdAuthArray = { 1, &cmdSessionArray[0] };
462 emptyBuffer.size = 0;
464 // Set result size to 0, in case any errors occur
467 // Init input sessions struct
468 cmdAuth.sessionHandle = TPM_RS_PW;
469 cmdAuth.nonce.t.size = 0;
470 *((UINT8 *) ((void *) &cmdAuth.sessionAttributes)) = 0;
471 cmdAuth.hmac.t.size = 0;
473 rval = Tss2_Sys_HashSequenceStart(sapi_context, 0, &nullAuth, hashAlg,
475 if (rval != TPM_RC_SUCCESS) {
480 for (i = 0; i < numBuffers; i++) {
481 rval = Tss2_Sys_SequenceUpdate(sapi_context, sequenceHandle,
482 &cmdAuthArray, &bufferList[i], 0);
484 if (rval != TPM_RC_SUCCESS) {
489 rval = Tss2_Sys_SequenceComplete(sapi_context, sequenceHandle,
490 &cmdAuthArray, (TPM2B_MAX_BUFFER *) &emptyBuffer,
491 TPM_RH_PLATFORM, result, &validation, 0);
493 if (rval != TPM_RC_SUCCESS) {
500 int tpm_hash_compute_data(TSS2_SYS_CONTEXT *sapi_context, BYTE *buffer,
501 UINT16 length, TPMI_ALG_HASH halg, TPM2B_DIGEST *result) {
503 if (length <= MAX_DIGEST_BUFFER) {
504 if (tpm_hash(sapi_context, halg, length, buffer,
505 result) == TPM_RC_SUCCESS)
511 UINT8 numBuffers = (length - 1) / MAX_DIGEST_BUFFER + 1;
513 TPM2B_MAX_BUFFER *bufferList = (TPM2B_MAX_BUFFER *) calloc(numBuffers,
514 sizeof(TPM2B_MAX_BUFFER));
515 if (bufferList == NULL)
519 for (i = 0; i < (UINT32)(numBuffers - 1); i++) {
520 bufferList[i].t.size = MAX_DIGEST_BUFFER;
521 memcpy(bufferList[i].t.buffer, buffer + i * MAX_DIGEST_BUFFER,
524 bufferList[i].t.size = length - i * MAX_DIGEST_BUFFER;
525 memcpy(bufferList[i].t.buffer, buffer + i * MAX_DIGEST_BUFFER,
526 bufferList[i].t.size);
528 TPM_RC rval = hash_sequence_ex(sapi_context, halg, numBuffers, bufferList, result);
530 return rval == TPM_RC_SUCCESS ? 0 : -3;
534 static bool get_key_type(TSS2_SYS_CONTEXT *sapi_context, TPMI_DH_OBJECT objectHandle,
535 TPMI_ALG_PUBLIC *type) {
537 TPMS_AUTH_RESPONSE session_data_out;
539 TPMS_AUTH_RESPONSE *session_data_out_array[1] = {
543 TSS2_SYS_RSP_AUTHS sessions_data_out = {
545 &session_data_out_array[0]
548 TPM2B_PUBLIC out_public = {
552 TPM2B_NAME name = TPM2B_TYPE_INIT(TPM2B_NAME, name);
554 TPM2B_NAME qaulified_name = TPM2B_TYPE_INIT(TPM2B_NAME, name);
556 TPM_RC rval = Tss2_Sys_ReadPublic(sapi_context, objectHandle, 0, &out_public, &name,
557 &qaulified_name, &sessions_data_out);
558 if (rval != TPM_RC_SUCCESS) {
559 printf("Sys_ReadPublic failed, error code: 0x%x", rval);
562 *type = out_public.t.publicArea.type;
566 static bool set_scheme(TSS2_SYS_CONTEXT *sapi_context, TPMI_DH_OBJECT keyHandle,
567 TPMI_ALG_HASH halg, TPMT_SIG_SCHEME *inScheme) {
570 bool result = get_key_type(sapi_context, keyHandle, &type);
577 inScheme->scheme = TPM_ALG_RSASSA;
578 inScheme->details.rsassa.hashAlg = halg;
580 case TPM_ALG_KEYEDHASH :
581 inScheme->scheme = TPM_ALG_HMAC;
582 inScheme->details.hmac.hashAlg = halg;
585 inScheme->scheme = TPM_ALG_ECDSA;
586 inScheme->details.ecdsa.hashAlg = halg;
588 case TPM_ALG_SYMCIPHER :
590 printf("Unknown key type, got: 0x%x", type);
596 static bool sign_and_save(tpm_sign_ctx *ctx, unsigned char *sig, int *sig_len) {
597 TPM2B_DIGEST digest = TPM2B_TYPE_INIT(TPM2B_DIGEST, buffer);
599 TPMT_SIG_SCHEME in_scheme;
600 TPMT_SIGNATURE signature;
602 TSS2_SYS_CMD_AUTHS sessions_data;
603 TPMS_AUTH_RESPONSE session_data_out;
604 TSS2_SYS_RSP_AUTHS sessions_data_out;
605 TPMS_AUTH_COMMAND *session_data_array[1];
606 TPMS_AUTH_RESPONSE *session_data_out_array[1];
608 session_data_array[0] = &ctx->sessionData;
609 sessions_data.cmdAuths = &session_data_array[0];
610 session_data_out_array[0] = &session_data_out;
611 sessions_data_out.rspAuths = &session_data_out_array[0];
612 sessions_data_out.rspAuthsCount = 1;
613 sessions_data.cmdAuthsCount = 1;
615 int rc = tpm_hash_compute_data(ctx->sapi_context, ctx->msg, ctx->length, ctx->halg, &digest);
617 printf("Compute message hash failed!");
621 bool result = set_scheme(ctx->sapi_context, ctx->keyHandle, ctx->halg, &in_scheme);
626 TPM_RC rval = Tss2_Sys_Sign(ctx->sapi_context, ctx->keyHandle,
627 &sessions_data, &digest, &in_scheme,
628 &ctx->validation, &signature,
631 if (rval != TPM_RC_SUCCESS) {
632 printf("Sys_Sign failed, error code: 0x%x", rval);
635 signature_len = sizeof(signature);
636 sig_len = &signature_len;
637 sig = (unsigned char *)&signature;
642 int tpm2_plugin_rsa_sign(
644 unsigned long mechanism,
651 common_opts_t opts = COMMON_OPTS_INITIALIZER;
652 TSS2_TCTI_CONTEXT *tcti_ctx;
653 tcti_ctx = tcti_init_from_options(&opts);
654 if (tcti_ctx == NULL)
657 TSS2_SYS_CONTEXT *sapi_context = NULL;
659 sapi_context = sapi_ctx_init(tcti_ctx);
668 .sessionData = { 0 },
672 .sapi_context = sapi_context
675 printf("rsa_sign API mechanism is %lx \n", mechanism);
676 ctx.sessionData.sessionHandle = TPM_RS_PW;
677 ctx.validation.tag = TPM_ST_HASHCHECK;
678 ctx.validation.hierarchy = TPM_RH_NULL;
679 ctx.halg = TPM_ALG_SHA256;
680 ctx.keyHandle = *(TPMI_DH_OBJECT *)keyHandle;
682 rval = Tss2_Sys_ContextLoad(ctx.sapi_context, &loaded_key_context, &ctx.keyHandle);
683 if (rval != TPM_RC_SUCCESS) {
684 printf("ContextLoad Error in RSA Sign API. TPM Error:0x%x", rval);
687 ctx.length = msg_len;
690 if (!sign_and_save(&ctx, sig, sig_len)){
691 printf("RSA sign failed\n");
695 printf("RSA sign API successful in TPM plugin ! \n");
698 sapi_teardown_full(sapi_context);