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