1 // 2 // Copyright (c) 2010-2022 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.Utilities; 8 using System; 9 using System.Linq; 10 using System.Numerics; 11 12 namespace Antmicro.Renode.Peripherals.Miscellaneous.Crypto 13 { 14 public class RSAServiceProvider 15 { RSAServiceProvider(InternalMemoryManager manager)16 public RSAServiceProvider(InternalMemoryManager manager) 17 { 18 this.manager = manager; 19 } 20 ModularExponentation()21 public void ModularExponentation() 22 { 23 manager.TryReadDoubleWord((long)RSARegisters.ExponentationModulusLength, out var modulusLength); 24 manager.TryReadDoubleWord((long)RSARegisters.ExponentLength, out var exponentLength); 25 var baseAddress = (long)RSARegisters.BaseAddress + exponentLength * 4; 26 27 var n = AthenaX5200_BigIntegerHelper.CreateBigIntegerFromMemory(manager, (long)RSARegisters.Modulus, modulusLength); 28 var e = AthenaX5200_BigIntegerHelper.CreateBigIntegerFromMemory(manager, (long)RSARegisters.Exponent, exponentLength); 29 var operand = AthenaX5200_BigIntegerHelper.CreateBigIntegerFromMemory(manager, baseAddress, modulusLength); 30 31 var resultBytes = BigInteger.ModPow(operand, e, n).ToByteArray(); 32 AthenaX5200_BigIntegerHelper.StoreBigIntegerBytes(manager, modulusLength, resultBytes, baseAddress); 33 } 34 ModularReduction()35 public void ModularReduction() 36 { 37 manager.TryReadDoubleWord((long)RSARegisters.ReductionModulusLength, out var modulusLength); 38 manager.TryReadDoubleWord((long)RSARegisters.ReductionOperandLength, out var operandLength); 39 40 var n = AthenaX5200_BigIntegerHelper.CreateBigIntegerFromMemory(manager, (long)RSARegisters.Modulus, modulusLength); 41 var a = AthenaX5200_BigIntegerHelper.CreateBigIntegerFromMemory(manager, (long)RSARegisters.Operand, operandLength); 42 43 var resultBytes = (a % n).ToByteArray(); 44 AthenaX5200_BigIntegerHelper.StoreBigIntegerBytes(manager, modulusLength, resultBytes, (long)RSARegisters.Operand); 45 } 46 DecryptData()47 public void DecryptData() 48 { 49 manager.TryReadDoubleWord((long)RSARegisters.DecryptionModulusLength, out var modulusLength); 50 51 var n = AthenaX5200_BigIntegerHelper.CreateBigIntegerFromMemory(manager, (long)RSARegisters.N, modulusLength * 2); 52 53 // Step 1: 54 // m1 = c^dp mod p 55 var c = AthenaX5200_BigIntegerHelper.CreateBigIntegerFromMemory(manager, (long)RSARegisters.Cipher, modulusLength * 2); 56 var dp = AthenaX5200_BigIntegerHelper.CreateBigIntegerFromMemory(manager, (long)RSARegisters.DP, modulusLength); 57 var p = AthenaX5200_BigIntegerHelper.CreateBigIntegerFromMemory(manager, (long)RSARegisters.P, modulusLength); 58 var m1 = BigInteger.ModPow(c, dp, p); 59 60 // Step 2: 61 // m2 = c^dq mod q 62 var dq = AthenaX5200_BigIntegerHelper.CreateBigIntegerFromMemory(manager, (long)RSARegisters.DQ, modulusLength); 63 var q = AthenaX5200_BigIntegerHelper.CreateBigIntegerFromMemory(manager, (long)RSARegisters.Q, modulusLength); 64 var m2 = BigInteger.ModPow(c, dq, q); 65 66 // Step 3: 67 // h = (qInv * (m1 - m2)) mod p 68 var qInv = AthenaX5200_BigIntegerHelper.CreateBigIntegerFromMemory(manager, (long)RSARegisters.QInverted, modulusLength); 69 var x = m1 - m2; 70 // We add in an extra p here to keep x positive 71 // example: https://www.di-mgt.com.au/crt_rsa.html 72 while(x < 0) 73 { 74 x += p; 75 } 76 var h = (qInv * x) % p; 77 78 // Step 4: 79 // m = m2 + h * q 80 var mBytes = (m2 + h * q).ToByteArray(); 81 AthenaX5200_BigIntegerHelper.StoreBigIntegerBytes(manager, (uint)mBytes.Length, mBytes, (long)RSARegisters.BaseAddress); 82 } 83 Reset()84 public void Reset() 85 { 86 manager.ResetMemories(); 87 } 88 89 private readonly InternalMemoryManager manager; 90 91 private enum RSARegisters 92 { 93 ReductionOperandLength = 0x8, 94 ReductionModulusLength = 0xC, 95 ExponentationModulusLength = 0x10, 96 Operand = 0x10, 97 ExponentLength = 0x14, 98 Exponent = 0x18, 99 BaseAddress = 0x18, 100 DecryptionModulusLength = 0x30, 101 Cipher = 0x1e4, 102 DP = 0x4f0, 103 DQ = 0x5b0, 104 QInverted = 0x670, 105 Modulus = 0x1000, 106 P = 0x1348, 107 Q = 0x14cc, 108 N = 0x1650, 109 } 110 } 111 } 112