1 /* 2 * Copyright (c) 2000, 2013, 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.Confounder; 35 import sun.security.krb5.KrbCryptoException; 36 import sun.security.krb5.internal.*; 37 38 abstract class DesCbcEType extends EType { calculateChecksum(byte[] data, int size)39 protected abstract byte[] calculateChecksum(byte[] data, int size) 40 throws KrbCryptoException; 41 blockSize()42 public int blockSize() { 43 return 8; 44 } 45 keyType()46 public int keyType() { 47 return Krb5.KEYTYPE_DES; 48 } 49 keySize()50 public int keySize() { 51 return 8; 52 } 53 54 /** 55 * Encrypts the data using DES in CBC mode. 56 * @param data the buffer for plain text. 57 * @param key the key to encrypt the data. 58 * @return the buffer for encrypted data. 59 * 60 * @written by Yanni Zhang, Dec 6 99. 61 */ 62 encrypt(byte[] data, byte[] key, int usage)63 public byte[] encrypt(byte[] data, byte[] key, int usage) 64 throws KrbCryptoException { 65 byte[] ivec = new byte[keySize()]; 66 return encrypt(data, key, ivec, usage); 67 } 68 69 /** 70 * Encrypts the data using DES in CBC mode. 71 * @param data the buffer for plain text. 72 * @param key the key to encrypt the data. 73 * @param ivec initialization vector. 74 * @return buffer for encrypted data. 75 * 76 * @modified by Yanni Zhang, Feb 24 00. 77 */ encrypt(byte[] data, byte[] key, byte[] ivec, int usage)78 public byte[] encrypt(byte[] data, byte[] key, byte[] ivec, 79 int usage) throws KrbCryptoException { 80 81 /* 82 * To meet export control requirements, double check that the 83 * key being used is no longer than 64 bits. 84 * 85 * Note that from a protocol point of view, an 86 * algorithm that is not DES will be rejected before this 87 * point. Also, a DES key that is not 64 bits will be 88 * rejected by a good implementations of JCE. 89 */ 90 if (key.length > 8) 91 throw new KrbCryptoException("Invalid DES Key!"); 92 93 int new_size = data.length + confounderSize() + checksumSize(); 94 byte[] new_data; 95 byte pad; 96 /*Data padding: using Kerberos 5 GSS-API mechanism (1.2.2.3), Jun 1996. 97 *Before encryption, plain text data is padded to the next highest multiple of blocksize. 98 *by appending between 1 and 8 bytes, the value of each such byte being the total number 99 *of pad bytes. For example, if new_size = 10, blockSize is 8, we should pad 2 bytes, 100 *and the value of each byte is 2. 101 *If plaintext data is a multiple of blocksize, we pad a 8 bytes of 8. 102 */ 103 if (new_size % blockSize() == 0) { 104 new_data = new byte[new_size + blockSize()]; 105 pad = (byte)8; 106 } 107 else { 108 new_data = new byte[new_size + blockSize() - new_size % blockSize()]; 109 pad = (byte)(blockSize() - new_size % blockSize()); 110 } 111 for (int i = new_size; i < new_data.length; i++) { 112 new_data[i] = pad; 113 } 114 byte[] conf = Confounder.bytes(confounderSize()); 115 System.arraycopy(conf, 0, new_data, 0, confounderSize()); 116 System.arraycopy(data, 0, new_data, startOfData(), data.length); 117 byte[] cksum = calculateChecksum(new_data, new_data.length); 118 System.arraycopy(cksum, 0, new_data, startOfChecksum(), 119 checksumSize()); 120 byte[] cipher = new byte[new_data.length]; 121 Des.cbc_encrypt(new_data, cipher, key, ivec, true); 122 return cipher; 123 } 124 125 /** 126 * Decrypts the data using DES in CBC mode. 127 * @param cipher the input buffer. 128 * @param key the key to decrypt the data. 129 * 130 * @written by Yanni Zhang, Dec 6 99. 131 */ decrypt(byte[] cipher, byte[] key, int usage)132 public byte[] decrypt(byte[] cipher, byte[] key, int usage) 133 throws KrbApErrException, KrbCryptoException{ 134 byte[] ivec = new byte[keySize()]; 135 return decrypt(cipher, key, ivec, usage); 136 } 137 138 /** 139 * Decrypts the data using DES in CBC mode. 140 * @param cipher the input buffer. 141 * @param key the key to decrypt the data. 142 * @param ivec initialization vector. 143 * 144 * @modified by Yanni Zhang, Dec 6 99. 145 */ decrypt(byte[] cipher, byte[] key, byte[] ivec, int usage)146 public byte[] decrypt(byte[] cipher, byte[] key, byte[] ivec, int usage) 147 throws KrbApErrException, KrbCryptoException { 148 149 /* 150 * To meet export control requirements, double check that the 151 * key being used is no longer than 64 bits. 152 * 153 * Note that from a protocol point of view, an 154 * algorithm that is not DES will be rejected before this 155 * point. Also, a DES key that is not 64 bits will be 156 * rejected by a good JCE provider. 157 */ 158 if (key.length > 8) 159 throw new KrbCryptoException("Invalid DES Key!"); 160 161 byte[] data = new byte[cipher.length]; 162 Des.cbc_encrypt(cipher, data, key, ivec, false); 163 if (!isChecksumValid(data)) 164 throw new KrbApErrException(Krb5.KRB_AP_ERR_BAD_INTEGRITY); 165 return data; 166 } 167 copyChecksumField(byte[] data, byte[] cksum)168 private void copyChecksumField(byte[] data, byte[] cksum) { 169 for (int i = 0; i < checksumSize(); i++) 170 data[startOfChecksum() + i] = cksum[i]; 171 } 172 checksumField(byte[] data)173 private byte[] checksumField(byte[] data) { 174 byte[] result = new byte[checksumSize()]; 175 for (int i = 0; i < checksumSize(); i++) 176 result[i] = data[startOfChecksum() + i]; 177 return result; 178 } 179 resetChecksumField(byte[] data)180 private void resetChecksumField(byte[] data) { 181 for (int i = startOfChecksum(); i < startOfChecksum() + 182 checksumSize(); i++) 183 data[i] = 0; 184 } 185 186 /* 187 // Not used. 188 public void setChecksum(byte[] data, int size) throws KrbCryptoException{ 189 resetChecksumField(data); 190 byte[] cksum = calculateChecksum(data, size); 191 copyChecksumField(data, cksum); 192 } 193 */ 194 generateChecksum(byte[] data)195 private byte[] generateChecksum(byte[] data) throws KrbCryptoException{ 196 byte[] cksum1 = checksumField(data); 197 resetChecksumField(data); 198 byte[] cksum2 = calculateChecksum(data, data.length); 199 copyChecksumField(data, cksum1); 200 return cksum2; 201 } 202 isChecksumEqual(byte[] cksum1, byte[] cksum2)203 private boolean isChecksumEqual(byte[] cksum1, byte[] cksum2) { 204 if (cksum1 == cksum2) 205 return true; 206 if ((cksum1 == null && cksum2 != null) || 207 (cksum1 != null && cksum2 == null)) 208 return false; 209 if (cksum1.length != cksum2.length) 210 return false; 211 for (int i = 0; i < cksum1.length; i++) 212 if (cksum1[i] != cksum2[i]) 213 return false; 214 return true; 215 } 216 isChecksumValid(byte[] data)217 protected boolean isChecksumValid(byte[] data) throws KrbCryptoException { 218 byte[] cksum1 = checksumField(data); 219 byte[] cksum2 = generateChecksum(data); 220 return isChecksumEqual(cksum1, cksum2); 221 } 222 } 223