Ejemplo n.º 1
0
        private void ParseAsn1Item(XmlNode currentXmlNode, byte[] currentBytesToParse, long index)
        {
            int          buffer;
            int          buffer2;
            int          lengthCounter;
            XmlAttribute newXmlAttribute;
            XmlNode      newChildXmlNode;
            XmlNode      rawDataXmlNode;
            string       valueBuffer;
            UInt64       integerBuffer;

            while (index < currentBytesToParse.Length)
            {
                Asn1ItemData asn1ItemData = this.GetItemData(currentBytesToParse, true, ref index);

                newChildXmlNode = currentXmlNode.OwnerDocument.CreateElement(asn1ItemData.TagName);

                newXmlAttribute       = currentXmlNode.OwnerDocument.CreateAttribute("Length");
                newXmlAttribute.Value = asn1ItemData.BytesToParseLength.ToString();
                newChildXmlNode.Attributes.Append(newXmlAttribute);
                rawDataXmlNode           = currentXmlNode.OwnerDocument.CreateElement("RawData");
                rawDataXmlNode.InnerText = Convert.ToBase64String(asn1ItemData.BytesToParse);
                newChildXmlNode.AppendChild(rawDataXmlNode);
                currentXmlNode.AppendChild(newChildXmlNode);

                if (asn1ItemData.TagConstructedFlag == TagConstructed.Constructed)
                {                 //Recurse
                    long indexForNextRecursion = 0;
                    this.ParseAsn1Item(newChildXmlNode, asn1ItemData.BytesToParse, indexForNextRecursion);
                }
                else
                {
                    valueBuffer = "";
                    if (asn1ItemData.TagClass == TagClasses.Universal)
                    {
                        switch (asn1ItemData.TagNumber)
                        {
                        case UniversalTags.Boolean:
                            if (asn1ItemData.BytesToParse[0] != 0 && asn1ItemData.BytesToParse[0] != 0xFF)
                            {
                                throw new Exception("BOOLEAN containf wrong value (" + asn1ItemData.BytesToParse[0].ToString("X2") + ")");
                            }
                            else
                            {
                                if (asn1ItemData.BytesToParse[0] == 0xFF)
                                {
                                    valueBuffer = "True";
                                }
                                else
                                {
                                    valueBuffer = "False";
                                }
                            }
                            newXmlAttribute       = currentXmlNode.OwnerDocument.CreateAttribute("Value");
                            newXmlAttribute.Value = valueBuffer;
                            newChildXmlNode.Attributes.Append(newXmlAttribute);
                            break;

                        case UniversalTags.Oid:
                            if (asn1ItemData.BytesToParseLength > MAX_OID_SIZE)
                            {
                                throw new Exception("OID length (" + asn1ItemData.BytesToParseLength + ") > MAX_OID_SIZE");
                            }
                            //Format the OID
                            buffer  = asn1ItemData.BytesToParse[0] / 40;
                            buffer2 = asn1ItemData.BytesToParse[0] % 40;
                            if (buffer > 2)
                            {                                    //Some OID magic: shave of any excess (>2) of buffer and add to buffer2
                                buffer2 += (buffer - 2) * 40;
                                buffer   = 2;
                            }
                            valueBuffer = string.Format("{0}.{1}", buffer, buffer2);

                            buffer = 0;
                            for (lengthCounter = 1; lengthCounter < asn1ItemData.BytesToParseLength; lengthCounter++)
                            {
                                buffer = (buffer << 7) | (asn1ItemData.BytesToParse[lengthCounter] & 0x7F);
                                if ((asn1ItemData.BytesToParse[lengthCounter] & 0x80) == 0)
                                {
                                    valueBuffer += string.Format(".{0}", buffer);
                                    buffer       = 0;
                                }
                            }
                            newXmlAttribute       = currentXmlNode.OwnerDocument.CreateAttribute("Value");
                            newXmlAttribute.Value = valueBuffer;
                            newChildXmlNode.Attributes.Append(newXmlAttribute);
                            break;

                        case UniversalTags.Integer:
                        case UniversalTags.Enumerated:
                            if (asn1ItemData.BytesToParseLength < 9)
                            {
                                integerBuffer = 0;
                                for (lengthCounter = 0; lengthCounter < asn1ItemData.BytesToParseLength; lengthCounter++)
                                {
                                    integerBuffer = (integerBuffer << 8) | asn1ItemData.BytesToParse[lengthCounter];
                                }
                                valueBuffer = integerBuffer.ToString();
                            }
                            else
                            {
                                for (lengthCounter = 0; lengthCounter < asn1ItemData.BytesToParseLength; lengthCounter++)
                                {
                                    valueBuffer += asn1ItemData.BytesToParse[lengthCounter].ToString("X2") + " ";
                                }
                            }
                            newXmlAttribute       = currentXmlNode.OwnerDocument.CreateAttribute("Value");
                            newXmlAttribute.Value = valueBuffer;
                            newChildXmlNode.Attributes.Append(newXmlAttribute);
                            break;

                        case UniversalTags.OctetString:
                            long indexForNextRecursion = 0;

                            Asn1ItemData probeAsn1ItemData = this.GetItemData(asn1ItemData.BytesToParse, false, ref indexForNextRecursion);
                            if (probeAsn1ItemData != null)
                            {
                                if (probeAsn1ItemData.BytesToParseLength + probeAsn1ItemData.HeaderLength == asn1ItemData.BytesToParseLength)
                                {
                                    indexForNextRecursion = 0;
                                    this.ParseAsn1Item(newChildXmlNode, asn1ItemData.BytesToParse, indexForNextRecursion);
                                }
                                else
                                {
                                    for (lengthCounter = 0; lengthCounter < asn1ItemData.BytesToParseLength; lengthCounter++)
                                    {
                                        valueBuffer += asn1ItemData.BytesToParse[lengthCounter].ToString("X2") + " ";
                                    }
                                    newXmlAttribute       = currentXmlNode.OwnerDocument.CreateAttribute("Value");
                                    newXmlAttribute.Value = valueBuffer;
                                    newChildXmlNode.Attributes.Append(newXmlAttribute);
                                }
                            }
                            else
                            {
                                for (lengthCounter = 0; lengthCounter < asn1ItemData.BytesToParseLength; lengthCounter++)
                                {
                                    valueBuffer += asn1ItemData.BytesToParse[lengthCounter].ToString("X2") + " ";
                                }
                                newXmlAttribute       = currentXmlNode.OwnerDocument.CreateAttribute("Value");
                                newXmlAttribute.Value = valueBuffer;
                                newChildXmlNode.Attributes.Append(newXmlAttribute);
                            }
                            break;

                        case UniversalTags.Utf8String:
                        //TODO: Utf8String is not the same as PrintableString
                        case UniversalTags.BmpString:
                        //TODO: BmpString is not the same as PrintableString
                        case UniversalTags.VisibleString:
                        //TODO: VisibleString is not the same as PrintableString
                        case UniversalTags.IA5String:
                        //TODO: IA5String is not the same as PrintableString
                        case UniversalTags.PrintableString:
                            for (lengthCounter = 0; lengthCounter < asn1ItemData.BytesToParseLength; lengthCounter++)
                            {
                                valueBuffer += (char)asn1ItemData.BytesToParse[lengthCounter];
                            }
                            newXmlAttribute       = currentXmlNode.OwnerDocument.CreateAttribute("Value");
                            newXmlAttribute.Value = valueBuffer;
                            newChildXmlNode.Attributes.Append(newXmlAttribute);

                            break;

                        case UniversalTags.GeneralizedTime:
                            if (asn1ItemData.BytesToParseLength < 15)
                            {
                                throw new Exception("Genralized time has to be at least 15 bytes long (" + asn1ItemData.BytesToParseLength.ToString() + ")");
                            }
                            else
                            {
                                valueBuffer           = this.GetTime(asn1ItemData.BytesToParse, false);
                                newXmlAttribute       = currentXmlNode.OwnerDocument.CreateAttribute("Value");
                                newXmlAttribute.Value = valueBuffer;
                                newChildXmlNode.Attributes.Append(newXmlAttribute);
                            }
                            break;

                        case UniversalTags.UtcTime:
                            if (asn1ItemData.BytesToParseLength != 13)
                            {
                                throw new Exception("UTC time has to be 13 bytes long (" + asn1ItemData.BytesToParseLength.ToString() + ")");
                            }
                            else
                            {
                                valueBuffer           = this.GetTime(asn1ItemData.BytesToParse, true);
                                newXmlAttribute       = currentXmlNode.OwnerDocument.CreateAttribute("Value");
                                newXmlAttribute.Value = valueBuffer;
                                newChildXmlNode.Attributes.Append(newXmlAttribute);
                            }
                            break;

                        case UniversalTags.BitString:
                            int unusedBits = asn1ItemData.BytesToParse[0];
                            if (unusedBits < 0 || unusedBits > 7)
                            {
                                throw new Exception("Unused bits of bistring out of range [1-7] (" + unusedBits.ToString() + ")");
                            }
                            byte bitmask = 0x80;
                            if (asn1ItemData.BytesToParseLength - 1 < 5)
                            {                                     //Short enough to show bits
                                for (lengthCounter = 1; lengthCounter < asn1ItemData.BytesToParseLength; lengthCounter++)
                                {
                                    if (lengthCounter != (asn1ItemData.BytesToParseLength - 1))
                                    {
                                        for (int bitCounter = 0; bitCounter < 8; bitCounter++)
                                        {
                                            if (((bitmask >> bitCounter) & asn1ItemData.BytesToParse[lengthCounter]) == 0)
                                            {
                                                valueBuffer = "0" + valueBuffer;
                                            }
                                            else
                                            {
                                                valueBuffer = "1" + valueBuffer;
                                            }
                                        }
                                    }
                                    else
                                    {
                                        for (int bitCounter = 0; bitCounter < (8 - unusedBits); bitCounter++)
                                        {
                                            if (((bitmask >> bitCounter) & asn1ItemData.BytesToParse[lengthCounter]) == 0)
                                            {
                                                valueBuffer = "0" + valueBuffer;
                                            }
                                            else
                                            {
                                                valueBuffer = "1" + valueBuffer;
                                            }
                                        }
                                    }
                                }
                            }
                            else
                            {                                     //Too long show as in hexadecimal representation
                                for (lengthCounter = 1; lengthCounter < asn1ItemData.BytesToParseLength; lengthCounter++)
                                {
                                    valueBuffer += asn1ItemData.BytesToParse[lengthCounter].ToString("X2") + " ";
                                }
                            }
                            newXmlAttribute       = currentXmlNode.OwnerDocument.CreateAttribute("UnusedBits");
                            newXmlAttribute.Value = unusedBits.ToString();
                            newChildXmlNode.Attributes.Append(newXmlAttribute);

                            newXmlAttribute       = currentXmlNode.OwnerDocument.CreateAttribute("Value");
                            newXmlAttribute.Value = valueBuffer;
                            newChildXmlNode.Attributes.Append(newXmlAttribute);
                            break;

                        default:
                            if (asn1ItemData.BytesToParseLength > 0)
                            {
                                throw new Exception("Unparsed data encountered");
                            }
                            break;
                        }
                    }
                    else
                    {
                        valueBuffer = this.CheckText(asn1ItemData.BytesToParse);
                        if (valueBuffer == "")
                        {
                            for (lengthCounter = 0; lengthCounter < asn1ItemData.BytesToParseLength; lengthCounter++)
                            {
                                valueBuffer += asn1ItemData.BytesToParse[lengthCounter].ToString("X2") + " ";
                            }
                        }
                        newXmlAttribute       = currentXmlNode.OwnerDocument.CreateAttribute("Value");
                        newXmlAttribute.Value = valueBuffer;
                        newChildXmlNode.Attributes.Append(newXmlAttribute);
                    }
                }
            }
        }
