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 const (
22 tagBoolean = 1
23 tagInteger = 2
24 tagBitString = 3
25 tagOctetString = 4
26 tagOID = 6
27 tagEnum = 10
28 tagUTF8String = 12
29 tagSequence = 16
30 tagSet = 17
31 tagPrintableString = 19
32 tagT61String = 20
33 tagIA5String = 22
34 tagUTCTime = 23
35 tagGeneralizedTime = 24
36 tagGeneralString = 27
37 )
38
39 const (
40 classUniversal = 0
41 classApplication = 1
42 classContextSpecific = 2
43 classPrivate = 3
44 )
45
46 type tagAndLength struct {
47 class, tag, length int
48 isCompound bool
49 }
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70 type fieldParameters struct {
71 optional bool
72 explicit bool
73 application bool
74 defaultValue *int64
75 tag *int
76 stringType int
77 set bool
78
79
80
81 }
82
83
84
85
86 func parseFieldParameters(str string) (ret fieldParameters) {
87 for _, part := range strings.Split(str, ",") {
88 switch {
89 case part == "optional":
90 ret.optional = true
91 case part == "explicit":
92 ret.explicit = true
93 if ret.tag == nil {
94 ret.tag = new(int)
95 }
96 case part == "ia5":
97 ret.stringType = tagIA5String
98 case part == "printable":
99 ret.stringType = tagPrintableString
100 case strings.HasPrefix(part, "default:"):
101 i, err := strconv.Atoi64(part[8:])
102 if err == nil {
103 ret.defaultValue = new(int64)
104 *ret.defaultValue = i
105 }
106 case strings.HasPrefix(part, "tag:"):
107 i, err := strconv.Atoi(part[4:])
108 if err == nil {
109 ret.tag = new(int)
110 *ret.tag = i
111 }
112 case part == "set":
113 ret.set = true
114 case part == "application":
115 ret.application = true
116 if ret.tag == nil {
117 ret.tag = new(int)
118 }
119 }
120 }
121 return
122 }
123
124
125
126 func getUniversalType(t reflect.Type) (tagNumber int, isCompound, ok bool) {
127 switch t {
128 case objectIdentifierType:
129 return tagOID, false, true
130 case bitStringType:
131 return tagBitString, false, true
132 case timeType:
133 return tagUTCTime, false, true
134 case enumeratedType:
135 return tagEnum, false, true
136 case bigIntType:
137 return tagInteger, false, true
138 }
139 switch t.Kind() {
140 case reflect.Bool:
141 return tagBoolean, false, true
142 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
143 return tagInteger, false, true
144 case reflect.Struct:
145 return tagSequence, true, true
146 case reflect.Slice:
147 if t.Elem().Kind() == reflect.Uint8 {
148 return tagOctetString, false, true
149 }
150 if strings.HasSuffix(t.Name(), "SET") {
151 return tagSet, true, true
152 }
153 return tagSequence, true, true
154 case reflect.String:
155 return tagPrintableString, false, true
156 }
157 return 0, false, false
158 }