diff options
author | Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com> | 2015-10-11 05:26:58 -0400 |
---|---|---|
committer | Peter Huewe <peterhuewe@gmx.de> | 2015-10-18 19:01:20 -0400 |
commit | a74f8b36352e79b13d48fa92759c9ea6b78d5817 (patch) | |
tree | 672ff847e04b461d4926e982506605b846426603 /drivers/char | |
parent | b8e98dcdc5ad24bbecc763cd0ac87bbde602e5ea (diff) |
tpm: introduce tpm_buf
This patch introduces struct tpm_buf that provides a string buffer for
constructing TPM commands. This allows to construct variable sized TPM
commands. For the buffer a page is allocated and mapped, which limits
maximum size to PAGE_SIZE.
Variable sized TPM commands are needed in order to add algorithmic
agility.
Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
Reviewed-by: Peter Huewe <peterhuewe@gmx.de>
Signed-off-by: Peter Huewe <peterhuewe@gmx.de>
Diffstat (limited to 'drivers/char')
-rw-r--r-- | drivers/char/tpm/tpm.h | 97 |
1 files changed, 97 insertions, 0 deletions
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h index 36ceb710f0eb..cb46f6267af2 100644 --- a/drivers/char/tpm/tpm.h +++ b/drivers/char/tpm/tpm.h | |||
@@ -1,5 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2004 IBM Corporation | 2 | * Copyright (C) 2004 IBM Corporation |
3 | * Copyright (C) 2015 Intel Corporation | ||
3 | * | 4 | * |
4 | * Authors: | 5 | * Authors: |
5 | * Leendert van Doorn <leendert@watson.ibm.com> | 6 | * Leendert van Doorn <leendert@watson.ibm.com> |
@@ -28,6 +29,7 @@ | |||
28 | #include <linux/tpm.h> | 29 | #include <linux/tpm.h> |
29 | #include <linux/acpi.h> | 30 | #include <linux/acpi.h> |
30 | #include <linux/cdev.h> | 31 | #include <linux/cdev.h> |
32 | #include <linux/highmem.h> | ||
31 | 33 | ||
32 | enum tpm_const { | 34 | enum tpm_const { |
33 | TPM_MINOR = 224, /* officially assigned */ | 35 | TPM_MINOR = 224, /* officially assigned */ |
@@ -390,6 +392,101 @@ struct tpm_cmd_t { | |||
390 | tpm_cmd_params params; | 392 | tpm_cmd_params params; |
391 | } __packed; | 393 | } __packed; |
392 | 394 | ||
395 | /* A string buffer type for constructing TPM commands. This is based on the | ||
396 | * ideas of string buffer code in security/keys/trusted.h but is heap based | ||
397 | * in order to keep the stack usage minimal. | ||
398 | */ | ||
399 | |||
400 | enum tpm_buf_flags { | ||
401 | TPM_BUF_OVERFLOW = BIT(0), | ||
402 | }; | ||
403 | |||
404 | struct tpm_buf { | ||
405 | struct page *data_page; | ||
406 | unsigned int flags; | ||
407 | u8 *data; | ||
408 | }; | ||
409 | |||
410 | static inline void tpm_buf_init(struct tpm_buf *buf, u16 tag, u32 ordinal) | ||
411 | { | ||
412 | struct tpm_input_header *head; | ||
413 | |||
414 | buf->data_page = alloc_page(GFP_HIGHUSER); | ||
415 | if (!buf->data_page) | ||
416 | return -ENOMEM; | ||
417 | |||
418 | buf->flags = 0; | ||
419 | buf->data = kmap(buf->data_page); | ||
420 | |||
421 | head = (struct tpm_input_header *) buf->data; | ||
422 | |||
423 | head->tag = cpu_to_be16(tag); | ||
424 | head->length = cpu_to_be32(sizeof(*head)); | ||
425 | head->ordinal = cpu_to_be32(ordinal); | ||
426 | |||
427 | return 0; | ||
428 | } | ||
429 | |||
430 | static inline void tpm_buf_destroy(struct tpm_buf *buf) | ||
431 | { | ||
432 | kunmap(buf->data_page); | ||
433 | __free_page(buf->data_page); | ||
434 | } | ||
435 | |||
436 | static inline u32 tpm_buf_length(struct tpm_buf *buf) | ||
437 | { | ||
438 | struct tpm_input_header *head = (struct tpm_input_header *) buf->data; | ||
439 | |||
440 | return be32_to_cpu(head->length); | ||
441 | } | ||
442 | |||
443 | static inline u16 tpm_buf_tag(struct tpm_buf *buf) | ||
444 | { | ||
445 | struct tpm_input_header *head = (struct tpm_input_header *) buf->data; | ||
446 | |||
447 | return be16_to_cpu(head->tag); | ||
448 | } | ||
449 | |||
450 | static inline void tpm_buf_append(struct tpm_buf *buf, | ||
451 | const unsigned char *new_data, | ||
452 | unsigned int new_len) | ||
453 | { | ||
454 | struct tpm_input_header *head = (struct tpm_input_header *) buf->data; | ||
455 | u32 len = tpm_buf_length(buf); | ||
456 | |||
457 | /* Return silently if overflow has already happened. */ | ||
458 | if (buf->flags & TPM_BUF_OVERFLOW) | ||
459 | return; | ||
460 | |||
461 | if ((len + new_len) > PAGE_SIZE) { | ||
462 | WARN(1, "tpm_buf: overflow\n"); | ||
463 | buf->flags |= TPM_BUF_OVERFLOW; | ||
464 | return; | ||
465 | } | ||
466 | |||
467 | memcpy(&buf->data[len], new_data, new_len); | ||
468 | head->length = cpu_to_be32(len + new_len); | ||
469 | } | ||
470 | |||
471 | static inline void tpm_buf_append_u8(struct tpm_buf *buf, const u8 value) | ||
472 | { | ||
473 | tpm_buf_append(buf, &value, 1); | ||
474 | } | ||
475 | |||
476 | static inline void tpm_buf_append_u16(struct tpm_buf *buf, const u16 value) | ||
477 | { | ||
478 | __be16 value2 = cpu_to_be16(value); | ||
479 | |||
480 | tpm_buf_append(buf, (u8 *) &value2, 2); | ||
481 | } | ||
482 | |||
483 | static inline void tpm_buf_append_u32(struct tpm_buf *buf, const u32 value) | ||
484 | { | ||
485 | __be32 value2 = cpu_to_be32(value); | ||
486 | |||
487 | tpm_buf_append(buf, (u8 *) &value2, 4); | ||
488 | } | ||
489 | |||
393 | extern struct class *tpm_class; | 490 | extern struct class *tpm_class; |
394 | extern dev_t tpm_devt; | 491 | extern dev_t tpm_devt; |
395 | extern const struct file_operations tpm_fops; | 492 | extern const struct file_operations tpm_fops; |