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  }