mirror of
https://github.com/ultravioletrs/cocos.git
synced 2026-06-23 04:10:25 +00:00
NOISSUE - Fix attested TLS and attestation CLI (#184)
* update code to reflect updated libraries * fix attestation CLI * update manual test for attestation CLI
This commit is contained in:
committed by
GitHub
parent
6d170e9ca4
commit
24a76a1685
+33
-3
@@ -13,6 +13,7 @@ import (
|
||||
|
||||
"github.com/google/go-sev-guest/abi"
|
||||
"github.com/google/go-sev-guest/proto/check"
|
||||
"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"
|
||||
@@ -40,6 +41,8 @@ const (
|
||||
size48 = 48
|
||||
size64 = 64
|
||||
attestationFilePath = "attestation.bin"
|
||||
sevProductNameMilan = "Milan"
|
||||
sevProductNameGenoa = "Genoa"
|
||||
exampleJSONConfig = `
|
||||
{
|
||||
"rootOfTrust":{
|
||||
@@ -366,7 +369,7 @@ func (cli *CLI) NewValidateAttestationValidationCmd() *cobra.Command {
|
||||
"Hex-encoded SHA-384 hash values of trusted identity keys in AMD public key format",
|
||||
)
|
||||
cmd.Flags().StringVar(
|
||||
&cfg.RootOfTrust.Product,
|
||||
&cfg.RootOfTrust.ProductLine,
|
||||
"product",
|
||||
"",
|
||||
"The AMD product name for the chip that generated the attestation report.",
|
||||
@@ -394,6 +397,10 @@ func (cli *CLI) NewValidateAttestationValidationCmd() *cobra.Command {
|
||||
log.Fatalf("Failed to mark flag as required: %s", err)
|
||||
}
|
||||
|
||||
if err := cmd.MarkFlagRequired("product"); err != nil {
|
||||
log.Fatalf("Failed to mark flag as required: %s", err)
|
||||
}
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
@@ -402,13 +409,36 @@ func verifyAndValidateAttestation(attestation []byte) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
sopts.Product = cfg.Policy.Product
|
||||
|
||||
if cfg.Policy.Product == nil {
|
||||
productName := sevsnp.SevProduct_SEV_PRODUCT_UNKNOWN
|
||||
switch cfg.RootOfTrust.ProductLine {
|
||||
case sevProductNameMilan:
|
||||
productName = sevsnp.SevProduct_SEV_PRODUCT_MILAN
|
||||
case sevProductNameGenoa:
|
||||
productName = sevsnp.SevProduct_SEV_PRODUCT_GENOA
|
||||
default:
|
||||
}
|
||||
|
||||
if productName == sevsnp.SevProduct_SEV_PRODUCT_UNKNOWN {
|
||||
return fmt.Errorf("product name must be %s or %s", sevProductNameMilan, sevProductNameGenoa)
|
||||
}
|
||||
|
||||
sopts.Product = &sevsnp.SevProduct{
|
||||
Name: productName,
|
||||
}
|
||||
} else {
|
||||
sopts.Product = cfg.Policy.Product
|
||||
}
|
||||
|
||||
sopts.Getter = &trust.RetryHTTPSGetter{
|
||||
Timeout: timeout,
|
||||
MaxRetryDelay: maxRetryDelay,
|
||||
Getter: &trust.SimpleHTTPSGetter{},
|
||||
}
|
||||
attestationPB, err := abi.ReportCertsToProto(attestation)
|
||||
|
||||
// Only take the attestation report and ignore everything else.
|
||||
attestationPB, err := abi.ReportCertsToProto(attestation[:abi.ReportSize])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -35,10 +35,11 @@ const (
|
||||
)
|
||||
|
||||
const (
|
||||
cocosDirectory = ".cocos"
|
||||
caBundleName = "ask_ark.pem"
|
||||
productNameMilan = "Milan"
|
||||
productNameGenoa = "Genoa"
|
||||
cocosDirectory = ".cocos"
|
||||
caBundleName = "ask_ark.pem"
|
||||
productNameMilan = "Milan"
|
||||
productNameGenoa = "Genoa"
|
||||
attestationReportSize = 0x4A0
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -185,7 +186,7 @@ func connect(cfg Config) (*grpc.ClientConn, security, error) {
|
||||
|
||||
opts = append(opts, grpc.WithTransportCredentials(tc))
|
||||
|
||||
conn, err := grpc.Dial(cfg.URL, opts...)
|
||||
conn, err := grpc.NewClient(cfg.URL, opts...)
|
||||
if err != nil {
|
||||
return nil, secure, errors.Wrap(errGrpcConnect, err)
|
||||
}
|
||||
@@ -247,7 +248,8 @@ func verifyAttestationReportTLS(rawCerts [][]byte, verifiedChains [][]*x509.Cert
|
||||
Getter: &trust.SimpleHTTPSGetter{},
|
||||
}
|
||||
|
||||
attestationPB, err := abi.ReportCertsToProto(ext.Value)
|
||||
attestation_bytes := ext.Value[:attestationReportSize]
|
||||
attestationPB, err := abi.ReportCertsToProto(attestation_bytes)
|
||||
if err != nil {
|
||||
return errors.Wrap(errAttVerification, err)
|
||||
}
|
||||
@@ -293,7 +295,7 @@ func checkIfCertificateSelfSigned(cert *x509.Certificate) error {
|
||||
}
|
||||
|
||||
func fillInAttestationLocal(attestation *sevsnp.Attestation) error {
|
||||
product := attestationConfiguration.RootOfTrust.Product
|
||||
product := attestationConfiguration.RootOfTrust.ProductLine
|
||||
|
||||
chain := attestation.GetCertificateChain()
|
||||
if chain == nil {
|
||||
|
||||
@@ -24,8 +24,9 @@ const (
|
||||
)
|
||||
|
||||
var (
|
||||
_ streamSender = (*algoClientWrapper)(nil)
|
||||
_ streamSender = (*dataClientWrapper)(nil)
|
||||
_ streamSender = (*algoClientWrapper)(nil)
|
||||
_ streamSender = (*dataClientWrapper)(nil)
|
||||
warnOnlyOnce = false
|
||||
)
|
||||
|
||||
type streamSender interface {
|
||||
@@ -192,7 +193,11 @@ func (p *ProgressBar) renderProgressBar() error {
|
||||
// Get terminal width.
|
||||
width, err := terminalWidth()
|
||||
if err != nil {
|
||||
return err
|
||||
if !warnOnlyOnce {
|
||||
fmt.Println("Progress bar could not be rendered")
|
||||
warnOnlyOnce = true
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
if p.maxWidth < width {
|
||||
|
||||
@@ -10,5 +10,3 @@ clap = { version = "4.0", features = ["derive"] }
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_json = "1.0"
|
||||
sev = "3.1.1"
|
||||
sysinfo = "0.30.12"
|
||||
regex = "1.10.4"
|
||||
|
||||
@@ -1,12 +1,27 @@
|
||||
use clap::{Arg, Command, value_parser};
|
||||
use serde::Serialize;
|
||||
use std::arch::x86_64::__cpuid;
|
||||
use std::fs::File;
|
||||
use std::io::Write;
|
||||
use sysinfo::System;
|
||||
use regex::Regex;
|
||||
use sev::firmware::host::*;
|
||||
|
||||
const BACKEND_INFO_JSON : &str = "backend_info.json";
|
||||
const EXTENDED_FAMILY_SHIFT: u32 = 20;
|
||||
const EXTENDED_MODEL_SHIFT: u32 = 16;
|
||||
const FAMILY_SHIFT: u32 = 8;
|
||||
const SEV_EXTENDED_FAMILY: u32 = 0xA;
|
||||
const SEV_FAMILY: u32 = 0xF;
|
||||
const MILAN_EXTENDED_MODEL: u32 = 0x0;
|
||||
const GENOA_EXTENDED_MODEL: u32 = 0x1;
|
||||
|
||||
const SEV_PRODUCT_UNKNOWN: i32 = 0;
|
||||
const SEV_PRODUCT_MILAN: i32 = 1;
|
||||
const SEV_PRODUCT_GENOA: i32 = 2;
|
||||
|
||||
#[derive(Clone, Copy, Serialize)]
|
||||
struct SevProduct {
|
||||
name: i32,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
struct Vmpl {
|
||||
@@ -30,6 +45,7 @@ struct SnpPolicy {
|
||||
minimum_version: String,
|
||||
permit_provisional_firmware: bool,
|
||||
require_id_block: bool,
|
||||
product: SevProduct,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
@@ -37,6 +53,7 @@ struct RootOfTrust {
|
||||
product: String,
|
||||
check_crl : bool,
|
||||
disallow_network : bool,
|
||||
product_line : String,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
@@ -45,30 +62,52 @@ struct Computation {
|
||||
root_of_trust: RootOfTrust,
|
||||
}
|
||||
|
||||
fn get_product_name() -> String {
|
||||
let mut sys = System::new_all();
|
||||
sys.refresh_all();
|
||||
|
||||
let re = Regex::new(r"EPYC.*7..3.*").unwrap();
|
||||
fn get_sev_snp_processor() -> u32 {
|
||||
let cpuid_result = unsafe { __cpuid(1)};
|
||||
cpuid_result.eax
|
||||
}
|
||||
|
||||
for cpu in sys.cpus() {
|
||||
if re.is_match(cpu.brand()) {
|
||||
return "Milan".to_string()
|
||||
}
|
||||
fn get_product_name(product: i32) -> String {
|
||||
match product {
|
||||
SEV_PRODUCT_MILAN => return "Milan".to_string(),
|
||||
SEV_PRODUCT_GENOA => return "Genoa".to_string(),
|
||||
_ => return "Unknown".to_string(),
|
||||
}
|
||||
|
||||
"Unknown".to_string()
|
||||
}
|
||||
|
||||
fn get_uint64_from_tcb(tcb_version : &TcbVersion) -> u64 {
|
||||
let microcode = (tcb_version.microcode as u64) << 56;
|
||||
let snp = (tcb_version.snp as u64) << 48;
|
||||
let tee = (tcb_version.tee as u64) << 8;
|
||||
let bootloader = tcb_version.bootloader as u64;
|
||||
let bootloader: u64 = tcb_version.bootloader as u64;
|
||||
|
||||
microcode | snp | tee | bootloader
|
||||
}
|
||||
|
||||
fn sev_product(eax: u32) -> SevProduct {
|
||||
let extended_family = (eax >> EXTENDED_FAMILY_SHIFT) & 0xff;
|
||||
let extended_model = (eax >> EXTENDED_MODEL_SHIFT) & 0xf;
|
||||
let family = (eax >> FAMILY_SHIFT) & 0xf;
|
||||
|
||||
let mut product_name = SEV_PRODUCT_UNKNOWN;
|
||||
|
||||
if extended_family == SEV_EXTENDED_FAMILY && family == SEV_FAMILY {
|
||||
product_name = match extended_model {
|
||||
MILAN_EXTENDED_MODEL => SEV_PRODUCT_MILAN,
|
||||
GENOA_EXTENDED_MODEL => SEV_PRODUCT_GENOA,
|
||||
_ => {
|
||||
return SevProduct {
|
||||
name: SEV_PRODUCT_UNKNOWN,
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
SevProduct {
|
||||
name: product_name,
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let matches = Command::new("Backend info")
|
||||
.about("Processes command line options and outputs a JSON file for Attestation verification")
|
||||
@@ -84,21 +123,22 @@ fn main() {
|
||||
let status: SnpPlatformStatus = firmware.snp_platform_status().unwrap();
|
||||
|
||||
let policy: u64 = *matches.get_one::<u64>("policy").unwrap();
|
||||
let family_id = vec![0];
|
||||
let image_id = vec![0];
|
||||
let family_id = vec![0; 16];
|
||||
let image_id = vec![0; 16];
|
||||
let vmpl = Vmpl { value: 0};
|
||||
let minimum_tcb = get_uint64_from_tcb(&status.platform_tcb_version);
|
||||
let minimum_launch_tcb = get_uint64_from_tcb(&status.platform_tcb_version);
|
||||
let require_author_key = false;
|
||||
let measurement = vec![0];
|
||||
let host_data = vec![0];
|
||||
let report_id_ma = vec![0];
|
||||
let report_id_ma = vec![0xFF; 32];
|
||||
let cpu_id: Identifier = firmware.get_identifier().unwrap();
|
||||
let chip_id: Vec<u8> = cpu_id.0;
|
||||
let minimum_build = status.build_id;
|
||||
let minimum_version = status.version.to_string();
|
||||
let permit_provisional_firmware = false;
|
||||
let require_id_block = false;
|
||||
let product = sev_product(get_sev_snp_processor());
|
||||
|
||||
let snp_policy = SnpPolicy {
|
||||
policy,
|
||||
@@ -116,12 +156,14 @@ fn main() {
|
||||
minimum_version,
|
||||
permit_provisional_firmware,
|
||||
require_id_block,
|
||||
product,
|
||||
};
|
||||
|
||||
let root_of_trust = RootOfTrust {
|
||||
product : get_product_name(),
|
||||
product : get_product_name(product.name),
|
||||
check_crl : true,
|
||||
disallow_network : false,
|
||||
product_line : get_product_name(product.name),
|
||||
};
|
||||
|
||||
let computation = Computation {
|
||||
|
||||
@@ -68,7 +68,8 @@ export AGENT_GRPC_ATTESTED_TLS=true
|
||||
go run cmd/cli/main.go attestation get '<report_data>'
|
||||
|
||||
# Validate Attestation
|
||||
go run cmd/cli/main.go attestation validate '<attesation>' --report_data '<report_data>'
|
||||
# Product name must be Milan or Genoa
|
||||
go run cmd/cli/main.go attestation validate '<attesation>' --report_data '<report_data>' --product <product_name>
|
||||
|
||||
# Run the CLI program with algorithm input
|
||||
go run cmd/cli/main.go algo test/manual/algo/lin_reg.bin <private_key_file_path>
|
||||
|
||||
Reference in New Issue
Block a user