Vadim Bendebury | 5679752 | 2015-05-20 10:32:25 -0700 | [diff] [blame] | 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 |
Vadim Bendebury | 30f6dee | 2015-05-29 22:51:10 -0700 | [diff] [blame] | 92 | out->outSymSeed.t.size = sizeof(out->outSymSeed.t.buffer); |
Vadim Bendebury | 5679752 | 2015-05-20 10:32:25 -0700 | [diff] [blame] | 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 | } |