tpm: tpm_passthrough: Read the buffer size from the host device
Rather than hard coding the buffer size in the tpm_passthrough backend read the TPM I/O buffer size from the host device. Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com> Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
This commit is contained in:
		
							parent
							
								
									56388eee01
								
							
						
					
					
						commit
						abc5cda097
					
				| @ -45,11 +45,20 @@ struct tpm_resp_hdr { | ||||
| 
 | ||||
| #define TPM_ORD_ContinueSelfTest  0x53 | ||||
| #define TPM_ORD_GetTicks          0xf1 | ||||
| #define TPM_ORD_GetCapability     0x65 | ||||
| 
 | ||||
| #define TPM_CAP_PROPERTY          0x05 | ||||
| 
 | ||||
| #define TPM_CAP_PROP_INPUT_BUFFER 0x124 | ||||
| 
 | ||||
| /* TPM2 defines */ | ||||
| #define TPM2_ST_NO_SESSIONS       0x8001 | ||||
| 
 | ||||
| #define TPM2_CC_ReadClock         0x00000181 | ||||
| #define TPM2_CC_GetCapability     0x0000017a | ||||
| 
 | ||||
| #define TPM2_CAP_TPM_PROPERTIES   0x6 | ||||
| 
 | ||||
| #define TPM2_PT_MAX_COMMAND_SIZE  0x11e | ||||
| 
 | ||||
| #endif /* TPM_TPM_INT_H */ | ||||
|  | ||||
| @ -57,6 +57,7 @@ struct TPMPassthruState { | ||||
|     int cancel_fd; | ||||
| 
 | ||||
|     TPMVersion tpm_version; | ||||
|     size_t tpm_buffersize; | ||||
| }; | ||||
| 
 | ||||
| typedef struct TPMPassthruState TPMPassthruState; | ||||
| @ -201,7 +202,15 @@ static TPMVersion tpm_passthrough_get_tpm_version(TPMBackend *tb) | ||||
| 
 | ||||
| static size_t tpm_passthrough_get_buffer_size(TPMBackend *tb) | ||||
| { | ||||
|     return 4096; | ||||
|     TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(tb); | ||||
|     int ret; | ||||
| 
 | ||||
|     ret = tpm_util_get_buffer_size(tpm_pt->tpm_fd, tpm_pt->tpm_version, | ||||
|                                    &tpm_pt->tpm_buffersize); | ||||
|     if (ret < 0) { | ||||
|         tpm_pt->tpm_buffersize = 4096; | ||||
|     } | ||||
|     return tpm_pt->tpm_buffersize; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  | ||||
| @ -20,10 +20,19 @@ | ||||
|  */ | ||||
| 
 | ||||
| #include "qemu/osdep.h" | ||||
| #include "qemu/error-report.h" | ||||
| #include "tpm_util.h" | ||||
| #include "tpm_int.h" | ||||
| #include "exec/memory.h" | ||||
| 
 | ||||
| #define DEBUG_TPM 0 | ||||
| 
 | ||||
| #define DPRINTF(fmt, ...) do { \ | ||||
|     if (DEBUG_TPM) { \ | ||||
|         fprintf(stderr, "tpm-util:"fmt"\n", ## __VA_ARGS__); \ | ||||
|     } \ | ||||
| } while (0) | ||||
| 
 | ||||
| /*
 | ||||
|  * Write an error message in the given output buffer. | ||||
|  */ | ||||
| @ -173,3 +182,109 @@ int tpm_util_test_tpmdev(int tpm_fd, TPMVersion *tpm_version) | ||||
| 
 | ||||
|     return 1; | ||||
| } | ||||
| 
 | ||||
| int tpm_util_get_buffer_size(int tpm_fd, TPMVersion tpm_version, | ||||
|                              size_t *buffersize) | ||||
| { | ||||
|     unsigned char buf[1024]; | ||||
|     int ret; | ||||
| 
 | ||||
|     switch (tpm_version) { | ||||
|     case TPM_VERSION_1_2: { | ||||
|         const struct tpm_req_get_buffer_size { | ||||
|             struct tpm_req_hdr hdr; | ||||
|             uint32_t capability; | ||||
|             uint32_t len; | ||||
|             uint32_t subcap; | ||||
|         } QEMU_PACKED tpm_get_buffer_size = { | ||||
|             .hdr = { | ||||
|                 .tag = cpu_to_be16(TPM_TAG_RQU_COMMAND), | ||||
|                 .len = cpu_to_be32(sizeof(tpm_get_buffer_size)), | ||||
|                 .ordinal = cpu_to_be32(TPM_ORD_GetCapability), | ||||
|             }, | ||||
|             .capability = cpu_to_be32(TPM_CAP_PROPERTY), | ||||
|             .len = cpu_to_be32(sizeof(uint32_t)), | ||||
|             .subcap = cpu_to_be32(TPM_CAP_PROP_INPUT_BUFFER), | ||||
|         }; | ||||
|         struct tpm_resp_get_buffer_size { | ||||
|             struct tpm_resp_hdr hdr; | ||||
|             uint32_t len; | ||||
|             uint32_t buffersize; | ||||
|         } QEMU_PACKED *tpm_resp = (struct tpm_resp_get_buffer_size *)buf; | ||||
| 
 | ||||
|         ret = tpm_util_request(tpm_fd, (unsigned char *)&tpm_get_buffer_size, | ||||
|                                sizeof(tpm_get_buffer_size), buf, sizeof(buf)); | ||||
|         if (ret < 0) { | ||||
|             return ret; | ||||
|         } | ||||
| 
 | ||||
|         if (be32_to_cpu(tpm_resp->hdr.len) != sizeof(*tpm_resp) || | ||||
|             be32_to_cpu(tpm_resp->len) != sizeof(uint32_t)) { | ||||
|             DPRINTF("tpm_resp->hdr.len = %u, expected = %zu\n", | ||||
|                     be32_to_cpu(tpm_resp->hdr.len), sizeof(*tpm_resp)); | ||||
|             DPRINTF("tpm_resp->len = %u, expected = %zu\n", | ||||
|                     be32_to_cpu(tpm_resp->len), sizeof(uint32_t)); | ||||
|             error_report("tpm_util: Got unexpected response to " | ||||
|                          "TPM_GetCapability; errcode: 0x%x", | ||||
|                          be32_to_cpu(tpm_resp->hdr.errcode)); | ||||
|             return -EFAULT; | ||||
|         } | ||||
|         *buffersize = be32_to_cpu(tpm_resp->buffersize); | ||||
|         break; | ||||
|     } | ||||
|     case TPM_VERSION_2_0: { | ||||
|         const struct tpm2_req_get_buffer_size { | ||||
|             struct tpm_req_hdr hdr; | ||||
|             uint32_t capability; | ||||
|             uint32_t property; | ||||
|             uint32_t count; | ||||
|         } QEMU_PACKED tpm2_get_buffer_size = { | ||||
|             .hdr = { | ||||
|                 .tag = cpu_to_be16(TPM2_ST_NO_SESSIONS), | ||||
|                 .len = cpu_to_be32(sizeof(tpm2_get_buffer_size)), | ||||
|                 .ordinal = cpu_to_be32(TPM2_CC_GetCapability), | ||||
|             }, | ||||
|             .capability = cpu_to_be32(TPM2_CAP_TPM_PROPERTIES), | ||||
|             .property = cpu_to_be32(TPM2_PT_MAX_COMMAND_SIZE), | ||||
|             .count = cpu_to_be32(2), /* also get TPM2_PT_MAX_RESPONSE_SIZE */ | ||||
|         }; | ||||
|         struct tpm2_resp_get_buffer_size { | ||||
|             struct tpm_resp_hdr hdr; | ||||
|             uint8_t more; | ||||
|             uint32_t capability; | ||||
|             uint32_t count; | ||||
|             uint32_t property1; | ||||
|             uint32_t value1; | ||||
|             uint32_t property2; | ||||
|             uint32_t value2; | ||||
|         } QEMU_PACKED *tpm2_resp = (struct tpm2_resp_get_buffer_size *)buf; | ||||
| 
 | ||||
|         ret = tpm_util_request(tpm_fd, (unsigned char *)&tpm2_get_buffer_size, | ||||
|                                sizeof(tpm2_get_buffer_size), buf, sizeof(buf)); | ||||
|         if (ret < 0) { | ||||
|             return ret; | ||||
|         } | ||||
| 
 | ||||
|         if (be32_to_cpu(tpm2_resp->hdr.len) != sizeof(*tpm2_resp) || | ||||
|             be32_to_cpu(tpm2_resp->count) != 2) { | ||||
|             DPRINTF("tpm2_resp->hdr.len = %u, expected = %zu\n", | ||||
|                     be32_to_cpu(tpm2_resp->hdr.len), sizeof(*tpm2_resp)); | ||||
|             DPRINTF("tpm2_resp->len = %u, expected = %u\n", | ||||
|                     be32_to_cpu(tpm2_resp->count), 2); | ||||
|             error_report("tpm_util: Got unexpected response to " | ||||
|                          "TPM2_GetCapability; errcode: 0x%x", | ||||
|                          be32_to_cpu(tpm2_resp->hdr.errcode)); | ||||
|             return -EFAULT; | ||||
|         } | ||||
|         *buffersize = MAX(be32_to_cpu(tpm2_resp->value1), | ||||
|                           be32_to_cpu(tpm2_resp->value2)); | ||||
|         break; | ||||
|     } | ||||
|     case TPM_VERSION_UNSPEC: | ||||
|         return -EFAULT; | ||||
|     } | ||||
| 
 | ||||
|     DPRINTF("buffersize of device: %zu\n", *buffersize); | ||||
| 
 | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| @ -36,4 +36,7 @@ static inline uint32_t tpm_cmd_get_size(const void *b) | ||||
|     return be32_to_cpu(*(const uint32_t *)(b + 2)); | ||||
| } | ||||
| 
 | ||||
| int tpm_util_get_buffer_size(int tpm_fd, TPMVersion tpm_version, | ||||
|                              size_t *buffersize); | ||||
| 
 | ||||
| #endif /* TPM_TPM_UTIL_H */ | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Stefan Berger
						Stefan Berger