14c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrompackage org.bouncycastle.asn1;
24c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
34c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport java.io.ByteArrayInputStream;
44c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport java.io.FileInputStream;
54c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport java.io.IOException;
64c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport java.io.InputStream;
74c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
84c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromclass StreamUtil
94c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom{
104c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    private static final long  MAX_MEMORY = Runtime.getRuntime().maxMemory();
114c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
124c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    /**
134c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom     * Find out possible longest length...
144c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom     *
154c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom     * @param in input stream of interest
164c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom     * @return length calculation or MAX_VALUE.
174c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom     */
184c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    static int findLimit(InputStream in)
194c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    {
204c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        if (in instanceof LimitedInputStream)
214c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
224c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            return ((LimitedInputStream)in).getRemaining();
234c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
244c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        else if (in instanceof ASN1InputStream)
254c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
264c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            return ((ASN1InputStream)in).getLimit();
274c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
284c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        else if (in instanceof ByteArrayInputStream)
294c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
304c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            return ((ByteArrayInputStream)in).available();
314c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
324c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        else if (in instanceof FileInputStream)
334c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
344c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            try
354c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            {
364c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                long  size = ((FileInputStream)in).getChannel().size();
374c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
384c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                if (size < Integer.MAX_VALUE)
394c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                {
404c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                    return (int)size;
414c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                }
424c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            }
434c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            catch (IOException e)
444c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            {
454c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                // ignore - they'll find out soon enough!
464c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            }
474c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
484c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
494c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        if (MAX_MEMORY > Integer.MAX_VALUE)
504c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
514c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            return Integer.MAX_VALUE;
524c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
534c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
544c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        return (int)MAX_MEMORY;
554c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    }
564c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
574c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    static int calculateBodyLength(
584c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        int length)
594c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    {
604c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        int count = 1;
614c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
624c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        if (length > 127)
634c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
644c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            int size = 1;
654c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            int val = length;
664c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
674c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            while ((val >>>= 8) != 0)
684c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            {
694c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                size++;
704c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            }
714c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
724c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            for (int i = (size - 1) * 8; i >= 0; i -= 8)
734c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            {
744c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                count++;
754c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            }
764c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
774c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
784c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        return count;
794c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    }
804c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
814c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    static int calculateTagLength(int tagNo)
824c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        throws IOException
834c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    {
844c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        int length = 1;
854c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
864c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        if (tagNo >= 31)
874c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
884c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            if (tagNo < 128)
894c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            {
904c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                length++;
914c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            }
924c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            else
934c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            {
944c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                byte[] stack = new byte[5];
954c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                int pos = stack.length;
964c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
974c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                stack[--pos] = (byte)(tagNo & 0x7F);
984c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
994c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                do
1004c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                {
1014c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                    tagNo >>= 7;
1024c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                    stack[--pos] = (byte)(tagNo & 0x7F | 0x80);
1034c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                }
1044c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                while (tagNo > 127);
1054c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
1064c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                length += stack.length - pos;
1074c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            }
1084c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
1094c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
1104c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        return length;
1114c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    }
1124c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom}
113