Skip to content

Commit

Permalink
8229951: Better Ticket Granting Services
Browse files Browse the repository at this point in the history
Reviewed-by: ahgross, valeriep
  • Loading branch information
wangweij committed Sep 26, 2019
1 parent 40429ee commit bda0fba
Show file tree
Hide file tree
Showing 17 changed files with 138 additions and 267 deletions.
151 changes: 64 additions & 87 deletions src/java.security.jgss/share/classes/sun/security/krb5/Checksum.java
Expand Up @@ -73,6 +73,7 @@ public class Checksum {
// draft-brezak-win2k-krb-rc4-hmac-04.txt
public static final int CKSUMTYPE_HMAC_MD5_ARCFOUR = -138;

// default checksum type, -1 if not set
static int CKSUMTYPE_DEFAULT;
static int SAFECKSUMTYPE_DEFAULT;

Expand All @@ -87,26 +88,19 @@ public static void initStatic() {
try {
cfg = Config.getInstance();
temp = cfg.get("libdefaults", "default_checksum");
if (temp != null)
{
CKSUMTYPE_DEFAULT = Config.getType(temp);
} else {
/*
* If the default checksum is not
* specified in the configuration we
* set it to RSA_MD5. We follow the MIT and
* SEAM implementation.
*/
CKSUMTYPE_DEFAULT = CKSUMTYPE_RSA_MD5;
}
if (temp != null) {
CKSUMTYPE_DEFAULT = Config.getType(temp);
} else {
CKSUMTYPE_DEFAULT = -1;
}
} catch (Exception exc) {
if (DEBUG) {
System.out.println("Exception in getting default checksum "+
"value from the configuration " +
"Setting default checksum to be RSA-MD5");
"value from the configuration. " +
"No default checksum set.");
exc.printStackTrace();
}
CKSUMTYPE_DEFAULT = CKSUMTYPE_RSA_MD5;
CKSUMTYPE_DEFAULT = -1;
}


Expand All @@ -116,117 +110,100 @@ public static void initStatic() {
{
SAFECKSUMTYPE_DEFAULT = Config.getType(temp);
} else {
SAFECKSUMTYPE_DEFAULT = CKSUMTYPE_RSA_MD5_DES;
SAFECKSUMTYPE_DEFAULT = -1;
}
} catch (Exception exc) {
if (DEBUG) {
System.out.println("Exception in getting safe default " +
"checksum value " +
"from the configuration Setting " +
"safe default checksum to be RSA-MD5");
"from the configuration Setting. " +
"No safe default checksum set.");
exc.printStackTrace();
}
SAFECKSUMTYPE_DEFAULT = CKSUMTYPE_RSA_MD5_DES;
SAFECKSUMTYPE_DEFAULT = -1;
}
}

/**
* Constructs a new Checksum using the raw data and type.
*
* This constructor is only used by Authenticator Checksum
* {@link sun.security.jgss.krb5.InitialToken.OverloadedChecksum}
* where the checksum type must be 0x8003
* (see https://tools.ietf.org/html/rfc4121#section-4.1.1)
* and checksum field/value is used to convey service flags,
* channel bindings, and optional delegation information.
* This special type does NOT have a {@link CksumType} and has its
* own calculating and verification rules. It does has the same
* ASN.1 encoding though.
*
* @param data the byte array of checksum.
* @param new_cksumType the type of checksum.
*
*/
// used in InitialToken
public Checksum(byte[] data, int new_cksumType) {
cksumType = new_cksumType;
checksum = data;
}

