File: googletpm.go

package info (click to toggle)
golang-github-duo-labs-webauthn 0.0~git20220815.00c9fb5-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 908 kB
  • sloc: makefile: 5
file content (152 lines) | stat: -rw-r--r-- 4,014 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
package googletpm

import (
	"encoding/binary"
	"errors"
	"fmt"
	"io"
	"reflect"
)

// From github.com/google/go-tpm
// Portions of existing package conflicted with existing build environment
// and only needed very small amount of code for pubarea and certinfo structs
// so copied them out to this package

// Supported Algorithms.
const (
	AlgUnknown   Algorithm = 0x0000
	AlgRSA       Algorithm = 0x0001
	AlgSHA1      Algorithm = 0x0004
	AlgAES       Algorithm = 0x0006
	AlgKeyedHash Algorithm = 0x0008
	AlgSHA256    Algorithm = 0x000B
	AlgSHA384    Algorithm = 0x000C
	AlgSHA512    Algorithm = 0x000D
	AlgNull      Algorithm = 0x0010
	AlgRSASSA    Algorithm = 0x0014
	AlgRSAES     Algorithm = 0x0015
	AlgRSAPSS    Algorithm = 0x0016
	AlgOAEP      Algorithm = 0x0017
	AlgECDSA     Algorithm = 0x0018
	AlgECDH      Algorithm = 0x0019
	AlgECDAA     Algorithm = 0x001A
	AlgKDF2      Algorithm = 0x0021
	AlgECC       Algorithm = 0x0023
	AlgCTR       Algorithm = 0x0040
	AlgOFB       Algorithm = 0x0041
	AlgCBC       Algorithm = 0x0042
	AlgCFB       Algorithm = 0x0043
	AlgECB       Algorithm = 0x0044
)

// UnpackBuf recursively unpacks types from a reader just as encoding/binary
// does under binary.BigEndian, but with one difference: it unpacks a byte
// slice by first reading an integer with lengthPrefixSize bytes, then reading
// that many bytes. It assumes that incoming values are pointers to values so
// that, e.g., underlying slices can be resized as needed.
func UnpackBuf(buf io.Reader, elts ...interface{}) error {
	for _, e := range elts {
		v := reflect.ValueOf(e)
		k := v.Kind()
		if k != reflect.Ptr {
			return fmt.Errorf("all values passed to Unpack must be pointers, got %v", k)
		}

		if v.IsNil() {
			return errors.New("can't fill a nil pointer")
		}

		iv := reflect.Indirect(v)
		switch iv.Kind() {
		case reflect.Struct:
			// Decompose the struct and copy over the values.
			for i := 0; i < iv.NumField(); i++ {
				if err := UnpackBuf(buf, iv.Field(i).Addr().Interface()); err != nil {
					return err
				}
			}
		case reflect.Slice:
			var size int
			_, isHandles := e.(*[]Handle)

			switch {
			// []Handle always uses 2-byte length, even with TPM 1.2.
			case isHandles:
				var tmpSize uint16
				if err := binary.Read(buf, binary.BigEndian, &tmpSize); err != nil {
					return err
				}
				size = int(tmpSize)
			// TPM 2.0
			case lengthPrefixSize == tpm20PrefixSize:
				var tmpSize uint16
				if err := binary.Read(buf, binary.BigEndian, &tmpSize); err != nil {
					return err
				}
				size = int(tmpSize)
			// TPM 1.2
			case lengthPrefixSize == tpm12PrefixSize:
				var tmpSize uint32
				if err := binary.Read(buf, binary.BigEndian, &tmpSize); err != nil {
					return err
				}
				size = int(tmpSize)
			default:
				return fmt.Errorf("lengthPrefixSize is %d, must be either 2 or 4", lengthPrefixSize)
			}

			// A zero size is used by the TPM to signal that certain elements
			// are not present.
			if size == 0 {
				continue
			}

			// Make len(e) match size exactly.
			switch b := e.(type) {
			case *[]byte:
				if len(*b) >= size {
					*b = (*b)[:size]
				} else {
					*b = append(*b, make([]byte, size-len(*b))...)
				}
			case *[]Handle:
				if len(*b) >= size {
					*b = (*b)[:size]
				} else {
					*b = append(*b, make([]Handle, size-len(*b))...)
				}
			default:
				return fmt.Errorf("can't fill pointer to %T, only []byte or []Handle slices", e)
			}

			if err := binary.Read(buf, binary.BigEndian, e); err != nil {
				return err
			}
		default:
			if err := binary.Read(buf, binary.BigEndian, e); err != nil {
				return err
			}
		}

	}

	return nil
}

// lengthPrefixSize is the size in bytes of length prefix for byte slices.
//
// In TPM 1.2 this is 4 bytes.
// In TPM 2.0 this is 2 bytes.
var lengthPrefixSize int

const (
	tpm12PrefixSize = 4
	tpm20PrefixSize = 2
)

// UseTPM20LengthPrefixSize makes Pack/Unpack use TPM 2.0 encoding for byte
// arrays.
func UseTPM20LengthPrefixSize() {
	lengthPrefixSize = tpm20PrefixSize
}