/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Sun designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Sun in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 */

/*
 *
 *  (C) Copyright IBM Corp. 1999 All Rights Reserved.
 *  Copyright 1997 The Open Group Research Institute.  All rights reserved.
 */

package sun.security.krb5.internal;

import sun.security.krb5.*;
import sun.security.util.*;
import java.util.Vector;
import java.io.IOException;
import java.math.BigInteger;

/**
 * Implements the ASN.1 EncAPRepPart type.
 *
 * <xmp>
 * EncAPRepPart ::= [APPLICATION 27] SEQUENCE {
 *      ctime           [0] KerberosTime,
 *      cusec           [1] Microseconds,
 *      subkey          [2] EncryptionKey OPTIONAL,
 *      seq-number      [3] UInt32 OPTIONAL
 * }
 * </xmp>
 *
 * <p>
 * This definition reflects the Network Working Group RFC 4120
 * specification available at
 * <a href="http://www.ietf.org/rfc/rfc4120.txt">
 * http://www.ietf.org/rfc/rfc4120.txt</a>.
 */
public class EncAPRepPart {
        public KerberosTime ctime;
        public int cusec;
    EncryptionKey subKey; //optional
    Integer seqNumber; //optional

        public EncAPRepPart(
                KerberosTime new_ctime,
                int new_cusec,
                EncryptionKey new_subKey,
                Integer new_seqNumber
        ) {
                ctime = new_ctime;
                cusec = new_cusec;
                subKey = new_subKey;
                seqNumber = new_seqNumber;
        }

        public EncAPRepPart(byte[] data)
                throws Asn1Exception, IOException {
                init(new DerValue(data));
        }

        public EncAPRepPart(DerValue encoding)
                throws Asn1Exception, IOException {
                init(encoding);
        }

        /**
         * Initializes an EncaPRepPart object.
         * @param encoding a single DER-encoded value.
         * @exception Asn1Exception if an error occurs while decoding an ASN1 encoded data.
         * @exception IOException if an I/O error occurs while reading encoded data.
         */
        private void init(DerValue encoding) throws Asn1Exception, IOException {
                DerValue der, subDer;
        if (((encoding.getTag() & (byte)0x1F) != (byte)0x1B)
             || (encoding.isApplication() != true)
                        || (encoding.isConstructed() != true))
                        throw new Asn1Exception(Krb5.ASN1_BAD_ID);
        der = encoding.getData().getDerValue();
        if (der.getTag() != DerValue.tag_Sequence)
            throw new Asn1Exception(Krb5.ASN1_BAD_ID);
                ctime = KerberosTime.parse(der.getData(), (byte)0x00, true);
                subDer = der.getData().getDerValue();
                if ((subDer.getTag() & (byte)0x1F) == (byte)0x01) {
                        cusec = subDer.getData().getBigInteger().intValue();
                }
        else
                        throw new Asn1Exception(Krb5.ASN1_BAD_ID);
                if (der.getData().available() > 0) {
                        subKey = EncryptionKey.parse(der.getData(), (byte)0x02, true);
                }
                else {
                        subKey = null;
                        seqNumber = null;
                }
                if (der.getData().available() > 0) {
                        subDer = der.getData().getDerValue();
                        if ((subDer.getTag() & 0x1F) != 0x03) {
                                throw new Asn1Exception(Krb5.ASN1_BAD_ID);
                        }
                        seqNumber = new Integer(subDer.getData().getBigInteger().intValue());
                }
                else seqNumber = null;
                if (der.getData().available() > 0)
                        throw new Asn1Exception(Krb5.ASN1_BAD_ID);
        }

        /**
         * Encodes an EncAPRepPart object.
         * @return byte array of encoded EncAPRepPart object.
         * @exception Asn1Exception if an error occurs while decoding an ASN1 encoded data.
         * @exception IOException if an I/O error occurs while reading encoded data.
         */
        public byte[] asn1Encode() throws Asn1Exception, IOException{
                Vector<DerValue> v = new Vector<DerValue> ();
        DerOutputStream temp = new DerOutputStream();
                v.addElement(new DerValue(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x00), ctime.asn1Encode()));
                temp.putInteger(BigInteger.valueOf(cusec));
                v.addElement(new DerValue(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x01), temp.toByteArray()));
                if (subKey != null)
                        v.addElement(new DerValue(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x02), subKey.asn1Encode()));
                if (seqNumber != null) {
                        temp = new DerOutputStream();
                        // encode as an unsigned integer (UInt32)
                        temp.putInteger(BigInteger.valueOf(seqNumber.longValue()));
                        v.addElement(new DerValue(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x03), temp.toByteArray()));
                }
                DerValue der[] = new DerValue[v.size()];
                v.copyInto(der);
                temp = new DerOutputStream();
                temp.putSequence(der);
        DerOutputStream out = new DerOutputStream();
        out.write(DerValue.createTag(DerValue.TAG_APPLICATION, true, (byte)0x1B), temp);
                return out.toByteArray();
        }

    public final EncryptionKey getSubKey() {
        return subKey;
    }

    public final Integer getSeqNumber() {
        return seqNumber;
    }

}
