-
Notifications
You must be signed in to change notification settings - Fork 19
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add support for validating VLEK certificates #67
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the patch! 😸
656bbe4
to
454b644
Compare
Hey @deeglaze , In any case, this is what I found:
Not sure how these discrepancies should be handled. I guess we need to change go-sev-guest's assumptions? Best, |
Thanks Otto. This helps, since I don't have a real example of a VLEK to work from. Do you have a binary that you can share that I could use for testing purposes? |
3745e45
to
f2ed12c
Compare
I've added the VLEK bundle from the KDS and fixed up the issues you mentioned. Please give the updated patch another try. |
verify/trust/trust.go
Outdated
switch key { | ||
case abi.VcekReportSigner: | ||
intermediates.AddCert(r.Ask) | ||
case abi.VlekReportSigner: | ||
intermediates.AddCert(r.Asvk) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Move the r.Ask == nil
case from the if
in L236 to the switch.
switch key { | |
case abi.VcekReportSigner: | |
intermediates.AddCert(r.Ask) | |
case abi.VlekReportSigner: | |
intermediates.AddCert(r.Asvk) | |
} | |
switch key { | |
case abi.VcekReportSigner: | |
if r.Ask == nil { | |
return nil | |
} | |
intermediates.AddCert(r.Ask) | |
case abi.VlekReportSigner: | |
if r.Asvk == nil { | |
return nil | |
} | |
intermediates.AddCert(r.Asvk) | |
} |
That was the only problem left during my testing 🎉
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice, thanks so much for your help testing. It's tough without a spec :P
verify/verify.go
Outdated
if ica == nil { | ||
return fmt.Errorf("root of trust missing intermediate certificate authority certificate for key %v", key) | ||
} | ||
if _, err := cert.Verify(*r.X509Options(opts.Now, key)); err != nil { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if _, err := cert.Verify(*r.X509Options(opts.Now, key)); err != nil { | |
tmp := r.X509Options(opts.Now, key) | |
if tmp == nil { | |
return fmt.Errorf("internal error: could not get X509 options for %v", key) | |
} | |
if _, err := cert.Verify(*tmp); err != nil { |
Not sure how to call that variable ^^
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah yes, uninitialized intermediate certs will lead to a nil dereference. Good catch.
Nicee. Works now :P. LGTM, once the two changes are included 👍 That's the raw cert table from the ExtendedReport I used for testing. Hope that is what you were looking for.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Works as expected :)
@@ -293,6 +295,13 @@ func mbz(data []uint8, lo, hi int) error { | |||
return nil | |||
} | |||
|
|||
func mbz64(data uint64, base string, hi, lo int) error { | |||
if (data>>lo)&((1<<(hi-lo+1))-1) != 0 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you add some comments here? It's not quite clear what being checked here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
testing/fake_certs.go
Outdated
cert.NotAfter = b.VcekCreationTime.Add(vcekExpirationYears * 365 * 24 * time.Hour) | ||
var hwid [64]byte | ||
cert.ExtraExtensions = CustomVcekExtensions(kds.TCBParts{}, hwid) | ||
func (b *AmdSignerBuilder) vekPrecert(creationTime time.Time, hwid []byte, serialNumber *big.Int, key abi.ReportSigner) *x509.Certificate { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"vek" stands for "vcek/vlek"? This feels a bit confusing. Can we just call it AmdKeyPrecert or something like that?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
vek is versioned endorsement key. I just expanded to endorsementKey and dropped the versioned.
testing/fake_certs.go
Outdated
b.Vlek = signed | ||
return err | ||
} | ||
|
||
// CertChain creates a test-only certificate chain from the keys and configurables in b. | ||
func (b *AmdSignerBuilder) CertChain() (*AmdSigner, error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we call this TestOnlyCertChain() or so to make it clear this is test-only, since it's not in a test file?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
testing/fakekds.go
Outdated
RootBundles: map[string]string{"Milan": string(milanCerts)}, | ||
Certs: &kpb.Certificates{}, | ||
RootBundles: map[string]RootBundle{"Milan": { | ||
VcekBundle: string(testdata.MilanBytes), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we change this also to "MilanVcekBytes"?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
verify/testdata/testdata.go
Outdated
@@ -25,11 +25,16 @@ import _ "embed" | |||
//go:embed vcek.testcer | |||
var VcekBytes []byte | |||
|
|||
// MilanBytes is the Milan product cert_chain as issued by the AMD KDS. | |||
// MilanBytes is the Milan product vcek cert_chain as issued by the AMD KDS. | |||
// | |||
//go:embed milan.testcer | |||
var MilanBytes []byte |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
MilanVcekBytes?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
@@ -165,7 +166,11 @@ func TestSnpReportSignature(t *testing.T) { | |||
if !bytes.Equal(got, want) { | |||
t.Errorf("%s: GetRawReport(%v) = %v, want %v", tc.Name, tc.Input, got, want) | |||
} | |||
if err := SnpReportSignature(raw, d.Signer.Vcek); err != nil { | |||
key := d.Signer.Vcek |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we add an enum or so here for vcek/vlek instead of a bool tc.Vlek? That may be more readable and in case more type of certs are added in the future.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
This changes the AuthorKeyEn report field to a better-named SignerInfo. The interpretation of this field selects which key the fake signer will use when signing reports. The VLEK certificate extensions are now checked against AMD's VLEK specification. The difference is VLEK certs are like VCEK certs, except the HWID extension is swapped with a CSP_ID extension. Tests have been updated to reflect these changes, including new VLEK-specific test cases. Signed-off-by: Dionna Glaze <dionnaglaze@google.com>
This changes the AuthorKeyEn report field to a better-named SignerInfo. The interpretation of this field selects which key the fake signer will use when signing reports. The VLEK certificate extensions are now checked against AMD's VLEK specification. The difference is VLEK certs are like VCEK certs, except the HWID extension is swapped with a CSP_ID extension.
Tests have been updated to reflect these changes, including new VLEK-specific test cases.