blob: 7179ac36c435e1e4b4dd95022bdb9f301c29b8a8 [file] [log] [blame]
Vadim Bendebury56797522015-05-20 10:32:25 -07001// This file was extracted from the TCG Published
2// Trusted Platform Module Library
3// Part 3: Commands
4// Family "2.0"
5// Level 00 Revision 01.16
6// October 30, 2014
7
8#include "InternalRoutines.h"
9#include "EncryptDecrypt_fp.h"
10//
11//
12// Error Returns Meaning
13//
14// TPM_RC_KEY is not a symmetric decryption key with both public and private
15// portions loaded
16// TPM_RC_SIZE IvIn size is incompatible with the block cipher mode; or inData size is
17// not an even multiple of the block size for CBC or ECB mode
18// TPM_RC_VALUE keyHandle is restricted and the argument mode does not match the
19// key's mode
20//
21TPM_RC
22TPM2_EncryptDecrypt(
23 EncryptDecrypt_In *in, // IN: input parameter list
24 EncryptDecrypt_Out *out // OUT: output parameter list
25 )
26{
27 OBJECT *symKey;
28 UINT16 keySize;
29 UINT16 blockSize;
30 BYTE *key;
31 TPM_ALG_ID alg;
32
33// Input Validation
34 symKey = ObjectGet(in->keyHandle);
35
36 // The input key should be a symmetric decrypt key.
37 if( symKey->publicArea.type != TPM_ALG_SYMCIPHER
38 || symKey->attributes.publicOnly == SET)
39 return TPM_RC_KEY + RC_EncryptDecrypt_keyHandle;
40
41 // If the input mode is TPM_ALG_NULL, use the key's mode
42 if( in->mode == TPM_ALG_NULL)
Vadim Bendeburya49f9122015-10-27 16:32:54 -070043 in->mode = symKey->publicArea.parameters.symDetail.sym.mode.sym;
Vadim Bendebury56797522015-05-20 10:32:25 -070044
45 // If the key is restricted, the input symmetric mode should match the key's
46 // symmetric mode
47 if( symKey->publicArea.objectAttributes.restricted == SET
Vadim Bendeburya49f9122015-10-27 16:32:54 -070048 && symKey->publicArea.parameters.symDetail.sym.mode.sym != in->mode)
Vadim Bendebury56797522015-05-20 10:32:25 -070049 return TPM_RC_VALUE + RC_EncryptDecrypt_mode;
50
51 // If the mode is null, then we have a problem.
52 // Note: Construction of a TPMT_SYM_DEF does not allow the 'mode' to be
53 // TPM_ALG_NULL so setting in->mode to the mode of the key should have
54 // produced a valid mode. However, this is suspenders.
55 if(in->mode == TPM_ALG_NULL)
56 return TPM_RC_VALUE + RC_EncryptDecrypt_mode;
57
58 // The input iv for ECB mode should be null. All the other modes should
59 // have an iv size same as encryption block size
60
Vadim Bendeburya49f9122015-10-27 16:32:54 -070061 keySize = symKey->publicArea.parameters.symDetail.sym.keyBits.sym;
62 alg = symKey->publicArea.parameters.symDetail.sym.algorithm;
Vadim Bendebury56797522015-05-20 10:32:25 -070063 blockSize = CryptGetSymmetricBlockSize(alg, keySize);
64 if( (in->mode == TPM_ALG_ECB && in->ivIn.t.size != 0)
65 || (in->mode != TPM_ALG_ECB && in->ivIn.t.size != blockSize))
66 return TPM_RC_SIZE + RC_EncryptDecrypt_ivIn;
67
68 // The input data size of CBC mode or ECB mode must be an even multiple of
69 // the symmetric algorithm's block size
70 if( (in->mode == TPM_ALG_CBC || in->mode == TPM_ALG_ECB)
71 && (in->inData.t.size % blockSize) != 0)
72 return TPM_RC_SIZE + RC_EncryptDecrypt_inData;
73
74 // Copy IV
75 // Note: This is copied here so that the calls to the encrypt/decrypt functions
76 // will modify the output buffer, not the input buffer
77 out->ivOut = in->ivIn;
78
79// Command Output
80
81 key = symKey->sensitive.sensitive.sym.t.buffer;
82 // For symmetric encryption, the cipher data size is the same as plain data
83 // size.
84 out->outData.t.size = in->inData.t.size;
85 if(in->decrypt == YES)
86 {
87 // Decrypt data to output
88 CryptSymmetricDecrypt(out->outData.t.buffer,
89 alg,
90 keySize, in->mode, key,
91 &(out->ivOut),
92 in->inData.t.size,
93 in->inData.t.buffer);
94 }
95 else
96 {
97 // Encrypt data to output
98 CryptSymmetricEncrypt(out->outData.t.buffer,
99 alg,
100 keySize,
101 in->mode, key,
102 &(out->ivOut),
103 in->inData.t.size,
104 in->inData.t.buffer);
105 }
106
107 return TPM_RC_SUCCESS;
108}