|
|
@@ -0,0 +1,569 @@ |
|
|
//**********************************************************************; |
|
|
// Copyright (c) 2017, Intel Corporation |
|
|
// All rights reserved. |
|
|
// |
|
|
// Redistribution and use in source and binary forms, with or without |
|
|
// modification, are permitted provided that the following conditions are met: |
|
|
// |
|
|
// 1. Redistributions of source code must retain the above copyright notice, |
|
|
// this list of conditions and the following disclaimer. |
|
|
// |
|
|
// 2. Redistributions in binary form must reproduce the above copyright notice, |
|
|
// this list of conditions and the following disclaimer in the documentation |
|
|
// and/or other materials provided with the distribution. |
|
|
// |
|
|
// 3. Neither the name of Intel Corporation nor the names of its contributors |
|
|
// may be used to endorse or promote products derived from this software without |
|
|
// specific prior written permission. |
|
|
// |
|
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
|
|
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
|
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
|
|
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
|
|
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
|
|
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
|
|
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
|
|
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
|
|
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
|
|
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF |
|
|
// THE POSSIBILITY OF SUCH DAMAGE. |
|
|
//**********************************************************************; |
|
|
|
|
|
#include <stdbool.h> |
|
|
#include <stdlib.h> |
|
|
#include <stdio.h> |
|
|
#include <string.h> |
|
|
|
|
|
#include <openssl/rand.h> |
|
|
#include <openssl/bn.h> |
|
|
#include <openssl/evp.h> |
|
|
#include <openssl/sha.h> |
|
|
#include <openssl/hmac.h> |
|
|
#include <openssl/aes.h> |
|
|
#include <openssl/rsa.h> |
|
|
|
|
|
#include <limits.h> |
|
|
#include <sapi/tpm20.h> |
|
|
#include <sapi/tss2_mu.h> |
|
|
|
|
|
#include "log.h" |
|
|
#include "files.h" |
|
|
#include "tpm_kdfa.h" |
|
|
#include "tpm2_options.h" |
|
|
#include "tpm2_util.h" |
|
|
|
|
|
#define SYM_KEY_SIZE 16 |
|
|
#define max_buffer_size 1024 |
|
|
|
|
|
typedef struct tpm_import_ctx tpm_import_ctx; |
|
|
struct tpm_import_ctx { |
|
|
char *input_key_file; |
|
|
char *import_key_public_file; |
|
|
char *import_key_private_file; |
|
|
char *parent_key_public_file; |
|
|
uint8_t input_key_buffer[SYM_KEY_SIZE]; |
|
|
//Parent public key for seed encryption |
|
|
TPM2B_PUBLIC_KEY_RSA parent_public_key; |
|
|
TPM_HANDLE parent_key_handle; |
|
|
//External key public |
|
|
TPM2B_PUBLIC import_key_public; |
|
|
//External key name |
|
|
TPM2B_NAME import_key_public_name; |
|
|
//External key sensitive |
|
|
TPM2B_SENSITIVE import_key_sensitive; |
|
|
//External key private |
|
|
TPM2B_PRIVATE import_key_private; |
|
|
//Protection Seed and keys |
|
|
uint8_t protection_seed_data[SHA256_DIGEST_SIZE]; //max tpm digest |
|
|
uint8_t encrypted_protection_seed_data[MAX_RSA_KEY_BYTES]; |
|
|
uint8_t protection_hmac_key[SHA256_DIGEST_SIZE]; |
|
|
uint8_t protection_enc_key[SYM_KEY_SIZE]; |
|
|
uint8_t import_key_public_unique_data[SHA256_DIGEST_SIZE]; |
|
|
uint8_t outer_integrity_hmac[SHA256_DIGEST_SIZE]; |
|
|
TPM2B_DATA enc_sensitive_key; |
|
|
TPM2B_MAX_BUFFER encrypted_inner_integrity; |
|
|
TPM2B_MAX_BUFFER encrypted_duplicate_sensitive; |
|
|
}; |
|
|
|
|
|
static tpm_import_ctx ctx = { |
|
|
.input_key_file = NULL, |
|
|
.parent_key_handle = 0, |
|
|
.parent_public_key = TPM2B_INIT(MAX_RSA_KEY_BYTES), |
|
|
.import_key_public = TPM2B_TYPE_INIT(TPM2B_PUBLIC, publicArea), |
|
|
.import_key_public_name = TPM2B_TYPE_INIT(TPM2B_NAME, name), |
|
|
.import_key_private = TPM2B_EMPTY_INIT, |
|
|
}; |
|
|
|
|
|
static void ssl_RSA_set0_key(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d) { |
|
|
|
|
|
if ((r->n == NULL && n == NULL) || (r->e == NULL && e == NULL)) { |
|
|
return; |
|
|
} |
|
|
|
|
|
if (n != NULL) { |
|
|
BN_free(r->n); |
|
|
r->n = n; |
|
|
} |
|
|
|
|
|
if (e != NULL) { |
|
|
BN_free(r->e); |
|
|
r->e = e; |
|
|
} |
|
|
|
|
|
if (d != NULL) { |
|
|
BN_free(r->d); |
|
|
r->d = d; |
|
|
} |
|
|
} |
|
|
|
|
|
static bool encrypt_seed_with_tpm2_rsa_public_key(void) { |
|
|
//Public Modulus |
|
|
FILE *fp = fopen(ctx.parent_key_public_file, "rb"); |
|
|
if (fp == NULL) { |
|
|
LOG_ERR("Failed accessing parent key public file."); |
|
|
return false; |
|
|
} |
|
|
if (fseek(fp, 102, SEEK_SET) != 0) { |
|
|
LOG_ERR("Expected parent key public data file size failure"); |
|
|
return false; |
|
|
} |
|
|
unsigned char pub_modulus[MAX_RSA_KEY_BYTES] = { 0 }; |
|
|
int ret = fread(pub_modulus, 1, MAX_RSA_KEY_BYTES, fp); |
|
|
if (ret != MAX_RSA_KEY_BYTES) { |
|
|
LOG_ERR("Failed reading public modulus from parent key public file"); |
|
|
return false; |
|
|
} |
|
|
fclose(fp); |
|
|
RSA *rsa = NULL; |
|
|
unsigned char encoded[MAX_RSA_KEY_BYTES]; |
|
|
unsigned char label[10] = { 'D', 'U', 'P', 'L', 'I', 'C', 'A', 'T', 'E', 0 }; |
|
|
int return_code = RSA_padding_add_PKCS1_OAEP_mgf1(encoded, |
|
|
MAX_RSA_KEY_BYTES, ctx.protection_seed_data, 32, label, 10, |
|
|
EVP_sha256(), NULL); |
|
|
if (return_code != 1) { |
|
|
LOG_ERR("Failed RSA_padding_add_PKCS1_OAEP_mgf1\n"); |
|
|
return false; |
|
|
} |
|
|
BIGNUM* bne = BN_new(); |
|
|
return_code = BN_set_word(bne, RSA_F4); |
|
|
if (return_code != 1) { |
|
|
LOG_ERR("BN_set_word failed\n"); |
|
|
return 1; |
|
|
} |
|
|
rsa = RSA_new(); |
|
|
return_code = RSA_generate_key_ex(rsa, 2048, bne, NULL); |
|
|
if (return_code != 1) { |
|
|
LOG_ERR("RSA_generate_key_ex failed\n"); |
|
|
return 1; |
|
|
} |
|
|
BIGNUM *n = BN_bin2bn(pub_modulus, MAX_RSA_KEY_BYTES, NULL); |
|
|
ssl_RSA_set0_key(rsa, n, NULL, NULL); |
|
|
if (n == NULL) { |
|
|
LOG_ERR("Failed RSA_set0_key\n"); |
|
|
return 1; |
|
|
} |
|
|
// Encrypting |
|
|
return_code = RSA_public_encrypt(MAX_RSA_KEY_BYTES, encoded, |
|
|
ctx.encrypted_protection_seed_data, rsa, RSA_NO_PADDING); |
|
|
if (return_code < 0) { |
|
|
LOG_ERR("Failed RSA_public_encrypt\n"); |
|
|
} |
|
|
RSA_free(rsa); |
|
|
BN_free(bne); |
|
|
return true; |
|
|
} |
|
|
|
|
|
static void aes_128_cfb_encrypt_buffers(uint8_t *buffer1, uint16_t buffer1_size, |
|
|
uint8_t *buffer2, uint16_t buffer2_size, uint8_t *encryption_key, |
|
|
uint8_t *encrypted_data) { |
|
|
//AES encryption |
|
|
uint8_t to_encrypt_buffer[max_buffer_size]; |
|
|
memcpy(to_encrypt_buffer, buffer1, buffer1_size); |
|
|
memcpy(to_encrypt_buffer + buffer1_size, buffer2, buffer2_size); |
|
|
|
|
|
uint8_t iv_in[SYM_KEY_SIZE] = { 0 }; |
|
|
AES_KEY aes; |
|
|
AES_set_encrypt_key(encryption_key, SYM_KEY_SIZE * 8, &aes); |
|
|
|
|
|
int block; |
|
|
int num = 0; |
|
|
for (block = 0; block < (buffer1_size + buffer2_size) / SYM_KEY_SIZE; |
|
|
block++) { |
|
|
AES_cfb128_encrypt(to_encrypt_buffer + (block * SYM_KEY_SIZE), |
|
|
encrypted_data + (block * SYM_KEY_SIZE), |
|
|
SYM_KEY_SIZE, &aes, iv_in, &num, AES_ENCRYPT); |
|
|
} |
|
|
AES_cfb128_encrypt(to_encrypt_buffer + (block * SYM_KEY_SIZE), |
|
|
encrypted_data + (block * SYM_KEY_SIZE), |
|
|
(buffer1_size + buffer2_size) % SYM_KEY_SIZE, &aes, iv_in, &num, |
|
|
AES_ENCRYPT); |
|
|
} |
|
|
|
|
|
static void hmac_outer_integrity(uint8_t *buffer1, uint16_t buffer1_size, |
|
|
uint8_t *buffer2, uint16_t buffer2_size, uint8_t *hmac_key, |
|
|
uint8_t *outer_integrity_hmac) { |
|
|
|
|
|
uint8_t to_hmac_buffer[max_buffer_size]; |
|
|
memcpy(to_hmac_buffer, buffer1, buffer1_size); |
|
|
memcpy(to_hmac_buffer + buffer1_size, buffer2, buffer2_size); |
|
|
uint32_t size_in = 0; |
|
|
HMAC(EVP_sha256(), hmac_key, SHA256_DIGEST_SIZE, to_hmac_buffer, |
|
|
buffer1_size + buffer2_size, outer_integrity_hmac, &size_in); |
|
|
} |
|
|
|
|
|
static void create_random_seed_and_sensitive_enc_key(void) { |
|
|
|
|
|
RAND_bytes(ctx.protection_seed_data, SHA256_DIGEST_SIZE); //max tpm digest |
|
|
ctx.enc_sensitive_key.b.size = SYM_KEY_SIZE; |
|
|
RAND_bytes(ctx.enc_sensitive_key.b.buffer, SYM_KEY_SIZE); |
|
|
|
|
|
} |
|
|
|
|
|
static bool calc_sensitive_unique_data(void) { |
|
|
|
|
|
uint8_t *concatenated_seed_unique = malloc( |
|
|
SHA256_DIGEST_SIZE + SYM_KEY_SIZE); |
|
|
if (!concatenated_seed_unique) { |
|
|
LOG_ERR("oom"); |
|
|
return false; |
|
|
} |
|
|
|
|
|
memcpy(concatenated_seed_unique, ctx.protection_seed_data, |
|
|
SHA256_DIGEST_SIZE); |
|
|
memcpy(concatenated_seed_unique + SHA256_DIGEST_SIZE, ctx.input_key_buffer, |
|
|
SYM_KEY_SIZE); |
|
|
|
|
|
SHA256(concatenated_seed_unique, SHA256_DIGEST_SIZE + SYM_KEY_SIZE, |
|
|
ctx.import_key_public_unique_data); |
|
|
|
|
|
free(concatenated_seed_unique); |
|
|
|
|
|
return true; |
|
|
} |
|
|
|
|
|
#define IMPORT_KEY_SYM_PUBLIC_AREA(X) \ |
|
|
(X).t.publicArea.type = TPM_ALG_SYMCIPHER; \ |
|
|
(X).t.publicArea.nameAlg = TPM_ALG_SHA256;\ |
|
|
(X).t.publicArea.objectAttributes.restricted = 0;\ |
|
|
(X).t.publicArea.objectAttributes.userWithAuth = 1;\ |
|
|
(X).t.publicArea.objectAttributes.decrypt = 1;\ |
|
|
(X).t.publicArea.objectAttributes.sign = 1;\ |
|
|
(X).t.publicArea.objectAttributes.fixedTPM = 0;\ |
|
|
(X).t.publicArea.objectAttributes.fixedParent = 0;\ |
|
|
(X).t.publicArea.objectAttributes.sensitiveDataOrigin = 0;\ |
|
|
(X).t.publicArea.authPolicy.t.size = 0;\ |
|
|
(X).t.publicArea.parameters.symDetail.sym.algorithm = TPM_ALG_AES;\ |
|
|
(X).t.publicArea.parameters.symDetail.sym.keyBits.sym = 128;\ |
|
|
(X).t.publicArea.parameters.symDetail.sym.mode.sym = TPM_ALG_CFB;\ |
|
|
(X).t.publicArea.unique.sym.t.size = SHA256_DIGEST_SIZE;\ |
|
|
|
|
|
static bool create_import_key_public_data_and_name(void) { |
|
|
|
|
|
IMPORT_KEY_SYM_PUBLIC_AREA(ctx.import_key_public) |
|
|
|
|
|
memcpy(ctx.import_key_public.t.publicArea.unique.sym.t.buffer, |
|
|
ctx.import_key_public_unique_data, SHA256_DIGEST_SIZE); |
|
|
|
|
|
size_t public_area_marshalled_offset = 0; |
|
|
uint8_t *marshalled_bytes = malloc(sizeof(ctx.import_key_public)); |
|
|
if (!marshalled_bytes) { |
|
|
LOG_ERR("oom"); |
|
|
return false; |
|
|
} |
|
|
|
|
|
Tss2_MU_TPM2B_PUBLIC_Marshal(&ctx.import_key_public, marshalled_bytes, |
|
|
sizeof(ctx.import_key_public), &public_area_marshalled_offset); |
|
|
|
|
|
ctx.import_key_public_name.t.size = SHA256_DIGEST_SIZE; |
|
|
size_t name_digest_alg_offset = 0; |
|
|
Tss2_MU_UINT16_Marshal(TPM_ALG_SHA256, ctx.import_key_public_name.t.name, |
|
|
sizeof(TPM_ALG_ID), &name_digest_alg_offset); |
|
|
ctx.import_key_public_name.t.size += name_digest_alg_offset; |
|
|
SHA256(marshalled_bytes + sizeof(uint16_t), |
|
|
public_area_marshalled_offset - sizeof(uint16_t), |
|
|
ctx.import_key_public_name.t.name + sizeof(TPM_ALG_ID)); |
|
|
free(marshalled_bytes); |
|
|
|
|
|
return true; |
|
|
} |
|
|
|
|
|
#define IMPORT_KEY_SYM_SENSITIVE_AREA(X) \ |
|
|
(X).t.sensitiveArea.sensitiveType = TPM_ALG_SYMCIPHER; \ |
|
|
(X).t.sensitiveArea.authValue.t.size = 0; \ |
|
|
(X).t.sensitiveArea.seedValue.t.size = SHA256_DIGEST_SIZE; \ |
|
|
(X).t.sensitiveArea.sensitive.sym.t.size = SYM_KEY_SIZE; \ |
|
|
|
|
|
static void create_import_key_sensitive_data(void) { |
|
|
|
|
|
IMPORT_KEY_SYM_SENSITIVE_AREA(ctx.import_key_sensitive); |
|
|
|
|
|
memcpy(ctx.import_key_sensitive.t.sensitiveArea.seedValue.t.buffer, |
|
|
ctx.protection_seed_data, SHA256_DIGEST_SIZE); //max digest size |
|
|
|
|
|
memcpy(ctx.import_key_sensitive.t.sensitiveArea.sensitive.sym.t.buffer, |
|
|
ctx.input_key_buffer, SYM_KEY_SIZE); |
|
|
} |
|
|
|
|
|
#define PARENT_NAME_ALG TPM_ALG_SHA256 |
|
|
static bool calc_outer_integrity_hmac_key_and_dupsensitive_enc_key(void) { |
|
|
|
|
|
TPM2B null_2b = { .size = 0 }; |
|
|
TPM2B_DIGEST to_TPM2B_seed = TPM2B_INIT(SHA256_DIGEST_SIZE); |
|
|
memcpy(to_TPM2B_seed.t.buffer, ctx.protection_seed_data, |
|
|
SHA256_DIGEST_SIZE); //max digest size |
|
|
TPM2B_MAX_BUFFER result_key; |
|
|
|
|
|
TPM_RC rval = tpm_kdfa(PARENT_NAME_ALG, &to_TPM2B_seed.b, "INTEGRITY", |
|
|
&null_2b, &null_2b, SHA256_DIGEST_SIZE * 8, &result_key); |
|
|
if (rval != TPM_RC_SUCCESS) { |
|
|
return false; |
|
|
} |
|
|
memcpy(ctx.protection_hmac_key, result_key.t.buffer, SHA256_DIGEST_SIZE); |
|
|
|
|
|
rval = tpm_kdfa(PARENT_NAME_ALG, &to_TPM2B_seed.b, "STORAGE", |
|
|
&ctx.import_key_public_name.b, &null_2b, SYM_KEY_SIZE * 8, |
|
|
&result_key); |
|
|
if (rval != TPM_RC_SUCCESS) { |
|
|
return false; |
|
|
} |
|
|
memcpy(ctx.protection_enc_key, result_key.t.buffer, SYM_KEY_SIZE); |
|
|
|
|
|
return true; |
|
|
} |
|
|
|
|
|
static void calculate_inner_integrity(void) { |
|
|
|
|
|
//Marshal sensitive area |
|
|
uint8_t buffer_marshalled_sensitiveArea[max_buffer_size] = { 0 }; |
|
|
size_t marshalled_sensitive_size = 0; |
|
|
Tss2_MU_TPMT_SENSITIVE_Marshal(&ctx.import_key_sensitive.t.sensitiveArea, |
|
|
buffer_marshalled_sensitiveArea + sizeof(uint16_t), max_buffer_size, |
|
|
&marshalled_sensitive_size); |
|
|
size_t marshalled_sensitive_size_info = 0; |
|
|
Tss2_MU_UINT16_Marshal(marshalled_sensitive_size, buffer_marshalled_sensitiveArea, |
|
|
sizeof(uint16_t), &marshalled_sensitive_size_info); |
|
|
|
|
|
//concatenate NAME |
|
|
memcpy( |
|
|
buffer_marshalled_sensitiveArea + marshalled_sensitive_size |
|
|
+ marshalled_sensitive_size_info, |
|
|
ctx.import_key_public_name.t.name, |
|
|
ctx.import_key_public_name.t.size); |
|
|
|
|
|
//Digest marshalled-sensitive || name |
|
|
uint8_t *marshalled_sensitive_and_name_digest = |
|
|
buffer_marshalled_sensitiveArea + marshalled_sensitive_size |
|
|
+ marshalled_sensitive_size_info |
|
|
+ ctx.import_key_public_name.t.size; |
|
|
size_t digest_size_info = 0; |
|
|
Tss2_MU_UINT16_Marshal(SHA256_DIGEST_SIZE, marshalled_sensitive_and_name_digest, |
|
|
sizeof(uint16_t), &digest_size_info); |
|
|
|
|
|
SHA256(buffer_marshalled_sensitiveArea, |
|
|
marshalled_sensitive_size_info + marshalled_sensitive_size |
|
|
+ ctx.import_key_public_name.t.size, |
|
|
marshalled_sensitive_and_name_digest + digest_size_info); |
|
|
|
|
|
//Inner integrity |
|
|
ctx.encrypted_inner_integrity.t.size = marshalled_sensitive_size_info |
|
|
+ marshalled_sensitive_size + ctx.import_key_public_name.t.size; |
|
|
aes_128_cfb_encrypt_buffers(marshalled_sensitive_and_name_digest, |
|
|
SHA256_DIGEST_SIZE + digest_size_info, |
|
|
buffer_marshalled_sensitiveArea, |
|
|
marshalled_sensitive_size_info + marshalled_sensitive_size, |
|
|
ctx.enc_sensitive_key.b.buffer, |
|
|
&ctx.encrypted_inner_integrity.t.buffer[0]); |
|
|
} |
|
|
|
|
|
static void calculate_outer_integrity(void) { |
|
|
|
|
|
//Calculate dupSensitive |
|
|
ctx.encrypted_duplicate_sensitive.t.size = |
|
|
ctx.encrypted_inner_integrity.t.size; |
|
|
|
|
|
aes_128_cfb_encrypt_buffers(ctx.encrypted_inner_integrity.t.buffer, |
|
|
ctx.encrypted_inner_integrity.t.size, NULL, 0, |
|
|
ctx.protection_enc_key, |
|
|
&ctx.encrypted_duplicate_sensitive.t.buffer[0]); |
|
|
//Calculate outerHMAC |
|
|
hmac_outer_integrity(ctx.encrypted_duplicate_sensitive.b.buffer, |
|
|
ctx.encrypted_duplicate_sensitive.t.size, |
|
|
ctx.import_key_public_name.t.name, |
|
|
ctx.import_key_public_name.t.size, ctx.protection_hmac_key, |
|
|
ctx.outer_integrity_hmac); |
|
|
} |
|
|
|
|
|
static void create_import_key_private_data(void) { |
|
|
ctx.import_key_private.b.size = sizeof(uint16_t) + SHA256_DIGEST_SIZE |
|
|
+ ctx.encrypted_duplicate_sensitive.t.size; |
|
|
size_t hmac_size_offset = 0; |
|
|
Tss2_MU_UINT16_Marshal(SHA256_DIGEST_SIZE, ctx.import_key_private.b.buffer, |
|
|
sizeof(uint16_t), &hmac_size_offset); |
|
|
memcpy(ctx.import_key_private.b.buffer + hmac_size_offset, |
|
|
ctx.outer_integrity_hmac, SHA256_DIGEST_SIZE); |
|
|
memcpy( |
|
|
ctx.import_key_private.b.buffer + hmac_size_offset |
|
|
+ SHA256_DIGEST_SIZE, |
|
|
ctx.encrypted_duplicate_sensitive.t.buffer, |
|
|
ctx.encrypted_duplicate_sensitive.t.size); |
|
|
} |
|
|
|
|
|
static bool import_external_key_and_save_public_private_data(TSS2_SYS_CONTEXT *sapi_context) { |
|
|
|
|
|
|
|
|
TPMS_AUTH_COMMAND npsessionData = TPMS_AUTH_COMMAND_INIT(TPM_RS_PW); |
|
|
TPMS_AUTH_COMMAND *npsessionDataArray[] = { |
|
|
&npsessionData |
|
|
}; |
|
|
|
|
|
TSS2_SYS_CMD_AUTHS npsessionsData = |
|
|
TSS2_SYS_CMD_AUTHS_INIT(npsessionDataArray); |
|
|
|
|
|
TPMS_AUTH_RESPONSE npsessionDataOut; |
|
|
TPMS_AUTH_RESPONSE *npsessionDataOutArray[] = { |
|
|
&npsessionDataOut |
|
|
}; |
|
|
|
|
|
TSS2_SYS_RSP_AUTHS npsessionsDataOut = |
|
|
TSS2_SYS_RSP_AUTHS_INIT(npsessionDataOutArray); |
|
|
|
|
|
TPMT_SYM_DEF_OBJECT symmetricAlg = { |
|
|
.algorithm = TPM_ALG_AES, |
|
|
.keyBits.aes = 128, |
|
|
.mode.aes = TPM_ALG_CFB |
|
|
}; |
|
|
|
|
|
TPM2B_PRIVATE importPrivate = TPM2B_TYPE_INIT(TPM2B_PRIVATE, buffer); |
|
|
TPM2B_ENCRYPTED_SECRET enc_inp_seed = TPM2B_INIT(MAX_RSA_KEY_BYTES); |
|
|
|
|
|
memcpy(enc_inp_seed.t.secret, ctx.encrypted_protection_seed_data, |
|
|
MAX_RSA_KEY_BYTES); |
|
|
|
|
|
TPM_RC rval = Tss2_Sys_Import(sapi_context, ctx.parent_key_handle, |
|
|
&npsessionsData, &ctx.enc_sensitive_key, &ctx.import_key_public, |
|
|
&ctx.import_key_private, &enc_inp_seed, &symmetricAlg, |
|
|
&importPrivate, &npsessionsDataOut); |
|
|
if (rval != TPM_RC_SUCCESS) { |
|
|
LOG_ERR("Failed Key Import %08X", rval); |
|
|
return false; |
|
|
} |
|
|
|
|
|
if (!files_save_bytes_to_file(ctx.import_key_public_file, |
|
|
(UINT8 *) &ctx.import_key_public, |
|
|
sizeof(ctx.import_key_public))) { |
|
|
return false; |
|
|
} |
|
|
|
|
|
if (!files_save_bytes_to_file(ctx.import_key_private_file, |
|
|
(UINT8 *) &importPrivate, sizeof(importPrivate))) { |
|
|
return false; |
|
|
} |
|
|
|
|
|
return true; |
|
|
} |
|
|
|
|
|
static bool key_import(TSS2_SYS_CONTEXT *sapi_context) { |
|
|
|
|
|
create_random_seed_and_sensitive_enc_key(); |
|
|
|
|
|
bool res = calc_sensitive_unique_data(); |
|
|
if (!res) { |
|
|
return false; |
|
|
} |
|
|
|
|
|
res = create_import_key_public_data_and_name(); |
|
|
if (!res) { |
|
|
return false; |
|
|
} |
|
|
|
|
|
create_import_key_sensitive_data(); |
|
|
|
|
|
calc_outer_integrity_hmac_key_and_dupsensitive_enc_key(); |
|
|
|
|
|
calculate_inner_integrity(); |
|
|
|
|
|
calculate_outer_integrity(); |
|
|
|
|
|
create_import_key_private_data(); |
|
|
|
|
|
res = encrypt_seed_with_tpm2_rsa_public_key(); |
|
|
if (!res) { |
|
|
LOG_ERR("Failed Seed Encryption\n"); |
|
|
return false; |
|
|
} |
|
|
|
|
|
res = import_external_key_and_save_public_private_data(sapi_context); |
|
|
if (!res) { |
|
|
return false; |
|
|
} |
|
|
|
|
|
return true; |
|
|
} |
|
|
|
|
|
static bool on_option(char key, char *value) { |
|
|
|
|
|
switch(key) { |
|
|
case 'k': |
|
|
ctx.input_key_file = value; |
|
|
uint16_t input_key_buffer_length = SYM_KEY_SIZE; |
|
|
if (!files_load_bytes_from_path(ctx.input_key_file, |
|
|
ctx.input_key_buffer, &input_key_buffer_length)) { |
|
|
return false; |
|
|
} |
|
|
break; |
|
|
case 'H': |
|
|
if (!tpm2_util_string_to_uint32(value, &ctx.parent_key_handle)) { |
|
|
LOG_ERR("Failed retrieving parent-key-handle value"); |
|
|
return false; |
|
|
} |
|
|
break; |
|
|
case 'f': |
|
|
ctx.parent_key_public_file = value; |
|
|
break; |
|
|
case 'q': |
|
|
ctx.import_key_public_file = value; |
|
|
break; |
|
|
case 'r': |
|
|
ctx.import_key_private_file = value; |
|
|
break; |
|
|
default: |
|
|
LOG_ERR("Invalid option"); |
|
|
return false; |
|
|
} |
|
|
|
|
|
return true; |
|
|
} |
|
|
|
|
|
bool tpm2_tool_onstart(tpm2_options **opts) { |
|
|
|
|
|
const struct option topts[] = { |
|
|
{ "input-key-file", required_argument, NULL, 'k'}, |
|
|
{ "parent-key-handle", required_argument, NULL, 'H'}, |
|
|
{ "parent-key-public", required_argument, NULL, 'f'}, |
|
|
{ "import-key-private", required_argument, NULL, 'r'}, |
|
|
{ "import-key-public", required_argument, NULL, 'q'}, |
|
|
}; |
|
|
|
|
|
setbuf(stdout, NULL); |
|
|
setvbuf (stdout, NULL, _IONBF, BUFSIZ); |
|
|
|
|
|
*opts = tpm2_options_new("k:H:f:q:r:", ARRAY_LEN(topts), topts, on_option, NULL); |
|
|
|
|
|
return *opts != NULL; |
|
|
} |
|
|
|
|
|
int tpm2_tool_onrun(TSS2_SYS_CONTEXT *sapi_context, tpm2_option_flags flags) { |
|
|
|
|
|
UNUSED(flags); |
|
|
|
|
|
if (!ctx.input_key_file || !ctx.parent_key_handle |
|
|
|| !ctx.parent_key_public_file || !ctx.import_key_public_file |
|
|
|| !ctx.import_key_private_file) { |
|
|
LOG_ERR("tpm2_import tool missing arguments: %s\n %08X\n %s\n %s\n %s\n", |
|
|
ctx.input_key_file, ctx.parent_key_handle, ctx.parent_key_public_file, |
|
|
ctx.import_key_public_file,ctx.import_key_private_file ); |
|
|
return 1; |
|
|
} |
|
|
|
|
|
return !key_import(sapi_context); |
|
|
} |