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 "Duplicate_fp.h"
     10 #include "Object_spt_fp.h"
     11 //
     12 //
     13 //     Error Returns                Meaning
     14 //
     15 //     TPM_RC_ATTRIBUTES            key to duplicate has fixedParent SET
     16 //     TPM_RC_HIERARCHY             encryptedDuplication is SET and newParentHandle specifies Null
     17 //                                  Hierarchy
     18 //     TPM_RC_KEY                   newParentHandle references invalid ECC key (public point not on the
     19 //                                  curve)
     20 //     TPM_RC_SIZE                  input encryption key size does not match the size specified in
     21 //                                  symmetric algorithm
     22 //     TPM_RC_SYMMETRIC             encryptedDuplication is SET but no symmetric algorithm is provided
     23 //     TPM_RC_TYPE                  newParentHandle is neither a storage key nor TPM_RH_NULL; or
     24 //                                  the object has a NULL nameAlg
     25 //
     26 TPM_RC
     27 TPM2_Duplicate(
     28    Duplicate_In      *in,            // IN: input parameter list
     29    Duplicate_Out     *out            // OUT: output parameter list
     30    )
     31 {
     32    TPM_RC                   result = TPM_RC_SUCCESS;
     33    TPMT_SENSITIVE           sensitive;
     34 
     35    UINT16                   innerKeySize = 0; // encrypt key size for inner wrap
     36 
     37    OBJECT                   *object;
     38    TPM2B_DATA               data;
     39 
     40 // Input Validation
     41 
     42    // Get duplicate object pointer
     43    object = ObjectGet(in->objectHandle);
     44 
     45    // duplicate key must have fixParent bit CLEAR.
     46    if(object->publicArea.objectAttributes.fixedParent == SET)
     47        return TPM_RC_ATTRIBUTES + RC_Duplicate_objectHandle;
     48 
     49    // Do not duplicate object with NULL nameAlg
     50    if(object->publicArea.nameAlg == TPM_ALG_NULL)
     51        return TPM_RC_TYPE + RC_Duplicate_objectHandle;
     52 
     53    // new parent key must be a storage object or TPM_RH_NULL
     54    if(in->newParentHandle != TPM_RH_NULL
     55            && !ObjectIsStorage(in->newParentHandle))
     56        return TPM_RC_TYPE + RC_Duplicate_newParentHandle;
     57 
     58    // If the duplicates object has encryptedDuplication SET, then there must be
     59    // an inner wrapper and the new parent may not be TPM_RH_NULL
     60    if(object->publicArea.objectAttributes.encryptedDuplication == SET)
     61    {
     62        if(in->symmetricAlg.algorithm == TPM_ALG_NULL)
     63            return TPM_RC_SYMMETRIC + RC_Duplicate_symmetricAlg;
     64        if(in->newParentHandle == TPM_RH_NULL)
     65             return TPM_RC_HIERARCHY + RC_Duplicate_newParentHandle;
     66    }
     67 
     68    if(in->symmetricAlg.algorithm == TPM_ALG_NULL)
     69    {
     70        // if algorithm is TPM_ALG_NULL, input key size must be 0
     71        if(in->encryptionKeyIn.t.size != 0)
     72            return TPM_RC_SIZE + RC_Duplicate_encryptionKeyIn;
     73    }
     74    else
     75    {
     76        // Get inner wrap key size
     77        innerKeySize = in->symmetricAlg.keyBits.sym;
     78 
     79        // If provided the input symmetric key must match the size of the algorithm
     80        if(in->encryptionKeyIn.t.size != 0
     81                && in->encryptionKeyIn.t.size != (innerKeySize + 7) / 8)
     82            return TPM_RC_SIZE + RC_Duplicate_encryptionKeyIn;
     83    }
     84 
     85 // Command Output
     86 
     87    if(in->newParentHandle != TPM_RH_NULL)
     88    {
     89 
     90        // Make encrypt key and its associated secret structure. A TPM_RC_KEY
     91        // error may be returned at this point
     92        out->outSymSeed.t.size = sizeof(out->outSymSeed.t.secret);
     93        result = CryptSecretEncrypt(in->newParentHandle,
     94                                    "DUPLICATE", &data, &out->outSymSeed);
     95        pAssert(result != TPM_RC_VALUE);
     96        if(result != TPM_RC_SUCCESS)
     97            return result;
     98    }
     99    else
    100    {
    101        // Do not apply outer wrapper
    102        data.t.size = 0;
    103        out->outSymSeed.t.size = 0;
    104    }
    105 
    106    // Copy sensitive area
    107    sensitive = object->sensitive;
    108 
    109    // Prepare output private data from sensitive
    110    SensitiveToDuplicate(&sensitive, &object->name, in->newParentHandle,
    111                         object->publicArea.nameAlg, (TPM2B_SEED *) &data,
    112                         &in->symmetricAlg, &in->encryptionKeyIn,
    113                         &out->duplicate);
    114 
    115    out->encryptionKeyOut = in->encryptionKeyIn;
    116 
    117    return TPM_RC_SUCCESS;
    118 }
    119