Home | History | Annotate | Download | only in tpm2
      1 // 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 //
     21 TPM_RC
     22 TPM2_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)
     43        in->mode = symKey->publicArea.parameters.symDetail.sym.mode.sym;
     44 
     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
     48       && symKey->publicArea.parameters.symDetail.sym.mode.sym != in->mode)
     49        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 
     61    keySize = symKey->publicArea.parameters.symDetail.sym.keyBits.sym;
     62    alg = symKey->publicArea.parameters.symDetail.sym.algorithm;
     63    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 }
    109