001 /** 002 * 003 * Licensed to the Apache Software Foundation (ASF) under one or more 004 * contributor license agreements. See the NOTICE file distributed with 005 * this work for additional information regarding copyright ownership. 006 * The ASF licenses this file to You under the Apache License, Version 2.0 007 * (the "License"); you may not use this file except in compliance with 008 * the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018 019 package org.apache.geronimo.util.asn1; 020 021 import java.io.ByteArrayInputStream; 022 import java.io.EOFException; 023 import java.io.FilterInputStream; 024 import java.io.IOException; 025 import java.io.InputStream; 026 027 /** 028 * Don't use this class. It will eventually disappear, use ASN1InputStream. 029 * <br> 030 * This class is scheduled for removal. 031 * @deprecated use ASN1InputStream 032 */ 033 public class DERInputStream 034 extends FilterInputStream implements DERTags 035 { 036 /** 037 * @deprecated use ASN1InputStream 038 */ 039 public DERInputStream( 040 InputStream is) 041 { 042 super(is); 043 } 044 045 protected int readLength() 046 throws IOException 047 { 048 int length = read(); 049 if (length < 0) 050 { 051 throw new IOException("EOF found when length expected"); 052 } 053 054 if (length == 0x80) 055 { 056 return -1; // indefinite-length encoding 057 } 058 059 if (length > 127) 060 { 061 int size = length & 0x7f; 062 063 if (size > 4) 064 { 065 throw new IOException("DER length more than 4 bytes"); 066 } 067 068 length = 0; 069 for (int i = 0; i < size; i++) 070 { 071 int next = read(); 072 073 if (next < 0) 074 { 075 throw new IOException("EOF found reading length"); 076 } 077 078 length = (length << 8) + next; 079 } 080 081 if (length < 0) 082 { 083 throw new IOException("corrupted steam - negative length found"); 084 } 085 } 086 087 return length; 088 } 089 090 protected void readFully( 091 byte[] bytes) 092 throws IOException 093 { 094 int left = bytes.length; 095 096 if (left == 0) 097 { 098 return; 099 } 100 101 while (left > 0) 102 { 103 int l = read(bytes, bytes.length - left, left); 104 105 if (l < 0) 106 { 107 throw new EOFException("unexpected end of stream"); 108 } 109 110 left -= l; 111 } 112 } 113 114 /** 115 * build an object given its tag and a byte stream to construct it 116 * from. 117 */ 118 protected DERObject buildObject( 119 int tag, 120 byte[] bytes) 121 throws IOException 122 { 123 switch (tag) 124 { 125 case NULL: 126 return null; 127 case SEQUENCE | CONSTRUCTED: 128 ByteArrayInputStream bIn = new ByteArrayInputStream(bytes); 129 BERInputStream dIn = new BERInputStream(bIn); 130 DERConstructedSequence seq = new DERConstructedSequence(); 131 132 try 133 { 134 for (;;) 135 { 136 DERObject obj = dIn.readObject(); 137 138 seq.addObject(obj); 139 } 140 } 141 catch (EOFException ex) 142 { 143 return seq; 144 } 145 case SET | CONSTRUCTED: 146 bIn = new ByteArrayInputStream(bytes); 147 dIn = new BERInputStream(bIn); 148 149 ASN1EncodableVector v = new ASN1EncodableVector(); 150 151 try 152 { 153 for (;;) 154 { 155 DERObject obj = dIn.readObject(); 156 157 v.add(obj); 158 } 159 } 160 catch (EOFException ex) 161 { 162 return new DERConstructedSet(v); 163 } 164 case BOOLEAN: 165 return new DERBoolean(bytes); 166 case INTEGER: 167 return new DERInteger(bytes); 168 case ENUMERATED: 169 return new DEREnumerated(bytes); 170 case OBJECT_IDENTIFIER: 171 return new DERObjectIdentifier(bytes); 172 case BIT_STRING: 173 int padBits = bytes[0]; 174 byte[] data = new byte[bytes.length - 1]; 175 176 System.arraycopy(bytes, 1, data, 0, bytes.length - 1); 177 178 return new DERBitString(data, padBits); 179 case UTF8_STRING: 180 return new DERUTF8String(bytes); 181 case PRINTABLE_STRING: 182 return new DERPrintableString(bytes); 183 case IA5_STRING: 184 return new DERIA5String(bytes); 185 case T61_STRING: 186 return new DERT61String(bytes); 187 case VISIBLE_STRING: 188 return new DERVisibleString(bytes); 189 case UNIVERSAL_STRING: 190 return new DERUniversalString(bytes); 191 case GENERAL_STRING: 192 return new DERGeneralString(bytes); 193 case BMP_STRING: 194 return new DERBMPString(bytes); 195 case OCTET_STRING: 196 return new DEROctetString(bytes); 197 case UTC_TIME: 198 return new DERUTCTime(bytes); 199 case GENERALIZED_TIME: 200 return new DERGeneralizedTime(bytes); 201 default: 202 // 203 // with tagged object tag number is bottom 5 bits 204 // 205 if ((tag & TAGGED) != 0) 206 { 207 if ((tag & 0x1f) == 0x1f) 208 { 209 throw new IOException("unsupported high tag encountered"); 210 } 211 212 if (bytes.length == 0) // empty tag! 213 { 214 if ((tag & CONSTRUCTED) == 0) 215 { 216 return new DERTaggedObject(false, tag & 0x1f, new DERNull()); 217 } 218 else 219 { 220 return new DERTaggedObject(false, tag & 0x1f, new DERConstructedSequence()); 221 } 222 } 223 224 // 225 // simple type - implicit... return an octet string 226 // 227 if ((tag & CONSTRUCTED) == 0) 228 { 229 return new DERTaggedObject(false, tag & 0x1f, new DEROctetString(bytes)); 230 } 231 232 bIn = new ByteArrayInputStream(bytes); 233 dIn = new BERInputStream(bIn); 234 235 DEREncodable dObj = dIn.readObject(); 236 237 // 238 // explicitly tagged (probably!) - if it isn't we'd have to 239 // tell from the context 240 // 241 if (dIn.available() == 0) 242 { 243 return new DERTaggedObject(tag & 0x1f, dObj); 244 } 245 246 // 247 // another implicit object, we'll create a sequence... 248 // 249 seq = new DERConstructedSequence(); 250 251 seq.addObject(dObj); 252 253 try 254 { 255 for (;;) 256 { 257 dObj = dIn.readObject(); 258 259 seq.addObject(dObj); 260 } 261 } 262 catch (EOFException ex) 263 { 264 // ignore -- 265 } 266 267 return new DERTaggedObject(false, tag & 0x1f, seq); 268 } 269 270 return new DERUnknownTag(tag, bytes); 271 } 272 } 273 274 public DERObject readObject() 275 throws IOException 276 { 277 int tag = read(); 278 if (tag == -1) 279 { 280 throw new EOFException(); 281 } 282 283 int length = readLength(); 284 byte[] bytes = new byte[length]; 285 286 readFully(bytes); 287 288 return buildObject(tag, bytes); 289 } 290 }