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
98
99 i := strings.IndexByte(str, ',')
100 if i < 0 {
101 part, str = str, ""
102 } else {
103 part, str = str[:i], str[i+1:]
104 }
105 switch {
106 case part == "optional":
107 ret.optional = true
108 case part == "explicit":
109 ret.explicit = true
110 if ret.tag == nil {
111 ret.tag = new(int)
112 }
113 case part == "generalized":
114 ret.timeType = TagGeneralizedTime
115 case part == "utc":
116 ret.timeType = TagUTCTime
117 case part == "ia5":
118 ret.stringType = TagIA5String
119 case part == "printable":
120 ret.stringType = TagPrintableString
121 case part == "numeric":
122 ret.stringType = TagNumericString
123 case part == "utf8":
124 ret.stringType = TagUTF8String
125 case strings.HasPrefix(part, "default:"):
126 i, err := strconv.ParseInt(part[8:], 10, 64)
127 if err == nil {
128 ret.defaultValue = new(int64)
129 *ret.defaultValue = i
130 }
131 case strings.HasPrefix(part, "tag:"):
132 i, err := strconv.Atoi(part[4:])
133 if err == nil {
134 ret.tag = new(int)
135 *ret.tag = i
136 }
137 case part == "set":
138 ret.set = true
139 case part == "application":
140 ret.application = true
141 if ret.tag == nil {
142 ret.tag = new(int)
143 }
144 case part == "private":
145 ret.private = true
146 if ret.tag == nil {
147 ret.tag = new(int)
148 }
149 case part == "omitempty":
150 ret.omitEmpty = true
151 }
152 }
153 return
154 }
155
156
157
158 func getUniversalType(t reflect.Type) (matchAny bool, tagNumber int, isCompound, ok bool) {
159 switch t {
160 case rawValueType:
161 return true, -1, false, true
162 case objectIdentifierType:
163 return false, TagOID, false, true
164 case bitStringType:
165 return false, TagBitString, false, true
166 case timeType:
167 return false, TagUTCTime, false, true
168 case enumeratedType:
169 return false, TagEnum, false, true
170 case bigIntType:
171 return false, TagInteger, false, true
172 }
173 switch t.Kind() {
174 case reflect.Bool:
175 return false, TagBoolean, false, true
176 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
177 return false, TagInteger, false, true
178 case reflect.Struct:
179 return false, TagSequence, true, true
180 case reflect.Slice:
181 if t.Elem().Kind() == reflect.Uint8 {
182 return false, TagOctetString, false, true
183 }
184 if strings.HasSuffix(t.Name(), "SET") {
185 return false, TagSet, true, true
186 }
187 return false, TagSequence, true, true
188 case reflect.String:
189 return false, TagPrintableString, false, true
190 }
191 return false, 0, false, false
192 }
193
View as plain text