common.go 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  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. // ASN.1 tags represent the type of the following object.
  17. const (
  18. TagBoolean = 1
  19. TagInteger = 2
  20. TagBitString = 3
  21. TagOctetString = 4
  22. TagNull = 5
  23. TagOID = 6
  24. TagEnum = 10
  25. TagUTF8String = 12
  26. TagSequence = 16
  27. TagSet = 17
  28. TagNumericString = 18
  29. TagPrintableString = 19
  30. TagT61String = 20
  31. TagIA5String = 22
  32. TagUTCTime = 23
  33. TagGeneralizedTime = 24
  34. TagGeneralString = 27
  35. TagBMPString = 30
  36. )
  37. // ASN.1 class types represent the namespace of the tag.
  38. const (
  39. ClassUniversal = 0
  40. ClassApplication = 1
  41. ClassContextSpecific = 2
  42. ClassPrivate = 3
  43. )
  44. type tagAndLength struct {
  45. class, tag, length int
  46. isCompound bool
  47. }
  48. // ASN.1 has IMPLICIT and EXPLICIT tags, which can be translated as "instead
  49. // of" and "in addition to". When not specified, every primitive type has a
  50. // default tag in the UNIVERSAL class.
  51. //
  52. // For example: a BIT STRING is tagged [UNIVERSAL 3] by default (although ASN.1
  53. // doesn't actually have a UNIVERSAL keyword). However, by saying [IMPLICIT
  54. // CONTEXT-SPECIFIC 42], that means that the tag is replaced by another.
  55. //
  56. // On the other hand, if it said [EXPLICIT CONTEXT-SPECIFIC 10], then an
  57. // /additional/ tag would wrap the default tag. This explicit tag will have the
  58. // compound flag set.
  59. //
  60. // (This is used in order to remove ambiguity with optional elements.)
  61. //
  62. // You can layer EXPLICIT and IMPLICIT tags to an arbitrary depth, however we
  63. // don't support that here. We support a single layer of EXPLICIT or IMPLICIT
  64. // tagging with tag strings on the fields of a structure.
  65. // fieldParameters is the parsed representation of tag string from a structure field.
  66. type fieldParameters struct {
  67. optional bool // true iff the field is OPTIONAL
  68. explicit bool // true iff an EXPLICIT tag is in use.
  69. application bool // true iff an APPLICATION tag is in use.
  70. private bool // true iff a PRIVATE tag is in use.
  71. defaultValue *int64 // a default value for INTEGER typed fields (maybe nil).
  72. tag *int // the EXPLICIT or IMPLICIT tag (maybe nil).
  73. stringType int // the string tag to use when marshaling.
  74. timeType int // the time tag to use when marshaling.
  75. set bool // true iff this should be encoded as a SET
  76. omitEmpty bool // true iff this should be omitted if empty when marshaling.
  77. lax bool // true iff unmarshalling should skip some error checks
  78. name string // name of field for better diagnostics
  79. // Invariants:
  80. // if explicit is set, tag is non-nil.
  81. }
  82. // Given a tag string with the format specified in the package comment,
  83. // parseFieldParameters will parse it into a fieldParameters structure,
  84. // ignoring unknown parts of the string.
  85. func parseFieldParameters(str string) (ret fieldParameters) {
  86. for _, part := range strings.Split(str, ",") {
  87. switch {
  88. case part == "optional":
  89. ret.optional = true
  90. case part == "explicit":
  91. ret.explicit = true
  92. if ret.tag == nil {
  93. ret.tag = new(int)
  94. }
  95. case part == "generalized":
  96. ret.timeType = TagGeneralizedTime
  97. case part == "utc":
  98. ret.timeType = TagUTCTime
  99. case part == "ia5":
  100. ret.stringType = TagIA5String
  101. case part == "printable":
  102. ret.stringType = TagPrintableString
  103. case part == "numeric":
  104. ret.stringType = TagNumericString
  105. case part == "utf8":
  106. ret.stringType = TagUTF8String
  107. case strings.HasPrefix(part, "default:"):
  108. i, err := strconv.ParseInt(part[8:], 10, 64)
  109. if err == nil {
  110. ret.defaultValue = new(int64)
  111. *ret.defaultValue = i
  112. }
  113. case strings.HasPrefix(part, "tag:"):
  114. i, err := strconv.Atoi(part[4:])
  115. if err == nil {
  116. ret.tag = new(int)
  117. *ret.tag = i
  118. }
  119. case part == "set":
  120. ret.set = true
  121. case part == "application":
  122. ret.application = true
  123. if ret.tag == nil {
  124. ret.tag = new(int)
  125. }
  126. case part == "private":
  127. ret.private = true
  128. if ret.tag == nil {
  129. ret.tag = new(int)
  130. }
  131. case part == "omitempty":
  132. ret.omitEmpty = true
  133. case part == "lax":
  134. ret.lax = true
  135. }
  136. }
  137. return
  138. }
  139. // Given a reflected Go type, getUniversalType returns the default tag number
  140. // and expected compound flag.
  141. func getUniversalType(t reflect.Type) (matchAny bool, tagNumber int, isCompound, ok bool) {
  142. switch t {
  143. case rawValueType:
  144. return true, -1, false, true
  145. case objectIdentifierType:
  146. return false, TagOID, false, true
  147. case bitStringType:
  148. return false, TagBitString, false, true
  149. case timeType:
  150. return false, TagUTCTime, false, true
  151. case enumeratedType:
  152. return false, TagEnum, false, true
  153. case bigIntType:
  154. return false, TagInteger, false, true
  155. }
  156. switch t.Kind() {
  157. case reflect.Bool:
  158. return false, TagBoolean, false, true
  159. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  160. return false, TagInteger, false, true
  161. case reflect.Struct:
  162. return false, TagSequence, true, true
  163. case reflect.Slice:
  164. if t.Elem().Kind() == reflect.Uint8 {
  165. return false, TagOctetString, false, true
  166. }
  167. if strings.HasSuffix(t.Name(), "SET") {
  168. return false, TagSet, true, true
  169. }
  170. return false, TagSequence, true, true
  171. case reflect.String:
  172. return false, TagPrintableString, false, true
  173. }
  174. return false, 0, false, false
  175. }