// -*- mode:c++ -*- // Copyright (c) 2020 Metempsy Technology Consulting // All rights reserved // // The license below extends only to copyright in the software and shall // not be construed as granting a license to any other intellectual // property including but not limited to intellectual property relating // to a hardware implementation of the functionality of the software // licensed hereunder. You may use the software subject to the license // terms below provided that you ensure that this notice is replicated // unmodified and in its entirety in all distributions of the software, // modified or unmodified, in source code or in binary form. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer; // redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution; // neither the name of the copyright holders nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "arch/arm/qarma.hh" #include #include "base/bitfield.hh" namespace gem5 { using namespace QARMA; uint8_t QARMA::rotCell(uint8_t incell, int amount) { uint8_t res = ((incell << amount) | (incell >> (4-amount)))& 0xF; return res; } uint8_t QARMA::tweakCellInvRot(uint8_t incell) { uint8_t outcell = 0x0; outcell = incell << 1; uint8_t t = 0x1 & (incell ^ (incell>>3)); outcell |= t; return outcell & 0xF; } uint8_t QARMA::tweakCellRot(uint8_t incell) { uint8_t outcell = 0x0; outcell = incell >> 1; uint8_t t = 0x1 & (incell ^ (incell>>1)); outcell |= t<<3; return outcell & 0xF; } BIT64 QARMA::tweakInvShuffle(BIT64 indata) { BIT64 outdata = 0x0; outdata.b0 = tweakCellInvRot(indata.b12); outdata.b1 = indata.b13; outdata.b2 = indata.b5; outdata.b3 = indata.b6; outdata.b4 = indata.b0; outdata.b5 = indata.b1; outdata.b6 = tweakCellInvRot(indata.b2); outdata.b7 = indata.b3; outdata.b8 = tweakCellInvRot(indata.b7); outdata.b9 = tweakCellInvRot(indata.b15); outdata.b10 = tweakCellInvRot(indata.b14); outdata.b11 = tweakCellInvRot(indata.b4); outdata.b12 = indata.b8; outdata.b13 = indata.b9; outdata.b14 = indata.b10; outdata.b15 = tweakCellInvRot(indata.b11); return outdata; } BIT64 QARMA::tweakShuffle(BIT64 indata) { BIT64 outdata = 0x0; outdata.b0 = indata.b4; outdata.b1 = indata.b5; outdata.b2 = tweakCellRot(indata.b6); outdata.b3 = indata.b7; outdata.b4 = tweakCellRot(indata.b11); outdata.b5 = indata.b2; outdata.b6 = indata.b3; outdata.b7 = tweakCellRot(indata.b8); outdata.b8 = indata.b12; outdata.b9 = indata.b13; outdata.b10 = indata.b14; outdata.b11 = tweakCellRot(indata.b15); outdata.b12 = tweakCellRot(indata.b0); outdata.b13 = indata.b1; outdata.b14 = tweakCellRot(indata.b10); outdata.b15 = tweakCellRot(indata.b9); return outdata; } BIT64 QARMA::PACCellInvShuffle(BIT64 indata) { BIT64 outdata = 0x0; outdata.b0 = indata.b3; outdata.b1 = indata.b6; outdata.b2 = indata.b12; outdata.b3 = indata.b9; outdata.b4 = indata.b14; outdata.b5 = indata.b11; outdata.b6 = indata.b1; outdata.b7 = indata.b4; outdata.b8 = indata.b8; outdata.b9 = indata.b13; outdata.b10 = indata.b7; outdata.b11 = indata.b2; outdata.b12 = indata.b5; outdata.b13 = indata.b0; outdata.b14 = indata.b10; outdata.b15 = indata.b15; return outdata; } BIT64 QARMA::PACCellShuffle(BIT64 indata) { BIT64 outdata = 0x0; outdata.b0 = indata.b13; outdata.b1 = indata.b6; outdata.b2 = indata.b11; outdata.b3 = indata.b0; outdata.b4 = indata.b7; outdata.b5 = indata.b12; outdata.b6 = indata.b1; outdata.b7 = indata.b10; outdata.b8 = indata.b8; outdata.b9 = indata.b3; outdata.b10 = indata.b14; outdata.b11 = indata.b5; outdata.b12 = indata.b2; outdata.b13 = indata.b9; outdata.b14 = indata.b4; outdata.b15 = indata.b15; return outdata; } uint64_t QARMA::PACInvSub(uint64_t tInput) { // This is a 4-bit substitution from the PRINCE-family cipher uint64_t t_output = 0x0; for (int i=15; i>=0; i--) { t_output = t_output << 4; uint8_t b = (tInput >> i*4 ) & 0xF; switch ( b ) { case 0x0: t_output |= 0x5; break; case 0x1: t_output |= 0xe; break; case 0x2: t_output |= 0xd; break; case 0x3: t_output |= 0x8; break; case 0x4: t_output |= 0xa; break; case 0x5: t_output |= 0xb; break; case 0x6: t_output |= 0x1; break; case 0x7: t_output |= 0x9; break; case 0x8: t_output |= 0x2; break; case 0x9: t_output |= 0x6; break; case 0xa: t_output |= 0xf; break; case 0xb: t_output |= 0x0; break; case 0xc: t_output |= 0x4; break; case 0xd: t_output |= 0xc; break; case 0xe: t_output |= 0x7; break; case 0xf: t_output |= 0x3; break; default: //unreachable break; } } return t_output; } uint64_t QARMA::PACSub(uint64_t tInput){ // This is a 4-bit substitution from the PRINCE-family cipher uint64_t t_output = 0x0; for (int i=15; i>=0; i--) { t_output = t_output << 4; uint8_t b = (tInput >> i*4 ) & 0xF; switch ( b ) { case 0x0: t_output |= 0xb; break; case 0x1: t_output |= 0x6; break; case 0x2: t_output |= 0x8; break; case 0x3: t_output |= 0xf; break; case 0x4: t_output |= 0xc; break; case 0x5: t_output |= 0x0; break; case 0x6: t_output |= 0x9; break; case 0x7: t_output |= 0xe; break; case 0x8: t_output |= 0x3; break; case 0x9: t_output |= 0x7; break; case 0xa: t_output |= 0x4; break; case 0xb: t_output |= 0x5; break; case 0xc: t_output |= 0xd; break; case 0xd: t_output |= 0x2; break; case 0xe: t_output |= 0x1; break; case 0xf: t_output |= 0xa; break; default: //unreachable break; } } return t_output; } uint64_t QARMA::PACMult(uint64_t tInput) { uint64_t t_output = 0; for (int i=0;i<=3; i++) { uint8_t b8 = (tInput >> (4*(i+8))) & 0xF; uint8_t b4 = (tInput >> (4*(i+4))) & 0xF; uint8_t b12 = (tInput >> (4*(i+12))) & 0xF; uint8_t b0 = (tInput >> (4*(i))) & 0xF; uint64_t t0 = rotCell(b8, 1) ^ rotCell(b4, 2); t0 = t0 ^ rotCell(b0, 1); uint64_t t1 = rotCell(b12, 1) ^ rotCell(b4, 1); t1 = t1 ^ rotCell(b0, 2); uint64_t t2 = rotCell(b12, 2) ^ rotCell(b8, 1); t2 = t2 ^ rotCell(b0, 1); uint64_t t3 = rotCell(b12, 1) ^ rotCell(b8, 2); t3 = t3 ^ rotCell(b4, 1); t_output |= (t3 << (4*i)); t_output |= (t2 << (4*(i+4))); t_output |= (t1 << (4*(i+8))); t_output |= (t0 << (4*(i+12))); } return t_output; } BIT64 QARMA::computePAC(BIT64 data, BIT64 modifier, BIT64 key0, BIT64 key1) { BIT64 workingval; BIT64 runningmod; BIT64 roundkey; BIT64 modk0; std::array RC; RC[0] = (BIT64) 0x0000000000000000; RC[1] = (BIT64) 0x13198A2E03707344; RC[2] = (BIT64) 0xA4093822299F31D0; RC[3] = (BIT64) 0x082EFA98EC4E6C89; RC[4] = (BIT64) 0x452821E638D01377; const BIT64 alpha = 0xC0AC29B7C97C50DD; //modk0 = key0<0>:key0<63:2>: modk0 = (key0 & 0x1) << 63; modk0 = modk0 | ((key0 & ~0x3) >> 1); modk0 = modk0 | ((key0.b15>>3) ^ ((key0.b0 & 0x2)>>1)); runningmod = modifier; workingval = data^key0; for (int i=0; i<=4; i++) { roundkey = key1 ^ runningmod; workingval = workingval ^ roundkey; workingval = workingval ^ RC[i]; if (i > 0) { workingval = PACCellShuffle(workingval); workingval = PACMult(workingval); } workingval = PACSub(workingval); runningmod = tweakShuffle(runningmod); } roundkey = modk0 ^ runningmod; workingval = workingval ^ roundkey; workingval = PACCellShuffle(workingval); workingval = PACMult(workingval); workingval = PACSub(workingval); workingval = PACCellShuffle(workingval); workingval = PACMult(workingval); workingval = key1 ^ workingval; workingval = PACCellInvShuffle(workingval); workingval = PACInvSub(workingval); workingval = PACMult(workingval); workingval = PACCellInvShuffle(workingval); workingval = workingval ^ key0; workingval = workingval ^ runningmod; for (int i=0; i<=4; i++) { workingval = PACInvSub(workingval); if (i < 4) { workingval = PACMult(workingval); workingval = PACCellInvShuffle(workingval); } runningmod = tweakInvShuffle(runningmod); roundkey = key1 ^ runningmod; workingval = workingval ^ RC[4-i]; workingval = workingval ^ roundkey; workingval = workingval ^ alpha; } workingval = workingval ^ modk0; return workingval; } } // namespace gem5