blob: 2ed53ccb61a958c189a9faa50ff54109a6472428 [file] [log] [blame]
/* Microsoft Reference Implementation for TPM 2.0
*
* The copyright in this software is being made available under the BSD License,
* included below. This software may be subject to other third party and
* contributor rights, including patent rights, and no such rights are granted
* under this license.
*
* Copyright (c) Microsoft Corporation
*
* All rights reserved.
*
* BSD License
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS""
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "Tpm.h"
#include "Import_fp.h"
#if CC_Import // Conditional expansion of this file
#include "Object_spt_fp.h"
/*(See part 3 specification)
// This command allows an asymmetrically encrypted blob, containing a duplicated
// object to be re-encrypted using the group symmetric key associated with the
// parent.
*/
// Return Type: TPM_RC
// TPM_RC_ATTRIBUTES 'FixedTPM' and 'fixedParent' of 'objectPublic' are not
// both CLEAR; or 'inSymSeed' is nonempty and
// 'parentHandle' does not reference a decryption key; or
// 'objectPublic' and 'parentHandle' have incompatible
// or inconsistent attributes; or
// encrytpedDuplication is SET in 'objectPublic' but the
// inner or outer wrapper is missing.
// Note that if the TPM provides parameter values, the
// parameter number will indicate 'symmetricKey' (missing
// inner wrapper) or 'inSymSeed' (missing outer wrapper)
// TPM_RC_BINDING 'duplicate' and 'objectPublic' are not
// cryptographically bound
// TPM_RC_ECC_POINT 'inSymSeed' is nonempty and ECC point in 'inSymSeed'
// is not on the curve
// TPM_RC_HASH 'objectPublic' does not have a valid nameAlg
// TPM_RC_INSUFFICIENT 'inSymSeed' is nonempty and failed to retrieve ECC
// point from the secret; or unmarshaling sensitive value
// from 'duplicate' failed the result of 'inSymSeed'
// decryption
// TPM_RC_INTEGRITY 'duplicate' integrity is broken
// TPM_RC_KDF 'objectPublic' representing decrypting keyed hash
// object specifies invalid KDF
// TPM_RC_KEY inconsistent parameters of 'objectPublic'; or
// 'inSymSeed' is nonempty and 'parentHandle' does not
// reference a key of supported type; or
// invalid key size in 'objectPublic' representing an
// asymmetric key
// TPM_RC_NO_RESULT 'inSymSeed' is nonempty and multiplication resulted in
// ECC point at infinity
// TPM_RC_OBJECT_MEMORY no available object slot
// TPM_RC_SCHEME inconsistent attributes 'decrypt', 'sign',
// 'restricted' and key's scheme ID in 'objectPublic';
// or hash algorithm is inconsistent with the scheme ID
// for keyed hash object
// TPM_RC_SIZE 'authPolicy' size does not match digest size of the
// name algorithm in 'objectPublic'; or
// 'symmetricAlg' and 'encryptionKey' have different
// sizes; or
// 'inSymSeed' is nonempty and it size is not
// consistent with the type of 'parentHandle'; or
// unmarshaling sensitive value from 'duplicate' failed
// TPM_RC_SYMMETRIC 'objectPublic' is either a storage key with no
// symmetric algorithm or a non-storage key with
// symmetric algorithm different from TPM_ALG_NULL
// TPM_RC_TYPE unsupported type of 'objectPublic'; or
// 'parentHandle' is not a storage key; or
// only the public portion of 'parentHandle' is loaded;
// or 'objectPublic' and 'duplicate' are of different
// types
// TPM_RC_VALUE nonempty 'inSymSeed' and its numeric value is
// greater than the modulus of the key referenced by
// 'parentHandle' or 'inSymSeed' is larger than the
// size of the digest produced by the name algorithm of
// the symmetric key referenced by 'parentHandle'
TPM_RC
TPM2_Import(
Import_In *in, // IN: input parameter list
Import_Out *out // OUT: output parameter list
)
{
TPM_RC result = TPM_RC_SUCCESS;
OBJECT *parentObject;
TPM2B_DATA data; // symmetric key
TPMT_SENSITIVE sensitive;
TPM2B_NAME name;
TPMA_OBJECT attributes;
UINT16 innerKeySize = 0; // encrypt key size for inner
// wrapper
// Input Validation
// to save typing
attributes = in->objectPublic.publicArea.objectAttributes;
// FixedTPM and fixedParent must be CLEAR
if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, fixedTPM)
|| IS_ATTRIBUTE(attributes, TPMA_OBJECT, fixedParent))
return TPM_RCS_ATTRIBUTES + RC_Import_objectPublic;
// Get parent pointer
parentObject = HandleToObject(in->parentHandle);
if(!ObjectIsParent(parentObject))
return TPM_RCS_TYPE + RC_Import_parentHandle;
if(in->symmetricAlg.algorithm != TPM_ALG_NULL)
{
// Get inner wrap key size
innerKeySize = in->symmetricAlg.keyBits.sym;
// Input symmetric key must match the size of algorithm.
if(in->encryptionKey.t.size != (innerKeySize + 7) / 8)
return TPM_RCS_SIZE + RC_Import_encryptionKey;
}
else
{
// If input symmetric algorithm is NULL, input symmetric key size must
// be 0 as well
if(in->encryptionKey.t.size != 0)
return TPM_RCS_SIZE + RC_Import_encryptionKey;
// If encryptedDuplication is SET, then the object must have an inner
// wrapper
if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, encryptedDuplication))
return TPM_RCS_ATTRIBUTES + RC_Import_encryptionKey;
}
// See if there is an outer wrapper
if(in->inSymSeed.t.size != 0)
{
// in->inParentHandle is a parent, but in order to decrypt an outer wrapper,
// it must be able to do key exchange and a symmetric key can't do that.
if(parentObject->publicArea.type == TPM_ALG_SYMCIPHER)
return TPM_RCS_TYPE + RC_Import_parentHandle;
// Decrypt input secret data via asymmetric decryption. TPM_RC_ATTRIBUTES,
// TPM_RC_ECC_POINT, TPM_RC_INSUFFICIENT, TPM_RC_KEY, TPM_RC_NO_RESULT,
// TPM_RC_SIZE, TPM_RC_VALUE may be returned at this point
result = CryptSecretDecrypt(parentObject, NULL, DUPLICATE_STRING,
&in->inSymSeed, &data);
pAssert(result != TPM_RC_BINDING);
if(result != TPM_RC_SUCCESS)
return RcSafeAddToResult(result, RC_Import_inSymSeed);
}
else
{
// If encrytpedDuplication is set, then the object must have an outer
// wrapper
if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, encryptedDuplication))
return TPM_RCS_ATTRIBUTES + RC_Import_inSymSeed;
data.t.size = 0;
}
// Compute name of object
PublicMarshalAndComputeName(&(in->objectPublic.publicArea), &name);
if(name.t.size == 0)
return TPM_RCS_HASH + RC_Import_objectPublic;
// Retrieve sensitive from private.
// TPM_RC_INSUFFICIENT, TPM_RC_INTEGRITY, TPM_RC_SIZE may be returned here.
result = DuplicateToSensitive(&in->duplicate.b, &name.b, parentObject,
in->objectPublic.publicArea.nameAlg,
&data.b, &in->symmetricAlg,
&in->encryptionKey.b, &sensitive);
if(result != TPM_RC_SUCCESS)
return RcSafeAddToResult(result, RC_Import_duplicate);
// If the parent of this object has fixedTPM SET, then validate this
// object as if it were being loaded so that validation can be skipped
// when it is actually loaded.
if(IS_ATTRIBUTE(parentObject->publicArea.objectAttributes, TPMA_OBJECT, fixedTPM))
{
result = ObjectLoad(NULL, NULL, &in->objectPublic.publicArea,
&sensitive, RC_Import_objectPublic, RC_Import_duplicate,
NULL);
}
// Command output
if(result == TPM_RC_SUCCESS)
{
// Prepare output private data from sensitive
SensitiveToPrivate(&sensitive, &name, parentObject,
in->objectPublic.publicArea.nameAlg,
&out->outPrivate);
}
return result;
}
#endif // CC_Import