diff options
| -rw-r--r-- | crypto/asymmetric_keys/asym_tpm.c | 112 | ||||
| -rw-r--r-- | include/crypto/asym_tpm_subtype.h | 3 |
2 files changed, 115 insertions, 0 deletions
diff --git a/crypto/asymmetric_keys/asym_tpm.c b/crypto/asymmetric_keys/asym_tpm.c index d0b2b97e8e54..308c51e055a4 100644 --- a/crypto/asymmetric_keys/asym_tpm.c +++ b/crypto/asymmetric_keys/asym_tpm.c | |||
| @@ -7,6 +7,7 @@ | |||
| 7 | #include <linux/seq_file.h> | 7 | #include <linux/seq_file.h> |
| 8 | #include <linux/scatterlist.h> | 8 | #include <linux/scatterlist.h> |
| 9 | #include <linux/tpm.h> | 9 | #include <linux/tpm.h> |
| 10 | #include <asm/unaligned.h> | ||
| 10 | #include <keys/asymmetric-subtype.h> | 11 | #include <keys/asymmetric-subtype.h> |
| 11 | #include <crypto/asym_tpm_subtype.h> | 12 | #include <crypto/asym_tpm_subtype.h> |
| 12 | 13 | ||
| @@ -37,6 +38,110 @@ static void asym_tpm_destroy(void *payload0, void *payload3) | |||
| 37 | kfree(tk); | 38 | kfree(tk); |
| 38 | } | 39 | } |
| 39 | 40 | ||
| 41 | /* | ||
| 42 | * Parse enough information out of TPM_KEY structure: | ||
| 43 | * TPM_STRUCT_VER -> 4 bytes | ||
| 44 | * TPM_KEY_USAGE -> 2 bytes | ||
| 45 | * TPM_KEY_FLAGS -> 4 bytes | ||
| 46 | * TPM_AUTH_DATA_USAGE -> 1 byte | ||
| 47 | * TPM_KEY_PARMS -> variable | ||
| 48 | * UINT32 PCRInfoSize -> 4 bytes | ||
| 49 | * BYTE* -> PCRInfoSize bytes | ||
| 50 | * TPM_STORE_PUBKEY | ||
| 51 | * UINT32 encDataSize; | ||
| 52 | * BYTE* -> encDataSize; | ||
| 53 | * | ||
| 54 | * TPM_KEY_PARMS: | ||
| 55 | * TPM_ALGORITHM_ID -> 4 bytes | ||
| 56 | * TPM_ENC_SCHEME -> 2 bytes | ||
| 57 | * TPM_SIG_SCHEME -> 2 bytes | ||
| 58 | * UINT32 parmSize -> 4 bytes | ||
| 59 | * BYTE* -> variable | ||
| 60 | */ | ||
| 61 | static int extract_key_parameters(struct tpm_key *tk) | ||
| 62 | { | ||
| 63 | const void *cur = tk->blob; | ||
| 64 | uint32_t len = tk->blob_len; | ||
| 65 | const void *pub_key; | ||
| 66 | uint32_t sz; | ||
| 67 | uint32_t key_len; | ||
| 68 | |||
| 69 | if (len < 11) | ||
| 70 | return -EBADMSG; | ||
| 71 | |||
| 72 | /* Ensure this is a legacy key */ | ||
| 73 | if (get_unaligned_be16(cur + 4) != 0x0015) | ||
| 74 | return -EBADMSG; | ||
| 75 | |||
| 76 | /* Skip to TPM_KEY_PARMS */ | ||
| 77 | cur += 11; | ||
| 78 | len -= 11; | ||
| 79 | |||
| 80 | if (len < 12) | ||
| 81 | return -EBADMSG; | ||
| 82 | |||
| 83 | /* Make sure this is an RSA key */ | ||
| 84 | if (get_unaligned_be32(cur) != 0x00000001) | ||
| 85 | return -EBADMSG; | ||
| 86 | |||
| 87 | /* Make sure this is TPM_ES_RSAESPKCSv15 encoding scheme */ | ||
| 88 | if (get_unaligned_be16(cur + 4) != 0x0002) | ||
| 89 | return -EBADMSG; | ||
| 90 | |||
| 91 | /* Make sure this is TPM_SS_RSASSAPKCS1v15_DER signature scheme */ | ||
| 92 | if (get_unaligned_be16(cur + 6) != 0x0003) | ||
| 93 | return -EBADMSG; | ||
| 94 | |||
| 95 | sz = get_unaligned_be32(cur + 8); | ||
| 96 | if (len < sz + 12) | ||
| 97 | return -EBADMSG; | ||
| 98 | |||
| 99 | /* Move to TPM_RSA_KEY_PARMS */ | ||
| 100 | len -= 12; | ||
| 101 | cur += 12; | ||
| 102 | |||
| 103 | /* Grab the RSA key length */ | ||
| 104 | key_len = get_unaligned_be32(cur); | ||
| 105 | |||
| 106 | switch (key_len) { | ||
| 107 | case 512: | ||
| 108 | case 1024: | ||
| 109 | case 1536: | ||
| 110 | case 2048: | ||
| 111 | break; | ||
| 112 | default: | ||
| 113 | return -EINVAL; | ||
| 114 | } | ||
| 115 | |||
| 116 | /* Move just past TPM_KEY_PARMS */ | ||
| 117 | cur += sz; | ||
| 118 | len -= sz; | ||
| 119 | |||
| 120 | if (len < 4) | ||
| 121 | return -EBADMSG; | ||
| 122 | |||
| 123 | sz = get_unaligned_be32(cur); | ||
| 124 | if (len < 4 + sz) | ||
| 125 | return -EBADMSG; | ||
| 126 | |||
| 127 | /* Move to TPM_STORE_PUBKEY */ | ||
| 128 | cur += 4 + sz; | ||
| 129 | len -= 4 + sz; | ||
| 130 | |||
| 131 | /* Grab the size of the public key, it should jive with the key size */ | ||
| 132 | sz = get_unaligned_be32(cur); | ||
| 133 | if (sz > 256) | ||
| 134 | return -EINVAL; | ||
| 135 | |||
| 136 | pub_key = cur + 4; | ||
| 137 | |||
| 138 | tk->key_len = key_len; | ||
| 139 | tk->pub_key = pub_key; | ||
| 140 | tk->pub_key_len = sz; | ||
| 141 | |||
| 142 | return 0; | ||
| 143 | } | ||
| 144 | |||
| 40 | /* Given the blob, parse it and load it into the TPM */ | 145 | /* Given the blob, parse it and load it into the TPM */ |
| 41 | struct tpm_key *tpm_key_create(const void *blob, uint32_t blob_len) | 146 | struct tpm_key *tpm_key_create(const void *blob, uint32_t blob_len) |
| 42 | { | 147 | { |
| @@ -64,8 +169,15 @@ struct tpm_key *tpm_key_create(const void *blob, uint32_t blob_len) | |||
| 64 | 169 | ||
| 65 | tk->blob_len = blob_len; | 170 | tk->blob_len = blob_len; |
| 66 | 171 | ||
| 172 | r = extract_key_parameters(tk); | ||
| 173 | if (r < 0) | ||
| 174 | goto error_extract; | ||
| 175 | |||
| 67 | return tk; | 176 | return tk; |
| 68 | 177 | ||
| 178 | error_extract: | ||
| 179 | kfree(tk->blob); | ||
| 180 | tk->blob_len = 0; | ||
| 69 | error_memdup: | 181 | error_memdup: |
| 70 | kfree(tk); | 182 | kfree(tk); |
| 71 | error: | 183 | error: |
diff --git a/include/crypto/asym_tpm_subtype.h b/include/crypto/asym_tpm_subtype.h index 03550b850998..48198c36d6b9 100644 --- a/include/crypto/asym_tpm_subtype.h +++ b/include/crypto/asym_tpm_subtype.h | |||
| @@ -7,6 +7,9 @@ | |||
| 7 | struct tpm_key { | 7 | struct tpm_key { |
| 8 | void *blob; | 8 | void *blob; |
| 9 | u32 blob_len; | 9 | u32 blob_len; |
| 10 | uint16_t key_len; /* Size in bits of the key */ | ||
| 11 | const void *pub_key; /* pointer inside blob to the public key bytes */ | ||
| 12 | uint16_t pub_key_len; /* length of the public key */ | ||
| 10 | }; | 13 | }; |
| 11 | 14 | ||
| 12 | struct tpm_key *tpm_key_create(const void *blob, uint32_t blob_len); | 15 | struct tpm_key *tpm_key_create(const void *blob, uint32_t blob_len); |
