1 /*
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.  Oracle designates this
7  * particular file as subject to the "Classpath" exception as provided
8  * 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 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
21  * or visit www.oracle.com if you need additional information or have any
22  * questions.
23  */
24 
25 /*
26  *
27  *  (C) Copyright IBM Corp. 1999 All Rights Reserved.
28  *  Copyright 1997 The Open Group Research Institute.  All rights reserved.
29  */
30 
31 package sun.security.krb5.internal;
32 
33 import sun.security.krb5.*;
34 import sun.security.util.*;
35 import java.util.Vector;
36 import java.io.IOException;
37 import java.math.BigInteger;
38 
39 /**
40  * Implements the ASN.1 EncAPRepPart type.
41  *
42  * <pre>{@code
43  * EncAPRepPart ::= [APPLICATION 27] SEQUENCE {
44  *      ctime           [0] KerberosTime,
45  *      cusec           [1] Microseconds,
46  *      subkey          [2] EncryptionKey OPTIONAL,
47  *      seq-number      [3] UInt32 OPTIONAL
48  * }
49  * }</pre>
50  *
51  * <p>
52  * This definition reflects the Network Working Group RFC 4120
53  * specification available at
54  * <a href="http://www.ietf.org/rfc/rfc4120.txt">
55  * http://www.ietf.org/rfc/rfc4120.txt</a>.
56  */
57 public class EncAPRepPart {
58 
59     public KerberosTime ctime;
60     public int cusec;
61     EncryptionKey subKey; //optional
62     Integer seqNumber; //optional
63 
EncAPRepPart( KerberosTime new_ctime, int new_cusec, EncryptionKey new_subKey, Integer new_seqNumber)64     public EncAPRepPart(
65             KerberosTime new_ctime,
66             int new_cusec,
67             EncryptionKey new_subKey,
68             Integer new_seqNumber) {
69         ctime = new_ctime;
70         cusec = new_cusec;
71         subKey = new_subKey;
72         seqNumber = new_seqNumber;
73     }
74 
EncAPRepPart(byte[] data)75     public EncAPRepPart(byte[] data)
76             throws Asn1Exception, IOException {
77         init(new DerValue(data));
78     }
79 
EncAPRepPart(DerValue encoding)80     public EncAPRepPart(DerValue encoding)
81             throws Asn1Exception, IOException {
82         init(encoding);
83     }
84 
85     /**
86      * Initializes an EncaPRepPart object.
87      * @param encoding a single DER-encoded value.
88      * @exception Asn1Exception if an error occurs while decoding an ASN1 encoded data.
89      * @exception IOException if an I/O error occurs while reading encoded data.
90      */
init(DerValue encoding)91     private void init(DerValue encoding) throws Asn1Exception, IOException {
92         DerValue der, subDer;
93         if (((encoding.getTag() & (byte) 0x1F) != (byte) 0x1B)
94                 || (encoding.isApplication() != true)
95                 || (encoding.isConstructed() != true)) {
96             throw new Asn1Exception(Krb5.ASN1_BAD_ID);
97         }
98         der = encoding.getData().getDerValue();
99         if (der.getTag() != DerValue.tag_Sequence) {
100             throw new Asn1Exception(Krb5.ASN1_BAD_ID);
101         }
102         ctime = KerberosTime.parse(der.getData(), (byte) 0x00, true);
103         subDer = der.getData().getDerValue();
104         if ((subDer.getTag() & (byte) 0x1F) == (byte) 0x01) {
105             cusec = subDer.getData().getBigInteger().intValue();
106         } else {
107             throw new Asn1Exception(Krb5.ASN1_BAD_ID);
108         }
109         if (der.getData().available() > 0) {
110             subKey = EncryptionKey.parse(der.getData(), (byte) 0x02, true);
111         } else {
112             subKey = null;
113             seqNumber = null;
114         }
115         if (der.getData().available() > 0) {
116             subDer = der.getData().getDerValue();
117             if ((subDer.getTag() & 0x1F) != 0x03) {
118                 throw new Asn1Exception(Krb5.ASN1_BAD_ID);
119             }
120             seqNumber = subDer.getData().getBigInteger().intValue();
121         } else {
122             seqNumber = null;
123         }
124         if (der.getData().available() > 0) {
125             throw new Asn1Exception(Krb5.ASN1_BAD_ID);
126         }
127     }
128 
129     /**
130      * Encodes an EncAPRepPart object.
131      * @return byte array of encoded EncAPRepPart object.
132      * @exception Asn1Exception if an error occurs while decoding an ASN1 encoded data.
133      * @exception IOException if an I/O error occurs while reading encoded data.
134      */
asn1Encode()135     public byte[] asn1Encode() throws Asn1Exception, IOException {
136         Vector<DerValue> v = new Vector<>();
137         DerOutputStream temp = new DerOutputStream();
138         v.addElement(new DerValue(DerValue.createTag(DerValue.TAG_CONTEXT,
139                 true, (byte) 0x00), ctime.asn1Encode()));
140         temp.putInteger(BigInteger.valueOf(cusec));
141         v.addElement(new DerValue(DerValue.createTag(DerValue.TAG_CONTEXT,
142                 true, (byte) 0x01), temp.toByteArray()));
143         if (subKey != null) {
144             v.addElement(new DerValue(DerValue.createTag(DerValue.TAG_CONTEXT,
145                     true, (byte) 0x02), subKey.asn1Encode()));
146         }
147         if (seqNumber != null) {
148             temp = new DerOutputStream();
149             // encode as an unsigned integer (UInt32)
150             temp.putInteger(BigInteger.valueOf(seqNumber.longValue()));
151             v.addElement(new DerValue(DerValue.createTag(DerValue.TAG_CONTEXT,
152                     true, (byte) 0x03), temp.toByteArray()));
153         }
154         DerValue[] der = new DerValue[v.size()];
155         v.copyInto(der);
156         temp = new DerOutputStream();
157         temp.putSequence(der);
158         DerOutputStream out = new DerOutputStream();
159         out.write(DerValue.createTag(DerValue.TAG_APPLICATION,
160                 true, (byte) 0x1B), temp);
161         return out.toByteArray();
162     }
163 
getSubKey()164     public final EncryptionKey getSubKey() {
165         return subKey;
166     }
167 
getSeqNumber()168     public final Integer getSeqNumber() {
169         return seqNumber;
170     }
171 }
172