Ejemplo n.º 2
0
        private Asn1ItemData GetItemData(byte[] currentBytesToParse, bool throwErrors, ref long index)
        {
            int          buffer;
            int          buffer2;
            long         lengthLength = 0;
            int          lengthCounter;
            Asn1ItemData retVal;

            retVal = new Asn1ItemData();

            try
            {
                //Fetch the tag
                buffer                    = currentBytesToParse[index++];
                retVal.TagClass           = (TagClasses)((buffer & TagClassMask) >> 6);
                retVal.TagConstructedFlag = (TagConstructed)((buffer & TagConstructedFlagMask) >> 5);
                retVal.TagNumber          = (UniversalTags)(buffer & TagNumberMask);

                //Fetch the length
                retVal.BytesToParseLength = currentBytesToParse[index++];
                if ((retVal.BytesToParseLength & LEN_XTND) != 0)
                {                                                        //We have a multiple byte length
                    lengthLength = retVal.BytesToParseLength & LEN_MASK; //Strip bit
                    if (lengthLength > 4)
                    {
                        throw new Exception("Bad length encountered: " + lengthLength.ToString() + " (index: " + index + ")");
                    }
                    if (lengthLength == 0)
                    {
                        throw new Exception("Parser can't deal with indefinite length (index: " + index + ")");
                    }
                    retVal.BytesToParseLength = 0;
                    for (lengthCounter = 0; lengthCounter < lengthLength; lengthCounter++)
                    {
                        buffer2 = currentBytesToParse[index++];
                        retVal.BytesToParseLength = (retVal.BytesToParseLength << 8) | (uint)buffer2;
                    }
                }
                retVal.HeaderLength = 2 + lengthLength;

                //Fetch the raw data
                retVal.BytesToParse = new byte[retVal.BytesToParseLength];
                for (lengthCounter = 0; lengthCounter < retVal.BytesToParseLength; lengthCounter++)
                {
                    retVal.BytesToParse[lengthCounter] = currentBytesToParse[index++];
                }

                retVal.TagName = retVal.TagClass.ToString() + "_" + retVal.TagConstructedFlag.ToString() + "_";
                if (retVal.TagClass == TagClasses.Universal)
                {
                    retVal.TagName += retVal.TagNumber.ToString();
                }
                else
                {
                    retVal.TagName += buffer.ToString("X2");
                }
            }
            catch (Exception exception)
            {
                if (throwErrors)
                {
                    throw exception;
                }
                else
                {
                    retVal = null;
                }
            }

            return(retVal);
        }