rebase: vendor files required for kmip

Signed-off-by: Rakshith R <rar@redhat.com>
This commit is contained in:
Rakshith R
2022-08-16 15:18:06 +05:30
committed by mergify[bot]
parent 0c33a33d5c
commit e72ed593be
186 changed files with 39195 additions and 203 deletions

499
vendor/github.com/gemalto/kmip-go/ttlv/decoder.go generated vendored Normal file
View File

@ -0,0 +1,499 @@
package ttlv
import (
"bufio"
"bytes"
"errors"
"io"
"reflect"
"github.com/ansel1/merry"
)
var ErrUnexpectedValue = errors.New("no field was found to unmarshal value into")
// Unmarshal parses TTLV encoded data and stores the result
// in the value pointed to by v.
//
// An error will be returned if v is nil or not a point, or
// if b is not valid TTLV.
//
// Unmarshal will allocate values to store the result in, similar to the
// json.Marshal. Generally, the destination value can be a pointer or
// or a direct value. Currently, Unmarshal does not support anonymous fields.
// They will be ignored. Private fields are ignored.
//
// Unmarshal maps TTLV values to golang values according to the following
// rules:
//
// 1. If the destination value is interface{}, it will be set to the result
// of TTLV.Value()
// 2. If the destination implements Unmarshaler, that will be called.
// 3. If the destination is a slice (except for []byte), append the
// unmarshalled value to the slice
// 4. Structure unmarshals into a struct. See rules
// below for matching struct fields to the values in the Structure.
// 5. Interval unmarshals into an int64
// 6. DateTime and DateTimeExtended ummarshal into time.Time
// 7. ByteString unmarshals to a []byte
// 8. TextString unmarshals into a string
// 9. Boolean unmarshals into a bool
// 10. Enumeration can unmarshal into an int, int8, int16, int32, or their
// uint counterparts. If the KMIP value overflows the destination, a
// *UnmarshalerError with cause ErrIntOverflow is returned.
// 11. Integer can unmarshal to the same types as Enumeration, with the
// same overflow check.
// 12. LongInteger unmarshals to int64 or uint64
// 13. BitInteger unmarshals to big.Int.
//
// If the destination value is not a supported type, an *UnmarshalerError with
// cause ErrUnsupportedTypeError is returned. If the source value's type is not recognized,
// *UnmarshalerError with cause ErrInvalidType is returned.
//
// Unmarshaling Structure
//
// Unmarshal will try to match the values in the Structure with the fields in the
// destination struct. Structure is an array of values, while a struct is more like
// a map, so not all Structure values can be accurately represented by a golang struct.
// In particular, a Structure can hold the same tag multiple times, e.g. 3 TagComment values
// in a row.
//
// For each field in the struct, Unmarshal infers a KMIP Tag by examining both the name
// and type of the field. It uses the following rules, in order:
//
// 1. If the type of a field is a struct, and the struct contains a field named "TTLVTag", and the field
// has a "ttlv" struct tag, the value of the struct tag will be parsed using ParseTag(). If
// parsing fails, an error is returned. The type and value of the TTLVTag field is ignored.
// In this example, the F field will map to TagDeactivationDate:
//
// type Bar struct {
// F Foo
// }
// type Foo struct {
// TTLVTag struct{} `ttlv:"DeactivationDate"`
// }
//
// If Bar uses a struct tag on F indicating a different tag, it is an error:
//
// type Bar struct {
// F Foo `ttlv:"DerivationData"` // this will cause an ErrTagConflict
// // because conflict Bar's field tag
// // conflicts with Foo's intrinsic tag
// F2 Foo `ttlv:"0x420034"` // the value can also be hex
// }
// 2. If the type of the field is a struct, and the struct contains a field named "TTLVTag",
// and that field is of type ttlv.Tag and is not empty, the value of the field will be the
// inferred Tag. For example:
//
// type Foo struct {
// TTLVTag ttlv.Tag
// }
// f := Foo{TTLVTag: ttlv.TagState}
//
// This allows you to dynamically set the KMIP tag that a value will marshal to.
// 3. The "ttlv" struct tag can be used to indicate the tag for a field. The value will
// be parsed with ParseTag()
//
// type Bar struct {
// F Foo `ttlv:"DerivationData"`
// }
//
// 4. The name of the field is parsed with ParseTag():
//
// type Bar struct {
// DerivationData int
// }
//
// 5. The name of the field's type is parsed with ParseTab():
//
// type DerivationData int
//
// type Bar struct {
// dd DerivationData
// }
//
// If no tag value can be inferred, the field is ignored. Multiple fields
// *cannot* map to the same KMIP tag. If they do, an ErrTagConflict will
// be returned.
//
// Each value in the Structure will be matched against the first field
// in the struct with the same inferred tag.
//
// If the value cannot be matched with a field, Unmarshal will look for
// the first field with the "any" struct flag set and unmarshal into that:
//
// type Foo struct {
// Comment string // the Comment will unmarshal into this
// EverythingElse []interface{} `,any` // all other values will unmarshal into this
// AnotherAny []interface{} `,any` // allowed, but ignored. first any field will always match
// NotLegal []interface{} `TagComment,any` // you cannot specify a tag and the any flag.
// // will return error
// }
//
// If after applying these rules no destination field is found, the KMIP value is ignored.
func Unmarshal(ttlv TTLV, v interface{}) error {
return NewDecoder(bytes.NewReader(ttlv)).Decode(v)
}
// Unmarshaler knows how to unmarshal a ttlv value into itself.
// The decoder argument may be used to decode the ttlv value into
// intermediary values if needed.
type Unmarshaler interface {
UnmarshalTTLV(d *Decoder, ttlv TTLV) error
}
// Decoder reads KMIP values from a stream, and decodes them into golang values.
// It currently only decodes TTLV encoded KMIP values.
// TODO: support decoding XML and JSON, so their decoding can be configured
//
// If DisallowExtraValues is true, the decoder will return an error when decoding
// Structures into structs and a matching field can't get found for every value.
type Decoder struct {
r io.Reader
bufr *bufio.Reader
DisallowExtraValues bool
currStruct reflect.Type
currField string
}
func NewDecoder(r io.Reader) *Decoder {
return &Decoder{
r: r,
bufr: bufio.NewReader(r),
}
}
// Reset resets the internal state of the decoder for reuse.
func (dec *Decoder) Reset(r io.Reader) {
*dec = Decoder{
r: r,
bufr: dec.bufr,
}
dec.bufr.Reset(r)
}
// Decode the first KMIP value from the reader into v.
// See Unmarshal for decoding rules.
func (dec *Decoder) Decode(v interface{}) error {
ttlv, err := dec.NextTTLV()
if err != nil {
return err
}
return dec.DecodeValue(v, ttlv)
}
// DecodeValue decodes a ttlv value into v. This doesn't read anything
// from the Decoder's reader.
// See Unmarshal for decoding rules.
func (dec *Decoder) DecodeValue(v interface{}, ttlv TTLV) error {
val := reflect.ValueOf(v)
if val.Kind() != reflect.Ptr {
return merry.New("non-pointer passed to Decode")
}
return dec.unmarshal(val, ttlv)
}
func (dec *Decoder) unmarshal(val reflect.Value, ttlv TTLV) error {
if len(ttlv) == 0 {
return nil
}
// Load value from interface, but only if the result will be
// usefully addressable.
if val.Kind() == reflect.Interface && !val.IsNil() {
e := val.Elem()
if e.Kind() == reflect.Ptr && !e.IsNil() {
val = e
}
}
if val.Kind() == reflect.Ptr {
if val.IsNil() {
val.Set(reflect.New(val.Type().Elem()))
}
val = val.Elem()
}
if val.Type().Implements(unmarshalerType) {
return val.Interface().(Unmarshaler).UnmarshalTTLV(dec, ttlv) //nolint:forcetypeassert
}
if val.CanAddr() {
valAddr := val.Addr()
if valAddr.CanInterface() && valAddr.Type().Implements(unmarshalerType) {
return valAddr.Interface().(Unmarshaler).UnmarshalTTLV(dec, ttlv) //nolint:forcetypeassert
}
}
switch val.Kind() {
case reflect.Interface:
if ttlv.Type() == TypeStructure {
// if the value is a structure, set the whole TTLV
// as the value.
val.Set(reflect.ValueOf(ttlv))
} else {
// set blank interface equal to the TTLV.Value()
val.Set(reflect.ValueOf(ttlv.Value()))
}
return nil
case reflect.Slice:
typ := val.Type()
if typ.Elem() == byteType {
// []byte
break
}
// Slice of element values.
// Grow slice.
n := val.Len()
val.Set(reflect.Append(val, reflect.Zero(val.Type().Elem())))
// Recur to read element into slice.
if err := dec.unmarshal(val.Index(n), ttlv); err != nil {
val.SetLen(n)
return err
}
return nil
default:
}
typeMismatchErr := func() error {
e := &UnmarshalerError{
Struct: dec.currStruct,
Field: dec.currField,
Tag: ttlv.Tag(),
Type: ttlv.Type(),
Val: val.Type(),
}
err := merry.WrapSkipping(e, 1).WithCause(ErrUnsupportedTypeError)
return err
}
switch ttlv.Type() {
case TypeStructure:
if val.Kind() != reflect.Struct {
return typeMismatchErr()
}
// stash currStruct
currStruct := dec.currStruct
err := dec.unmarshalStructure(ttlv, val)
// restore currStruct
dec.currStruct = currStruct
return err
case TypeInterval:
if val.Kind() != reflect.Int64 {
return typeMismatchErr()
}
val.SetInt(int64(ttlv.ValueInterval()))
case TypeDateTime, TypeDateTimeExtended:
if val.Type() != timeType {
return typeMismatchErr()
}
val.Set(reflect.ValueOf(ttlv.ValueDateTime()))
case TypeByteString:
if val.Kind() != reflect.Slice && val.Type().Elem() != byteType {
return typeMismatchErr()
}
val.SetBytes(ttlv.ValueByteString())
case TypeTextString:
if val.Kind() != reflect.String {
return typeMismatchErr()
}
val.SetString(ttlv.ValueTextString())
case TypeBoolean:
if val.Kind() != reflect.Bool {
return typeMismatchErr()
}
val.SetBool(ttlv.ValueBoolean())
// nolint:dupl
case TypeEnumeration:
switch val.Kind() {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32:
i := int64(ttlv.ValueEnumeration())
if val.OverflowInt(i) {
return dec.newUnmarshalerError(ttlv, val.Type(), ErrIntOverflow)
}
val.SetInt(i)
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32:
i := uint64(ttlv.ValueEnumeration())
if val.OverflowUint(i) {
return dec.newUnmarshalerError(ttlv, val.Type(), ErrIntOverflow)
}
val.SetUint(i)
default:
return typeMismatchErr()
}
// nolint:dupl
case TypeInteger:
switch val.Kind() {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32:
i := int64(ttlv.ValueInteger())
if val.OverflowInt(i) {
return dec.newUnmarshalerError(ttlv, val.Type(), ErrIntOverflow)
}
val.SetInt(i)
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32:
i := uint64(ttlv.ValueInteger())
if val.OverflowUint(i) {
return dec.newUnmarshalerError(ttlv, val.Type(), ErrIntOverflow)
}
val.SetUint(i)
default:
return typeMismatchErr()
}
case TypeLongInteger:
switch val.Kind() {
case reflect.Int64:
val.SetInt(ttlv.ValueLongInteger())
case reflect.Uint64:
val.SetUint(uint64(ttlv.ValueLongInteger()))
default:
return typeMismatchErr()
}
case TypeBigInteger:
if val.Type() != bigIntType {
return typeMismatchErr()
}
val.Set(reflect.ValueOf(*ttlv.ValueBigInteger()))
default:
return dec.newUnmarshalerError(ttlv, val.Type(), ErrInvalidType)
}
return nil
}
func (dec *Decoder) unmarshalStructure(ttlv TTLV, val reflect.Value) error {
ti, err := getTypeInfo(val.Type())
if err != nil {
return dec.newUnmarshalerError(ttlv, val.Type(), err)
}
if ti.tagField != nil && ti.tagField.ti.typ == tagType {
val.FieldByIndex(ti.tagField.index).Set(reflect.ValueOf(ttlv.Tag()))
}
fields := ti.valueFields
// push currStruct (caller will pop)
dec.currStruct = val.Type()
for n := ttlv.ValueStructure(); n != nil; n = n.Next() {
fldIdx := -1
for i := range fields {
if fields[i].flags.any() {
// if this is the first any field found, keep track
// of it as the current candidate match, but
// keep looking for a tag match
if fldIdx == -1 {
fldIdx = i
}
} else if fields[i].tag == n.Tag() {
// tag match found
// we can stop looking
fldIdx = i
break
}
}
if fldIdx > -1 {
// push currField
currField := dec.currField
dec.currField = fields[fldIdx].name
err := dec.unmarshal(val.FieldByIndex(fields[fldIdx].index), n)
// restore currField
dec.currField = currField
if err != nil {
return err
}
} else if dec.DisallowExtraValues {
return dec.newUnmarshalerError(ttlv, val.Type(), ErrUnexpectedValue)
}
}
return nil
}
// NextTTLV reads the next, full KMIP value off the reader.
func (dec *Decoder) NextTTLV() (TTLV, error) {
// first, read the header
header, err := dec.bufr.Peek(8)
if err != nil {
return nil, merry.Wrap(err)
}
if err := TTLV(header).ValidHeader(); err != nil {
// bad header, abort
return TTLV(header), merry.Prependf(err, "invalid header: %v", TTLV(header))
}
// allocate a buffer large enough for the entire message
fullLen := TTLV(header).FullLen()
buf := make([]byte, fullLen)
var totRead int
for {
n, err := dec.bufr.Read(buf[totRead:])
if err != nil {
return TTLV(buf), merry.Wrap(err)
}
totRead += n
if totRead >= fullLen {
// we've read off a single full message
return buf, nil
} // else keep reading
}
}
func (dec *Decoder) newUnmarshalerError(ttlv TTLV, valType reflect.Type, cause error) merry.Error {
e := &UnmarshalerError{
Struct: dec.currStruct,
Field: dec.currField,
Tag: ttlv.Tag(),
Type: ttlv.Type(),
Val: valType,
}
return merry.WrapSkipping(e, 1).WithCause(cause)
}
type UnmarshalerError struct {
// Val is the type of the destination value
Val reflect.Type
// Struct is the type of the containing struct if the value is a field
Struct reflect.Type
// Field is the name of the value field
Field string
Tag Tag
Type Type
}
func (e *UnmarshalerError) Error() string {
msg := "kmip: error unmarshaling " + e.Tag.String() + " with type " + e.Type.String() + " into value of type " + e.Val.Name()
if e.Struct != nil {
msg += " in struct field " + e.Struct.Name() + "." + e.Field
}
return msg
}

