diff --git a/meta-tpm/recipes-tpm/openssl-tpm-engine/files/0005-tpm-openssl-tpm-engine-parse-an-encrypted-TPM-key-pa.patch b/meta-tpm/recipes-tpm/openssl-tpm-engine/files/0005-tpm-openssl-tpm-engine-parse-an-encrypted-TPM-key-pa.patch new file mode 100644 index 0000000..0301308 --- /dev/null +++ b/meta-tpm/recipes-tpm/openssl-tpm-engine/files/0005-tpm-openssl-tpm-engine-parse-an-encrypted-TPM-key-pa.patch @@ -0,0 +1,274 @@ +From 889639aed890d03a47d9c575280cc785ecc28380 Mon Sep 17 00:00:00 2001 +From: Limeng +Date: Tue, 22 Aug 2017 13:02:51 +0800 +Subject: [PATCH] tpm : openssl-tpm-engine: parse an encrypted TPM key password + from env + +when openssl-tpm-engine lib is used on an unattended device, there is no +way to input TPM key password. So add this feature to support parse an +encrypted(AES algorithm) TPM key password from env. +The default decrypting AES password and salt is set in bb file. +When we create a TPM key(TSS format), generate a 8 bytes random data +as its password, and then we need to encrypt the password with the same +AES password and salt in bb file. +At last, we set a env as below: +export TPM_KEY_ENC_PW=xxxxxxxx +"xxxxxxxx" is the encrypted TPM key password for libtpm.so. + +Signed-off-by: Meng Li +--- + e_tpm.c | 110 ++++++++++++++++++++++++++++++++++++++++++++++-------------- + e_tpm.h | 4 +-- + e_tpm_err.c | 4 +-- + 3 files changed, 89 insertions(+), 29 deletions(-) + +diff --git a/e_tpm.c b/e_tpm.c +index 11bf74b..ee86a3a 100644 +--- a/e_tpm.c ++++ b/e_tpm.c +@@ -275,7 +275,7 @@ static int tpm_decode_base64(unsigned char *indata, + return 0; + } + +-static int tpm_decrypt_srk_pw(unsigned char *indata, int in_len, ++static int tpm_decrypt_pw(unsigned char *indata, int in_len, + unsigned char *outdata, + int *out_len) + { +@@ -288,35 +288,35 @@ static int tpm_decrypt_srk_pw(unsigned char *indata, int in_len, + const EVP_MD *dgst = NULL; + EVP_CIPHER_CTX *ctx = NULL; + +- if (sizeof(SRK_DEC_SALT) - 1 > PKCS5_SALT_LEN) { +- TSSerr(TPM_F_TPM_DECRYPT_SRK_PW, TPM_R_DECRYPT_SRK_PW_FAILED); ++ if (sizeof(DEC_SALT) - 1 > PKCS5_SALT_LEN) { ++ TSSerr(TPM_F_TPM_DECRYPT_PW, TPM_R_DECRYPT_PW_FAILED); + return 1; + } + +- aes_pw = malloc(sizeof(SRK_DEC_PW) - 1); ++ aes_pw = malloc(sizeof(DEC_PW) - 1); + if (aes_pw == NULL) { +- TSSerr(TPM_F_TPM_DECRYPT_SRK_PW, TPM_R_DECRYPT_SRK_PW_FAILED); ++ TSSerr(TPM_F_TPM_DECRYPT_PW, TPM_R_DECRYPT_PW_FAILED); + return 1; + } + + memset(aes_salt, 0x00, sizeof(aes_salt)); +- memcpy(aes_pw, SRK_DEC_PW, sizeof(SRK_DEC_PW) - 1); +- memcpy(aes_salt, SRK_DEC_SALT, sizeof(SRK_DEC_SALT) - 1); ++ memcpy(aes_pw, DEC_PW, sizeof(DEC_PW) - 1); ++ memcpy(aes_salt, DEC_SALT, sizeof(DEC_SALT) - 1); + + cipher = EVP_get_cipherbyname("aes-128-cbc"); + if (cipher == NULL) { +- TSSerr(TPM_F_TPM_DECRYPT_SRK_PW, TPM_R_DECRYPT_SRK_PW_FAILED); ++ TSSerr(TPM_F_TPM_DECRYPT_PW, TPM_R_DECRYPT_PW_FAILED); + free(aes_pw); + return 1; + } + dgst = EVP_sha256(); + +- EVP_BytesToKey(cipher, dgst, aes_salt, (unsigned char *)aes_pw, sizeof(SRK_DEC_PW) - 1, 1, key, iv); ++ EVP_BytesToKey(cipher, dgst, aes_salt, (unsigned char *)aes_pw, sizeof(DEC_PW) - 1, 1, key, iv); + + ctx = EVP_CIPHER_CTX_new(); + /* Don't set key or IV right away; we want to check lengths */ + if (!EVP_CipherInit_ex(ctx, cipher, NULL, NULL, NULL, 0)) { +- TSSerr(TPM_F_TPM_DECRYPT_SRK_PW, TPM_R_DECRYPT_SRK_PW_FAILED); ++ TSSerr(TPM_F_TPM_DECRYPT_PW, TPM_R_DECRYPT_PW_FAILED); + free(aes_pw); + return 1; + } +@@ -325,14 +325,14 @@ static int tpm_decrypt_srk_pw(unsigned char *indata, int in_len, + OPENSSL_assert(EVP_CIPHER_CTX_iv_length(ctx) == 16); + + if (!EVP_CipherInit_ex(ctx, NULL, NULL, key, iv, 0)) { +- TSSerr(TPM_F_TPM_DECRYPT_SRK_PW, TPM_R_DECRYPT_SRK_PW_FAILED); ++ TSSerr(TPM_F_TPM_DECRYPT_PW, TPM_R_DECRYPT_PW_FAILED); + free(aes_pw); + return 1; + } + + if (!EVP_CipherUpdate(ctx, dec_data, &dec_data_len, indata, in_len)) { + /* Error */ +- TSSerr(TPM_F_TPM_DECRYPT_SRK_PW, TPM_R_DECRYPT_SRK_PW_FAILED); ++ TSSerr(TPM_F_TPM_DECRYPT_PW, TPM_R_DECRYPT_PW_FAILED); + free(aes_pw); + EVP_CIPHER_CTX_free(ctx); + return 1; +@@ -340,7 +340,7 @@ static int tpm_decrypt_srk_pw(unsigned char *indata, int in_len, + + if (!EVP_CipherFinal_ex(ctx, dec_data + dec_data_len, &dec_data_lenfinal)) { + /* Error */ +- TSSerr(TPM_F_TPM_DECRYPT_SRK_PW, TPM_R_DECRYPT_SRK_PW_FAILED); ++ TSSerr(TPM_F_TPM_DECRYPT_PW, TPM_R_DECRYPT_PW_FAILED); + free(aes_pw); + EVP_CIPHER_CTX_free(ctx); + return 1; +@@ -448,8 +448,7 @@ int tpm_load_srk(UI_METHOD *ui, void *cb_data) + return 0; + } + +- if (tpm_decrypt_srk_pw(out_buf, out_len, +- auth, &authlen)) { ++ if (tpm_decrypt_pw(out_buf, out_len, auth, &authlen)) { + Tspi_Context_CloseObject(hContext, hSRK); + free(auth); + free(out_buf); +@@ -460,7 +459,7 @@ int tpm_load_srk(UI_METHOD *ui, void *cb_data) + free(out_buf); + } + #ifdef TPM_SRK_PLAIN_PW +- else if (NULL != (srkPasswd = getenv("TPM_SRK_PW")) { ++ else if (NULL != (srkPasswd = getenv("TPM_SRK_PW"))) { + if (0 == strcmp(srkPasswd, "#WELLKNOWN#")) { + memset(auth, 0, TPM_WELL_KNOWN_KEY_LEN); + secretMode = TSS_SECRET_MODE_SHA1; +@@ -807,6 +806,9 @@ static EVP_PKEY *tpm_engine_load_key(ENGINE *e, const char *key_id, + if (authusage) { + TSS_HPOLICY hPolicy; + BYTE *auth; ++ char *tpmKeyPasswd = NULL; ++ int authlen = 0; ++ TSS_FLAG secretMode = secret_mode; + + if ((auth = calloc(1, 128)) == NULL) { + Tspi_Context_CloseObject(hContext, hKey); +@@ -814,13 +816,71 @@ static EVP_PKEY *tpm_engine_load_key(ENGINE *e, const char *key_id, + return NULL; + } + +- if (!tpm_engine_get_auth(ui, (char *)auth, 128, +- "TPM Key Password: ", +- cb_data)) { +- Tspi_Context_CloseObject(hContext, hKey); +- free(auth); +- TSSerr(TPM_F_TPM_ENGINE_LOAD_KEY, TPM_R_REQUEST_FAILED); +- return NULL; ++ tpmKeyPasswd = getenv("TPM_KEY_ENC_PW"); ++ if (NULL != tpmKeyPasswd) { ++ int in_len = strlen(tpmKeyPasswd); ++ int out_len; ++ unsigned char *out_buf; ++ ++ if (!in_len || in_len % 4) { ++ Tspi_Context_CloseObject(hContext, hKey); ++ free(auth); ++ TSSerr(TPM_F_TPM_ENGINE_LOAD_KEY, TPM_R_REQUEST_FAILED); ++ return NULL; ++ } ++ out_len = in_len * 3 / 4; ++ out_buf = malloc(out_len); ++ if (NULL == out_buf) { ++ Tspi_Context_CloseObject(hContext, hKey); ++ free(auth); ++ TSSerr(TPM_F_TPM_ENGINE_LOAD_KEY, ERR_R_MALLOC_FAILURE); ++ return NULL; ++ } ++ ++ if (tpm_decode_base64(tpmKeyPasswd, strlen(tpmKeyPasswd), ++ out_buf, &out_len)) { ++ Tspi_Context_CloseObject(hContext, hKey); ++ free(auth); ++ free(out_buf); ++ TSSerr(TPM_F_TPM_ENGINE_LOAD_KEY, TPM_R_REQUEST_FAILED); ++ return NULL; ++ } ++ ++ if (tpm_decrypt_pw(out_buf, out_len, auth, &authlen)) { ++ Tspi_Context_CloseObject(hContext, hKey); ++ free(auth); ++ free(out_buf); ++ TSSerr(TPM_F_TPM_ENGINE_LOAD_KEY, TPM_R_REQUEST_FAILED); ++ return 0; ++ } ++ secretMode = TSS_SECRET_MODE_PLAIN; ++ free(out_buf); ++ } ++#ifdef TPM_KEY_PLAIN_PW ++ else if (NULL != (tpmKeyPasswd = getenv("TPM_KEY_PW"))) { ++ if (0 == strcmp(tpmKeyPasswd, "#WELLKNOWN#")) { ++ memset(auth, 0, TPM_WELL_KNOWN_KEY_LEN); ++ secretMode = TSS_SECRET_MODE_SHA1; ++ authlen = TPM_WELL_KNOWN_KEY_LEN; ++ } else { ++ int authbuflen = 128; ++ memset(auth, 0, authbuflen); ++ strncpy(auth, tpmKeyPasswd, authbuflen-1); ++ secretMode = TSS_SECRET_MODE_PLAIN; ++ authlen = strlen(auth); ++ } ++ } ++#endif ++ else { ++ if (!tpm_engine_get_auth(ui, (char *)auth, 128, ++ "TPM Key Password: ", cb_data)) { ++ Tspi_Context_CloseObject(hContext, hKey); ++ free(auth); ++ TSSerr(TPM_F_TPM_ENGINE_LOAD_KEY, TPM_R_REQUEST_FAILED); ++ return NULL; ++ } ++ secretMode = secret_mode; ++ authlen = strlen(auth); + } + + if ((result = Tspi_Context_CreateObject(hContext, +@@ -842,8 +902,8 @@ static EVP_PKEY *tpm_engine_load_key(ENGINE *e, const char *key_id, + } + + if ((result = Tspi_Policy_SetSecret(hPolicy, +- TSS_SECRET_MODE_PLAIN, +- strlen((char *)auth), auth))) { ++ secretMode, ++ authlen, auth))) { + Tspi_Context_CloseObject(hContext, hKey); + Tspi_Context_CloseObject(hContext, hPolicy); + free(auth); +diff --git a/e_tpm.h b/e_tpm.h +index 56ff202..7faf744 100644 +--- a/e_tpm.h ++++ b/e_tpm.h +@@ -67,7 +67,7 @@ void ERR_TSS_error(int function, int reason, char *file, int line); + #define TPM_F_TPM_ENGINE_GET_AUTH 117 + #define TPM_F_TPM_CREATE_SRK_POLICY 118 + #define TPM_F_TPM_DECODE_BASE64 119 +-#define TPM_F_TPM_DECRYPT_SRK_PW 120 ++#define TPM_F_TPM_DECRYPT_PW 120 + + /* Reason codes. */ + #define TPM_R_ALREADY_LOADED 100 +@@ -99,7 +99,7 @@ void ERR_TSS_error(int function, int reason, char *file, int line); + #define TPM_R_UI_METHOD_FAILED 126 + #define TPM_R_UNKNOWN_SECRET_MODE 127 + #define TPM_R_DECODE_BASE64_FAILED 128 +-#define TPM_R_DECRYPT_SRK_PW_FAILED 129 ++#define TPM_R_DECRYPT_PW_FAILED 129 + + /* structure pointed to by the RSA object's app_data pointer */ + struct rsa_app_data +diff --git a/e_tpm_err.c b/e_tpm_err.c +index 439e267..f8ce624 100644 +--- a/e_tpm_err.c ++++ b/e_tpm_err.c +@@ -236,7 +236,7 @@ static ERR_STRING_DATA TPM_str_functs[] = { + {ERR_PACK(0, TPM_F_TPM_FILL_RSA_OBJECT, 0), "TPM_FILL_RSA_OBJECT"}, + {ERR_PACK(0, TPM_F_TPM_ENGINE_GET_AUTH, 0), "TPM_ENGINE_GET_AUTH"}, + {ERR_PACK(0, TPM_F_TPM_DECODE_BASE64, 0), "TPM_DECODE_BASE64"}, +- {ERR_PACK(0, TPM_F_TPM_DECRYPT_SRK_PW, 0), "TPM_DECRYPT_SRK_PW"}, ++ {ERR_PACK(0, TPM_F_TPM_DECRYPT_PW, 0), "TPM_DECRYPT_SRK_PW"}, + {0, NULL} + }; + +@@ -268,7 +268,7 @@ static ERR_STRING_DATA TPM_str_reasons[] = { + {TPM_R_ID_INVALID, "engine id doesn't match"}, + {TPM_R_UI_METHOD_FAILED, "ui function failed"}, + {TPM_R_DECODE_BASE64_FAILED, "decode base64 failed"}, +- {TPM_R_DECRYPT_SRK_PW_FAILED, "decrypt srk password failed"}, ++ {TPM_R_DECRYPT_PW_FAILED, "decrypt password failed"}, + {0, NULL} + }; + +-- +2.9.3 + diff --git a/meta-tpm/recipes-tpm/openssl-tpm-engine/openssl-tpm-engine_git.bb b/meta-tpm/recipes-tpm/openssl-tpm-engine/openssl-tpm-engine_git.bb index 853590d..54766a5 100644 --- a/meta-tpm/recipes-tpm/openssl-tpm-engine/openssl-tpm-engine_git.bb +++ b/meta-tpm/recipes-tpm/openssl-tpm-engine/openssl-tpm-engine_git.bb @@ -16,6 +16,7 @@ SRC_URI = "\ file://0003-Fix-not-building-libtpm.la.patch \ file://0003-tpm-openssl-tpm-engine-parse-an-encrypted-tpm-SRK-pa.patch \ file://0004-tpm-openssl-tpm-engine-change-variable-c-type-from-c.patch \ + file://0005-tpm-openssl-tpm-engine-parse-an-encrypted-TPM-key-pa.patch \ " SRCREV = "bbc2b1af809f20686e0d3553a62f0175742c0d60" @@ -29,19 +30,22 @@ inherit autotools-brokensep # srk_dec_pw = "incendia" # srk_dec_pw = "\x69\x6e\x63\x65\x6e\x64\x69\x61" # srk_dec_pw = "\x1""nc""\x3""nd""\x1""a" -# + +# The definitions below are used to decrypt the passwords of both srk and loaded key. +dec_pw ?= "\\"\\\x1\\"\\"nc\\"\\"\\\x3\\"\\"nd\\"\\"\\\x1\\"\\"a\\"" +dec_salt ?= "\\"r\\"\\"\\\x00\\\x00\\"\\"t\\"" +CFLAGS_append += "-DDEC_PW=${dec_pw} -DDEC_SALT=${dec_salt}" # Due to the limit of escape character, the hybrid must be written in # above style. The actual values defined below in C code style are: -# srk_dec_pw[] = { 0x01, 'n', 'c', 0x03, 'n', 'd', 0x01, 'a' }; -# srk_dec_salt[] = { 'r', 0x00, 0x00, 't' }; -srk_dec_pw ?= "\\"\\\x1\\"\\"nc\\"\\"\\\x3\\"\\"nd\\"\\"\\\x1\\"\\"a\\"" -srk_dec_salt ?= "\\"r\\"\\"\\\x00\\\x00\\"\\"t\\"" - -CFLAGS_append += "-DSRK_DEC_PW=${srk_dec_pw} -DSRK_DEC_SALT=${srk_dec_salt}" +# dec_pw[] = {0x01, 'n', 'c', 0x03, 'n', 'd', 0x01, 'a'}; +# dec_salt[] = {'r', 0x00, 0x00, 't'}; # Uncomment below line if using the plain srk password for development #CFLAGS_append += "-DTPM_SRK_PLAIN_PW" +# Uncomment below line if using the plain tpm key password for development +#CFLAGS_append += "-DTPM_KEY_PLAIN_PW" + do_configure_prepend() { cd "${S}" cp LICENSE COPYING