2002/03/21 01:19:32
[org.ibex.core.git] / src / org / bouncycastle / asn1 / BERInputStream.java
diff --git a/src/org/bouncycastle/asn1/BERInputStream.java b/src/org/bouncycastle/asn1/BERInputStream.java
new file mode 100644 (file)
index 0000000..824b439
--- /dev/null
@@ -0,0 +1,159 @@
+package org.bouncycastle.asn1;
+
+import java.math.BigInteger;
+import java.io.*;
+import java.util.*;
+
+public class BERInputStream
+    extends DERInputStream
+{
+       private DERObject END_OF_STREAM = new DERObject() {
+                                                                               void encode(
+                                                                                       DEROutputStream out)
+                                                                               throws IOException
+                                                                               {
+                                                                                       throw new IOException("Eeek!");
+                                                                               }
+
+                                                                       };
+    public BERInputStream(
+        InputStream is)
+    {
+        super(is);
+    }
+
+    /**
+     * read a string of bytes representing an indefinite length object.
+     */
+    private byte[] readIndefiniteLengthFully()
+        throws IOException
+    {
+        ByteArrayOutputStream   bOut = new ByteArrayOutputStream();
+        int                     b, b1;
+
+        b1 = read();
+
+        while ((b = read()) >= 0)
+        {
+                       if (b1 == 0 && b == 0)
+                       {
+                               break;
+                       }
+
+            bOut.write(b1);
+            b1 = b;
+        }
+
+        return bOut.toByteArray();
+    }
+
+       private BERConstructedOctetString buildConstructedOctetString(
+               DEROctetString  o1,
+               DEROctetString  o2)
+               throws IOException
+       {
+        Vector                  octs = new Vector();
+
+               if (o1 != null)
+               {
+            octs.addElement(o1);
+            octs.addElement(o2);
+               }
+
+               for (;;)
+               {
+                       DERObject               o = readObject();
+
+                       if (o == END_OF_STREAM)
+                       {
+                               break;
+                       }
+
+            octs.addElement(o);
+               }
+
+               return new BERConstructedOctetString(octs);
+       }
+
+    public DERObject readObject()
+        throws IOException
+    {
+        int tag = read();
+        if (tag == -1)
+        {
+            throw new EOFException();
+        }
+    
+        int     length = readLength();
+
+        if (length < 0)    // indefinite length method
+        {
+            byte[]  bytes;
+    
+            switch (tag)
+            {
+            case NULL:
+                return null;
+            case SEQUENCE | CONSTRUCTED:
+                BERConstructedSequence  seq = new BERConstructedSequence();
+    
+                               for (;;)
+                               {
+                                       DERObject   obj = readObject();
+
+                                       if (obj == END_OF_STREAM)
+                                       {
+                                               break;
+                                       }
+
+                                       seq.addObject(obj);
+                               }
+                               return seq;
+            case OCTET_STRING | CONSTRUCTED:
+                               return buildConstructedOctetString(null, null);
+            default:
+                if ((tag & (TAGGED | CONSTRUCTED)) != 0)  
+                {
+                                       // with tagged object tag number is bottom 4 bits
+                    BERTaggedObject tagObj = new BERTaggedObject(tag & 0x0f, readObject());
+                                       DERObject               o = readObject();
+
+                                       if (o == END_OF_STREAM)
+                                       {
+                                               return tagObj;
+                                       }
+                                       else if (o instanceof DEROctetString
+                                                       && tagObj.getObject() instanceof DEROctetString)
+                                       {
+                                               //
+                                               // it's an implicit object - mark it as so...
+                                               //
+                                               tagObj = new BERTaggedObject(false, tag & 0x0f, 
+                                                                               buildConstructedOctetString((DEROctetString)tagObj.getObject(), (DEROctetString)o));
+
+                                               return tagObj;
+                                       }
+
+                                       throw new IOException("truncated tagged object");
+                }
+    
+               bytes = readIndefiniteLengthFully();
+
+                return buildObject(tag, bytes);
+            }
+        }
+        else
+        {
+            if (tag == 0 && length == 0)    // end of contents marker.
+            {
+                return END_OF_STREAM;
+            }
+
+            byte[]  bytes = new byte[length];
+    
+            readFully(bytes);
+    
+                       return buildObject(tag, bytes);
+        }
+    }
+}