//******************************************************************************
//
// File:    AES256CipherSmp.java
// Package: edu.rit.crypto.blockcipher
// Unit:    Class edu.rit.crypto.blockcipher.AES256CipherSmp
//
// This Java source file is copyright (C) 2007 by Alan Kaminsky. All rights
// reserved. For further information, contact the author, Alan Kaminsky, at
// ark@cs.rit.edu.
//
// This Java source file is part of the Parallel Java Library ("PJ"). PJ is free
// software; you can redistribute it and/or modify it under the terms of the GNU
// General Public License as published by the Free Software Foundation; either
// version 3 of the License, or (at your option) any later version.
//
// PJ is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
// A PARTICULAR PURPOSE. See the GNU General Public License for more details.
//
// A copy of the GNU General Public License is provided in the file gpl.txt. You
// may also obtain a copy of the GNU General Public License on the World Wide
// Web at http://www.gnu.org/licenses/gpl.html.
//
//******************************************************************************

package edu.rit.crypto.blockcipher;

/**
 * Class AES256CipherSmp provides a {@linkplain BlockCipher} using the Advanced
 * Encryption Standard (AES) with a 128-bit (16-byte) block length and a 256-bit
 * (32-byte) key length. The AES specification may be found at
 * http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf.
 * 

* Unlike class {@linkplain AES256Cipher}, class AES256CipherSmp includes extra * padding in the memory layout to avoid cache interference when running a * program with multiple threads on an SMP parallel computer. *

* Note: However, class AES256CipherSmp is not multiple thread safe. * * @author Alan Kaminsky * @version 18-Dec-2007 */ public class AES256CipherSmp extends BlockCipher { // Hidden tables. /** * The number of round keys. */ private static final int ROUND_KEY_COUNT = 15; /** * The fixed AES S-box. To apply the S-box to a byte i, write * byteSub [i]. */ private static final short[] byteSub = new short[] { /* 0x00 */ (short) 0x63, /* 0x01 */ (short) 0x7c, /* 0x02 */ (short) 0x77, /* 0x03 */ (short) 0x7b, /* 0x04 */ (short) 0xf2, /* 0x05 */ (short) 0x6b, /* 0x06 */ (short) 0x6f, /* 0x07 */ (short) 0xc5, /* 0x08 */ (short) 0x30, /* 0x09 */ (short) 0x01, /* 0x0A */ (short) 0x67, /* 0x0B */ (short) 0x2b, /* 0x0C */ (short) 0xfe, /* 0x0D */ (short) 0xd7, /* 0x0E */ (short) 0xab, /* 0x0F */ (short) 0x76, /* 0x10 */ (short) 0xca, /* 0x11 */ (short) 0x82, /* 0x12 */ (short) 0xc9, /* 0x13 */ (short) 0x7d, /* 0x14 */ (short) 0xfa, /* 0x15 */ (short) 0x59, /* 0x16 */ (short) 0x47, /* 0x17 */ (short) 0xf0, /* 0x18 */ (short) 0xad, /* 0x19 */ (short) 0xd4, /* 0x1A */ (short) 0xa2, /* 0x1B */ (short) 0xaf, /* 0x1C */ (short) 0x9c, /* 0x1D */ (short) 0xa4, /* 0x1E */ (short) 0x72, /* 0x1F */ (short) 0xc0, /* 0x20 */ (short) 0xb7, /* 0x21 */ (short) 0xfd, /* 0x22 */ (short) 0x93, /* 0x23 */ (short) 0x26, /* 0x24 */ (short) 0x36, /* 0x25 */ (short) 0x3f, /* 0x26 */ (short) 0xf7, /* 0x27 */ (short) 0xcc, /* 0x28 */ (short) 0x34, /* 0x29 */ (short) 0xa5, /* 0x2A */ (short) 0xe5, /* 0x2B */ (short) 0xf1, /* 0x2C */ (short) 0x71, /* 0x2D */ (short) 0xd8, /* 0x2E */ (short) 0x31, /* 0x2F */ (short) 0x15, /* 0x30 */ (short) 0x04, /* 0x31 */ (short) 0xc7, /* 0x32 */ (short) 0x23, /* 0x33 */ (short) 0xc3, /* 0x34 */ (short) 0x18, /* 0x35 */ (short) 0x96, /* 0x36 */ (short) 0x05, /* 0x37 */ (short) 0x9a, /* 0x38 */ (short) 0x07, /* 0x39 */ (short) 0x12, /* 0x3A */ (short) 0x80, /* 0x3B */ (short) 0xe2, /* 0x3C */ (short) 0xeb, /* 0x3D */ (short) 0x27, /* 0x3E */ (short) 0xb2, /* 0x3F */ (short) 0x75, /* 0x40 */ (short) 0x09, /* 0x41 */ (short) 0x83, /* 0x42 */ (short) 0x2c, /* 0x43 */ (short) 0x1a, /* 0x44 */ (short) 0x1b, /* 0x45 */ (short) 0x6e, /* 0x46 */ (short) 0x5a, /* 0x47 */ (short) 0xa0, /* 0x48 */ (short) 0x52, /* 0x49 */ (short) 0x3b, /* 0x4A */ (short) 0xd6, /* 0x4B */ (short) 0xb3, /* 0x4C */ (short) 0x29, /* 0x4D */ (short) 0xe3, /* 0x4E */ (short) 0x2f, /* 0x4F */ (short) 0x84, /* 0x50 */ (short) 0x53, /* 0x51 */ (short) 0xd1, /* 0x52 */ (short) 0x00, /* 0x53 */ (short) 0xed, /* 0x54 */ (short) 0x20, /* 0x55 */ (short) 0xfc, /* 0x56 */ (short) 0xb1, /* 0x57 */ (short) 0x5b, /* 0x58 */ (short) 0x6a, /* 0x59 */ (short) 0xcb, /* 0x5A */ (short) 0xbe, /* 0x5B */ (short) 0x39, /* 0x5C */ (short) 0x4a, /* 0x5D */ (short) 0x4c, /* 0x5E */ (short) 0x58, /* 0x5F */ (short) 0xcf, /* 0x60 */ (short) 0xd0, /* 0x61 */ (short) 0xef, /* 0x62 */ (short) 0xaa, /* 0x63 */ (short) 0xfb, /* 0x64 */ (short) 0x43, /* 0x65 */ (short) 0x4d, /* 0x66 */ (short) 0x33, /* 0x67 */ (short) 0x85, /* 0x68 */ (short) 0x45, /* 0x69 */ (short) 0xf9, /* 0x6A */ (short) 0x02, /* 0x6B */ (short) 0x7f, /* 0x6C */ (short) 0x50, /* 0x6D */ (short) 0x3c, /* 0x6E */ (short) 0x9f, /* 0x6F */ (short) 0xa8, /* 0x70 */ (short) 0x51, /* 0x71 */ (short) 0xa3, /* 0x72 */ (short) 0x40, /* 0x73 */ (short) 0x8f, /* 0x74 */ (short) 0x92, /* 0x75 */ (short) 0x9d, /* 0x76 */ (short) 0x38, /* 0x77 */ (short) 0xf5, /* 0x78 */ (short) 0xbc, /* 0x79 */ (short) 0xb6, /* 0x7A */ (short) 0xda, /* 0x7B */ (short) 0x21, /* 0x7C */ (short) 0x10, /* 0x7D */ (short) 0xff, /* 0x7E */ (short) 0xf3, /* 0x7F */ (short) 0xd2, /* 0x80 */ (short) 0xcd, /* 0x81 */ (short) 0x0c, /* 0x82 */ (short) 0x13, /* 0x83 */ (short) 0xec, /* 0x84 */ (short) 0x5f, /* 0x85 */ (short) 0x97, /* 0x86 */ (short) 0x44, /* 0x87 */ (short) 0x17, /* 0x88 */ (short) 0xc4, /* 0x89 */ (short) 0xa7, /* 0x8A */ (short) 0x7e, /* 0x8B */ (short) 0x3d, /* 0x8C */ (short) 0x64, /* 0x8D */ (short) 0x5d, /* 0x8E */ (short) 0x19, /* 0x8F */ (short) 0x73, /* 0x90 */ (short) 0x60, /* 0x91 */ (short) 0x81, /* 0x92 */ (short) 0x4f, /* 0x93 */ (short) 0xdc, /* 0x94 */ (short) 0x22, /* 0x95 */ (short) 0x2a, /* 0x96 */ (short) 0x90, /* 0x97 */ (short) 0x88, /* 0x98 */ (short) 0x46, /* 0x99 */ (short) 0xee, /* 0x9A */ (short) 0xb8, /* 0x9B */ (short) 0x14, /* 0x9C */ (short) 0xde, /* 0x9D */ (short) 0x5e, /* 0x9E */ (short) 0x0b, /* 0x9F */ (short) 0xdb, /* 0xA0 */ (short) 0xe0, /* 0xA1 */ (short) 0x32, /* 0xA2 */ (short) 0x3a, /* 0xA3 */ (short) 0x0a, /* 0xA4 */ (short) 0x49, /* 0xA5 */ (short) 0x06, /* 0xA6 */ (short) 0x24, /* 0xA7 */ (short) 0x5c, /* 0xA8 */ (short) 0xc2, /* 0xA9 */ (short) 0xd3, /* 0xAA */ (short) 0xac, /* 0xAB */ (short) 0x62, /* 0xAC */ (short) 0x91, /* 0xAD */ (short) 0x95, /* 0xAE */ (short) 0xe4, /* 0xAF */ (short) 0x79, /* 0xB0 */ (short) 0xe7, /* 0xB1 */ (short) 0xc8, /* 0xB2 */ (short) 0x37, /* 0xB3 */ (short) 0x6d, /* 0xB4 */ (short) 0x8d, /* 0xB5 */ (short) 0xd5, /* 0xB6 */ (short) 0x4e, /* 0xB7 */ (short) 0xa9, /* 0xB8 */ (short) 0x6c, /* 0xB9 */ (short) 0x56, /* 0xBA */ (short) 0xf4, /* 0xBB */ (short) 0xea, /* 0xBC */ (short) 0x65, /* 0xBD */ (short) 0x7a, /* 0xBE */ (short) 0xae, /* 0xBF */ (short) 0x08, /* 0xC0 */ (short) 0xba, /* 0xC1 */ (short) 0x78, /* 0xC2 */ (short) 0x25, /* 0xC3 */ (short) 0x2e, /* 0xC4 */ (short) 0x1c, /* 0xC5 */ (short) 0xa6, /* 0xC6 */ (short) 0xb4, /* 0xC7 */ (short) 0xc6, /* 0xC8 */ (short) 0xe8, /* 0xC9 */ (short) 0xdd, /* 0xCA */ (short) 0x74, /* 0xCB */ (short) 0x1f, /* 0xCC */ (short) 0x4b, /* 0xCD */ (short) 0xbd, /* 0xCE */ (short) 0x8b, /* 0xCF */ (short) 0x8a, /* 0xD0 */ (short) 0x70, /* 0xD1 */ (short) 0x3e, /* 0xD2 */ (short) 0xb5, /* 0xD3 */ (short) 0x66, /* 0xD4 */ (short) 0x48, /* 0xD5 */ (short) 0x03, /* 0xD6 */ (short) 0xf6, /* 0xD7 */ (short) 0x0e, /* 0xD8 */ (short) 0x61, /* 0xD9 */ (short) 0x35, /* 0xDA */ (short) 0x57, /* 0xDB */ (short) 0xb9, /* 0xDC */ (short) 0x86, /* 0xDD */ (short) 0xc1, /* 0xDE */ (short) 0x1d, /* 0xDF */ (short) 0x9e, /* 0xE0 */ (short) 0xe1, /* 0xE1 */ (short) 0xf8, /* 0xE2 */ (short) 0x98, /* 0xE3 */ (short) 0x11, /* 0xE4 */ (short) 0x69, /* 0xE5 */ (short) 0xd9, /* 0xE6 */ (short) 0x8e, /* 0xE7 */ (short) 0x94, /* 0xE8 */ (short) 0x9b, /* 0xE9 */ (short) 0x1e, /* 0xEA */ (short) 0x87, /* 0xEB */ (short) 0xe9, /* 0xEC */ (short) 0xce, /* 0xED */ (short) 0x55, /* 0xEE */ (short) 0x28, /* 0xEF */ (short) 0xdf, /* 0xF0 */ (short) 0x8c, /* 0xF1 */ (short) 0xa1, /* 0xF2 */ (short) 0x89, /* 0xF3 */ (short) 0x0d, /* 0xF4 */ (short) 0xbf, /* 0xF5 */ (short) 0xe6, /* 0xF6 */ (short) 0x42, /* 0xF7 */ (short) 0x68, /* 0xF8 */ (short) 0x41, /* 0xF9 */ (short) 0x99, /* 0xFA */ (short) 0x2d, /* 0xFB */ (short) 0x0f, /* 0xFC */ (short) 0xb0, /* 0xFD */ (short) 0x54, /* 0xFE */ (short) 0xbb, /* 0xFF */ (short) 0x16, }; /** * Table for computing the xtime function. To apply the xtime function to a * short i, write xtime [i]. */ private static final short[] xtime = new short[] { /* 0x00 */ (short) 0x00, /* 0x01 */ (short) 0x02, /* 0x02 */ (short) 0x04, /* 0x03 */ (short) 0x06, /* 0x04 */ (short) 0x08, /* 0x05 */ (short) 0x0A, /* 0x06 */ (short) 0x0C, /* 0x07 */ (short) 0x0E, /* 0x08 */ (short) 0x10, /* 0x09 */ (short) 0x12, /* 0x0A */ (short) 0x14, /* 0x0B */ (short) 0x16, /* 0x0C */ (short) 0x18, /* 0x0D */ (short) 0x1A, /* 0x0E */ (short) 0x1C, /* 0x0F */ (short) 0x1E, /* 0x10 */ (short) 0x20, /* 0x11 */ (short) 0x22, /* 0x12 */ (short) 0x24, /* 0x13 */ (short) 0x26, /* 0x14 */ (short) 0x28, /* 0x15 */ (short) 0x2A, /* 0x16 */ (short) 0x2C, /* 0x17 */ (short) 0x2E, /* 0x18 */ (short) 0x30, /* 0x19 */ (short) 0x32, /* 0x1A */ (short) 0x34, /* 0x1B */ (short) 0x36, /* 0x1C */ (short) 0x38, /* 0x1D */ (short) 0x3A, /* 0x1E */ (short) 0x3C, /* 0x1F */ (short) 0x3E, /* 0x20 */ (short) 0x40, /* 0x21 */ (short) 0x42, /* 0x22 */ (short) 0x44, /* 0x23 */ (short) 0x46, /* 0x24 */ (short) 0x48, /* 0x25 */ (short) 0x4A, /* 0x26 */ (short) 0x4C, /* 0x27 */ (short) 0x4E, /* 0x28 */ (short) 0x50, /* 0x29 */ (short) 0x52, /* 0x2A */ (short) 0x54, /* 0x2B */ (short) 0x56, /* 0x2C */ (short) 0x58, /* 0x2D */ (short) 0x5A, /* 0x2E */ (short) 0x5C, /* 0x2F */ (short) 0x5E, /* 0x30 */ (short) 0x60, /* 0x31 */ (short) 0x62, /* 0x32 */ (short) 0x64, /* 0x33 */ (short) 0x66, /* 0x34 */ (short) 0x68, /* 0x35 */ (short) 0x6A, /* 0x36 */ (short) 0x6C, /* 0x37 */ (short) 0x6E, /* 0x38 */ (short) 0x70, /* 0x39 */ (short) 0x72, /* 0x3A */ (short) 0x74, /* 0x3B */ (short) 0x76, /* 0x3C */ (short) 0x78, /* 0x3D */ (short) 0x7A, /* 0x3E */ (short) 0x7C, /* 0x3F */ (short) 0x7E, /* 0x40 */ (short) 0x80, /* 0x41 */ (short) 0x82, /* 0x42 */ (short) 0x84, /* 0x43 */ (short) 0x86, /* 0x44 */ (short) 0x88, /* 0x45 */ (short) 0x8A, /* 0x46 */ (short) 0x8C, /* 0x47 */ (short) 0x8E, /* 0x48 */ (short) 0x90, /* 0x49 */ (short) 0x92, /* 0x4A */ (short) 0x94, /* 0x4B */ (short) 0x96, /* 0x4C */ (short) 0x98, /* 0x4D */ (short) 0x9A, /* 0x4E */ (short) 0x9C, /* 0x4F */ (short) 0x9E, /* 0x50 */ (short) 0xA0, /* 0x51 */ (short) 0xA2, /* 0x52 */ (short) 0xA4, /* 0x53 */ (short) 0xA6, /* 0x54 */ (short) 0xA8, /* 0x55 */ (short) 0xAA, /* 0x56 */ (short) 0xAC, /* 0x57 */ (short) 0xAE, /* 0x58 */ (short) 0xB0, /* 0x59 */ (short) 0xB2, /* 0x5A */ (short) 0xB4, /* 0x5B */ (short) 0xB6, /* 0x5C */ (short) 0xB8, /* 0x5D */ (short) 0xBA, /* 0x5E */ (short) 0xBC, /* 0x5F */ (short) 0xBE, /* 0x60 */ (short) 0xC0, /* 0x61 */ (short) 0xC2, /* 0x62 */ (short) 0xC4, /* 0x63 */ (short) 0xC6, /* 0x64 */ (short) 0xC8, /* 0x65 */ (short) 0xCA, /* 0x66 */ (short) 0xCC, /* 0x67 */ (short) 0xCE, /* 0x68 */ (short) 0xD0, /* 0x69 */ (short) 0xD2, /* 0x6A */ (short) 0xD4, /* 0x6B */ (short) 0xD6, /* 0x6C */ (short) 0xD8, /* 0x6D */ (short) 0xDA, /* 0x6E */ (short) 0xDC, /* 0x6F */ (short) 0xDE, /* 0x70 */ (short) 0xE0, /* 0x71 */ (short) 0xE2, /* 0x72 */ (short) 0xE4, /* 0x73 */ (short) 0xE6, /* 0x74 */ (short) 0xE8, /* 0x75 */ (short) 0xEA, /* 0x76 */ (short) 0xEC, /* 0x77 */ (short) 0xEE, /* 0x78 */ (short) 0xF0, /* 0x79 */ (short) 0xF2, /* 0x7A */ (short) 0xF4, /* 0x7B */ (short) 0xF6, /* 0x7C */ (short) 0xF8, /* 0x7D */ (short) 0xFA, /* 0x7E */ (short) 0xFC, /* 0x7F */ (short) 0xFE, /* 0x80 */ (short) 0x1B, /* 0x81 */ (short) 0x19, /* 0x82 */ (short) 0x1F, /* 0x83 */ (short) 0x1D, /* 0x84 */ (short) 0x13, /* 0x85 */ (short) 0x11, /* 0x86 */ (short) 0x17, /* 0x87 */ (short) 0x15, /* 0x88 */ (short) 0x0B, /* 0x89 */ (short) 0x09, /* 0x8A */ (short) 0x0F, /* 0x8B */ (short) 0x0D, /* 0x8C */ (short) 0x03, /* 0x8D */ (short) 0x01, /* 0x8E */ (short) 0x07, /* 0x8F */ (short) 0x05, /* 0x90 */ (short) 0x3B, /* 0x91 */ (short) 0x39, /* 0x92 */ (short) 0x3F, /* 0x93 */ (short) 0x3D, /* 0x94 */ (short) 0x33, /* 0x95 */ (short) 0x31, /* 0x96 */ (short) 0x37, /* 0x97 */ (short) 0x35, /* 0x98 */ (short) 0x2B, /* 0x99 */ (short) 0x29, /* 0x9A */ (short) 0x2F, /* 0x9B */ (short) 0x2D, /* 0x9C */ (short) 0x23, /* 0x9D */ (short) 0x21, /* 0x9E */ (short) 0x27, /* 0x9F */ (short) 0x25, /* 0xA0 */ (short) 0x5B, /* 0xA1 */ (short) 0x59, /* 0xA2 */ (short) 0x5F, /* 0xA3 */ (short) 0x5D, /* 0xA4 */ (short) 0x53, /* 0xA5 */ (short) 0x51, /* 0xA6 */ (short) 0x57, /* 0xA7 */ (short) 0x55, /* 0xA8 */ (short) 0x4B, /* 0xA9 */ (short) 0x49, /* 0xAA */ (short) 0x4F, /* 0xAB */ (short) 0x4D, /* 0xAC */ (short) 0x43, /* 0xAD */ (short) 0x41, /* 0xAE */ (short) 0x47, /* 0xAF */ (short) 0x45, /* 0xB0 */ (short) 0x7B, /* 0xB1 */ (short) 0x79, /* 0xB2 */ (short) 0x7F, /* 0xB3 */ (short) 0x7D, /* 0xB4 */ (short) 0x73, /* 0xB5 */ (short) 0x71, /* 0xB6 */ (short) 0x77, /* 0xB7 */ (short) 0x75, /* 0xB8 */ (short) 0x6B, /* 0xB9 */ (short) 0x69, /* 0xBA */ (short) 0x6F, /* 0xBB */ (short) 0x6D, /* 0xBC */ (short) 0x63, /* 0xBD */ (short) 0x61, /* 0xBE */ (short) 0x67, /* 0xBF */ (short) 0x65, /* 0xC0 */ (short) 0x9B, /* 0xC1 */ (short) 0x99, /* 0xC2 */ (short) 0x9F, /* 0xC3 */ (short) 0x9D, /* 0xC4 */ (short) 0x93, /* 0xC5 */ (short) 0x91, /* 0xC6 */ (short) 0x97, /* 0xC7 */ (short) 0x95, /* 0xC8 */ (short) 0x8B, /* 0xC9 */ (short) 0x89, /* 0xCA */ (short) 0x8F, /* 0xCB */ (short) 0x8D, /* 0xCC */ (short) 0x83, /* 0xCD */ (short) 0x81, /* 0xCE */ (short) 0x87, /* 0xCF */ (short) 0x85, /* 0xD0 */ (short) 0xBB, /* 0xD1 */ (short) 0xB9, /* 0xD2 */ (short) 0xBF, /* 0xD3 */ (short) 0xBD, /* 0xD4 */ (short) 0xB3, /* 0xD5 */ (short) 0xB1, /* 0xD6 */ (short) 0xB7, /* 0xD7 */ (short) 0xB5, /* 0xD8 */ (short) 0xAB, /* 0xD9 */ (short) 0xA9, /* 0xDA */ (short) 0xAF, /* 0xDB */ (short) 0xAD, /* 0xDC */ (short) 0xA3, /* 0xDD */ (short) 0xA1, /* 0xDE */ (short) 0xA7, /* 0xDF */ (short) 0xA5, /* 0xE0 */ (short) 0xDB, /* 0xE1 */ (short) 0xD9, /* 0xE2 */ (short) 0xDF, /* 0xE3 */ (short) 0xDD, /* 0xE4 */ (short) 0xD3, /* 0xE5 */ (short) 0xD1, /* 0xE6 */ (short) 0xD7, /* 0xE7 */ (short) 0xD5, /* 0xE8 */ (short) 0xCB, /* 0xE9 */ (short) 0xC9, /* 0xEA */ (short) 0xCF, /* 0xEB */ (short) 0xCD, /* 0xEC */ (short) 0xC3, /* 0xED */ (short) 0xC1, /* 0xEE */ (short) 0xC7, /* 0xEF */ (short) 0xC5, /* 0xF0 */ (short) 0xFB, /* 0xF1 */ (short) 0xF9, /* 0xF2 */ (short) 0xFF, /* 0xF3 */ (short) 0xFD, /* 0xF4 */ (short) 0xF3, /* 0xF5 */ (short) 0xF1, /* 0xF6 */ (short) 0xF7, /* 0xF7 */ (short) 0xF5, /* 0xF8 */ (short) 0xEB, /* 0xF9 */ (short) 0xE9, /* 0xFA */ (short) 0xEF, /* 0xFB */ (short) 0xED, /* 0xFC */ (short) 0xE3, /* 0xFD */ (short) 0xE1, /* 0xFE */ (short) 0xE7, /* 0xFF */ (short) 0xE5, }; // Hidden helper classes. /** * The round key: a 4x4 array of bytes (represented as ints). The bytes are * declared as separate fields rather than an array to avoid the overhead of * array indexing. */ private static class RoundKey { public int key00, key01, key02, key03; public int key10, key11, key12, key13; public int key20, key21, key22, key23; public int key30, key31, key32, key33; // 128 bytes of padding, to avert cache interference when running on an // SMP parallel computer. private long p0, p1, p2, p3, p4, p5, p6, p7; private long p8, p9, pa, pb, pc, pd, pe, pf; public void erase() { key00 = 0; key01 = 0; key02 = 0; key03 = 0; key10 = 0; key11 = 0; key12 = 0; key13 = 0; key20 = 0; key21 = 0; key22 = 0; key23 = 0; key30 = 0; key31 = 0; key32 = 0; key33 = 0; } } // Hidden data members. /** * The state: a 4x4 array of bytes (represented as ints). The bytes are * declared as separate fields rather than an array to avoid the overhead of * array indexing. */ private int state00, state01, state02, state03; private int state10, state11, state12, state13; private int state20, state21, state22, state23; private int state30, state31, state32, state33; /** * The expanded key: an array of round keys derived from the encryption key * using the key schedule. */ private RoundKey[] expandedKey; // 128 bytes of padding, to avert cache interference when running on an // SMP parallel computer. private long p0, p1, p2, p3, p4, p5, p6, p7; private long p8, p9, pa, pb, pc, pd, pe, pf; // Exported constructors. /** * Construct a new AES-256 cipher object with the given secret key. After * the constructor returns, theKey is no longer needed and may be * erased (set to all 0s). The length of theKey must be at least * 32. Only the first 32 bytes are used. * * @param theKey Key (byte array). * * @exception NullPointerException * (unchecked exception) Thrown if theKey is null. * @exception IllegalArgumentException * (unchecked exception) Thrown if theKey.length < 32. */ public AES256CipherSmp (byte[] theKey) { super (16, 32); setKey (theKey); } // Exported operations. /** * Set the key to be used for all subsequent encryptions and decryptions. * After this method returns, theKey is no longer needed and may be * erased (set to all 0s). The length of theKey must be at least * 32. Only the first 32 bytes are used. * * @param theKey Key (byte array). * * @exception NullPointerException * (unchecked exception) Thrown if theKey is null. * @exception IllegalArgumentException * (unchecked exception) Thrown if theKey.length < 32. */ public void setKey (byte[] theKey) { // Verify arguments. if (theKey.length < 32) { throw new IllegalArgumentException ("Key is not 32 bytes"); } // Allocate storage for round keys if necessary. if (expandedKey == null) { expandedKey = new RoundKey [ROUND_KEY_COUNT+32]; // extra padding for (int i = 0; i < ROUND_KEY_COUNT; ++ i) { expandedKey[i] = new RoundKey(); } } // Fill in first two round keys from theKey. RoundKey roundKey; roundKey = expandedKey[0]; roundKey.key00 = theKey[ 0] & 0xFF; roundKey.key10 = theKey[ 1] & 0xFF; roundKey.key20 = theKey[ 2] & 0xFF; roundKey.key30 = theKey[ 3] & 0xFF; roundKey.key01 = theKey[ 4] & 0xFF; roundKey.key11 = theKey[ 5] & 0xFF; roundKey.key21 = theKey[ 6] & 0xFF; roundKey.key31 = theKey[ 7] & 0xFF; roundKey.key02 = theKey[ 8] & 0xFF; roundKey.key12 = theKey[ 9] & 0xFF; roundKey.key22 = theKey[10] & 0xFF; roundKey.key32 = theKey[11] & 0xFF; roundKey.key03 = theKey[12] & 0xFF; roundKey.key13 = theKey[13] & 0xFF; roundKey.key23 = theKey[14] & 0xFF; roundKey.key33 = theKey[15] & 0xFF; roundKey = expandedKey[1]; roundKey.key00 = theKey[16] & 0xFF; roundKey.key10 = theKey[17] & 0xFF; roundKey.key20 = theKey[18] & 0xFF; roundKey.key30 = theKey[19] & 0xFF; roundKey.key01 = theKey[20] & 0xFF; roundKey.key11 = theKey[21] & 0xFF; roundKey.key21 = theKey[22] & 0xFF; roundKey.key31 = theKey[23] & 0xFF; roundKey.key02 = theKey[24] & 0xFF; roundKey.key12 = theKey[25] & 0xFF; roundKey.key22 = theKey[26] & 0xFF; roundKey.key32 = theKey[27] & 0xFF; roundKey.key03 = theKey[28] & 0xFF; roundKey.key13 = theKey[29] & 0xFF; roundKey.key23 = theKey[30] & 0xFF; roundKey.key33 = theKey[31] & 0xFF; // Fill in remaining round keys. int rcon = 1; for (int i = 2; i < 14; i += 2) { advanceRoundKey (expandedKey[i-2], expandedKey[i-1], expandedKey[i], rcon); rcon = xtime [rcon]; advanceRoundKey (expandedKey[i-1], expandedKey[i], expandedKey[i+1]); } advanceRoundKey (expandedKey[12], expandedKey[13], expandedKey[14], rcon); } /** * Encrypt the given plaintext block. On input, thePlaintext * contains the plaintext. On output, the contents of theCiphertext * have been replaced by the ciphertext. thePlaintext and * theCiphertext may be the same block. The length of * thePlaintext must be at least 16. Only the first 16 bytes are * read. The length of theCiphertext must be at least 16. Only the * first 16 bytes are written. * * @param thePlaintext Input plaintext block to be encrypted. * @param theCiphertext Output ciphertext block. * * @exception NullPointerException * (unchecked exception) Thrown if thePlaintext is null or * theCiphertext is null. * @exception IllegalArgumentException * (unchecked exception) Thrown if thePlaintext.length < 16 * or theCiphertext.length < 16. * @exception IllegalStateException * (unchecked exception) Thrown if the key has been erased and not * re-set. */ public void encrypt (byte[] thePlaintext, byte[] theCiphertext) { int i; // Verify preconditions. if (thePlaintext.length < 16) { throw new IllegalArgumentException ("thePlaintext is not 16 bytes"); } if (theCiphertext.length < 16) { throw new IllegalArgumentException ("theCiphertext is not 16 bytes"); } if (expandedKey == null) { throw new IllegalArgumentException ("Key is not set"); } // Initialize the state. state00 = thePlaintext[ 0] & 0xFF; state10 = thePlaintext[ 1] & 0xFF; state20 = thePlaintext[ 2] & 0xFF; state30 = thePlaintext[ 3] & 0xFF; state01 = thePlaintext[ 4] & 0xFF; state11 = thePlaintext[ 5] & 0xFF; state21 = thePlaintext[ 6] & 0xFF; state31 = thePlaintext[ 7] & 0xFF; state02 = thePlaintext[ 8] & 0xFF; state12 = thePlaintext[ 9] & 0xFF; state22 = thePlaintext[10] & 0xFF; state32 = thePlaintext[11] & 0xFF; state03 = thePlaintext[12] & 0xFF; state13 = thePlaintext[13] & 0xFF; state23 = thePlaintext[14] & 0xFF; state33 = thePlaintext[15] & 0xFF; // Do the first 13 rounds. for (i = 0; i < 13; ++ i) { addRoundKeyByteSubShiftRow (expandedKey[i]); mixColumn(); } // Do the 14th round. addRoundKeyByteSubShiftRow (expandedKey[13]); addRoundKey (expandedKey[14]); // Output encrypted message. theCiphertext[ 0] = (byte) state00; theCiphertext[ 1] = (byte) state10; theCiphertext[ 2] = (byte) state20; theCiphertext[ 3] = (byte) state30; theCiphertext[ 4] = (byte) state01; theCiphertext[ 5] = (byte) state11; theCiphertext[ 6] = (byte) state21; theCiphertext[ 7] = (byte) state31; theCiphertext[ 8] = (byte) state02; theCiphertext[ 9] = (byte) state12; theCiphertext[10] = (byte) state22; theCiphertext[11] = (byte) state32; theCiphertext[12] = (byte) state03; theCiphertext[13] = (byte) state13; theCiphertext[14] = (byte) state23; theCiphertext[15] = (byte) state33; } /** * Erase this block cipher object's key material. */ public void erase() { state00 = 0; state01 = 0; state02 = 0; state03 = 0; state10 = 0; state11 = 0; state12 = 0; state13 = 0; state20 = 0; state21 = 0; state22 = 0; state23 = 0; state30 = 0; state31 = 0; state32 = 0; state33 = 0; if (expandedKey != null) { for (int i = 0; i < ROUND_KEY_COUNT; ++ i) { expandedKey[i].erase(); expandedKey[i] = null; } expandedKey = null; } } /** * Finalize this block cipher object. This block cipher object is erased if * it is not already erased. */ protected void finalize() { erase(); } // Hidden operations. /** * Compute the next round key from the previous round key and the round * constant. */ private static void advanceRoundKey (RoundKey prevprev, RoundKey prev, RoundKey next, int rcon) { // Column 0. next.key00 = prevprev.key00 ^ byteSub [prev.key13] ^ rcon; next.key10 = prevprev.key10 ^ byteSub [prev.key23]; next.key20 = prevprev.key20 ^ byteSub [prev.key33]; next.key30 = prevprev.key30 ^ byteSub [prev.key03]; // Column 1. next.key01 = prevprev.key01 ^ next.key00; next.key11 = prevprev.key11 ^ next.key10; next.key21 = prevprev.key21 ^ next.key20; next.key31 = prevprev.key31 ^ next.key30; // Column 2. next.key02 = prevprev.key02 ^ next.key01; next.key12 = prevprev.key12 ^ next.key11; next.key22 = prevprev.key22 ^ next.key21; next.key32 = prevprev.key32 ^ next.key31; // Column 3. next.key03 = prevprev.key03 ^ next.key02; next.key13 = prevprev.key13 ^ next.key12; next.key23 = prevprev.key23 ^ next.key22; next.key33 = prevprev.key33 ^ next.key32; } /** * Compute the next round key from the previous round key. */ private static void advanceRoundKey (RoundKey prevprev, RoundKey prev, RoundKey next) { // Column 0. next.key00 = prevprev.key00 ^ byteSub [prev.key03]; next.key10 = prevprev.key10 ^ byteSub [prev.key13]; next.key20 = prevprev.key20 ^ byteSub [prev.key23]; next.key30 = prevprev.key30 ^ byteSub [prev.key33]; // Column 1. next.key01 = prevprev.key01 ^ next.key00; next.key11 = prevprev.key11 ^ next.key10; next.key21 = prevprev.key21 ^ next.key20; next.key31 = prevprev.key31 ^ next.key30; // Column 2. next.key02 = prevprev.key02 ^ next.key01; next.key12 = prevprev.key12 ^ next.key11; next.key22 = prevprev.key22 ^ next.key21; next.key32 = prevprev.key32 ^ next.key31; // Column 3. next.key03 = prevprev.key03 ^ next.key02; next.key13 = prevprev.key13 ^ next.key12; next.key23 = prevprev.key23 ^ next.key22; next.key33 = prevprev.key33 ^ next.key32; } /** * To each byte of the state, add the corresponding byte of the round key. */ private void addRoundKey (RoundKey roundKey) { state00 ^= roundKey.key00; state01 ^= roundKey.key01; state02 ^= roundKey.key02; state03 ^= roundKey.key03; state10 ^= roundKey.key10; state11 ^= roundKey.key11; state12 ^= roundKey.key12; state13 ^= roundKey.key13; state20 ^= roundKey.key20; state21 ^= roundKey.key21; state22 ^= roundKey.key22; state23 ^= roundKey.key23; state30 ^= roundKey.key30; state31 ^= roundKey.key31; state32 ^= roundKey.key32; state33 ^= roundKey.key33; } /** * To each byte of the state, add the corresponding byte of the round key, * apply the S-box, and shift the state row. */ private void addRoundKeyByteSubShiftRow (RoundKey roundKey) { int temp; // Row 0: No shift. state00 = byteSub [state00 ^ roundKey.key00]; state01 = byteSub [state01 ^ roundKey.key01]; state02 = byteSub [state02 ^ roundKey.key02]; state03 = byteSub [state03 ^ roundKey.key03]; // Row 1: Left circular shift 1 byte. temp = state10; state10 = byteSub [state11 ^ roundKey.key11]; state11 = byteSub [state12 ^ roundKey.key12]; state12 = byteSub [state13 ^ roundKey.key13]; state13 = byteSub [temp ^ roundKey.key10]; // Row 2: Left circular shift 2 bytes. temp = state20; state20 = byteSub [state22 ^ roundKey.key22]; state22 = byteSub [temp ^ roundKey.key20]; temp = state21; state21 = byteSub [state23 ^ roundKey.key23]; state23 = byteSub [temp ^ roundKey.key21]; // Row 3: Left circular shift 3 bytes = right circular shift 1 byte. temp = state33; state33 = byteSub [state32 ^ roundKey.key32]; state32 = byteSub [state31 ^ roundKey.key31]; state31 = byteSub [state30 ^ roundKey.key30]; state30 = byteSub [temp ^ roundKey.key33]; } /** * Multiply each column of the state by a fixed polynomial, * 0x03 x^3 + 0x01 x^2 + 0x01 x + 0x02. */ private void mixColumn() { int temp, sum; // Column 0. temp = state00; sum = state00 ^ state10 ^ state20 ^ state30; state00 ^= xtime [state00 ^ state10] ^ sum; state10 ^= xtime [state10 ^ state20] ^ sum; state20 ^= xtime [state20 ^ state30] ^ sum; state30 ^= xtime [state30 ^ temp ] ^ sum; // Column 1. temp = state01; sum = state01 ^ state11 ^ state21 ^ state31; state01 ^= xtime [state01 ^ state11] ^ sum; state11 ^= xtime [state11 ^ state21] ^ sum; state21 ^= xtime [state21 ^ state31] ^ sum; state31 ^= xtime [state31 ^ temp ] ^ sum; // Column 2. temp = state02; sum = state02 ^ state12 ^ state22 ^ state32; state02 ^= xtime [state02 ^ state12] ^ sum; state12 ^= xtime [state12 ^ state22] ^ sum; state22 ^= xtime [state22 ^ state32] ^ sum; state32 ^= xtime [state32 ^ temp ] ^ sum; // Column 3. temp = state03; sum = state03 ^ state13 ^ state23 ^ state33; state03 ^= xtime [state03 ^ state13] ^ sum; state13 ^= xtime [state13 ^ state23] ^ sum; state23 ^= xtime [state23 ^ state33] ^ sum; state33 ^= xtime [state33 ^ temp ] ^ sum; } // Unit test main program. // /** // * Unit test main program. // */ // public static void main // (String[] args) // { // try // { // int i; // // // Verify command line arguments. // if (args.length != 2) // { // System.err.println ("Usage: java edu.rit.crypto.blockcipher.AES256CipherSmp "); // System.exit (1); // } // String keystring = args[0]; // String blockstring = args[1]; // // // Convert key string to bytes. // byte[] key = new byte[32]; // for (i = 0; i < 32; ++ i) // { // key[i] = (byte) // Integer.parseInt (keystring.substring (2*i, 2*i+2), 16); // } // // // Convert block string to bytes. // byte[] block = new byte[16]; // for (i = 0; i < 16; ++ i) // { // block[i] = (byte) // Integer.parseInt (blockstring.substring (2*i, 2*i+2), 16); // } // // // Create AES cipher object. // AES256CipherSmp bc = new AES256CipherSmp (key); // // // Dump key schedule. // System.out.println ("KEY SCHEDULE"); // for (i = 0; i < ROUND_KEY_COUNT; ++ i) // { // RoundKey roundkey = bc.expandedKey[i]; // System.out.print (4*i); // System.out.print ('\t'); // System.out.print (hexdigit [(roundkey.key00 >> 4) & 0xF]); // System.out.print (hexdigit [(roundkey.key00 ) & 0xF]); // System.out.print (hexdigit [(roundkey.key10 >> 4) & 0xF]); // System.out.print (hexdigit [(roundkey.key10 ) & 0xF]); // System.out.print (hexdigit [(roundkey.key20 >> 4) & 0xF]); // System.out.print (hexdigit [(roundkey.key20 ) & 0xF]); // System.out.print (hexdigit [(roundkey.key30 >> 4) & 0xF]); // System.out.print (hexdigit [(roundkey.key30 ) & 0xF]); // System.out.println(); // System.out.print (4*i+1); // System.out.print ('\t'); // System.out.print (hexdigit [(roundkey.key01 >> 4) & 0xF]); // System.out.print (hexdigit [(roundkey.key01 ) & 0xF]); // System.out.print (hexdigit [(roundkey.key11 >> 4) & 0xF]); // System.out.print (hexdigit [(roundkey.key11 ) & 0xF]); // System.out.print (hexdigit [(roundkey.key21 >> 4) & 0xF]); // System.out.print (hexdigit [(roundkey.key21 ) & 0xF]); // System.out.print (hexdigit [(roundkey.key31 >> 4) & 0xF]); // System.out.print (hexdigit [(roundkey.key31 ) & 0xF]); // System.out.println(); // System.out.print (4*i+2); // System.out.print ('\t'); // System.out.print (hexdigit [(roundkey.key02 >> 4) & 0xF]); // System.out.print (hexdigit [(roundkey.key02 ) & 0xF]); // System.out.print (hexdigit [(roundkey.key12 >> 4) & 0xF]); // System.out.print (hexdigit [(roundkey.key12 ) & 0xF]); // System.out.print (hexdigit [(roundkey.key22 >> 4) & 0xF]); // System.out.print (hexdigit [(roundkey.key22 ) & 0xF]); // System.out.print (hexdigit [(roundkey.key32 >> 4) & 0xF]); // System.out.print (hexdigit [(roundkey.key32 ) & 0xF]); // System.out.println(); // System.out.print (4*i+3); // System.out.print ('\t'); // System.out.print (hexdigit [(roundkey.key03 >> 4) & 0xF]); // System.out.print (hexdigit [(roundkey.key03 ) & 0xF]); // System.out.print (hexdigit [(roundkey.key13 >> 4) & 0xF]); // System.out.print (hexdigit [(roundkey.key13 ) & 0xF]); // System.out.print (hexdigit [(roundkey.key23 >> 4) & 0xF]); // System.out.print (hexdigit [(roundkey.key23 ) & 0xF]); // System.out.print (hexdigit [(roundkey.key33 >> 4) & 0xF]); // System.out.print (hexdigit [(roundkey.key33 ) & 0xF]); // System.out.println(); // } // // // Dump the plaintext. // System.out.println(); // System.out.println ("PLAINTEXT"); // for (i = 0; i < 16; ++ i) // { // System.out.print (hexdigit [(block[i] >> 4) & 0xF]); // System.out.print (hexdigit [(block[i] ) & 0xF]); // } // System.out.println(); // // // Encrypt the block. // bc.encrypt (block); // // // Dump the ciphertext. // System.out.println(); // System.out.println ("CIPHERTEXT"); // for (i = 0; i < 16; ++ i) // { // System.out.print (hexdigit [(block[i] >> 4) & 0xF]); // System.out.print (hexdigit [(block[i] ) & 0xF]); // } // System.out.println(); // } // // catch (Throwable exc) // { // System.err.println ("AES256CipherSmp: Uncaught exception"); // exc.printStackTrace (System.err); // System.exit (1); // } // } // // private static final char[] hexdigit = new char[] // {'0', '1', '2', '3', '4', '5', '6', '7', // '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; }

Ads help maintain this website.