Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/sun/security/util/DerIndefLenConverter.java
38830 views
/*1* Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package sun.security.util;2627import java.io.IOException;28import java.util.ArrayList;2930/**31* A package private utility class to convert indefinite length DER32* encoded byte arrays to definite length DER encoded byte arrays.33*34* This assumes that the basic data structure is "tag, length, value"35* triplet. In the case where the length is "indefinite", terminating36* end-of-contents bytes are expected.37*38* @author Hemma Prafullchandra39*/40class DerIndefLenConverter {4142private static final int TAG_MASK = 0x1f; // bits 5-143private static final int FORM_MASK = 0x20; // bits 644private static final int CLASS_MASK = 0xC0; // bits 8 and 74546private static final int LEN_LONG = 0x80; // bit 8 set47private static final int LEN_MASK = 0x7f; // bits 7 - 148private static final int SKIP_EOC_BYTES = 2;4950private byte[] data, newData;51private int newDataPos, dataPos, dataSize, index;52private int unresolved = 0;5354private ArrayList<Object> ndefsList = new ArrayList<Object>();5556private int numOfTotalLenBytes = 0;5758private boolean isEOC(int tag) {59return (((tag & TAG_MASK) == 0x00) && // EOC60((tag & FORM_MASK) == 0x00) && // primitive61((tag & CLASS_MASK) == 0x00)); // universal62}6364// if bit 8 is set then it implies either indefinite length or long form65static boolean isLongForm(int lengthByte) {66return ((lengthByte & LEN_LONG) == LEN_LONG);67}6869/*70* Default package private constructor71*/72DerIndefLenConverter() { }7374/**75* Checks whether the given length byte is of the form76* <em>Indefinite</em>.77*78* @param lengthByte the length byte from a DER encoded79* object.80* @return true if the byte is of Indefinite form otherwise81* returns false.82*/83static boolean isIndefinite(int lengthByte) {84return (isLongForm(lengthByte) && ((lengthByte & LEN_MASK) == 0));85}8687/**88* Parse the tag and if it is an end-of-contents tag then89* add the current position to the <code>eocList</code> vector.90*/91private void parseTag() throws IOException {92if (dataPos == dataSize)93return;94try {95if (isEOC(data[dataPos]) && (data[dataPos + 1] == 0)) {96int numOfEncapsulatedLenBytes = 0;97Object elem = null;98int index;99for (index = ndefsList.size()-1; index >= 0; index--) {100// Determine the first element in the vector that does not101// have a matching EOC102elem = ndefsList.get(index);103if (elem instanceof Integer) {104break;105} else {106numOfEncapsulatedLenBytes += ((byte[])elem).length - 3;107}108}109if (index < 0) {110throw new IOException("EOC does not have matching " +111"indefinite-length tag");112}113int sectionLen = dataPos - ((Integer)elem).intValue() +114numOfEncapsulatedLenBytes;115byte[] sectionLenBytes = getLengthBytes(sectionLen);116ndefsList.set(index, sectionLenBytes);117unresolved--;118119// Add the number of bytes required to represent this section120// to the total number of length bytes,121// and subtract the indefinite-length tag (1 byte) and122// EOC bytes (2 bytes) for this section123numOfTotalLenBytes += (sectionLenBytes.length - 3);124}125dataPos++;126} catch (IndexOutOfBoundsException iobe) {127throw new IOException(iobe);128}129}130131/**132* Write the tag and if it is an end-of-contents tag133* then skip the tag and its 1 byte length of zero.134*/135private void writeTag() {136if (dataPos == dataSize)137return;138int tag = data[dataPos++];139if (isEOC(tag) && (data[dataPos] == 0)) {140dataPos++; // skip length141writeTag();142} else143newData[newDataPos++] = (byte)tag;144}145146/**147* Parse the length and if it is an indefinite length then add148* the current position to the <code>ndefsList</code> vector.149*/150private int parseLength() throws IOException {151int curLen = 0;152if (dataPos == dataSize)153return curLen;154int lenByte = data[dataPos++] & 0xff;155if (isIndefinite(lenByte)) {156ndefsList.add(new Integer(dataPos));157unresolved++;158return curLen;159}160if (isLongForm(lenByte)) {161lenByte &= LEN_MASK;162if (lenByte > 4) {163throw new IOException("Too much data");164}165if ((dataSize - dataPos) < (lenByte + 1)) {166throw new IOException("Too little data");167}168for (int i = 0; i < lenByte; i++) {169curLen = (curLen << 8) + (data[dataPos++] & 0xff);170}171if (curLen < 0) {172throw new IOException("Invalid length bytes");173}174} else {175curLen = (lenByte & LEN_MASK);176}177return curLen;178}179180/**181* Write the length and if it is an indefinite length182* then calculate the definite length from the positions183* of the indefinite length and its matching EOC terminator.184* Then, write the value.185*/186private void writeLengthAndValue() throws IOException {187if (dataPos == dataSize)188return;189int curLen = 0;190int lenByte = data[dataPos++] & 0xff;191if (isIndefinite(lenByte)) {192byte[] lenBytes = (byte[])ndefsList.get(index++);193System.arraycopy(lenBytes, 0, newData, newDataPos,194lenBytes.length);195newDataPos += lenBytes.length;196return;197}198if (isLongForm(lenByte)) {199lenByte &= LEN_MASK;200for (int i = 0; i < lenByte; i++) {201curLen = (curLen << 8) + (data[dataPos++] & 0xff);202}203if (curLen < 0) {204throw new IOException("Invalid length bytes");205}206} else {207curLen = (lenByte & LEN_MASK);208}209writeLength(curLen);210writeValue(curLen);211}212213private void writeLength(int curLen) {214if (curLen < 128) {215newData[newDataPos++] = (byte)curLen;216217} else if (curLen < (1 << 8)) {218newData[newDataPos++] = (byte)0x81;219newData[newDataPos++] = (byte)curLen;220221} else if (curLen < (1 << 16)) {222newData[newDataPos++] = (byte)0x82;223newData[newDataPos++] = (byte)(curLen >> 8);224newData[newDataPos++] = (byte)curLen;225226} else if (curLen < (1 << 24)) {227newData[newDataPos++] = (byte)0x83;228newData[newDataPos++] = (byte)(curLen >> 16);229newData[newDataPos++] = (byte)(curLen >> 8);230newData[newDataPos++] = (byte)curLen;231232} else {233newData[newDataPos++] = (byte)0x84;234newData[newDataPos++] = (byte)(curLen >> 24);235newData[newDataPos++] = (byte)(curLen >> 16);236newData[newDataPos++] = (byte)(curLen >> 8);237newData[newDataPos++] = (byte)curLen;238}239}240241private byte[] getLengthBytes(int curLen) {242byte[] lenBytes;243int index = 0;244245if (curLen < 128) {246lenBytes = new byte[1];247lenBytes[index++] = (byte)curLen;248249} else if (curLen < (1 << 8)) {250lenBytes = new byte[2];251lenBytes[index++] = (byte)0x81;252lenBytes[index++] = (byte)curLen;253254} else if (curLen < (1 << 16)) {255lenBytes = new byte[3];256lenBytes[index++] = (byte)0x82;257lenBytes[index++] = (byte)(curLen >> 8);258lenBytes[index++] = (byte)curLen;259260} else if (curLen < (1 << 24)) {261lenBytes = new byte[4];262lenBytes[index++] = (byte)0x83;263lenBytes[index++] = (byte)(curLen >> 16);264lenBytes[index++] = (byte)(curLen >> 8);265lenBytes[index++] = (byte)curLen;266267} else {268lenBytes = new byte[5];269lenBytes[index++] = (byte)0x84;270lenBytes[index++] = (byte)(curLen >> 24);271lenBytes[index++] = (byte)(curLen >> 16);272lenBytes[index++] = (byte)(curLen >> 8);273lenBytes[index++] = (byte)curLen;274}275276return lenBytes;277}278279// Returns the number of bytes needed to represent the given length280// in ASN.1 notation281private int getNumOfLenBytes(int len) {282int numOfLenBytes = 0;283284if (len < 128) {285numOfLenBytes = 1;286} else if (len < (1 << 8)) {287numOfLenBytes = 2;288} else if (len < (1 << 16)) {289numOfLenBytes = 3;290} else if (len < (1 << 24)) {291numOfLenBytes = 4;292} else {293numOfLenBytes = 5;294}295return numOfLenBytes;296}297298/**299* Parse the value;300*/301private void parseValue(int curLen) {302dataPos += curLen;303}304305/**306* Write the value;307*/308private void writeValue(int curLen) {309for (int i=0; i < curLen; i++)310newData[newDataPos++] = data[dataPos++];311}312313/**314* Converts a indefinite length DER encoded byte array to315* a definte length DER encoding.316*317* @param indefData the byte array holding the indefinite318* length encoding.319* @return the byte array containing the definite length320* DER encoding.321* @exception IOException on parsing or re-writing errors.322*/323byte[] convert(byte[] indefData) throws IOException {324data = indefData;325dataPos=0; index=0;326dataSize = data.length;327int len=0;328int unused = 0;329330// parse and set up the vectors of all the indefinite-lengths331while (dataPos < dataSize) {332parseTag();333len = parseLength();334parseValue(len);335if (unresolved == 0) {336unused = dataSize - dataPos;337dataSize = dataPos;338break;339}340}341342if (unresolved != 0) {343throw new IOException("not all indef len BER resolved");344}345346newData = new byte[dataSize + numOfTotalLenBytes + unused];347dataPos=0; newDataPos=0; index=0;348349// write out the new byte array replacing all the indefinite-lengths350// and EOCs351while (dataPos < dataSize) {352writeTag();353writeLengthAndValue();354}355System.arraycopy(indefData, dataSize,356newData, dataSize + numOfTotalLenBytes, unused);357358return newData;359}360}361362363