jdk/src/share/classes/com/sun/crypto/provider/AESCrypt.java
changeset 13559 17445744f2af
parent 10336 0bb1999251f8
equal deleted inserted replaced
13558:3fb57310d83b 13559:17445744f2af
     1 /*
     1 /*
     2  * Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved.
     2  * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     7  * published by the Free Software Foundation.  Oracle designates this
    35  */
    35  */
    36 
    36 
    37 package com.sun.crypto.provider;
    37 package com.sun.crypto.provider;
    38 
    38 
    39 import java.security.InvalidKeyException;
    39 import java.security.InvalidKeyException;
       
    40 import java.util.Arrays;
    40 
    41 
    41 /**
    42 /**
    42  * Rijndael --pronounced Reindaal-- is a symmetric cipher with a 128-bit
    43  * Rijndael --pronounced Reindaal-- is a symmetric cipher with a 128-bit
    43  * block size and variable key-size (128-, 192- and 256-bit).
    44  * block size and variable key-size (128-, 192- and 256-bit).
    44  * <p>
    45  * <p>
    52 
    53 
    53     /** Session and Sub keys */
    54     /** Session and Sub keys */
    54     private Object[] sessionK = null;
    55     private Object[] sessionK = null;
    55     private int[] K = null;
    56     private int[] K = null;
    56 
    57 
    57     /** (ROUNDS-1) * 4 */
    58     /** Cipher encryption/decryption key */
       
    59     // skip re-generating Session and Sub keys if the cipher key is
       
    60     // the same
       
    61     private byte[] lastKey = null;
       
    62 
       
    63     /** ROUNDS * 4 */
    58     private int limit = 0;
    64     private int limit = 0;
    59 
    65 
    60     AESCrypt() {
    66     AESCrypt() {
    61         // empty
    67         // empty
    62     }
    68     }
    80         if (!isKeySizeValid(key.length)) {
    86         if (!isKeySizeValid(key.length)) {
    81             throw new InvalidKeyException("Invalid AES key length: " +
    87             throw new InvalidKeyException("Invalid AES key length: " +
    82                 key.length + " bytes");
    88                 key.length + " bytes");
    83         }
    89         }
    84 
    90 
    85         // generate session key and reset sub key.
    91         if (!Arrays.equals(key, lastKey)) {
    86         sessionK = makeKey(key);
    92             // re-generate session key 'sessionK' when cipher key changes
    87         setSubKey(decrypting);
    93             makeSessionKey(key);
    88     }
    94             lastKey = key.clone();  // save cipher key
    89 
    95         }
    90     private void setSubKey(boolean decrypting) {
    96 
    91         int[][] Kd = (int[][]) sessionK[decrypting ? 1 : 0];
    97         // set sub key to the corresponding session Key
    92         int rounds = Kd.length;
    98         this.K = (int[]) sessionK[(decrypting? 1:0)];
    93         this.K = new int[rounds*4];
    99     }
    94         for(int i=0; i<rounds; i++) {
   100 
       
   101     /**
       
   102      * Expand an int[(ROUNDS+1)][4] into int[(ROUNDS+1)*4].
       
   103      * For decryption round keys, need to rotate right by 4 ints.
       
   104      * @param kr The round keys for encryption or decryption.
       
   105      * @param decrypting True if 'kr' is for decryption and false otherwise.
       
   106      */
       
   107     private static final int[] expandToSubKey(int[][] kr, boolean decrypting) {
       
   108         int total = kr.length;
       
   109         int[] expK = new int[total*4];
       
   110         if (decrypting) {
       
   111             // decrypting, rotate right by 4 ints
       
   112             // i.e. i==0
    95             for(int j=0; j<4; j++) {
   113             for(int j=0; j<4; j++) {
    96                 K[i*4 + j] = Kd[i][j];
   114                 expK[j] = kr[total-1][j];
    97             }
   115             }
    98         }
   116             for(int i=1; i<total; i++) {
    99 
   117                 for(int j=0; j<4; j++) {
   100         if (decrypting) {
   118                     expK[i*4 + j] = kr[i-1][j];
   101             int j0 = K[K.length-4];
   119                 }
   102             int j1 = K[K.length-3];
   120             }
   103             int j2 = K[K.length-2];
   121         } else {
   104             int j3 = K[K.length-1];
   122             // encrypting, straight expansion
   105 
   123             for(int i=0; i<total; i++) {
   106             for (int i=this.K.length-1; i>3; i--) {
   124                 for(int j=0; j<4; j++) {
   107                 this.K[i] = this.K[i-4];
   125                     expK[i*4 + j] = kr[i][j];
   108             }
   126                 }
   109             K[0] = j0;
   127             }
   110             K[1] = j1;
   128         }
   111             K[2] = j2;
   129         return expK;
   112             K[3] = j3;
       
   113         }
       
   114 
       
   115         ROUNDS_12 = (rounds>=13);
       
   116         ROUNDS_14 = (rounds==15);
       
   117 
       
   118         rounds--;
       
   119         limit=rounds*4;
       
   120     }
   130     }
   121 
   131 
   122     private static int[]
   132     private static int[]
   123         alog = new int[256],
   133         alog = new int[256],
   124         log  = new int[256];
   134         log  = new int[256];
   564 
   574 
   565 
   575 
   566     /**
   576     /**
   567      * Expand a user-supplied key material into a session key.
   577      * Expand a user-supplied key material into a session key.
   568      *
   578      *
   569      * @param key The 128/192/256-bit user-key to use.
   579      * @param k The 128/192/256-bit cipher key to use.
   570      * @exception InvalidKeyException  If the key is invalid.
   580      * @exception InvalidKeyException  If the key is invalid.
   571      */
   581      */
   572     private static Object[] makeKey(byte[] k) throws InvalidKeyException {
   582     private void makeSessionKey(byte[] k) throws InvalidKeyException {
   573         if (k == null) {
   583         if (k == null) {
   574             throw new InvalidKeyException("Empty key");
   584             throw new InvalidKeyException("Empty key");
   575         }
   585         }
   576         if (!isKeySizeValid(k.length)) {
   586         if (!isKeySizeValid(k.length)) {
   577              throw new InvalidKeyException("Invalid AES key length: " +
   587              throw new InvalidKeyException("Invalid AES key length: " +
   637                            U2[(tt >>> 16) & 0xFF] ^
   647                            U2[(tt >>> 16) & 0xFF] ^
   638                            U3[(tt >>>  8) & 0xFF] ^
   648                            U3[(tt >>>  8) & 0xFF] ^
   639                            U4[ tt         & 0xFF];
   649                            U4[ tt         & 0xFF];
   640             }
   650             }
   641         }
   651         }
   642         // assemble the encryption (Ke) and decryption (Kd) round keys into
   652 
   643         // one sessionKey object
   653         // assemble the encryption (Ke) and decryption (Kd) round keys
   644         Object[] result = new Object[] {Ke, Kd};
   654         // and expand them into arrays of ints.
   645         return result;
   655         int[] expandedKe = expandToSubKey(Ke, false); // decrypting==false
       
   656         int[] expandedKd = expandToSubKey(Kd, true);  // decrypting==true
       
   657 
       
   658         ROUNDS_12 = (ROUNDS>=12);
       
   659         ROUNDS_14 = (ROUNDS==14);
       
   660         limit = ROUNDS*4;
       
   661 
       
   662         // store the expanded sub keys into 'sessionK'
       
   663         sessionK = new Object[] { expandedKe, expandedKd };
   646     }
   664     }
   647 
   665 
   648 
   666 
   649     /**
   667     /**
   650      * Return The number of rounds for a given Rijndael keysize.
   668      * Return The number of rounds for a given Rijndael keysize.