private int strToInt(int off, int count) throws ASN1Exception { int result = 0; for (int i = off, end = off + count; i < end; i++) { int c = buffer[i] - 48; if (c < 0 || c > 9) { throw new ASN1Exception("Time encoding has invalid char"); } result = result * 10 + c; } return result; }
private ASN1Exception expected(String what) throws ASN1Exception { throw new ASN1Exception("ASN.1 " + what + " identifier expected at [" + tagOffset + "], got " + Integer.toHexString(tag)); }
/** * Reads the next encoded byte from the encoded input stream. */ protected int read() throws IOException { if (offset == buffer.length) { throw new ASN1Exception("Unexpected end of encoding"); } if (in == null) { return buffer[offset++] & 0xFF; } else { int octet = in.read(); if (octet == -1) { throw new ASN1Exception("Unexpected end of encoding"); } buffer[offset++] = (byte) octet; return octet; } }
public void readUTCTime() throws IOException { if (tag == ASN1Constants.TAG_C_UTCTIME) { // It is a string type and it can be encoded as primitive or constructed. throw new ASN1Exception("ASN.1 UTCTime: constructed identifier at [" + tagOffset + "]. Not valid for DER."); } // check format: DER uses YYMMDDHHMMSS'Z' only if (length != ASN1UTCTime.UTC_HMS) { throw new ASN1Exception("ASN.1 UTCTime: wrong format for DER, identifier at [" + tagOffset + "]"); } super.readUTCTime(); }
public void readBitString() throws IOException { if (tag == ASN1Constants.TAG_C_BITSTRING) { throw new ASN1Exception("ASN.1 bitstring: constructed identifier at [" + tagOffset + "]. Not valid for DER."); } super.readBitString(); //check: unused bits values - MUST be 0 if (length > 1 && buffer[contentOffset] != 0 && (buffer[offset - 1] & UNUSED_BITS_MASK[buffer[contentOffset] - 1]) != 0) { throw new ASN1Exception("ASN.1 bitstring: wrong content at [" + contentOffset + "]. DER requires zero unused bits in final octet."); } }
public int next() throws IOException { int tag = super.next(); if (length == INDEFINIT_LENGTH) { throw new ASN1Exception("DER: only definite length encoding MUST be used"); } // FIXME add check: length encoding uses minimum number of octets return tag; }
public void readOctetString() throws IOException { if (tag == ASN1Constants.TAG_C_OCTETSTRING) { throw new ASN1Exception("ASN.1 octetstring: constructed identifier at [" + tagOffset + "]. Not valid for DER."); } super.readOctetString(); }
/** * Decodes ASN.1 Set type */ public void readSet(ASN1Set set) throws IOException { if (tag != ASN1Constants.TAG_C_SET) { throw expected("set"); } throw new ASN1Exception("Decoding ASN.1 Set type is not supported"); }
public void readGeneralizedTime() throws IOException { if (tag == ASN1Constants.TAG_C_GENERALIZEDTIME) { // It is a string type and it can be encoded as primitive or constructed. throw new ASN1Exception("ASN.1 GeneralizedTime: constructed identifier at [" + tagOffset + "]. Not valid for DER."); } super.readGeneralizedTime(); } }
public void readString(ASN1StringType type) throws IOException { if (tag == type.constrId) { throw new ASN1Exception("ASN.1 string: constructed identifier at [" + tagOffset + "]. Not valid for DER."); } super.readString(type); }
public void readBoolean() throws IOException { super.readBoolean(); // check encoded content if (buffer[contentOffset] != 0 && buffer[contentOffset] != (byte) 0xFF) { throw new ASN1Exception("ASN.1 boolean: wrong content at [" + contentOffset + "]. DER allows only 0x00 or 0xFF values"); } }
/** * Creates stream for decoding. * * @param encoded bytes array to be decoded * @param offset the encoding offset * @param expectedLength expected length of full encoding, this includes * identifier, length an content octets */ public BerInputStream(byte[] encoded, int offset, int expectedLength) throws IOException { this.in = null; this.buffer = encoded; this.offset = offset; next(); // compare expected and decoded length if (length != INDEFINIT_LENGTH && (offset + expectedLength) != (this.offset + this.length)) { throw new ASN1Exception("Wrong content length"); } }
public Object decode(BerInputStream in) throws IOException { int index = Arrays.binarySearch(identifiers[0], in.tag); if (index < 0) { throw new ASN1Exception("Failed to decode ASN.1 choice type. No alternatives were found for " + getClass().getName());// FIXME message } index = identifiers[1][index]; in.content = type[index].decode(in); // set index for getDecodedObject method in.choiceIndex = index; if (in.isVerify) { return null; } return getDecodedObject(in); }
/** * Creates stream for decoding. * * @param initialSize the internal buffer initial size */ public BerInputStream(InputStream in, int initialSize) throws IOException { this.in = in; buffer = new byte[initialSize]; next(); if (length != INDEFINIT_LENGTH) { // input stream has definite length encoding // check allocated length to avoid further reallocations if (buffer.length < (length + offset)) { byte[] newBuffer = new byte[length + offset]; System.arraycopy(buffer, 0, newBuffer, 0, offset); buffer = newBuffer; } } else { isIndefinedLength = true; throw new ASN1Exception("Decoding indefinite length encoding is not supported"); } }
/** * Decodes ASN.1 Integer type */ public void readInteger() throws IOException { if (tag != ASN1Constants.TAG_INTEGER) { throw expected("integer"); } // check encoded length if (length < 1) { throw new ASN1Exception("Wrong length for ASN.1 integer at [" + tagOffset + "]"); } readContent(); // check encoded content if (length > 1) { byte firstByte = buffer[offset - length]; byte secondByte = (byte) (buffer[offset - length + 1] & 0x80); if (firstByte == 0 && secondByte == 0 || firstByte == (byte) 0xFF && secondByte == (byte) 0x80) { throw new ASN1Exception("Wrong content for ASN.1 integer at [" + (offset - length) + "]. An integer MUST be encoded in minimum number of octets"); } } }
/** * Decodes ASN.1 Octetstring type */ public void readOctetString() throws IOException { if (tag == ASN1Constants.TAG_OCTETSTRING) { readContent(); } else if (tag == ASN1Constants.TAG_C_OCTETSTRING) { throw new ASN1Exception("Decoding constructed ASN.1 octet string type is not supported"); } else { throw expected("octetstring"); } }
public Object decode(BerInputStream in) throws IOException { if (constrId != in.tag) { throw new ASN1Exception("ASN.1 explicitly tagged type is expected at [" + in.tagOffset + "]. Expected tag: " + Integer.toHexString(constrId) + ", " + "but encountered tag " + Integer.toHexString(in.tag)); } in.next(); in.content = type.decode(in); if (in.isVerify) { return null; } return getDecodedObject(in); }
/** * Decodes ASN.1 boolean type */ public void readBoolean() throws IOException { if (tag != ASN1Constants.TAG_BOOLEAN) { throw expected("boolean"); } // check encoded length if (length != 1) { throw new ASN1Exception("Wrong length for ASN.1 boolean at [" + tagOffset + "]"); } readContent(); }
/** * Decodes ASN.1 String type * * @throws IOException if an I/O error occurs or the end of the stream is reached */ public void readString(ASN1StringType type) throws IOException { if (tag == type.id) { readContent(); } else if (tag == type.constrId) { throw new ASN1Exception("Decoding constructed ASN.1 string type is not provided"); } else { throw expected("string"); } }
public Object decode(BerInputStream in) throws IOException { if (!checkTag(in.tag)) { // FIXME need look for tagging type throw new ASN1Exception("ASN.1 implicitly tagged type expected at " + "[" + in.tagOffset + "]. Expected tag: " + Integer.toHexString(id) + ", " + "but got " + Integer.toHexString(in.tag)); } // substitute identifier for further decoding if (id == in.tag) { in.tag = type.id; } else { in.tag = type.constrId; } in.content = type.decode(in); if (in.isVerify) { return null; } return getDecodedObject(in); }