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