github.com/mad-day/Yawning-crypto@v0.0.0-20190711051033-5a5f8cca32ec/bsaes/ct32/aes_ct32_dec.go (about) 1 // Copyright (c) 2016 Thomas Pornin <pornin@bolet.org> 2 // Copyright (c) 2017 Yawning Angel <yawning at schwanenlied dot me> 3 // 4 // Permission is hereby granted, free of charge, to any person obtaining 5 // a copy of this software and associated documentation files (the 6 // "Software"), to deal in the Software without restriction, including 7 // without limitation the rights to use, copy, modify, merge, publish, 8 // distribute, sublicense, and/or sell copies of the Software, and to 9 // permit persons to whom the Software is furnished to do so, subject to 10 // the following conditions: 11 // 12 // The above copyright notice and this permission notice shall be 13 // included in all copies or substantial portions of the Software. 14 // 15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 19 // BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 20 // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 // SOFTWARE. 23 24 package ct32 25 26 func InvSbox(q *[8]uint32) { 27 // AES S-box is: 28 // S(x) = A(I(x)) ^ 0x63 29 // where I() is inversion in GF(256), and A() is a linear 30 // transform (0 is formally defined to be its own inverse). 31 // Since inversion is an involution, the inverse S-box can be 32 // computed from the S-box as: 33 // iS(x) = B(S(B(x ^ 0x63)) ^ 0x63) 34 // where B() is the inverse of A(). Indeed, for any y in GF(256): 35 // iS(S(y)) = B(A(I(B(A(I(y)) ^ 0x63 ^ 0x63))) ^ 0x63 ^ 0x63) = y 36 // 37 // Note: we reuse the implementation of the forward S-box, 38 // instead of duplicating it here, so that total code size is 39 // lower. By merging the B() transforms into the S-box circuit 40 // we could make faster CBC decryption, but CBC decryption is 41 // already quite faster than CBC encryption because we can 42 // process two blocks in parallel. 43 var q0, q1, q2, q3, q4, q5, q6, q7 uint32 44 45 q0 = ^q[0] 46 q1 = ^q[1] 47 q2 = q[2] 48 q3 = q[3] 49 q4 = q[4] 50 q5 = ^q[5] 51 q6 = ^q[6] 52 q7 = q[7] 53 q[7] = q1 ^ q4 ^ q6 54 q[6] = q0 ^ q3 ^ q5 55 q[5] = q7 ^ q2 ^ q4 56 q[4] = q6 ^ q1 ^ q3 57 q[3] = q5 ^ q0 ^ q2 58 q[2] = q4 ^ q7 ^ q1 59 q[1] = q3 ^ q6 ^ q0 60 q[0] = q2 ^ q5 ^ q7 61 62 Sbox(q) 63 64 q0 = ^q[0] 65 q1 = ^q[1] 66 q2 = q[2] 67 q3 = q[3] 68 q4 = q[4] 69 q5 = ^q[5] 70 q6 = ^q[6] 71 q7 = q[7] 72 q[7] = q1 ^ q4 ^ q6 73 q[6] = q0 ^ q3 ^ q5 74 q[5] = q7 ^ q2 ^ q4 75 q[4] = q6 ^ q1 ^ q3 76 q[3] = q5 ^ q0 ^ q2 77 q[2] = q4 ^ q7 ^ q1 78 q[1] = q3 ^ q6 ^ q0 79 q[0] = q2 ^ q5 ^ q7 80 } 81 82 func InvShiftRows(q *[8]uint32) { 83 for i := 0; i < 8; i++ { 84 x := q[i] 85 q[i] = (x & 0x000000FF) | 86 ((x & 0x00003F00) << 2) | ((x & 0x0000C000) >> 6) | 87 ((x & 0x000F0000) << 4) | ((x & 0x00F00000) >> 4) | 88 ((x & 0x03000000) << 6) | ((x & 0xFC000000) >> 2) 89 } 90 } 91 92 func InvMixColumns(q *[8]uint32) { 93 var q0, q1, q2, q3, q4, q5, q6, q7 uint32 94 var r0, r1, r2, r3, r4, r5, r6, r7 uint32 95 96 q0 = q[0] 97 q1 = q[1] 98 q2 = q[2] 99 q3 = q[3] 100 q4 = q[4] 101 q5 = q[5] 102 q6 = q[6] 103 q7 = q[7] 104 r0 = (q0 >> 8) | (q0 << 24) 105 r1 = (q1 >> 8) | (q1 << 24) 106 r2 = (q2 >> 8) | (q2 << 24) 107 r3 = (q3 >> 8) | (q3 << 24) 108 r4 = (q4 >> 8) | (q4 << 24) 109 r5 = (q5 >> 8) | (q5 << 24) 110 r6 = (q6 >> 8) | (q6 << 24) 111 r7 = (q7 >> 8) | (q7 << 24) 112 113 q[0] = q5 ^ q6 ^ q7 ^ r0 ^ r5 ^ r7 ^ rotr16(q0^q5^q6^r0^r5) 114 q[1] = q0 ^ q5 ^ r0 ^ r1 ^ r5 ^ r6 ^ r7 ^ rotr16(q1^q5^q7^r1^r5^r6) 115 q[2] = q0 ^ q1 ^ q6 ^ r1 ^ r2 ^ r6 ^ r7 ^ rotr16(q0^q2^q6^r2^r6^r7) 116 q[3] = q0 ^ q1 ^ q2 ^ q5 ^ q6 ^ r0 ^ r2 ^ r3 ^ r5 ^ rotr16(q0^q1^q3^q5^q6^q7^r0^r3^r5^r7) 117 q[4] = q1 ^ q2 ^ q3 ^ q5 ^ r1 ^ r3 ^ r4 ^ r5 ^ r6 ^ r7 ^ rotr16(q1^q2^q4^q5^q7^r1^r4^r5^r6) 118 q[5] = q2 ^ q3 ^ q4 ^ q6 ^ r2 ^ r4 ^ r5 ^ r6 ^ r7 ^ rotr16(q2^q3^q5^q6^r2^r5^r6^r7) 119 q[6] = q3 ^ q4 ^ q5 ^ q7 ^ r3 ^ r5 ^ r6 ^ r7 ^ rotr16(q3^q4^q6^q7^r3^r6^r7) 120 q[7] = q4 ^ q5 ^ q6 ^ r4 ^ r6 ^ r7 ^ rotr16(q4^q5^q7^r4^r7) 121 } 122 123 func decrypt(numRounds int, skey []uint32, q *[8]uint32) { 124 AddRoundKey(q, skey[numRounds<<3:]) 125 for u := numRounds - 1; u > 0; u-- { 126 InvShiftRows(q) 127 InvSbox(q) 128 AddRoundKey(q, skey[u<<3:]) 129 InvMixColumns(q) 130 } 131 InvShiftRows(q) 132 InvSbox(q) 133 AddRoundKey(q, skey) 134 }