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// 27TPM_RC 28TPM2_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