/**
* Constructs a new Checksum by calculating the checksum over the data
* using specified checksum type.
* @param new_cksumType the type of checksum.
* @param data the data that needs to be performed a checksum calculation on.
* Constructs a new Checksum by calculating over the data using
* the specified checksum type. If the checksum is unkeyed, key
* and usage are ignored.
*
* @param new_cksumType the type of checksum. If set to -1, the
* {@linkplain EType#checksumType() mandatory checksum type}
* for the encryption type of {@code key} will be used
* @param data the data that needs to be performed a checksum calculation on
* @param key the key used by a keyed checksum
* @param usage the usage used by a keyed checksum
*/
public Checksum(int new_cksumType, byte[] data)
throws KdcErrException, KrbCryptoException {

cksumType = new_cksumType;
CksumType cksumEngine = CksumType.getInstance(cksumType);
if (!cksumEngine.isSafe()) {
checksum = cksumEngine.calculateChecksum(data, data.length);
public Checksum(int new_cksumType, byte[] data,
EncryptionKey key, int usage)
throws KdcErrException, KrbApErrException, KrbCryptoException {
if (new_cksumType == -1) {
cksumType = EType.getInstance(key.getEType()).checksumType();
} else {
throw new KdcErrException(Krb5.KRB_AP_ERR_INAPP_CKSUM);
cksumType = new_cksumType;
}
}

/**
* Constructs a new Checksum by calculating the keyed checksum
* over the data using specified checksum type.
* @param new_cksumType the type of checksum.
* @param data the data that needs to be performed a checksum calculation on.
*/
// KrbSafe, KrbTgsReq
public Checksum(int new_cksumType, byte[] data,
EncryptionKey key, int usage)
throws KdcErrException, KrbApErrException, KrbCryptoException {
cksumType = new_cksumType;
CksumType cksumEngine = CksumType.getInstance(cksumType);
if (!cksumEngine.isSafe())
throw new KrbApErrException(Krb5.KRB_AP_ERR_INAPP_CKSUM);
checksum =
cksumEngine.calculateKeyedChecksum(data,
data.length,
key.getBytes(),
usage);
checksum = CksumType.getInstance(cksumType).calculateChecksum(
data, data.length, key.getBytes(), usage);
}

/**
* Verifies the keyed checksum over the data passed in.
*/
public boolean verifyKeyedChecksum(byte[] data, EncryptionKey key,
int usage)
throws KdcErrException, KrbApErrException, KrbCryptoException {
public boolean verifyKeyedChecksum(byte[] data, EncryptionKey key, int usage)
throws KdcErrException, KrbApErrException, KrbCryptoException {
CksumType cksumEngine = CksumType.getInstance(cksumType);
if (!cksumEngine.isSafe())
if (!cksumEngine.isKeyed()) {
throw new KrbApErrException(Krb5.KRB_AP_ERR_INAPP_CKSUM);
return cksumEngine.verifyKeyedChecksum(data,
data.length,
key.getBytes(),
checksum,
usage);
}

// =============== ATTENTION! Use with care ==================
// According to https://tools.ietf.org/html/rfc3961#section-6.1,
// An unkeyed checksum should only be used "in limited circumstances
// where the lack of a key does not provide a window for an attack,
// preferably as part of an encrypted message".
public boolean verifyAnyChecksum(byte[] data, EncryptionKey key,
int usage)
throws KdcErrException, KrbCryptoException {
CksumType cksumEngine = CksumType.getInstance(cksumType);
if (!cksumEngine.isSafe()) {
return cksumEngine.verifyChecksum(data, checksum);
} else {
return cksumEngine.verifyKeyedChecksum(data,
data.length,
key.getBytes(),
checksum,
usage);
return cksumEngine.verifyChecksum(
data, data.length, key.getBytes(), checksum, usage);
}
}

/*
public Checksum(byte[] data) throws KdcErrException, KrbCryptoException {
this(Checksum.CKSUMTYPE_DEFAULT, data);

/**
* Verifies the checksum over the data passed in. The checksum might
* be a keyed or not.
*
* =============== ATTENTION! Use with care ==================
* According to https://tools.ietf.org/html/rfc3961#section-6.1,
* An unkeyed checksum should only be used "in limited circumstances
* where the lack of a key does not provide a window for an attack,
* preferably as part of an encrypted message".
*/
public boolean verifyAnyChecksum(byte[] data, EncryptionKey key, int usage)
throws KdcErrException, KrbCryptoException {
return CksumType.getInstance(cksumType).verifyChecksum(
data, data.length, key.getBytes(), checksum, usage);
}
*/

boolean isEqual(Checksum cksum) throws KdcErrException {
if (cksumType != cksum.cksumType)
if (cksumType != cksum.cksumType) {
return false;
CksumType cksumEngine = CksumType.getInstance(cksumType);
}
return CksumType.isChecksumEqual(checksum, cksum.checksum);
}

Expand Down
Expand Up @@ -320,28 +320,8 @@ private TGSReq createRequest(
byte[] temp = reqBody.asn1Encode(Krb5.KRB_TGS_REQ);
// if the checksum type is one of the keyed checksum types,
// use session key.
Checksum cksum;
switch (Checksum.CKSUMTYPE_DEFAULT) {
case Checksum.CKSUMTYPE_RSA_MD4_DES:
case Checksum.CKSUMTYPE_DES_MAC:
case Checksum.CKSUMTYPE_DES_MAC_K:
case Checksum.CKSUMTYPE_RSA_MD4_DES_K:
case Checksum.CKSUMTYPE_RSA_MD5_DES:
case Checksum.CKSUMTYPE_HMAC_SHA1_DES3_KD:
case Checksum.CKSUMTYPE_HMAC_MD5_ARCFOUR:
case Checksum.CKSUMTYPE_HMAC_SHA1_96_AES128:
case Checksum.CKSUMTYPE_HMAC_SHA1_96_AES256:
case Checksum.CKSUMTYPE_HMAC_SHA256_128_AES128:
case Checksum.CKSUMTYPE_HMAC_SHA384_192_AES256:
cksum = new Checksum(Checksum.CKSUMTYPE_DEFAULT, temp, key,
Checksum cksum = new Checksum(Checksum.CKSUMTYPE_DEFAULT, temp, key,
KeyUsage.KU_PA_TGS_REQ_CKSUM);
break;
case Checksum.CKSUMTYPE_CRC32:
case Checksum.CKSUMTYPE_RSA_MD4:
case Checksum.CKSUMTYPE_RSA_MD5:
default:
cksum = new Checksum(Checksum.CKSUMTYPE_DEFAULT, temp);
}

// Usage will be KeyUsage.KU_PA_TGS_REQ_AUTHENTICATOR

Expand Down
Expand Up @@ -135,6 +135,7 @@ public byte[] asn1Encode() throws Asn1Exception, IOException {
bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x01), name.getRealm().asn1Encode());

try {
// MS-SFU 2.2.1: use hmac-md5 checksum regardless of key type
Checksum cks = new Checksum(
Checksum.CKSUMTYPE_HMAC_MD5_ARCFOUR,
getS4UByteArray(),
Expand Down
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
Expand Down Expand Up @@ -31,10 +31,7 @@

package sun.security.krb5.internal.crypto;

import sun.security.krb5.Config;
import sun.security.krb5.Checksum;
import sun.security.krb5.EncryptedData;
import sun.security.krb5.KrbException;
import sun.security.krb5.KrbCryptoException;
import sun.security.krb5.internal.*;

Expand Down Expand Up @@ -81,12 +78,25 @@ public static CksumType getInstance(int cksumTypeConst)
cksumTypeName =
"sun.security.krb5.internal.crypto.HmacSha1Aes128CksumType";
break;

case Checksum.CKSUMTYPE_HMAC_SHA1_96_AES256:
cksumType = new HmacSha1Aes256CksumType();
cksumTypeName =
"sun.security.krb5.internal.crypto.HmacSha1Aes256CksumType";
break;

case Checksum.CKSUMTYPE_HMAC_SHA256_128_AES128:
cksumType = new HmacSha2Aes128CksumType();
cksumTypeName =
"sun.security.krb5.internal.crypto.HmacSha2Aes128CksumType";
break;

case Checksum.CKSUMTYPE_HMAC_SHA384_192_AES256:
cksumType = new HmacSha2Aes256CksumType();
cksumTypeName =
"sun.security.krb5.internal.crypto.HmacSha2Aes256CksumType";
break;

case Checksum.CKSUMTYPE_HMAC_MD5_ARCFOUR:
cksumType = new HmacMd5ArcFourCksumType();
cksumTypeName =
Expand Down Expand Up @@ -117,51 +127,24 @@ public static CksumType getInstance(int cksumTypeConst)
return cksumType;
}


/**
* Returns default checksum type.
*/
public static CksumType getInstance() throws KdcErrException {
// this method provided for Kerberos applications.
int cksumType = Checksum.CKSUMTYPE_RSA_MD5; // default
try {
Config c = Config.getInstance();
if ((cksumType = (Config.getType(c.get("libdefaults",
"ap_req_checksum_type")))) == - 1) {
if ((cksumType = Config.getType(c.get("libdefaults",
"checksum_type"))) == -1) {
cksumType = Checksum.CKSUMTYPE_RSA_MD5; // default
}
}
} catch (KrbException e) {
}
return getInstance(cksumType);
}

public abstract int confounderSize();

public abstract int cksumType();

public abstract boolean isSafe();
public abstract boolean isKeyed();

public abstract int cksumSize();

public abstract int keyType();

public abstract int keySize();

public abstract byte[] calculateChecksum(byte[] data, int size)
throws KrbCryptoException;

public abstract byte[] calculateKeyedChecksum(byte[] data, int size,
// Note: key and usage will be ignored for an unkeyed checksum.
public abstract byte[] calculateChecksum(byte[] data, int size,
byte[] key, int usage) throws KrbCryptoException;

public boolean verifyChecksum(byte[] data, byte[] checksum)
throws KrbCryptoException {
throw new UnsupportedOperationException("Not supported");
}

public abstract boolean verifyKeyedChecksum(byte[] data, int size,
// Note: key and usage will be ignored for an unkeyed checksum.
public abstract boolean verifyChecksum(byte[] data, int size,
byte[] key, byte[] checksum, int usage) throws KrbCryptoException;

public static boolean isChecksumEqual(byte[] cksum1, byte[] cksum2) {
Expand Down
Expand Up @@ -32,7 +32,6 @@

import sun.security.krb5.*;
import sun.security.krb5.internal.*;
import java.util.zip.CRC32;

public class Crc32CksumType extends CksumType {

Expand All @@ -47,7 +46,7 @@ public int cksumType() {
return Checksum.CKSUMTYPE_CRC32;
}

public boolean isSafe() {
public boolean isKeyed() {
return false;
}

Expand All @@ -63,18 +62,15 @@ public int keySize() {
return 0;
}

public byte[] calculateChecksum(byte[] data, int size) {
public byte[] calculateChecksum(byte[] data, int size,
byte[] key, int usage) {
return crc32.byte2crc32sum_bytes(data, size);
}

public byte[] calculateKeyedChecksum(byte[] data, int size,
byte[] key, int usage) {
return null;
}

public boolean verifyKeyedChecksum(byte[] data, int size,
byte[] key, byte[] checksum, int usage) {
return false;
public boolean verifyChecksum(byte[] data, int size,
byte[] key, byte[] checksum, int usage) {
return CksumType.isChecksumEqual(checksum,
crc32.byte2crc32sum_bytes(data));
}

public static byte[] int2quad(long input) {
Expand Down

0 comments on commit bda0fba

Please sign in to comment.