/// <summary> /// First determine whether parm enc/decryption is in effect for this command. If not /// return an unmodified buffer. If so then do the parm encryption. /// </summary> /// <param name="parms"></param> /// <param name="commandInfo"></param> /// <param name="offset"></param> /// <param name="inOrOut"></param> /// <returns></returns> private byte[] DoParmEncryption(byte[] parms, CommandInfo commandInfo, int offset, Direction inOrOut) { if (OuterCommand != TpmCc.None) return parms; AuthSession encSess = null; ParmCryptInfo encFlag2, encFlag4; if (inOrOut == Direction.Command) { encSess = DecSession; encFlag2 = ParmCryptInfo.EncIn2; encFlag4 = ParmCryptInfo.EncIn4; } else { encSess = EncSession; encFlag2 = ParmCryptInfo.DecOut2; encFlag4 = ParmCryptInfo.DecOut4; } // See if encryption/decryption is needed in whatever direction we are currently going ... if (encSess == null) { return parms; } if ((commandInfo.TheParmCryptInfo & (encFlag2 | encFlag4)) == 0) { if (!_Behavior.Passthrough) { throw new Exception(string.Format("Command {0} cannot use {1} session", commandInfo.CommandCode, inOrOut == Direction.Command ? "decryption" : "encryption")); } return parms; } // ... and get the length of the size counter prepending the XCrypted parameter. int countSize = commandInfo.TheParmCryptInfo.HasFlag(encFlag2) ? 2 : 4; // Now get the encrypted data (first parm) pos and length ... // We are interpreting the byte-stream starting at startPos as a length (2 or 4 byte) // prepended buffer byte[] lenX = Globs.CopyData(parms, offset, countSize); uint len = Globs.NetToHostVar(lenX); byte[] firstParm = Globs.CopyData(parms, offset + countSize, (int)len); byte[] encFirstParm = encSess.ParmEncrypt(firstParm, inOrOut); for (int j = 0; j < len; j++) { parms[offset + countSize + j] = encFirstParm[j]; } return parms; } // DoParmEncryption()
/// <summary> /// Updates TBS context database for commands that either fill or empty slots. /// </summary> /// <param name="caller"></param> /// <param name="command"></param> /// <param name="responseHandles"></param> /// <param name="inputObjects"></param> private void ProcessUpdatedTpmState(TbsContext caller, CommandInfo command, TpmHandle[] responseHandles, ObjectContext[] inputObjects) { switch (command.CommandCode) { // Commands that fill a slot (apart from contextLoad, which is more complex) case TpmCc.Load: case TpmCc.LoadExternal: case TpmCc.CreatePrimary: case TpmCc.HmacStart: case TpmCc.HashSequenceStart: case TpmCc.StartAuthSession: var t = new TpmHandle(responseHandles[0].handle); // ReSharper disable once UnusedVariable ObjectContext context2 = ContextManager.CreateObjectContext(caller, t); break; case TpmCc.ContextLoad: case TpmCc.ContextSave: throw new Exception("ProcessUpdatedTpmState: Should not be here"); case TpmCc.FlushContext: case TpmCc.SequenceComplete: ContextManager.Remove(inputObjects[0]); break; case TpmCc.EventSequenceComplete: ContextManager.Remove(inputObjects[1]); break; } }
private void PrepareRequestSessions(CommandInfo commandInfo, TpmHandle[] inHandles) { if (OuterCommand != TpmCc.None) { // Nested commands must not use sessions return; } Debug.Assert(commandInfo.AuthHandleCountIn <= inHandles.Length); // Does the command require authorization and not all sessions are provided? if (!_Behavior.Strict && commandInfo.AuthHandleCountIn > Sessions.Length) { // Allocate missing sessions if (Sessions.Length == 0) { Sessions = new SessionBase[commandInfo.AuthHandleCountIn]; } else { SessionBase[] explicitSessions = Sessions; Sessions = new SessionBase[commandInfo.AuthHandleCountIn]; explicitSessions.CopyTo(Sessions, 0); } } if (Sessions.Length == 0) { return; } for (int i = 0; i < Sessions.Length; ++i) { SessionBase s = Sessions[i]; // Is authorization for this handle explicitly suppressed? if (s == SessionBase.None) continue; TpmHandle authHandle = null; if (i < commandInfo.AuthHandleCountIn) { authHandle = inHandles[i]; switch (authHandle.handle) { case (uint)TpmRh.Owner: authHandle.Auth = OwnerAuth; break; case (uint)TpmRh.Endorsement: authHandle.Auth = EndorsementAuth; break; case (uint)TpmRh.Platform: authHandle.Auth = PlatformAuth; break; case (uint)TpmRh.Lockout: authHandle.Auth = LockoutAuth; break; default: if (authHandle.GetType() == Ht.Pcr && PcrHandles != null) { int pcrId = (int)authHandle.GetOffset(); Debug.Assert(pcrId < PcrHandles.Length); if (PcrHandles[pcrId] != null) { authHandle.Auth = PcrHandles[pcrId].Auth; } } break; } } if (SessionBase.IsPlaceholder(s)) { // Create missing session if (s == SessionBase.Hmac || s == SessionBase.Default && _GetUnderlyingDevice().NeedsHMAC) { s = Sessions[i] = CancelSafeStartAuthSession(TpmSe.Hmac, TpmAlgId.Sha256); // Stash away session object to flush it from TPM after the command completion TempSessions.Add(Sessions[i]); } else { s = Sessions[i] = new Pwap(authHandle.Auth); } } if (s.Handle != TpmRh.TpmRsPw && !_InitializeSession(s as AuthSession)) { // There are no session parameters associated with the session // handle (e.g., when the session was created by other Tpm2 object). throw new Exception("Wrong session handle"); } s.AuthHandle = authHandle; } foreach (TpmHandle h in inHandles) { if (h.Name == null) { byte[] name = null; // Use try-catch to intercept possible TpmRc.Handle error. try { switch (h.GetType()) { case Ht.Transient: case Ht.Persistent: { byte[] qualName = null; ReadPublic(h, out name, out qualName); break; } case Ht.NvIndex: { NvPublic pub = NvReadPublic(h, out name); if (!pub.attributes.HasFlag(NvAttr.Written) || (pub.attributes & (NvAttr.ClearStclear | NvAttr.Orderly)) != 0) { TempNames.Add(h); } break; } } } catch (TpmException) { // Failed to read public part of the object. Leave its name empty. } h.Name = name; } } // Roll the nonces. RollNonces(); // Determine if parameter encryption/decryption is necessary. PrepareParmEncryptionSessions(); }