1/* 2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3 * 4 * This code is free software; you can redistribute it and/or modify it 5 * under the terms of the GNU General Public License version 2 only, as 6 * published by the Free Software Foundation. Oracle designates this 7 * particular file as subject to the "Classpath" exception as provided 8 * by Oracle in the LICENSE file that accompanied this code. 9 * 10 * This code is distributed in the hope that it will be useful, but WITHOUT 11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 13 * version 2 for more details (a copy is included in the LICENSE file that 14 * accompanied this code). 15 * 16 * You should have received a copy of the GNU General Public License version 17 * 2 along with this work; if not, write to the Free Software Foundation, 18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 19 * 20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 21 * or visit www.oracle.com if you need additional information or have any 22 * questions. 23 */ 24 25/* 26 * (C) Copyright IBM Corp. 1999 All Rights Reserved. 27 * Copyright 1997 The Open Group Research Institute. All rights reserved. 28 */ 29 30package sun.security.krb5.internal.crypto; 31 32import sun.security.krb5.Checksum; 33import sun.security.krb5.Confounder; 34import sun.security.krb5.KrbCryptoException; 35import sun.security.krb5.internal.*; 36import javax.crypto.Cipher; 37import javax.crypto.SecretKey; 38import javax.crypto.spec.DESKeySpec; 39import java.security.MessageDigest; 40import java.security.Provider; 41import java.security.Security; 42import java.security.InvalidKeyException; 43 44public final class RsaMd5DesCksumType extends CksumType { 45 46 public RsaMd5DesCksumType() { 47 } 48 49 public int confounderSize() { 50 return 8; 51 } 52 53 public int cksumType() { 54 return Checksum.CKSUMTYPE_RSA_MD5_DES; 55 } 56 57 public boolean isSafe() { 58 return true; 59 } 60 61 public int cksumSize() { 62 return 24; 63 } 64 65 public int keyType() { 66 return Krb5.KEYTYPE_DES; 67 } 68 69 public int keySize() { 70 return 8; 71 } 72 73 /** 74 * Calculates keyed checksum. 75 * @param data the data used to generate the checksum. 76 * @param size length of the data. 77 * @param key the key used to encrypt the checksum. 78 * @return keyed checksum. 79 * 80 * @modified by Yanni Zhang, 12/08/99. 81 */ 82 public byte[] calculateKeyedChecksum(byte[] data, int size, byte[] key, 83 int usage) throws KrbCryptoException { 84 //prepend confounder 85 byte[] new_data = new byte[size + confounderSize()]; 86 byte[] conf = Confounder.bytes(confounderSize()); 87 System.arraycopy(conf, 0, new_data, 0, confounderSize()); 88 System.arraycopy(data, 0, new_data, confounderSize(), size); 89 90 //calculate md5 cksum 91 byte[] mdc_cksum = calculateChecksum(new_data, new_data.length); 92 byte[] cksum = new byte[cksumSize()]; 93 System.arraycopy(conf, 0, cksum, 0, confounderSize()); 94 System.arraycopy(mdc_cksum, 0, cksum, confounderSize(), 95 cksumSize() - confounderSize()); 96 97 //compute modified key 98 byte[] new_key = new byte[keySize()]; 99 System.arraycopy(key, 0, new_key, 0, key.length); 100 for (int i = 0; i < new_key.length; i++) 101 new_key[i] = (byte)(new_key[i] ^ 0xf0); 102 //check for weak keys 103 try { 104 if (DESKeySpec.isWeak(new_key, 0)) { 105 new_key[7] = (byte)(new_key[7] ^ 0xF0); 106 } 107 } catch (InvalidKeyException ex) { 108 // swallow, since it should never happen 109 } 110 byte[] ivec = new byte[new_key.length]; 111 112 //des-cbc encrypt 113 byte[] enc_cksum = new byte[cksum.length]; 114 Des.cbc_encrypt(cksum, enc_cksum, new_key, ivec, true); 115 return enc_cksum; 116 } 117 118 /** 119 * Verifies keyed checksum. 120 * @param data the data. 121 * @param size the length of data. 122 * @param key the key used to encrypt the checksum. 123 * @param checksum the checksum. 124 * @return true if verification is successful. 125 * 126 * @modified by Yanni Zhang, 12/08/99. 127 */ 128 public boolean verifyKeyedChecksum(byte[] data, int size, 129 byte[] key, byte[] checksum, int usage) throws KrbCryptoException { 130 //decrypt checksum 131 byte[] cksum = decryptKeyedChecksum(checksum, key); 132 133 //prepend confounder 134 byte[] new_data = new byte[size + confounderSize()]; 135 System.arraycopy(cksum, 0, new_data, 0, confounderSize()); 136 System.arraycopy(data, 0, new_data, confounderSize(), size); 137 138 byte[] new_cksum = calculateChecksum(new_data, new_data.length); 139 //extract original cksum value 140 byte[] orig_cksum = new byte[cksumSize() - confounderSize()]; 141 System.arraycopy(cksum, confounderSize(), orig_cksum, 0, 142 cksumSize() - confounderSize()); 143 144 return isChecksumEqual(orig_cksum, new_cksum); 145 } 146 147 /** 148 * Decrypts keyed checksum. 149 * @param enc_cksum the buffer for encrypted checksum. 150 * @param key the key. 151 * @return the checksum. 152 * 153 * @modified by Yanni Zhang, 12/08/99. 154 */ 155 private byte[] decryptKeyedChecksum(byte[] enc_cksum, byte[] key) throws KrbCryptoException { 156 //compute modified key 157 byte[] new_key = new byte[keySize()]; 158 System.arraycopy(key, 0, new_key, 0, key.length); 159 for (int i = 0; i < new_key.length; i++) 160 new_key[i] = (byte)(new_key[i] ^ 0xf0); 161 //check for weak keys 162 try { 163 if (DESKeySpec.isWeak(new_key, 0)) { 164 new_key[7] = (byte)(new_key[7] ^ 0xF0); 165 } 166 } catch (InvalidKeyException ex) { 167 // swallow, since it should never happen 168 } 169 byte[] ivec = new byte[new_key.length]; 170 171 byte[] cksum = new byte[enc_cksum.length]; 172 Des.cbc_encrypt(enc_cksum, cksum, new_key, ivec, false); 173 return cksum; 174 } 175 176 /** 177 * Calculates checksum using MD5. 178 * @param data the data used to generate the checksum. 179 * @param size length of the data. 180 * @return the checksum. 181 * 182 * @modified by Yanni Zhang, 12/08/99. 183 */ 184 public byte[] calculateChecksum(byte[] data, int size) throws KrbCryptoException{ 185 MessageDigest md5; 186 byte[] result = null; 187 try { 188 md5 = MessageDigest.getInstance("MD5"); 189 } catch (Exception e) { 190 throw new KrbCryptoException("JCE provider may not be installed. " + e.getMessage()); 191 } 192 try { 193 md5.update(data); 194 result = md5.digest(); 195 } catch (Exception e) { 196 throw new KrbCryptoException(e.getMessage()); 197 } 198 return result; 199 } 200 201} 202