Source Code Cross Referenced for BerInputStream.java in  » Apache-Harmony-Java-SE » org-package » org » apache » harmony » security » asn1 » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Apache Harmony Java SE » org package » org.apache.harmony.security.asn1 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         *  Licensed to the Apache Software Foundation (ASF) under one or more
0003:         *  contributor license agreements.  See the NOTICE file distributed with
0004:         *  this work for additional information regarding copyright ownership.
0005:         *  The ASF licenses this file to You under the Apache License, Version 2.0
0006:         *  (the "License"); you may not use this file except in compliance with
0007:         *  the License.  You may obtain a copy of the License at
0008:         *
0009:         *     http://www.apache.org/licenses/LICENSE-2.0
0010:         *
0011:         *  Unless required by applicable law or agreed to in writing, software
0012:         *  distributed under the License is distributed on an "AS IS" BASIS,
0013:         *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0014:         *  See the License for the specific language governing permissions and
0015:         *  limitations under the License.
0016:         */
0017:
0018:        /**
0019:         * @author Vladimir N. Molotkov, Stepan M. Mishura
0020:         * @version $Revision$
0021:         */package org.apache.harmony.security.asn1;
0022:
0023:        import java.io.IOException;
0024:        import java.io.InputStream;
0025:        import java.util.ArrayList;
0026:
0027:        import org.apache.harmony.security.internal.nls.Messages;
0028:
0029:        /**
0030:         * Decodes ASN.1 types encoded with BER (X.690)
0031:         * 
0032:         * @see http://asn1.elibel.tm.fr/en/standards/index.htm
0033:         */
0034:
0035:        public class BerInputStream {
0036:
0037:            /**
0038:             * Associated <code>InputStream</code>
0039:             */
0040:            protected InputStream in;
0041:
0042:            /**
0043:             * Internal buffer for storing encoded array 
0044:             */
0045:            protected byte[] buffer;
0046:
0047:            /**
0048:             * The position in the buffer.
0049:             * 
0050:             * Next read must place data into the buffer from this offset
0051:             */
0052:            protected int offset = 0;
0053:
0054:            // The buffer increment size.
0055:            // Must be reasonable big to reallocate memory not to often.
0056:            // Primary is used for decoding indefinite length encoding
0057:            private static final int BUF_INCREASE_SIZE = 1024 * 16;
0058:
0059:            /**
0060:             * Indicates indefinite length of the current type 
0061:             */
0062:            protected static final int INDEFINIT_LENGTH = -1;
0063:
0064:            /**
0065:             * Creates stream for decoding.
0066:             * 
0067:             * @param encoded - bytes array to be decoded
0068:             * @throws IOException - if an error occurs
0069:             */
0070:            public BerInputStream(byte[] encoded) throws IOException {
0071:                this (encoded, 0, encoded.length);
0072:            }
0073:
0074:            /**
0075:             * Creates stream for decoding.
0076:             * 
0077:             * @param encoded -
0078:             *            bytes array to be decoded
0079:             * @param offset -
0080:             *            the encoding offset
0081:             * @param expectedLength -
0082:             *            expected length of full encoding, this includes identifier,
0083:             *            length an content octets
0084:             * @throws IOException -
0085:             *             if an error occurs
0086:             */
0087:            public BerInputStream(byte[] encoded, int offset, int expectedLength)
0088:                    throws IOException {
0089:
0090:                this .buffer = encoded;
0091:                this .offset = offset;
0092:
0093:                next();
0094:
0095:                // compare expected and decoded length
0096:                if (length != INDEFINIT_LENGTH
0097:                        && (offset + expectedLength) != (this .offset + this .length)) {
0098:                    throw new ASN1Exception(Messages.getString("security.111")); //$NON-NLS-1$
0099:                }
0100:            }
0101:
0102:            /**
0103:             * Creates stream for decoding.
0104:             * 
0105:             * Allocates initial buffer of default size
0106:             *  
0107:             * @param is associated <code>InputStream</code>
0108:             */
0109:            public BerInputStream(InputStream in) throws IOException {
0110:                this (in, BUF_INCREASE_SIZE);
0111:            }
0112:
0113:            /**
0114:             * Creates stream for decoding.
0115:             * 
0116:             * Allocates initial buffer of <code>initialSize</code> size 
0117:             * 
0118:             * @param initialSize the internal buffer initial size
0119:             * @param is associated <code>InputStream</code>
0120:             */
0121:            public BerInputStream(InputStream in, int initialSize)
0122:                    throws IOException {
0123:
0124:                this .in = in;
0125:                buffer = new byte[initialSize];
0126:
0127:                next();
0128:
0129:                if (length != INDEFINIT_LENGTH) {
0130:                    // input stream has definite length encoding
0131:                    // check allocated length to avoid further reallocations
0132:                    if (buffer.length < (length + offset)) {
0133:                        byte[] newBuffer = new byte[length + offset];
0134:                        System.arraycopy(buffer, 0, newBuffer, 0, offset);
0135:                        buffer = newBuffer;
0136:                    }
0137:                } else {
0138:                    isIndefinedLength = true;
0139:                    throw new ASN1Exception(Messages.getString("security.112")); //$NON-NLS-1$
0140:                }
0141:            }
0142:
0143:            /**
0144:             * Resets this stream to initial state.
0145:             * 
0146:             * @param encoded - a new bytes array to be decoded
0147:             * @throws IOException - if an error occurs
0148:             */
0149:            public final void reset(byte[] encoded) throws IOException {
0150:                buffer = encoded;
0151:
0152:                next();
0153:            }
0154:
0155:            /**
0156:             * Current decoded tag
0157:             */
0158:            public int tag;
0159:
0160:            /**
0161:             * Current decoded length
0162:             */
0163:            protected int length;
0164:
0165:            /**
0166:             * Current decoded content
0167:             */
0168:            public Object content;
0169:
0170:            /**
0171:             * Current decoded tag offset
0172:             */
0173:            protected int tagOffset;
0174:
0175:            /**
0176:             * Current decoded content offset
0177:             */
0178:            protected int contentOffset;
0179:
0180:            /**
0181:             * Decodes next encoded type.
0182:             * Initializes tag, length, tagOffset and contentOffset variables
0183:             *
0184:             * @return next decoded tag
0185:             * @throws IOException - if error occured
0186:             */
0187:            public int next() throws IOException {
0188:
0189:                tagOffset = offset;
0190:
0191:                // read tag
0192:                tag = read();
0193:
0194:                // read length
0195:                length = read();
0196:                if (length != 0x80) { // definite form
0197:                    // long or short length form
0198:                    if ((length & 0x80) != 0) { // long form
0199:                        int numOctets = length & 0x7F;
0200:
0201:                        if (numOctets > 5) {
0202:                            throw new ASN1Exception(Messages.getString(
0203:                                    "security.113", //$NON-NLS-1$
0204:                                    tagOffset)); //FIXME message
0205:                        }
0206:
0207:                        // collect this value length
0208:                        length = read();
0209:                        for (int i = 1; i < numOctets; i++) {
0210:                            int ch = read();
0211:                            length = (length << 8) + ch;//read();
0212:                        }
0213:
0214:                        if (length > 0xFFFFFF) {
0215:                            throw new ASN1Exception(Messages.getString(
0216:                                    "security.113", //$NON-NLS-1$
0217:                                    tagOffset)); //FIXME message
0218:                        }
0219:                    }
0220:                } else { //indefinite form
0221:                    length = INDEFINIT_LENGTH;
0222:                }
0223:                contentOffset = offset;
0224:
0225:                return tag;
0226:            }
0227:
0228:            /**
0229:             * Returns the length of the encoding
0230:             */
0231:            public static int getLength(byte[] encoding) {
0232:                int length = encoding[1] & 0xFF;
0233:                int numOctets = 0;
0234:                if ((length & 0x80) != 0) { // long form
0235:                    numOctets = length & 0x7F;
0236:
0237:                    // collect this value length
0238:                    length = encoding[2] & 0xFF;
0239:                    for (int i = 3; i < numOctets + 2; i++) {
0240:                        length = (length << 8) + (encoding[i] & 0xFF);
0241:                    }
0242:                }
0243:                //    tag length long_form content
0244:                return 1 + 1 + numOctets + length;
0245:            }
0246:
0247:            /**
0248:             * Decodes ASN.1 bitstring type
0249:             * 
0250:             * @throws IOException - if error occured
0251:             */
0252:            public void readBitString() throws IOException {
0253:
0254:                if (tag == ASN1Constants.TAG_BITSTRING) {
0255:
0256:                    if (length == 0) {
0257:                        throw new ASN1Exception(Messages.getString(
0258:                                "security.114", tagOffset)); //$NON-NLS-1$
0259:                    }
0260:
0261:                    readContent();
0262:
0263:                    // content: check unused bits
0264:                    if (buffer[contentOffset] > 7) {
0265:                        throw new ASN1Exception(Messages.getString(
0266:                                "security.115", //$NON-NLS-1$
0267:                                contentOffset));
0268:                    }
0269:
0270:                    if (length == 1 && buffer[contentOffset] != 0) {
0271:                        throw new ASN1Exception(Messages.getString(
0272:                                "security.116", //$NON-NLS-1$
0273:                                contentOffset));
0274:                    }
0275:
0276:                } else if (tag == ASN1Constants.TAG_C_BITSTRING) {
0277:                    throw new ASN1Exception(Messages.getString("security.117")); //$NON-NLS-1$
0278:                } else {
0279:                    throw new ASN1Exception(Messages.getString(
0280:                            "security.118", tagOffset, //$NON-NLS-1$
0281:                            Integer.toHexString(tag)));
0282:                }
0283:            }
0284:
0285:            /**
0286:             * Decodes ASN.1 Enumerated type
0287:             * 
0288:             * @throws IOException - if error occured
0289:             */
0290:            public void readEnumerated() throws IOException {
0291:
0292:                if (tag != ASN1Constants.TAG_ENUM) {
0293:                    throw new ASN1Exception(Messages.getString(
0294:                            "security.119", tagOffset, //$NON-NLS-1$
0295:                            Integer.toHexString(tag)));
0296:                }
0297:
0298:                //
0299:                // all checks are the same as for ASN.1 integer type
0300:                //
0301:
0302:                // check encoded length
0303:                if (length == 0) {
0304:                    throw new ASN1Exception(Messages.getString(
0305:                            "security.11A", tagOffset));//$NON-NLS-1$
0306:                }
0307:
0308:                readContent();
0309:
0310:                // check encoded content
0311:                if (length > 1) {
0312:
0313:                    int bits = buffer[contentOffset] & 0xFF;
0314:                    if (buffer[contentOffset + 1] < 0) {
0315:                        bits += 0x100;
0316:                    }
0317:
0318:                    if (bits == 0 || bits == 0x1FF) {
0319:                        throw new ASN1Exception(Messages.getString(
0320:                                "security.11B", contentOffset)); //$NON-NLS-1$
0321:                    }
0322:                }
0323:            }
0324:
0325:            /**
0326:             * Decodes ASN.1 boolean type
0327:             * 
0328:             * @throws IOException - if error occured
0329:             */
0330:            public void readBoolean() throws IOException {
0331:
0332:                if (tag != ASN1Constants.TAG_BOOLEAN) {
0333:                    throw new ASN1Exception(Messages.getString("security.11C", //$NON-NLS-1$
0334:                            tagOffset, Integer.toHexString(tag)));
0335:                }
0336:
0337:                // check encoded length
0338:                if (length != 1) {
0339:                    throw new ASN1Exception(Messages.getString(
0340:                            "security.11D", tagOffset));//$NON-NLS-1$
0341:                }
0342:
0343:                readContent();
0344:            }
0345:
0346:            /**
0347:             * The last choice index
0348:             */
0349:            public int choiceIndex;
0350:
0351:            /**
0352:             * Keeps last decoded: year, month, day, hour, minute, second, millisecond
0353:             */
0354:            public int[] times;
0355:
0356:            /**
0357:             * Decodes ASN.1 GeneralizedTime type
0358:             * 
0359:             * @throws IOException - if error occured
0360:             */
0361:            public void readGeneralizedTime() throws IOException {
0362:
0363:                if (tag == ASN1Constants.TAG_GENERALIZEDTIME) {
0364:
0365:                    // FIXME: any other optimizations?
0366:                    readContent();
0367:                    // FIXME store string somewhere to allow a custom time type perform
0368:                    // additional checks
0369:
0370:                    // check syntax: the last char MUST be Z
0371:                    if (buffer[offset - 1] != 'Z') {
0372:                        // FIXME support only format that is acceptable for DER
0373:                        throw new ASN1Exception(Messages
0374:                                .getString("security.11E")); //$NON-NLS-1$
0375:                    }
0376:
0377:                    // check syntax: MUST be YYYYMMDDHHMMSS[(./,)DDD]'Z'
0378:                    if (length != 15 && (length < 17 || length > 19)) // invalid
0379:                    // length
0380:                    {
0381:                        throw new ASN1Exception(Messages.getString(
0382:                                "security.11F", //$NON-NLS-1$
0383:                                contentOffset));
0384:                    }
0385:
0386:                    // check content: milliseconds
0387:                    if (length > 16) {
0388:                        byte char14 = buffer[contentOffset + 14];
0389:                        if (char14 != '.' && char14 != ',') {
0390:                            throw new ASN1Exception(Messages.getString(
0391:                                    "security.11F", //$NON-NLS-1$
0392:                                    contentOffset));
0393:                        }
0394:                    }
0395:
0396:                    if (times == null) {
0397:                        times = new int[7];
0398:                    }
0399:                    times[0] = strToInt(contentOffset, 4); // year
0400:                    times[1] = strToInt(contentOffset + 4, 2); // month
0401:                    times[2] = strToInt(contentOffset + 6, 2); // day
0402:                    times[3] = strToInt(contentOffset + 8, 2); // hour
0403:                    times[4] = strToInt(contentOffset + 10, 2); // minute
0404:                    times[5] = strToInt(contentOffset + 12, 2); // second
0405:
0406:                    if (length > 16) {
0407:                        // FIXME optimize me
0408:                        times[6] = strToInt(contentOffset + 15, length - 16);
0409:
0410:                        if (length == 17) {
0411:                            times[6] = times[6] * 100;
0412:                        } else if (length == 18) {
0413:                            times[6] = times[6] * 10;
0414:                        }
0415:                    }
0416:
0417:                    // FIXME check all values for valid numbers!!!
0418:                } else if (tag == ASN1Constants.TAG_C_GENERALIZEDTIME) {
0419:                    throw new ASN1Exception(Messages.getString("security.120")); //$NON-NLS-1$
0420:
0421:                } else {
0422:                    throw new ASN1Exception(Messages.getString("security.121", //$NON-NLS-1$
0423:                            tagOffset, Integer.toHexString(tag)));
0424:                }
0425:            }
0426:
0427:            /**
0428:             * Decodes ASN.1 UTCTime type
0429:             *
0430:             * @throws IOException - if an I/O error occurs or the end of the stream is reached
0431:             */
0432:            public void readUTCTime() throws IOException {
0433:
0434:                if (tag == ASN1Constants.TAG_UTCTIME) {
0435:
0436:                    switch (length) {
0437:                    case ASN1UTCTime.UTC_HM:
0438:                    case ASN1UTCTime.UTC_HMS:
0439:                        break;
0440:                    case ASN1UTCTime.UTC_LOCAL_HM:
0441:                    case ASN1UTCTime.UTC_LOCAL_HMS:
0442:                        // FIXME only coordinated universal time formats are supported
0443:                        throw new ASN1Exception(Messages
0444:                                .getString("security.122")); //$NON-NLS-1$
0445:                    default:
0446:                        throw new ASN1Exception(Messages.getString(
0447:                                "security.123", //$NON-NLS-1$
0448:                                tagOffset));
0449:                    }
0450:
0451:                    // FIXME: any other optimizations?
0452:                    readContent();
0453:
0454:                    // FIXME store string somewhere to allow a custom time type perform
0455:                    // additional checks
0456:
0457:                    // check syntax: the last char MUST be Z
0458:                    if (buffer[offset - 1] != 'Z') {
0459:                        throw new ASN1Exception(
0460:                                "ASN.1 UTCTime wrongly encoded at [" //$NON-NLS-1$
0461:                                        + contentOffset + ']');
0462:                    }
0463:
0464:                    if (times == null) {
0465:                        times = new int[7];
0466:                    }
0467:
0468:                    times[0] = strToInt(contentOffset, 2); // year
0469:                    if (times[0] > 49) {
0470:                        times[0] += 1900;
0471:                    } else {
0472:                        times[0] += 2000;
0473:                    }
0474:
0475:                    times[1] = strToInt(contentOffset + 2, 2); // month
0476:                    times[2] = strToInt(contentOffset + 4, 2); // day
0477:                    times[3] = strToInt(contentOffset + 6, 2); // hour
0478:                    times[4] = strToInt(contentOffset + 8, 2); // minute
0479:
0480:                    if (length == ASN1UTCTime.UTC_HMS) {
0481:                        times[5] = strToInt(contentOffset + 10, 2); // second
0482:                    }
0483:
0484:                    // FIXME check all time values for valid numbers!!!
0485:                } else if (tag == ASN1Constants.TAG_C_UTCTIME) {
0486:                    throw new ASN1Exception(Messages.getString("security.124")); //$NON-NLS-1$
0487:                } else {
0488:                    throw new ASN1Exception(Messages.getString("security.125", //$NON-NLS-1$
0489:                            tagOffset, Integer.toHexString(tag)));
0490:                }
0491:            }
0492:
0493:            //TODO comment me
0494:            private int strToInt(int off, int count) throws ASN1Exception {
0495:
0496:                //FIXME works only with buffer
0497:
0498:                int c;
0499:                int result = 0;
0500:                for (int i = off, end = off + count; i < end; i++) {
0501:                    c = buffer[i] - 48;
0502:                    if (c < 0 || c > 9) {
0503:                        throw new ASN1Exception(Messages
0504:                                .getString("security.126")); //$NON-NLS-1$
0505:                    }
0506:                    result = result * 10 + c;
0507:                }
0508:                return result;
0509:            }
0510:
0511:            /**
0512:             * Decodes ASN.1 Integer type
0513:             * 
0514:             * @throws IOException - if error occured
0515:             */
0516:            public void readInteger() throws IOException {
0517:
0518:                if (tag != ASN1Constants.TAG_INTEGER) {
0519:                    throw new ASN1Exception(Messages.getString("security.127", //$NON-NLS-1$
0520:                            tagOffset, Integer.toHexString(tag)));
0521:                }
0522:
0523:                // check encoded length
0524:                if (length < 1) {
0525:                    throw new ASN1Exception(Messages.getString("security.128", //$NON-NLS-1$
0526:                            tagOffset)); //$NON-NLS-1$
0527:                }
0528:
0529:                readContent();
0530:
0531:                // check encoded content
0532:                if (length > 1) {
0533:
0534:                    byte firstByte = buffer[offset - length];
0535:                    byte secondByte = (byte) (buffer[offset - length + 1] & 0x80);
0536:
0537:                    if (firstByte == 0 && secondByte == 0
0538:                            || firstByte == (byte) 0xFF
0539:                            && secondByte == (byte) 0x80) {
0540:                        throw new ASN1Exception(Messages.getString(
0541:                                "security.129", //$NON-NLS-1$
0542:                                (offset - length)));
0543:                    }
0544:                }
0545:            }
0546:
0547:            /**
0548:             * Decodes ASN.1 Octetstring type
0549:             *
0550:             * @throws IOException - if error occured
0551:             */
0552:            public void readOctetString() throws IOException {
0553:
0554:                if (tag == ASN1Constants.TAG_OCTETSTRING) {
0555:                    readContent();
0556:                } else if (tag == ASN1Constants.TAG_C_OCTETSTRING) {
0557:                    throw new ASN1Exception(Messages.getString("security.12A")); //$NON-NLS-1$
0558:                } else {
0559:                    throw new ASN1Exception(Messages.getString(
0560:                            "security.12B", tagOffset, //$NON-NLS-1$
0561:                            Integer.toHexString(tag)));
0562:                }
0563:            }
0564:
0565:            //FIXME comment me
0566:            public int oidElement;
0567:
0568:            /**
0569:             * Decodes ASN.1 ObjectIdentifier type
0570:             *
0571:             * @throws IOException - if error occured
0572:             */
0573:            public void readOID() throws IOException {
0574:
0575:                if (tag != ASN1Constants.TAG_OID) {
0576:                    throw new ASN1Exception(Messages.getString("security.12C", //$NON-NLS-1$
0577:                            tagOffset, Integer.toHexString(tag)));
0578:                }
0579:
0580:                // check encoded length
0581:                if (length < 1) {
0582:                    throw new ASN1Exception(Messages.getString(
0583:                            "security.12D", tagOffset)); //$NON-NLS-1$
0584:                }
0585:
0586:                readContent();
0587:
0588:                // check content: last encoded byte (8th bit MUST be zero)
0589:                if ((buffer[offset - 1] & 0x80) != 0) {
0590:                    throw new ASN1Exception(Messages.getString(
0591:                            "security.12E", (offset - 1))); //$NON-NLS-1$
0592:                }
0593:
0594:                oidElement = 1;
0595:                for (int i = 0; i < length; i++, ++oidElement) {
0596:
0597:                    // According to ASN.1 BER spec:
0598:                    //    leading octet of subidentifier MUST not be 0x80
0599:                    // This assertion is not verified
0600:                    //
0601:                    //if (buffer[contentOffset + i] == (byte)0x80) {
0602:                    //    throw new ASN1Exception(
0603:                    //            "Wrong content for ASN.1 object identifier at ["
0604:                    //                    + contentOffset
0605:                    //                    + "]. Subidentifier MUST be encoded in minimum number of octets");
0606:                    //}
0607:
0608:                    while ((buffer[contentOffset + i] & 0x80) == 0x80) {
0609:                        i++;
0610:                    }
0611:                }
0612:            }
0613:
0614:            /**
0615:             * Decodes ASN.1 Sequence type
0616:             *
0617:             * @param sequence - ASN.1 sequence to be decoded
0618:             * @throws IOException - if error occured
0619:             */
0620:            public void readSequence(ASN1Sequence sequence) throws IOException {
0621:
0622:                if (tag != ASN1Constants.TAG_C_SEQUENCE) {
0623:                    throw new ASN1Exception(Messages.getString(
0624:                            "security.12F", tagOffset, //$NON-NLS-1$
0625:                            Integer.toHexString(tag)));
0626:                }
0627:
0628:                int begOffset = offset;
0629:                int endOffset = begOffset + length;
0630:
0631:                ASN1Type[] type = sequence.type;
0632:
0633:                int i = 0;
0634:
0635:                if (isVerify) {
0636:
0637:                    for (; (offset < endOffset) && (i < type.length); i++) {
0638:
0639:                        next();
0640:                        while (!type[i].checkTag(tag)) {
0641:                            // check whether it is optional component or not 
0642:                            if (!sequence.OPTIONAL[i] || (i == type.length - 1)) {
0643:                                throw new ASN1Exception(Messages.getString(
0644:                                        "security.130", //$NON-NLS-1$
0645:                                        tagOffset));
0646:                            }
0647:                            i++;
0648:                        }
0649:
0650:                        type[i].decode(this );
0651:                    }
0652:
0653:                    // check the rest of components
0654:                    for (; i < type.length; i++) {
0655:                        if (!sequence.OPTIONAL[i]) {
0656:                            throw new ASN1Exception(Messages.getString(
0657:                                    "security.131", //$NON-NLS-1$
0658:                                    tagOffset));
0659:                        }
0660:                    }
0661:
0662:                } else {
0663:
0664:                    int seqTagOffset = tagOffset; //store tag offset
0665:
0666:                    Object[] values = new Object[type.length];
0667:                    for (; (offset < endOffset) && (i < type.length); i++) {
0668:
0669:                        next();
0670:                        while (!type[i].checkTag(tag)) {
0671:                            // check whether it is optional component or not 
0672:                            if (!sequence.OPTIONAL[i] || (i == type.length - 1)) {
0673:                                throw new ASN1Exception(Messages.getString(
0674:                                        "security.132", //$NON-NLS-1$
0675:                                        tagOffset));
0676:                            }
0677:
0678:                            // sets default value
0679:                            if (sequence.DEFAULT[i] != null) {
0680:                                values[i] = sequence.DEFAULT[i];
0681:                            }
0682:                            i++;
0683:                        }
0684:                        values[i] = type[i].decode(this );
0685:                    }
0686:
0687:                    // check the rest of components
0688:                    for (; i < type.length; i++) {
0689:                        if (!sequence.OPTIONAL[i]) {
0690:                            throw new ASN1Exception(Messages.getString(
0691:                                    "security.133", //$NON-NLS-1$
0692:                                    tagOffset));
0693:                        }
0694:                        if (sequence.DEFAULT[i] != null) {
0695:                            values[i] = sequence.DEFAULT[i];
0696:                        }
0697:                    }
0698:                    content = values;
0699:
0700:                    tagOffset = seqTagOffset; //retrieve tag offset
0701:                }
0702:
0703:                if (offset != endOffset) {
0704:                    throw new ASN1Exception(Messages.getString(
0705:                            "security.134", begOffset)); //$NON-NLS-1$
0706:                }
0707:            }
0708:
0709:            /**
0710:             * Decodes ASN.1 SequenceOf type
0711:             *
0712:             * @param sequenceOf - ASN.1 sequence to be decoded
0713:             * @throws IOException - if error occured
0714:             */
0715:            public void readSequenceOf(ASN1SequenceOf sequenceOf)
0716:                    throws IOException {
0717:
0718:                if (tag != ASN1Constants.TAG_C_SEQUENCEOF) {
0719:                    throw new ASN1Exception(Messages.getString(
0720:                            "security.135", tagOffset, //$NON-NLS-1$
0721:                            Integer.toHexString(tag)));
0722:                }
0723:
0724:                decodeValueCollection(sequenceOf);
0725:            }
0726:
0727:            /**
0728:             * Decodes ASN.1 Set type
0729:             *
0730:             * @param set - ASN.1 set to be decoded
0731:             * @throws IOException - if error occured
0732:             */
0733:            public void readSet(ASN1Set set) throws IOException {
0734:
0735:                if (tag != ASN1Constants.TAG_C_SET) {
0736:                    throw new ASN1Exception(Messages.getString("security.136", //$NON-NLS-1$
0737:                            tagOffset, Integer.toHexString(tag)));
0738:                }
0739:
0740:                throw new ASN1Exception(Messages.getString("security.137")); //$NON-NLS-1$
0741:            }
0742:
0743:            /**
0744:             * Decodes ASN.1 SetOf type
0745:             *
0746:             * @param set - ASN.1 set to be decoded
0747:             * @throws IOException - if error occured
0748:             */
0749:            public void readSetOf(ASN1SetOf setOf) throws IOException {
0750:
0751:                if (tag != ASN1Constants.TAG_C_SETOF) {
0752:                    throw new ASN1Exception(Messages.getString("security.138", //$NON-NLS-1$
0753:                            tagOffset, Integer.toHexString(tag)));
0754:                }
0755:
0756:                decodeValueCollection(setOf);
0757:            }
0758:
0759:            private final void decodeValueCollection(
0760:                    ASN1ValueCollection collection) throws IOException {
0761:
0762:                int begOffset = offset;
0763:                int endOffset = begOffset + length;
0764:
0765:                ASN1Type type = collection.type;
0766:
0767:                if (isVerify) {
0768:                    while (endOffset > offset) {
0769:                        next();
0770:                        type.decode(this );
0771:                    }
0772:                } else {
0773:
0774:                    int seqTagOffset = tagOffset; //store tag offset
0775:
0776:                    ArrayList values = new ArrayList();
0777:                    while (endOffset > offset) {
0778:                        next();
0779:                        values.add(type.decode(this ));
0780:                    }
0781:
0782:                    content = values;
0783:
0784:                    tagOffset = seqTagOffset; //retrieve tag offset
0785:                }
0786:
0787:                if (offset != endOffset) {
0788:                    throw new ASN1Exception(Messages.getString(
0789:                            "security.134", begOffset)); //$NON-NLS-1$
0790:                }
0791:            }
0792:
0793:            /**
0794:             * Decodes ASN.1 String type
0795:             *
0796:             * @throws IOException - if an I/O error occurs or the end of the stream is reached
0797:             */
0798:            public void readString(ASN1StringType type) throws IOException {
0799:
0800:                //FIXME check string content
0801:                if (tag == type.id) {
0802:                    readContent();
0803:                } else if (tag == type.constrId) {
0804:                    throw new ASN1Exception(Messages.getString("security.139")); //$NON-NLS-1$
0805:                } else {
0806:                    throw new ASN1Exception(Messages.getString(
0807:                            "security.13A", tagOffset, //$NON-NLS-1$
0808:                            Integer.toHexString(tag)));
0809:                }
0810:            }
0811:
0812:            /**
0813:             * Returns encoded array.
0814:             * 
0815:             * MUST be invoked after decoding corresponding ASN.1 notation  
0816:             */
0817:            public byte[] getEncoded() {
0818:                byte[] encoded = new byte[offset - tagOffset];
0819:                System.arraycopy(buffer, tagOffset, encoded, 0, encoded.length);
0820:                return encoded;
0821:            }
0822:
0823:            /**
0824:             * Returns internal buffer used for decoding
0825:             *
0826:             * @return - buffer
0827:             */
0828:            public final byte[] getBuffer() {
0829:                return buffer;
0830:            }
0831:
0832:            /**
0833:             * Returns length of the current content for decoding
0834:             *
0835:             * @return - length of content
0836:             */
0837:            public final int getLength() {
0838:                return length;
0839:            }
0840:
0841:            /**
0842:             * Returns the current offset
0843:             *
0844:             * @return - offset
0845:             */
0846:            public final int getOffset() {
0847:                return offset;
0848:            }
0849:
0850:            /**
0851:             * Returns end offset for the current encoded type
0852:             *
0853:             * @return - offset
0854:             */
0855:            public final int getEndOffset() {
0856:                return offset + length;
0857:            }
0858:
0859:            /**
0860:             * Returns start offset for the current encoded type
0861:             *
0862:             * @return - offset
0863:             */
0864:            public final int getTagOffset() {
0865:                return tagOffset;
0866:            }
0867:
0868:            public final int getContentOffset() {
0869:                return contentOffset;
0870:            }
0871:
0872:            /**
0873:             * Indicates verify or store mode.
0874:             * 
0875:             * In store mode a decoded content is stored in a newly allocated
0876:             * appropriate object. The <code>content</code> variable holds
0877:             * a reference to the last created object.
0878:             * 
0879:             * In verify mode a decoded content is not stored.
0880:             */
0881:            // FIXME it is used only for one case
0882:            // decoding PCKS#8 Private Key Info notation
0883:            // remove this option because it does decoding more complex
0884:            protected boolean isVerify;
0885:
0886:            /**
0887:             * Sets verify mode.
0888:             */
0889:            public final void setVerify() {
0890:                isVerify = true;
0891:            }
0892:
0893:            /**
0894:             * Indicates defined or indefined reading mode for associated InputStream.
0895:             * 
0896:             * This mode is defined by reading a length
0897:             * for a first ASN.1 type from InputStream.
0898:             */
0899:            protected boolean isIndefinedLength;
0900:
0901:            /**
0902:             * Reads the next encoded byte from the encoded input stream.
0903:             *
0904:             * @return the next encoded byte
0905:             * @throws IOException - if error occured
0906:             */
0907:            protected int read() throws IOException {
0908:
0909:                if (offset == buffer.length) {
0910:                    throw new ASN1Exception(Messages.getString("security.13B")); //$NON-NLS-1$
0911:                }
0912:
0913:                if (in == null) {
0914:                    return buffer[offset++] & 0xFF;
0915:                } else {
0916:                    int octet = in.read();
0917:                    if (octet == -1) {
0918:                        throw new ASN1Exception(Messages
0919:                                .getString("security.13B")); //$NON-NLS-1$
0920:                    }
0921:
0922:                    buffer[offset++] = (byte) octet;
0923:
0924:                    return octet;
0925:                }
0926:            }
0927:
0928:            /**
0929:             * Reads the next encoded content from the encoded input stream.
0930:             * The method MUST be used for reading a primitive encoded content.
0931:             *
0932:             * @throws IOException - if error occured
0933:             */
0934:            public void readContent() throws IOException {
0935:                if (offset + length > buffer.length) {
0936:                    throw new ASN1Exception(Messages.getString("security.13B")); //$NON-NLS-1$
0937:                }
0938:
0939:                if (in == null) {
0940:                    offset += length;
0941:                } else {
0942:                    int bytesRead = in.read(buffer, offset, length);
0943:
0944:                    if (bytesRead != length) {
0945:                        // if input stream didn't return all data at once
0946:                        // try to read it in several blocks
0947:                        int c = bytesRead;
0948:                        do {
0949:                            if (c < 1 || bytesRead > length) {
0950:                                throw new ASN1Exception(Messages
0951:                                        .getString("security.13C")); //$NON-NLS-1$
0952:                            }
0953:                            c = in.read(buffer, offset + bytesRead, length
0954:                                    - bytesRead);
0955:                            bytesRead += c;
0956:                        } while (bytesRead != length);
0957:                    }
0958:
0959:                    offset += length;
0960:                }
0961:            }
0962:
0963:            //    // reallocates internal buffer for indefined reading mode
0964:            //    private void reallocateBuffer(int n) {
0965:            //        int newSize;
0966:            //        for (newSize = buffer.length * 2; newSize < buffer.length + n; newSize = newSize * 2)
0967:            //            ;
0968:            //        byte[] newBuffer = new byte[newSize];
0969:            //        System.arraycopy(buffer, 0, newBuffer, 0, buffer.length);
0970:            //        buffer = newBuffer;
0971:            //    }
0972:
0973:            /**
0974:             * Reallocates the buffer in order to make it
0975:             * exactly the size of data it contains
0976:             */
0977:            public void compactBuffer() {
0978:                if (offset != buffer.length) {
0979:                    byte[] newBuffer = new byte[offset];
0980:                    // restore buffer content
0981:                    System.arraycopy(buffer, 0, newBuffer, 0, offset);
0982:                    // set new buffer
0983:                    buffer = newBuffer;
0984:                }
0985:            }
0986:
0987:            //
0988:            //
0989:            //
0990:            //
0991:            //
0992:
0993:            private Object[][] pool;
0994:
0995:            public void put(Object key, Object entry) {
0996:
0997:                if (pool == null) {
0998:                    pool = new Object[2][10];
0999:                }
1000:
1001:                int i = 0;
1002:                for (; i < pool[0].length && pool[0][i] != null; i++) {
1003:                    if (pool[0][i] == key) {
1004:                        pool[1][i] = entry;
1005:                        return;
1006:                    }
1007:                }
1008:
1009:                if (i == pool[0].length) {
1010:                    Object[][] newPool = new Object[pool[0].length * 2][2];
1011:                    System.arraycopy(pool[0], 0, newPool[0], 0, pool[0].length);
1012:                    System.arraycopy(pool[1], 0, newPool[1], 0, pool[0].length);
1013:                    pool = newPool;
1014:                } else {
1015:                    pool[0][i] = key;
1016:                    pool[1][i] = entry;
1017:                }
1018:            }
1019:
1020:            public Object get(Object key) {
1021:
1022:                if (pool == null) {
1023:                    return null;
1024:                }
1025:
1026:                for (int i = 0; i < pool[0].length; i++) {
1027:                    if (pool[0][i] == key) {
1028:                        return pool[1][i];
1029:                    }
1030:                }
1031:                return null;
1032:            }
1033:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.