Home | History | Annotate | Download | only in cryptobyte
      1 // Copyright 2017 The Go Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style
      3 // license that can be found in the LICENSE file.
      4 
      5 // Package cryptobyte contains types that help with parsing and constructing
      6 // length-prefixed, binary messages, including ASN.1 DER. (The asn1 subpackage
      7 // contains useful ASN.1 constants.)
      8 //
      9 // The String type is for parsing. It wraps a []byte slice and provides helper
     10 // functions for consuming structures, value by value.
     11 //
     12 // The Builder type is for constructing messages. It providers helper functions
     13 // for appending values and also for appending length-prefixed submessages 
     14 // without having to worry about calculating the length prefix ahead of time.
     15 //
     16 // See the documentation and examples for the Builder and String types to get
     17 // started.
     18 package cryptobyte // import "golang.org/x/crypto/cryptobyte"
     19 
     20 // String represents a string of bytes. It provides methods for parsing
     21 // fixed-length and length-prefixed values from it.
     22 type String []byte
     23 
     24 // read advances a String by n bytes and returns them. If less than n bytes
     25 // remain, it returns nil.
     26 func (s *String) read(n int) []byte {
     27 	if len(*s) < n {
     28 		return nil
     29 	}
     30 	v := (*s)[:n]
     31 	*s = (*s)[n:]
     32 	return v
     33 }
     34 
     35 // Skip advances the String by n byte and reports whether it was successful.
     36 func (s *String) Skip(n int) bool {
     37 	return s.read(n) != nil
     38 }
     39 
     40 // ReadUint8 decodes an 8-bit value into out and advances over it. It
     41 // returns true on success and false on error.
     42 func (s *String) ReadUint8(out *uint8) bool {
     43 	v := s.read(1)
     44 	if v == nil {
     45 		return false
     46 	}
     47 	*out = uint8(v[0])
     48 	return true
     49 }
     50 
     51 // ReadUint16 decodes a big-endian, 16-bit value into out and advances over it.
     52 // It returns true on success and false on error.
     53 func (s *String) ReadUint16(out *uint16) bool {
     54 	v := s.read(2)
     55 	if v == nil {
     56 		return false
     57 	}
     58 	*out = uint16(v[0])<<8 | uint16(v[1])
     59 	return true
     60 }
     61 
     62 // ReadUint24 decodes a big-endian, 24-bit value into out and advances over it.
     63 // It returns true on success and false on error.
     64 func (s *String) ReadUint24(out *uint32) bool {
     65 	v := s.read(3)
     66 	if v == nil {
     67 		return false
     68 	}
     69 	*out = uint32(v[0])<<16 | uint32(v[1])<<8 | uint32(v[2])
     70 	return true
     71 }
     72 
     73 // ReadUint32 decodes a big-endian, 32-bit value into out and advances over it.
     74 // It returns true on success and false on error.
     75 func (s *String) ReadUint32(out *uint32) bool {
     76 	v := s.read(4)
     77 	if v == nil {
     78 		return false
     79 	}
     80 	*out = uint32(v[0])<<24 | uint32(v[1])<<16 | uint32(v[2])<<8 | uint32(v[3])
     81 	return true
     82 }
     83 
     84 func (s *String) readUnsigned(out *uint32, length int) bool {
     85 	v := s.read(length)
     86 	if v == nil {
     87 		return false
     88 	}
     89 	var result uint32
     90 	for i := 0; i < length; i++ {
     91 		result <<= 8
     92 		result |= uint32(v[i])
     93 	}
     94 	*out = result
     95 	return true
     96 }
     97 
     98 func (s *String) readLengthPrefixed(lenLen int, outChild *String) bool {
     99 	lenBytes := s.read(lenLen)
    100 	if lenBytes == nil {
    101 		return false
    102 	}
    103 	var length uint32
    104 	for _, b := range lenBytes {
    105 		length = length << 8
    106 		length = length | uint32(b)
    107 	}
    108 	if int(length) < 0 {
    109 		// This currently cannot overflow because we read uint24 at most, but check
    110 		// anyway in case that changes in the future.
    111 		return false
    112 	}
    113 	v := s.read(int(length))
    114 	if v == nil {
    115 		return false
    116 	}
    117 	*outChild = v
    118 	return true
    119 }
    120 
    121 // ReadUint8LengthPrefixed reads the content of an 8-bit length-prefixed value
    122 // into out and advances over it. It returns true on success and false on
    123 // error.
    124 func (s *String) ReadUint8LengthPrefixed(out *String) bool {
    125 	return s.readLengthPrefixed(1, out)
    126 }
    127 
    128 // ReadUint16LengthPrefixed reads the content of a big-endian, 16-bit
    129 // length-prefixed value into out and advances over it. It returns true on
    130 // success and false on error.
    131 func (s *String) ReadUint16LengthPrefixed(out *String) bool {
    132 	return s.readLengthPrefixed(2, out)
    133 }
    134 
    135 // ReadUint24LengthPrefixed reads the content of a big-endian, 24-bit
    136 // length-prefixed value into out and advances over it. It returns true on
    137 // success and false on error.
    138 func (s *String) ReadUint24LengthPrefixed(out *String) bool {
    139 	return s.readLengthPrefixed(3, out)
    140 }
    141 
    142 // ReadBytes reads n bytes into out and advances over them. It returns true on
    143 // success and false and error.
    144 func (s *String) ReadBytes(out *[]byte, n int) bool {
    145 	v := s.read(n)
    146 	if v == nil {
    147 		return false
    148 	}
    149 	*out = v
    150 	return true
    151 }
    152 
    153 // CopyBytes copies len(out) bytes into out and advances over them. It returns
    154 // true on success and false on error.
    155 func (s *String) CopyBytes(out []byte) bool {
    156 	n := len(out)
    157 	v := s.read(n)
    158 	if v == nil {
    159 		return false
    160 	}
    161 	return copy(out, v) == n
    162 }
    163 
    164 // Empty reports whether the string does not contain any bytes.
    165 func (s String) Empty() bool {
    166 	return len(s) == 0
    167 }
    168