jdk/src/share/classes/sun/security/krb5/internal/crypto/EType.java
changeset 2 90ce3da70b43
child 4987 5b7352dd6a2f
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/security/krb5/internal/crypto/EType.java	Sat Dec 01 00:00:00 2007 +0000
@@ -0,0 +1,320 @@
+/*
+ * Portions Copyright 2000-2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ *
+ *  (C) Copyright IBM Corp. 1999 All Rights Reserved.
+ *  Copyright 1997 The Open Group Research Institute.  All rights reserved.
+ */
+
+package sun.security.krb5.internal.crypto;
+
+import sun.security.krb5.internal.*;
+import sun.security.krb5.Config;
+import sun.security.krb5.EncryptedData;
+import sun.security.krb5.EncryptionKey;
+import sun.security.krb5.KrbException;
+import sun.security.krb5.Asn1Exception;
+import sun.security.krb5.KrbCryptoException;
+import javax.crypto.*;
+import java.util.List;
+import java.util.ArrayList;
+
+//only needed if dataSize() implementation changes back to spec;
+//see dataSize() below
+
+public abstract class EType {
+
+    private static final boolean DEBUG = Krb5.DEBUG;
+
+    public static EType getInstance  (int eTypeConst)
+        throws KdcErrException {
+        EType eType = null;
+        String eTypeName = null;
+        switch (eTypeConst) {
+        case EncryptedData.ETYPE_NULL:
+            eType = new NullEType();
+            eTypeName = "sun.security.krb5.internal.crypto.NullEType";
+            break;
+        case EncryptedData.ETYPE_DES_CBC_CRC:
+            eType = new DesCbcCrcEType();
+            eTypeName = "sun.security.krb5.internal.crypto.DesCbcCrcEType";
+            break;
+        case EncryptedData.ETYPE_DES_CBC_MD5:
+            eType = new DesCbcMd5EType();
+            eTypeName = "sun.security.krb5.internal.crypto.DesCbcMd5EType";
+            break;
+
+        case EncryptedData.ETYPE_DES3_CBC_HMAC_SHA1_KD:
+            eType = new Des3CbcHmacSha1KdEType();
+            eTypeName =
+                "sun.security.krb5.internal.crypto.Des3CbcHmacSha1KdEType";
+            break;
+
+        case EncryptedData.ETYPE_AES128_CTS_HMAC_SHA1_96:
+            eType = new Aes128CtsHmacSha1EType();
+            eTypeName =
+                "sun.security.krb5.internal.crypto.Aes128CtsHmacSha1EType";
+            break;
+
+        case EncryptedData.ETYPE_AES256_CTS_HMAC_SHA1_96:
+            eType = new Aes256CtsHmacSha1EType();
+            eTypeName =
+                "sun.security.krb5.internal.crypto.Aes256CtsHmacSha1EType";
+            break;
+
+        case EncryptedData.ETYPE_ARCFOUR_HMAC:
+            eType = new ArcFourHmacEType();
+            eTypeName = "sun.security.krb5.internal.crypto.ArcFourHmacEType";
+            break;
+
+        default:
+            String msg = "encryption type = " + toString(eTypeConst)
+                + " ("  + eTypeConst + ")";
+            throw new KdcErrException(Krb5.KDC_ERR_ETYPE_NOSUPP, msg);
+        }
+        if (DEBUG) {
+            System.out.println(">>> EType: " + eTypeName);
+        }
+        return eType;
+    }
+
+    public abstract int eType();
+
+    public abstract int minimumPadSize();
+
+    public abstract int confounderSize();
+
+    public abstract int checksumType();
+
+    public abstract int checksumSize();
+
+    public abstract int blockSize();
+
+    public abstract int keyType();
+
+    public abstract int keySize();
+
+    public abstract byte[] encrypt(byte[] data, byte[] key, int usage)
+        throws KrbCryptoException;
+
+    public abstract byte[] encrypt(byte[] data, byte[] key, byte[] ivec,
+        int usage) throws KrbCryptoException;
+
+    public abstract byte[] decrypt(byte[] cipher, byte[] key, int usage)
+        throws KrbApErrException, KrbCryptoException;
+
+    public abstract byte[] decrypt(byte[] cipher, byte[] key, byte[] ivec,
+        int usage) throws KrbApErrException, KrbCryptoException;
+
+    public int dataSize(byte[] data)
+    // throws Asn1Exception
+    {
+        // EncodeRef ref = new EncodeRef(data, startOfData());
+        // return ref.end - startOfData();
+        // should be the above according to spec, but in fact
+        // implementations include the pad bytes in the data size
+        return data.length - startOfData();
+    }
+
+    public int padSize(byte[] data) {
+        return data.length - confounderSize() - checksumSize() -
+            dataSize(data);
+    }
+
+    public int startOfChecksum() {
+        return confounderSize();
+    }
+
+    public int startOfData() {
+        return confounderSize() + checksumSize();
+    }
+
+    public int startOfPad(byte[] data) {
+        return confounderSize() + checksumSize() + dataSize(data);
+    }
+
+    public byte[] decryptedData(byte[] data) {
+        int tempSize = dataSize(data);
+        byte[] result = new byte[tempSize];
+        System.arraycopy(data, startOfData(), result, 0, tempSize);
+        return result;
+    }
+
+    private static final int[] BUILTIN_ETYPES = new int[] {
+        EncryptedData.ETYPE_DES_CBC_MD5,
+        EncryptedData.ETYPE_DES_CBC_CRC,
+        EncryptedData.ETYPE_ARCFOUR_HMAC,
+        EncryptedData.ETYPE_DES3_CBC_HMAC_SHA1_KD,
+        EncryptedData.ETYPE_AES128_CTS_HMAC_SHA1_96,
+        EncryptedData.ETYPE_AES256_CTS_HMAC_SHA1_96,
+    };
+
+    private static final int[] BUILTIN_ETYPES_NOAES256 = new int[] {
+        EncryptedData.ETYPE_DES_CBC_MD5,
+        EncryptedData.ETYPE_DES_CBC_CRC,
+        EncryptedData.ETYPE_ARCFOUR_HMAC,
+        EncryptedData.ETYPE_DES3_CBC_HMAC_SHA1_KD,
+        EncryptedData.ETYPE_AES128_CTS_HMAC_SHA1_96,
+    };
+
+
+    // used in Config
+    public static int[] getBuiltInDefaults() {
+        int allowed = 0;
+        try {
+            allowed = Cipher.getMaxAllowedKeyLength("AES");
+        } catch (Exception e) {
+            // should not happen
+        }
+        if (allowed < 256) {
+            return BUILTIN_ETYPES_NOAES256;
+        }
+        return BUILTIN_ETYPES;
+    }
+
+    /**
+     * Retrieves the default etypes from the configuration file, or
+     * if that's not available, return the built-in list of default etypes.
+     */
+    // used in KrbAsReq, KeyTab
+    public static int[] getDefaults(String configName) {
+        try {
+            return Config.getInstance().defaultEtype(configName);
+        } catch (KrbException exc) {
+            if (DEBUG) {
+                System.out.println("Exception while getting " +
+                    configName + exc.getMessage());
+                System.out.println("Using defaults " +
+                    "des-cbc-md5, des-cbc-crc, des3-cbc-sha1," +
+                        " aes128cts, aes256cts, rc4-hmac");
+            }
+            return getBuiltInDefaults();
+        }
+    }
+
+    /**
+     * Retrieve the default etypes from the configuration file for
+     * those etypes for which there are corresponding keys.
+     * Used in scenario we have some keys from a keytab with etypes
+     * different from those named in configName. Then, in order
+     * to decrypt an AS-REP, we should only ask for etypes for which
+     * we have keys.
+     */
+    public static int[] getDefaults(String configName, EncryptionKey[] keys)
+        throws KrbException {
+        int[] answer = getDefaults(configName);
+        if (answer == null) {
+            throw new KrbException("No supported encryption types listed in "
+                + configName);
+        }
+
+        List<Integer> list = new ArrayList<Integer> (answer.length);
+        for (int i = 0; i < answer.length; i++) {
+            if (EncryptionKey.findKey(answer[i], keys) != null) {
+                list.add(answer[i]);
+            }
+        }
+        int len = list.size();
+        if (len <= 0) {
+            StringBuffer keystr = new StringBuffer();
+            for (int i = 0; i < keys.length; i++) {
+                keystr.append(toString(keys[i].getEType()));
+                keystr.append(" ");
+            }
+            throw new KrbException(
+                "Do not have keys of types listed in " + configName +
+                " available; only have keys of following type: " +
+                keystr.toString());
+        } else {
+            answer = new int[len];
+            for (int i = 0; i < len; i++) {
+                answer[i] = list.get(i);
+            }
+            return answer;
+        }
+    }
+
+    public static boolean isSupported(int eTypeConst, int[] config) {
+        for (int i = 0; i < config.length; i++) {
+            if (eTypeConst == config[i]) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public static boolean isSupported(int eTypeConst) {
+        int[] enabledETypes = getBuiltInDefaults();
+        return isSupported(eTypeConst, enabledETypes);
+    }
+
+    public static String toString(int type) {
+        switch (type) {
+        case 0:
+            return "NULL";
+        case 1:
+            return "DES CBC mode with CRC-32";
+        case 2:
+            return "DES CBC mode with MD4";
+        case 3:
+            return "DES CBC mode with MD5";
+        case 4:
+            return "reserved";
+        case 5:
+            return "DES3 CBC mode with MD5";
+        case 6:
+            return "reserved";
+        case 7:
+            return "DES3 CBC mode with SHA1";
+        case 9:
+            return "DSA with SHA1- Cms0ID";
+        case 10:
+            return "MD5 with RSA encryption - Cms0ID";
+        case 11:
+            return "SHA1 with RSA encryption - Cms0ID";
+        case 12:
+            return "RC2 CBC mode with Env0ID";
+        case 13:
+            return "RSA encryption with Env0ID";
+        case 14:
+            return "RSAES-0AEP-ENV-0ID";
+        case 15:
+            return "DES-EDE3-CBC-ENV-0ID";
+        case 16:
+            return "DES3 CBC mode with SHA1-KD";
+        case 17:
+            return "AES128 CTS mode with HMAC SHA1-96";
+        case 18:
+            return "AES256 CTS mode with HMAC SHA1-96";
+        case 23:
+            return "RC4 with HMAC";
+        case 24:
+            return "RC4 with HMAC EXP";
+
+        }
+        return "Unknown (" + type + ")";
+    }
+}