diff options
| author | Mimi Zohar <zohar@linux.vnet.ibm.com> | 2010-12-13 16:53:10 -0500 |
|---|---|---|
| committer | James Morris <jmorris@namei.org> | 2010-12-15 01:44:25 -0500 |
| commit | bc5e0af0b36b6cc9de301074426c279fc9b72675 (patch) | |
| tree | 116b20ec3e81f4a956ecf0fde2dfba11d43117dc | |
| parent | 38ef4c2e437d11b5922723504b62824e96761459 (diff) | |
trusted-keys: additional TSS return code and other error handling
Previously not all TSS return codes were tested, as they were all eventually
caught by the TPM. Now all returns are tested and handled immediately.
This patch also fixes memory leaks in error and non-error paths.
Signed-off-by: David Safford <safford@watson.ibm.com>
Acked-by: Mimi Zohar <zohar@us.ibm.com>
Acked-by: David Howells <dhowells@redhat.com>
Acked-by: Serge E. Hallyn <serge@hallyn.com>
Signed-off-by: James Morris <jmorris@namei.org>
| -rw-r--r-- | security/keys/trusted_defined.c | 149 |
1 files changed, 87 insertions, 62 deletions
diff --git a/security/keys/trusted_defined.c b/security/keys/trusted_defined.c index aaaa069967a6..3dc3db15b5d9 100644 --- a/security/keys/trusted_defined.c +++ b/security/keys/trusted_defined.c | |||
| @@ -108,7 +108,8 @@ static int TSS_rawhmac(unsigned char *digest, const unsigned char *key, | |||
| 108 | goto out; | 108 | goto out; |
| 109 | } | 109 | } |
| 110 | va_end(argp); | 110 | va_end(argp); |
| 111 | ret = crypto_shash_final(&sdesc->shash, digest); | 111 | if (!ret) |
| 112 | ret = crypto_shash_final(&sdesc->shash, digest); | ||
| 112 | out: | 113 | out: |
| 113 | kfree(sdesc); | 114 | kfree(sdesc); |
| 114 | return ret; | 115 | return ret; |
| @@ -117,9 +118,9 @@ out: | |||
| 117 | /* | 118 | /* |
| 118 | * calculate authorization info fields to send to TPM | 119 | * calculate authorization info fields to send to TPM |
| 119 | */ | 120 | */ |
| 120 | static uint32_t TSS_authhmac(unsigned char *digest, const unsigned char *key, | 121 | static int TSS_authhmac(unsigned char *digest, const unsigned char *key, |
| 121 | const unsigned int keylen, unsigned char *h1, | 122 | const unsigned int keylen, unsigned char *h1, |
| 122 | unsigned char *h2, unsigned char h3, ...) | 123 | unsigned char *h2, unsigned char h3, ...) |
| 123 | { | 124 | { |
| 124 | unsigned char paramdigest[SHA1_DIGEST_SIZE]; | 125 | unsigned char paramdigest[SHA1_DIGEST_SIZE]; |
| 125 | struct sdesc *sdesc; | 126 | struct sdesc *sdesc; |
| @@ -146,15 +147,17 @@ static uint32_t TSS_authhmac(unsigned char *digest, const unsigned char *key, | |||
| 146 | break; | 147 | break; |
| 147 | data = va_arg(argp, unsigned char *); | 148 | data = va_arg(argp, unsigned char *); |
| 148 | ret = crypto_shash_update(&sdesc->shash, data, dlen); | 149 | ret = crypto_shash_update(&sdesc->shash, data, dlen); |
| 149 | if (ret < 0) | 150 | if (ret < 0) { |
| 151 | va_end(argp); | ||
| 150 | goto out; | 152 | goto out; |
| 153 | } | ||
| 151 | } | 154 | } |
| 152 | va_end(argp); | 155 | va_end(argp); |
| 153 | ret = crypto_shash_final(&sdesc->shash, paramdigest); | 156 | ret = crypto_shash_final(&sdesc->shash, paramdigest); |
| 154 | if (!ret) | 157 | if (!ret) |
| 155 | TSS_rawhmac(digest, key, keylen, SHA1_DIGEST_SIZE, | 158 | ret = TSS_rawhmac(digest, key, keylen, SHA1_DIGEST_SIZE, |
| 156 | paramdigest, TPM_NONCE_SIZE, h1, | 159 | paramdigest, TPM_NONCE_SIZE, h1, |
| 157 | TPM_NONCE_SIZE, h2, 1, &c, 0, 0); | 160 | TPM_NONCE_SIZE, h2, 1, &c, 0, 0); |
| 158 | out: | 161 | out: |
| 159 | kfree(sdesc); | 162 | kfree(sdesc); |
| 160 | return ret; | 163 | return ret; |
| @@ -163,11 +166,11 @@ out: | |||
| 163 | /* | 166 | /* |
| 164 | * verify the AUTH1_COMMAND (Seal) result from TPM | 167 | * verify the AUTH1_COMMAND (Seal) result from TPM |
| 165 | */ | 168 | */ |
| 166 | static uint32_t TSS_checkhmac1(unsigned char *buffer, | 169 | static int TSS_checkhmac1(unsigned char *buffer, |
| 167 | const uint32_t command, | 170 | const uint32_t command, |
| 168 | const unsigned char *ononce, | 171 | const unsigned char *ononce, |
| 169 | const unsigned char *key, | 172 | const unsigned char *key, |
| 170 | const unsigned int keylen, ...) | 173 | const unsigned int keylen, ...) |
| 171 | { | 174 | { |
| 172 | uint32_t bufsize; | 175 | uint32_t bufsize; |
| 173 | uint16_t tag; | 176 | uint16_t tag; |
| @@ -219,18 +222,22 @@ static uint32_t TSS_checkhmac1(unsigned char *buffer, | |||
| 219 | break; | 222 | break; |
| 220 | dpos = va_arg(argp, unsigned int); | 223 | dpos = va_arg(argp, unsigned int); |
| 221 | ret = crypto_shash_update(&sdesc->shash, buffer + dpos, dlen); | 224 | ret = crypto_shash_update(&sdesc->shash, buffer + dpos, dlen); |
| 222 | if (ret < 0) | 225 | if (ret < 0) { |
| 226 | va_end(argp); | ||
| 223 | goto out; | 227 | goto out; |
| 228 | } | ||
| 224 | } | 229 | } |
| 225 | va_end(argp); | 230 | va_end(argp); |
| 226 | ret = crypto_shash_final(&sdesc->shash, paramdigest); | 231 | ret = crypto_shash_final(&sdesc->shash, paramdigest); |
| 227 | if (ret < 0) | 232 | if (ret < 0) |
| 228 | goto out; | 233 | goto out; |
| 234 | |||
| 229 | ret = TSS_rawhmac(testhmac, key, keylen, SHA1_DIGEST_SIZE, paramdigest, | 235 | ret = TSS_rawhmac(testhmac, key, keylen, SHA1_DIGEST_SIZE, paramdigest, |
| 230 | TPM_NONCE_SIZE, enonce, TPM_NONCE_SIZE, ononce, | 236 | TPM_NONCE_SIZE, enonce, TPM_NONCE_SIZE, ononce, |
| 231 | 1, continueflag, 0, 0); | 237 | 1, continueflag, 0, 0); |
| 232 | if (ret < 0) | 238 | if (ret < 0) |
| 233 | goto out; | 239 | goto out; |
| 240 | |||
| 234 | if (memcmp(testhmac, authdata, SHA1_DIGEST_SIZE)) | 241 | if (memcmp(testhmac, authdata, SHA1_DIGEST_SIZE)) |
| 235 | ret = -EINVAL; | 242 | ret = -EINVAL; |
| 236 | out: | 243 | out: |
| @@ -241,13 +248,13 @@ out: | |||
| 241 | /* | 248 | /* |
| 242 | * verify the AUTH2_COMMAND (unseal) result from TPM | 249 | * verify the AUTH2_COMMAND (unseal) result from TPM |
| 243 | */ | 250 | */ |
| 244 | static uint32_t TSS_checkhmac2(unsigned char *buffer, | 251 | static int TSS_checkhmac2(unsigned char *buffer, |
| 245 | const uint32_t command, | 252 | const uint32_t command, |
| 246 | const unsigned char *ononce, | 253 | const unsigned char *ononce, |
| 247 | const unsigned char *key1, | 254 | const unsigned char *key1, |
| 248 | const unsigned int keylen1, | 255 | const unsigned int keylen1, |
| 249 | const unsigned char *key2, | 256 | const unsigned char *key2, |
| 250 | const unsigned int keylen2, ...) | 257 | const unsigned int keylen2, ...) |
| 251 | { | 258 | { |
| 252 | uint32_t bufsize; | 259 | uint32_t bufsize; |
| 253 | uint16_t tag; | 260 | uint16_t tag; |
| @@ -309,9 +316,12 @@ static uint32_t TSS_checkhmac2(unsigned char *buffer, | |||
| 309 | break; | 316 | break; |
| 310 | dpos = va_arg(argp, unsigned int); | 317 | dpos = va_arg(argp, unsigned int); |
| 311 | ret = crypto_shash_update(&sdesc->shash, buffer + dpos, dlen); | 318 | ret = crypto_shash_update(&sdesc->shash, buffer + dpos, dlen); |
| 312 | if (ret < 0) | 319 | if (ret < 0) { |
| 320 | va_end(argp); | ||
| 313 | goto out; | 321 | goto out; |
| 322 | } | ||
| 314 | } | 323 | } |
| 324 | va_end(argp); | ||
| 315 | ret = crypto_shash_final(&sdesc->shash, paramdigest); | 325 | ret = crypto_shash_final(&sdesc->shash, paramdigest); |
| 316 | if (ret < 0) | 326 | if (ret < 0) |
| 317 | goto out; | 327 | goto out; |
| @@ -319,6 +329,8 @@ static uint32_t TSS_checkhmac2(unsigned char *buffer, | |||
| 319 | ret = TSS_rawhmac(testhmac1, key1, keylen1, SHA1_DIGEST_SIZE, | 329 | ret = TSS_rawhmac(testhmac1, key1, keylen1, SHA1_DIGEST_SIZE, |
| 320 | paramdigest, TPM_NONCE_SIZE, enonce1, | 330 | paramdigest, TPM_NONCE_SIZE, enonce1, |
| 321 | TPM_NONCE_SIZE, ononce, 1, continueflag1, 0, 0); | 331 | TPM_NONCE_SIZE, ononce, 1, continueflag1, 0, 0); |
| 332 | if (ret < 0) | ||
| 333 | goto out; | ||
| 322 | if (memcmp(testhmac1, authdata1, SHA1_DIGEST_SIZE)) { | 334 | if (memcmp(testhmac1, authdata1, SHA1_DIGEST_SIZE)) { |
| 323 | ret = -EINVAL; | 335 | ret = -EINVAL; |
| 324 | goto out; | 336 | goto out; |
| @@ -326,6 +338,8 @@ static uint32_t TSS_checkhmac2(unsigned char *buffer, | |||
| 326 | ret = TSS_rawhmac(testhmac2, key2, keylen2, SHA1_DIGEST_SIZE, | 338 | ret = TSS_rawhmac(testhmac2, key2, keylen2, SHA1_DIGEST_SIZE, |
| 327 | paramdigest, TPM_NONCE_SIZE, enonce2, | 339 | paramdigest, TPM_NONCE_SIZE, enonce2, |
| 328 | TPM_NONCE_SIZE, ononce, 1, continueflag2, 0, 0); | 340 | TPM_NONCE_SIZE, ononce, 1, continueflag2, 0, 0); |
| 341 | if (ret < 0) | ||
| 342 | goto out; | ||
| 329 | if (memcmp(testhmac2, authdata2, SHA1_DIGEST_SIZE)) | 343 | if (memcmp(testhmac2, authdata2, SHA1_DIGEST_SIZE)) |
| 330 | ret = -EINVAL; | 344 | ret = -EINVAL; |
| 331 | out: | 345 | out: |
| @@ -364,8 +378,8 @@ static int tpm_get_random(struct tpm_buf *tb, unsigned char *buf, uint32_t len) | |||
| 364 | store32(tb, TPM_ORD_GETRANDOM); | 378 | store32(tb, TPM_ORD_GETRANDOM); |
| 365 | store32(tb, len); | 379 | store32(tb, len); |
| 366 | ret = trusted_tpm_send(TPM_ANY_NUM, tb->data, sizeof tb->data); | 380 | ret = trusted_tpm_send(TPM_ANY_NUM, tb->data, sizeof tb->data); |
| 367 | memcpy(buf, tb->data + TPM_GETRANDOM_SIZE, len); | 381 | if (!ret) |
| 368 | 382 | memcpy(buf, tb->data + TPM_GETRANDOM_SIZE, len); | |
| 369 | return ret; | 383 | return ret; |
| 370 | } | 384 | } |
| 371 | 385 | ||
| @@ -392,10 +406,13 @@ static int my_get_random(unsigned char *buf, int len) | |||
| 392 | static int pcrlock(const int pcrnum) | 406 | static int pcrlock(const int pcrnum) |
| 393 | { | 407 | { |
| 394 | unsigned char hash[SHA1_DIGEST_SIZE]; | 408 | unsigned char hash[SHA1_DIGEST_SIZE]; |
