Plan 9 from Bell Labs’s /usr/web/sources/contrib/ericvh/go-plan9/src/pkg/asn1/common.go

Copyright © 2021 Plan 9 Foundation.
Distributed under the MIT License.
Download the Plan 9 distribution.


// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package asn1

import (
	"reflect";
	"strconv";
	"strings";
)

// ASN.1 objects have metadata preceeding them:
//   the tag: the type of the object
//   a flag denoting if this object is compound or not
//   the class type: the namespace of the tag
//   the length of the object, in bytes

// Here are some standard tags and classes

const (
	tagBoolean		= 1;
	tagInteger		= 2;
	tagBitString		= 3;
	tagOctetString		= 4;
	tagOID			= 6;
	tagSequence		= 16;
	tagSet			= 17;
	tagPrintableString	= 19;
	tagIA5String		= 22;
	tagUTCTime		= 23;
)

const (
	classUniversal		= 0;
	classApplication	= 1;
	classContextSpecific	= 2;
	classPrivate		= 3;
)

type tagAndLength struct {
	class, tag, length	int;
	isCompound		bool;
}

// ASN.1 has IMPLICIT and EXPLICIT tags, which can be translated as "instead
// of" and "in addition to". When not specified, every primitive type has a
// default tag in the UNIVERSAL class.
//
// For example: a BIT STRING is tagged [UNIVERSAL 3] by default (although ASN.1
// doesn't actually have a UNIVERSAL keyword). However, by saying [IMPLICIT
// CONTEXT-SPECIFIC 42], that means that the tag is replaced by another.
//
// On the other hand, if it said [EXPLICIT CONTEXT-SPECIFIC 10], then an
// /additional/ tag would wrap the default tag. This explicit tag will have the
// compound flag set.
//
// (This is used in order to remove ambiguity with optional elements.)
//
// You can layer EXPLICIT and IMPLICIT tags to an arbitrary depth, however we
// don't support that here. We support a single layer of EXPLICIT or IMPLICIT
// tagging with tag strings on the fields of a structure.

// fieldParameters is the parsed representation of tag string from a structure field.
type fieldParameters struct {
	optional	bool;	// true iff the field is OPTIONAL
	explicit	bool;	// true iff and EXPLICIT tag is in use.
	defaultValue	*int64;	// a default value for INTEGER typed fields (maybe nil).
	tag		*int;	// the EXPLICIT or IMPLICIT tag (maybe nil).
	stringType	int;	// the string tag to use when marshaling.

	// Invariants:
	//   if explicit is set, tag is non-nil.
}

// Given a tag string with the format specified in the package comment,
// parseFieldParameters will parse it into a fieldParameters structure,
// ignoring unknown parts of the string.
func parseFieldParameters(str string) (ret fieldParameters) {
	for _, part := range strings.Split(str, ",", 0) {
		switch {
		case part == "optional":
			ret.optional = true
		case part == "explicit":
			ret.explicit = true;
			if ret.tag == nil {
				ret.tag = new(int);
				*ret.tag = 0;
			}
		case part == "ia5":
			ret.stringType = tagIA5String
		case part == "printable":
			ret.stringType = tagPrintableString
		case strings.HasPrefix(part, "default:"):
			i, err := strconv.Atoi64(part[8:]);
			if err == nil {
				ret.defaultValue = new(int64);
				*ret.defaultValue = i;
			}
		case strings.HasPrefix(part, "tag:"):
			i, err := strconv.Atoi(part[4:]);
			if err == nil {
				ret.tag = new(int);
				*ret.tag = i;
			}
		}
	}
	return;
}

// Given a reflected Go type, getUniversalType returns the default tag number
// and expected compound flag.
func getUniversalType(t reflect.Type) (tagNumber int, isCompound, ok bool) {
	switch t {
	case objectIdentifierType:
		return tagOID, false, true
	case bitStringType:
		return tagBitString, false, true
	case timeType:
		return tagUTCTime, false, true
	}
	switch i := t.(type) {
	case *reflect.BoolType:
		return tagBoolean, false, true
	case *reflect.IntType:
		return tagInteger, false, true
	case *reflect.Int64Type:
		return tagInteger, false, true
	case *reflect.StructType:
		return tagSequence, true, true
	case *reflect.SliceType:
		if _, ok := t.(*reflect.SliceType).Elem().(*reflect.Uint8Type); ok {
			return tagOctetString, false, true
		}
		return tagSequence, true, true;
	case *reflect.StringType:
		return tagPrintableString, false, true
	}
	return 0, false, false;
}

Bell Labs OSI certified Powered by Plan 9

(Return to Plan 9 Home Page)

Copyright © 2021 Plan 9 Foundation. All Rights Reserved.
Comments to webmaster@9p.io.