22
vendor/github.com/gemalto/kmip-go/ttlv/docs.go generated vendored Normal file
View File

@ -0,0 +1,22 @@
// Package ttlv encodes and decodes the 3 wire formats defined in the KMIP specification:
//
// 1. TTLV (the default, binary wire format)
// 2. JSON
// 3. XML
//
// The core representation of KMIP values is the ttlv.TTLV type, which is
// a []byte encoded in the TTLV binary format. The ttlv.TTLV type knows how to marshal/
// unmarshal to and from the JSON and XML encoding formats.
//
// This package also knows how to marshal and unmarshal ttlv.TTLV values to golang structs,
// in a way similar to the json or xml packages.
//
// See Marshal() and Unmarshal() for the rules about how golang values map to KMIP TTLVs.
// Encoder and Decoder can be used to process streams of KMIP values.
//
// This package holds a registry of type, tag, and enum value names, which are used to transcode
// strings into these values. KMIP 1.4 names will be automatically loaded into the
// DefaultRegistry. See the kmip20 package to add definitions for 2.0 names.
//
// Print() and PrettyPrintHex() can be used to debug TTLV values.
package ttlv

962
vendor/github.com/gemalto/kmip-go/ttlv/encoder.go generated vendored Normal file
View File

@ -0,0 +1,962 @@
package ttlv
import (
"bytes"
"encoding/binary"
"errors"
"fmt"
"io"
"math"
"math/big"
"reflect"
"strings"
"time"
"github.com/ansel1/merry"
)
const structFieldTag = "ttlv"
var (
ErrIntOverflow = fmt.Errorf("value exceeds max int value %d", math.MaxInt32)
ErrUnsupportedEnumTypeError = errors.New("unsupported type for enums, must be string, or int types")
ErrUnsupportedTypeError = errors.New("marshaling/unmarshaling is not supported for this type")
ErrNoTag = errors.New("unable to determine tag for field")
ErrTagConflict = errors.New("tag conflict")
)
// Marshal encodes a golang value into a KMIP value.
//
// An error will be returned if v is an invalid pointer.
//
// Currently, Marshal does not support anonymous fields.
// Private fields are ignored.
//
// Marshal maps the golang value to a KMIP tag, type, and value
// encoding. To determine the KMIP tag, Marshal uses the same rules
// as Unmarshal.
//
// The appropriate type and encoding are inferred from the golang type
// and from the inferred KMIP tag, according to these rules:
//
// 1. If the value is a TTLV, it is copied byte for byte
// 2. If the value implements Marshaler, call that
// 3. If the struct field has an "omitempty" flag, and the value is
// zero, skip the field:
//
// type Foo struct {
// Comment string `ttlv:,omitempty`
// }
//
// 4. If the value is a slice (except []byte) or array, marshal all
// values concatenated
// 5. If a tag has not been inferred at this point, return *MarshalerError with
// cause ErrNoTag
// 6. If the Tag is registered as an enum, or has the "enum" struct tag flag, attempt
// to marshal as an Enumeration. int, int8, int16, int32, and their uint counterparts
// can be marshaled as an Enumeration. A string can be marshaled to an Enumeration
// if the string contains a number, a 4 byte (8 char) hex string with the prefix "0x",
// or the normalized name of an enum value registered to this tag. Examples:
//
// type Foo struct {
// CancellationResult string // will encode as an Enumeration because
// // the tag CancellationResult is registered
// // as an enum.
// C int `ttlv:"Comment,enum" // The tag Comment is not registered as an enum
// // but the enum flag will force this to encode
// // as an enumeration.
// }
//
// If the string can't be interpreted as an enum value, it will be encoded as a TextString. If
// the "enum" struct flag is set, the value *must* successfully encode to an Enumeration using
// above rules, or an error is returned.
// 7. If the Tag is registered as a bitmask, or has the "bitmask" struct tag flag, attempt
// to marshal to an Integer, following the same rules as for Enumerations. The ParseInt()
// function is used to parse string values.
// 9. time.Time marshals to DateTime. If the field has the "datetimeextended" struct flag,
// marshal as DateTimeExtended. Example:
//
// type Foo struct {
// ActivationDate time.Time `ttlv:",datetimeextended"`
// }
//
// 10. big.Int marshals to BigInteger
// 11. time.Duration marshals to Interval
// 12. string marshals to TextString
// 13. []byte marshals to ByteString
// 14. all int and uint variants except int64 and uint64 marshal to Integer. If the golang
// value overflows the KMIP value, *MarshalerError with cause ErrIntOverflow is returned
// 15. int64 and uint64 marshal to LongInteger
// 16. bool marshals to Boolean
// 17. structs marshal to Structure. Each field of the struct will be marshaled into the
// values of the Structure according to the above rules.
//
// Any other golang type will return *MarshalerError with cause ErrUnsupportedTypeError.
func Marshal(v interface{}) (TTLV, error) {
buf := bytes.NewBuffer(nil)
err := NewEncoder(buf).Encode(v)
if err != nil {
return nil, err
}
return buf.Bytes(), nil
}
// Marshaler knows how to encode itself to TTLV.
// The implementation should use the primitive methods of the encoder,
// such as EncodeInteger(), etc.
//
// The tag inferred by the Encoder from the field or type information is
// passed as an argument, but the implementation can choose to ignore it.
type Marshaler interface {
MarshalTTLV(e *Encoder, tag Tag) error
}
func NewEncoder(w io.Writer) *Encoder {
return &Encoder{w: w}
}
// Encode a single value and flush to the writer. The tag will be inferred from
// the value. If no tag can be inferred, an error is returned.
// See Marshal for encoding rules.
func (e *Encoder) Encode(v interface{}) error {
return e.EncodeValue(TagNone, v)
}
// EncodeValue encodes a single value with the given tag and flushes it
// to the writer.
// See Marshal for encoding rules.
func (e *Encoder) EncodeValue(tag Tag, v interface{}) error {
err := e.encode(tag, reflect.ValueOf(v), nil)
if err != nil {
return err
}
return e.Flush()
}
// EncodeStructure encodes a Structure with the given tag to the writer.
// The function argument should encode the enclosed values inside the Structure.
// Call Flush() to write the data to the writer.
func (e *Encoder) EncodeStructure(tag Tag, f func(e *Encoder) error) error {
e.encodeDepth++
i := e.encBuf.begin(tag, TypeStructure)
err := f(e)
e.encBuf.end(i)
e.encodeDepth--
return err
}
// EncodeEnumeration, along with the other Encode<Type> methods, encodes a
// single KMIP value with the given tag to an internal buffer. These methods
// do not flush the data to the writer: call Flush() to flush the buffer.
func (e *Encoder) EncodeEnumeration(tag Tag, v uint32) {
e.encBuf.encodeEnum(tag, v)
}
func (e *Encoder) EncodeInteger(tag Tag, v int32) {
e.encBuf.encodeInt(tag, v)
}
func (e *Encoder) EncodeLongInteger(tag Tag, v int64) {
e.encBuf.encodeLongInt(tag, v)
}
func (e *Encoder) EncodeInterval(tag Tag, v time.Duration) {
e.encBuf.encodeInterval(tag, v)
}
func (e *Encoder) EncodeDateTime(tag Tag, v time.Time) {
e.encBuf.encodeDateTime(tag, v)
}
func (e *Encoder) EncodeDateTimeExtended(tag Tag, v time.Time) {
e.encBuf.encodeDateTimeExtended(tag, v)
}
func (e *Encoder) EncodeBigInteger(tag Tag, v *big.Int) {
e.encBuf.encodeBigInt(tag, v)
}
func (e *Encoder) EncodeBoolean(tag Tag, v bool) {
e.encBuf.encodeBool(tag, v)
}
func (e *Encoder) EncodeTextString(tag Tag, v string) {
e.encBuf.encodeTextString(tag, v)
}
func (e *Encoder) EncodeByteString(tag Tag, v []byte) {
e.encBuf.encodeByteString(tag, v)
}
// Flush flushes the internal encoding buffer to the writer.
func (e *Encoder) Flush() error {
if e.encodeDepth > 0 {
return nil
}
_, err := e.encBuf.WriteTo(e.w)
e.encBuf.Reset()
return err
}
type MarshalerError struct {
// Type is the golang type of the value being marshaled
Type reflect.Type
// Struct is the name of the enclosing struct if the marshaled value is a field.
Struct string
// Field is the name of the field being marshaled
Field string
Tag Tag
}
func (e *MarshalerError) Error() string {
msg := "kmip: error marshaling value"
if e.Type != nil {
msg += " of type " + e.Type.String()
}
if e.Struct != "" {
msg += " in struct field " + e.Struct + "." + e.Field
}
return msg
}
func (e *Encoder) marshalingError(tag Tag, t reflect.Type, cause error) merry.Error {
err := &MarshalerError{
Type: t,
Struct: e.currStruct,
Field: e.currField,
Tag: tag,
}
return merry.WrapSkipping(err, 1).WithCause(cause)
}
var (
byteType = reflect.TypeOf(byte(0))
marshalerType = reflect.TypeOf((*Marshaler)(nil)).Elem()
unmarshalerType = reflect.TypeOf((*Unmarshaler)(nil)).Elem()
timeType = reflect.TypeOf((*time.Time)(nil)).Elem()
bigIntPtrType = reflect.TypeOf((*big.Int)(nil))
bigIntType = bigIntPtrType.Elem()
durationType = reflect.TypeOf(time.Nanosecond)
ttlvType = reflect.TypeOf((*TTLV)(nil)).Elem()
tagType = reflect.TypeOf(Tag(0))
)
var invalidValue = reflect.Value{}
// indirect dives into interfaces values, and one level deep into pointers
// returns an invalid value if the resolved value is nil or invalid.
func indirect(v reflect.Value) reflect.Value {
if !v.IsValid() {
return v
}
if v.Kind() == reflect.Interface {
v = v.Elem()
}
if !v.IsValid() {
return v
}
if v.Kind() == reflect.Ptr {
v = v.Elem()
}
switch v.Kind() {
case reflect.Func, reflect.Slice, reflect.Map, reflect.Chan, reflect.Ptr, reflect.Interface:
if v.IsNil() {
return invalidValue
}
default:
}
return v
}
var zeroBigInt = big.Int{}
func isEmptyValue(v reflect.Value) bool {
switch v.Kind() {
case reflect.Array, reflect.Map, reflect.Slice, reflect.String:
return v.Len() == 0
case reflect.Bool:
return !v.Bool()
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return v.Int() == 0
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
return v.Uint() == 0
case reflect.Float32, reflect.Float64:
return v.Float() == 0
case reflect.Interface, reflect.Ptr:
return v.IsNil()
default:
}
switch v.Type() {
case timeType:
return v.Interface().(time.Time).IsZero() //nolint:forcetypeassert
case bigIntType:
i := v.Interface().(big.Int) //nolint:forcetypeassert
return zeroBigInt.Cmp(&i) == 0
}
return false
}
func (e *Encoder) encode(tag Tag, v reflect.Value, fi *fieldInfo) error {
// if pointer or interface
v = indirect(v)
if !v.IsValid() {
return nil
}
typ := v.Type()
if typ == ttlvType {
// fast path: if the value is TTLV, we write it directly to the output buffer
_, err := e.encBuf.Write(v.Bytes())
return err
}
typeInfo, err := getTypeInfo(typ)
if err != nil {
return err
}
if tag == TagNone {
tag = tagForMarshal(v, typeInfo, fi)
}
var flags fieldFlags
if fi != nil {
flags = fi.flags
}
// check for Marshaler
switch {
case typ.Implements(marshalerType):
if flags.omitEmpty() && isEmptyValue(v) {
return nil
}
return v.Interface().(Marshaler).MarshalTTLV(e, tag) //nolint:forcetypeassert
case v.CanAddr():
pv := v.Addr()
pvtyp := pv.Type()
if pvtyp.Implements(marshalerType) {
if flags.omitEmpty() && isEmptyValue(v) {
return nil
}
return pv.Interface().(Marshaler).MarshalTTLV(e, tag) //nolint:forcetypeassert
}
}
// If the type doesn't implement Marshaler, then validate the value is a supported kind
switch v.Kind() {
case reflect.Chan, reflect.Map, reflect.Func, reflect.Ptr, reflect.UnsafePointer, reflect.Uintptr, reflect.Float32,
reflect.Float64,
reflect.Complex64,
reflect.Complex128,
reflect.Interface:
return e.marshalingError(tag, v.Type(), ErrUnsupportedTypeError)
default:
}
// skip if value is empty and tags include omitempty
if flags.omitEmpty() && isEmptyValue(v) {
return nil
}
// recurse to handle slices of values
switch v.Kind() {
case reflect.Slice:
if typ.Elem() == byteType {
// special case, encode as a ByteString, handled below
break
}
fallthrough
case reflect.Array:
for i := 0; i < v.Len(); i++ {
// turn off the omit empty flag. applies at the field level,
// not to each member of the slice
// TODO: is this true?
var fi2 *fieldInfo
if fi != nil {
fi2 = &fieldInfo{}
// make a copy.
*fi2 = *fi
fi2.flags &^= fOmitEmpty
}
err := e.encode(tag, v.Index(i), fi2)
if err != nil {
return err
}
}
return nil
default:
}
if tag == TagNone {
return e.marshalingError(tag, v.Type(), ErrNoTag)
}
// handle enums and bitmasks
//
// If the field has the "enum" or "bitmask" flag, or the tag is registered as an enum or bitmask,
// attempt to interpret the go value as such.
//
// If the field is explicitly flag, return an error if the value can't be interpreted. Otherwise
// ignore errors and let processing fallthrough to the type-based encoding.
enumMap := DefaultRegistry.EnumForTag(tag)
if flags.enum() || flags.bitmask() || enumMap != nil {
switch typ.Kind() {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32:
i := v.Int()
if flags.bitmask() || (enumMap != nil && enumMap.Bitmask()) {
e.encBuf.encodeInt(tag, int32(i))
} else {
e.encBuf.encodeEnum(tag, uint32(i))
}
return nil
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32:
i := v.Uint()
if flags.bitmask() || (enumMap != nil && enumMap.Bitmask()) {
e.encBuf.encodeInt(tag, int32(i))
} else {
e.encBuf.encodeEnum(tag, uint32(i))
}
return nil
case reflect.String:
s := v.String()
if flags.bitmask() || (enumMap != nil && enumMap.Bitmask()) {
i, err := ParseInt(s, enumMap)
if err == nil {
e.encBuf.encodeInt(tag, i)
return nil
}
// only throw an error if the field is explicitly marked as a bitmask
// otherwise just ignore it, and let it encode as a string later on.
if flags.bitmask() {
// if we couldn't parse the string as an enum value
return e.marshalingError(tag, typ, err)
}
} else {
i, err := ParseEnum(s, enumMap)
if err == nil {
e.encBuf.encodeEnum(tag, i)
return nil
}
// only throw an error if the field is explicitly marked as an enum
// otherwise just ignore it, and let it encode as a string later on.
if flags.enum() {
// if we couldn't parse the string as an enum value
return e.marshalingError(tag, typ, err)
}
}
default:
if flags.enum() || flags.bitmask() {
return e.marshalingError(tag, typ, ErrUnsupportedEnumTypeError).Append(typ.String())
}
}
}
// handle special types
switch typ {
case timeType:
if flags.dateTimeExt() {
e.encBuf.encodeDateTimeExtended(tag, v.Interface().(time.Time)) //nolint:forcetypeassert
} else {
e.encBuf.encodeDateTime(tag, v.Interface().(time.Time)) //nolint:forcetypeassert
}
return nil
case bigIntType:
bi := v.Interface().(big.Int) //nolint:forcetypeassert
e.encBuf.encodeBigInt(tag, &bi)
return nil
case bigIntPtrType:
e.encBuf.encodeBigInt(tag, v.Interface().(*big.Int)) //nolint:forcetypeassert
return nil
case durationType:
e.encBuf.encodeInterval(tag, time.Duration(v.Int()))
return nil
}
// handle the rest of the kinds
switch typ.Kind() {
case reflect.Struct:
// push current struct onto stack
currStruct := e.currStruct
e.currStruct = typ.Name()
err = e.EncodeStructure(tag, func(e *Encoder) error {
for _, field := range typeInfo.valueFields {
fv := v.FieldByIndex(field.index)
// note: we're staying in reflection world here instead of
// converting back to an interface{} value and going through
// the non-reflection path again. Calling Interface()
// on the reflect value would make a potentially addressable value
// into an unaddressable value, reducing the chances we can coerce
// the value into a Marshalable.
//
// tl;dr
// Consider a type which implements Marshaler with
// a pointer receiver, and a struct with a non-pointer field of that type:
//
// type Wheel struct{}
// func (*Wheel) MarshalTTLV(...)
//
// type Car struct{
// Wheel Wheel
// }
//
// When traversing the Car struct, should the encoder invoke Wheel's
// Marshaler method, or not? Technically, the type `Wheel`
// doesn't implement the Marshaler interface. Only the type `*Wheel`
// implements it. However, the other encoders in the SDK, like JSON
// and XML, will try, if possible, to get a pointer to field values like this, in
// order to invoke the Marshaler interface anyway.
//
// Encoders can only get a pointer to field values if the field
// value is `addressable`. Addressability is explained in the docs for reflect.Value#CanAddr().
// Using reflection to turn a reflect.Value() back into an interface{}
// can make a potentially addressable value (like the field of an addressable struct)
// into an unaddressable value (reflect.Value#Interface{} always returns an unaddressable
// copy).
// push the currField
currField := e.currField
e.currField = field.name
err := e.encode(TagNone, fv, &field) //nolint:gosec,scopelint
// pop the currField
e.currField = currField
if err != nil {
return err
}
}
return nil
})
// pop current struct
e.currStruct = currStruct
return err
case reflect.String:
e.encBuf.encodeTextString(tag, v.String())
case reflect.Slice:
// special case, encode as a ByteString
// all slices which aren't []byte should have been handled above
// the call to v.Bytes() will panic if this assumption is wrong
e.encBuf.encodeByteString(tag, v.Bytes())
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32:
i := v.Int()
if i > math.MaxInt32 {
return e.marshalingError(tag, typ, ErrIntOverflow)
}
e.encBuf.encodeInt(tag, int32(i))
return nil
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32:
u := v.Uint()
if u > math.MaxInt32 {
return e.marshalingError(tag, typ, ErrIntOverflow)
}
e.encBuf.encodeInt(tag, int32(u))
return nil
case reflect.Uint64:
u := v.Uint()
e.encBuf.encodeLongInt(tag, int64(u))
return nil
case reflect.Int64:
e.encBuf.encodeLongInt(tag, v.Int())
return nil
case reflect.Bool:
e.encBuf.encodeBool(tag, v.Bool())
default:
// all kinds should have been handled by now
panic(errors.New("should never get here"))
}
return nil
}
func tagForMarshal(v reflect.Value, ti typeInfo, fi *fieldInfo) Tag {
// the tag on the TTLVTag field
if ti.tagField != nil && ti.tagField.explicitTag != TagNone {
return ti.tagField.explicitTag
}
// the value of the TTLVTag field of type Tag
if v.IsValid() && ti.tagField != nil && ti.tagField.ti.typ == tagType {
tag := v.FieldByIndex(ti.tagField.index).Interface().(Tag) //nolint:forcetypeassert
if tag != TagNone {
return tag
}
}
// if value is in a struct field, infer the tag from the field
// else infer from the value's type name
if fi != nil {
return fi.tag
}
return ti.inferredTag
}
// encBuf encodes basic KMIP types into TTLV.
type encBuf struct {
bytes.Buffer
}
func (h *encBuf) begin(tag Tag, typ Type) int {
_ = h.WriteByte(byte(tag >> 16))
_ = h.WriteByte(byte(tag >> 8))
_ = h.WriteByte(byte(tag))
_ = h.WriteByte(byte(typ))
_, _ = h.Write(zeros[:4])
return h.Len()
}
func (h *encBuf) end(i int) {
n := h.Len() - i
if m := n % 8; m > 0 {
_, _ = h.Write(zeros[:8-m])
}
binary.BigEndian.PutUint32(h.Bytes()[i-4:], uint32(n))
}
func (h *encBuf) writeLongIntVal(tag Tag, typ Type, i int64) {
s := h.begin(tag, typ)
ll := h.Len()
_, _ = h.Write(zeros[:8])
binary.BigEndian.PutUint64(h.Bytes()[ll:], uint64(i))
h.end(s)
}
func (h *encBuf) writeIntVal(tag Tag, typ Type, val uint32) {
s := h.begin(tag, typ)
ll := h.Len()
_, _ = h.Write(zeros[:4])
binary.BigEndian.PutUint32(h.Bytes()[ll:], val)
h.end(s)
}
var (
ones = [8]byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}
zeros = [8]byte{}
)
func (h *encBuf) encodeBigInt(tag Tag, i *big.Int) {
if i == nil {
return
}
ii := h.begin(tag, TypeBigInteger)
switch i.Sign() {
case 0:
_, _ = h.Write(zeros[:8])
case 1:
b := i.Bytes()
l := len(b)
// if n is positive, but the first bit is a 1, it will look like
// a negative in 2's complement, so prepend zeroes in front
if b[0]&0x80 > 0 {
_ = h.WriteByte(byte(0))
l++
}
// pad front with zeros to multiple of 8
if m := l % 8; m > 0 {
_, _ = h.Write(zeros[:8-m])
}
_, _ = h.Write(b)
case -1:
length := uint(i.BitLen()/8+1) * 8
j := new(big.Int).Lsh(one, length)
b := j.Add(i, j).Bytes()
// When the most significant bit is on a byte
// boundary, we can get some extra significant
// bits, so strip them off when that happens.
if len(b) >= 2 && b[0] == 0xff && b[1]&0x80 != 0 {
b = b[1:]
}
l := len(b)
// pad front with ones to multiple of 8
if m := l % 8; m > 0 {
_, _ = h.Write(ones[:8-m])
}
_, _ = h.Write(b)
}
h.end(ii)
}
func (h *encBuf) encodeInt(tag Tag, i int32) {
h.writeIntVal(tag, TypeInteger, uint32(i))
}
func (h *encBuf) encodeBool(tag Tag, b bool) {
if b {
h.writeLongIntVal(tag, TypeBoolean, 1)
} else {
h.writeLongIntVal(tag, TypeBoolean, 0)
}
}
func (h *encBuf) encodeLongInt(tag Tag, i int64) {
h.writeLongIntVal(tag, TypeLongInteger, i)
}
func (h *encBuf) encodeDateTime(tag Tag, t time.Time) {
h.writeLongIntVal(tag, TypeDateTime, t.Unix())
}
func (h *encBuf) encodeDateTimeExtended(tag Tag, t time.Time) {
// take unix seconds, times a million, to get microseconds, then
// add nanoseconds remainder/1000
//
// this gives us a larger ranger of possible values than just t.UnixNano() / 1000.
// see UnixNano() docs for its limits.
//
// this is limited to max(int64) *microseconds* from epoch, rather than
// max(int64) nanoseconds like UnixNano().
m := (t.Unix() * 1000000) + int64(t.Nanosecond()/1000)
h.writeLongIntVal(tag, TypeDateTimeExtended, m)
}
func (h *encBuf) encodeInterval(tag Tag, d time.Duration) {
h.writeIntVal(tag, TypeInterval, uint32(d/time.Second))
}
func (h *encBuf) encodeEnum(tag Tag, i uint32) {
h.writeIntVal(tag, TypeEnumeration, i)
}
func (h *encBuf) encodeTextString(tag Tag, s string) {
i := h.begin(tag, TypeTextString)
_, _ = h.WriteString(s)
h.end(i)
}
func (h *encBuf) encodeByteString(tag Tag, b []byte) {
if b == nil {
return
}
i := h.begin(tag, TypeByteString)
_, _ = h.Write(b)
h.end(i)
}
func getTypeInfo(typ reflect.Type) (ti typeInfo, err error) {
ti.inferredTag, _ = DefaultRegistry.ParseTag(typ.Name())
ti.typ = typ
err = ti.getFieldsInfo()
return ti, err
}
var errSkip = errors.New("skip")
func getFieldInfo(typ reflect.Type, sf reflect.StructField) (fieldInfo, error) {
var fi fieldInfo
// skip anonymous and unexported fields
if sf.Anonymous || /*unexported:*/ sf.PkgPath != "" {
return fi, errSkip
}
fi.name = sf.Name
fi.structType = typ
fi.index = sf.Index
var anyField bool
// handle field tags
parts := strings.Split(sf.Tag.Get(structFieldTag), ",")
for i, value := range parts {
if i == 0 {
switch value {
case "-":
// skip
return fi, errSkip
case "":
default:
var err error
fi.explicitTag, err = DefaultRegistry.ParseTag(value)
if err != nil {
return fi, err
}
}
} else {
switch strings.ToLower(value) {
case "enum":
fi.flags |= fEnum
case "omitempty":
fi.flags |= fOmitEmpty
case "datetimeextended":
fi.flags |= fDateTimeExtended
case "bitmask":
fi.flags |= fBitBask
case "any":
anyField = true
fi.flags |= fAny
}
}
}
if anyField && fi.explicitTag != TagNone {
return fi, merry.Here(ErrTagConflict).Appendf(`field %s.%s may not specify a TTLV tag and the "any" flag`, fi.structType.Name(), fi.name)
}
// extract type info for the field. The KMIP tag
// for this field is derived from either the field name,
// the field tags, or the field type.
var err error
fi.ti, err = getTypeInfo(sf.Type)
if err != nil {
return fi, err
}
if fi.ti.tagField != nil && fi.ti.tagField.explicitTag != TagNone {
fi.tag = fi.ti.tagField.explicitTag
if fi.explicitTag != TagNone && fi.explicitTag != fi.tag {
// if there was a tag on the struct field containing this value, it must
// agree with the value's intrinsic tag
return fi, merry.Here(ErrTagConflict).Appendf(`TTLV tag "%s" in tag of %s.%s conflicts with TTLV tag "%s" in %s.%s`, fi.explicitTag, fi.structType.Name(), fi.name, fi.ti.tagField.explicitTag, fi.ti.typ.Name(), fi.ti.tagField.name)
}
}
// pre-calculate the tag for this field. This intentional duplicates
// some of tagForMarshaling(). The value is primarily used in unmarshaling
// where the dynamic value of the field is not needed.
if fi.tag == TagNone {
fi.tag = fi.explicitTag
}
if fi.tag == TagNone {
fi.tag, _ = DefaultRegistry.ParseTag(fi.name)
}
return fi, nil
}
func (ti *typeInfo) getFieldsInfo() error {
if ti.typ.Kind() != reflect.Struct {
return nil
}
for i := 0; i < ti.typ.NumField(); i++ {
fi, err := getFieldInfo(ti.typ, ti.typ.Field(i))
switch {
case err == errSkip: //nolint:errorlint
// skip
case err != nil:
return err
case fi.name == "TTLVTag":
ti.tagField = &fi
default:
ti.valueFields = append(ti.valueFields, fi)
}
}
// verify that multiple fields don't have the same tag
names := map[Tag]string{}
for _, f := range ti.valueFields {
if f.flags.any() {
// ignore any fields
continue
}
tag := f.tag
if tag != TagNone {
if fname, ok := names[tag]; ok {
return merry.Here(ErrTagConflict).Appendf("field resolves to the same tag (%s) as other field (%s)", tag, fname)
}
names[tag] = f.name
}
}
return nil
}
type typeInfo struct {
typ reflect.Type
inferredTag Tag
tagField *fieldInfo
valueFields []fieldInfo
}
const (
fOmitEmpty fieldFlags = 1 << iota
fEnum
fDateTimeExtended
fAny
fBitBask
)
type fieldFlags int
func (f fieldFlags) omitEmpty() bool {
return f&fOmitEmpty != 0
}
func (f fieldFlags) any() bool {
return f&fAny != 0
}
func (f fieldFlags) dateTimeExt() bool {
return f&fDateTimeExtended != 0
}
func (f fieldFlags) enum() bool {
return f&fEnum != 0
}
func (f fieldFlags) bitmask() bool {
return f&fBitBask != 0
}
type fieldInfo struct {
structType reflect.Type
explicitTag, tag Tag
name string
index []int
flags fieldFlags
ti typeInfo
}

