1 /*
   2  * Copyright (c) 2000, 2012, 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 boolean allowWeakCrypto;
  52 
  53     static {
  54         initStatic();
  55     }
  56 
  57     public static void initStatic() {
  58         boolean allowed = false;
  59         try {
  60             Config cfg = Config.getInstance();
  61             String temp = cfg.get("libdefaults", "allow_weak_crypto");
  62             if (temp != null && temp.equals("true")) allowed = true;
  63         } catch (Exception exc) {
  64             if (DEBUG) {
  65                 System.out.println ("Exception in getting allow_weak_crypto, " +
  66                                     "using default value " +
  67                                     exc.getMessage());
  68             }
  69         }
  70         allowWeakCrypto = allowed;
  71     }
  72 
  73     public static EType getInstance  (int eTypeConst)
  74         throws KdcErrException {
  75         EType eType = null;
  76         String eTypeName = null;
  77         switch (eTypeConst) {
  78         case EncryptedData.ETYPE_NULL:
  79             eType = new NullEType();
  80             eTypeName = "sun.security.krb5.internal.crypto.NullEType";
  81             break;
  82         case EncryptedData.ETYPE_DES_CBC_CRC:
  83             eType = new DesCbcCrcEType();
  84             eTypeName = "sun.security.krb5.internal.crypto.DesCbcCrcEType";
  85             break;
  86         case EncryptedData.ETYPE_DES_CBC_MD5:
  87             eType = new DesCbcMd5EType();
  88             eTypeName = "sun.security.krb5.internal.crypto.DesCbcMd5EType";
  89             break;
  90 
  91         case EncryptedData.ETYPE_DES3_CBC_HMAC_SHA1_KD:
  92             eType = new Des3CbcHmacSha1KdEType();
  93             eTypeName =
  94                 "sun.security.krb5.internal.crypto.Des3CbcHmacSha1KdEType";
  95             break;
  96 
  97         case EncryptedData.ETYPE_AES128_CTS_HMAC_SHA1_96:
  98             eType = new Aes128CtsHmacSha1EType();
  99             eTypeName =
 100                 "sun.security.krb5.internal.crypto.Aes128CtsHmacSha1EType";
 101             break;
 102 
 103         case EncryptedData.ETYPE_AES256_CTS_HMAC_SHA1_96:
 104             eType = new Aes256CtsHmacSha1EType();
 105             eTypeName =
 106                 "sun.security.krb5.internal.crypto.Aes256CtsHmacSha1EType";
 107             break;
 108 
 109         case EncryptedData.ETYPE_ARCFOUR_HMAC:
 110             eType = new ArcFourHmacEType();
 111             eTypeName = "sun.security.krb5.internal.crypto.ArcFourHmacEType";
 112             break;
 113 
 114         default:
 115             String msg = "encryption type = " + toString(eTypeConst)
 116                 + " ("  + eTypeConst + ")";
 117             throw new KdcErrException(Krb5.KDC_ERR_ETYPE_NOSUPP, msg);
 118         }
 119         if (DEBUG) {
 120             System.out.println(">>> EType: " + eTypeName);
 121         }
 122         return eType;
 123     }
 124 
 125     public abstract int eType();
 126 
 127     public abstract int minimumPadSize();
 128 
 129     public abstract int confounderSize();
 130 
 131     public abstract int checksumType();
 132 
 133     public abstract int checksumSize();
 134 
 135     public abstract int blockSize();
 136 
 137     public abstract int keyType();
 138 
 139     public abstract int keySize();
 140 
 141     public abstract byte[] encrypt(byte[] data, byte[] key, int usage)
 142         throws KrbCryptoException;
 143 
 144     public abstract byte[] encrypt(byte[] data, byte[] key, byte[] ivec,
 145         int usage) throws KrbCryptoException;
 146 
 147     public abstract byte[] decrypt(byte[] cipher, byte[] key, int usage)
 148         throws KrbApErrException, KrbCryptoException;
 149 
 150     public abstract byte[] decrypt(byte[] cipher, byte[] key, byte[] ivec,
 151         int usage) throws KrbApErrException, KrbCryptoException;
 152 
 153     public int dataSize(byte[] data)
 154     // throws Asn1Exception
 155     {
 156         // EncodeRef ref = new EncodeRef(data, startOfData());
 157         // return ref.end - startOfData();
 158         // should be the above according to spec, but in fact
 159         // implementations include the pad bytes in the data size
 160         return data.length - startOfData();
 161     }
 162 
 163     public int padSize(byte[] data) {
 164         return data.length - confounderSize() - checksumSize() -
 165             dataSize(data);
 166     }
 167 
 168     public int startOfChecksum() {
 169         return confounderSize();
 170     }
 171 
 172     public int startOfData() {
 173         return confounderSize() + checksumSize();
 174     }
 175 
 176     public int startOfPad(byte[] data) {
 177         return confounderSize() + checksumSize() + dataSize(data);
 178     }
 179 
 180     public byte[] decryptedData(byte[] data) {
 181         int tempSize = dataSize(data);
 182         byte[] result = new byte[tempSize];
 183         System.arraycopy(data, startOfData(), result, 0, tempSize);
 184         return result;
 185     }
 186 
 187     // Note: the first 2 entries of BUILTIN_ETYPES and BUILTIN_ETYPES_NOAES256
 188     // should be kept DES-related. They will be removed when allow_weak_crypto
 189     // is set to false.
 190 
 191     private static final int[] BUILTIN_ETYPES = new int[] {
 192         EncryptedData.ETYPE_AES256_CTS_HMAC_SHA1_96,
 193         EncryptedData.ETYPE_AES128_CTS_HMAC_SHA1_96,
 194         EncryptedData.ETYPE_DES3_CBC_HMAC_SHA1_KD,
 195         EncryptedData.ETYPE_ARCFOUR_HMAC,
 196         EncryptedData.ETYPE_DES_CBC_CRC,
 197         EncryptedData.ETYPE_DES_CBC_MD5,
 198     };
 199 
 200     private static final int[] BUILTIN_ETYPES_NOAES256 = new int[] {
 201         EncryptedData.ETYPE_AES128_CTS_HMAC_SHA1_96,
 202         EncryptedData.ETYPE_DES3_CBC_HMAC_SHA1_KD,
 203         EncryptedData.ETYPE_ARCFOUR_HMAC,
 204         EncryptedData.ETYPE_DES_CBC_CRC,
 205         EncryptedData.ETYPE_DES_CBC_MD5,
 206     };
 207 
 208 
 209     // used in Config
 210     public static int[] getBuiltInDefaults() {
 211         int allowed = 0;
 212         try {
 213             allowed = Cipher.getMaxAllowedKeyLength("AES");
 214         } catch (Exception e) {
 215             // should not happen
 216         }
 217         int[] result;
 218         if (allowed < 256) {
 219             result = BUILTIN_ETYPES_NOAES256;
 220         } else {
 221             result = BUILTIN_ETYPES;
 222         }
 223         if (!allowWeakCrypto) {
 224             // The last 2 etypes are now weak ones
 225             return Arrays.copyOfRange(result, 0, result.length - 2);
 226         }
 227         return result;
 228     }
 229 
 230     /**
 231      * Retrieves the default etypes from the configuration file, or
 232      * if that's not available, return the built-in list of default etypes.
 233      */
 234     // used in KrbAsReq, KeyTab
 235     public static int[] getDefaults(String configName) {
 236         try {
 237             return Config.getInstance().defaultEtype(configName);
 238         } catch (KrbException exc) {
 239             if (DEBUG) {
 240                 System.out.println("Exception while getting " +
 241                     configName + exc.getMessage());
 242                 System.out.println("Using default builtin etypes");
 243             }
 244             return getBuiltInDefaults();
 245         }
 246     }
 247 
 248     /**
 249      * Retrieve the default etypes from the configuration file for
 250      * those etypes for which there are corresponding keys.
 251      * Used in scenario we have some keys from a keytab with etypes
 252      * different from those named in configName. Then, in order
 253      * to decrypt an AS-REP, we should only ask for etypes for which
 254      * we have keys.
 255      */
 256     public static int[] getDefaults(String configName, EncryptionKey[] keys)
 257         throws KrbException {
 258         int[] answer = getDefaults(configName);
 259         if (answer == null) {
 260             throw new KrbException("No supported encryption types listed in "
 261                 + configName);
 262         }
 263 
 264         List<Integer> list = new ArrayList<>(answer.length);
 265         for (int i = 0; i < answer.length; i++) {
 266             if (EncryptionKey.findKey(answer[i], keys) != null) {
 267                 list.add(answer[i]);
 268             }
 269         }
 270         int len = list.size();
 271         if (len <= 0) {
 272             StringBuffer keystr = new StringBuffer();
 273             for (int i = 0; i < keys.length; i++) {
 274                 keystr.append(toString(keys[i].getEType()));
 275                 keystr.append(" ");
 276             }
 277             throw new KrbException(
 278                 "Do not have keys of types listed in " + configName +
 279                 " available; only have keys of following type: " +
 280                 keystr.toString());
 281         } else {
 282             answer = new int[len];
 283             for (int i = 0; i < len; i++) {
 284                 answer[i] = list.get(i);
 285             }
 286             return answer;
 287         }
 288     }
 289 
 290     public static boolean isSupported(int eTypeConst, int[] config) {
 291         for (int i = 0; i < config.length; i++) {
 292             if (eTypeConst == config[i]) {
 293                 return true;
 294             }
 295         }
 296         return false;
 297     }
 298 
 299     public static boolean isSupported(int eTypeConst) {
 300         int[] enabledETypes = getBuiltInDefaults();
 301         return isSupported(eTypeConst, enabledETypes);
 302     }
 303 
 304     public static String toString(int type) {
 305         switch (type) {
 306         case 0:
 307             return "NULL";
 308         case 1:
 309             return "DES CBC mode with CRC-32";
 310         case 2:
 311             return "DES CBC mode with MD4";
 312         case 3:
 313             return "DES CBC mode with MD5";
 314         case 4:
 315             return "reserved";
 316         case 5:
 317             return "DES3 CBC mode with MD5";
 318         case 6:
 319             return "reserved";
 320         case 7:
 321             return "DES3 CBC mode with SHA1";
 322         case 9:
 323             return "DSA with SHA1- Cms0ID";
 324         case 10:
 325             return "MD5 with RSA encryption - Cms0ID";
 326         case 11:
 327             return "SHA1 with RSA encryption - Cms0ID";
 328         case 12:
 329             return "RC2 CBC mode with Env0ID";
 330         case 13:
 331             return "RSA encryption with Env0ID";
 332         case 14:
 333             return "RSAES-0AEP-ENV-0ID";
 334         case 15:
 335             return "DES-EDE3-CBC-ENV-0ID";
 336         case 16:
 337             return "DES3 CBC mode with SHA1-KD";
 338         case 17:
 339             return "AES128 CTS mode with HMAC SHA1-96";
 340         case 18:
 341             return "AES256 CTS mode with HMAC SHA1-96";
 342         case 23:
 343             return "RC4 with HMAC";
 344         case 24:
 345             return "RC4 with HMAC EXP";
 346 
 347         }
 348         return "Unknown (" + type + ")";
 349     }
 350 }