common.go 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. // Copyright 2009 The Go Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. package asn1
  5. import (
  6. "reflect"
  7. "strconv"
  8. "strings"
  9. )
  10. // ASN.1 objects have metadata preceding them:
  11. // the tag: the type of the object
  12. // a flag denoting if this object is compound or not
  13. // the class type: the namespace of the tag
  14. // the length of the object, in bytes
  15. // Here are some standard tags and classes
  16. const (
  17. tagBoolean = 1
  18. tagInteger = 2
  19. tagBitString = 3
  20. tagOctetString = 4
  21. tagOID = 6
  22. tagEnum = 10
  23. tagUTF8String = 12
  24. tagSequence = 16
  25. tagSet = 17
  26. tagPrintableString = 19
  27. tagT61String = 20
  28. tagIA5String = 22
  29. tagUTCTime = 23
  30. tagGeneralizedTime = 24
  31. tagGeneralString = 27
  32. )
  33. const (
  34. classUniversal = 0
  35. classApplication = 1
  36. classContextSpecific = 2
  37. classPrivate = 3
  38. )
  39. type tagAndLength struct {
  40. class, tag, length int
  41. isCompound bool
  42. }
  43. // ASN.1 has IMPLICIT and EXPLICIT tags, which can be translated as "instead
  44. // of" and "in addition to". When not specified, every primitive type has a
  45. // default tag in the UNIVERSAL class.
  46. //
  47. // For example: a BIT STRING is tagged [UNIVERSAL 3] by default (although ASN.1
  48. // doesn't actually have a UNIVERSAL keyword). However, by saying [IMPLICIT
  49. // CONTEXT-SPECIFIC 42], that means that the tag is replaced by another.
  50. //
  51. // On the other hand, if it said [EXPLICIT CONTEXT-SPECIFIC 10], then an
  52. // /additional/ tag would wrap the default tag. This explicit tag will have the
  53. // compound flag set.
  54. //
  55. // (This is used in order to remove ambiguity with optional elements.)
  56. //
  57. // You can layer EXPLICIT and IMPLICIT tags to an arbitrary depth, however we
  58. // don't support that here. We support a single layer of EXPLICIT or IMPLICIT
  59. // tagging with tag strings on the fields of a structure.
  60. // fieldParameters is the parsed representation of tag string from a structure field.
  61. type fieldParameters struct {
  62. optional bool // true iff the field is OPTIONAL
  63. explicit bool // true iff an EXPLICIT tag is in use.
  64. application bool // true iff an APPLICATION tag is in use.
  65. defaultValue *int64 // a default value for INTEGER typed fields (maybe nil).
  66. tag *int // the EXPLICIT or IMPLICIT tag (maybe nil).
  67. stringType int // the string tag to use when marshaling.
  68. set bool // true iff this should be encoded as a SET
  69. omitEmpty bool // true iff this should be omitted if empty when marshaling.
  70. // Invariants:
  71. // if explicit is set, tag is non-nil.
  72. }
  73. // Given a tag string with the format specified in the package comment,
  74. // parseFieldParameters will parse it into a fieldParameters structure,
  75. // ignoring unknown parts of the string.
  76. func parseFieldParameters(str string) (ret fieldParameters) {
  77. for _, part := range strings.Split(str, ",") {
  78. switch {
  79. case part == "optional":
  80. ret.optional = true
  81. case part == "explicit":
  82. ret.explicit = true
  83. if ret.tag == nil {
  84. ret.tag = new(int)
  85. }
  86. case part == "ia5":
  87. ret.stringType = tagIA5String
  88. case part == "printable":
  89. ret.stringType = tagPrintableString
  90. case part == "utf8":
  91. ret.stringType = tagUTF8String
  92. case strings.HasPrefix(part, "default:"):
  93. i, err := strconv.ParseInt(part[8:], 10, 64)
  94. if err == nil {
  95. ret.defaultValue = new(int64)
  96. *ret.defaultValue = i
  97. }
  98. case strings.HasPrefix(part, "tag:"):
  99. i, err := strconv.Atoi(part[4:])
  100. if err == nil {
  101. ret.tag = new(int)
  102. *ret.tag = i
  103. }
  104. case part == "set":
  105. ret.set = true
  106. case part == "application":
  107. ret.application = true
  108. if ret.tag == nil {
  109. ret.tag = new(int)
  110. }
  111. case part == "omitempty":
  112. ret.omitEmpty = true
  113. }
  114. }
  115. return
  116. }
  117. // Given a reflected Go type, getUniversalType returns the default tag number
  118. // and expected compound flag.
  119. func getUniversalType(t reflect.Type) (tagNumber int, isCompound, ok bool) {
  120. switch t {
  121. case objectIdentifierType:
  122. return tagOID, false, true
  123. case bitStringType:
  124. return tagBitString, false, true
  125. case timeType:
  126. return tagUTCTime, false, true
  127. case enumeratedType:
  128. return tagEnum, false, true
  129. case bigIntType:
  130. return tagInteger, false, true
  131. }
  132. switch t.Kind() {
  133. case reflect.Bool:
  134. return tagBoolean, false, true
  135. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  136. return tagInteger, false, true
  137. case reflect.Struct:
  138. return tagSequence, true, true
  139. case reflect.Slice:
  140. if t.Elem().Kind() == reflect.Uint8 {
  141. return tagOctetString, false, true
  142. }
  143. if strings.HasSuffix(t.Name(), "SET") {
  144. return tagSet, true, true
  145. }
  146. return tagSequence, true, true
  147. case reflect.String:
  148. return tagPrintableString, false, true
  149. }
  150. return 0, false, false
  151. }