8
vendor/github.com/gemalto/kmip-go/ttlv/errors.go generated vendored Normal file
View File

@ -0,0 +1,8 @@
package ttlv
import "github.com/ansel1/merry"
// Details prints details from the error, including a stacktrace when available.
func Details(err error) string {
return merry.Details(err)
}

314
vendor/github.com/gemalto/kmip-go/ttlv/formatting.go generated vendored Normal file
View File

@ -0,0 +1,314 @@
package ttlv
import (
"fmt"
"strconv"
"strings"
"github.com/ansel1/merry"
"github.com/gemalto/kmip-go/internal/kmiputil"
)
// FormatType formats a byte as a KMIP Type string,
// as described in the KMIP Profiles spec. If the value is registered,
// the normalized name of the value will be returned.
//
// Otherwise, a 1 byte hex string is returned, but this is not
// technically a valid encoding for types in the JSON and XML encoding
// specs. Hex values Should only be used for debugging. Examples:
//
// - Integer
// - 0x42
func FormatType(b byte, enumMap EnumMap) string {
if enumMap != nil {
if s, ok := enumMap.Name(uint32(b)); ok {
return s
}
}
return fmt.Sprintf("%#02x", b)
}
// FormatTag formats an uint32 as a KMIP Tag string,
// as described in the KMIP Profiles spec. If the value is registered,
// the normalized name of the value will be returned. Otherwise, a
// 3 byte hex string is returned. Examples:
//
// - ActivationDate
// - 0x420001
func FormatTag(v uint32, enumMap EnumMap) string {
if enumMap != nil {
if s, ok := enumMap.Name(v); ok {
return s
}
}
return fmt.Sprintf("%#06x", v)
}
// FormatTagCanonical formats an uint32 as a canonical Tag name
// from the KMIP spec. If the value is registered,
// the canonical name of the value will be returned. Otherwise, a
// 3 byte hex string is returned. Examples:
//
// - Activation Date
// - 0x420001
//
// Canonical tag names are used in the AttributeName of Attribute structs.
func FormatTagCanonical(v uint32, enumMap EnumMap) string {
if enumMap != nil {
if s, ok := enumMap.CanonicalName(v); ok {
return s
}
}
return fmt.Sprintf("%#06x", v)
}
// FormatEnum formats an uint32 as a KMIP Enumeration string,
// as described in the KMIP Profiles spec. If the value is registered,
// the normalized name of the value will be returned. Otherwise, a
// four byte hex string is returned. Examples:
//
// - SymmetricKey
// - 0x00000002
func FormatEnum(v uint32, enumMap EnumMap) string {
if enumMap != nil {
if s, ok := enumMap.Name(v); ok {
return s
}
}
return fmt.Sprintf("%#08x", v)
}
// FormatInt formats an integer as a KMIP bitmask string, as
// described in the KMIP Profiles spec for JSON under
// the "Special case for Masks" section. Examples:
//
// - 0x0000100c
// - Encrypt|Decrypt|CertificateSign
// - CertificateSign|0x00000004|0x0000008
// - CertificateSign|0x0000000c
func FormatInt(i int32, enumMap EnumMap) string {
if enumMap == nil {
return fmt.Sprintf("%#08x", i)
}
values := enumMap.Values()
if len(values) == 0 {
return fmt.Sprintf("%#08x", i)
}
v := uint32(i)
// bitmask
// decompose mask into the names of set flags, concatenated by pipe
// if remaining value (minus registered flags) is not zero, append
// the remaining value as hex.
var sb strings.Builder
for _, v1 := range values {
if v1&v == v1 {
if name, ok := enumMap.Name(v1); ok {
if sb.Len() > 0 {
sb.WriteString("|")
}
sb.WriteString(name)
v ^= v1
}
}
if v == 0 {
break
}
}
if v != 0 {
if sb.Len() > 0 {
sb.WriteString("|")
}
_, _ = fmt.Fprintf(&sb, "%#08x", v)
}
return sb.String()
}
// ParseEnum parses a string into a uint32 according to the rules
// in the KMIP Profiles regarding encoding enumeration values.
// See FormatEnum for examples of the formats which can be parsed.
// It will also parse numeric strings. Examples:
//
// ParseEnum("UnableToCancel", registry.EnumForTag(TagCancellationResult))
// ParseEnum("0x00000002")
// ParseEnum("2")
//
// Returns ErrInvalidHexString if the string is invalid hex, or
// if the hex value is less than 1 byte or more than 4 bytes (ignoring
// leading zeroes).
//
// Returns ErrUnregisteredEnumName if string value is not a
// registered enum value name.
func ParseEnum(s string, enumMap EnumMap) (uint32, error) {
u, err := strconv.ParseUint(s, 10, 32)
if err == nil {
// it was a raw number
return uint32(u), nil
}
v, err := parseHexOrName(s, 4, enumMap)
if err != nil {
return 0, merry.Here(err)
}
return v, nil
}
// ParseInt parses a string into an int32 according the rules
// in the KMIP Profiles regarding encoding integers, including
// the special rules for bitmasks. See FormatInt for examples
// of the formats which can be parsed.
//
// Returns ErrInvalidHexString if the string is invalid hex, or
// if the hex value is less than 1 byte or more than 4 bytes (ignoring
// leading zeroes).
//
// Returns ErrUnregisteredEnumName if string value is not a
// registered enum value name.
func ParseInt(s string, enumMap EnumMap) (int32, error) {
i, err := strconv.ParseInt(s, 10, 32)
if err == nil {
// it was a raw number
return int32(i), nil
}
if !strings.ContainsAny(s, "| ") {
v, err := parseHexOrName(s, 4, enumMap)
if err != nil {
return 0, merry.Here(err)
}
return int32(v), nil
}
// split values, look up each, and recombine
s = strings.ReplaceAll(s, "|", " ")
parts := strings.Split(s, " ")
var v uint32
for _, part := range parts {
if len(part) == 0 {
continue
}
i, err := parseHexOrName(part, 4, enumMap)
if err != nil {
return 0, merry.Here(err)
}
v |= i
}
return int32(v), nil
}
func parseHexOrName(s string, max int, enumMap EnumMap) (uint32, error) {
b, err := kmiputil.ParseHexValue(s, max)
if err != nil {
return 0, err
}
if b != nil {
return kmiputil.DecodeUint32(b), nil
}
if enumMap != nil {
if v, ok := enumMap.Value(s); ok {
return v, nil
}
}
return 0, merry.Append(ErrUnregisteredEnumName, s)
}
// ParseTag parses a string into Tag according the rules
// in the KMIP Profiles regarding encoding tag values.
// See FormatTag for examples of the formats which can be parsed.
//
// Returns ErrInvalidHexString if the string is invalid hex, or
// if the hex value is less than 1 byte or more than 3 bytes (ignoring
// leading zeroes).
//
// Returns ErrUnregisteredEnumName if string value is not a
// registered enum value name.
func ParseTag(s string, enumMap EnumMap) (Tag, error) {
v, err := parseHexOrName(s, 3, enumMap)
if err != nil {
return 0, merry.Here(err)
}
return Tag(v), nil
}
// ParseType parses a string into Type according the rules
// in the KMIP Profiles regarding encoding type values.
// See FormatType for examples of the formats which can be parsed.
// This also supports parsing a hex string type (e.g. "0x01"), though
// this is not technically a valid encoding of a type in the spec.
//
// Returns ErrInvalidHexString if the string is invalid hex, or
// if the hex value is less than 1 byte or more than 3 bytes (ignoring
// leading zeroes).
//
// Returns ErrUnregisteredEnumName if string value is not a
// registered enum value name.
func ParseType(s string, enumMap EnumMap) (Type, error) {
b, err := kmiputil.ParseHexValue(s, 1)
if err != nil {
return 0, merry.Here(err)
}
if b != nil {
return Type(b[0]), nil
}
if enumMap != nil {
if v, ok := enumMap.Value(s); ok {
return Type(v), nil
}
}
return 0, merry.Here(ErrUnregisteredEnumName).Append(s)
}
// EnumMap defines a set of named enumeration values. Canonical names should
// be the name from the spec. Names should be in the normalized format
// described in the KMIP spec (see NormalizeName()).
//
//
// Value enumerations are used for encoding and decoding KMIP Enumeration values,
// KMIP Integer bitmask values, Types, and Tags.
type EnumMap interface {
// Name returns the normalized name for a value, e.g. AttributeName.
// If the name is not registered, it returns "", false.
Name(v uint32) (string, bool)
// CanonicalName returns the canonical name for the value from the spec,
// e.g. Attribute Name.
// If the name is not registered, it returns "", false
CanonicalName(v uint32) (string, bool)
// Value returns the value registered for the name argument. If there is
// no name registered for this value, it returns 0, false.
// The name argument may be the canonical name (e.g. "Cryptographic Algorithm") or
// the normalized name (e.g. "CryptographicAlgorithm").
Value(name string) (uint32, bool)
// Values returns the complete set of registered values. The order
// they are returned in will be the order they are encoded in when
// encoding bitmasks as strings.
Values() []uint32
// Bitmask returns true if this is an enumeration of bitmask flags.
Bitmask() bool
}

