| Richard Marian Thomaiyar | 14fddef | 2018-07-13 23:55:56 +0530 | [diff] [blame] | 1 | From eb28ad92a2722fd30f8114840cf2b1ade26b80ee Mon Sep 17 00:00:00 2001 | 
|  | 2 | From: Limeng <Meng.Li@windriver.com> | 
|  | 3 | Date: Fri, 23 Jun 2017 11:39:04 +0800 | 
|  | 4 | Subject: [PATCH] tpm:openssl-tpm-engine:parse an encrypted tpm SRK password | 
|  | 5 | from env | 
|  | 6 |  | 
|  | 7 | Before, we support reading SRK password from env TPM_SRK_PW, | 
|  | 8 | but it is a plain password and not secure. | 
|  | 9 | So, we improve it and support to get an encrypted (AES algorithm) | 
|  | 10 | SRK password from env, and then parse it. The default decrypting | 
|  | 11 | AES password and salt is set in bb file. | 
|  | 12 | When we initialize TPM, and set a SRK pw, and then we need to | 
|  | 13 | encrypt it with the same AES password and salt by AES algorithm. | 
|  | 14 | At last, we set a env as below: | 
|  | 15 | export TPM_SRK_ENC_PW=xxxxxxxx | 
|  | 16 | "xxxxxxxx" is the encrypted SRK password for libtpm.so. | 
|  | 17 |  | 
|  | 18 | Signed-off-by: Meng Li <Meng.Li@windriver.com> | 
|  | 19 | --- | 
| Patrick Williams | 520786c | 2023-06-25 16:20:36 -0500 | [diff] [blame^] | 20 | Upstream-Status: Pending | 
|  | 21 |  | 
| Richard Marian Thomaiyar | 14fddef | 2018-07-13 23:55:56 +0530 | [diff] [blame] | 22 | e_tpm.c     | 157 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- | 
|  | 23 | e_tpm.h     |   4 ++ | 
|  | 24 | e_tpm_err.c |   4 ++ | 
|  | 25 | 3 files changed, 164 insertions(+), 1 deletion(-) | 
|  | 26 |  | 
| Brad Bishop | 1a4b7ee | 2018-12-16 17:11:34 -0800 | [diff] [blame] | 27 | Index: git/src/e_tpm.c | 
|  | 28 | =================================================================== | 
|  | 29 | --- git.orig/src/e_tpm.c | 
|  | 30 | +++ git/src/e_tpm.c | 
|  | 31 | @@ -259,6 +259,118 @@ void ENGINE_load_tpm(void) | 
| Richard Marian Thomaiyar | 14fddef | 2018-07-13 23:55:56 +0530 | [diff] [blame] | 32 | ERR_clear_error(); | 
|  | 33 | } | 
|  | 34 |  | 
|  | 35 | +static int tpm_decode_base64(unsigned char *indata, | 
|  | 36 | +				int in_len, | 
|  | 37 | +				unsigned char *outdata, | 
|  | 38 | +				int *out_len) | 
|  | 39 | +{ | 
|  | 40 | +	int total_len, len, ret; | 
|  | 41 | +	EVP_ENCODE_CTX dctx; | 
|  | 42 | + | 
|  | 43 | +	EVP_DecodeInit(&dctx); | 
|  | 44 | + | 
|  | 45 | +	total_len = 0; | 
|  | 46 | +	ret = EVP_DecodeUpdate(&dctx, outdata, &len, indata, in_len); | 
|  | 47 | +	if (ret < 0) { | 
|  | 48 | +		TSSerr(TPM_F_TPM_DECODE_BASE64, TPM_R_DECODE_BASE64_FAILED); | 
|  | 49 | +		return 1; | 
|  | 50 | +	} | 
|  | 51 | + | 
|  | 52 | +	total_len += len; | 
|  | 53 | +	ret = EVP_DecodeFinal(&dctx, outdata, &len); | 
|  | 54 | +	if (ret < 0) { | 
|  | 55 | +		TSSerr(TPM_F_TPM_DECODE_BASE64, TPM_R_DECODE_BASE64_FAILED); | 
|  | 56 | +		return 1; | 
|  | 57 | +	} | 
|  | 58 | +	total_len += len; | 
|  | 59 | + | 
|  | 60 | +	*out_len = total_len; | 
|  | 61 | + | 
|  | 62 | +	return 0; | 
|  | 63 | +} | 
|  | 64 | + | 
|  | 65 | +static int tpm_decrypt_srk_pw(unsigned char *indata, int in_len, | 
|  | 66 | +				unsigned char *outdata, | 
|  | 67 | +				int *out_len) | 
|  | 68 | +{ | 
|  | 69 | +	int dec_data_len, dec_data_lenfinal; | 
|  | 70 | +	unsigned char dec_data[256]; | 
|  | 71 | +	unsigned char *aes_pw; | 
|  | 72 | +	unsigned char aes_salt[PKCS5_SALT_LEN]; | 
|  | 73 | +	unsigned char key[EVP_MAX_KEY_LENGTH], iv[EVP_MAX_IV_LENGTH]; | 
|  | 74 | +	const EVP_CIPHER *cipher = NULL; | 
|  | 75 | +	const EVP_MD *dgst = NULL; | 
|  | 76 | +	EVP_CIPHER_CTX *ctx = NULL; | 
|  | 77 | + | 
|  | 78 | +	if (sizeof(SRK_DEC_SALT) - 1 > PKCS5_SALT_LEN) { | 
|  | 79 | +		TSSerr(TPM_F_TPM_DECRYPT_SRK_PW, TPM_R_DECRYPT_SRK_PW_FAILED); | 
|  | 80 | +		return 1; | 
|  | 81 | +	} | 
|  | 82 | + | 
|  | 83 | +	aes_pw = malloc(sizeof(SRK_DEC_PW) - 1); | 
|  | 84 | +	if (aes_pw == NULL) { | 
|  | 85 | +		TSSerr(TPM_F_TPM_DECRYPT_SRK_PW, TPM_R_DECRYPT_SRK_PW_FAILED); | 
|  | 86 | +		return 1; | 
|  | 87 | +	} | 
|  | 88 | + | 
|  | 89 | +	memset(aes_salt, 0x00, sizeof(aes_salt)); | 
|  | 90 | +	memcpy(aes_pw, SRK_DEC_PW, sizeof(SRK_DEC_PW) - 1); | 
|  | 91 | +	memcpy(aes_salt, SRK_DEC_SALT, sizeof(SRK_DEC_SALT) - 1); | 
|  | 92 | + | 
|  | 93 | +	cipher = EVP_get_cipherbyname("aes-128-cbc"); | 
|  | 94 | +	if (cipher == NULL) { | 
|  | 95 | +		TSSerr(TPM_F_TPM_DECRYPT_SRK_PW, TPM_R_DECRYPT_SRK_PW_FAILED); | 
|  | 96 | +		free(aes_pw); | 
|  | 97 | +		return 1; | 
|  | 98 | +	} | 
|  | 99 | +	dgst = EVP_sha256(); | 
|  | 100 | + | 
|  | 101 | +	EVP_BytesToKey(cipher, dgst, aes_salt, (unsigned char *)aes_pw, sizeof(SRK_DEC_PW) - 1, 1, key, iv); | 
|  | 102 | + | 
|  | 103 | +	ctx = EVP_CIPHER_CTX_new(); | 
|  | 104 | +	/* Don't set key or IV right away; we want to check lengths */ | 
|  | 105 | +	if (!EVP_CipherInit_ex(ctx, cipher, NULL, NULL, NULL, 0)) { | 
|  | 106 | +		TSSerr(TPM_F_TPM_DECRYPT_SRK_PW, TPM_R_DECRYPT_SRK_PW_FAILED); | 
|  | 107 | +		free(aes_pw); | 
|  | 108 | +		return 1; | 
|  | 109 | +	} | 
|  | 110 | + | 
|  | 111 | +	OPENSSL_assert(EVP_CIPHER_CTX_key_length(ctx) == 16); | 
|  | 112 | +	OPENSSL_assert(EVP_CIPHER_CTX_iv_length(ctx) == 16); | 
|  | 113 | + | 
|  | 114 | +	if (!EVP_CipherInit_ex(ctx, NULL, NULL, key, iv, 0)) { | 
|  | 115 | +		TSSerr(TPM_F_TPM_DECRYPT_SRK_PW, TPM_R_DECRYPT_SRK_PW_FAILED); | 
|  | 116 | +		free(aes_pw); | 
|  | 117 | +		return 1; | 
|  | 118 | +	} | 
|  | 119 | + | 
|  | 120 | +	if (!EVP_CipherUpdate(ctx, dec_data, &dec_data_len, indata, in_len)) { | 
|  | 121 | +		/* Error */ | 
|  | 122 | +		TSSerr(TPM_F_TPM_DECRYPT_SRK_PW, TPM_R_DECRYPT_SRK_PW_FAILED); | 
|  | 123 | +		free(aes_pw); | 
|  | 124 | +		EVP_CIPHER_CTX_free(ctx); | 
|  | 125 | +		return 1; | 
|  | 126 | +	} | 
|  | 127 | + | 
|  | 128 | +	if (!EVP_CipherFinal_ex(ctx, dec_data + dec_data_len, &dec_data_lenfinal)) { | 
|  | 129 | +		/* Error */ | 
|  | 130 | +		TSSerr(TPM_F_TPM_DECRYPT_SRK_PW, TPM_R_DECRYPT_SRK_PW_FAILED); | 
|  | 131 | +		free(aes_pw); | 
|  | 132 | +		EVP_CIPHER_CTX_free(ctx); | 
|  | 133 | +		return 1; | 
|  | 134 | +	} | 
|  | 135 | + | 
|  | 136 | +	dec_data_len = dec_data_len + dec_data_lenfinal; | 
|  | 137 | + | 
|  | 138 | +	memcpy(outdata, dec_data, dec_data_len); | 
|  | 139 | +	*out_len = dec_data_len; | 
|  | 140 | + | 
|  | 141 | +	free(aes_pw); | 
|  | 142 | +	EVP_CIPHER_CTX_free(ctx); | 
|  | 143 | + | 
|  | 144 | +	return 0; | 
|  | 145 | +} | 
|  | 146 | + | 
|  | 147 | int tpm_load_srk(UI_METHOD *ui, void *cb_data) | 
|  | 148 | { | 
|  | 149 | TSS_RESULT result; | 
| Brad Bishop | 1a4b7ee | 2018-12-16 17:11:34 -0800 | [diff] [blame] | 150 | @@ -319,8 +431,50 @@ int tpm_load_srk(UI_METHOD *ui, void *cb | 
| Richard Marian Thomaiyar | 14fddef | 2018-07-13 23:55:56 +0530 | [diff] [blame] | 151 | return 0; | 
|  | 152 | } | 
|  | 153 |  | 
|  | 154 | -	srkPasswd = getenv("TPM_SRK_PW"); | 
|  | 155 | +	srkPasswd = getenv("TPM_SRK_ENC_PW"); | 
|  | 156 | if (NULL != srkPasswd) { | 
|  | 157 | +		int in_len = strlen(srkPasswd); | 
|  | 158 | +		int out_len; | 
|  | 159 | +		unsigned char *out_buf; | 
|  | 160 | + | 
|  | 161 | +		if (!in_len || in_len % 4) { | 
|  | 162 | +			Tspi_Context_CloseObject(hContext, hSRK); | 
|  | 163 | +			free(auth); | 
|  | 164 | +			TSSerr(TPM_F_TPM_LOAD_SRK, TPM_R_REQUEST_FAILED); | 
|  | 165 | +			return 0; | 
|  | 166 | +		} | 
|  | 167 | + | 
|  | 168 | +		out_len = in_len * 3 / 4; | 
|  | 169 | +		out_buf = malloc(out_len); | 
|  | 170 | +		if (NULL == out_buf) { | 
|  | 171 | +			Tspi_Context_CloseObject(hContext, hSRK); | 
|  | 172 | +			free(auth); | 
|  | 173 | +			TSSerr(TPM_F_TPM_LOAD_SRK, TPM_R_REQUEST_FAILED); | 
|  | 174 | +			return 0; | 
|  | 175 | +		} | 
|  | 176 | + | 
|  | 177 | +		if (tpm_decode_base64(srkPasswd, strlen(srkPasswd), | 
|  | 178 | +					out_buf, &out_len)) { | 
|  | 179 | +			Tspi_Context_CloseObject(hContext, hSRK); | 
|  | 180 | +			free(auth); | 
|  | 181 | +			free(out_buf); | 
|  | 182 | +			TSSerr(TPM_F_TPM_LOAD_SRK, TPM_R_REQUEST_FAILED); | 
|  | 183 | +			return 0; | 
|  | 184 | +		} | 
|  | 185 | + | 
|  | 186 | +		if (tpm_decrypt_srk_pw(out_buf, out_len, | 
|  | 187 | +							auth, &authlen)) { | 
|  | 188 | +			Tspi_Context_CloseObject(hContext, hSRK); | 
|  | 189 | +			free(auth); | 
|  | 190 | +			free(out_buf); | 
|  | 191 | +			TSSerr(TPM_F_TPM_LOAD_SRK, TPM_R_REQUEST_FAILED); | 
|  | 192 | +			return 0; | 
|  | 193 | +		} | 
|  | 194 | +		secretMode = TSS_SECRET_MODE_PLAIN; | 
|  | 195 | +		free(out_buf); | 
|  | 196 | +	} | 
|  | 197 | +#ifdef TPM_SRK_PLAIN_PW | 
|  | 198 | +	else if (NULL != (srkPasswd = getenv("TPM_SRK_PW")) { | 
|  | 199 | if (0 == strcmp(srkPasswd, "#WELLKNOWN#")) { | 
|  | 200 | memset(auth, 0, TPM_WELL_KNOWN_KEY_LEN); | 
|  | 201 | secretMode = TSS_SECRET_MODE_SHA1; | 
| Brad Bishop | 1a4b7ee | 2018-12-16 17:11:34 -0800 | [diff] [blame] | 202 | @@ -333,6 +487,7 @@ int tpm_load_srk(UI_METHOD *ui, void *cb | 
| Richard Marian Thomaiyar | 14fddef | 2018-07-13 23:55:56 +0530 | [diff] [blame] | 203 | authlen = strlen(auth); | 
|  | 204 | } | 
|  | 205 | } | 
|  | 206 | +#endif | 
|  | 207 | else { | 
|  | 208 | if (!tpm_engine_get_auth(ui, (char *)auth, 128, | 
|  | 209 | "SRK authorization: ", cb_data)) { | 
| Brad Bishop | 1a4b7ee | 2018-12-16 17:11:34 -0800 | [diff] [blame] | 210 | Index: git/src/e_tpm.h | 
|  | 211 | =================================================================== | 
|  | 212 | --- git.orig/src/e_tpm.h | 
|  | 213 | +++ git/src/e_tpm.h | 
|  | 214 | @@ -66,6 +66,8 @@ void ERR_TSS_error(int function, int rea | 
| Richard Marian Thomaiyar | 14fddef | 2018-07-13 23:55:56 +0530 | [diff] [blame] | 215 | #define TPM_F_TPM_FILL_RSA_OBJECT		116 | 
|  | 216 | #define TPM_F_TPM_ENGINE_GET_AUTH		117 | 
|  | 217 | #define TPM_F_TPM_CREATE_SRK_POLICY		118 | 
|  | 218 | +#define TPM_F_TPM_DECODE_BASE64			119 | 
|  | 219 | +#define TPM_F_TPM_DECRYPT_SRK_PW		120 | 
|  | 220 |  | 
|  | 221 | /* Reason codes. */ | 
|  | 222 | #define TPM_R_ALREADY_LOADED			100 | 
| Brad Bishop | 1a4b7ee | 2018-12-16 17:11:34 -0800 | [diff] [blame] | 223 | @@ -96,6 +98,8 @@ void ERR_TSS_error(int function, int rea | 
| Richard Marian Thomaiyar | 14fddef | 2018-07-13 23:55:56 +0530 | [diff] [blame] | 224 | #define TPM_R_ID_INVALID			125 | 
|  | 225 | #define TPM_R_UI_METHOD_FAILED			126 | 
|  | 226 | #define TPM_R_UNKNOWN_SECRET_MODE		127 | 
|  | 227 | +#define TPM_R_DECODE_BASE64_FAILED		128 | 
|  | 228 | +#define TPM_R_DECRYPT_SRK_PW_FAILED		129 | 
|  | 229 |  | 
|  | 230 | /* structure pointed to by the RSA object's app_data pointer */ | 
|  | 231 | struct rsa_app_data | 
| Brad Bishop | 1a4b7ee | 2018-12-16 17:11:34 -0800 | [diff] [blame] | 232 | Index: git/src/e_tpm_err.c | 
|  | 233 | =================================================================== | 
|  | 234 | --- git.orig/src/e_tpm_err.c | 
|  | 235 | +++ git/src/e_tpm_err.c | 
|  | 236 | @@ -234,6 +234,8 @@ static ERR_STRING_DATA TPM_str_functs[] | 
| Richard Marian Thomaiyar | 14fddef | 2018-07-13 23:55:56 +0530 | [diff] [blame] | 237 | {ERR_PACK(0, TPM_F_TPM_BIND_FN, 0), "TPM_BIND_FN"}, | 
|  | 238 | {ERR_PACK(0, TPM_F_TPM_FILL_RSA_OBJECT, 0), "TPM_FILL_RSA_OBJECT"}, | 
|  | 239 | {ERR_PACK(0, TPM_F_TPM_ENGINE_GET_AUTH, 0), "TPM_ENGINE_GET_AUTH"}, | 
|  | 240 | +	{ERR_PACK(0, TPM_F_TPM_DECODE_BASE64, 0), "TPM_DECODE_BASE64"}, | 
|  | 241 | +	{ERR_PACK(0, TPM_F_TPM_DECRYPT_SRK_PW, 0), "TPM_DECRYPT_SRK_PW"}, | 
|  | 242 | {0, NULL} | 
|  | 243 | }; | 
|  | 244 |  | 
| Brad Bishop | 1a4b7ee | 2018-12-16 17:11:34 -0800 | [diff] [blame] | 245 | @@ -264,6 +266,8 @@ static ERR_STRING_DATA TPM_str_reasons[] | 
| Richard Marian Thomaiyar | 14fddef | 2018-07-13 23:55:56 +0530 | [diff] [blame] | 246 | {TPM_R_FILE_READ_FAILED, "failed reading the key file"}, | 
|  | 247 | {TPM_R_ID_INVALID, "engine id doesn't match"}, | 
|  | 248 | {TPM_R_UI_METHOD_FAILED, "ui function failed"}, | 
|  | 249 | +	{TPM_R_DECODE_BASE64_FAILED, "decode base64 failed"}, | 
|  | 250 | +	{TPM_R_DECRYPT_SRK_PW_FAILED, "decrypt srk password failed"}, | 
|  | 251 | {0, NULL} | 
|  | 252 | }; | 
|  | 253 |  |