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 "Import_fp.h"
     10 #include "Object_spt_fp.h"
     11 //
     12 //
     13 //    Error Returns                     Meaning
     14 //
     15 //    TPM_RC_ASYMMETRIC                 non-duplicable storage key represented by objectPublic and its
     16 //                                      parent referenced by parentHandle have different public parameters
     17 //    TPM_RC_ATTRIBUTES                 attributes FixedTPM and fixedParent of objectPublic are not both
     18 //                                      CLEAR; or inSymSeed is nonempty and parentHandle does not
     19 //                                      reference a decryption key; or objectPublic and parentHandle have
     20 //                                      incompatible or inconsistent attributes; or encrytpedDuplication is
     21 //                                      SET in objectPublic but the inner or outer wrapper is missing.
     22 //
     23 //    NOTE:           if the TPM provides parameter values, the parameter number will indicate symmetricKey (missing
     24 //                    inner wrapper) or inSymSeed (missing outer wrapper).
     25 //
     26 //
     27 //    TPM_RC_BINDING                    duplicate and objectPublic are not cryptographically
     28 //                                      bound
     29 //
     30 //    TPM_RC_ECC_POINT                  inSymSeed is nonempty and ECC point in inSymSeed is not on the
     31 //                                      curve
     32 //    TPM_RC_HASH                       non-duplicable storage key represented by objectPublic and its
     33 //                                      parent referenced by parentHandle have different name algorithm
     34 //    TPM_RC_INSUFFICIENT               inSymSeed is nonempty and failed to retrieve ECC point from the
     35 //                                      secret; or unmarshaling sensitive value from duplicate failed the
     36 //                                      result of inSymSeed decryption
     37 //    TPM_RC_INTEGRITY                  duplicate integrity is broken
     38 //    TPM_RC_KDF                        objectPublic representing decrypting keyed hash object specifies
     39 //                                      invalid KDF
     40 //    TPM_RC_KEY                        inconsistent parameters of objectPublic; or inSymSeed is nonempty
     41 //                                      and parentHandle does not reference a key of supported type; or
     42 //                                      invalid key size in objectPublic representing an asymmetric key
     43 //    TPM_RC_NO_RESULT                  inSymSeed is nonempty and multiplication resulted in ECC point at
     44 //                                      infinity
     45 //    TPM_RC_OBJECT_MEMORY              no available object slot
     46 //    TPM_RC_SCHEME                     inconsistent attributes decrypt, sign, restricted and key's scheme ID
     47 //                                      in objectPublic; or hash algorithm is inconsistent with the scheme ID
     48 //                                      for keyed hash object
     49 //    TPM_RC_SIZE                       authPolicy size does not match digest size of the name algorithm in
     50 //                                      objectPublic; or symmetricAlg and encryptionKey have different
     51 //                                      sizes; or inSymSeed is nonempty and it size is not consistent with the
     52 //                                      type of parentHandle; or unmarshaling sensitive value from duplicate
     53 //                                      failed
     54 //    TPM_RC_SYMMETRIC                  objectPublic is either a storage key with no symmetric algorithm or a
     55 //                                      non-storage key with symmetric algorithm different from
     56 //                                      TPM_ALG_NULL
     57 //    TPM_RC_TYPE                       unsupported type of objectPublic; or non-duplicable storage key
     58 //                                      represented by objectPublic and its parent referenced by
     59 //                                      parentHandle are of different types; or parentHandle is not a storage
     60 //                                      key; or only the public portion of parentHandle is loaded; or
     61 //                                  objectPublic and duplicate are of different types
     62 //     TPM_RC_VALUE                 nonempty inSymSeed and its numeric value is greater than the
     63 //                                  modulus of the key referenced by parentHandle or inSymSeed is
     64 //                                  larger than the size of the digest produced by the name algorithm of
     65 //                                  the symmetric key referenced by parentHandle
     66 //
     67 TPM_RC
     68 TPM2_Import(
     69    Import_In         *in,            // IN: input parameter list
     70    Import_Out        *out            // OUT: output parameter list
     71    )
     72 {
     73 
     74    TPM_RC                   result = TPM_RC_SUCCESS;
     75    OBJECT                   *parentObject;
     76    TPM2B_DATA               data;                   // symmetric key
     77    TPMT_SENSITIVE           sensitive;
     78    TPM2B_NAME               name;
     79 
     80    UINT16                   innerKeySize = 0;             // encrypt key size for inner
     81                                                           // wrapper
     82 
     83 // Input Validation
     84 
     85    // FixedTPM and fixedParent must be CLEAR
     86    if(   in->objectPublic.t.publicArea.objectAttributes.fixedTPM == SET
     87       || in->objectPublic.t.publicArea.objectAttributes.fixedParent == SET)
     88        return TPM_RC_ATTRIBUTES + RC_Import_objectPublic;
     89 
     90    // Get parent pointer
     91    parentObject = ObjectGet(in->parentHandle);
     92 
     93    if(!AreAttributesForParent(parentObject))
     94        return TPM_RC_TYPE + RC_Import_parentHandle;
     95 
     96    if(in->symmetricAlg.algorithm != TPM_ALG_NULL)
     97    {
     98        // Get inner wrap key size
     99        innerKeySize = in->symmetricAlg.keyBits.sym;
    100        // Input symmetric key must match the size of algorithm.
    101        if(in->encryptionKey.t.size != (innerKeySize + 7) / 8)
    102            return TPM_RC_SIZE + RC_Import_encryptionKey;
    103    }
    104    else
    105    {
    106        // If input symmetric algorithm is NULL, input symmetric key size must
    107        // be 0 as well
    108        if(in->encryptionKey.t.size != 0)
    109            return TPM_RC_SIZE + RC_Import_encryptionKey;
    110        // If encryptedDuplication is SET, then the object must have an inner
    111        // wrapper
    112        if(in->objectPublic.t.publicArea.objectAttributes.encryptedDuplication)
    113            return TPM_RC_ATTRIBUTES + RC_Import_encryptionKey;
    114    }
    115 
    116    // See if there is an outer wrapper
    117    if(in->inSymSeed.t.size != 0)
    118    {
    119        // Decrypt input secret data via asymmetric decryption. TPM_RC_ATTRIBUTES,
    120        // TPM_RC_ECC_POINT, TPM_RC_INSUFFICIENT, TPM_RC_KEY, TPM_RC_NO_RESULT,
    121        // TPM_RC_SIZE, TPM_RC_VALUE may be returned at this point
    122        result = CryptSecretDecrypt(in->parentHandle, NULL, "DUPLICATE",
    123                                    &in->inSymSeed, &data);
    124        pAssert(result != TPM_RC_BINDING);
    125 //
    126        if(result != TPM_RC_SUCCESS)
    127            return RcSafeAddToResult(result, RC_Import_inSymSeed);
    128    }
    129    else
    130    {
    131        // If encrytpedDuplication is set, then the object must have an outer
    132        // wrapper
    133        if(in->objectPublic.t.publicArea.objectAttributes.encryptedDuplication)
    134            return TPM_RC_ATTRIBUTES + RC_Import_inSymSeed;
    135        data.t.size = 0;
    136    }
    137 
    138    // Compute name of object
    139    ObjectComputeName(&(in->objectPublic.t.publicArea), &name);
    140 
    141    // Retrieve sensitive from private.
    142    // TPM_RC_INSUFFICIENT, TPM_RC_INTEGRITY, TPM_RC_SIZE may be returned here.
    143    result = DuplicateToSensitive(&in->duplicate, &name, in->parentHandle,
    144                                  in->objectPublic.t.publicArea.nameAlg,
    145                                  (TPM2B_SEED *) &data, &in->symmetricAlg,
    146                                  &in->encryptionKey, &sensitive);
    147    if(result != TPM_RC_SUCCESS)
    148        return RcSafeAddToResult(result, RC_Import_duplicate);
    149 
    150    // If the parent of this object has fixedTPM SET, then fully validate this
    151    // object so that validation can be skipped when it is loaded
    152    if(parentObject->publicArea.objectAttributes.fixedTPM == SET)
    153    {
    154        TPM_HANDLE       objectHandle;
    155 
    156        // Perform self check on input public area. A TPM_RC_SIZE, TPM_RC_SCHEME,
    157        // TPM_RC_VALUE, TPM_RC_SYMMETRIC, TPM_RC_TYPE, TPM_RC_HASH,
    158        // TPM_RC_ASYMMETRIC, TPM_RC_ATTRIBUTES or TPM_RC_KDF error may be returned
    159        // at this point
    160        result = PublicAttributesValidation(TRUE, in->parentHandle,
    161                                            &in->objectPublic.t.publicArea);
    162        if(result != TPM_RC_SUCCESS)
    163            return RcSafeAddToResult(result, RC_Import_objectPublic);
    164 
    165        // Create internal object. A TPM_RC_KEY_SIZE, TPM_RC_KEY or
    166        // TPM_RC_OBJECT_MEMORY error may be returned at this point
    167        result = ObjectLoad(TPM_RH_NULL, &in->objectPublic.t.publicArea,
    168                            &sensitive, NULL, in->parentHandle, FALSE,
    169                            &objectHandle);
    170        if(result != TPM_RC_SUCCESS)
    171            return result;
    172 
    173        // Don't need the object, just needed the checks to be performed so
    174        // flush the object
    175        ObjectFlush(objectHandle);
    176    }
    177 
    178 // Command output
    179 
    180    // Prepare output private data from sensitive
    181    SensitiveToPrivate(&sensitive, &name, in->parentHandle,
    182                       in->objectPublic.t.publicArea.nameAlg,
    183                       &out->outPrivate);
    184 
    185    return TPM_RC_SUCCESS;
    186 }
    187