github.com/egonelbre/exp@v0.0.0-20240430123955-ed1d3aa93911/smime/ber/marshaling.go (about) 1 package ber 2 3 // http://play.golang.org/p/MdL7k8-5ER 4 5 import ( 6 "encoding/asn1" 7 "errors" 8 "fmt" 9 "math/big" 10 ) 11 12 // TODO: Optional/Check/Explicit should be all be a single type, 13 // otherwise it's hard to make them work nicely with nesting 14 15 type Marshaler interface { 16 Marshal() (*Tree, error) 17 Unmarshal(*Tree) error 18 } 19 20 type RawTree struct { 21 Tree **Tree 22 } 23 24 func (m RawTree) Unmarshal(tree *Tree) error { 25 *m.Tree = tree 26 return nil 27 } 28 29 func (m RawTree) Marshal() (*Tree, error) { 30 return *m.Tree, nil 31 } 32 33 type DER struct { 34 V *[]byte 35 } 36 37 func (m DER) Unmarshal(tree *Tree) (err error) { 38 *m.V, err = EncodeTree(tree) 39 return 40 } 41 42 func (m DER) Marshal() (*Tree, error) { 43 return DecodeTree(*m.V) 44 } 45 46 type ASN1RawValue struct { 47 V *asn1.RawValue 48 } 49 50 func (m ASN1RawValue) Unmarshal(tree *Tree) (err error) { 51 var data []byte 52 if data, err = EncodeTree(tree); err != nil { 53 return 54 } 55 56 _, err = asn1.Unmarshal(data, m.V) 57 return 58 } 59 60 func (m ASN1RawValue) Marshal() (*Tree, error) { 61 return ASN1Tree(m.V) 62 } 63 64 type Check struct { 65 Class int 66 Tag int 67 Sub Marshaler 68 } 69 70 func (m Check) Unmarshal(tree *Tree) (err error) { 71 if tree.Class != m.Class || tree.Tag != m.Tag { 72 return fmt.Errorf("class/tag doesn't match: got %d/%d expected %d/%d", tree.Class, tree.Tag, m.Class, m.Tag) 73 } 74 return m.Sub.Unmarshal(tree) 75 } 76 77 func (m Check) Marshal() (*Tree, error) { 78 tree, err := m.Sub.Marshal() 79 if err != nil { 80 return nil, err 81 } 82 83 tree.Class = m.Class 84 tree.Tag = m.Tag 85 return tree, nil 86 } 87 88 type Sequence []Marshaler 89 90 func (s Sequence) Unmarshal(tree *Tree) (err error) { 91 children := tree.Children 92 93 var si, ti int 94 for si < len(s) { 95 m := s[si] 96 if opt, ok := m.(Optional); ok { 97 if ti >= len(children) { 98 si += 1 99 continue 100 } 101 102 switch optsub := opt.Sub.(type) { 103 case Check: 104 sub := children[ti] 105 if optsub.Class == sub.Class && optsub.Tag == sub.Tag { 106 if err = optsub.Sub.Unmarshal(sub); err != nil { 107 return 108 } 109 ti += 1 110 } 111 si += 1 112 default: 113 if err = optsub.Unmarshal(children[ti]); err != nil { 114 return 115 } 116 ti += 1 117 si += 1 118 } 119 } else { 120 if ti >= len(children) { 121 return fmt.Errorf("not enough children in tree") 122 } 123 124 sub := children[ti] 125 if err = m.Unmarshal(sub); err != nil { 126 return 127 } 128 129 ti += 1 130 si += 1 131 } 132 } 133 return 134 } 135 136 func (s Sequence) Marshal() (root *Tree, err error) { 137 root = &Tree{ 138 Token: &Token{ 139 Kind: Constructed, 140 Class: Universal, 141 Tag: TagSequence, 142 }, 143 } 144 145 var sub *Tree 146 for _, m := range s { 147 if sub, err = m.Marshal(); err != nil { 148 return 149 } 150 if _, optional := m.(Optional); optional && sub == nil { 151 // we can safely skip this 152 } else { 153 if sub == nil { 154 err = errors.New("marshaling returned nil") 155 return 156 } 157 root.Children = append(root.Children, sub) 158 } 159 } 160 return 161 } 162 163 type Choice []Marshaler 164 165 func (s Choice) Unmarshal(tree *Tree) (err error) { 166 for _, m := range s { 167 check, ok := m.(Check) 168 if !ok { 169 return fmt.Errorf("choice sequence doesn't contain check") 170 } 171 172 if check.Class == tree.Class && check.Tag == tree.Tag { 173 err = check.Unmarshal(tree) 174 return 175 } 176 } 177 178 return fmt.Errorf("applicable choice element not found") 179 } 180 181 func (s Choice) Marshal() (*Tree, error) { 182 // is there a way to handle this? 183 panic("choice shoudln't be used while marshaling") 184 return nil, nil 185 } 186 187 type Optional struct { 188 Sub Marshaler 189 } 190 191 func (m Optional) Unmarshal(tree *Tree) (err error) { 192 return m.Sub.Unmarshal(tree) 193 } 194 195 func isExplicit(s Marshaler) bool { 196 _, ok := s.(Explicit) 197 return ok 198 } 199 200 func isZero(tree *Tree) bool { 201 return (tree == nil) || 202 (tree.Kind == Value && len(tree.Bytes) == 0) || 203 (tree.Kind == Constructed && len(tree.Children) == 0) 204 } 205 206 func (m Optional) Marshal() (tree *Tree, err error) { 207 if tree, err = m.Sub.Marshal(); err != nil { 208 return 209 } 210 211 if isZero(tree) { 212 return nil, nil 213 } else if isExplicit(m.Sub) && isZero(tree.Children[0]) { 214 return nil, nil 215 } 216 return 217 } 218 219 type Explicit struct { 220 Sub Marshaler 221 } 222 223 func (m Explicit) Unmarshal(tree *Tree) (err error) { 224 if len(tree.Children) != 1 { 225 return fmt.Errorf("not enough values for explicit type") 226 } 227 return m.Sub.Unmarshal(tree.Children[0]) 228 } 229 230 func (m Explicit) Marshal() (tree *Tree, err error) { 231 var sub *Tree 232 if sub, err = m.Sub.Marshal(); err != nil { 233 return 234 } 235 tree = &Tree{ 236 Token: &Token{ 237 Kind: Constructed, 238 Class: Context, 239 Tag: 0, 240 }, 241 Children: []*Tree{sub}, 242 } 243 return 244 } 245 246 // TYPES 247 248 type OctetString struct { 249 V *[]byte 250 } 251 252 func (m OctetString) Unmarshal(tree *Tree) error { 253 val, err := tree.AsOctetString() 254 *m.V = val 255 return err 256 } 257 258 func (m OctetString) Marshal() (*Tree, error) { 259 return &Tree{ 260 Token: &Token{ 261 Kind: Value, 262 Class: Universal, 263 Tag: TagOctetString, 264 Bytes: *m.V, 265 }, 266 }, nil 267 } 268 269 type Int64 struct { 270 V *int64 271 } 272 273 func (m Int64) Unmarshal(tree *Tree) error { 274 val, err := tree.AsInt64() 275 *m.V = val 276 return err 277 } 278 279 func (m Int64) Marshal() (*Tree, error) { 280 return ASN1Tree(m.V) 281 } 282 283 type BigInt struct { 284 V **big.Int 285 } 286 287 func (m BigInt) Unmarshal(tree *Tree) error { 288 val, err := tree.AsBigInt() 289 *m.V = val 290 return err 291 } 292 func (m BigInt) Marshal() (*Tree, error) { 293 return ASN1Tree(m.V) 294 } 295 296 type ObjectIdentifier struct { 297 V *asn1.ObjectIdentifier 298 } 299 300 func (m ObjectIdentifier) Unmarshal(tree *Tree) error { 301 val, err := tree.AsObjectIdentifier() 302 *m.V = val 303 return err 304 } 305 func (m ObjectIdentifier) Marshal() (*Tree, error) { 306 return ASN1Tree(m.V) 307 } 308 309 func ASN1Tree(v interface{}) (*Tree, error) { 310 bytes, err := asn1.Marshal(v) 311 if err != nil { 312 return nil, err 313 } 314 return DecodeTree(bytes) 315 }