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  }