/src/netbsd/src/crypto/external/cpl/tpm-tools/dist/lib/tpm_unseal.c
C | 499 lines | 393 code | 58 blank | 48 comment | 95 complexity | 4aedc1b25d4224c773cfd4f293e33f19 MD5 | raw file
Possible License(s): CC0-1.0, MIT, LGPL-2.0, LGPL-3.0, WTFPL, GPL-2.0, BSD-2-Clause, AGPL-3.0, CC-BY-SA-3.0, MPL-2.0, JSON, BSD-3-Clause-No-Nuclear-License-2014, LGPL-2.1, CPL-1.0, AGPL-1.0, 0BSD, ISC, Apache-2.0, GPL-3.0, IPL-1.0, MPL-2.0-no-copyleft-exception, BSD-3-Clause
- /*
- * The Initial Developer of the Original Code is International
- * Business Machines Corporation. Portions created by IBM
- * Corporation are Copyright (C) 2005, 2006 International Business
- * Machines Corporation. All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the Common Public License as published by
- * IBM Corporation; either version 1 of the License, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * Common Public License for more details.
- *
- * You should have received a copy of the Common Public License
- * along with this program; if not, a copy can be viewed at
- * http://www.opensource.org/licenses/cpl1.0.php.
- */
- #include "tpm_tspi.h"
- #include "tpm_seal.h"
- #include "tpm_unseal.h"
- #include <errno.h>
- #include <string.h>
- #include <stdio.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <unistd.h>
- #include <openssl/evp.h>
- #include <trousers/tss.h>
- #include <trousers/trousers.h>
- enum tspi_errors {
- ETSPICTXCREAT = 0,
- ETSPICTXCNCT,
- ETSPICTXCO,
- ETSPICTXLKBU,
- ETSPICTXLKBB,
- ETSPISETAD,
- ETSPIGETPO,
- ETSPIPOLSS,
- ETSPIDATU,
- ETSPIPOLATO,
- };
- TSS_HCONTEXT hContext = 0;
- #define TSPI_FUNCTION_NAME_MAX 30
- char tspi_error_strings[][TSPI_FUNCTION_NAME_MAX]= {
- "Tspi_Context_Create",
- "Tspi_Context_Connect",
- "Tspi_Context_CreateObject",
- "Tspi_Context_LoadKeyByUUID",
- "Tspi_Context_LoadKeyByBlob",
- "Tspi_SetAttribData",
- "Tspi_GetPolicyObject",
- "Tspi_Policy_SetSecret",
- "Tspi_Data_Unseal",
- "Tspi_Policy_AssignToObject",
- };
- #define TSSKEY_DEFAULT_SIZE 768
- #define EVPKEY_DEFAULT_SIZE 512
- int tpm_errno;
- int tpmUnsealFile( char* fname, unsigned char** tss_data, int* tss_size,
- BOOL srkWellKnown ) {
- int rc, rcLen=0, tssLen=0, evpLen=0;
- BYTE* rcPtr;
- char data[EVP_CIPHER_block_size(EVP_aes_256_cbc()) * 16];
- BYTE *tssKeyData = NULL;
- int tssKeyDataSize = 0;
- BYTE *evpKeyData = NULL;
- int evpKeyDataSize = 0;
- struct stat stats;
- TSS_HENCDATA hEncdata;
- TSS_HKEY hSrk, hKey;
- TSS_HPOLICY hPolicy;
- UINT32 symKeyLen;
- BYTE *symKey;
- BYTE wellKnown[TCPA_SHA1_160_HASH_LEN] = TSS_WELL_KNOWN_SECRET;
- char *srkSecret = NULL;
- int srkSecretLen;
- unsigned char* res_data = NULL;
- int res_size = 0;
- BIO *bdata = NULL, *b64 = NULL, *bmem = NULL;
- int bioRc;
- if ( tss_data == NULL || tss_size == NULL ) {
- rc = TPMSEAL_STD_ERROR;
- tpm_errno = EINVAL;
- goto out;
- }
- *tss_data = NULL;
- *tss_size = 0;
- /* Test for file existence */
- if ((rc = stat(fname, &stats))) {
- tpm_errno = errno;
- goto out;
- }
- /* Create an input file BIO */
- if((bdata = BIO_new_file(fname, "r")) == NULL ) {
- tpm_errno = errno;
- rc = TPMSEAL_STD_ERROR;
- goto out;
- }
- /* Test file header for TSS */
- BIO_gets(bdata, data, sizeof(data));
- if (strncmp(data, TPMSEAL_HDR_STRING,
- strlen(TPMSEAL_HDR_STRING)) != 0) {
- rc = TPMSEAL_FILE_ERROR;
- tpm_errno = ENOTSSHDR;
- goto out;
- }
- /* Looking for TSS Key Header */
- BIO_gets(bdata, data, sizeof(data));
- if (strncmp(data, TPMSEAL_TSS_STRING,
- strlen(TPMSEAL_TSS_STRING)) != 0) {
- rc = TPMSEAL_FILE_ERROR;
- tpm_errno = EWRONGTSSTAG;
- goto out;
- }
- /* Create a memory BIO to hold the base64 TSS key */
- if ((bmem = BIO_new(BIO_s_mem())) == NULL) {
- tpm_errno = EAGAIN;
- rc = TPMSEAL_STD_ERROR;
- goto out;
- }
- BIO_set_mem_eof_return(bmem, 0);
- /* Read the base64 TSS key into the memory BIO */
- while ((rcLen = BIO_gets(bdata, data, sizeof(data))) > 0) {
- /* Look for EVP Key Header (end of key) */
- if (strncmp(data, TPMSEAL_EVP_STRING,
- strlen(TPMSEAL_EVP_STRING)) == 0)
- break;
- if (BIO_write(bmem, data, rcLen) <= 0) {
- tpm_errno = EIO;
- rc = TPMSEAL_STD_ERROR;
- goto out;
- }
- }
- if (strncmp(data, TPMSEAL_EVP_STRING,
- strlen(TPMSEAL_EVP_STRING)) != 0 ) {
- tpm_errno = EWRONGEVPTAG;
- rc = TPMSEAL_FILE_ERROR;
- goto out;
- }
- /* Create a base64 BIO to decode the TSS key */
- if ((b64 = BIO_new(BIO_f_base64())) == NULL) {
- tpm_errno = EAGAIN;
- rc = TPMSEAL_STD_ERROR;
- goto out;
- }
- /* Decode the TSS key */
- bmem = BIO_push( b64, bmem );
- while ((rcLen = BIO_read(bmem, data, sizeof(data))) > 0) {
- if ((tssLen + rcLen) > tssKeyDataSize) {
- tssKeyDataSize += TSSKEY_DEFAULT_SIZE;
- rcPtr = realloc( tssKeyData, tssKeyDataSize);
- if ( rcPtr == NULL ) {
- tpm_errno = ENOMEM;
- rc = TPMSEAL_STD_ERROR;
- goto out;
- }
- tssKeyData = rcPtr;
- }
- memcpy(tssKeyData + tssLen, data, rcLen);
- tssLen += rcLen;
- }
- bmem = BIO_pop(b64);
- BIO_free(b64);
- b64 = NULL;
- bioRc = BIO_reset(bmem);
- /* Check for EVP Key Type Header */
- BIO_gets(bdata, data, sizeof(data));
- if (strncmp(data, TPMSEAL_KEYTYPE_SYM,
- strlen(TPMSEAL_KEYTYPE_SYM)) != 0 ) {
- rc = TPMSEAL_FILE_ERROR;
- tpm_errno = EWRONGKEYTYPE;
- goto out;
- }
- /* Make sure it's a supported cipher
- (currently only AES 256 CBC) */
- if (strncmp(data + strlen(TPMSEAL_KEYTYPE_SYM),
- TPMSEAL_CIPHER_AES256CBC,
- strlen(TPMSEAL_CIPHER_AES256CBC)) != 0) {
- rc = TPMSEAL_FILE_ERROR;
- tpm_errno = EWRONGKEYTYPE;
- goto out;
- }
- /* Read the base64 Symmetric key into the memory BIO */
- while ((rcLen = BIO_gets(bdata, data, sizeof(data))) > 0) {
- /* Look for Encrypted Data Header (end of key) */
- if (strncmp(data, TPMSEAL_ENC_STRING,
- strlen(TPMSEAL_ENC_STRING)) == 0)
- break;
- if (BIO_write(bmem, data, rcLen) <= 0) {
- tpm_errno = EIO;
- rc = TPMSEAL_STD_ERROR;
- goto out;
- }
- }
- if (strncmp(data, TPMSEAL_ENC_STRING,
- strlen(TPMSEAL_ENC_STRING)) != 0 ) {
- tpm_errno = EWRONGDATTAG;
- rc = TPMSEAL_FILE_ERROR;
- goto out;
- }
- /* Create a base64 BIO to decode the Symmetric key */
- if ((b64 = BIO_new(BIO_f_base64())) == NULL) {
- tpm_errno = EAGAIN;
- rc = TPMSEAL_STD_ERROR;
- goto out;
- }
- /* Decode the Symmetric key */
- bmem = BIO_push( b64, bmem );
- while ((rcLen = BIO_read(bmem, data, sizeof(data))) > 0) {
- if ((evpLen + rcLen) > evpKeyDataSize) {
- evpKeyDataSize += EVPKEY_DEFAULT_SIZE;
- rcPtr = realloc( evpKeyData, evpKeyDataSize);
- if ( rcPtr == NULL ) {
- tpm_errno = ENOMEM;
- rc = TPMSEAL_STD_ERROR;
- goto out;
- }
- evpKeyData = rcPtr;
- }
- memcpy(evpKeyData + evpLen, data, rcLen);
- evpLen += rcLen;
- }
- bmem = BIO_pop(b64);
- BIO_free(b64);
- b64 = NULL;
- bioRc = BIO_reset(bmem);
- /* Read the base64 encrypted data into the memory BIO */
- while ((rcLen = BIO_gets(bdata, data, sizeof(data))) > 0) {
- /* Look for TSS Footer (end of data) */
- if (strncmp(data, TPMSEAL_FTR_STRING,
- strlen(TPMSEAL_FTR_STRING)) == 0)
- break;
- if (BIO_write(bmem, data, rcLen) <= 0) {
- tpm_errno = EIO;
- rc = TPMSEAL_STD_ERROR;
- goto out;
- }
- }
- if (strncmp(data, TPMSEAL_FTR_STRING,
- strlen(TPMSEAL_FTR_STRING)) != 0 ) {
- tpm_errno = ENOTSSFTR;
- rc = TPMSEAL_FILE_ERROR;
- goto out;
- }
- /* Unseal */
- if ((rc=Tspi_Context_Create(&hContext)) != TSS_SUCCESS) {
- tpm_errno = ETSPICTXCREAT;
- goto out;
- }
- if (!srkWellKnown) {
- /* Prompt for SRK password */
- srkSecret = GETPASSWD(_("Enter SRK password: "), &srkSecretLen, FALSE);
- if (!srkSecret)
- goto out;
- }
- if ((rc=Tspi_Context_Connect(hContext, NULL)) != TSS_SUCCESS) {
- tpm_errno = ETSPICTXCNCT;
- goto tss_out;
- }
-
- if ((rc=Tspi_Context_CreateObject(hContext,
- TSS_OBJECT_TYPE_ENCDATA,
- TSS_ENCDATA_SEAL,
- &hEncdata)) != TSS_SUCCESS) {
- tpm_errno = ETSPICTXCO;
- goto tss_out;
- }
-
- if ((rc=Tspi_SetAttribData(hEncdata,
- TSS_TSPATTRIB_ENCDATA_BLOB,
- TSS_TSPATTRIB_ENCDATABLOB_BLOB,
- evpLen, evpKeyData)) != TSS_SUCCESS) {
- tpm_errno = ETSPISETAD;
- goto tss_out;
- }
- if ((rc=Tspi_Context_CreateObject(hContext,
- TSS_OBJECT_TYPE_POLICY,
- TSS_POLICY_USAGE,
- &hPolicy)) != TSS_SUCCESS) {
- tpm_errno = ETSPICTXCO;
- goto tss_out;
- }
- if ((rc=Tspi_Policy_SetSecret(hPolicy, TSS_SECRET_MODE_PLAIN,
- strlen(TPMSEAL_SECRET),
- (BYTE *)TPMSEAL_SECRET)) != TSS_SUCCESS) {
- tpm_errno = ETSPIPOLSS;
- goto tss_out;
- }
- if ((rc=Tspi_Policy_AssignToObject(hPolicy, hEncdata)) != TSS_SUCCESS) {
- tpm_errno = ETSPIPOLATO;
- goto tss_out;
- }
- if ((rc=Tspi_Context_LoadKeyByUUID(hContext, TSS_PS_TYPE_SYSTEM,
- SRK_UUID, &hSrk)) != TSS_SUCCESS) {
- tpm_errno = ETSPICTXLKBU;
- goto tss_out;
- }
- /* Don't create a new policy for the SRK's secret, just use the context's
- * default policy */
- if ((rc=Tspi_GetPolicyObject(hSrk, TSS_POLICY_USAGE,
- &hPolicy)) != TSS_SUCCESS){
- tpm_errno = ETSPIGETPO;
- goto tss_out;
- }
-
- if (srkWellKnown)
- rc = Tspi_Policy_SetSecret(hPolicy, TSS_SECRET_MODE_SHA1,
- sizeof(wellKnown),
- (BYTE *) wellKnown);
- else
- rc = Tspi_Policy_SetSecret(hPolicy,TSS_SECRET_MODE_PLAIN,
- srkSecretLen,
- (BYTE *) srkSecret);
-
- if (rc != TSS_SUCCESS) {
- tpm_errno = ETSPIPOLSS;
- goto tss_out;
- }
- /* Failure point if trying to unseal data on a differnt TPM */
- if ((rc=Tspi_Context_LoadKeyByBlob(hContext, hSrk, tssLen,
- tssKeyData, &hKey)) != TSS_SUCCESS) {
- tpm_errno = ETSPICTXLKBB;
- goto tss_out;
- }
- if ((rc=Tspi_Context_CreateObject(hContext,
- TSS_OBJECT_TYPE_POLICY,
- TSS_POLICY_USAGE,
- &hPolicy)) != TSS_SUCCESS) {
- tpm_errno = ETSPICTXCO;
- goto tss_out;
- }
- if ((rc=Tspi_Policy_SetSecret(hPolicy, TSS_SECRET_MODE_PLAIN,
- strlen(TPMSEAL_SECRET),
- (BYTE *)TPMSEAL_SECRET)) != TSS_SUCCESS) {
- tpm_errno = ETSPIPOLSS;
- goto tss_out;
- }
- if ((rc=Tspi_Policy_AssignToObject(hPolicy, hKey)) != TSS_SUCCESS) {
- tpm_errno = ETSPIPOLATO;
- goto tss_out;
- }
- if ((rc=Tspi_Data_Unseal(hEncdata, hKey, &symKeyLen,
- &symKey)) != TSS_SUCCESS) {
- tpm_errno = ETSPIDATU;
- goto tss_out;
- }
- /* Malloc a block of storage to hold the decrypted data
- Using the size of the mem BIO is more than enough
- (plus an extra cipher block size) */
- res_data = malloc(BIO_pending(bmem) + EVP_CIPHER_block_size(EVP_aes_256_cbc()));
- if ( res_data == NULL ) {
- rc = TPMSEAL_STD_ERROR;
- tpm_errno = ENOMEM;
- goto tss_out;
- }
- /* Decode and decrypt the encrypted data */
- EVP_CIPHER_CTX ctx;
- EVP_DecryptInit(&ctx, EVP_aes_256_cbc(), symKey, (unsigned char *)TPMSEAL_IV);
- /* Create a base64 BIO to decode the encrypted data */
- if ((b64 = BIO_new(BIO_f_base64())) == NULL) {
- tpm_errno = EAGAIN;
- rc = TPMSEAL_STD_ERROR;
- goto tss_out;
- }
- bmem = BIO_push( b64, bmem );
- while ((rcLen = BIO_read(bmem, data, sizeof(data))) > 0) {
- EVP_DecryptUpdate(&ctx, res_data+res_size,
- &rcLen, (unsigned char *)data, rcLen);
- res_size += rcLen;
- }
- EVP_DecryptFinal(&ctx, res_data+res_size, &rcLen);
- res_size += rcLen;
- bmem = BIO_pop(b64);
- BIO_free(b64);
- b64 = NULL;
- bioRc = BIO_reset(bmem);
- tss_out:
- Tspi_Context_Close(hContext);
- out:
- if (srkSecret)
- shredPasswd(srkSecret);
-
- if ( bdata )
- BIO_free(bdata);
- if ( b64 )
- BIO_free(b64);
- if ( bmem ) {
- bioRc = BIO_set_close(bmem, BIO_CLOSE);
- BIO_free(bmem);
- }
- if ( evpKeyData )
- free(evpKeyData);
- if ( tssKeyData )
- free(tssKeyData);
- if ( rc == 0 ) {
- *tss_data = res_data;
- *tss_size = res_size;
- } else
- free(res_data);
- return rc;
- }
- void tpmUnsealShred(unsigned char* data, int size) {
- if ( data != NULL ) {
- memset( data, 0, size);
- free(data);
- }
- }
- char tpm_error_buf[512];
- char * tpmUnsealStrerror(int rc) {
- switch(rc) {
- case 0:
- return "Success";
- case TPMSEAL_STD_ERROR:
- return strerror(tpm_errno);
- case TPMSEAL_FILE_ERROR:
- switch(tpm_errno) {
- case ENOTSSHDR:
- return _("No TSS header present");
- case ENOTSSFTR:
- return _("No TSS footer present");
- case EWRONGTSSTAG:
- return _("Wrong TSS tag");
- case EWRONGEVPTAG:
- return _("Wrong EVP tag");
- case EWRONGDATTAG:
- return _("Wrong DATA tag");
- case EWRONGKEYTYPE:
- return _("Not a Symmetric EVP Key");
- case EBADSEEK:
- return _("Unable to move to desired file position");
- }
- default:
- snprintf(tpm_error_buf, sizeof(tpm_error_buf),
- "%s: 0x%08x - layer=%s, code=%04x (%d), %s",
- tspi_error_strings[tpm_errno],
- rc, Trspi_Error_Layer(rc),
- Trspi_Error_Code(rc),
- Trspi_Error_Code(rc),
- Trspi_Error_String(rc));
- return tpm_error_buf;
- }
- return "";
- }