| 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 */  | 
 | 
 | 
 | 
/*  | 
 | 
 *  (C) Copyright IBM Corp. 1999 All Rights Reserved.  | 
 | 
 *  Copyright 1997 The Open Group Research Institute.  All rights reserved.  | 
 | 
 */  | 
 | 
 | 
 | 
package sun.security.krb5.internal.crypto;  | 
 | 
 | 
 | 
import sun.security.krb5.Checksum;  | 
 | 
import sun.security.krb5.Confounder;  | 
 | 
import sun.security.krb5.KrbCryptoException;  | 
 | 
import sun.security.krb5.internal.*;  | 
 | 
import javax.crypto.spec.DESKeySpec;  | 
 | 
import java.security.MessageDigest;  | 
 | 
import java.security.InvalidKeyException;  | 
 | 
 | 
 | 
public final class RsaMd5DesCksumType extends CksumType { | 
 | 
 | 
 | 
    public RsaMd5DesCksumType() { | 
 | 
    }  | 
 | 
 | 
 | 
    public int confounderSize() { | 
 | 
        return 8;  | 
 | 
    }  | 
 | 
 | 
 | 
    public int cksumType() { | 
 | 
        return Checksum.CKSUMTYPE_RSA_MD5_DES;  | 
 | 
    }  | 
 | 
 | 
 | 
    public boolean isKeyed() { | 
 | 
        return true;  | 
 | 
    }  | 
 | 
 | 
 | 
    public int cksumSize() { | 
 | 
        return 24;  | 
 | 
    }  | 
 | 
 | 
 | 
    public int keyType() { | 
 | 
        return Krb5.KEYTYPE_DES;  | 
 | 
    }  | 
 | 
 | 
 | 
    public int keySize() { | 
 | 
        return 8;  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    public byte[] calculateChecksum(byte[] data, int size, byte[] key,  | 
 | 
        int usage) throws KrbCryptoException { | 
 | 
          | 
 | 
        byte[] new_data = new byte[size + confounderSize()];  | 
 | 
        byte[] conf = Confounder.bytes(confounderSize());  | 
 | 
        System.arraycopy(conf, 0, new_data, 0, confounderSize());  | 
 | 
        System.arraycopy(data, 0, new_data, confounderSize(), size);  | 
 | 
 | 
 | 
          | 
 | 
        byte[] mdc_cksum = calculateRawChecksum(new_data, new_data.length);  | 
 | 
        byte[] cksum = new byte[cksumSize()];  | 
 | 
        System.arraycopy(conf, 0, cksum, 0, confounderSize());  | 
 | 
        System.arraycopy(mdc_cksum, 0, cksum, confounderSize(),  | 
 | 
                         cksumSize() - confounderSize());  | 
 | 
 | 
 | 
          | 
 | 
        byte[] new_key = new byte[keySize()];  | 
 | 
        System.arraycopy(key, 0, new_key, 0, key.length);  | 
 | 
        for (int i = 0; i < new_key.length; i++)  | 
 | 
        new_key[i] = (byte)(new_key[i] ^ 0xf0);  | 
 | 
          | 
 | 
        try { | 
 | 
            if (DESKeySpec.isWeak(new_key, 0)) { | 
 | 
                new_key[7] = (byte)(new_key[7] ^ 0xF0);  | 
 | 
            }  | 
 | 
        } catch (InvalidKeyException ex) { | 
 | 
            // swallow, since it should never happen  | 
 | 
        }  | 
 | 
        byte[] ivec = new byte[new_key.length];  | 
 | 
 | 
 | 
          | 
 | 
        byte[] enc_cksum = new byte[cksum.length];  | 
 | 
        Des.cbc_encrypt(cksum, enc_cksum, new_key, ivec, true);  | 
 | 
        return enc_cksum;  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    public boolean verifyChecksum(byte[] data, int size,  | 
 | 
        byte[] key, byte[] checksum, int usage) throws KrbCryptoException { | 
 | 
          | 
 | 
        byte[] cksum = decryptKeyedChecksum(checksum, key);  | 
 | 
 | 
 | 
          | 
 | 
        byte[] new_data = new byte[size + confounderSize()];  | 
 | 
        System.arraycopy(cksum, 0, new_data, 0, confounderSize());  | 
 | 
        System.arraycopy(data, 0, new_data, confounderSize(), size);  | 
 | 
 | 
 | 
        byte[] new_cksum = calculateRawChecksum(new_data, new_data.length);  | 
 | 
          | 
 | 
        byte[] orig_cksum = new byte[cksumSize() - confounderSize()];  | 
 | 
        System.arraycopy(cksum,  confounderSize(), orig_cksum, 0,  | 
 | 
                         cksumSize() - confounderSize());  | 
 | 
 | 
 | 
        return isChecksumEqual(orig_cksum, new_cksum);  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    private byte[] decryptKeyedChecksum(byte[] enc_cksum, byte[] key) throws KrbCryptoException { | 
 | 
          | 
 | 
        byte[] new_key = new byte[keySize()];  | 
 | 
        System.arraycopy(key, 0, new_key, 0, key.length);  | 
 | 
        for (int i = 0; i < new_key.length; i++)  | 
 | 
        new_key[i] = (byte)(new_key[i] ^ 0xf0);  | 
 | 
          | 
 | 
        try { | 
 | 
            if (DESKeySpec.isWeak(new_key, 0)) { | 
 | 
                new_key[7] = (byte)(new_key[7] ^ 0xF0);  | 
 | 
            }  | 
 | 
        } catch (InvalidKeyException ex) { | 
 | 
            // swallow, since it should never happen  | 
 | 
        }  | 
 | 
        byte[] ivec = new byte[new_key.length];  | 
 | 
 | 
 | 
        byte[] cksum = new byte[enc_cksum.length];  | 
 | 
        Des.cbc_encrypt(enc_cksum, cksum, new_key, ivec, false);  | 
 | 
        return cksum;  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    private byte[] calculateRawChecksum(byte[] data, int size) throws KrbCryptoException{ | 
 | 
        MessageDigest md5;  | 
 | 
        byte[] result = null;  | 
 | 
        try { | 
 | 
            md5 = MessageDigest.getInstance("MD5"); | 
 | 
        } catch (Exception e) { | 
 | 
            throw new KrbCryptoException("JCE provider may not be installed. " + e.getMessage()); | 
 | 
        }  | 
 | 
        try { | 
 | 
            md5.update(data);  | 
 | 
            result = md5.digest();  | 
 | 
        } catch (Exception e) { | 
 | 
            throw new KrbCryptoException(e.getMessage());  | 
 | 
        }  | 
 | 
        return result;  | 
 | 
    }  | 
 | 
}  |