1 // 2 // Copyright (c) 2010-2021 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 NUnit.Framework; 9 using Antmicro.Renode.Core; 10 using Antmicro.Renode.Debugging; 11 using Antmicro.Renode.Peripherals.Miscellaneous; 12 using System.Collections.Generic; 13 14 namespace Antmicro.Renode.PeripheralsTests 15 { 16 [TestFixture] 17 public class OpenTitan_AES_Tests 18 { 19 [SetUp] SetUp()20 public void SetUp() 21 { 22 peripheral = new OpenTitan_AES(new Machine()); 23 } 24 25 [Test] ShouldStartInIdleMode()26 public void ShouldStartInIdleMode() 27 { 28 var status = peripheral.ReadDoubleWord((long)OpenTitan_AES.Registers.Status); 29 Assert.AreEqual(0x1, status & 0x1); 30 } 31 32 [Test] ShouldChangeStatusWhenSetToAutomaticMode()33 public void ShouldChangeStatusWhenSetToAutomaticMode() 34 { 35 peripheral.WriteDoubleWord((long)OpenTitan_AES.Registers.Control, 0x8); 36 var status = peripheral.ReadDoubleWord((long)OpenTitan_AES.Registers.Status); 37 Assert.AreEqual(0x10, status & 0x10); 38 } 39 40 [Test] ShouldKeepTrackOfDataWrites()41 public void ShouldKeepTrackOfDataWrites() 42 { 43 peripheral.WriteDoubleWord((long)OpenTitan_AES.Registers.InputData_0, 0x1234); 44 45 Assert.IsFalse(peripheral.InputDataReady); 46 WriteInputData(encrypted); 47 Assert.IsTrue(peripheral.InputDataReady); 48 } 49 50 [Test] 51 //This test is based on OpenTitan AES smoketest binary ShouldGiveCorrectEncryptionOutput()52 public void ShouldGiveCorrectEncryptionOutput() 53 { 54 SetKeyShare(); 55 56 peripheral.WriteDoubleWord((long)OpenTitan_AES.Registers.Control, 0x205); 57 WriteInputData(decrypted); 58 59 for(int i = 0; i < 4; i++) 60 { 61 var actual = peripheral.ReadDoubleWord((long)OpenTitan_AES.Registers.OutputData_0 + 4 * i); 62 Assert.AreEqual(encrypted[i], actual, "DATA_OUT_{0}: Expected: 0x{1:X}, Got: 0x{2:x}", i, encrypted[i], actual); 63 } 64 } 65 66 [Test] 67 //This test is based on OpenTitan AES smoketest binary ShouldWorkInManualModeToo()68 public void ShouldWorkInManualModeToo() 69 { 70 SetKeyShare(); 71 72 peripheral.WriteDoubleWord((long)OpenTitan_AES.Registers.Control, 0x8405); 73 WriteInputData(decrypted); 74 75 // Before trigger 76 for(int i = 0; i < 4; i++) 77 { 78 var actual = peripheral.ReadDoubleWord((long)OpenTitan_AES.Registers.OutputData_0 + 4 * i); 79 Assert.AreEqual(0x0, actual, "DATA_OUT_{0}: Expected to be zero before trigger, Got: 0x{1:x}", i, actual); 80 } 81 82 peripheral.WriteDoubleWord((long)OpenTitan_AES.Registers.Trigger, 0x1); 83 84 // After trigger 85 for(int i = 0; i < 4; i++) 86 { 87 var actual = peripheral.ReadDoubleWord((long)OpenTitan_AES.Registers.OutputData_0 + 4 * i); 88 Assert.AreEqual(encrypted[i], actual, "DATA_OUT_{0}: Expected: 0x{1:X}, Got: 0x{2:x}", i, encrypted[i], actual); 89 } 90 91 } 92 93 [Test] 94 //This test is based on OpenTitan AES smoketest binary ShouldGiveCorrectDecryptionOutput()95 public void ShouldGiveCorrectDecryptionOutput() 96 { 97 SetKeyShare(); 98 99 peripheral.WriteDoubleWord((long)OpenTitan_AES.Registers.Control, 0x206); 100 101 WriteInputData(encrypted); 102 103 for(int i = 0; i < 4; i++) 104 { 105 var actual = peripheral.ReadDoubleWord((long)OpenTitan_AES.Registers.OutputData_0+ 4 * i); 106 Assert.AreEqual(decrypted[i], actual, "DATA_OUT_{0}: Expected: 0x{1:X}, Got: 0x{2:x}", i, decrypted[i], actual); 107 } 108 } 109 110 [Test] ShouldRandomizeDataOutputOnTrigger()111 public void ShouldRandomizeDataOutputOnTrigger() 112 { 113 peripheral.WriteDoubleWord((long)OpenTitan_AES.Registers.Trigger, 0x4); 114 uint sum = 0; 115 for(int i = 0; i < 4; i++) 116 { 117 sum += peripheral.ReadDoubleWord((long)OpenTitan_AES.Registers.OutputData_0 + 4 * i); 118 } 119 Assert.AreNotEqual(0x0, sum); 120 } 121 122 [Test] ShouldRandomizeInputRegistersOnTrigger()123 public void ShouldRandomizeInputRegistersOnTrigger() 124 { 125 peripheral.WriteDoubleWord((long)OpenTitan_AES.Registers.Control, 0x1005); 126 127 // We only test if the output is different after randomizing 128 WriteInputData(decrypted); 129 peripheral.WriteDoubleWord((long)OpenTitan_AES.Registers.Trigger, 0x6); 130 peripheral.WriteDoubleWord((long)OpenTitan_AES.Registers.Trigger, 0x1); 131 132 for( var i = 0; i < 4; i++) 133 { 134 var actual = peripheral.ReadDoubleWord((long)OpenTitan_AES.Registers.OutputData_0 + 4 * i); 135 Assert.AreNotEqual(encrypted[i], actual); 136 } 137 } 138 139 [Test] ShouldBeAbleToDoMultipleTransformationsWithASingleKey()140 public void ShouldBeAbleToDoMultipleTransformationsWithASingleKey() 141 { 142 SetKeyShare(); 143 144 peripheral.WriteDoubleWord((long)OpenTitan_AES.Registers.Control, 0x206); 145 146 WriteInputData(decrypted); 147 WriteInputData(encrypted); 148 149 for(int i = 0; i < 4; i++) 150 { 151 var actual = peripheral.ReadDoubleWord((long)OpenTitan_AES.Registers.OutputData_0 + 4 * i); 152 Assert.AreEqual(decrypted[i], actual, "DATA_OUT_{0}: Expected: 0x{1:X}, Got: 0x{2:x}", i, decrypted[i], actual); 153 } 154 } 155 WriteInputData(uint[] data)156 private void WriteInputData(uint[] data) 157 { 158 DebugHelper.Assert(data.Length == 4); 159 160 for(var i = 0; i < 4; i++) 161 { 162 peripheral.WriteDoubleWord((long)OpenTitan_AES.Registers.InputData_0 + 4 * i, data[i]); 163 } 164 } 165 SetKeyShare()166 private void SetKeyShare() 167 { 168 for(int i = 0; i < 8; i++) 169 { 170 peripheral.WriteDoubleWord((long)OpenTitan_AES.Registers.InitialKeyShare0_0 + i * 4, keyShare0[i]); 171 peripheral.WriteDoubleWord((long)OpenTitan_AES.Registers.InitialKeyShare1_0 + i * 4, keyShare1[i]); 172 } 173 } 174 175 private OpenTitan_AES peripheral; 176 177 private readonly uint[] keyShare0 = { 0x3C2D1E0F, 0x78695A4B, 0xB4A59687, 0xF0E1D2C3, 0x29380B1A, 0x6D7C4F5E, 0xA1B08392, 0xE5F4C7D6 }; 178 private readonly uint[] keyShare1 = { 0x3F2F1F0F, 0x7F6F5F4F, 0xBFAF9F8F, 0xFFEFDFCF, 0x3A2A1A0A, 0x7A6A5A4A, 0xBAAA9A8A, 0xFAEADACA }; 179 private readonly uint[] encrypted = { 0xCAB7A28E, 0xBF456751, 0x9049FCEA, 0x8960494B }; 180 private readonly uint[] decrypted = { 0x33221100, 0x77665544, 0xBBAA9988, 0xFFEEDDCC }; 181 } 182 } 183