forked from duo-labs/webauthn
/
pubarea.go
240 lines (215 loc) · 6.71 KB
/
pubarea.go
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
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
package googletpm
import (
"bytes"
"fmt"
"math/big"
)
// DecodePublic decodes a TPMT_PUBLIC message. No error is returned if
// the input has extra trailing data.
func DecodePublic(buf []byte) (Public, error) {
in := bytes.NewBuffer(buf)
var pub Public
var err error
if err = UnpackBuf(in, &pub.Type, &pub.NameAlg, &pub.Attributes, &pub.AuthPolicy); err != nil {
return pub, fmt.Errorf("decoding TPMT_PUBLIC: %v", err)
}
switch pub.Type {
case AlgRSA:
pub.RSAParameters, err = decodeRSAParams(in)
case AlgECC:
pub.ECCParameters, err = decodeECCParams(in)
default:
err = fmt.Errorf("unsupported type in TPMT_PUBLIC: %v", pub.Type)
}
return pub, err
}
// Public contains the public area of an object.
type Public struct {
Type Algorithm
NameAlg Algorithm
Attributes KeyProp
AuthPolicy []byte
// If Type is AlgKeyedHash, then do not set these.
// Otherwise, only one of the Parameters fields should be set. When encoding/decoding,
// one will be picked based on Type.
RSAParameters *RSAParams
ECCParameters *ECCParams
}
// Algorithm represents a TPM_ALG_ID value.
type Algorithm uint16
// KeyProp is a bitmask used in Attributes field of key templates. Individual
// flags should be OR-ed to form a full mask.
type KeyProp uint32
// Key properties.
const (
FlagFixedTPM KeyProp = 0x00000002
FlagFixedParent KeyProp = 0x00000010
FlagSensitiveDataOrigin KeyProp = 0x00000020
FlagUserWithAuth KeyProp = 0x00000040
FlagAdminWithPolicy KeyProp = 0x00000080
FlagNoDA KeyProp = 0x00000400
FlagRestricted KeyProp = 0x00010000
FlagDecrypt KeyProp = 0x00020000
FlagSign KeyProp = 0x00040000
FlagSealDefault = FlagFixedTPM | FlagFixedParent
FlagSignerDefault = FlagSign | FlagRestricted | FlagFixedTPM |
FlagFixedParent | FlagSensitiveDataOrigin | FlagUserWithAuth
FlagStorageDefault = FlagDecrypt | FlagRestricted | FlagFixedTPM |
FlagFixedParent | FlagSensitiveDataOrigin | FlagUserWithAuth
)
func decodeRSAParams(in *bytes.Buffer) (*RSAParams, error) {
var params RSAParams
var err error
if params.Symmetric, err = decodeSymScheme(in); err != nil {
return nil, fmt.Errorf("decoding Symmetric: %v", err)
}
if params.Sign, err = decodeSigScheme(in); err != nil {
return nil, fmt.Errorf("decoding Sign: %v", err)
}
var modBytes []byte
if err := UnpackBuf(in, ¶ms.KeyBits, ¶ms.Exponent, &modBytes); err != nil {
return nil, fmt.Errorf("decoding KeyBits, Exponent, Modulus: %v", err)
}
if params.Exponent == 0 {
params.encodeDefaultExponentAsZero = true
params.Exponent = defaultRSAExponent
}
params.Modulus = new(big.Int).SetBytes(modBytes)
return ¶ms, nil
}
const defaultRSAExponent = 1<<16 + 1
// RSAParams represents parameters of an RSA key pair.
//
// Symmetric and Sign may be nil, depending on key Attributes in Public.
//
// One of Modulus and ModulusRaw must always be non-nil. Modulus takes
// precedence. ModulusRaw is used for key templates where the field named
// "unique" must be a byte array of all zeroes.
type RSAParams struct {
Symmetric *SymScheme
Sign *SigScheme
KeyBits uint16
// The default Exponent (65537) has two representations; the
// 0 value, and the value 65537.
// If encodeDefaultExponentAsZero is set, an exponent of 65537
// will be encoded as zero. This is necessary to produce an identical
// encoded bitstream, so Name digest calculations will be correct.
encodeDefaultExponentAsZero bool
Exponent uint32
ModulusRaw []byte
Modulus *big.Int
}
// SymScheme represents a symmetric encryption scheme.
type SymScheme struct {
Alg Algorithm
KeyBits uint16
Mode Algorithm
} // SigScheme represents a signing scheme.
type SigScheme struct {
Alg Algorithm
Hash Algorithm
Count uint32
}
func decodeSigScheme(in *bytes.Buffer) (*SigScheme, error) {
var scheme SigScheme
if err := UnpackBuf(in, &scheme.Alg); err != nil {
return nil, fmt.Errorf("decoding Alg: %v", err)
}
if scheme.Alg == AlgNull {
return nil, nil
}
if err := UnpackBuf(in, &scheme.Hash); err != nil {
return nil, fmt.Errorf("decoding Hash: %v", err)
}
if scheme.Alg.UsesCount() {
if err := UnpackBuf(in, &scheme.Count); err != nil {
return nil, fmt.Errorf("decoding Count: %v", err)
}
}
return &scheme, nil
}
// UsesCount returns true if a signature algorithm uses count value.
func (a Algorithm) UsesCount() bool {
return a == AlgECDAA
}
func decodeKDFScheme(in *bytes.Buffer) (*KDFScheme, error) {
var scheme KDFScheme
if err := UnpackBuf(in, &scheme.Alg); err != nil {
return nil, fmt.Errorf("decoding Alg: %v", err)
}
if scheme.Alg == AlgNull {
return nil, nil
}
if err := UnpackBuf(in, &scheme.Hash); err != nil {
return nil, fmt.Errorf("decoding Hash: %v", err)
}
return &scheme, nil
}
func decodeSymScheme(in *bytes.Buffer) (*SymScheme, error) {
var scheme SymScheme
if err := UnpackBuf(in, &scheme.Alg); err != nil {
return nil, fmt.Errorf("decoding Alg: %v", err)
}
if scheme.Alg == AlgNull {
return nil, nil
}
if err := UnpackBuf(in, &scheme.KeyBits, &scheme.Mode); err != nil {
return nil, fmt.Errorf("decoding KeyBits, Mode: %v", err)
}
return &scheme, nil
}
func decodeECCParams(in *bytes.Buffer) (*ECCParams, error) {
var params ECCParams
var err error
if params.Symmetric, err = decodeSymScheme(in); err != nil {
return nil, fmt.Errorf("decoding Symmetric: %v", err)
}
if params.Sign, err = decodeSigScheme(in); err != nil {
return nil, fmt.Errorf("decoding Sign: %v", err)
}
if err := UnpackBuf(in, ¶ms.CurveID); err != nil {
return nil, fmt.Errorf("decoding CurveID: %v", err)
}
if params.KDF, err = decodeKDFScheme(in); err != nil {
return nil, fmt.Errorf("decoding KDF: %v", err)
}
var x, y []byte
if err := UnpackBuf(in, &x, &y); err != nil {
return nil, fmt.Errorf("decoding Point: %v", err)
}
params.Point.X = new(big.Int).SetBytes(x)
params.Point.Y = new(big.Int).SetBytes(y)
return ¶ms, nil
}
// ECCParams represents parameters of an ECC key pair.
//
// Symmetric, Sign and KDF may be nil, depending on key Attributes in Public.
type ECCParams struct {
Symmetric *SymScheme
Sign *SigScheme
CurveID EllipticCurve
KDF *KDFScheme
Point ECPoint
}
// EllipticCurve identifies specific EC curves.
type EllipticCurve uint16
// ECC curves supported by TPM 2.0 spec.
const (
CurveNISTP192 = EllipticCurve(iota + 1)
CurveNISTP224
CurveNISTP256
CurveNISTP384
CurveNISTP521
CurveBNP256 = EllipticCurve(iota + 10)
CurveBNP638
CurveSM2P256 = EllipticCurve(0x0020)
)
// ECPoint represents a ECC coordinates for a point.
type ECPoint struct {
X, Y *big.Int
}
// KDFScheme represents a KDF (Key Derivation Function) scheme.
type KDFScheme struct {
Alg Algorithm
Hash Algorithm
}