Frames | No Frames |
1: /* BasePad.java -- 2: Copyright (C) 2001, 2002, 2003, 2006, 2010 Free Software Foundation, Inc. 3: 4: This file is a part of GNU Classpath. 5: 6: GNU Classpath is free software; you can redistribute it and/or modify 7: it under the terms of the GNU General Public License as published by 8: the Free Software Foundation; either version 2 of the License, or (at 9: your option) any later version. 10: 11: GNU Classpath is distributed in the hope that it will be useful, but 12: WITHOUT ANY WARRANTY; without even the implied warranty of 13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14: General Public License for more details. 15: 16: You should have received a copy of the GNU General Public License 17: along with GNU Classpath; if not, write to the Free Software 18: Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 19: USA 20: 21: Linking this library statically or dynamically with other modules is 22: making a combined work based on this library. Thus, the terms and 23: conditions of the GNU General Public License cover the whole 24: combination. 25: 26: As a special exception, the copyright holders of this library give you 27: permission to link this library with independent modules to produce an 28: executable, regardless of the license terms of these independent 29: modules, and to copy and distribute the resulting executable under 30: terms of your choice, provided that you also meet, for each linked 31: independent module, the terms and conditions of the license of that 32: module. An independent module is a module which is not derived from 33: or based on this library. If you modify this library, you may extend 34: this exception to your version of the library, but you are not 35: obligated to do so. If you do not wish to do so, delete this 36: exception statement from your version. */ 37: 38: 39: package gnu.javax.crypto.pad; 40: 41: import gnu.java.lang.CPStringBuilder; 42: 43: import gnu.java.security.Configuration; 44: 45: import java.util.Map; 46: import java.util.logging.Level; 47: import java.util.logging.Logger; 48: 49: /** 50: * An abstract class to facilitate implementing padding algorithms. 51: */ 52: public abstract class BasePad 53: implements IPad 54: { 55: private static final Logger log = Configuration.DEBUG ? 56: Logger.getLogger(BasePad.class.getName()) : null; 57: /** The canonical name prefix of the padding algorithm. */ 58: protected String name; 59: /** The block size, in bytes, for this instance. */ 60: protected int blockSize; 61: 62: /** Trivial constructor for use by concrete subclasses. */ 63: protected BasePad(final String name) 64: { 65: super(); 66: 67: this.name = name; 68: blockSize = -1; 69: } 70: 71: public String name() 72: { 73: final CPStringBuilder sb = new CPStringBuilder(name); 74: if (blockSize != -1) 75: sb.append('-').append(String.valueOf(8 * blockSize)); 76: return sb.toString(); 77: } 78: 79: public void init(final int bs) throws IllegalStateException 80: { 81: if (blockSize != -1) 82: throw new IllegalStateException(); 83: blockSize = bs; 84: setup(); 85: } 86: 87: /** 88: * Initialises the algorithm with designated attributes. Names, valid and/or 89: * recognisable by all concrete implementations are described in {@link IPad} 90: * class documentation. Other algorithm-specific attributes MUST be documented 91: * in the implementation class of that padding algorithm. 92: * <p> 93: * For compatibility reasons, this method is not declared <i>abstract</i>. 94: * Furthermore, and unless overridden, the default implementation will throw 95: * an {@link UnsupportedOperationException}. Concrete padding algorithms MUST 96: * override this method if they wish to offer an initialisation method that 97: * allows for other than the padding block size parameter to be specified. 98: * 99: * @param attributes a set of name-value pairs that describes the desired 100: * future behaviour of this instance. 101: * @exception IllegalStateException if the instance is already initialised. 102: * @exception IllegalArgumentException if the block size value is invalid. 103: */ 104: public void init(Map attributes) throws IllegalStateException 105: { 106: throw new UnsupportedOperationException(); 107: } 108: 109: public void reset() 110: { 111: blockSize = -1; 112: } 113: 114: /** 115: * A default implementation of a correctness test that exercises the padder 116: * implementation, using block sizes varying from 2 to 256 bytes. 117: * 118: * @return <code>true</code> if the concrete implementation correctly unpads 119: * what it pads for all tested block sizes. Returns <code>false</code> 120: * if the test fails for any block size. 121: */ 122: public boolean selfTest() 123: { 124: final byte[] in = new byte[1024]; 125: for (int bs = 2; bs < 256; bs++) 126: if (! test1BlockSize(bs, in)) 127: return false; 128: return true; 129: } 130: 131: /** 132: * The basic symmetric test for a padder given a specific block size. 133: * <p> 134: * The code ensures that the implementation is capable of unpadding what it 135: * pads. 136: * 137: * @param size the block size to test. 138: * @param buffer a work buffer. It is exposed as an argument for this method 139: * to reduce un-necessary object allocations. 140: * @return <code>true</code> if the test passes; <code>false</code> 141: * otherwise. 142: */ 143: protected boolean test1BlockSize(int size, byte[] buffer) 144: { 145: byte[] padBytes; 146: final int offset = 5; 147: final int limit = buffer.length; 148: this.init(size); 149: for (int i = 0; i < limit - offset - blockSize; i++) 150: { 151: padBytes = pad(buffer, offset, i); 152: if (((i + padBytes.length) % blockSize) != 0) 153: { 154: if (Configuration.DEBUG) 155: log.log(Level.SEVERE, 156: "Length of padded text MUST be a multiple of " 157: + blockSize, new RuntimeException(name())); 158: return false; 159: } 160: System.arraycopy(padBytes, 0, buffer, offset + i, padBytes.length); 161: try 162: { 163: if (padBytes.length != unpad(buffer, offset, i + padBytes.length)) 164: { 165: if (Configuration.DEBUG) 166: log.log(Level.SEVERE, 167: "IPad [" + name() + "] failed symmetric operation", 168: new RuntimeException(name())); 169: return false; 170: } 171: } 172: catch (WrongPaddingException x) 173: { 174: if (Configuration.DEBUG) 175: log.throwing(this.getClass().getName(), "test1BlockSize", x); 176: return false; 177: } 178: } 179: this.reset(); 180: return true; 181: } 182: 183: /** 184: * If any additional checks or resource setup must be done by the subclass, 185: * then this is the hook for it. This method will be called before the 186: * {@link #init(int)} method returns. 187: */ 188: public abstract void setup(); 189: 190: public abstract byte[] pad(byte[] in, int off, int len); 191: 192: public abstract int unpad(byte[] in, int off, int len) 193: throws WrongPaddingException; 194: }