1 // 2 // Copyright (c) 2010-2023 Antmicro 3 // 4 // This file is licensed under the MIT License. 5 // Full license text is available in 'licenses/MIT.txt'. 6 // 7 using System; 8 using System.Linq; 9 using System.Collections.Generic; 10 using Antmicro.Renode.Core; 11 using Antmicro.Renode.Core.Structure.Registers; 12 using Antmicro.Renode.Exceptions; 13 using Antmicro.Renode.Peripherals.MemoryControllers; 14 using Antmicro.Renode.Logging; 15 using Antmicro.Renode.Utilities; 16 using Org.BouncyCastle.Crypto.Macs; 17 using Org.BouncyCastle.Crypto.Parameters; 18 19 namespace Antmicro.Renode.Peripherals.Miscellaneous 20 { 21 public class OpenTitan_KeyManager : BasicDoubleWordPeripheral, IKnownSize 22 { OpenTitan_KeyManager(IMachine machine, OpenTitan_ROMController romController, string deviceId, string lifeCycleDiversificationConstant, string creatorKey, string ownerKey, string rootKey, string softOutputSeed, string hardOutputSeed, string destinationNoneSeed, string destinationAesSeed, string destinationOtbnSeed, string destinationKmacSeed, string revisionSeed, string creatorIdentitySeed, string ownerIntermediateIdentitySeed, string ownerIdentitySeed, bool kmacEnableMasking = true, int randomSeed = 0, ISideloadableKey kmac = null, ISideloadableKey aes = null, ISideloadableKey otbn = null)23 public OpenTitan_KeyManager(IMachine machine, OpenTitan_ROMController romController, 24 string deviceId, string lifeCycleDiversificationConstant, string creatorKey, string ownerKey, string rootKey, 25 string softOutputSeed, string hardOutputSeed, string destinationNoneSeed, string destinationAesSeed, string destinationOtbnSeed, string destinationKmacSeed, 26 string revisionSeed, string creatorIdentitySeed, string ownerIntermediateIdentitySeed, string ownerIdentitySeed, 27 bool kmacEnableMasking = true, int randomSeed = 0, ISideloadableKey kmac = null, ISideloadableKey aes = null, ISideloadableKey otbn = null) : base(machine) 28 { 29 this.romController = romController; 30 destinations = new Dictionary<Destination, ISideloadableKey>(); 31 if(kmac != null) 32 { 33 destinations.Add(Destination.KMAC, kmac); 34 } 35 if(aes != null) 36 { 37 destinations.Add(Destination.AES, aes); 38 } 39 if(otbn != null) 40 { 41 destinations.Add(Destination.OTBN, otbn); 42 } 43 OperationDoneIRQ = new GPIO(); 44 FatalAlert = new GPIO(); 45 RecoverableAlert = new GPIO(); 46 47 random = new Random(randomSeed); 48 sealingSoftwareBinding = new byte[MultiRegistersCount * 4]; 49 attestationSoftwareBinding = new byte[MultiRegistersCount * 4]; 50 salt = new byte[MultiRegistersCount * 4]; 51 softwareShareOutput = new byte[MultiRegistersCount * 4 * NumberOfSoftwareShareOutputs]; 52 53 this.deviceId = ConstructorParseHexstringArgument("deviceId", deviceId, DeviceIdExpectedLength); // OTP_HW_CFG_DATA_DEFAULT.device_id 54 this.lifeCycleDiversificationConstant = ConstructorParseHexstringArgument("lifeCycleDiversificationConstant", lifeCycleDiversificationConstant, LifeCycleDiversificationConstantLength); // RndCnstLcKeymgrDiv 55 this.creatorKey = ConstructorParseHexstringArgument("creatorKey", creatorKey, CreatorKeyExpectedLength); // KEYMGR_FLASH_DEFAULT.seeds[CreatorSeedIdx] 56 this.ownerKey = ConstructorParseHexstringArgument("ownerKey", ownerKey, OwnerKeyExpectedLength); // KEYMGR_FLASH_DEFAULT.seeds[OwnerSeedIdx] 57 var rootKeyTemp = ConstructorParseHexstringArgument("rootKey", rootKey, RootKeyExpectedLength); // OTP_KEYMGR_KEY_DEFAULT 58 // If `KmacEnMasking` is set then key is composed of both shares, 59 // otherwise the first key share is a xor of shares and the second key share is zero 60 if(kmacEnableMasking) 61 { 62 this.rootKey = rootKeyTemp; 63 } 64 else 65 { 66 this.rootKey = rootKeyTemp 67 .Take(rootKeyTemp.Length / 2) 68 .Zip(rootKeyTemp.Skip(rootKeyTemp.Length / 2), (b0, b1) => (byte)(b0 ^ b1)) 69 .Concat(Enumerable.Repeat((byte)0, rootKeyTemp.Length / 2)) 70 .ToArray(); 71 } 72 this.softOutputSeed = ConstructorParseHexstringArgument("softOutputSeed", softOutputSeed, SeedExpectedLength); // RndCnstSoftOutputSeed 73 this.hardOutputSeed = ConstructorParseHexstringArgument("hardOutputSeed", hardOutputSeed, SeedExpectedLength); // RndCnstHardOutputSeed 74 this.destinationNoneSeed = ConstructorParseHexstringArgument("destinationNoneSeed", destinationNoneSeed, SeedExpectedLength); // RndCnstAesSeed 75 this.destinationAesSeed = ConstructorParseHexstringArgument("destinationAesSeed", destinationAesSeed, SeedExpectedLength); // RndCnstKmacSeed 76 this.destinationOtbnSeed = ConstructorParseHexstringArgument("destinationOtbnSeed", destinationOtbnSeed, SeedExpectedLength); // RndCnstOtbnSeed 77 this.destinationKmacSeed = ConstructorParseHexstringArgument("destinationKmacSeed", destinationKmacSeed, SeedExpectedLength); // RndCnstNoneSeed 78 this.revisionSeed = ConstructorParseHexstringArgument("revisionSeed", revisionSeed, SeedExpectedLength); // RndCnstRevisionSeed 79 this.creatorIdentitySeed = ConstructorParseHexstringArgument("creatorIdentitySeed", creatorIdentitySeed, SeedExpectedLength); // RndCnstCreatorIdentitySeed 80 this.ownerIntermediateIdentitySeed = ConstructorParseHexstringArgument("ownerIntermediateIdentitySeed", ownerIntermediateIdentitySeed, SeedExpectedLength); // RndCnstOwnerIntIdentitySeed 81 this.ownerIdentitySeed = ConstructorParseHexstringArgument("ownerIdentitySeed", ownerIdentitySeed, SeedExpectedLength); // RndCnstOwnerIdentitySeed 82 83 DefineRegisters(); 84 Reset(); 85 } 86 Reset()87 public override void Reset() 88 { 89 base.Reset(); 90 91 FatalAlert.Unset(); 92 RecoverableAlert.Unset(); 93 Array.Clear(sealingSoftwareBinding, 0, sealingSoftwareBinding.Length); 94 Array.Clear(attestationSoftwareBinding, 0, attestationSoftwareBinding.Length); 95 Array.Clear(salt, 0, salt.Length); 96 Array.Clear(softwareShareOutput, 0, softwareShareOutput.Length); 97 } 98 99 public long Size => 0x1000; 100 101 public GPIO OperationDoneIRQ { get; } 102 103 public GPIO FatalAlert { get; } 104 public GPIO RecoverableAlert { get; } 105 ConstructorParseHexstringArgument(string fieldName, string value, int expectedLength)106 static private byte[] ConstructorParseHexstringArgument(string fieldName, string value, int expectedLength) 107 { 108 byte[] field; 109 var lengthInBytes = value.Length / 2; 110 if(lengthInBytes != expectedLength) 111 { 112 throw new ConstructionException($"Expected `{fieldName}`'s size is {expectedLength} bytes, got {lengthInBytes}"); 113 } 114 try 115 { 116 field = Misc.HexStringToByteArray(value); 117 } 118 catch 119 { 120 throw new ConstructionException($"Could not parse `{fieldName}`: Expected hexstring, got: \"{value}\""); 121 } 122 return field; 123 } 124 125 private static WorkingState[] IllegalForAdvance = { WorkingState.Invalid, WorkingState.Disabled }; 126 private static WorkingState[] IllegalForDisable = { WorkingState.Invalid, WorkingState.Disabled }; 127 private static WorkingState[] IllegalForGenerate = { WorkingState.Invalid, WorkingState.Disabled, WorkingState.Init }; 128 RunCommand()129 private void RunCommand() 130 { 131 var command = operationMode.Value; 132 this.Log(LogLevel.Debug, "Received command: {0}", command); 133 if(state.Value == WorkingState.Reset && command != OperationMode.Advance) 134 { 135 // In the Reset state no other commands are allowed 136 this.Log(LogLevel.Warning, "Ignoring command {0} in the reset state", command); 137 return; 138 } 139 140 switch(command) 141 { 142 case OperationMode.Advance: 143 if(CheckLegality(IllegalForAdvance)) 144 { 145 AdvanceState(); 146 } 147 break; 148 case OperationMode.GenerateID: 149 if(CheckLegality(IllegalForGenerate)) 150 { 151 softwareShareOutput = CalculateKMAC(IdentitySeed, softwareShareOutput.Length); 152 } 153 break; 154 case OperationMode.GenerateHWOutput: 155 if(CheckLegality(IllegalForGenerate) && CheckKeyVersion()) 156 { 157 var data = BitConverter.GetBytes((uint)keyVersion.Value) 158 .Concat(salt) 159 .Concat(DestinationCipherSeed) 160 .Concat(hardOutputSeed); 161 var length = destination.Value == Destination.OTBN ? SideloadKeyLengthOTBN : SideloadKeyLength; 162 var output = CalculateKMAC(data, length); 163 if(destinations.TryGetValue(destination.Value, out var dest)) 164 { 165 dest.SideloadKey = output; 166 } 167 else 168 { 169 this.Log(LogLevel.Warning, "Sideload key for {0} is not possible, peripheral is not specified", destination.Value); 170 } 171 } 172 break; 173 case OperationMode.GenerateSWOutput: 174 if(CheckLegality(IllegalForGenerate) && CheckKeyVersion()) 175 { 176 var data = BitConverter.GetBytes((uint)keyVersion.Value) 177 .Concat(salt) 178 .Concat(DestinationCipherSeed) 179 .Concat(softOutputSeed); 180 softwareShareOutput = CalculateKMAC(data, softwareShareOutput.Length); 181 } 182 break; 183 case OperationMode.Disable: 184 if(CheckLegality(IllegalForDisable)) 185 { 186 state.Value = WorkingState.Disabled; 187 } 188 break; 189 default: 190 this.Log(LogLevel.Warning, "Unsupported {0} operation", state.Value); 191 break; 192 } 193 } 194 CheckLegality(WorkingState[] illegalStates)195 private bool CheckLegality(WorkingState[] illegalStates) 196 { 197 if(illegalStates.Contains(state.Value)) 198 { 199 HandleIllegalOperation(); 200 return false; 201 } 202 return true; 203 } 204 CheckKeyVersion()205 private bool CheckKeyVersion() 206 { 207 if(keyVersion.Value > MaxKeyVersion) 208 { 209 invalidKmacInputFlag.Value = true; 210 return false; 211 } 212 return true; 213 } 214 Invalidate()215 private void Invalidate() 216 { 217 var key = new byte[SideloadKeyLength]; 218 foreach(var dest in destinations.Values) 219 { 220 random.NextBytes(key); 221 dest.SideloadKey = key; 222 } 223 random.NextBytes(softwareShareOutput); 224 } 225 HandleIllegalOperation()226 private void HandleIllegalOperation() 227 { 228 status.Value = Status.DoneError; 229 invalidOperationFlag.Value = true; 230 } 231 AdvanceState()232 private void AdvanceState() 233 { 234 IEnumerable<byte> data; 235 236 switch(state.Value) 237 { 238 case WorkingState.Reset: 239 state.Value++; 240 internalKey = rootKey; 241 break; 242 case WorkingState.Init: 243 state.Value++; 244 data = SoftwareBinding 245 .Concat(revisionSeed) 246 .Concat(deviceId) 247 .Concat(lifeCycleDiversificationConstant) 248 .Concat(romController.Digest) 249 .Concat(creatorKey); 250 creatorRootStateKey = CalculateKMAC(data, RootKeyExpectedLength); 251 internalKey = creatorRootStateKey; 252 break; 253 case WorkingState.CreatorRootKey: 254 state.Value++; 255 data = SoftwareBinding 256 .Concat(ownerKey); 257 ownerIntermediateStateKey = CalculateKMAC(data, RootKeyExpectedLength); 258 internalKey = ownerIntermediateStateKey; 259 break; 260 case WorkingState.OwnerIntermediateKey: 261 state.Value++; 262 data = SoftwareBinding; 263 ownerStateKey = CalculateKMAC(data, RootKeyExpectedLength); 264 internalKey = ownerStateKey; 265 break; 266 case WorkingState.OwnerKey: 267 state.Value++; 268 break; 269 case WorkingState.Disabled: 270 Invalidate(); 271 break; 272 case WorkingState.Invalid: 273 // This is a proper state, no additonal logging is required 274 break; 275 default: 276 this.Log(LogLevel.Warning, "Reached unexpected state: {0}", state.Value); 277 break; 278 } 279 280 this.Log(LogLevel.Debug, "WorkingState advanced to '{0}'", state.Value); 281 status.Value = Status.Idle; 282 } 283 CalculateKMAC(IEnumerable<byte> data, int outputLength)284 public byte[] CalculateKMAC(IEnumerable<byte> data, int outputLength) 285 { 286 var mac = new KMac(KmacBitLength, null); 287 mac.Init(new KeyParameter(internalKey)); 288 var dataArray = data.ToArray(); 289 mac.BlockUpdate(dataArray, 0, dataArray.Length); 290 var output = new byte[outputLength]; 291 mac.DoFinal(output, 0, outputLength); 292 return output; 293 } 294 DefineRegisters()295 private void DefineRegisters() 296 { 297 Registers.InterruptState.Define(this) 298 .WithFlag(0, out interruptStatusOperationDone, FieldMode.Read | FieldMode.WriteOneToClear, name: "op_done") 299 .WithIgnoredBits(1, 31) 300 .WithWriteCallback((_, __) => UpdateInterrupts()); 301 302 Registers.InterruptEnable.Define(this) 303 .WithFlag(0, out interruptEnableOperationDone, name: "op_done") 304 .WithIgnoredBits(1, 31) 305 .WithWriteCallback((_, __) => UpdateInterrupts()); 306 307 Registers.InterruptTest.Define(this) 308 .WithFlag(0, FieldMode.Write, writeCallback: (_, val) => { interruptStatusOperationDone.Value |= val; }, name: "op_done") 309 .WithIgnoredBits(1, 31) 310 .WithWriteCallback((_, __) => UpdateInterrupts()); 311 312 Registers.AlertTest.Define(this) 313 .WithFlag(0, FieldMode.Write, writeCallback: (_, val) => { if(val) RecoverableAlert.Blink(); }, name: "recov_operation_err") // FieldMode.Write 314 .WithFlag(1, FieldMode.Write, writeCallback: (_, val) => { if(val) FatalAlert.Blink(); }, name: "fatal_fault_err") // FieldMode.Write 315 .WithIgnoredBits(2, 30); 316 317 Registers.ConfigurationWriteEnable.Define(this, 0x1) 318 .WithTaggedFlag("EN", 0) // FieldMode.Read 319 .WithIgnoredBits(1, 31); 320 321 Registers.OperationControls.Define(this) 322 .WithFlag(0, writeCallback: (_, val) => { if (val) RunCommand(); }, valueProviderCallback: _ => false, name: "START") 323 .WithReservedBits(1, 3) 324 .WithEnumField<DoubleWordRegister, OperationMode>(4, 3, out operationMode, name: "OPERATION") 325 .WithEnumField<DoubleWordRegister, CDISetting>(7, 1, out cdiSetting, name: "CDI_SEL") 326 .WithReservedBits(8, 4) 327 .WithEnumField<DoubleWordRegister, Destination>(12, 3, out destination, name: "DEST_SEL") 328 .WithIgnoredBits(15, 17) 329 .WithWriteCallback((_, __) => UpdateInterrupts()); 330 331 Registers.SideloadClear.Define(this) 332 .WithTag("VAL", 0, 3) 333 .WithIgnoredBits(3, 29); 334 335 Registers.ReseedIntervalWriteEnable.Define(this, 0x1) 336 .WithTaggedFlag("EN", 0) // FieldMode.Read | FieldMode.WriteZeroToClear 337 .WithReservedBits(1, 31); 338 339 Registers.ReseedInterval.Define(this, 0x100) 340 .WithValueField(0, 32, out entropyReseedInterval, name: "VAL"); 341 342 Registers.SoftwareBindingWriteEnable.Define(this, 0x1) 343 .WithTaggedFlag("EN", 0) // FieldMode.Read | FieldMode.WriteZeroToClear 344 .WithIgnoredBits(1, 31); 345 346 Registers.SealingSoftwareBinding0.DefineMany(this, MultiRegistersCount, (register, idx) => 347 { 348 register.WithValueField(0, 32, writeCallback: (_, val) => { sealingSoftwareBinding.SetBytesFromValue((uint)val, idx * 4); }, valueProviderCallback: _ => (uint)BitConverter.ToInt32(sealingSoftwareBinding, idx * 4), name: $"VAL_{idx}"); 349 }); 350 351 Registers.AttestationSoftwareBinding0.DefineMany(this, MultiRegistersCount, (register, idx) => 352 { 353 register.WithValueField(0, 32, writeCallback: (_, val) => { attestationSoftwareBinding.SetBytesFromValue((uint)val, idx * 4); }, valueProviderCallback: _ => (uint)BitConverter.ToInt32(attestationSoftwareBinding, idx * 4), name: $"VAL_{idx}"); 354 }); 355 356 Registers.Salt0.DefineMany(this, MultiRegistersCount, (register, idx) => 357 { 358 register.WithValueField(0, 32, writeCallback: (_, val) => { salt.SetBytesFromValue((uint)val, idx * 4); }, valueProviderCallback: _ => (uint)BitConverter.ToInt32(salt, idx * 4), name: $"VAL_{idx}"); 359 }); 360 361 Registers.KeyVersion.Define(this) 362 .WithValueField(0, 32, out keyVersion, name: "VAL"); 363 364 Registers.MaxCreatorKeyVersionWriteEnable.Define(this, 0x1) 365 .WithTaggedFlag("EN", 0) // FieldMode.Read | FieldMode.WriteZeroToClear 366 .WithIgnoredBits(1, 31); 367 368 Registers.MaxCreatorKeyVersion.Define(this) 369 .WithValueField(0, 32, out maxCreatorKeyVersion, name: "VAL"); 370 371 Registers.MaxOwnerIntermediateKeyVersionWriteEnable.Define(this, 0x1) 372 .WithTaggedFlag("EN", 0) // FieldMode.Read | FieldMode.WriteZeroToClear 373 .WithIgnoredBits(1, 31); 374 375 Registers.MaxOwnerIntermediateKeyVersion.Define(this) 376 .WithValueField(0, 32, out maxOwnerIntermediateKeyVersion, name: "VAL"); 377 378 Registers.MaxOwnerKeyVersionWriteEnable.Define(this, 0x1) 379 .WithTaggedFlag("EN", 0) // FieldMode.Read | FieldMode.WriteZeroToClear 380 .WithIgnoredBits(1, 31); 381 382 Registers.MaxOwnerKeyVersion.Define(this) 383 .WithValueField(0, 32, out maxOwnerKeyVersion, name: "VAL"); 384 385 for(var i = 0; i < NumberOfSoftwareShareOutputs; ++i) 386 { 387 var offset = Registers.SoftwareShare1Output0 - Registers.SoftwareShare0Output0; 388 (Registers.SoftwareShare0Output0 + offset * i).DefineMany(this, MultiRegistersCount, (register, idx) => 389 { 390 register.WithValueField(0, 32, FieldMode.ReadToClear, valueProviderCallback: _ => 391 { 392 var startIndex = i * MultiRegistersCount * 4 + idx * 4; 393 var value = (uint)BitConverter.ToInt32(softwareShareOutput, startIndex); 394 softwareShareOutput.SetBytesFromValue(0, startIndex); 395 return value; 396 }, name: $"VAL_{idx}"); 397 }); 398 } 399 400 Registers.WorkingState.Define(this) 401 .WithEnumField<DoubleWordRegister, WorkingState>(0, 3, out state, FieldMode.Read, name: "STATE") 402 .WithIgnoredBits(3, 29); 403 404 Registers.Status.Define(this) 405 .WithEnumField<DoubleWordRegister, Status>(0, 2, out status, FieldMode.Read | FieldMode.WriteOneToClear, name: "STATE") 406 .WithIgnoredBits(2, 30); 407 408 Registers.ErrorCode.Define(this) 409 .WithFlag(0, out invalidOperationFlag, FieldMode.Read | FieldMode.WriteOneToClear, name: "INVALID_OP") 410 .WithFlag(1, out invalidKmacInputFlag, FieldMode.Read | FieldMode.WriteOneToClear, name: "INVALID_KMAC_INPUT") 411 .WithTaggedFlag("INVALID_SHADOW_UPDATE", 2) // FieldMode.Read | FieldMode.WriteOneToClear 412 .WithIgnoredBits(3, 29); 413 414 Registers.FaultStatus.Define(this) 415 .WithTaggedFlag("CMDA", 0) // FieldMode.Read 416 .WithTaggedFlag("KMAC_FSM", 1) // FieldMode.Read 417 .WithTaggedFlag("KMAC_OPKMAC", 2) // FieldMode.Read 418 .WithTaggedFlag("KMAC_OUTKMAC", 3) // FieldMode.Read 419 .WithTaggedFlag("REGFILE_INTG", 4) // FieldMode.Read 420 .WithTaggedFlag("SHADOW", 5) // FieldMode.Read 421 .WithTaggedFlag("CTRL_FSM_INTG", 6) // FieldMode.Read 422 .WithTaggedFlag("CTRL_FSM_CNT", 7) // FieldMode.Read 423 .WithTaggedFlag("RESEED_CNT", 8) // FieldMode.Read 424 .WithTaggedFlag("SIDE_CTRL_FSM", 9) // FieldMode.Read 425 .WithReservedBits(10, 22); 426 } 427 UpdateInterrupts()428 private void UpdateInterrupts() 429 { 430 OperationDoneIRQ.Set(interruptStatusOperationDone.Value && interruptEnableOperationDone.Value); 431 } 432 433 private IEnumerable<byte> SoftwareBinding => cdiSetting.Value == CDISetting.Sealing ? sealingSoftwareBinding : attestationSoftwareBinding; 434 435 private IEnumerable<byte> DestinationCipherSeed 436 { 437 get 438 { 439 switch(destination.Value) 440 { 441 case Destination.None: 442 return destinationNoneSeed; 443 case Destination.AES: 444 return destinationAesSeed; 445 case Destination.KMAC: 446 return destinationKmacSeed; 447 case Destination.OTBN: 448 return destinationOtbnSeed; 449 default: 450 this.Log(LogLevel.Error, "Invalid state, destination's value is 0x{0:X}", destination.Value); 451 return Enumerable.Empty<byte>(); 452 } 453 } 454 } 455 456 private IEnumerable<byte> IdentitySeed 457 { 458 get 459 { 460 switch(state.Value) 461 { 462 case WorkingState.CreatorRootKey: 463 return creatorIdentitySeed; 464 case WorkingState.OwnerIntermediateKey: 465 return ownerIntermediateIdentitySeed; 466 case WorkingState.OwnerKey: 467 default: 468 this.Log(LogLevel.Error, "Invalid state for getting `IdentitySeed`, state's value is 0x{0:X}", state.Value); 469 return Enumerable.Empty<byte>(); 470 } 471 } 472 } 473 474 private uint MaxKeyVersion 475 { 476 get 477 { 478 switch(state.Value) 479 { 480 case WorkingState.CreatorRootKey: 481 return (uint)maxCreatorKeyVersion.Value; 482 case WorkingState.OwnerIntermediateKey: 483 return (uint)maxOwnerIntermediateKeyVersion.Value; 484 case WorkingState.OwnerKey: 485 return (uint)maxOwnerKeyVersion.Value; 486 default: 487 this.Log(LogLevel.Error, "Invalid state for getting `MaxKeyVersion`, state's value is 0x{0:X}", state.Value); 488 return 0; 489 } 490 } 491 } 492 493 private IFlagRegisterField interruptStatusOperationDone; 494 private IFlagRegisterField interruptEnableOperationDone; 495 private IEnumRegisterField<CDISetting> cdiSetting; 496 private IEnumRegisterField<Destination> destination; 497 private IEnumRegisterField<OperationMode> operationMode; 498 private IEnumRegisterField<Status> status; 499 private IEnumRegisterField<WorkingState> state; 500 private IFlagRegisterField invalidOperationFlag; 501 private IFlagRegisterField invalidKmacInputFlag; 502 private IValueRegisterField entropyReseedInterval; 503 private IValueRegisterField keyVersion; 504 private IValueRegisterField maxCreatorKeyVersion; 505 private IValueRegisterField maxOwnerIntermediateKeyVersion; 506 private IValueRegisterField maxOwnerKeyVersion; 507 private byte[] creatorRootStateKey; 508 private byte[] ownerIntermediateStateKey; 509 private byte[] ownerStateKey; 510 private byte[] softwareShareOutput; 511 private byte[] internalKey; 512 513 private readonly byte[] sealingSoftwareBinding; 514 private readonly byte[] attestationSoftwareBinding; 515 private readonly byte[] salt; 516 private readonly byte[] revisionSeed; 517 private readonly byte[] deviceId; 518 private readonly byte[] lifeCycleDiversificationConstant; 519 private readonly byte[] creatorKey; 520 private readonly byte[] ownerKey; 521 private readonly byte[] rootKey; 522 private readonly byte[] softOutputSeed; 523 private readonly byte[] hardOutputSeed; 524 private readonly byte[] destinationNoneSeed; 525 private readonly byte[] destinationAesSeed; 526 private readonly byte[] destinationOtbnSeed; 527 private readonly byte[] destinationKmacSeed; 528 private readonly byte[] creatorIdentitySeed; 529 private readonly byte[] ownerIntermediateIdentitySeed; 530 private readonly byte[] ownerIdentitySeed; 531 private readonly Random random; 532 private readonly OpenTitan_ROMController romController; 533 private readonly Dictionary<Destination, ISideloadableKey> destinations; 534 535 private const int MultiRegistersCount = 8; 536 private const int KmacBitLength = 256; 537 private const int SeedExpectedLength = 256 / 8; 538 private const int DeviceIdExpectedLength = 256 / 8; 539 private const int LifeCycleDiversificationConstantLength = 128 / 8; 540 private const int CreatorKeyExpectedLength = 256 / 8; 541 private const int OwnerKeyExpectedLength = 256 / 8; 542 private const int RootKeyExpectedLength = 256 * 2 / 8; 543 private const int NumberOfSoftwareShareOutputs = 2; 544 private const int SideloadKeyLength = 256 / 8; 545 private const int SideloadKeyLengthOTBN = 384 / 8; 546 547 public enum OperationMode 548 { 549 Advance = 0, 550 GenerateID = 1, 551 GenerateSWOutput = 2, 552 GenerateHWOutput = 3, 553 Disable = 4, 554 } 555 556 public enum WorkingState 557 { 558 Reset = 0, 559 Init = 1, 560 CreatorRootKey = 2, 561 OwnerIntermediateKey = 3, 562 OwnerKey = 4, 563 Disabled = 5, 564 Invalid = 6, 565 } 566 567 public enum Registers 568 { 569 InterruptState = 0x0, 570 InterruptEnable = 0x4, 571 InterruptTest = 0x8, 572 AlertTest = 0xc, 573 ConfigurationWriteEnable = 0x10, 574 OperationControls = 0x14, 575 SideloadClear = 0x18, 576 ReseedIntervalWriteEnable = 0x1c, 577 ReseedInterval = 0x20, 578 SoftwareBindingWriteEnable = 0x24, 579 SealingSoftwareBinding0 = 0x28, 580 SealingSoftwareBinding1 = 0x2c, 581 SealingSoftwareBinding2 = 0x30, 582 SealingSoftwareBinding3 = 0x34, 583 SealingSoftwareBinding4 = 0x38, 584 SealingSoftwareBinding5 = 0x3c, 585 SealingSoftwareBinding6 = 0x40, 586 SealingSoftwareBinding7 = 0x44, 587 AttestationSoftwareBinding0 = 0x48, 588 AttestationSoftwareBinding1 = 0x4c, 589 AttestationSoftwareBinding2 = 0x50, 590 AttestationSoftwareBinding3 = 0x54, 591 AttestationSoftwareBinding4 = 0x58, 592 AttestationSoftwareBinding5 = 0x5c, 593 AttestationSoftwareBinding6 = 0x60, 594 AttestationSoftwareBinding7 = 0x64, 595 Salt0 = 0x68, 596 Salt1 = 0x6c, 597 Salt2 = 0x70, 598 Salt3 = 0x74, 599 Salt4 = 0x78, 600 Salt5 = 0x7c, 601 Salt6 = 0x80, 602 Salt7 = 0x84, 603 KeyVersion = 0x88, 604 MaxCreatorKeyVersionWriteEnable = 0x8c, 605 MaxCreatorKeyVersion = 0x90, 606 MaxOwnerIntermediateKeyVersionWriteEnable = 0x94, 607 MaxOwnerIntermediateKeyVersion = 0x98, 608 MaxOwnerKeyVersionWriteEnable = 0x9c, 609 MaxOwnerKeyVersion = 0xa0, 610 SoftwareShare0Output0 = 0xa4, 611 SoftwareShare0Output1 = 0xa8, 612 SoftwareShare0Output2 = 0xac, 613 SoftwareShare0Output3 = 0xb0, 614 SoftwareShare0Output4 = 0xb4, 615 SoftwareShare0Output5 = 0xb8, 616 SoftwareShare0Output6 = 0xbc, 617 SoftwareShare0Output7 = 0xc0, 618 SoftwareShare1Output0 = 0xc4, 619 SoftwareShare1Output1 = 0xc8, 620 SoftwareShare1Output2 = 0xcc, 621 SoftwareShare1Output3 = 0xd0, 622 SoftwareShare1Output4 = 0xd4, 623 SoftwareShare1Output5 = 0xd8, 624 SoftwareShare1Output6 = 0xdc, 625 SoftwareShare1Output7 = 0xe0, 626 WorkingState = 0xe4, 627 Status = 0xe8, 628 ErrorCode = 0xec, 629 FaultStatus = 0xf0, 630 } 631 632 private enum CDISetting 633 { 634 Sealing = 0, 635 Attestation = 1, 636 } 637 638 private enum Destination 639 { 640 None = 0, 641 AES = 1, 642 KMAC = 2, 643 OTBN = 3, 644 } 645 646 private enum SideloadClear 647 { 648 None = 0, 649 AES = 1, 650 KMAC = 2, 651 OTBN = 3, 652 } 653 654 private enum Status 655 { 656 Idle = 0, 657 WIP = 1, 658 DoneSuccess = 2, 659 DoneError = 3, 660 } 661 } 662 } 663