248
vendor/github.com/gemalto/kmip-go/ttlv/registry.go generated vendored Normal file
View File

@ -0,0 +1,248 @@
package ttlv
import (
"sort"
"github.com/ansel1/merry"
"github.com/gemalto/kmip-go/internal/kmiputil"
)
// DefaultRegistry holds the default mappings of types, tags, enums, and bitmasks
// to canonical names and normalized names from the KMIP spec. It is pre-populated with the 1.4 spec's
// values. It can be replaced, or additional values can be registered with it.
//
// It is not currently concurrent-safe, so replace or configure it early in your
// program.
var DefaultRegistry Registry
// nolint:gochecknoinits
func init() {
RegisterTypes(&DefaultRegistry)
}
var (
ErrInvalidHexString = kmiputil.ErrInvalidHexString
ErrUnregisteredEnumName = merry.New("unregistered enum name")
)
// NormalizeName tranforms KMIP names from the spec into the
// normalized form of the name. Typically, this means removing spaces,
// and replacing some special characters. The normalized form of the name
// is used in the JSON and XML encodings from the KMIP Profiles.
// The spec describes the normalization process in 5.4.1.1 and 5.5.1.1
func NormalizeName(s string) string {
return kmiputil.NormalizeName(s)
}
// Enum represents an enumeration of KMIP values (as uint32), and maps them
// to the canonical string names and the normalized string names of the
// value as declared in the KMIP specs.
// Enum is used to transpose values from strings to byte values, as required
// by the JSON and XML encodings defined in the KMIP Profiles spec.
// These mappings are also used to pretty print KMIP values, and to marshal
// and unmarshal enum and bitmask values to golang string values.
//
// Enum currently uses plain maps, so it is not thread safe to register new values
// concurrently. You should register all values at the start of your program before
// using this package concurrently.
//
// Enums are used in the KMIP spec for two purposes: for defining the possible values
// for values encoded as the KMIP Enumeration type, and for bitmask values. Bitmask
// values are encoded as Integers, but are really enum values bitwise-OR'd together.
//
// Enums are registered with a Registry. The code to register enums is typically
// generated by the kmipgen tool.
type Enum struct {
valuesToName map[uint32]string
valuesToCanonicalName map[uint32]string
nameToValue map[string]uint32
canonicalNamesToValue map[string]uint32
bitMask bool
}
func NewEnum() Enum {
return Enum{}
}
func NewBitmask() Enum {
return Enum{
bitMask: true,
}
}
// RegisterValue adds a mapping of a uint32 value to a name. The name will be
// processed by NormalizeName to produce the normalized enum value name as described
// in the KMIP spec.
func (e *Enum) RegisterValue(v uint32, name string) {
nn := NormalizeName(name)
if e.valuesToName == nil {
e.valuesToName = map[uint32]string{}
e.nameToValue = map[string]uint32{}
e.valuesToCanonicalName = map[uint32]string{}
e.canonicalNamesToValue = map[string]uint32{}
}
e.valuesToName[v] = nn
e.nameToValue[nn] = v
e.valuesToCanonicalName[v] = name
e.canonicalNamesToValue[name] = v
}
func (e *Enum) Name(v uint32) (string, bool) {
if e == nil {
return "", false
}
name, ok := e.valuesToName[v]
return name, ok
}
func (e *Enum) CanonicalName(v uint32) (string, bool) {
if e == nil {
return "", false
}
name, ok := e.valuesToCanonicalName[v]
return name, ok
}
func (e *Enum) Value(name string) (uint32, bool) {
if e == nil {
return 0, false
}
v, ok := e.nameToValue[name]
if !ok {
v, ok = e.canonicalNamesToValue[name]
}
return v, ok
}
func (e *Enum) Values() []uint32 {
values := make([]uint32, 0, len(e.valuesToName))
for v := range e.valuesToName {
values = append(values, v)
}
// Always list them in order of value so output is stable.
sort.Sort(uint32Slice(values))
return values
}
func (e *Enum) Bitmask() bool {
if e == nil {
return false
}
return e.bitMask
}
// Registry holds all the known tags, types, enums and bitmaps declared in
// a KMIP spec. It's used throughout the package to map values their canonical
// and normalized names.
type Registry struct {
enums map[Tag]EnumMap
tags Enum
types Enum
}
func (r *Registry) RegisterType(t Type, name string) {
r.types.RegisterValue(uint32(t), name)
}
func (r *Registry) RegisterTag(t Tag, name string) {
r.tags.RegisterValue(uint32(t), name)
}
func (r *Registry) RegisterEnum(t Tag, def EnumMap) {
if r.enums == nil {
r.enums = map[Tag]EnumMap{}
}
r.enums[t] = def
}
// EnumForTag returns the enum map registered for a tag. Returns
// nil if no map is registered for this tag.
func (r *Registry) EnumForTag(t Tag) EnumMap {
if r.enums == nil {
return nil
}
return r.enums[t]
}
func (r *Registry) IsBitmask(t Tag) bool {
if e := r.EnumForTag(t); e != nil {
return e.Bitmask()
}
return false
}
func (r *Registry) IsEnum(t Tag) bool {
if e := r.EnumForTag(t); e != nil {
return !e.Bitmask()
}
return false
}
func (r *Registry) Tags() EnumMap {
return &r.tags
}
func (r *Registry) Types() EnumMap {
return &r.types
}
func (r *Registry) FormatEnum(t Tag, v uint32) string {
return FormatEnum(v, r.EnumForTag(t))
}
func (r *Registry) FormatInt(t Tag, v int32) string {
return FormatInt(v, r.EnumForTag(t))
}
func (r *Registry) FormatTag(t Tag) string {
return FormatTag(uint32(t), &r.tags)
}
func (r *Registry) FormatTagCanonical(t Tag) string {
return FormatTagCanonical(uint32(t), &r.tags)
}
func (r *Registry) FormatType(t Type) string {
return FormatType(byte(t), &r.types)
}
func (r *Registry) ParseEnum(t Tag, s string) (uint32, error) {
return ParseEnum(s, r.EnumForTag(t))
}
func (r *Registry) ParseInt(t Tag, s string) (int32, error) {
return ParseInt(s, r.EnumForTag(t))
}
// ParseTag parses a string into Tag according the rules
// in the KMIP Profiles regarding encoding tag values.
// Returns TagNone if not found.
// Returns error if s is a malformed hex string, or a hex string of incorrect length
func (r *Registry) ParseTag(s string) (Tag, error) {
return ParseTag(s, &r.tags)
}
func (r *Registry) ParseType(s string) (Type, error) {
return ParseType(s, &r.types)
}
// uint32Slice attaches the methods of Interface to []int, sorting in increasing order.
type uint32Slice []uint32
func (p uint32Slice) Len() int { return len(p) }
func (p uint32Slice) Less(i, j int) bool { return p[i] < p[j] }
func (p uint32Slice) Swap(i, j int) { p[i], p[j] = p[j], p[i] }

