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 "Rewrap_fp.h"
     10 #include "Object_spt_fp.h"
     11 //
     12 //
     13 //     Error Returns                 Meaning
     14 //
     15 //     TPM_RC_ATTRIBUTES             newParent is not a decryption key
     16 //     TPM_RC_HANDLE                 oldParent does not consistent with inSymSeed
     17 //     TPM_RC_INTEGRITY              the integrity check of inDuplicate failed
     18 //     TPM_RC_KEY                    for an ECC key, the public key is not on the curve of the curve ID
     19 //     TPM_RC_KEY_SIZE               the decrypted input symmetric key size does not matches the
     20 //                                   symmetric algorithm key size of oldParent
     21 //     TPM_RC_TYPE                   oldParent is not a storage key, or 'newParent is not a storage key
     22 //     TPM_RC_VALUE                  for an 'oldParent; RSA key, the data to be decrypted is greater than
     23 //                                   the public exponent
     24 //     Unmarshal errors              errors during unmarshaling the input encrypted buffer to a ECC public
     25 //                                   key, or unmarshal the private buffer to sensitive
     26 //
     27 TPM_RC
     28 TPM2_Rewrap(
     29    Rewrap_In         *in,             // IN: input parameter list
     30    Rewrap_Out        *out             // OUT: output parameter list
     31    )
     32 {
     33    TPM_RC                   result = TPM_RC_SUCCESS;
     34    OBJECT                   *oldParent;
     35    TPM2B_DATA               data;               // symmetric key
     36    UINT16                   hashSize = 0;
     37    TPM2B_PRIVATE            privateBlob;        // A temporary private blob
     38                                                 // to transit between old
     39                                                 // and new wrappers
     40 
     41 // Input Validation
     42 
     43    if((in->inSymSeed.t.size == 0 && in->oldParent != TPM_RH_NULL)
     44            || (in->inSymSeed.t.size != 0 && in->oldParent == TPM_RH_NULL))
     45        return TPM_RC_HANDLE + RC_Rewrap_oldParent;
     46 
     47    if(in->oldParent != TPM_RH_NULL)
     48    {
     49        // Get old parent pointer
     50        oldParent = ObjectGet(in->oldParent);
     51 
     52          // old parent key must be a storage object
     53          if(!ObjectIsStorage(in->oldParent))
     54              return TPM_RC_TYPE + RC_Rewrap_oldParent;
     55 
     56          // Decrypt input secret data via asymmetric decryption. A
     57          // TPM_RC_VALUE, TPM_RC_KEY or unmarshal errors may be returned at this
     58          // point
     59          result = CryptSecretDecrypt(in->oldParent, NULL,
     60                                      "DUPLICATE", &in->inSymSeed, &data);
     61          if(result != TPM_RC_SUCCESS)
     62              return TPM_RC_VALUE + RC_Rewrap_inSymSeed;
     63 
     64        // Unwrap Outer
     65        result = UnwrapOuter(in->oldParent, &in->name,
     66                             oldParent->publicArea.nameAlg, (TPM2B_SEED *) &data,
     67                             FALSE,
     68                             in->inDuplicate.t.size, in->inDuplicate.t.buffer);
     69        if(result != TPM_RC_SUCCESS)
     70            return RcSafeAddToResult(result, RC_Rewrap_inDuplicate);
     71 
     72        // Copy unwrapped data to temporary variable, remove the integrity field
     73        hashSize = sizeof(UINT16) +
     74                   CryptGetHashDigestSize(oldParent->publicArea.nameAlg);
     75        privateBlob.t.size = in->inDuplicate.t.size - hashSize;
     76        MemoryCopy(privateBlob.t.buffer, in->inDuplicate.t.buffer + hashSize,
     77                   privateBlob.t.size, sizeof(privateBlob.t.buffer));
     78    }
     79    else
     80    {
     81        // No outer wrap from input blob.   Direct copy.
     82        privateBlob = in->inDuplicate;
     83    }
     84 
     85    if(in->newParent != TPM_RH_NULL)
     86    {
     87        OBJECT          *newParent;
     88        newParent = ObjectGet(in->newParent);
     89 
     90        // New parent must be a storage object
     91        if(!ObjectIsStorage(in->newParent))
     92            return TPM_RC_TYPE + RC_Rewrap_newParent;
     93 
     94        // Make new encrypt key and its associated secret structure. A
     95        // TPM_RC_VALUE error may be returned at this point if RSA algorithm is
     96        // enabled in TPM
     97        out->outSymSeed.t.size = sizeof(out->outSymSeed.t.secret);
     98        result = CryptSecretEncrypt(in->newParent,
     99                                    "DUPLICATE", &data, &out->outSymSeed);
    100        if(result != TPM_RC_SUCCESS) return result;
    101 
    102 // Command output
    103        // Copy temporary variable to output, reserve the space for integrity
    104        hashSize = sizeof(UINT16) +
    105                   CryptGetHashDigestSize(newParent->publicArea.nameAlg);
    106        out->outDuplicate.t.size = privateBlob.t.size;
    107        MemoryCopy(out->outDuplicate.t.buffer + hashSize, privateBlob.t.buffer,
    108                   privateBlob.t.size, sizeof(out->outDuplicate.t.buffer));
    109 
    110        // Produce outer wrapper for output
    111        out->outDuplicate.t.size = ProduceOuterWrap(in->newParent, &in->name,
    112                                   newParent->publicArea.nameAlg,
    113                                   (TPM2B_SEED *) &data,
    114                                   FALSE,
    115                                   out->outDuplicate.t.size,
    116                                   out->outDuplicate.t.buffer);
    117 
    118    }
    119    else // New parent is a null key so there is no seed
    120    {
    121        out->outSymSeed.t.size = 0;
    122 
    123        // Copy privateBlob directly
    124        out->outDuplicate = privateBlob;
    125    }
    126 
    127    return TPM_RC_SUCCESS;
    128 }
    129