Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/sun/security/krb5/Checksum.java
38830 views
/*1* Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.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 it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* 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 WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 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 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425/*26* (C) Copyright IBM Corp. 1999 All Rights Reserved.27* Copyright 1997 The Open Group Research Institute. All rights reserved.28*/2930package sun.security.krb5;3132import java.util.Arrays;33import sun.security.util.*;34import sun.security.krb5.internal.*;35import sun.security.krb5.internal.crypto.*;36import java.io.IOException;37import java.math.BigInteger;3839/**40* This class encapsulates the concept of a Kerberos checksum.41*/42public class Checksum {4344private int cksumType;45private byte[] checksum;4647// ----------------------------------------------+-------------+-----------48// Checksum type |sumtype |checksum49// |value | size50// ----------------------------------------------+-------------+-----------51public static final int CKSUMTYPE_NULL = 0; // 052public static final int CKSUMTYPE_CRC32 = 1; // 453public static final int CKSUMTYPE_RSA_MD4 = 2; // 1654public static final int CKSUMTYPE_RSA_MD4_DES = 3; // 2455public static final int CKSUMTYPE_DES_MAC = 4; // 1656public static final int CKSUMTYPE_DES_MAC_K = 5; // 857public static final int CKSUMTYPE_RSA_MD4_DES_K = 6; // 1658public static final int CKSUMTYPE_RSA_MD5 = 7; // 1659public static final int CKSUMTYPE_RSA_MD5_DES = 8; // 246061// draft-ietf-krb-wg-crypto-07.txt62public static final int CKSUMTYPE_HMAC_SHA1_DES3_KD = 12; // 206364// draft-raeburn-krb-rijndael-krb-07.txt65public static final int CKSUMTYPE_HMAC_SHA1_96_AES128 = 15; // 9666public static final int CKSUMTYPE_HMAC_SHA1_96_AES256 = 16; // 966768// draft-brezak-win2k-krb-rc4-hmac-04.txt69public static final int CKSUMTYPE_HMAC_MD5_ARCFOUR = -138;7071// default checksum type, -1 if not set72static int CKSUMTYPE_DEFAULT;73static int SAFECKSUMTYPE_DEFAULT;7475private static boolean DEBUG = Krb5.DEBUG;76static {77initStatic();78}7980public static void initStatic() {81String temp = null;82Config cfg = null;83try {84cfg = Config.getInstance();85temp = cfg.get("libdefaults", "default_checksum");86if (temp != null) {87CKSUMTYPE_DEFAULT = Config.getType(temp);88} else {89CKSUMTYPE_DEFAULT = -1;90}91} catch (Exception exc) {92if (DEBUG) {93System.out.println("Exception in getting default checksum "+94"value from the configuration. " +95"No default checksum set.");96exc.printStackTrace();97}98CKSUMTYPE_DEFAULT = -1;99}100101102try {103temp = cfg.get("libdefaults", "safe_checksum_type");104if (temp != null)105{106SAFECKSUMTYPE_DEFAULT = Config.getType(temp);107} else {108SAFECKSUMTYPE_DEFAULT = -1;109}110} catch (Exception exc) {111if (DEBUG) {112System.out.println("Exception in getting safe default " +113"checksum value " +114"from the configuration Setting. " +115"No safe default checksum set.");116exc.printStackTrace();117}118SAFECKSUMTYPE_DEFAULT = -1;119}120}121122/**123* Constructs a new Checksum using the raw data and type.124*125* This constructor is only used by Authenticator Checksum126* {@link sun.security.jgss.krb5.InitialToken.OverloadedChecksum}127* where the checksum type must be 0x8003128* (see https://tools.ietf.org/html/rfc4121#section-4.1.1)129* and checksum field/value is used to convey service flags,130* channel bindings, and optional delegation information.131* This special type does NOT have a {@link CksumType} and has its132* own calculating and verification rules. It does has the same133* ASN.1 encoding though.134*135* @param data the byte array of checksum.136* @param new_cksumType the type of checksum.137*/138public Checksum(byte[] data, int new_cksumType) {139cksumType = new_cksumType;140checksum = data;141}142143/**144* Constructs a new Checksum by calculating over the data using145* the specified checksum type. If the checksum is unkeyed, key146* and usage are ignored.147*148* @param new_cksumType the type of checksum. If set to -1, the149* {@linkplain EType#checksumType() mandatory checksum type}150* for the encryption type of {@code key} will be used151* @param data the data that needs to be performed a checksum calculation on152* @param key the key used by a keyed checksum153* @param usage the usage used by a keyed checksum154*/155public Checksum(int new_cksumType, byte[] data,156EncryptionKey key, int usage)157throws KdcErrException, KrbApErrException, KrbCryptoException {158if (new_cksumType == -1) {159cksumType = EType.getInstance(key.getEType()).checksumType();160} else {161cksumType = new_cksumType;162}163checksum = CksumType.getInstance(cksumType).calculateChecksum(164data, data.length, key.getBytes(), usage);165}166167/**168* Verifies the keyed checksum over the data passed in.169*/170public boolean verifyKeyedChecksum(byte[] data, EncryptionKey key, int usage)171throws KdcErrException, KrbApErrException, KrbCryptoException {172CksumType cksumEngine = CksumType.getInstance(cksumType);173if (!cksumEngine.isKeyed()) {174throw new KrbApErrException(Krb5.KRB_AP_ERR_INAPP_CKSUM);175} else {176return cksumEngine.verifyChecksum(177data, data.length, key.getBytes(), checksum, usage);178}179}180181182/**183* Verifies the checksum over the data passed in. The checksum might184* be a keyed or not.185*186* =============== ATTENTION! Use with care ==================187* According to https://tools.ietf.org/html/rfc3961#section-6.1,188* An unkeyed checksum should only be used "in limited circumstances189* where the lack of a key does not provide a window for an attack,190* preferably as part of an encrypted message".191*/192public boolean verifyAnyChecksum(byte[] data, EncryptionKey key, int usage)193throws KdcErrException, KrbCryptoException {194return CksumType.getInstance(cksumType).verifyChecksum(195data, data.length, key.getBytes(), checksum, usage);196}197198boolean isEqual(Checksum cksum) throws KdcErrException {199if (cksumType != cksum.cksumType) {200return false;201}202return CksumType.isChecksumEqual(checksum, cksum.checksum);203}204205/**206* Constructs an instance of Checksum from an ASN.1 encoded representation.207* @param encoding a single DER-encoded value.208* @exception Asn1Exception if an error occurs while decoding an ASN1209* encoded data.210* @exception IOException if an I/O error occurs while reading encoded data.211*212*/213public Checksum(DerValue encoding) throws Asn1Exception, IOException {214DerValue der;215if (encoding.getTag() != DerValue.tag_Sequence) {216throw new Asn1Exception(Krb5.ASN1_BAD_ID);217}218der = encoding.getData().getDerValue();219if ((der.getTag() & (byte)0x1F) == (byte)0x00) {220cksumType = der.getData().getBigInteger().intValue();221}222else223throw new Asn1Exception(Krb5.ASN1_BAD_ID);224der = encoding.getData().getDerValue();225if ((der.getTag() & (byte)0x1F) == (byte)0x01) {226checksum = der.getData().getOctetString();227}228else229throw new Asn1Exception(Krb5.ASN1_BAD_ID);230if (encoding.getData().available() > 0) {231throw new Asn1Exception(Krb5.ASN1_BAD_ID);232}233}234235/**236* Encodes a Checksum object.237* <pre>{@code238* Checksum ::= SEQUENCE {239* cksumtype [0] Int32,240* checksum [1] OCTET STRING241* }242* }</pre>243*244* <p>245* This definition reflects the Network Working Group RFC 4120246* specification available at247* <a href="http://www.ietf.org/rfc/rfc4120.txt">248* http://www.ietf.org/rfc/rfc4120.txt</a>.249* @return byte array of enocded Checksum.250* @exception Asn1Exception if an error occurs while decoding an251* ASN1 encoded data.252* @exception IOException if an I/O error occurs while reading253* encoded data.254*255*/256public byte[] asn1Encode() throws Asn1Exception, IOException {257DerOutputStream bytes = new DerOutputStream();258DerOutputStream temp = new DerOutputStream();259temp.putInteger(BigInteger.valueOf(cksumType));260bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT,261true, (byte)0x00), temp);262temp = new DerOutputStream();263temp.putOctetString(checksum);264bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT,265true, (byte)0x01), temp);266temp = new DerOutputStream();267temp.write(DerValue.tag_Sequence, bytes);268return temp.toByteArray();269}270271272/**273* Parse (unmarshal) a checksum object from a DER input stream. This form274* parsing might be used when expanding a value which is part of275* a constructed sequence and uses explicitly tagged type.276*277* @exception Asn1Exception if an error occurs while decoding an278* ASN1 encoded data.279* @exception IOException if an I/O error occurs while reading280* encoded data.281* @param data the Der input stream value, which contains one or more282* marshaled value.283* @param explicitTag tag number.284* @param optional indicates if this data field is optional285* @return an instance of Checksum.286*287*/288public static Checksum parse(DerInputStream data,289byte explicitTag, boolean optional)290throws Asn1Exception, IOException {291292if ((optional) &&293(((byte)data.peekByte() & (byte)0x1F) != explicitTag)) {294return null;295}296DerValue der = data.getDerValue();297if (explicitTag != (der.getTag() & (byte)0x1F)) {298throw new Asn1Exception(Krb5.ASN1_BAD_ID);299} else {300DerValue subDer = der.getData().getDerValue();301return new Checksum(subDer);302}303}304305/**306* Returns the raw bytes of the checksum, not in ASN.1 encoded form.307*/308public final byte[] getBytes() {309return checksum;310}311312public final int getType() {313return cksumType;314}315316@Override public boolean equals(Object obj) {317if (this == obj) {318return true;319}320if (!(obj instanceof Checksum)) {321return false;322}323324try {325return isEqual((Checksum)obj);326} catch (KdcErrException kee) {327return false;328}329}330331@Override public int hashCode() {332int result = 17;333result = 37 * result + cksumType;334if (checksum != null) {335result = 37 * result + Arrays.hashCode(checksum);336}337return result;338}339}340341342