attestation: use go-sev-guest library (#2269)

* wip: switch to  attestation

* add extra comments

Signed-off-by: Moritz Sanft <58110325+msanft@users.noreply.github.com>

* MAA checks

Signed-off-by: Moritz Sanft <58110325+msanft@users.noreply.github.com>

* use provided functions to parse report / cert chain

Signed-off-by: Moritz Sanft <58110325+msanft@users.noreply.github.com>

* replace `CommitedTCB` check with `LaunchTCB` check

Signed-off-by: Moritz Sanft <58110325+msanft@users.noreply.github.com>

* remove debug check

Signed-off-by: Moritz Sanft <58110325+msanft@users.noreply.github.com>

* remove `LaunchTCB` == `CommitedTCB` check

Signed-off-by: Moritz Sanft <58110325+msanft@users.noreply.github.com>

* custom IdKeyDigests check

Signed-off-by: Moritz Sanft <58110325+msanft@users.noreply.github.com>

* basic test of report parsing from instance info

Signed-off-by: Moritz Sanft <58110325+msanft@users.noreply.github.com>

* retrieve VCEK from AMD KDS

Signed-off-by: Moritz Sanft <58110325+msanft@users.noreply.github.com>

* remove VCEK from `azureInstanceInfo`

Signed-off-by: Moritz Sanft <58110325+msanft@users.noreply.github.com>

* use `go-sev-guest` TCB version type

Signed-off-by: Moritz Sanft <58110325+msanft@users.noreply.github.com>

* fix validation parsing test

Signed-off-by: Moritz Sanft <58110325+msanft@users.noreply.github.com>

* fix error message

* fix comment

Signed-off-by: Moritz Sanft <58110325+msanft@users.noreply.github.com>

* remove certificate chain from `instanceInfo`

Signed-off-by: Moritz Sanft <58110325+msanft@users.noreply.github.com>

* add test for idkeydigest check

Signed-off-by: Moritz Sanft <58110325+msanft@users.noreply.github.com>

* update buildfiles

Signed-off-by: Moritz Sanft <58110325+msanft@users.noreply.github.com>

* wip: update tests

Signed-off-by: Moritz Sanft <58110325+msanft@users.noreply.github.com>

* update buildfiles

Signed-off-by: Moritz Sanft <58110325+msanft@users.noreply.github.com>

* [remove] debug prints

Signed-off-by: Moritz Sanft <58110325+msanft@users.noreply.github.com>

* wip: fix tests

Signed-off-by: Moritz Sanft <58110325+msanft@users.noreply.github.com>

* wip: fix tests

Signed-off-by: Moritz Sanft <58110325+msanft@users.noreply.github.com>

* fix tests, do some clean-up

Signed-off-by: Moritz Sanft <58110325+msanft@users.noreply.github.com>

* add test case for fetching error

Signed-off-by: Moritz Sanft <58110325+msanft@users.noreply.github.com>

* Update internal/attestation/azure/snp/validator.go

Co-authored-by: Daniel Weiße <66256922+daniel-weisse@users.noreply.github.com>

* correct `hack` dependency

Signed-off-by: Moritz Sanft <58110325+msanft@users.noreply.github.com>

* fix id key check

Signed-off-by: Moritz Sanft <58110325+msanft@users.noreply.github.com>

* [remove] comment out wip unit tests

Signed-off-by: Moritz Sanft <58110325+msanft@users.noreply.github.com>

* add missing newline

Signed-off-by: Moritz Sanft <58110325+msanft@users.noreply.github.com>

* switch to released version of `go-sev-guest`

Signed-off-by: Moritz Sanft <58110325+msanft@users.noreply.github.com>

* add constructor test

Signed-off-by: Moritz Sanft <58110325+msanft@users.noreply.github.com>

* add VMPL check

Signed-off-by: Moritz Sanft <58110325+msanft@users.noreply.github.com>

* add test assertions

Signed-off-by: Moritz Sanft <58110325+msanft@users.noreply.github.com>

* update buildfiles

Signed-off-by: Moritz Sanft <58110325+msanft@users.noreply.github.com>

* switch to pseudoversion

Signed-off-by: Moritz Sanft <58110325+msanft@users.noreply.github.com>

* use fork with windows fix

Signed-off-by: Moritz Sanft <58110325+msanft@users.noreply.github.com>

* fix linter checks

Signed-off-by: Moritz Sanft <58110325+msanft@users.noreply.github.com>

* use data from THIM

Signed-off-by: Moritz Sanft <58110325+msanft@users.noreply.github.com>

* update embeds

Signed-off-by: Moritz Sanft <58110325+msanft@users.noreply.github.com>

* verify against ARK in config

Signed-off-by: Moritz Sanft <58110325+msanft@users.noreply.github.com>

* invalid ASK

Signed-off-by: Moritz Sanft <58110325+msanft@users.noreply.github.com>

* Update internal/attestation/azure/snp/validator.go

Co-authored-by: Thomas Tendyck <51411342+thomasten@users.noreply.github.com>

* Update internal/attestation/azure/snp/validator.go

Co-authored-by: Thomas Tendyck <51411342+thomasten@users.noreply.github.com>

* Update internal/attestation/azure/snp/validator.go

Co-authored-by: 3u13r <lc@edgeless.systems>

* Update internal/attestation/azure/snp/validator.go

Co-authored-by: 3u13r <lc@edgeless.systems>

* nits

Signed-off-by: Moritz Sanft <58110325+msanft@users.noreply.github.com>

* remove unnecessary checks

Signed-off-by: Moritz Sanft <58110325+msanft@users.noreply.github.com>

* refactoring

Signed-off-by: Moritz Sanft <58110325+msanft@users.noreply.github.com>

* Update internal/attestation/azure/snp/validator.go

Co-authored-by: Thomas Tendyck <51411342+thomasten@users.noreply.github.com>

* Update internal/attestation/azure/snp/validator.go

Co-authored-by: Thomas Tendyck <51411342+thomasten@users.noreply.github.com>

* Update internal/attestation/azure/snp/validator.go

Co-authored-by: Thomas Tendyck <51411342+thomasten@users.noreply.github.com>

* use upstream library with pseudoversion

Signed-off-by: Moritz Sanft <58110325+msanft@users.noreply.github.com>

* Update internal/attestation/azure/snp/validator.go

Co-authored-by: Paul Meyer <49727155+katexochen@users.noreply.github.com>

* Update internal/attestation/azure/snp/validator.go

Co-authored-by: Paul Meyer <49727155+katexochen@users.noreply.github.com>

* Update internal/attestation/azure/snp/validator.go

Co-authored-by: Paul Meyer <49727155+katexochen@users.noreply.github.com>

* simplify control flow

Signed-off-by: Moritz Sanft <58110325+msanft@users.noreply.github.com>

* fix return error

Signed-off-by: Moritz Sanft <58110325+msanft@users.noreply.github.com>

* fix VCEK test

Signed-off-by: Moritz Sanft <58110325+msanft@users.noreply.github.com>

* tidy

Signed-off-by: Moritz Sanft <58110325+msanft@users.noreply.github.com>

* revert unintentional changes

Signed-off-by: Moritz Sanft <58110325+msanft@users.noreply.github.com>

* use new upstream release

Signed-off-by: Moritz Sanft <58110325+msanft@users.noreply.github.com>

* fix removed AuthorKeyEn field

Signed-off-by: Moritz Sanft <58110325+msanft@users.noreply.github.com>

* fix verification report printing

Signed-off-by: Moritz Sanft <58110325+msanft@users.noreply.github.com>

---------

Signed-off-by: Moritz Sanft <58110325+msanft@users.noreply.github.com>
Co-authored-by: Daniel Weiße <66256922+daniel-weisse@users.noreply.github.com>
Co-authored-by: Thomas Tendyck <51411342+thomasten@users.noreply.github.com>
Co-authored-by: 3u13r <lc@edgeless.systems>
Co-authored-by: Paul Meyer <49727155+katexochen@users.noreply.github.com>
This commit is contained in:
Moritz Sanft 2023-09-21 14:08:00 +02:00 committed by GitHub
parent 8f549f0622
commit 3ed001fa8a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 1371 additions and 624 deletions

View File

@ -2456,8 +2456,8 @@ def go_dependencies():
build_file_generation = "on",
build_file_proto_mode = "disable_global",
importpath = "github.com/google/go-sev-guest",
sum = "h1:NajHkAaLqN9/aW7bCFSUplUMtDgk2+HcN7jC2btFtk0=",
version = "v0.6.1",
sum = "h1:IIZIqdcMJXgTm1nMvId442OUpYebbWDWa9bi9/lUUwc=",
version = "v0.8.0",
)
go_repository(
name = "com_github_google_go_tpm",
@ -2595,8 +2595,8 @@ def go_dependencies():
build_file_generation = "on",
build_file_proto_mode = "disable_global",
importpath = "github.com/google/uuid",
sum = "h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=",
version = "v1.3.0",
sum = "h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4=",
version = "v1.3.1",
)
go_repository(
name = "com_github_google_wire",
@ -7324,8 +7324,8 @@ def go_dependencies():
build_file_generation = "on",
build_file_proto_mode = "disable_global",
importpath = "golang.org/x/crypto",
sum = "h1:tFM/ta59kqch6LlvYnPa0yx5a83cL2nHflFhYKvv9Yk=",
version = "v0.12.0",
sum = "h1:mvySKfSWJ+UKUii46M40LOvyWfN0s2U+46/jDd0e6Ck=",
version = "v0.13.0",
)
go_repository(
name = "org_golang_x_exp",
@ -7397,24 +7397,24 @@ def go_dependencies():
build_file_generation = "on",
build_file_proto_mode = "disable_global",
importpath = "golang.org/x/sys",
sum = "h1:eG7RXZHdqOJ1i+0lgLgCpSXAp6M3LYlAo6osgSi0xOM=",
version = "v0.11.0",
sum = "h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o=",
version = "v0.12.0",
)
go_repository(
name = "org_golang_x_term",
build_file_generation = "on",
build_file_proto_mode = "disable_global",
importpath = "golang.org/x/term",
sum = "h1:F9tnn/DA/Im8nCwm+fX+1/eBwi4qFjRT++MhtVC4ZX0=",
version = "v0.11.0",
sum = "h1:/ZfYdc3zq+q02Rv9vGqTeSItdzZTSNDmfTi0mBAuidU=",
version = "v0.12.0",
)
go_repository(
name = "org_golang_x_text",
build_file_generation = "on",
build_file_proto_mode = "disable_global",
importpath = "golang.org/x/text",
sum = "h1:k+n5B8goJNdU7hSvEtMUz3d1Q6D/XW4COJSJR6fN0mc=",
version = "v0.12.0",
sum = "h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k=",
version = "v0.13.0",
)
go_repository(
name = "org_golang_x_time",

View File

@ -428,6 +428,11 @@ func (f *attestationDocFormatterImpl) parseSNPReport(b *strings.Builder, reportB
return fmt.Errorf("parsing signature: %w", err)
}
signerInfo, err := abi.ParseSignerInfo(report.SignerInfo)
if err != nil {
return fmt.Errorf("parsing signer info: %w", err)
}
writeTCB := func(tcbVersion uint64) {
tcb := kds.DecomposeTCBVersion(kds.TCBVersion(tcbVersion))
writeIndentfln(b, 3, "Secure Processor bootloader SVN: %d", tcb.BlSpl)
@ -459,7 +464,10 @@ func (f *attestationDocFormatterImpl) parseSNPReport(b *strings.Builder, reportB
writeIndentfln(b, 2, "Platform Info:")
writeIndentfln(b, 3, "Symmetric Multithreading enabled (SMT): %t", platformInfo.SMTEnabled)
writeIndentfln(b, 3, "Transparent secure memory encryption (TSME): %t", platformInfo.TSMEEnabled)
writeIndentfln(b, 2, "Author Key ID: %x", report.AuthorKeyEn)
writeIndentfln(b, 2, "Signer Info:")
writeIndentfln(b, 3, "Author Key Enabled: %t", signerInfo.AuthorKeyEn)
writeIndentfln(b, 3, "Chip ID Masking: %t", signerInfo.MaskChipKey)
writeIndentfln(b, 3, "Signing Type: %s", signerInfo.SigningKey)
writeIndentfln(b, 2, "Report Data: %x", report.ReportData)
writeIndentfln(b, 2, "Measurement: %x", report.Measurement)
writeIndentfln(b, 2, "Host Data: %x", report.HostData)

12
go.mod
View File

@ -77,10 +77,10 @@ require (
github.com/go-playground/universal-translator v0.18.1
github.com/go-playground/validator/v10 v10.14.1
github.com/golang-jwt/jwt/v5 v5.0.0
github.com/google/go-sev-guest v0.6.1
github.com/google/go-sev-guest v0.8.0
github.com/google/go-tpm v0.9.0
github.com/google/go-tpm-tools v0.4.0
github.com/google/uuid v1.3.0
github.com/google/uuid v1.3.1
github.com/googleapis/gax-go/v2 v2.12.0
github.com/gophercloud/gophercloud v1.5.0
github.com/gophercloud/utils v0.0.0-20230523080330-de873b9cf00d
@ -109,9 +109,9 @@ require (
github.com/theupdateframework/go-tuf v0.5.2
go.uber.org/goleak v1.2.1
go.uber.org/zap v1.24.0
golang.org/x/crypto v0.12.0
golang.org/x/crypto v0.13.0
golang.org/x/mod v0.12.0
golang.org/x/sys v0.11.0
golang.org/x/sys v0.12.0
golang.org/x/tools v0.10.0
google.golang.org/api v0.130.0
google.golang.org/grpc v1.56.2
@ -321,8 +321,8 @@ require (
golang.org/x/net v0.14.0 // indirect
golang.org/x/oauth2 v0.9.0 // indirect
golang.org/x/sync v0.3.0 // indirect
golang.org/x/term v0.11.0 // indirect
golang.org/x/text v0.12.0 // indirect
golang.org/x/term v0.12.0 // indirect
golang.org/x/text v0.13.0 // indirect
golang.org/x/time v0.3.0 // indirect
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect
google.golang.org/appengine v1.6.7 // indirect

23
go.sum
View File

@ -535,8 +535,8 @@ github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-containerregistry v0.15.2 h1:MMkSh+tjSdnmJZO7ljvEqV1DjfekB6VUEAZgy3a+TQE=
github.com/google/go-containerregistry v0.15.2/go.mod h1:wWK+LnOv4jXMM23IT/F1wdYftGWGr47Is8CG+pmHK1Q=
github.com/google/go-sev-guest v0.6.1 h1:NajHkAaLqN9/aW7bCFSUplUMtDgk2+HcN7jC2btFtk0=
github.com/google/go-sev-guest v0.6.1/go.mod h1:UEi9uwoPbLdKGl1QHaq1G8pfCbQ4QP0swWX4J0k6r+Q=
github.com/google/go-sev-guest v0.8.0 h1:IIZIqdcMJXgTm1nMvId442OUpYebbWDWa9bi9/lUUwc=
github.com/google/go-sev-guest v0.8.0/go.mod h1:hc1R4R6f8+NcJwITs0L90fYWTsBpd1Ix+Gur15sqHDs=
github.com/google/go-tpm-tools v0.4.0 h1:bYRZAUvQEmn11WTKCkTLRCCv4aTlOBgBBeqCK0ABT2A=
github.com/google/go-tpm-tools v0.4.0/go.mod h1:G7PFUk8KKQzdYYGv/cpV9LB9sPT7czAAomnceugzNKQ=
github.com/google/go-tspi v0.3.0 h1:ADtq8RKfP+jrTyIWIZDIYcKOMecRqNJFOew2IT0Inus=
@ -573,8 +573,9 @@ github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4=
github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/enterprise-certificate-proxy v0.2.5 h1:UR4rDjcgpgEnqpIEvkiqTYKBCKLNmlge2eVjoZfySzM=
github.com/googleapis/enterprise-certificate-proxy v0.2.5/go.mod h1:RxW0N9901Cko1VOCW3SXCpWP+mlIEkk2tP7jnHy9a3w=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
@ -1112,8 +1113,8 @@ golang.org/x/crypto v0.0.0-20220829220503-c86fa9a7ed90/go.mod h1:IxCIyHEi3zRg3s0
golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
golang.org/x/crypto v0.5.0/go.mod h1:NK/OQwhpMQP3MwtdjgLlYHnH9ebylxKWv3e0fK+mkQU=
golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58=
golang.org/x/crypto v0.12.0 h1:tFM/ta59kqch6LlvYnPa0yx5a83cL2nHflFhYKvv9Yk=
golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw=
golang.org/x/crypto v0.13.0 h1:mvySKfSWJ+UKUii46M40LOvyWfN0s2U+46/jDd0e6Ck=
golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
@ -1313,8 +1314,8 @@ golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.11.0 h1:eG7RXZHdqOJ1i+0lgLgCpSXAp6M3LYlAo6osgSi0xOM=
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o=
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
@ -1322,8 +1323,8 @@ golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U=
golang.org/x/term v0.11.0 h1:F9tnn/DA/Im8nCwm+fX+1/eBwi4qFjRT++MhtVC4ZX0=
golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU=
golang.org/x/term v0.12.0 h1:/ZfYdc3zq+q02Rv9vGqTeSItdzZTSNDmfTi0mBAuidU=
golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@ -1337,8 +1338,8 @@ golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.12.0 h1:k+n5B8goJNdU7hSvEtMUz3d1Q6D/XW4COJSJR6fN0mc=
golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k=
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=

View File

@ -168,7 +168,7 @@ require (
github.com/google/go-attestation v0.5.0 // indirect
github.com/google/go-cmp v0.5.9 // indirect
github.com/google/go-containerregistry v0.15.2 // indirect
github.com/google/go-sev-guest v0.6.1 // indirect
github.com/google/go-sev-guest v0.8.0 // indirect
github.com/google/go-tpm v0.9.0 // indirect
github.com/google/go-tpm-tools v0.4.0 // indirect
github.com/google/go-tspi v0.3.0 // indirect
@ -176,7 +176,7 @@ require (
github.com/google/logger v1.1.1 // indirect
github.com/google/s2a-go v0.1.4 // indirect
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
github.com/google/uuid v1.3.0 // indirect
github.com/google/uuid v1.3.1 // indirect
github.com/googleapis/enterprise-certificate-proxy v0.2.5 // indirect
github.com/googleapis/gax-go/v2 v2.12.0 // indirect
github.com/gophercloud/gophercloud v1.5.0 // indirect
@ -280,13 +280,13 @@ require (
go.starlark.net v0.0.0-20220223235035-243c74974e97 // indirect
go.uber.org/atomic v1.11.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
golang.org/x/crypto v0.12.0 // indirect
golang.org/x/crypto v0.13.0 // indirect
golang.org/x/net v0.14.0 // indirect
golang.org/x/oauth2 v0.9.0 // indirect
golang.org/x/sync v0.3.0 // indirect
golang.org/x/sys v0.11.0 // indirect
golang.org/x/term v0.11.0 // indirect
golang.org/x/text v0.12.0 // indirect
golang.org/x/sys v0.12.0 // indirect
golang.org/x/term v0.12.0 // indirect
golang.org/x/text v0.13.0 // indirect
golang.org/x/time v0.3.0 // indirect
golang.org/x/tools v0.10.0 // indirect
google.golang.org/api v0.130.0 // indirect

View File

@ -496,8 +496,8 @@ github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-containerregistry v0.15.2 h1:MMkSh+tjSdnmJZO7ljvEqV1DjfekB6VUEAZgy3a+TQE=
github.com/google/go-containerregistry v0.15.2/go.mod h1:wWK+LnOv4jXMM23IT/F1wdYftGWGr47Is8CG+pmHK1Q=
github.com/google/go-sev-guest v0.6.1 h1:NajHkAaLqN9/aW7bCFSUplUMtDgk2+HcN7jC2btFtk0=
github.com/google/go-sev-guest v0.6.1/go.mod h1:UEi9uwoPbLdKGl1QHaq1G8pfCbQ4QP0swWX4J0k6r+Q=
github.com/google/go-sev-guest v0.8.0 h1:IIZIqdcMJXgTm1nMvId442OUpYebbWDWa9bi9/lUUwc=
github.com/google/go-sev-guest v0.8.0/go.mod h1:hc1R4R6f8+NcJwITs0L90fYWTsBpd1Ix+Gur15sqHDs=
github.com/google/go-tpm v0.9.0 h1:sQF6YqWMi+SCXpsmS3fd21oPy/vSddwZry4JnmltHVk=
github.com/google/go-tpm v0.9.0/go.mod h1:FkNVkc6C+IsvDI9Jw1OveJmxGZUUaKxtrpOS47QWKfU=
github.com/google/go-tpm-tools v0.4.0 h1:bYRZAUvQEmn11WTKCkTLRCCv4aTlOBgBBeqCK0ABT2A=
@ -533,8 +533,9 @@ github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4=
github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/enterprise-certificate-proxy v0.2.5 h1:UR4rDjcgpgEnqpIEvkiqTYKBCKLNmlge2eVjoZfySzM=
github.com/googleapis/enterprise-certificate-proxy v0.2.5/go.mod h1:RxW0N9901Cko1VOCW3SXCpWP+mlIEkk2tP7jnHy9a3w=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
@ -1068,8 +1069,8 @@ golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4
golang.org/x/crypto v0.5.0/go.mod h1:NK/OQwhpMQP3MwtdjgLlYHnH9ebylxKWv3e0fK+mkQU=
golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58=
golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
golang.org/x/crypto v0.12.0 h1:tFM/ta59kqch6LlvYnPa0yx5a83cL2nHflFhYKvv9Yk=
golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw=
golang.org/x/crypto v0.13.0 h1:mvySKfSWJ+UKUii46M40LOvyWfN0s2U+46/jDd0e6Ck=
golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
@ -1269,16 +1270,16 @@ golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.11.0 h1:eG7RXZHdqOJ1i+0lgLgCpSXAp6M3LYlAo6osgSi0xOM=
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o=
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U=
golang.org/x/term v0.11.0 h1:F9tnn/DA/Im8nCwm+fX+1/eBwi4qFjRT++MhtVC4ZX0=
golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU=
golang.org/x/term v0.12.0 h1:/ZfYdc3zq+q02Rv9vGqTeSItdzZTSNDmfTi0mBAuidU=
golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@ -1293,8 +1294,8 @@ golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.12.0 h1:k+n5B8goJNdU7hSvEtMUz3d1Q6D/XW4COJSJR6fN0mc=
golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k=
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=

View File

@ -4,7 +4,6 @@ load("//bazel/go:go_test.bzl", "go_test")
go_library(
name = "snp",
srcs = [
"errors.go",
"imds.go",
"issuer.go",
"maa.go",
@ -20,8 +19,13 @@ go_library(
"//internal/attestation/vtpm",
"//internal/cloud/azure",
"//internal/config",
"//internal/crypto",
"@com_github_edgelesssys_go_azguestattestation//maa",
"@com_github_google_go_sev_guest//abi",
"@com_github_google_go_sev_guest//kds",
"@com_github_google_go_sev_guest//proto/sevsnp",
"@com_github_google_go_sev_guest//validate",
"@com_github_google_go_sev_guest//verify",
"@com_github_google_go_sev_guest//verify/trust",
"@com_github_google_go_tpm//legacy/tpm2",
"@com_github_google_go_tpm_tools//client",
"@com_github_google_go_tpm_tools//proto/attest",
@ -42,12 +46,19 @@ go_test(
"//conditions:default": ["disable_tpm_simulator"],
}),
deps = [
"//internal/attestation",
"//internal/attestation/azure/snp/testdata",
"//internal/attestation/idkeydigest",
"//internal/attestation/simulator",
"//internal/attestation/vtpm",
"//internal/config",
"//internal/logger",
"@com_github_edgelesssys_go_azguestattestation//maa",
"@com_github_google_go_sev_guest//abi",
"@com_github_google_go_sev_guest//kds",
"@com_github_google_go_sev_guest//proto/sevsnp",
"@com_github_google_go_sev_guest//validate",
"@com_github_google_go_sev_guest//verify",
"@com_github_google_go_tpm//legacy/tpm2",
"@com_github_google_go_tpm_tools//client",
"@com_github_google_go_tpm_tools//proto/attest",

View File

@ -1,76 +0,0 @@
/*
Copyright (c) Edgeless Systems GmbH
SPDX-License-Identifier: AGPL-3.0-only
*/
package snp
import (
"errors"
"fmt"
)
type signatureError struct {
innerError error
}
func (e *signatureError) Unwrap() error {
return e.innerError
}
func (e *signatureError) Error() string {
return fmt.Sprintf("signature validation failed: %v", e.innerError)
}
type askError struct {
innerError error
}
func (e *askError) Unwrap() error {
return e.innerError
}
func (e *askError) Error() string {
return fmt.Sprintf("validating ASK: %v", e.innerError)
}
type vcekError struct {
innerError error
}
func (e *vcekError) Unwrap() error {
return e.innerError
}
func (e *vcekError) Error() string {
return fmt.Sprintf("validating VCEK: %v", e.innerError)
}
type idKeyError struct {
encounteredValue []byte
expectedValues [][]byte
}
func (e *idKeyError) Unwrap() error {
return nil
}
func (e *idKeyError) Error() string {
return fmt.Sprintf("accepted idkeydigest list %x doesn't contain reported idkeydigest %x", e.expectedValues, e.encounteredValue)
}
type versionError struct {
expectedType string
excpectedVersion tcbVersion
}
func (e *versionError) Unwrap() error {
return nil
}
func (e *versionError) Error() string {
return fmt.Sprintf("invalid %s version: %x", e.expectedType, e.excpectedVersion)
}
var errDebugEnabled = errors.New("SNP report indicates debugging, expected no debugging")

View File

@ -66,7 +66,7 @@ func (i *Issuer) getInstanceInfo(ctx context.Context, tpm io.ReadWriteCloser, us
}
instanceInfo := azureInstanceInfo{
Vcek: params.VcekCert,
VCEK: params.VcekCert,
CertChain: params.VcekChain,
AttestationReport: params.SNPReport,
RuntimeData: params.RuntimeData,

View File

@ -103,7 +103,7 @@ func TestGetSNPAttestation(t *testing.T) {
err = json.Unmarshal(attestationJSON, &instanceInfo)
require.NoError(err)
assert.Equal(params.VcekCert, instanceInfo.Vcek)
assert.Equal(params.VcekCert, instanceInfo.VCEK)
assert.Equal(params.VcekChain, instanceInfo.CertChain)
assert.Equal(params.SNPReport, instanceInfo.AttestationReport)
assert.Equal(params.RuntimeData, instanceInfo.RuntimeData)

View File

@ -0,0 +1,15 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "testdata",
srcs = ["testdata.go"],
embedsrcs = [
"attestation.bin",
"vcek.cert",
"certchain.pem",
"runtimedata.bin",
"vcek.pem",
],
importpath = "github.com/edgelesssys/constellation/v2/internal/attestation/azure/snp/testdata",
visibility = ["//:__subpackages__"],
)

Binary file not shown.

View File

@ -0,0 +1,74 @@
-----BEGIN CERTIFICATE-----
MIIGiTCCBDigAwIBAgIDAQABMEYGCSqGSIb3DQEBCjA5oA8wDQYJYIZIAWUDBAIC
BQChHDAaBgkqhkiG9w0BAQgwDQYJYIZIAWUDBAICBQCiAwIBMKMDAgEBMHsxFDAS
BgNVBAsMC0VuZ2luZWVyaW5nMQswCQYDVQQGEwJVUzEUMBIGA1UEBwwLU2FudGEg
Q2xhcmExCzAJBgNVBAgMAkNBMR8wHQYDVQQKDBZBZHZhbmNlZCBNaWNybyBEZXZp
Y2VzMRIwEAYDVQQDDAlBUkstTWlsYW4wHhcNMjAxMDIyMTgyNDIwWhcNNDUxMDIy
MTgyNDIwWjB7MRQwEgYDVQQLDAtFbmdpbmVlcmluZzELMAkGA1UEBhMCVVMxFDAS
BgNVBAcMC1NhbnRhIENsYXJhMQswCQYDVQQIDAJDQTEfMB0GA1UECgwWQWR2YW5j
ZWQgTWljcm8gRGV2aWNlczESMBAGA1UEAwwJU0VWLU1pbGFuMIICIjANBgkqhkiG
9w0BAQEFAAOCAg8AMIICCgKCAgEAnU2drrNTfbhNQIllf+W2y+ROCbSzId1aKZft
2T9zjZQOzjGccl17i1mIKWl7NTcB0VYXt3JxZSzOZjsjLNVAEN2MGj9TiedL+Qew
KZX0JmQEuYjm+WKksLtxgdLp9E7EZNwNDqV1r0qRP5tB8OWkyQbIdLeu4aCz7j/S
l1FkBytev9sbFGzt7cwnjzi9m7noqsk+uRVBp3+In35QPdcj8YflEmnHBNvuUDJh
LCJMW8KOjP6++Phbs3iCitJcANEtW4qTNFoKW3CHlbcSCjTM8KsNbUx3A8ek5EVL
jZWH1pt9E3TfpR6XyfQKnY6kl5aEIPwdW3eFYaqCFPrIo9pQT6WuDSP4JCYJbZne
KKIbZjzXkJt3NQG32EukYImBb9SCkm9+fS5LZFg9ojzubMX3+NkBoSXI7OPvnHMx
jup9mw5se6QUV7GqpCA2TNypolmuQ+cAaxV7JqHE8dl9pWf+Y3arb+9iiFCwFt4l
AlJw5D0CTRTC1Y5YWFDBCrA/vGnmTnqG8C+jjUAS7cjjR8q4OPhyDmJRPnaC/ZG5
uP0K0z6GoO/3uen9wqshCuHegLTpOeHEJRKrQFr4PVIwVOB0+ebO5FgoyOw43nyF
D5UKBDxEB4BKo/0uAiKHLRvvgLbORbU8KARIs1EoqEjmF8UtrmQWV2hUjwzqwvHF
ei8rPxMCAwEAAaOBozCBoDAdBgNVHQ4EFgQUO8ZuGCrD/T1iZEib47dHLLT8v/gw
HwYDVR0jBBgwFoAUhawa0UP3yKxV1MUdQUir1XhK1FMwEgYDVR0TAQH/BAgwBgEB
/wIBADAOBgNVHQ8BAf8EBAMCAQQwOgYDVR0fBDMwMTAvoC2gK4YpaHR0cHM6Ly9r
ZHNpbnRmLmFtZC5jb20vdmNlay92MS9NaWxhbi9jcmwwRgYJKoZIhvcNAQEKMDmg
DzANBglghkgBZQMEAgIFAKEcMBoGCSqGSIb3DQEBCDANBglghkgBZQMEAgIFAKID
AgEwowMCAQEDggIBAIgeUQScAf3lDYqgWU1VtlDbmIN8S2dC5kmQzsZ/HtAjQnLE
PI1jh3gJbLxL6gf3K8jxctzOWnkYcbdfMOOr28KT35IaAR20rekKRFptTHhe+DFr
3AFzZLDD7cWK29/GpPitPJDKCvI7A4Ug06rk7J0zBe1fz/qe4i2/F12rvfwCGYhc
RxPy7QF3q8fR6GCJdB1UQ5SlwCjFxD4uezURztIlIAjMkt7DFvKRh+2zK+5plVGG
FsjDJtMz2ud9y0pvOE4j3dH5IW9jGxaSGStqNrabnnpF236ETr1/a43b8FFKL5QN
mt8Vr9xnXRpznqCRvqjr+kVrb6dlfuTlliXeQTMlBoRWFJORL8AcBJxGZ4K2mXft
l1jU5TLeh5KXL9NW7a/qAOIUs2FiOhqrtzAhJRg9Ij8QkQ9Pk+cKGzw6El3T3kFr
Eg6zkxmvMuabZOsdKfRkWfhH2ZKcTlDfmH1H0zq0Q2bG3uvaVdiCtFY1LlWyB38J
S2fNsR/Py6t5brEJCFNvzaDky6KeC4ion/cVgUai7zzS3bGQWzKDKU35SqNU2WkP
I8xCZ00WtIiKKFnXWUQxvlKmmgZBIYPe01zD0N8atFxmWiSnfJl690B9rJpNR/fI
ajxCW3Seiws6r1Zm+tCuVbMiNtpS9ThjNX4uve5thyfE2DgoxRFvY1CsoF5M
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIGYzCCBBKgAwIBAgIDAQAAMEYGCSqGSIb3DQEBCjA5oA8wDQYJYIZIAWUDBAIC
BQChHDAaBgkqhkiG9w0BAQgwDQYJYIZIAWUDBAICBQCiAwIBMKMDAgEBMHsxFDAS
BgNVBAsMC0VuZ2luZWVyaW5nMQswCQYDVQQGEwJVUzEUMBIGA1UEBwwLU2FudGEg
Q2xhcmExCzAJBgNVBAgMAkNBMR8wHQYDVQQKDBZBZHZhbmNlZCBNaWNybyBEZXZp
Y2VzMRIwEAYDVQQDDAlBUkstTWlsYW4wHhcNMjAxMDIyMTcyMzA1WhcNNDUxMDIy
MTcyMzA1WjB7MRQwEgYDVQQLDAtFbmdpbmVlcmluZzELMAkGA1UEBhMCVVMxFDAS
BgNVBAcMC1NhbnRhIENsYXJhMQswCQYDVQQIDAJDQTEfMB0GA1UECgwWQWR2YW5j
ZWQgTWljcm8gRGV2aWNlczESMBAGA1UEAwwJQVJLLU1pbGFuMIICIjANBgkqhkiG
9w0BAQEFAAOCAg8AMIICCgKCAgEA0Ld52RJOdeiJlqK2JdsVmD7FktuotWwX1fNg
W41XY9Xz1HEhSUmhLz9Cu9DHRlvgJSNxbeYYsnJfvyjx1MfU0V5tkKiU1EesNFta
1kTA0szNisdYc9isqk7mXT5+KfGRbfc4V/9zRIcE8jlHN61S1ju8X93+6dxDUrG2
SzxqJ4BhqyYmUDruPXJSX4vUc01P7j98MpqOS95rORdGHeI52Naz5m2B+O+vjsC0
60d37jY9LFeuOP4Meri8qgfi2S5kKqg/aF6aPtuAZQVR7u3KFYXP59XmJgtcog05
gmI0T/OitLhuzVvpZcLph0odh/1IPXqx3+MnjD97A7fXpqGd/y8KxX7jksTEzAOg
bKAeam3lm+3yKIcTYMlsRMXPcjNbIvmsBykD//xSniusuHBkgnlENEWx1UcbQQrs
+gVDkuVPhsnzIRNgYvM48Y+7LGiJYnrmE8xcrexekBxrva2V9TJQqnN3Q53kt5vi
Qi3+gCfmkwC0F0tirIZbLkXPrPwzZ0M9eNxhIySb2npJfgnqz55I0u33wh4r0ZNQ
eTGfw03MBUtyuzGesGkcw+loqMaq1qR4tjGbPYxCvpCq7+OgpCCoMNit2uLo9M18
fHz10lOMT8nWAUvRZFzteXCm+7PHdYPlmQwUw3LvenJ/ILXoQPHfbkH0CyPfhl1j
WhJFZasCAwEAAaN+MHwwDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBSFrBrRQ/fI
rFXUxR1BSKvVeErUUzAPBgNVHRMBAf8EBTADAQH/MDoGA1UdHwQzMDEwL6AtoCuG
KWh0dHBzOi8va2RzaW50Zi5hbWQuY29tL3ZjZWsvdjEvTWlsYW4vY3JsMEYGCSqG
SIb3DQEBCjA5oA8wDQYJYIZIAWUDBAICBQChHDAaBgkqhkiG9w0BAQgwDQYJYIZI
AWUDBAICBQCiAwIBMKMDAgEBA4ICAQC6m0kDp6zv4Ojfgy+zleehsx6ol0ocgVel
ETobpx+EuCsqVFRPK1jZ1sp/lyd9+0fQ0r66n7kagRk4Ca39g66WGTJMeJdqYriw
STjjDCKVPSesWXYPVAyDhmP5n2v+BYipZWhpvqpaiO+EGK5IBP+578QeW/sSokrK
dHaLAxG2LhZxj9aF73fqC7OAJZ5aPonw4RE299FVarh1Tx2eT3wSgkDgutCTB1Yq
zT5DuwvAe+co2CIVIzMDamYuSFjPN0BCgojl7V+bTou7dMsqIu/TW/rPCX9/EUcp
KGKqPQ3P+N9r1hjEFY1plBg93t53OOo49GNI+V1zvXPLI6xIFVsh+mto2RtgEX/e
pmMKTNN6psW88qg7c1hTWtN6MbRuQ0vm+O+/2tKBF2h8THb94OvvHHoFDpbCELlq
HnIYhxy0YKXGyaW1NjfULxrrmxVW4wcn5E8GddmvNa6yYm8scJagEi13mhGu4Jqh
3QU3sf8iUSUr09xQDwHtOQUVIqx4maBZPBtSMf+qUDtjXSSq8lfWcd8bLr9mdsUn
JZJ0+tuPMKmBnSH860llKk+VpVQsgqbzDIvOLvD6W1Umq25boxCYJ+TuBoa4s+HH
CViAvgT9kf/rBq1d+ivj6skkHxuzcxbk1xv6ZGxrteJxVH7KlX7YRdZ6eARKwLe4
AFZEAwoKCQ==
-----END CERTIFICATE-----

View File

@ -0,0 +1 @@
{"keys":[{"kid":"HCLAkPub","key_ops":["encrypt"],"kty":"RSA","e":"AQAB","n":"tyFqvAAAf2GFelkW7VcRhJnA2YvY6LjBzeUN2vaMZnZth_tFnWMkK5AXtusyCNel3uip3VGZzTaz5X2tGVjGrs-MVHcap9QdwqUXVW3g9OQ_tEbixcx7-xblUJQkGEQfnbbSdnPI2lvLzOs1Z_0vjeDAxvSQrmags6nY-cJAWH-pgDVJyHtpsUSs_QBWklazDso5WHmnMt9s9MuilWXox0RSyXnUeaQyhY1ju7RTScRnVXuNy67z_EJnwM92drwFb8AUd0SJ_9ohvEYl4aZRDECGo0VrjcSHU-JGJeuWC5VhDBR5EOoCVBBgqe9e83v_lJxI3WLe2ovSIZIIzAmbSQ"}],"vm-configuration":{"console-enabled":true,"current-time":1661455391,"secure-boot":false,"tpm-enabled":true,"vmUniqueId":"B6C98C3B-4EC7-4DA6-BD2F-7D98D20D7B75"}}

View File

@ -0,0 +1,35 @@
/*
Copyright (c) Edgeless Systems GmbH
SPDX-License-Identifier: AGPL-3.0-only
*/
// Package testdata contains testing data for an attestation process.
package testdata
import _ "embed"
// AttestationBytes is an example attestation report from a Constellation VM.
//
//go:embed attestation.bin
var AttestationReport []byte
// AzureThimVCEK is an example VCEK certificate (PEM, as returned from Azure THIM) for the AttestationReport.
//
//go:embed vcek.pem
var AzureThimVCEK []byte
// AmdKdsVCEK is an example VCEK certificate (DER, as returned from AMD KDS) for the AttestationReport.
//
//go:embed vcek.cert
var AmdKdsVCEK []byte
// RuntimeData is an example runtime data from the TPM for the AttestationReport.
//
//go:embed runtimedata.bin
var RuntimeData []byte
// CertChain is a valid certificate chain (PEM, as returned from Azure THIM) for the VCEK certificate.
//
//go:embed certchain.pem
var CertChain []byte

Binary file not shown.

View File

@ -0,0 +1,31 @@
-----BEGIN CERTIFICATE-----
MIIFTDCCAvugAwIBAgIBADBGBgkqhkiG9w0BAQowOaAPMA0GCWCGSAFlAwQCAgUA
oRwwGgYJKoZIhvcNAQEIMA0GCWCGSAFlAwQCAgUAogMCATCjAwIBATB7MRQwEgYD
VQQLDAtFbmdpbmVlcmluZzELMAkGA1UEBhMCVVMxFDASBgNVBAcMC1NhbnRhIENs
YXJhMQswCQYDVQQIDAJDQTEfMB0GA1UECgwWQWR2YW5jZWQgTWljcm8gRGV2aWNl
czESMBAGA1UEAwwJU0VWLU1pbGFuMB4XDTIzMDgzMDEyMTUyNFoXDTMwMDgzMDEy
MTUyNFowejEUMBIGA1UECwwLRW5naW5lZXJpbmcxCzAJBgNVBAYTAlVTMRQwEgYD
VQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExHzAdBgNVBAoMFkFkdmFuY2Vk
IE1pY3JvIERldmljZXMxETAPBgNVBAMMCFNFVi1WQ0VLMHYwEAYHKoZIzj0CAQYF
K4EEACIDYgAEhPX8Cl9uA7PxqNGzeqamJNYJLx/VFE/s3+8qOWtaztKNcn1PaAI4
ndE+yaVfMHsiA8CLTylumpWXcVBHPYV9kPEVrtozhvrrT5Oii9OpZPYHJ7/WPVmM
J3K8/Iz3AshTo4IBFjCCARIwEAYJKwYBBAGceAEBBAMCAQAwFwYJKwYBBAGceAEC
BAoWCE1pbGFuLUIwMBEGCisGAQQBnHgBAwEEAwIBAjARBgorBgEEAZx4AQMCBAMC
AQAwEQYKKwYBBAGceAEDBAQDAgEAMBEGCisGAQQBnHgBAwUEAwIBADARBgorBgEE
AZx4AQMGBAMCAQAwEQYKKwYBBAGceAEDBwQDAgEAMBEGCisGAQQBnHgBAwMEAwIB
BjARBgorBgEEAZx4AQMIBAMCAV0wTQYJKwYBBAGceAEEBECeRKrvAs/Kb926ymac
bP0p4auNl+vJOYVxKKy7E7h0DfMUNtNOhuX4rgzf6zoOGF20beysF2zHfXYcIqG5
3PJbMEYGCSqGSIb3DQEBCjA5oA8wDQYJYIZIAWUDBAICBQChHDAaBgkqhkiG9w0B
AQgwDQYJYIZIAWUDBAICBQCiAwIBMKMDAgEBA4ICAQBoVGgDdFV9gWPHaEOBrHzd
WVYyuuMBH340DDSXbCGlPR6rhgja0qALmkUPG50REQGvoPsikAskwqhzRG2XEDO2
b6+fRPIq3DjEbz/8V89IiYiOZI/ycFACi3EEVECAWbzjXSfiOio1NfbniXP6tWzW
D/8xpd/8N8166bHpgNgMl9pX4i0I9vaTl3qH+jBuSMZ5Q4heTHLB+v4V7q+H6SZo
7htqpaI3keLEhQL/pCP72udMPAzU+/5W/x/t/LD6SbQcQQoHbWDU6kgTDuXabDxl
A4JoEZfatr+/TO6jKQcGtqOLKT8JFGcigUlBi/TBVP+Xs8E4CWYGZZiTpYoLwNAu
yuKOP9VVFViSCqPvzpNs2G+e0zXg2w3te7oMw/l0bD8iQCAS8rR0+r+8pZL4e010
KLZ3yEfA0moXef66k5xyf4y37ZIP189wz6qJ+YXqOujDmeTomCU0SnZXlri6GhbF
19rp2z5/lsZG+W27CRxvzTB3hk+ukZr35vCqNq4Rs+c7/hYcYzzyZ4ysATwdglNF
WddfVw5Qunlu6Ngxr84ifz3HrnUx9bR5DzmFbztrb7IbkZhq7GjImwJULub1viyg
YFa7X3p8b1WllienSEfvbadobbS9HeuLUrWyh0kZjQnz+0Q1UB1/zlzokeQmAYCf
8H3kABPv6hqrFftRNbargQ==
-----END CERTIFICATE-----

View File

@ -12,20 +12,24 @@ import (
"crypto"
"crypto/sha256"
"crypto/x509"
"encoding/asn1"
"encoding/base64"
"encoding/binary"
"encoding/json"
"encoding/pem"
"errors"
"fmt"
"math/big"
"github.com/edgelesssys/constellation/v2/internal/attestation"
"github.com/edgelesssys/constellation/v2/internal/attestation/idkeydigest"
"github.com/edgelesssys/constellation/v2/internal/attestation/variant"
"github.com/edgelesssys/constellation/v2/internal/attestation/vtpm"
"github.com/edgelesssys/constellation/v2/internal/config"
internalCrypto "github.com/edgelesssys/constellation/v2/internal/crypto"
"github.com/google/go-sev-guest/abi"
"github.com/google/go-sev-guest/kds"
spb "github.com/google/go-sev-guest/proto/sevsnp"
"github.com/google/go-sev-guest/validate"
"github.com/google/go-sev-guest/verify"
"github.com/google/go-sev-guest/verify/trust"
"github.com/google/go-tpm-tools/proto/attest"
"github.com/google/go-tpm/legacy/tpm2"
)
@ -36,251 +40,359 @@ type Validator struct {
*vtpm.Validator
hclValidator hclAkValidator
maa maaValidator
getter trust.HTTPSGetter
attestationVerifier attestationVerifier
attestationValidator attestationValidator
config *config.AzureSEVSNP
log attestation.Logger
}
type attestationVerifier interface {
SNPAttestation(attestation *spb.Attestation, options *verify.Options) error
}
type attestationValidator interface {
SNPAttestation(attestation *spb.Attestation, options *validate.Options) error
}
type attestationVerifierImpl struct{}
// SNPAttestation verifies the report signature, the VCEK certificate, as well as the certificate chain of the attestation report.
func (attestationVerifierImpl) SNPAttestation(attestation *spb.Attestation, options *verify.Options) error {
return verify.SnpAttestation(attestation, options)
}
type attestationValidatorImpl struct{}
// SNPAttestation validates the attestation report against the given set of constraints.
func (attestationValidatorImpl) SNPAttestation(attestation *spb.Attestation, options *validate.Options) error {
return validate.SnpAttestation(attestation, options)
}
// NewValidator initializes a new Azure validator with the provided PCR values.
func NewValidator(cfg *config.AzureSEVSNP, log attestation.Logger) *Validator {
if log == nil {
log = nopAttestationLogger{}
}
v := &Validator{
hclValidator: &azureInstanceInfo{},
maa: newMAAClient(),
config: cfg,
log: log,
hclValidator: &azureInstanceInfo{},
maa: newMAAClient(),
config: cfg,
log: log,
getter: trust.DefaultHTTPSGetter(),
attestationVerifier: attestationVerifierImpl{},
attestationValidator: attestationValidatorImpl{},
}
v.Validator = vtpm.NewValidator(
cfg.Measurements,
v.getTrustedKey,
validateCVM,
// stub, since SEV-SNP attestation is already verified in trustedKeyFromSNP().
func(vtpm.AttestationDocument, *attest.MachineState) error {
return nil
},
log,
)
return v
}
// validateCVM is a stub, since SEV-SNP attestation is already verified in trustedKeyFromSNP().
func validateCVM(vtpm.AttestationDocument, *attest.MachineState) error {
return nil
}
func newSNPReportFromBytes(reportRaw []byte) (snpAttestationReport, error) {
var report snpAttestationReport
if err := binary.Read(bytes.NewReader(reportRaw), binary.LittleEndian, &report); err != nil {
return snpAttestationReport{}, fmt.Errorf("reading attestation report: %w", err)
}
return report, nil
}
func reverseEndian(b []byte) {
for i := 0; i < len(b)/2; i++ {
b[i], b[len(b)-i-1] = b[len(b)-i-1], b[i]
}
}
// getTrustedKey establishes trust in the given public key.
// It does so by verifying the SNP attestation statement in instanceInfo.
// It does so by verifying the SNP attestation document.
func (v *Validator) getTrustedKey(ctx context.Context, attDoc vtpm.AttestationDocument, extraData []byte) (crypto.PublicKey, error) {
// transform the instanceInfo received from Microsoft into a verifiable attestation report format.
var instanceInfo azureInstanceInfo
if err := json.Unmarshal(attDoc.InstanceInfo, &instanceInfo); err != nil {
return nil, fmt.Errorf("unmarshalling instanceInfoRaw: %w", err)
return nil, fmt.Errorf("unmarshalling instanceInfo: %w", err)
}
report, err := newSNPReportFromBytes(instanceInfo.AttestationReport)
att, err := instanceInfo.attestationWithCerts(v.log, v.getter)
if err != nil {
return nil, fmt.Errorf("parsing attestation report: %w", err)
}
vcek, err := v.validateVCEK(instanceInfo.Vcek, instanceInfo.CertChain)
// Verify the attestation report's certificates.
trustedArk := x509.Certificate(v.config.AMDRootKey) // ARK, specified in Constellation config.
ask, err := x509.ParseCertificate(att.CertificateChain.AskCert) // ASK, as reported from THIM / KDS.
if err != nil {
return nil, fmt.Errorf("validating VCEK: %w", err)
return nil, fmt.Errorf("parsing ASK certificate: %w", err)
}
if err := v.validateSNPReport(ctx, vcek, report, instanceInfo.MAAToken, extraData); err != nil {
return nil, fmt.Errorf("validating SNP report: %w", err)
verifyOpts := &verify.Options{
TrustedRoots: map[string][]*trust.AMDRootCerts{
"Milan": {
{
Product: "Milan",
ProductCerts: &trust.ProductCerts{
Ask: ask,
Ark: &trustedArk,
},
},
},
},
}
if err := v.attestationVerifier.SNPAttestation(att, verifyOpts); err != nil {
return nil, fmt.Errorf("verifying SNP attestation: %w", err)
}
// Checks if the attestation report matches the given constraints.
// Some constraints are implicitly checked by validate.SnpAttestation:
// - the report is not expired
if err := v.attestationValidator.SNPAttestation(att, &validate.Options{
GuestPolicy: abi.SnpPolicy{
Debug: false, // Debug means the VM can be decrypted by the host for debugging purposes and thus is not allowed.
SMT: true, // Allow Simultaneous Multi-Threading (SMT). Normally, we would want to disable SMT
// but Azure does not allow to disable it.
},
VMPL: new(int), // Checks that Virtual Machine Privilege Level (VMPL) is 0.
// This checks that the reported TCB version is equal or greater than the minimum specified in the config.
MinimumTCB: kds.TCBParts{
BlSpl: v.config.BootloaderVersion.Value, // Bootloader
TeeSpl: v.config.TEEVersion.Value, // TEE (Secure OS)
SnpSpl: v.config.SNPVersion.Value, // SNP
UcodeSpl: v.config.MicrocodeVersion.Value, // Microcode
},
// This checks that the reported LaunchTCB version is equal or greater than the minimum specified in the config.
MinimumLaunchTCB: kds.TCBParts{
BlSpl: v.config.BootloaderVersion.Value, // Bootloader
TeeSpl: v.config.TEEVersion.Value, // TEE (Secure OS)
SnpSpl: v.config.SNPVersion.Value, // SNP
UcodeSpl: v.config.MicrocodeVersion.Value, // Microcode
},
// Check that CurrentTCB >= CommittedTCB.
PermitProvisionalFirmware: true,
// Check if the IDKey hash in the report is in the list of accepted hashes.
TrustedIDKeyHashes: v.config.FirmwareSignerConfig.AcceptedKeyDigests,
// The IDKey hash should not be checked if the enforcement policy is set to MAAFallback or WarnOnly to prevent
// an error from being returned because of the TrustedIDKeyHashes validation. In this case, we should perform a
// custom check of the MAA-specific values later. Right now, this is a double check, since a custom MAA check
// is performed either way.
RequireIDBlock: v.config.FirmwareSignerConfig.EnforcementPolicy == idkeydigest.Equal,
}); err != nil {
return nil, fmt.Errorf("validating SNP attestation: %w", err)
}
// Custom check of the IDKeyDigests, taking care of the WarnOnly / MAAFallback cases,
// but also double-checking the IDKeyDigests if the enforcement policy is set to Equal.
if err := v.checkIDKeyDigest(ctx, att, instanceInfo.MAAToken, extraData); err != nil {
return nil, fmt.Errorf("checking IDKey digests: %w", err)
}
// Decode the public area of the attestation key and validate its trustworthiness.
pubArea, err := tpm2.DecodePublic(attDoc.Attestation.AkPub)
if err != nil {
return nil, err
}
if err = v.hclValidator.validateAk(instanceInfo.RuntimeData, report.ReportData[:], pubArea.RSAParameters); err != nil {
if err = v.hclValidator.validateAk(instanceInfo.RuntimeData, att.Report.ReportData, pubArea.RSAParameters); err != nil {
return nil, fmt.Errorf("validating HCLAkPub: %w", err)
}
return pubArea.Key()
}
// validateVCEK takes the PEM-encoded X509 certificate VCEK, ASK and ARK and verifies the integrity of the chain.
// ARK (hardcoded) validates ASK (cloud metadata API) validates VCEK (cloud metadata API).
func (v *Validator) validateVCEK(vcekRaw []byte, certChain []byte) (*x509.Certificate, error) {
vcek, err := internalCrypto.PemToX509Cert(vcekRaw)
// checkIDKeyDigest validates the IDKeyDigest in the given attestation report against the accepted IDKeyDigests in the
// validator's config. If an IDKeyDigest is present in the report that is not in the accepted IDKeyDigests, the validation proceeds
// according to the enforcement policy. If the enforcement policy is set to MAAFallback, the maaToken is validated against the MAA.
// If the enforcement policy is set to WarnOnly, a warning is logged. If the enforcement policy is set to neither WarnOnly or MAAFallback, an
// error is returned.
func (v *Validator) checkIDKeyDigest(ctx context.Context, report *spb.Attestation, maaToken string, extraData []byte) error {
for _, digest := range v.config.FirmwareSignerConfig.AcceptedKeyDigests {
if bytes.Equal(digest, report.Report.IdKeyDigest) {
return nil
}
}
// IDKeyDigest that was not expected is present, check the enforcement policy and verify against
// the MAA if necessary.
switch v.config.FirmwareSignerConfig.EnforcementPolicy {
case idkeydigest.MAAFallback:
v.log.Infof(
"Configured idkeydigests %x don't contain reported idkeydigest %x, falling back to MAA validation",
v.config.FirmwareSignerConfig.AcceptedKeyDigests,
report.Report.IdKeyDigest,
)
return v.maa.validateToken(ctx, v.config.FirmwareSignerConfig.MAAURL, maaToken, extraData)
case idkeydigest.WarnOnly:
v.log.Warnf(
"Configured idkeydigests %x don't contain reported idkeydigest %x",
v.config.FirmwareSignerConfig.AcceptedKeyDigests,
report.Report.IdKeyDigest,
)
default:
return fmt.Errorf(
"configured idkeydigests %x don't contain reported idkeydigest %x",
v.config.FirmwareSignerConfig.AcceptedKeyDigests,
report.Report.IdKeyDigest,
)
}
// No IDKeyDigest that was not expected is present.
return nil
}
// azureInstanceInfo contains the necessary information to establish trust in
// an Azure CVM.
type azureInstanceInfo struct {
// VCEK is the PEM-encoded VCEK certificate for the attestation report.
VCEK []byte
// CertChain is the PEM-encoded certificate chain for the attestation report.
CertChain []byte
// AttestationReport is the attestation report from the vTPM (NVRAM) of the CVM.
AttestationReport []byte
// RuntimeData is the Azure runtime data from the vTPM (NVRAM) of the CVM.
RuntimeData []byte
// MAAToken is the token of the MAA for the attestation report, used as a fallback
// if the IDKeyDigest cannot be verified.
MAAToken string
}
// attestationWithCerts returns a formatted version of the attestation report and its certificates from the instanceInfo.
// if the VCEK certificate or the certificate chain is not present, the given getter is used to retrieve them
// from the AMD KDS.
func (a *azureInstanceInfo) attestationWithCerts(logger attestation.Logger, getter trust.HTTPSGetter) (*spb.Attestation, error) {
report, err := abi.ReportToProto(a.AttestationReport)
if err != nil {
return nil, fmt.Errorf("loading vcek: %w", err)
return nil, fmt.Errorf("converting report to proto: %w", err)
}
// certChain includes two PEM encoded certs. The ASK and the ARK, in that order.
ask, err := internalCrypto.PemToX509Cert(certChain)
// Product info as reported through CPUID[EAX=1]
sevProduct := abi.DefaultSevProduct()
productName := kds.ProductString(sevProduct)
att := &spb.Attestation{
Report: report,
CertificateChain: &spb.CertificateChain{},
Product: sevProduct,
}
// If the VCEK certificate is present, parse it and format it.
vcek, err := a.parseVCEK()
if err != nil {
return nil, fmt.Errorf("loading askPEM: %w", err)
logger.Warnf("Error parsing VCEK: %v", err)
}
if vcek != nil {
att.CertificateChain.VcekCert = vcek.Raw
} else {
// Otherwise, retrieve it from AMD KDS.
logger.Infof("VCEK certificate not present, falling back to retrieving it from AMD KDS")
vcekURL := kds.VCEKCertURL(productName, report.GetChipId(), kds.TCBVersion(report.GetReportedTcb()))
vcek, err := getter.Get(vcekURL)
if err != nil {
return nil, fmt.Errorf("retrieving VCEK certificate from AMD KDS: %w", err)
}
att.CertificateChain.VcekCert = vcek
}
if err = ask.CheckSignatureFrom((*x509.Certificate)(&v.config.AMDRootKey)); err != nil {
return nil, &askError{err}
// If the certificate chain is present, parse it and format it.
ask, ark, err := a.parseCertChain()
if err != nil {
logger.Warnf("Error parsing certificate chain: %v", err)
}
if ask != nil {
att.CertificateChain.AskCert = ask.Raw
}
if ark != nil {
att.CertificateChain.ArkCert = ark.Raw
}
// Otherwise, retrieve it from AMD KDS.
if att.CertificateChain.AskCert == nil || att.CertificateChain.ArkCert == nil {
logger.Infof(
"Certificate chain not fully present (ARK present: %t, ASK present: %t), falling back to retrieving it from AMD KDS",
(att.CertificateChain.ArkCert != nil),
(att.CertificateChain.AskCert != nil),
)
kdsCertChain, err := trust.GetProductChain(productName, abi.VcekReportSigner, getter)
if err != nil {
return nil, fmt.Errorf("retrieving certificate chain from AMD KDS: %w", err)
}
if att.CertificateChain.AskCert == nil {
att.CertificateChain.AskCert = kdsCertChain.Ask.Raw
}
if att.CertificateChain.ArkCert == nil {
att.CertificateChain.ArkCert = kdsCertChain.Ark.Raw
}
}
if err = vcek.CheckSignatureFrom(ask); err != nil {
return nil, &vcekError{err}
return att, nil
}
// parseCertChain parses the certificate chain from the instanceInfo into x509-formatted ASK and ARK certificates.
// If less than 2 certificates are present, only the present certificate is returned.
// If more than 2 certificates are present, an error is returned.
func (a *azureInstanceInfo) parseCertChain() (ask, ark *x509.Certificate, retErr error) {
rest := bytes.TrimSpace(a.CertChain)
i := 1
var block *pem.Block
for block, rest = pem.Decode(rest); block != nil; block, rest = pem.Decode(rest) {
if i > 2 {
retErr = fmt.Errorf("parse certificate %d: more than 2 certificates in chain", i)
return
}
if block.Type != "CERTIFICATE" {
retErr = fmt.Errorf("parse certificate %d: expected PEM block type 'CERTIFICATE', got '%s'", i, block.Type)
return
}
cert, err := x509.ParseCertificate(block.Bytes)
if err != nil {
retErr = fmt.Errorf("parse certificate %d: %w", i, err)
return
}
// https://www.amd.com/content/dam/amd/en/documents/epyc-technical-docs/specifications/57230.pdf
// Table 6 and 7
switch cert.Subject.CommonName {
case "SEV-Milan":
ask = cert
case "ARK-Milan":
ark = cert
default:
retErr = fmt.Errorf("parse certificate %d: unexpected subject CN %s", i, cert.Subject.CommonName)
return
}
i++
}
switch {
case i == 1:
retErr = fmt.Errorf("no PEM blocks found")
case len(rest) != 0:
retErr = fmt.Errorf("remaining PEM block is not a valid certificate: %s", rest)
}
return
}
// parseVCEK parses the VCEK certificate from the instanceInfo into an x509-formatted certificate.
// If the VCEK certificate is not present, nil is returned.
func (a *azureInstanceInfo) parseVCEK() (*x509.Certificate, error) {
newlinesTrimmed := bytes.TrimSpace(a.VCEK)
if len(newlinesTrimmed) == 0 {
// VCEK is not present.
return nil, nil
}
block, rest := pem.Decode(newlinesTrimmed)
if block == nil {
return nil, fmt.Errorf("no PEM blocks found")
}
if len(rest) != 0 {
return nil, fmt.Errorf("received more data than expected")
}
if block.Type != "CERTIFICATE" {
return nil, fmt.Errorf("expected PEM block type 'CERTIFICATE', got '%s'", block.Type)
}
vcek, err := x509.ParseCertificate(block.Bytes)
if err != nil {
return nil, fmt.Errorf("parsing VCEK certificate: %w", err)
}
return vcek, nil
}
func (v *Validator) validateSNPReport(
ctx context.Context, cert *x509.Certificate, report snpAttestationReport, maaToken string, extraData []byte,
) error {
if report.Policy.Debug() {
return errDebugEnabled
}
if !report.CommittedTCB.isVersion(v.config.BootloaderVersion.Value, v.config.TEEVersion.Value, v.config.SNPVersion.Value, v.config.MicrocodeVersion.Value) {
return &versionError{"COMMITTED_TCB", report.CommittedTCB}
}
if report.LaunchTCB != report.CommittedTCB {
return &versionError{"LAUNCH_TCB", report.LaunchTCB}
}
if !report.CommittedTCB.supersededBy(report.CurrentTCB) {
return &versionError{"CURRENT_TCB", report.CurrentTCB}
}
if err := validateVCEKExtensions(cert, report); err != nil {
return fmt.Errorf("mismatching vcek extensions: %w", err)
}
sigR := report.Signature.R[:]
sigS := report.Signature.S[:]
// Table 107 in https://www.amd.com/system/files/TechDocs/56860.pdf mentions little endian signature components.
// They come out of the certificate as big endian.
reverseEndian(sigR)
reverseEndian(sigS)
rParam := new(big.Int).SetBytes(sigR)
sParam := new(big.Int).SetBytes(sigS)
sequence := ecdsaSig{rParam, sParam}
sigEncoded, err := asn1.Marshal(sequence)
if err != nil {
return fmt.Errorf("marshalling ecdsa signature: %w", err)
}
buf := new(bytes.Buffer)
if err = binary.Write(buf, binary.LittleEndian, report); err != nil {
return fmt.Errorf("writing report to buf: %w", err)
}
// signature is only calculated from 0x0 to 0x2a0
if err := cert.CheckSignature(x509.ECDSAWithSHA384, buf.Bytes()[:0x2a0], sigEncoded); err != nil {
return &signatureError{err}
}
hasExpectedIDKeyDigest := false
for _, digest := range v.config.FirmwareSignerConfig.AcceptedKeyDigests {
if bytes.Equal(digest, report.IDKeyDigest[:]) {
hasExpectedIDKeyDigest = true
break
}
}
if !hasExpectedIDKeyDigest {
switch v.config.FirmwareSignerConfig.EnforcementPolicy {
case idkeydigest.MAAFallback:
v.log.Infof(
"configured idkeydigests %x don't contain reported idkeydigest %x, falling back to MAA validation",
v.config.FirmwareSignerConfig.AcceptedKeyDigests,
report.IDKeyDigest[:],
)
return v.maa.validateToken(ctx, v.config.FirmwareSignerConfig.MAAURL, maaToken, extraData)
case idkeydigest.WarnOnly:
v.log.Warnf(
"configured idkeydigests %x don't contain reported idkeydigest %x",
v.config.FirmwareSignerConfig.AcceptedKeyDigests,
report.IDKeyDigest[:],
)
default:
return &idKeyError{report.IDKeyDigest[:], v.config.FirmwareSignerConfig.AcceptedKeyDigests}
}
}
return nil
}
// validateVCEKExtensions checks that the certificate extension values in cert match the values described in report.
func validateVCEKExtensions(cert *x509.Certificate, report snpAttestationReport) error {
var certVersion int
for _, extension := range cert.Extensions {
switch extension.Id.String() {
// check bootloader version
case "1.3.6.1.4.1.3704.1.3.1":
{
_, err := asn1.Unmarshal(extension.Value, &certVersion)
if err != nil {
return fmt.Errorf("unmarshalling bootloader version: %w", err)
}
if certVersion != int(report.CommittedTCB.Bootloader) {
return fmt.Errorf("bootloader version %d from report does not match VCEK version %d", int(report.CommittedTCB.Bootloader), certVersion)
}
}
// check TEE version
case "1.3.6.1.4.1.3704.1.3.2":
{
_, err := asn1.Unmarshal(extension.Value, &certVersion)
if err != nil {
return fmt.Errorf("unmarshalling tee version: %w", err)
}
if certVersion != int(report.CommittedTCB.TEE) {
return fmt.Errorf("bootloader version %d from report does not match VCEK version %d", int(report.CommittedTCB.TEE), certVersion)
}
}
// check SNP Firmware version
case "1.3.6.1.4.1.3704.1.3.3":
{
_, err := asn1.Unmarshal(extension.Value, &certVersion)
if err != nil {
return fmt.Errorf("unmarshalling snp version: %w", err)
}
if certVersion != int(report.CommittedTCB.SNP) {
return fmt.Errorf("bootloader version %d from report does not match VCEK version %d", int(report.CommittedTCB.SNP), certVersion)
}
}
// check microcode version
case "1.3.6.1.4.1.3704.1.3.8":
{
_, err := asn1.Unmarshal(extension.Value, &certVersion)
if err != nil {
return fmt.Errorf("unmarshalling microcode version: %w", err)
}
if certVersion != int(report.CommittedTCB.Microcode) {
return fmt.Errorf("bootloader version %d from report does not match VCEK version %d", int(report.CommittedTCB.Microcode), certVersion)
}
}
}
}
return nil
}
type azureInstanceInfo struct {
Vcek []byte
CertChain []byte
AttestationReport []byte
RuntimeData []byte
MAAToken string
}
// validateAk validates that the attestation key from the TPM is trustworthy. The steps are:
// 1. runtime data read from the TPM has the same sha256 digest as reported in `report_data` of the SNP report.
// 2. modulus reported in runtime data matches modulus from key at idx 0x81000003.
@ -336,84 +448,7 @@ type hclAkValidator interface {
validateAk(runtimeDataRaw []byte, reportData []byte, rsaParameters *tpm2.RSAParams) error
}
// Reference: https://github.com/AMDESE/sev-guest/blob/main/include/attestation.h
type snpAttestationReport struct {
Version uint32 // 0x000
GuestSVN uint32 // 0x004
Policy guestPolicy // 0x008
FamilyID [16]byte // 0x010
ImageID [16]byte // 0x020
VMPL uint32 // 0x030
SignatureAlgo uint32 // 0x034
CurrentTCB tcbVersion // 0x038
PlatformInfo uint64 // 0x040
Flags uint32 // 0x048
Reserved0 uint32 // 0x04C
ReportData [64]byte // 0x050
Measurement [48]byte // 0x090
HostData [32]byte // 0x0C0
IDKeyDigest [48]byte // 0x0E0
AuthorKeyDigest [48]byte // 0x110
ReportID [32]byte // 0x140
ReportIDMa [32]byte // 0x160
ReportedTCB tcbVersion // 0x180
_ [24]byte // 0x188
ChipID [64]byte // 0x1A0
CommittedTCB tcbVersion // 0x1E0
CurrentBuild byte // 0x1E8
CurrentMinor byte // 0x1E9
CurrentMajor byte // 0x1EA
_ byte // 0x1EB
CommittedBuild byte // 0x1EC
CommittedMinor byte // 0x1ED
CommittedMajor byte // 0x1EE
_ byte // 0x1EF
LaunchTCB tcbVersion // 0x1F0
_ [168]byte // 0x1F8
Signature snpSignature // 0x2A0
}
type guestPolicy struct {
AbiMinor uint8 // 0x0
AbiMajor uint8 // 0x8
ContainerValue byte // 0x10 - encodes the following four values:
// Smt bool // 0x10 - bit 0 in 'ContainerValue'.
// _ bool // 0x11 - bit 1 in 'ContainerValue'.
// MigrateMa bool // 0x12 - bit 2 in 'ContainerValue'.
// Debug bool // 0x13 - bit 3 in 'ContainerValue'.
// SingleSocket bool // 0x14 - bit 4 in 'ContainerValue'.
_ [5]byte // 0x15
}
func (g *guestPolicy) Debug() bool {
return (g.ContainerValue & 0b00001000) != 0
}
type tcbVersion struct {
Bootloader uint8 // 0x0
TEE uint8 // 0x10
_ [4]byte // 0x2F
SNP uint8 // 0x37
Microcode uint8 // 0x3F
}
func (t *tcbVersion) isVersion(expectedBootloader, expectedTEE, expectedSNP, expectedMicrocode uint8) bool {
return t.Bootloader >= expectedBootloader && t.TEE >= expectedTEE && t.SNP >= expectedSNP && t.Microcode >= expectedMicrocode
}
func (t *tcbVersion) supersededBy(new tcbVersion) bool {
return new.Bootloader >= t.Bootloader && new.TEE >= t.TEE && new.SNP >= t.SNP && new.Microcode >= t.Microcode
}
type snpSignature struct {
R [72]byte
S [72]byte
Reserved [512 - 144]byte
}
type ecdsaSig struct {
R, S *big.Int
}
// akPub are the public parameters of an RSA attestation key.
type akPub struct {
E string
N string

File diff suppressed because one or more lines are too long

View File

@ -83,7 +83,7 @@ require (
github.com/google/gnostic v0.5.7-v3refs // indirect
github.com/google/go-cmp v0.5.9 // indirect
github.com/google/gofuzz v1.2.0 // indirect
github.com/google/uuid v1.3.0 // indirect
github.com/google/uuid v1.3.1 // indirect
github.com/googleapis/enterprise-certificate-proxy v0.2.5 // indirect
github.com/imdario/mergo v0.3.13 // indirect
github.com/josharian/intern v1.0.0 // indirect
@ -106,12 +106,12 @@ require (
go.uber.org/atomic v1.11.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
go.uber.org/zap v1.24.0 // indirect
golang.org/x/crypto v0.12.0 // indirect
golang.org/x/crypto v0.13.0 // indirect
golang.org/x/net v0.14.0 // indirect
golang.org/x/oauth2 v0.9.0 // indirect
golang.org/x/sys v0.11.0 // indirect
golang.org/x/term v0.11.0 // indirect
golang.org/x/text v0.12.0 // indirect
golang.org/x/sys v0.12.0 // indirect
golang.org/x/term v0.12.0 // indirect
golang.org/x/text v0.13.0 // indirect
golang.org/x/time v0.3.0 // indirect
gomodules.xyz/jsonpatch/v2 v2.3.0 // indirect
google.golang.org/appengine v1.6.7 // indirect

View File

@ -222,8 +222,8 @@ github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm4
github.com/google/s2a-go v0.1.4 h1:1kZ/sQM3srePvKs3tXAvQzo66XfcReoqFpIpIccE7Oc=
github.com/google/s2a-go v0.1.4/go.mod h1:Ej+mSEMGRnqRzjc7VtF+jdBwYG5fuJfiZ8ELkjEwM0A=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4=
github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/enterprise-certificate-proxy v0.2.5 h1:UR4rDjcgpgEnqpIEvkiqTYKBCKLNmlge2eVjoZfySzM=
github.com/googleapis/enterprise-certificate-proxy v0.2.5/go.mod h1:RxW0N9901Cko1VOCW3SXCpWP+mlIEkk2tP7jnHy9a3w=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
@ -356,8 +356,8 @@ golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20220314234659-1baeb1ce4c0b/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.12.0 h1:tFM/ta59kqch6LlvYnPa0yx5a83cL2nHflFhYKvv9Yk=
golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw=
golang.org/x/crypto v0.13.0 h1:mvySKfSWJ+UKUii46M40LOvyWfN0s2U+46/jDd0e6Ck=
golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
@ -497,12 +497,12 @@ golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.11.0 h1:eG7RXZHdqOJ1i+0lgLgCpSXAp6M3LYlAo6osgSi0xOM=
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o=
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.11.0 h1:F9tnn/DA/Im8nCwm+fX+1/eBwi4qFjRT++MhtVC4ZX0=
golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU=
golang.org/x/term v0.12.0 h1:/ZfYdc3zq+q02Rv9vGqTeSItdzZTSNDmfTi0mBAuidU=
golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@ -512,8 +512,8 @@ golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
golang.org/x/text v0.12.0 h1:k+n5B8goJNdU7hSvEtMUz3d1Q6D/XW4COJSJR6fN0mc=
golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k=
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=