1 /*
   2  * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   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
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 /*
  27  *
  28  *  (C) Copyright IBM Corp. 1999 All Rights Reserved.
  29  *  Copyright 1997 The Open Group Research Institute.  All rights reserved.
  30  */
  31 
  32 package sun.security.krb5.internal.crypto;
  33 
  34 import sun.security.krb5.internal.*;
  35 import sun.security.krb5.Config;
  36 import sun.security.krb5.EncryptedData;
  37 import sun.security.krb5.EncryptionKey;
  38 import sun.security.krb5.KrbException;
  39 import sun.security.krb5.KrbCryptoException;
  40 import javax.crypto.*;
  41 import java.util.Arrays;
  42 import java.util.List;
  43 import java.util.ArrayList;
  44 
  45 //only needed if dataSize() implementation changes back to spec;
  46 //see dataSize() below
  47 
  48 public abstract class EType {
  49 
  50     private static final boolean DEBUG = Krb5.DEBUG;
  51     private static final boolean ALLOW_WEAK_CRYPTO;
  52 
  53     static {
  54         boolean allowed = true;
  55         try {
  56             Config cfg = Config.getInstance();
  57             String temp = cfg.getDefault("allow_weak_crypto", "libdefaults");
  58             if (temp != null && temp.equals("false")) allowed = false;
  59         } catch (Exception exc) {
  60             if (DEBUG) {
  61                 System.out.println ("Exception in getting allow_weak_crypto, " +
  62                                     "using default value " +
  63                                     exc.getMessage());
  64             }
  65         }
  66         ALLOW_WEAK_CRYPTO = allowed;
  67     }
  68 
  69     public static EType getInstance  (int eTypeConst)
  70         throws KdcErrException {
  71         EType eType = null;
  72         String eTypeName = null;
  73         switch (eTypeConst) {
  74         case EncryptedData.ETYPE_NULL:
  75             eType = new NullEType();
  76             eTypeName = "sun.security.krb5.internal.crypto.NullEType";
  77             break;
  78         case EncryptedData.ETYPE_DES_CBC_CRC:
  79             eType = new DesCbcCrcEType();
  80             eTypeName = "sun.security.krb5.internal.crypto.DesCbcCrcEType";
  81             break;
  82         case EncryptedData.ETYPE_DES_CBC_MD5:
  83             eType = new DesCbcMd5EType();
  84             eTypeName = "sun.security.krb5.internal.crypto.DesCbcMd5EType";
  85             break;
  86 
  87         case EncryptedData.ETYPE_DES3_CBC_HMAC_SHA1_KD:
  88             eType = new Des3CbcHmacSha1KdEType();
  89             eTypeName =
  90                 "sun.security.krb5.internal.crypto.Des3CbcHmacSha1KdEType";
  91             break;
  92 
  93         case EncryptedData.ETYPE_AES128_CTS_HMAC_SHA1_96:
  94             eType = new Aes128CtsHmacSha1EType();
  95             eTypeName =
  96                 "sun.security.krb5.internal.crypto.Aes128CtsHmacSha1EType";
  97             break;
  98 
  99         case EncryptedData.ETYPE_AES256_CTS_HMAC_SHA1_96:
 100             eType = new Aes256CtsHmacSha1EType();
 101             eTypeName =
 102                 "sun.security.krb5.internal.crypto.Aes256CtsHmacSha1EType";
 103             break;
 104 
 105         case EncryptedData.ETYPE_ARCFOUR_HMAC:
 106             eType = new ArcFourHmacEType();
 107             eTypeName = "sun.security.krb5.internal.crypto.ArcFourHmacEType";
 108             break;
 109 
 110         default:
 111             String msg = "encryption type = " + toString(eTypeConst)
 112                 + " ("  + eTypeConst + ")";
 113             throw new KdcErrException(Krb5.KDC_ERR_ETYPE_NOSUPP, msg);
 114         }
 115         if (DEBUG) {
 116             System.out.println(">>> EType: " + eTypeName);
 117         }
 118         return eType;
 119     }
 120 
 121     public abstract int eType();
 122 
 123     public abstract int minimumPadSize();
 124 
 125     public abstract int confounderSize();
 126 
 127     public abstract int checksumType();
 128 
 129     public abstract int checksumSize();
 130 
 131     public abstract int blockSize();
 132 
 133     public abstract int keyType();
 134 
 135     public abstract int keySize();
 136 
 137     public abstract byte[] encrypt(byte[] data, byte[] key, int usage)
 138         throws KrbCryptoException;
 139 
 140     public abstract byte[] encrypt(byte[] data, byte[] key, byte[] ivec,
 141         int usage) throws KrbCryptoException;
 142 
 143     public abstract byte[] decrypt(byte[] cipher, byte[] key, int usage)
 144         throws KrbApErrException, KrbCryptoException;
 145 
 146     public abstract byte[] decrypt(byte[] cipher, byte[] key, byte[] ivec,
 147         int usage) throws KrbApErrException, KrbCryptoException;
 148 
 149     public int dataSize(byte[] data)
 150     // throws Asn1Exception
 151     {
 152         // EncodeRef ref = new EncodeRef(data, startOfData());
 153         // return ref.end - startOfData();
 154         // should be the above according to spec, but in fact
 155         // implementations include the pad bytes in the data size
 156         return data.length - startOfData();
 157     }
 158 
 159     public int padSize(byte[] data) {
 160         return data.length - confounderSize() - checksumSize() -
 161             dataSize(data);
 162     }
 163 
 164     public int startOfChecksum() {
 165         return confounderSize();
 166     }
 167 
 168     public int startOfData() {
 169         return confounderSize() + checksumSize();
 170     }
 171 
 172     public int startOfPad(byte[] data) {
 173         return confounderSize() + checksumSize() + dataSize(data);
 174     }
 175 
 176     public byte[] decryptedData(byte[] data) {
 177         int tempSize = dataSize(data);
 178         byte[] result = new byte[tempSize];
 179         System.arraycopy(data, startOfData(), result, 0, tempSize);
 180         return result;
 181     }
 182 
 183     // Note: the first 2 entries of BUILTIN_ETYPES and BUILTIN_ETYPES_NOAES256
 184     // should be kept DES-related. They will be removed when allow_weak_crypto
 185     // is set to false.
 186 
 187     private static final int[] BUILTIN_ETYPES = new int[] {
 188         EncryptedData.ETYPE_AES256_CTS_HMAC_SHA1_96,
 189         EncryptedData.ETYPE_AES128_CTS_HMAC_SHA1_96,
 190         EncryptedData.ETYPE_DES3_CBC_HMAC_SHA1_KD,
 191         EncryptedData.ETYPE_ARCFOUR_HMAC,
 192         EncryptedData.ETYPE_DES_CBC_CRC,
 193         EncryptedData.ETYPE_DES_CBC_MD5,
 194     };
 195 
 196     private static final int[] BUILTIN_ETYPES_NOAES256 = new int[] {
 197         EncryptedData.ETYPE_AES128_CTS_HMAC_SHA1_96,
 198         EncryptedData.ETYPE_DES3_CBC_HMAC_SHA1_KD,
 199         EncryptedData.ETYPE_ARCFOUR_HMAC,
 200         EncryptedData.ETYPE_DES_CBC_CRC,
 201         EncryptedData.ETYPE_DES_CBC_MD5,
 202     };
 203 
 204 
 205     // used in Config
 206     public static int[] getBuiltInDefaults() {
 207         int allowed = 0;
 208         try {
 209             allowed = Cipher.getMaxAllowedKeyLength("AES");
 210         } catch (Exception e) {
 211             // should not happen
 212         }
 213         int[] result;
 214         if (allowed < 256) {
 215             result = BUILTIN_ETYPES_NOAES256;
 216         } else {
 217             result = BUILTIN_ETYPES;
 218         }
 219         if (!ALLOW_WEAK_CRYPTO) {
 220             // The last 2 etypes are now weak ones
 221             return Arrays.copyOfRange(result, 0, result.length - 2);
 222         }
 223         return result;
 224     }
 225 
 226     /**
 227      * Retrieves the default etypes from the configuration file, or
 228      * if that's not available, return the built-in list of default etypes.
 229      */
 230     // used in KrbAsReq, KeyTab
 231     public static int[] getDefaults(String configName) {
 232         try {
 233             return Config.getInstance().defaultEtype(configName);
 234         } catch (KrbException exc) {
 235             if (DEBUG) {
 236                 System.out.println("Exception while getting " +
 237                     configName + exc.getMessage());
 238                 System.out.println("Using default builtin etypes");
 239             }
 240             return getBuiltInDefaults();
 241         }
 242     }
 243 
 244     /**
 245      * Retrieve the default etypes from the configuration file for
 246      * those etypes for which there are corresponding keys.
 247      * Used in scenario we have some keys from a keytab with etypes
 248      * different from those named in configName. Then, in order
 249      * to decrypt an AS-REP, we should only ask for etypes for which
 250      * we have keys.
 251      */
 252     public static int[] getDefaults(String configName, EncryptionKey[] keys)
 253         throws KrbException {
 254         int[] answer = getDefaults(configName);
 255         if (answer == null) {
 256             throw new KrbException("No supported encryption types listed in "
 257                 + configName);
 258         }
 259 
 260         List<Integer> list = new ArrayList<>(answer.length);
 261         for (int i = 0; i < answer.length; i++) {
 262             if (EncryptionKey.findKey(answer[i], keys) != null) {
 263                 list.add(answer[i]);
 264             }
 265         }
 266         int len = list.size();
 267         if (len <= 0) {
 268             StringBuffer keystr = new StringBuffer();
 269             for (int i = 0; i < keys.length; i++) {
 270                 keystr.append(toString(keys[i].getEType()));
 271                 keystr.append(" ");
 272             }
 273             throw new KrbException(
 274                 "Do not have keys of types listed in " + configName +
 275                 " available; only have keys of following type: " +
 276                 keystr.toString());
 277         } else {
 278             answer = new int[len];
 279             for (int i = 0; i < len; i++) {
 280                 answer[i] = list.get(i);
 281             }
 282             return answer;
 283         }
 284     }
 285 
 286     public static boolean isSupported(int eTypeConst, int[] config) {
 287         for (int i = 0; i < config.length; i++) {
 288             if (eTypeConst == config[i]) {
 289                 return true;
 290             }
 291         }
 292         return false;
 293     }
 294 
 295     public static boolean isSupported(int eTypeConst) {
 296         int[] enabledETypes = getBuiltInDefaults();
 297         return isSupported(eTypeConst, enabledETypes);
 298     }
 299 
 300     public static String toString(int type) {
 301         switch (type) {
 302         case 0:
 303             return "NULL";
 304         case 1:
 305             return "DES CBC mode with CRC-32";
 306         case 2:
 307             return "DES CBC mode with MD4";
 308         case 3:
 309             return "DES CBC mode with MD5";
 310         case 4:
 311             return "reserved";
 312         case 5:
 313             return "DES3 CBC mode with MD5";
 314         case 6:
 315             return "reserved";
 316         case 7:
 317             return "DES3 CBC mode with SHA1";
 318         case 9:
 319             return "DSA with SHA1- Cms0ID";
 320         case 10:
 321             return "MD5 with RSA encryption - Cms0ID";
 322         case 11:
 323             return "SHA1 with RSA encryption - Cms0ID";
 324         case 12:
 325             return "RC2 CBC mode with Env0ID";
 326         case 13:
 327             return "RSA encryption with Env0ID";
 328         case 14:
 329             return "RSAES-0AEP-ENV-0ID";
 330         case 15:
 331             return "DES-EDE3-CBC-ENV-0ID";
 332         case 16:
 333             return "DES3 CBC mode with SHA1-KD";
 334         case 17:
 335             return "AES128 CTS mode with HMAC SHA1-96";
 336         case 18:
 337             return "AES256 CTS mode with HMAC SHA1-96";
 338         case 23:
 339             return "RC4 with HMAC";
 340         case 24:
 341             return "RC4 with HMAC EXP";
 342 
 343         }
 344         return "Unknown (" + type + ")";
 345     }
 346 }