50
vendor/github.com/gemalto/kmip-go/ttlv/tag.go generated vendored Normal file
View File

@ -0,0 +1,50 @@
package ttlv
const (
TagNone = Tag(0)
tagAttributeName Tag = 0x42000a
tagAttributeValue Tag = 0x42000b
)
// Tag
// 9.1.3.1
type Tag uint32
// String returns the normalized name of the tag.
func (t Tag) String() string {
return DefaultRegistry.FormatTag(t)
}
// CanonicalName returns the canonical name of the tag.
func (t Tag) CanonicalName() string {
return DefaultRegistry.FormatTagCanonical(t)
}
func (t Tag) MarshalText() (text []byte, err error) {
return []byte(t.String()), nil
}
func (t *Tag) UnmarshalText(text []byte) (err error) {
*t, err = DefaultRegistry.ParseTag(string(text))
return
}
const (
minStandardTag uint32 = 0x00420000
maxStandardTag uint32 = 0x00430000
minCustomTag uint32 = 0x00540000
maxCustomTag uint32 = 0x00550000
)
// Valid checks whether the tag's numeric value is valid according to
// the ranges in the spec.
func (t Tag) Valid() bool {
switch {
case uint32(t) >= minStandardTag && uint32(t) < maxStandardTag:
return true
case uint32(t) >= minCustomTag && uint32(t) < maxCustomTag:
return true
default:
return false
}
}

