blob: c5ad4769317e4d54204a32cc5ab1fca63c9bcbc9 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
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. Sun designates this
7 * particular file as subject to the "Classpath" exception as provided
8 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
21 * CA 95054 USA or visit www.sun.com if you need additional information or
22 * have any 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
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}