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 8 using System; 9 using Antmicro.Renode.Core; 10 using Antmicro.Renode.Core.Structure.Registers; 11 using Antmicro.Renode.Logging; 12 using Antmicro.Renode.Peripherals.Bus; 13 using Antmicro.Renode.Utilities.Crypto; 14 15 namespace Antmicro.Renode.Peripherals.Miscellaneous 16 { 17 public sealed class NRF52840_ECB : BasicDoubleWordPeripheral, IKnownSize, INRFEventProvider 18 { NRF52840_ECB(IMachine machine)19 public NRF52840_ECB(IMachine machine) : base(machine) 20 { 21 IRQ = new GPIO(); 22 DefineRegisters(); 23 } 24 Reset()25 public override void Reset() 26 { 27 base.Reset(); 28 UpdateInterrupts(); 29 } 30 31 public long Size => 0x1000; 32 33 public GPIO IRQ { get; } 34 35 public event Action<uint> EventTriggered; 36 DefineRegisters()37 private void DefineRegisters() 38 { 39 Registers.Start.Define(this) 40 .WithFlag(0, FieldMode.Write, name: "TASKS_START", 41 writeCallback: (_, __) => 42 { 43 RunEncryption(); 44 eventEnd.Value = true; 45 EventTriggered?.Invoke((uint)Registers.EventEnd); 46 UpdateInterrupts(); 47 }) 48 .WithReservedBits(1, 31) 49 ; 50 51 Registers.EventEnd.Define(this, name: "EVENTS_ENDECB") 52 .WithFlag(0, out eventEnd, name: "ENDECB") 53 .WithReservedBits(1, 31) 54 .WithWriteCallback((_, __) => UpdateInterrupts()) 55 ; 56 57 Registers.InterruptEnableSet.Define(this, name: "INTENSET") 58 .WithFlag(0, out endInterruptEnabled, FieldMode.Set | FieldMode.Read, name: "ENDECB") 59 .WithReservedBits(1, 31) 60 .WithWriteCallback((_, __) => UpdateInterrupts()) 61 ; 62 63 Registers.InterruptEnableClear.Define(this, name: "INTENCLR") 64 .WithFlag(0, 65 writeCallback: (_, value) => endInterruptEnabled.Value &= !value, 66 valueProviderCallback: _ => endInterruptEnabled.Value, name: "ENDECB") 67 .WithReservedBits(1, 31) 68 .WithWriteCallback((_, __) => UpdateInterrupts()) 69 ; 70 71 Registers.DataPtr.Define(this) 72 .WithValueField(0, 32, out dataPointer, name: "ECBDATAPTR") 73 ; 74 } 75 RunEncryption()76 private void RunEncryption() 77 { 78 this.Log(LogLevel.Debug, "Running the encryption process; key at 0x{0:X}, cleartext at 0x{1:X}", dataPointer.Value, dataPointer.Value + KeySize); 79 80 var key = sysbus.ReadBytes(dataPointer.Value, KeySize); 81 var clearText = sysbus.ReadBytes(dataPointer.Value + KeySize, ClearTextSize); 82 var clearTextBlock = Block.UsingBytes(clearText); 83 84 using(var aes = AesProvider.GetEcbProvider(key)) 85 { 86 aes.EncryptBlockInSitu(clearTextBlock); 87 } 88 89 sysbus.WriteBytes(clearText, dataPointer.Value + KeySize + ClearTextSize); 90 } 91 UpdateInterrupts()92 private void UpdateInterrupts() 93 { 94 var flag = false; 95 96 flag |= endInterruptEnabled.Value & eventEnd.Value; 97 98 IRQ.Set(flag); 99 } 100 101 private IFlagRegisterField eventEnd; 102 private IFlagRegisterField endInterruptEnabled; 103 private IValueRegisterField dataPointer; 104 105 private const int KeySize = 16; 106 private const int ClearTextSize = 16; 107 108 private enum Registers 109 { 110 Start = 0x0, 111 Stop = 0x4, 112 EventEnd = 0x100, 113 EventError = 0x104, 114 InterruptEnableSet = 0x304, 115 InterruptEnableClear = 0x308, 116 DataPtr = 0x504, 117 } 118 } 119 } 120