1252
vendor/github.com/gemalto/kmip-go/ttlv/ttlv.go generated vendored Normal file

File diff suppressed because it is too large Load Diff

196
vendor/github.com/gemalto/kmip-go/ttlv/types.go generated vendored Normal file
View File

@ -0,0 +1,196 @@
package ttlv
import (
"io"
"time"
)
func RegisterTypes(r *Registry) {
m := map[string]Type{
"BigInteger": TypeBigInteger,
"Boolean": TypeBoolean,
"ByteString": TypeByteString,
"DateTime": TypeDateTime,
"Enumeration": TypeEnumeration,
"Integer": TypeInteger,
"Interval": TypeInterval,
"LongInteger": TypeLongInteger,
"Structure": TypeStructure,
"TextString": TypeTextString,
"DateTimeExtended": TypeDateTimeExtended,
}
for name, v := range m {
r.RegisterType(v, name)
}
}
// Type describes the type of a KMIP TTLV.
// 2 and 9.1.1.2
type Type byte
const (
TypeStructure Type = 0x01
TypeInteger Type = 0x02
TypeLongInteger Type = 0x03
TypeBigInteger Type = 0x04
TypeEnumeration Type = 0x05
TypeBoolean Type = 0x06
TypeTextString Type = 0x07
TypeByteString Type = 0x08
TypeDateTime Type = 0x09
TypeInterval Type = 0x0A
TypeDateTimeExtended Type = 0x0B
)
// String returns the normalized name of the type. If the type
// name isn't registered, it returns the hex value of the type,
// e.g. "0x01" (TypeStructure). The value of String() is suitable
// for use in the JSON or XML encoding of TTLV.
func (t Type) String() string {
return DefaultRegistry.FormatType(t)
}
func (t Type) MarshalText() (text []byte, err error) {
return []byte(t.String()), nil
}
func (t *Type) UnmarshalText(text []byte) (err error) {
*t, err = DefaultRegistry.ParseType(string(text))
return
}
// DateTimeExtended is a time wrapper which always marshals to a DateTimeExtended.
type DateTimeExtended struct {
time.Time
}
func (t *DateTimeExtended) UnmarshalTTLV(d *Decoder, ttlv TTLV) error {
if len(ttlv) == 0 {
return nil
}
if t == nil {
*t = DateTimeExtended{}
}
err := d.DecodeValue(&t.Time, ttlv)
if err != nil {
return err
}
return nil
}
func (t DateTimeExtended) MarshalTTLV(e *Encoder, tag Tag) error {
e.EncodeDateTimeExtended(tag, t.Time)
return nil
}
// Value is a go-typed mapping for a TTLV value. It holds a tag, and the value in
// the form of a native go type.
//
// Value supports marshaling and unmarshaling, allowing a mapping between encoded TTLV
// bytes and native go types. It's useful in tests, or where you want to construct
// an arbitrary TTLV structure in code without declaring a bespoke type, e.g.:
//
// v := ttlv.Value{Tag: TagBatchCount, Value: Values{
// Value{Tag: TagComment, Value: "red"},
// Value{Tag: TagComment, Value: "blue"},
// Value{Tag: TagComment, Value: "green"},
// }
// t, err := ttlv.Marshal(v)
//
// KMIP Structure types are mapped to the Values go type. When marshaling, if the Value
// field is set to a Values{}, the resulting TTLV will be TypeStructure. When unmarshaling
// a TTLV with TypeStructure, the Value field will be set to a Values{}.
type Value struct {
Tag Tag
Value interface{}
}
// UnmarshalTTLV implements Unmarshaler
func (t *Value) UnmarshalTTLV(d *Decoder, ttlv TTLV) error {
t.Tag = ttlv.Tag()
switch ttlv.Type() {
case TypeStructure:
var v Values
ttlv = ttlv.ValueStructure()
for ttlv.Valid() == nil {
err := d.DecodeValue(&v, ttlv)
if err != nil {
return err
}
ttlv = ttlv.Next()
}
t.Value = v
default:
t.Value = ttlv.Value()
}
return nil
}
// MarshalTTLV implements Marshaler
func (t Value) MarshalTTLV(e *Encoder, tag Tag) error {
// if tag is set, override the suggested tag
if t.Tag != TagNone {
tag = t.Tag
}
if tvs, ok := t.Value.(Values); ok {
return e.EncodeStructure(tag, func(e *Encoder) error {
for _, v := range tvs {
if err := e.Encode(v); err != nil {
return err
}
}
return nil
})
}
return e.EncodeValue(tag, t.Value)
}
// Values is a slice of Value objects. It represents the body of a TTLV with a type of Structure.
type Values []Value
// NewValue creates a new tagged value.
func NewValue(tag Tag, val interface{}) Value {
return Value{
Tag: tag,
Value: val,
}
}
// NewStruct creates a new tagged value which is of type struct.
func NewStruct(tag Tag, vals ...Value) Value {
return Value{
Tag: tag,
Value: Values(vals),
}
}
type Encoder struct {
encodeDepth int
w io.Writer
encBuf encBuf
// these fields store where the encoder is when marshaling a nested struct. its
// used to construct error messages.
currStruct string
currField string
}
// EnumValue is a uint32 wrapper which always encodes as an enumeration.
type EnumValue uint32
func (v EnumValue) MarshalTTLV(e *Encoder, tag Tag) error {
e.EncodeEnumeration(tag, uint32(v))
return nil
}