d63550e4fd5b9666d56b58f08d9f716aa36a5191
[aaf/sshsm.git] / TPM2-Plugin / lib / tpm2_plugin_api.c
1 //**********************************************************************;
2 // Copyright (c) 2017, Intel Corporation
3 // All rights reserved.
4 //
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are met:
7 //
8 // 1. Redistributions of source code must retain the above copyright notice,
9 // this list of conditions and the following disclaimer.
10 //
11 // 2. Redistributions in binary form must reproduce the above copyright notice,
12 // this list of conditions and the following disclaimer in the documentation
13 // and/or other materials provided with the distribution.
14 //
15 // 3. Neither the name of Intel Corporation nor the names of its contributors
16 // may be used to endorse or promote products derived from this software without
17 // specific prior written permission.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
29 // THE POSSIBILITY OF SUCH DAMAGE.
30 //**********************************************************************;
31
32 #include <tss2/tss2_sys.h>
33 #include <stdbool.h>
34 #include <unistd.h>
35 #include "tpm2_plugin_api.h"
36 #include "tpm2_convert.h"
37 #include "tpm2_tcti_ldr.h"
38 #include "tpm2_tool.h"
39 #include "tpm2_hash.h"
40 #include "tpm2_alg_util.h"
41 #include "log.h"
42 #include "files.h"
43
44 bool output_enabled = true;
45
46 const char *tcti_path="libtss2-tcti-device.so";
47
48 static void tcti_teardown (TSS2_TCTI_CONTEXT *tcti_context)
49 {
50
51     Tss2_Tcti_Finalize (tcti_context);
52     free (tcti_context);
53 }
54
55 static void sapi_teardown (TSS2_SYS_CONTEXT *sapi_context)
56 {
57
58     if (sapi_context == NULL)
59         return;
60     Tss2_Sys_Finalize (sapi_context);
61     free (sapi_context);
62 }
63
64 static void sapi_teardown_full (TSS2_SYS_CONTEXT *sapi_context)
65 {
66
67     TSS2_TCTI_CONTEXT *tcti_context = NULL;
68     TSS2_RC rc;
69
70     rc = Tss2_Sys_GetTctiContext (sapi_context, &tcti_context);
71     if (rc != TPM2_RC_SUCCESS)
72         return;
73     sapi_teardown (sapi_context);
74     tcti_teardown (tcti_context);
75 }
76
77 #define SUPPORTED_ABI_VERSION \
78 { \
79     .tssCreator = 1, \
80     .tssFamily = 2, \
81     .tssLevel = 1, \
82     .tssVersion = 108, \
83 }
84
85 static TSS2_SYS_CONTEXT* sapi_ctx_init(TSS2_TCTI_CONTEXT *tcti_ctx)
86 {
87
88     TSS2_ABI_VERSION abi_version = SUPPORTED_ABI_VERSION;
89
90     size_t size = Tss2_Sys_GetContextSize(0);
91     TSS2_SYS_CONTEXT *sapi_ctx = (TSS2_SYS_CONTEXT*) calloc(1, size);
92     if (sapi_ctx == NULL) {
93         LOG_ERR("Failed to allocate 0x%zx bytes for the SAPI context\n",
94                 size);
95         return NULL;
96     }
97
98     TSS2_RC rval = Tss2_Sys_Initialize(sapi_ctx, size, tcti_ctx, &abi_version);
99     if (rval != TPM2_RC_SUCCESS) {
100         LOG_PERR(Tss2_Sys_Initialize, rval);
101         free(sapi_ctx);
102         return NULL;
103     }
104
105     return sapi_ctx;
106 }
107
108
109 int tpm2_plugin_init()
110 {
111     printf("Init API done for TPM plugin ! \n");
112     return 0;
113 }
114
115 int tpm2_plugin_uninit()
116 {
117     printf("UnInit API done for TPM plugin ! \n");
118     return 0;
119 }
120
121 TPM2_HANDLE srk_handle;
122 int tpm2_plugin_activate(SSHSM_HW_PLUGIN_ACTIVATE_LOAD_IN_INFO_t *activate_in_info)
123 {
124     /*
125     */
126     char *handle;
127     printf("number of buffers %d ! \n", activate_in_info->num_buffers);
128     if (activate_in_info->num_buffers!=1){
129         printf("activate failed ! \n");
130         return 1;
131     }
132     printf("number of buffers %d ! \n", activate_in_info->num_buffers);
133     handle = malloc(activate_in_info->buffer_info[0]->length_of_buffer);
134     memcpy(handle, activate_in_info->buffer_info[0]->buffer, activate_in_info->buffer_info[0]->length_of_buffer);
135     srk_handle = strtol(handle, NULL, 16);
136     printf("Activate API done for TPM plugin ! \n");
137     return 0;
138 }
139
140 TPM2_HANDLE handle_load;
141
142 typedef struct tpm_load_ctx tpm_load_ctx;
143 struct tpm_load_ctx {
144     TPMS_AUTH_COMMAND session_data;
145     TPMI_DH_OBJECT parent_handle;
146     TPM2B_PUBLIC  in_public;
147     TPM2B_PRIVATE in_private;
148     char *out_file;
149     char *context_file;
150     char *context_parent_file;
151     struct {
152         UINT8 H : 1;
153         UINT8 u : 1;
154         UINT8 r : 1;
155         UINT8 c : 1;
156         UINT8 C : 1;
157     } flags;
158 };
159
160 static tpm_load_ctx ctx_load = {
161     .session_data = {
162         .sessionHandle = TPM2_RS_PW,
163         .nonce = TPM2B_EMPTY_INIT,
164         .hmac = TPM2B_EMPTY_INIT,
165         .sessionAttributes = 0
166     }
167 };
168
169 int load (TSS2_SYS_CONTEXT *sapi_context) {
170     UINT32 rval;
171     TSS2L_SYS_AUTH_COMMAND sessionsData;
172     TSS2L_SYS_AUTH_RESPONSE sessionsDataOut;
173
174     TPM2B_NAME nameExt = TPM2B_TYPE_INIT(TPM2B_NAME, name);
175
176     sessionsData.count = 1;
177     sessionsData.auths[0] = ctx_load.session_data;
178
179     rval = TSS2_RETRY_EXP(Tss2_Sys_Load(sapi_context,
180                          ctx_load.parent_handle,
181                          &sessionsData,
182                          &ctx_load.in_private,
183                          &ctx_load.in_public,
184                          &handle_load,
185                          &nameExt,
186                          &sessionsDataOut));
187     if(rval != TPM2_RC_SUCCESS)
188     {
189         LOG_PERR(Tss2_Sys_Load, rval);
190         return -1;
191     }
192     tpm2_tool_output("handle_load: 0x%08x\n", handle_load);
193
194     if (ctx_load.out_file) {
195         if(!files_save_bytes_to_file(ctx_load.out_file, nameExt.name, nameExt.size)) {
196             return -2;
197         }
198     }
199
200     return 0;
201 }
202
203 int tpm2_tool_load_key(TSS2_SYS_CONTEXT *sapi_context)
204 {
205
206     int returnVal = 0;
207
208     if ((!ctx_load.flags.H && !ctx_load.flags.c) || (!ctx_load.flags.u || !ctx_load.flags.r)) {
209         LOG_ERR("Expected options (H or c) and u and r");
210         return 1;
211     }
212
213     if(ctx_load.flags.c) {
214         returnVal = files_load_tpm_context_from_path(sapi_context,
215                                                &ctx_load.parent_handle,
216                                                ctx_load.context_parent_file) != true;
217         if (returnVal) {
218             return 1;
219         }
220     }
221
222     returnVal = load(sapi_context);
223     if (returnVal) {
224         return 1;
225     }
226
227     if (ctx_load.flags.C) {
228         returnVal = files_save_tpm_context_to_path (sapi_context,
229                                                     handle_load,
230                                                     ctx_load.context_file) != true;
231         if (returnVal) {
232             return 1;
233         }
234     }
235
236     return 0;
237 }
238
239 int tpm2_plugin_load_key(
240            SSHSM_HW_PLUGIN_ACTIVATE_LOAD_IN_INFO_t *loadkey_in_info,
241            void **keyHandle
242         )
243 {
244     int ret = 1;
245     TSS2_TCTI_CONTEXT *tcti;
246     tcti = tpm2_tcti_ldr_load(tcti_path, NULL);
247     if (!tcti) {
248         LOG_ERR("Could not load tcti, got: \"%s\"", tcti_path);
249         return -1;
250     }
251
252     TSS2_SYS_CONTEXT *sapi_context = NULL;
253     if (tcti) {
254         sapi_context = sapi_ctx_init(tcti);
255         if (!sapi_context) {
256             goto free_tcti;
257         }
258     }
259
260     ret = tpm2_tool_load_key(sapi_context);
261     if (ret != 0) {
262         LOG_ERR("Unable to run tpm2_tool_iload_key");
263     sapi_teardown_full(sapi_context);
264
265 free_tcti:
266     tpm2_tcti_ldr_unload();
267     return ret;
268     }
269
270     printf("Load key API done for TPM plugin ! \n");
271     return 0;
272
273 }
274
275 typedef struct tpm_sign_ctx tpm_sign_ctx;
276 struct tpm_sign_ctx {
277     TPMT_TK_HASHCHECK validation;
278     TPMS_AUTH_COMMAND sessionData;
279     TPMI_DH_OBJECT keyHandle;
280     TPMI_ALG_HASH halg;
281     TPM2B_DIGEST digest;
282     char *outFilePath;
283     BYTE *msg;
284     UINT16 length;
285     char *contextKeyFile;
286     char *inMsgFileName;
287     tpm2_convert_sig_fmt sig_format;
288     struct {
289         UINT16 k : 1;
290         UINT16 P : 1;
291         UINT16 g : 1;
292         UINT16 m : 1;
293         UINT16 t : 1;
294         UINT16 s : 1;
295         UINT16 c : 1;
296         UINT16 f : 1;
297         UINT16 D : 1;
298     } flags;
299 };
300
301 tpm_sign_ctx ctx_sign = {
302         .msg = NULL,
303         .sessionData = TPMS_AUTH_COMMAND_INIT(TPM2_RS_PW),
304         .halg = TPM2_ALG_SHA1,
305         .digest = TPM2B_TYPE_INIT(TPM2B_DIGEST, buffer),
306 };
307
308
309 int tpm2_plugin_rsa_sign_init(
310         void *keyHandle,
311         unsigned long mechanish,
312         void *param,
313         int len)
314 {
315     printf("rsa_sign_init API done for tpm2_plugin... \n");
316     return 0;
317 }
318
319 static bool init_sign(TSS2_SYS_CONTEXT *sapi_context) {
320
321     if (!((ctx_sign.flags.k || ctx_sign.flags.c) && (ctx_sign.flags.m || ctx_sign.flags.D) && ctx_sign.flags.s)) {
322         LOG_ERR("Expected options (k or c) and (m or D) and s");
323         return false;
324     }
325
326     if (ctx_sign.flags.D && (ctx_sign.flags.t || ctx_sign.flags.m)) {
327         LOG_WARN("Option D provided, options m and t are ignored.");
328     }
329
330     if (ctx_sign.flags.D || !ctx_sign.flags.t) {
331         ctx_sign.validation.tag = TPM2_ST_HASHCHECK;
332         ctx_sign.validation.hierarchy = TPM2_RH_NULL;
333         memset(&ctx_sign.validation.digest, 0, sizeof(ctx_sign.validation.digest));
334     }
335
336     /*
337      * load tpm context from a file if -c is provided
338      */
339     if (ctx_sign.flags.c) {
340         bool result = files_load_tpm_context_from_path(sapi_context, &ctx_sign.keyHandle,
341                 ctx_sign.contextKeyFile);
342         if (!result) {
343             return false;
344         }
345     }
346
347     /*
348      * Process the msg file if needed
349      */
350     if (ctx_sign.flags.m && !ctx_sign.flags.D) {
351       unsigned long file_size;
352       bool result = files_get_file_size_path(ctx_sign.inMsgFileName, &file_size);
353       if (!result) {
354           return false;
355       }
356       if (file_size == 0) {
357           LOG_ERR("The message file \"%s\" is empty!", ctx_sign.inMsgFileName);
358           return false;
359       }
360
361       if (file_size > UINT16_MAX) {
362           LOG_ERR(
363                   "The message file \"%s\" is too large, got: %lu bytes, expected less than: %u bytes!",
364                   ctx_sign.inMsgFileName, file_size, UINT16_MAX + 1);
365           return false;
366       }
367
368       ctx_sign.msg = (BYTE*) calloc(required_argument, file_size);
369       if (!ctx_sign.msg) {
370           LOG_ERR("oom");
371           return false;
372       }
373
374       ctx_sign.length = file_size;
375       result = files_load_bytes_from_path(ctx_sign.inMsgFileName, ctx_sign.msg, &ctx_sign.length);
376       if (!result) {
377           free(ctx_sign.msg);
378           return false;
379       }
380     }
381
382     return true;
383 }
384
385
386 static bool sign_and_save(TSS2_SYS_CONTEXT *sapi_context) {
387
388     TPMT_SIG_SCHEME in_scheme;
389     TPMT_SIGNATURE signature;
390
391     TSS2L_SYS_AUTH_COMMAND sessions_data = { 1, { ctx_sign.sessionData }};
392     TSS2L_SYS_AUTH_RESPONSE sessions_data_out;
393
394     if (!ctx_sign.flags.D) {
395       bool res = tpm2_hash_compute_data(sapi_context, ctx_sign.halg, TPM2_RH_NULL,
396               ctx_sign.msg, ctx_sign.length, &ctx_sign.digest, NULL);
397       if (!res) {
398           LOG_ERR("Compute message hash failed!");
399           return false;
400       }
401     }
402
403     bool result = get_signature_scheme(sapi_context, ctx_sign.keyHandle, ctx_sign.halg, &in_scheme);
404     if (!result) {
405         return false;
406     }
407
408     TSS2_RC rval = TSS2_RETRY_EXP(Tss2_Sys_Sign(sapi_context, ctx_sign.keyHandle,
409             &sessions_data, &ctx_sign.digest, &in_scheme, &ctx_sign.validation, &signature,
410             &sessions_data_out));
411     if (rval != TPM2_RC_SUCCESS) {
412         LOG_PERR(Tss2_Sys_Sign, rval);
413         return false;
414     }
415
416     return tpm2_convert_sig(&signature, ctx_sign.sig_format, ctx_sign.outFilePath);
417 }
418
419
420 int tpm2_tool_sign(TSS2_SYS_CONTEXT *sapi_context)
421 {
422
423     bool result = init_sign(sapi_context);
424     if (!result) {
425         return 1;
426     }
427
428     result = sign_and_save(sapi_context);
429
430     free(ctx_sign.msg);
431
432     return result != true;
433 }
434
435
436 int tpm2_plugin_rsa_sign(
437         void  *keyHandle,
438         unsigned long mechanism,
439         unsigned char *msg,
440         int msg_len,
441         unsigned char *sig,
442         int *sig_len)
443 {
444     int ret = 1;
445     TSS2_TCTI_CONTEXT *tcti;
446     tcti = tpm2_tcti_ldr_load(tcti_path, NULL);
447     if (!tcti) {
448         LOG_ERR("Could not load tcti, got: \"%s\"", tcti_path);
449         return -1;
450     }
451     
452     TSS2_SYS_CONTEXT *sapi_context = NULL;
453     if (tcti) {
454         sapi_context = sapi_ctx_init(tcti);
455         if (!sapi_context) {
456             goto free_tcti;
457         }
458     }
459     
460     ret = tpm2_tool_sign(sapi_context);
461     if (ret != 0) {
462         LOG_ERR("Unable to run tpm2_tool_sign");
463     sapi_teardown_full(sapi_context);
464
465 free_tcti:
466     tpm2_tcti_ldr_unload();
467     return ret;
468     }
469     printf("rsa_sign API done for tpm2_plugin... \n");
470 }
471
472 int tpm2_rsa_create_object(
473                         unsigned long appHandle,
474                         //DhsmWPKRSAFormat* wpk,
475                         void *wpk,
476                         unsigned char* swk,
477                         int swk_len,
478                         unsigned char* iv,
479                         int iv_len,
480                         int tag_len,
481                         void **cb_object)
482 {
483     return 0;
484 }
485
486 int tpm2_rsa_delete_object(void *cb_object)
487 {
488     return 0;
489 }
490
491 int tpm2_import_object(unsigned long appHandle, 
492                        unsigned char* tlvbuffer, 
493                        int buflen, 
494                        unsigned char* iv, 
495                        int iv_len, 
496                        unsigned char* tpm_pwd, 
497                        int tpm_pwd_len)
498
499 {
500     return 0;
501 }