Source for gnu.javax.crypto.sasl.srp.CALG

   1: /* CALG.java --
   2:    Copyright (C) 2003, 2006 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.sasl.srp;
  40: 
  41: import gnu.java.security.Registry;
  42: import gnu.javax.crypto.assembly.Assembly;
  43: import gnu.javax.crypto.assembly.Cascade;
  44: import gnu.javax.crypto.assembly.Direction;
  45: import gnu.javax.crypto.assembly.Stage;
  46: import gnu.javax.crypto.assembly.Transformer;
  47: import gnu.javax.crypto.assembly.TransformerException;
  48: import gnu.javax.crypto.cipher.CipherFactory;
  49: import gnu.javax.crypto.cipher.IBlockCipher;
  50: import gnu.javax.crypto.mode.IMode;
  51: import gnu.javax.crypto.mode.ModeFactory;
  52: import gnu.javax.crypto.pad.IPad;
  53: import gnu.javax.crypto.pad.PadFactory;
  54: import gnu.javax.crypto.sasl.ConfidentialityException;
  55: 
  56: import java.util.HashMap;
  57: 
  58: import javax.security.sasl.SaslException;
  59: 
  60: /**
  61:  * A Factory class that returns CALG (Confidentiality Algorithm) instances that
  62:  * operate as described in the draft-burdis-cat-sasl-srp-08.
  63:  * <p>
  64:  * The designated CALG block cipher should be used in OFB (Output Feedback
  65:  * Block) mode in the ISO variant, as described in <i>The Handbook of Applied
  66:  * Cryptography</i>, algorithm 7.20.
  67:  * <p>
  68:  * Let <code>k</code> be the block size of the chosen symmetric key block
  69:  * cipher algorithm; e.g. for AES this is <code>128</code> bits or
  70:  * <code>16</code> octets. The OFB mode used shall be of length/size
  71:  * <code>k</code>.
  72:  * <p>
  73:  * It is recommended that block ciphers operating in OFB mode be used with an
  74:  * Initial Vector (the mode's IV). In such a mode of operation - OFB with key
  75:  * re-use - the IV need not be secret. For the mechanism in question the IVs
  76:  * shall be a random octet sequence of <code>k</code> bytes.
  77:  * <p>
  78:  * The input data to the confidentiality protection algorithm shall be a
  79:  * multiple of the symmetric cipher block size <code>k</code>. When the input
  80:  * length is not a multiple of <code>k</code> octets, the data shall be padded
  81:  * according to the following scheme:
  82:  * <p>
  83:  * Assuming the length of the input is <code>l</code> octets,
  84:  * <code>(k - (l mod k))</code> octets, all having the value
  85:  * <code>(k - (l mod k))</code>, shall be appended to the original data. In
  86:  * other words, the input is padded at the trailing end with one of the
  87:  * following sequences:
  88:  * <pre>
  89:  *
  90:  *                     01 -- if l mod k = k-1
  91:  *                    02 02 -- if l mod k = k-2
  92:  *                              ...
  93:  *                              ...
  94:  *                              ...
  95:  *                  k k ... k k -- if l mod k = 0
  96:  * </pre>
  97:  * <p>
  98:  * The padding can be removed unambiguously since all input is padded and no
  99:  * padding sequence is a suffix of another. This padding method is well-defined
 100:  * if and only if <code>k &lt; 256</code> octets, which is the case with
 101:  * symmetric key block ciphers today, and in the forseeable future.
 102:  */
 103: public final class CALG
 104: {
 105:   private Assembly assembly;
 106:   private Object modeNdx; // initialisation key of the cascade's attributes
 107:   private int blockSize; // the underlying cipher's blocksize == IV length
 108:   private int keySize; // the underlying cipher's key size (in bytes).
 109: 
 110:   /** Private constructor to enforce instantiation through Factory method. */
 111:   private CALG(final int blockSize, final int keySize, final Object modeNdx,
 112:                final Assembly assembly)
 113:   {
 114:     super();
 115: 
 116:     this.blockSize = blockSize;
 117:     this.keySize = keySize;
 118:     this.modeNdx = modeNdx;
 119:     this.assembly = assembly;
 120:   }
 121: 
 122:   /**
 123:    * Returns an instance of a SASL-SRP CALG implementation.
 124:    *
 125:    * @param algorithm the name of the symmetric cipher algorithm.
 126:    * @return an instance of this object.
 127:    */
 128:   static synchronized CALG getInstance(final String algorithm)
 129:   {
 130:     final IBlockCipher cipher = CipherFactory.getInstance(algorithm);
 131:     final int blockSize = cipher.defaultBlockSize();
 132:     final int keySize = cipher.defaultKeySize();
 133:     final Cascade ofbCipher = new Cascade();
 134:     IMode ofbMode = ModeFactory.getInstance(Registry.OFB_MODE,
 135:                                             cipher,
 136:                                             blockSize);
 137:     Stage modeStage = Stage.getInstance(ofbMode, Direction.FORWARD);
 138:     final Object modeNdx = ofbCipher.append(modeStage);
 139:     final IPad pkcs7 = PadFactory.getInstance(Registry.PKCS7_PAD);
 140:     final Assembly asm = new Assembly();
 141:     asm.addPreTransformer(Transformer.getCascadeTransformer(ofbCipher));
 142:     asm.addPreTransformer(Transformer.getPaddingTransformer(pkcs7));
 143:     return new CALG(blockSize, keySize, modeNdx, asm);
 144:   }
 145: 
 146:   /**
 147:    * Initialises a SASL-SRP CALG implementation.
 148:    *
 149:    * @param kdf the key derivation function.
 150:    * @param iv the initial vector value to use.
 151:    * @param dir whether this CALG is used for encryption or decryption.
 152:    */
 153:   public void init(final KDF kdf, final byte[] iv, final Direction dir)
 154:       throws SaslException
 155:   {
 156:     final byte[] realIV;
 157:     if (iv.length == blockSize)
 158:       realIV = iv;
 159:     else
 160:       {
 161:         realIV = new byte[blockSize];
 162:         if (iv.length > blockSize)
 163:           System.arraycopy(iv, 0, realIV, 0, blockSize);
 164:         else // shouldnt happen
 165:           System.arraycopy(iv, 0, realIV, 0, iv.length);
 166:       }
 167:     final HashMap modeAttributes = new HashMap();
 168:     final byte[] sk = kdf.derive(keySize);
 169:     modeAttributes.put(IBlockCipher.KEY_MATERIAL, sk);
 170:     modeAttributes.put(IMode.IV, realIV);
 171:     final HashMap attributes = new HashMap();
 172:     attributes.put(Assembly.DIRECTION, dir);
 173:     attributes.put(modeNdx, modeAttributes);
 174:     try
 175:       {
 176:         assembly.init(attributes);
 177:       }
 178:     catch (TransformerException x)
 179:       {
 180:         throw new SaslException("getInstance()", x);
 181:       }
 182:   }
 183: 
 184:   /**
 185:    * Encrypts or decrypts, depending on the mode already set, a designated array
 186:    * of bytes and returns the result.
 187:    *
 188:    * @param data the data to encrypt/decrypt.
 189:    * @return the decrypted/encrypted result.
 190:    * @throws ConfidentialityException if an exception occurs duirng the process.
 191:    */
 192:   public byte[] doFinal(final byte[] data) throws ConfidentialityException
 193:   {
 194:     return doFinal(data, 0, data.length);
 195:   }
 196: 
 197:   /**
 198:    * Encrypts or decrypts, depending on the mode already set, a designated array
 199:    * of bytes and returns the result.
 200:    *
 201:    * @param data the data to encrypt/decrypt.
 202:    * @param offset where to start in <code>data</code>.
 203:    * @param length how many bytes to consider in <code>data</code>.
 204:    * @return the decrypted/encrypted result.
 205:    * @throws ConfidentialityException if an exception occurs duirng the process.
 206:    */
 207:   public byte[] doFinal(final byte[] data, final int offset, final int length)
 208:       throws ConfidentialityException
 209:   {
 210:     final byte[] result;
 211:     try
 212:       {
 213:         result = assembly.lastUpdate(data, offset, length);
 214:       }
 215:     catch (TransformerException x)
 216:       {
 217:         throw new ConfidentialityException("doFinal()", x);
 218:       }
 219:     return result;
 220:   }
 221: }