1/*
2 *  Licensed to the Apache Software Foundation (ASF) under one or more
3 *  contributor license agreements.  See the NOTICE file distributed with
4 *  this work for additional information regarding copyright ownership.
5 *  The ASF licenses this file to You under the Apache License, Version 2.0
6 *  (the "License"); you may not use this file except in compliance with
7 *  the License.  You may obtain a copy of the License at
8 *
9 *     http://www.apache.org/licenses/LICENSE-2.0
10 *
11 *  Unless required by applicable law or agreed to in writing, software
12 *  distributed under the License is distributed on an "AS IS" BASIS,
13 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 *  See the License for the specific language governing permissions and
15 *  limitations under the License.
16 */
17
18/**
19* @author Vladimir N. Molotkov, Stepan M. Mishura
20* @version $Revision$
21*/
22
23package org.apache.harmony.security.asn1;
24
25
26/**
27 * Encodes ASN.1 types with BER (X.690)
28 *
29 * @see <a href="http://asn1.elibel.tm.fr/en/standards/index.htm">ASN.1</a>
30 */
31public class BerOutputStream {
32
33    /** Encoded byte array */
34    public byte[] encoded;
35
36    /** current offset */
37    protected int offset;
38
39    /** Current encoded length */
40    public int length;
41
42    /** Current encoded content */
43    public Object content;
44
45    public final void encodeTag(int tag) {
46        encoded[offset++] = (byte) tag; //FIXME long form?
47
48        if (length > 127) { //long form
49            int eLen = length >> 8;
50            byte numOctets = 1;
51            for (; eLen > 0; eLen = eLen >> 8) {
52                numOctets++;
53            }
54
55            encoded[offset] = (byte) (numOctets | 0x80);
56            offset++;
57
58            eLen = length;
59            int numOffset = offset + numOctets - 1;
60            for (int i = 0; i < numOctets; i++, eLen = eLen >> 8) {
61                encoded[numOffset - i] = (byte) eLen; //FIXME long value?
62            }
63            offset += numOctets;
64        } else { //short form
65            encoded[offset++] = (byte) length;
66        }
67    }
68
69    public void encodeANY() {
70        System.arraycopy(content, 0, encoded, offset, length);
71        offset += length;
72    }
73
74    public void encodeBitString() {
75        //FIXME check encoding
76        BitString bStr = (BitString) content;
77        encoded[offset] = (byte) bStr.unusedBits;
78        System.arraycopy(bStr.bytes, 0, encoded, offset + 1, length - 1);
79        offset += length;
80    }
81
82    public void encodeBoolean() {
83        if ((Boolean) content) {
84            encoded[offset] = (byte) 0xFF;
85        } else {
86            encoded[offset] = 0x00;
87        }
88        offset++;
89    }
90
91    public void encodeChoice(ASN1Choice choice) {
92        throw new RuntimeException("Is not implemented yet"); //FIXME
93    }
94
95    public void encodeExplicit(ASN1Explicit explicit) {
96        throw new RuntimeException("Is not implemented yet"); //FIXME
97    }
98
99    public void encodeGeneralizedTime() {
100        System.arraycopy(content, 0, encoded, offset, length);
101        offset += length;
102    }
103
104    public void encodeUTCTime() {
105        System.arraycopy(content, 0, encoded, offset, length);
106        offset += length;
107    }
108
109    public void encodeInteger() {
110        System.arraycopy(content, 0, encoded, offset, length);
111        offset += length;
112    }
113
114    public void encodeOctetString() {
115        System.arraycopy(content, 0, encoded, offset, length);
116        offset += length;
117    }
118
119    public void encodeOID() {
120
121        int[] oid = (int[]) content;
122
123        int oidLen = length;
124
125        // all subidentifiers except first
126        int elem;
127        for (int i = oid.length - 1; i > 1; i--, oidLen--) {
128            elem = oid[i];
129            if (elem > 127) {
130                encoded[offset + oidLen - 1] = (byte) (elem & 0x7F);
131                elem = elem >> 7;
132                for (; elem > 0;) {
133                    oidLen--;
134                    encoded[offset + oidLen - 1] = (byte) (elem | 0x80);
135                    elem = elem >> 7;
136                }
137            } else {
138                encoded[offset + oidLen - 1] = (byte) elem;
139            }
140        }
141
142        // first subidentifier
143        elem = oid[0] * 40 + oid[1];
144        if (elem > 127) {
145            encoded[offset + oidLen - 1] = (byte) (elem & 0x7F);
146            elem = elem >> 7;
147            for (; elem > 0;) {
148                oidLen--;
149                encoded[offset + oidLen - 1] = (byte) (elem | 0x80);
150                elem = elem >> 7;
151            }
152        } else {
153            encoded[offset + oidLen - 1] = (byte) elem;
154        }
155
156        offset += length;
157    }
158
159    public void encodeSequence(ASN1Sequence sequence) {
160        throw new RuntimeException("Is not implemented yet"); //FIXME
161    }
162
163    public void encodeSequenceOf(ASN1SequenceOf sequenceOf) {
164        throw new RuntimeException("Is not implemented yet"); //FIXME
165    }
166
167    public void encodeSet(ASN1Set set) {
168        throw new RuntimeException("Is not implemented yet"); //FIXME
169    }
170
171    public void encodeSetOf(ASN1SetOf setOf) {
172        throw new RuntimeException("Is not implemented yet"); //FIXME
173    }
174
175    public void encodeString() {
176        System.arraycopy(content, 0, encoded, offset, length);
177        offset += length;
178    }
179
180    public void getChoiceLength(ASN1Choice choice) {
181        throw new RuntimeException("Is not implemented yet"); //FIXME
182    }
183
184    public void getExplicitLength(ASN1Explicit sequence) {
185        throw new RuntimeException("Is not implemented yet"); //FIXME
186    }
187
188    public void getSequenceLength(ASN1Sequence sequence) {
189        throw new RuntimeException("Is not implemented yet"); //FIXME
190    }
191
192    public void getSequenceOfLength(ASN1SequenceOf sequence) {
193        throw new RuntimeException("Is not implemented yet"); //FIXME
194    }
195
196    public void getSetLength(ASN1Set set) {
197        throw new RuntimeException("Is not implemented yet"); //FIXME
198    }
199
200    public void getSetOfLength(ASN1SetOf setOf) {
201        throw new RuntimeException("Is not implemented yet"); //FIXME
202    }
203}
204