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. |