1
2
3
4
5 package asn1
6
7 import (
8 "reflect"
9 "strconv"
10 "strings"
11 )
12
13
14
15
16
17
18
19
20
21
22 const (
23 TagBoolean = 1
24 TagInteger = 2
25 TagBitString = 3
26 TagOctetString = 4
27 TagNull = 5
28 TagOID = 6
29 TagEnum = 10
30 TagUTF8String = 12
31 TagSequence = 16
32 TagSet = 17
33 TagNumericString = 18
34 TagPrintableString = 19
35 TagT61String = 20
36 TagIA5String = 22
37 TagUTCTime = 23
38 TagGeneralizedTime = 24
39 TagGeneralString = 27
40 TagBMPString = 30
41 )
42
43
44 const (
45 ClassUniversal = 0
46 ClassApplication = 1
47 ClassContextSpecific = 2
48 ClassPrivate = 3
49 )
50
51 type tagAndLength struct {
52 class, tag, length int
53 isCompound bool
54 }
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75 type fieldParameters struct {
76 optional bool
77 explicit bool
78 application bool
79 private bool
80 defaultValue *int64
81 tag *int
82 stringType int
83 timeType int
84 set bool
85 omitEmpty bool
86
87
88
89 }
90
91
92
93
94 func parseFieldParameters(str string) (ret fieldParameters) {
95 var part string
96 for len(str) > 0 {
97 part, str, _ = strings.Cut(str, ",")
98 switch {
99 case part == "optional":
100 ret.optional = true
101 case part == "explicit":
102 ret.explicit = true
103 if ret.tag == nil {
104 ret.tag = new(int)
105 }
106 case part == "generalized":
107 ret.timeType = TagGeneralizedTime
108 case part == "utc":
109 ret.timeType = TagUTCTime
110 case part == "ia5":
111 ret.stringType = TagIA5String
112 case part == "printable":
113 ret.stringType = TagPrintableString
114 case part == "numeric":
115 ret.stringType = TagNumericString
116 case part == "utf8":
117 ret.stringType = TagUTF8String
118 case strings.HasPrefix(part, "default:"):
119 i, err := strconv.ParseInt(part[8:], 10, 64)
120 if err == nil {
121 ret.defaultValue = new(int64)
122 *ret.defaultValue = i
123 }
124 case strings.HasPrefix(part, "tag:"):
125 i, err := strconv.Atoi(part[4:])
126 if err == nil {
127 ret.tag = new(int)
128 *ret.tag = i
129 }
130 case part == "set":
131 ret.set = true
132 case part == "application":
133 ret.application = true
134 if ret.tag == nil {
135 ret.tag = new(int)
136 }
137 case part == "private":
138 ret.private = true
139 if ret.tag == nil {
140 ret.tag = new(int)
141 }
142 case part == "omitempty":
143 ret.omitEmpty = true
144 }
145 }
146 return
147 }
148
149
150
151 func getUniversalType(t reflect.Type) (matchAny bool, tagNumber int, isCompound, ok bool) {
152 switch t {
153 case rawValueType:
154 return true, -1, false, true
155 case objectIdentifierType:
156 return false, TagOID, false, true
157 case bitStringType:
158 return false, TagBitString, false, true
159 case timeType:
160 return false, TagUTCTime, false, true
161 case enumeratedType:
162 return false, TagEnum, false, true
163 case bigIntType:
164 return false, TagInteger, false, true
165 }
166 switch t.Kind() {
167 case reflect.Bool:
168 return false, TagBoolean, false, true
169 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
170 return false, TagInteger, false, true
171 case reflect.Struct:
172 return false, TagSequence, true, true
173 case reflect.Slice:
174 if t.Elem().Kind() == reflect.Uint8 {
175 return false, TagOctetString, false, true
176 }
177 if strings.HasSuffix(t.Name(), "SET") {
178 return false, TagSet, true, true
179 }
180 return false, TagSequence, true, true
181 case reflect.String:
182 return false, TagPrintableString, false, true
183 }
184 return false, 0, false, false
185 }
186
View as plain text