...

Source file src/github.com/sassoftware/relic/signers/apk/serializer.go

Documentation: github.com/sassoftware/relic/signers/apk

     1  //
     2  // Copyright (c) SAS Institute Inc.
     3  //
     4  // Licensed under the Apache License, Version 2.0 (the "License");
     5  // you may not use this file except in compliance with the License.
     6  // You may obtain a copy of the License at
     7  //
     8  //     http://www.apache.org/licenses/LICENSE-2.0
     9  //
    10  // Unless required by applicable law or agreed to in writing, software
    11  // distributed under the License is distributed on an "AS IS" BASIS,
    12  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  // See the License for the specific language governing permissions and
    14  // limitations under the License.
    15  //
    16  
    17  package apk
    18  
    19  import (
    20  	"encoding/binary"
    21  	"fmt"
    22  	"io"
    23  	"reflect"
    24  
    25  	"github.com/pkg/errors"
    26  )
    27  
    28  // implement the uint32-prefixed structure of a APK Signature Scheme v2 Block
    29  // https://source.android.com/security/apksigning/v2#apk-signature-scheme-v2-block-format
    30  
    31  var errTrailingData = errors.New("trailing data after structure")
    32  
    33  type apkRaw []byte
    34  
    35  // Bytes returns the inner content of the raw item, without the length prefix
    36  func (r apkRaw) Bytes() []byte {
    37  	return []byte(r[4:])
    38  }
    39  
    40  var (
    41  	bytesType  = reflect.TypeOf([]byte(nil))
    42  	rawType    = reflect.TypeOf(apkRaw(nil))
    43  	uint32Type = reflect.TypeOf(uint32(0))
    44  )
    45  
    46  func unmarshal(blob []byte, dest interface{}) error {
    47  	v := reflect.ValueOf(dest)
    48  	if v.Kind() != reflect.Ptr || v.IsNil() {
    49  		return errors.New("target of unmarshal must be a non-nil pointer")
    50  	}
    51  	v = v.Elem()
    52  	blob, err := unmarshalR(blob, v) //, "x")
    53  	if err != nil {
    54  		return err
    55  	} else if len(blob) != 0 {
    56  		return errTrailingData
    57  	}
    58  	return nil
    59  }
    60  
    61  func unmarshalR(blob []byte, v reflect.Value /*, path string*/) ([]byte, error) {
    62  	// scalar types (no prefix)
    63  	switch {
    64  	case v.Type() == uint32Type:
    65  		if len(blob) < 4 {
    66  			return nil, io.ErrUnexpectedEOF
    67  		}
    68  		i := binary.LittleEndian.Uint32(blob)
    69  		//fmt.Printf("%s = 0x%x\n", path, i)
    70  		v.SetUint(uint64(i))
    71  		return blob[4:], nil
    72  	}
    73  	// read uint32 length prefix
    74  	if len(blob) < 4 {
    75  		return nil, io.ErrUnexpectedEOF
    76  	}
    77  	size := int(binary.LittleEndian.Uint32(blob))
    78  	if 4+len(blob) < size {
    79  		return nil, io.ErrUnexpectedEOF
    80  	}
    81  	remainder := blob[4+size:]
    82  	raw := blob[:4+size]
    83  	blob = raw[4:]
    84  	switch {
    85  	case v.Type() == bytesType:
    86  		// []byte
    87  		//fmt.Printf("%s = []byte(\"%x\")\n", path, blob)
    88  		v.SetBytes(blob)
    89  	case v.Type() == rawType:
    90  		// apkRaw (same as above but keep the prefix)
    91  		//fmt.Printf("%s = raw(\"%x\")\n", path, raw)
    92  		v.SetBytes(raw)
    93  	// compound types
    94  	case v.Kind() == reflect.Slice:
    95  		// slice other than []byte
    96  		itemType := v.Type().Elem()
    97  		//fmt.Printf("%s = %s{}\n", path, v.Type())
    98  		v.SetLen(0)
    99  		for len(blob) > 0 {
   100  			var err error
   101  			// append a zero value and unmarshal directly into the slice
   102  			n := v.Len()
   103  			v.Set(reflect.Append(v, reflect.Zero(itemType)))
   104  			blob, err = unmarshalR(blob, v.Index(n)) //, fmt.Sprintf("%s[%d]", path, n))
   105  			if err != nil {
   106  				return nil, err
   107  			}
   108  		}
   109  	case v.Kind() == reflect.Struct:
   110  		// structure
   111  		//fmt.Printf("%s = %s{}\n", path, v.Type())
   112  		for i := 0; i < v.NumField(); i++ {
   113  			var err error
   114  			blob, err = unmarshalR(blob, v.Field(i)) //, fmt.Sprintf("%s.%s", path, v.Type().Field(i).Name))
   115  			if err != nil {
   116  				return nil, err
   117  			}
   118  		}
   119  		if len(blob) > 0 {
   120  			return nil, errTrailingData
   121  		}
   122  	default:
   123  		panic("can't unmarshal type " + v.Type().String())
   124  	}
   125  	return remainder, nil
   126  }
   127  
   128  func marshal(src interface{}) (apkRaw, error) {
   129  	v := reflect.ValueOf(src)
   130  	m := new(marshaller)
   131  	if err := m.marshal(v); err != nil {
   132  		return nil, err
   133  	}
   134  	return apkRaw(m.buf), nil
   135  }
   136  
   137  type marshaller struct {
   138  	buf []byte
   139  	pos int
   140  }
   141  
   142  func (m *marshaller) grow(n int) []byte {
   143  	if cap(m.buf)-m.pos < n {
   144  		buf := make([]byte, 2*cap(m.buf)+n)
   145  		copy(buf, m.buf)
   146  		m.buf = buf
   147  	}
   148  	m.buf = m.buf[:m.pos+n]
   149  	ret := m.buf[m.pos : m.pos+n]
   150  	m.pos += n
   151  	return ret
   152  }
   153  
   154  func (m *marshaller) write(d []byte) {
   155  	copy(m.grow(len(d)), d)
   156  }
   157  
   158  func (m *marshaller) marshal(v reflect.Value) error {
   159  	if v.Type() == rawType {
   160  		// raw
   161  		m.write(v.Bytes())
   162  		return nil
   163  	}
   164  	// scalar types
   165  	switch {
   166  	case v.Type() == uint32Type:
   167  		binary.LittleEndian.PutUint32(m.grow(4), uint32(v.Uint()))
   168  		return nil
   169  	}
   170  	// prefixed types
   171  	start := m.pos
   172  	m.grow(4)
   173  	switch {
   174  	case v.Type() == bytesType:
   175  		// []byte
   176  		m.write(v.Bytes())
   177  	case v.Kind() == reflect.Slice:
   178  		// slice other than []byte
   179  		for i := 0; i < v.Len(); i++ {
   180  			if err := m.marshal(v.Index(i)); err != nil {
   181  				return err
   182  			}
   183  		}
   184  	case v.Kind() == reflect.Struct:
   185  		// structure
   186  		for i := 0; i < v.NumField(); i++ {
   187  			if err := m.marshal(v.Field(i)); err != nil {
   188  				return err
   189  			}
   190  		}
   191  	default:
   192  		return fmt.Errorf("can't marshal type %s", v.Type())
   193  	}
   194  	// put prefix
   195  	end := m.pos
   196  	binary.LittleEndian.PutUint32(m.buf[start:], uint32(end-start-4))
   197  	return nil
   198  }
   199  

View as plain text