diff options
Diffstat (limited to 'bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/signedcontent/BERProcessor.java')
-rw-r--r-- | bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/signedcontent/BERProcessor.java | 274 |
1 files changed, 274 insertions, 0 deletions
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/signedcontent/BERProcessor.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/signedcontent/BERProcessor.java new file mode 100644 index 000000000..57b985226 --- /dev/null +++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/signedcontent/BERProcessor.java @@ -0,0 +1,274 @@ +/******************************************************************************* + * Copyright (c) 2006, 2007 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.osgi.internal.signedcontent; + +import java.math.BigInteger; +import java.security.SignatureException; + +/** + * This is a simple class that processes BER structures. This class + * uses BER processing as outlined in X.690. + */ +public class BERProcessor { + /** + * This is the buffer that contains the BER structures that are being interrogated. + */ + byte buffer[]; + /** + * The offset into <code>buffer</code> to the start of the structure being interrogated. + * If the offset is -1 that means that we have read the last structure. + */ + int offset; + /** + * The last valid offset in <code>buffer</code>. + */ + int lastOffset; + /** + * The offset into <code>buffer</code> to the start of the content of the structure + * being interrogated. + */ + int contentOffset; + /** + * The length of the content of the structure being interrogated. + */ + int contentLength; + /** + * The offset into <code>buffer</code> of the end of the structure being interrogated. + */ + int endOffset; + /** + * The class of the tag of the current structure. + */ + int classOfTag; + static final int UNIVERSAL_TAGCLASS = 0; + static final int APPLICATION_TAGCLASS = 1; + static final int CONTEXTSPECIFIC_TAGCLASS = 2; + static final int PRIVATE_TAGCLASS = 3; + + static final byte BOOLTAG = 1; + static final byte INTTAG = 2; + static final byte OIDTAG = 6; + static final byte SEQTAG = 16; + static final byte SETTAG = 17; + static final byte NULLTAG = 5; + + /** + * Tagnames used in toString() + */ + static final String tagNames[] = {"<null>", "boolean", "int", "bitstring", "octetstring", "null", "objid", "objdesc", "external", "real", "enum", "pdv", "utf8", "relobjid", "resv", "resv", "sequence", "set", "char string"}; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$ //$NON-NLS-9$ //$NON-NLS-10$ //$NON-NLS-11$ //$NON-NLS-12$ //$NON-NLS-13$ //$NON-NLS-14$ //$NON-NLS-15$ //$NON-NLS-16$ //$NON-NLS-17$ //$NON-NLS-18$ //$NON-NLS-19$ + + /** + * True if this is a structure for a constructed encoding. + */ + public boolean constructed; + /** + * The tag type. Note that X.690 specifies encodings for tags with values greater than 31, + * but currently this class does not handle these kinds of tags. + */ + public byte tag; + + /** + * Constructs a BERProcessor to operate on the passed buffer. The first structure in the + * buffer will be processed before this method returns. + * + * @param buffer the buffer containing the BER structures. + * @param offset the offset into <code>buffer</code> to the start of the first structure. + * @param len the length of the BER structure. + * @throws SignatureException + */ + public BERProcessor(byte buffer[], int offset, int len) throws SignatureException { + this.buffer = buffer; + this.offset = offset; + lastOffset = len + offset; + processStructure(); + } + + /** + * Parse the structure found at the current <code>offset</code> into <code>buffer</code>. + * Most methods, constructor, and stepinto, will call this method automatically. If + * <code>offset</code> is modified outside of those methods, this method will need to + * be invoked. + */ + public void processStructure() throws SignatureException { + // Don't process if we are at the end + if (offset == -1) + return; + endOffset = offset; + // section 8.1.2.2 + classOfTag = (buffer[offset] & 0xff) >> 6; + // section 8.1.2.5 + constructed = (buffer[offset] & 0x20) != 0; + // section 8.1.2.3 + byte tagNumber = (byte) (buffer[offset] & 0x1f); + if (tagNumber < 32) { + tag = tagNumber; + endOffset = offset + 1; + } else { + throw new SignatureException("Can't handle tags > 32"); //$NON-NLS-1$ + } + if ((buffer[endOffset] & 0x80) == 0) { + // section 8.1.3.4 (doing the short form of the length) + contentLength = buffer[endOffset]; + endOffset++; + } else { + // section 8.1.3.5 (doing the long form of the length) + int octetCount = buffer[endOffset] & 0x7f; + if (octetCount > 3) + throw new SignatureException("ContentLength octet count too large: " + octetCount); //$NON-NLS-1$ + contentLength = 0; + endOffset++; + for (int i = 0; i < octetCount; i++) { + contentLength <<= 8; + contentLength |= buffer[endOffset] & 0xff; + endOffset++; + } + // section 8.1.3.6 (doing the indefinite form + if (octetCount == 0) + contentLength = -1; + } + contentOffset = endOffset; + if (contentLength != -1) + endOffset += contentLength; + if (endOffset > lastOffset) + throw new SignatureException("Content length too large: " + endOffset + " > " + lastOffset); //$NON-NLS-1$ //$NON-NLS-2$ + } + + /** + * Returns a String representation of the current BER structure. + * @return a String representation of the current BER structure. + * @see java.lang.Object#toString() + */ + public String toString() { + StringBuffer sb = new StringBuffer(); + switch (classOfTag) { + case UNIVERSAL_TAGCLASS : + sb.append('U'); + break; + case APPLICATION_TAGCLASS : + sb.append('A'); + break; + case CONTEXTSPECIFIC_TAGCLASS : + sb.append('C'); + break; + case PRIVATE_TAGCLASS : + sb.append('P'); + break; + } + sb.append(constructed ? 'C' : 'P'); + sb.append(" tag=" + tag); //$NON-NLS-1$ + if (tag < tagNames.length) { + sb.append("(" + tagNames[tag] + ")"); //$NON-NLS-1$ //$NON-NLS-2$ + } + sb.append(" len="); //$NON-NLS-1$ + sb.append(contentLength); + switch (tag) { + case INTTAG : + sb.append(" value=" + getIntValue()); //$NON-NLS-1$ + break; + case OIDTAG : + sb.append(" value="); //$NON-NLS-1$ + int oid[] = getObjId(); + for (int i = 0; i < oid.length; i++) { + if (i > 0) + sb.append('.'); + sb.append(oid[i]); + } + } + if (tag == 12 || (tag >= 18 && tag <= 22) || (tag >= 25 && tag <= 30)) { + sb.append(" value="); //$NON-NLS-1$ + sb.append(getString()); + } + return sb.toString(); + } + + /** + * Returns a BERProcessor for the content of the current structure. + * @throws SignatureException + */ + public BERProcessor stepInto() throws SignatureException { + return new BERProcessor(buffer, contentOffset, contentLength); + } + + public void stepOver() throws SignatureException { + offset = endOffset; + if (endOffset >= lastOffset) { + offset = -1; + return; + } + processStructure(); + } + + public boolean endOfSequence() { + return offset == -1; + } + + /** + * Gets the content from the current structure as a String. + * @return the content from the current structure as a String. + */ + public String getString() { + return new String(buffer, contentOffset, contentLength); + } + + /** + * Gets the content from the current structure as an int. + * @return the content from the current structure as an int. + */ + public BigInteger getIntValue() { + return new BigInteger(getBytes()); + } + + /** + * Gets the content from the current structure as an object id (int[]). + * @return the content from the current structure as an object id (int[]). + */ + public int[] getObjId() { + // First count the ids + int count = 0; + for (int i = 0; i < contentLength; i++) { + // section 8.19.2 + if ((buffer[contentOffset + i] & 0x80) == 0) + count++; + } + count++; // section 8.19.3 + int oid[] = new int[count]; + int index = 0; + int currentValue = 0; + for (int i = 0; i < contentLength; i++) { + currentValue <<= 7; + currentValue |= buffer[contentOffset + i] & 0x7f; + // section 8.19.2 + if ((buffer[contentOffset + i] & 0x80) == 0) { + if (index == 0) { + // section 8.19.4 special processing + oid[index++] = currentValue / 40; + oid[index++] = currentValue % 40; + } else { + oid[index++] = currentValue; + } + currentValue = 0; + } + } + return oid; + } + + /** + * Get a copy of the bytes in the content of the current structure. + * @return a copy of the bytes in the content of the current structure. + */ + public byte[] getBytes() { + byte v[] = new byte[contentLength]; + System.arraycopy(buffer, contentOffset, v, 0, contentLength); + return v; + } + +} |