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 Antmicro.Renode.Core; 8 using Antmicro.Renode.Core.Structure.Registers; 9 using Antmicro.Renode.Logging; 10 using Antmicro.Renode.Peripherals.Bus; 11 using System; 12 using System.Collections.Generic; 13 14 namespace Antmicro.Renode.Peripherals.Miscellaneous.Crypto 15 { 16 public class AthenaX5200 : IDoubleWordPeripheral, IProvidesRegisterCollection<DoubleWordRegisterCollection>, IKnownSize 17 { AthenaX5200(IMachine machine)18 public AthenaX5200(IMachine machine) 19 { 20 memoryManager = new InternalMemoryManager(); 21 RegistersCollection = new DoubleWordRegisterCollection(this); 22 rsaServiceProvider = new RSAServiceProvider(memoryManager); 23 aesServiceProvider = new AESServiceProvider(memoryManager, machine.GetSystemBus(this)); 24 msgAuthServiceProvider = new MessageAuthenticationServiceProvider(memoryManager, machine.GetSystemBus(this)); 25 dsaServiceProvider = new DSAServiceProvider(memoryManager, machine.GetSystemBus(this)); 26 27 Registers.CSR.Define(this) 28 .WithFlag(0, 29 writeCallback: (_, val) => 30 { 31 if(val) 32 { 33 Reset(); 34 } 35 coreReset = val; 36 }, 37 valueProviderCallback: _ => coreReset, name: "RESET") 38 .WithFlag(1, FieldMode.Write, writeCallback: (_, val) => 39 { 40 if(val) 41 { 42 isCompleted = false; 43 } 44 }, name: "CLEAR_COMPLETE") 45 .WithFlag(2, FieldMode.Read, valueProviderCallback: _ => isCompleted, name: "COMPLETE") 46 .WithTag("BUSY", 3, 1) 47 .WithFlag(4, out coreExecuteCommand, name: "EXECUTE_COMMAND") 48 .WithReservedBits(5, 3) 49 .WithEnumField(8, 8, out operation) 50 .WithReservedBits(16, 3) 51 .WithTag("PKX_OFFSET", 19, 1) 52 .WithReservedBits(20, 12) 53 .WithWriteCallback((_, __) => 54 { 55 if(!coreExecuteCommand.Value) 56 { 57 return; 58 } 59 if(!commands.TryGetValue(operation.Value, out var command)) 60 { 61 this.Log(LogLevel.Error, "Unknown command: [{0}].", operation.Value); 62 return; 63 } 64 this.Log(LogLevel.Noisy, "Executing command: [{0}]", operation.Value); 65 command(); 66 isCompleted = true; 67 coreExecuteCommand.Value = false; 68 }); 69 70 commands = new Dictionary<JumpTable, Action> 71 { 72 { JumpTable.PrecomputeValueRSA, EmptyHandler }, 73 { JumpTable.InstantiateDRBG, InstantiateDRBG }, 74 { JumpTable.GenerateBlocksFromDRBG, GenerateBlocksWithDRBG }, 75 { JumpTable.UninstantiateDRBG, UninstantiateDRBG }, 76 { JumpTable.ModularExponentationRSA, rsaServiceProvider.ModularExponentation }, 77 { JumpTable.ModularReductionRSA, rsaServiceProvider.ModularReduction }, 78 { JumpTable.DecryptCipherRSA, rsaServiceProvider.DecryptData }, 79 { JumpTable.RunAES, aesServiceProvider.PerformAESOperation }, 80 { JumpTable.RunAES_DMA, aesServiceProvider.PerformAESOperationDMA }, 81 { JumpTable.RunGCM, msgAuthServiceProvider.PerformGCMMessageAuthentication }, 82 { JumpTable.RunGCMNew, msgAuthServiceProvider.PerformGCMMessageAuthentication }, 83 { JumpTable.RunSHA, msgAuthServiceProvider.PerformSHA }, 84 { JumpTable.RunSHADMA, msgAuthServiceProvider.PerformSHADMA }, 85 { JumpTable.RunHMACSHA, msgAuthServiceProvider.PerformHMACSHA }, 86 { JumpTable.RunDSA_Sign, dsaServiceProvider.SignDMA }, 87 }; 88 89 Reset(); 90 } 91 ReadDoubleWord(long offset)92 public uint ReadDoubleWord(long offset) 93 { 94 return memoryManager.TryReadDoubleWord(offset, out uint result) 95 ? result 96 : RegistersCollection.Read(offset); 97 } 98 WriteDoubleWord(long offset, uint value)99 public void WriteDoubleWord(long offset, uint value) 100 { 101 if(!memoryManager.TryWriteDoubleWord(offset, value)) 102 { 103 RegistersCollection.Write(offset, value); 104 } 105 } 106 Reset()107 public void Reset() 108 { 109 memoryManager.ResetMemories(); 110 RegistersCollection.Reset(); 111 msgAuthServiceProvider.Reset(); 112 rsaServiceProvider.Reset(); 113 aesServiceProvider.Reset(); 114 randomGenerator?.Reset(); 115 isCompleted = false; 116 coreReset = false; 117 } 118 119 public long Size => 0x1000000; 120 public DoubleWordRegisterCollection RegistersCollection { get; } 121 EmptyHandler()122 private void EmptyHandler() 123 { 124 // There are commands in which no processing is needed, 125 // but we want to report in the Status Register that it has completed. 126 } 127 InstantiateDRBG()128 private void InstantiateDRBG() 129 { 130 if(randomGenerator != null) 131 { 132 this.Log(LogLevel.Error, "RNG subsystem already instantiated. Aborting!"); 133 return; 134 } 135 randomGenerator = new PseudorandomBitGenerator(memoryManager); 136 } 137 GenerateBlocksWithDRBG()138 private void GenerateBlocksWithDRBG() 139 { 140 if(randomGenerator == null) 141 { 142 this.Log(LogLevel.Error, "RNG subsystem is not instantiated. Aborting!"); 143 return; 144 } 145 randomGenerator.Generate(); 146 } 147 UninstantiateDRBG()148 private void UninstantiateDRBG() 149 { 150 if(randomGenerator == null) 151 { 152 this.Log(LogLevel.Error, "RNG subsystem is not instantiated. Aborting!"); 153 return; 154 } 155 randomGenerator = null; 156 } 157 158 private bool coreReset; 159 private bool isCompleted; 160 private PseudorandomBitGenerator randomGenerator; 161 162 private readonly InternalMemoryManager memoryManager; 163 private readonly Dictionary<JumpTable, Action> commands; 164 private readonly IEnumRegisterField<JumpTable> operation; 165 private readonly IFlagRegisterField coreExecuteCommand; 166 private readonly RSAServiceProvider rsaServiceProvider; 167 private readonly AESServiceProvider aesServiceProvider; 168 private readonly MessageAuthenticationServiceProvider msgAuthServiceProvider; 169 private readonly DSAServiceProvider dsaServiceProvider; 170 171 private enum JumpTable 172 { 173 // gaps in addressing - only a few commands are implemented 174 PrecomputeValueRSA = 0x0, 175 ModularExponentationRSA = 0x2, 176 ModularReductionRSA = 0x12, 177 RunSHA = 0x1E, 178 RunAES = 0x20, 179 RunGCM = 0x24, 180 InstantiateDRBG = 0x2C, 181 GenerateBlocksFromDRBG = 0x30, 182 RunAES_DMA = 0x38, 183 UninstantiateDRBG = 0x32, 184 RunHMACSHA = 0x36, 185 RunSHADMA = 0x3C, 186 RunDSA_Sign = 0x40, 187 DecryptCipherRSA = 0x4E, 188 RunGCMNew = 0x5A 189 } 190 191 private enum Registers : uint 192 { 193 CSR = 0x7F80 194 } 195 } 196 } 197