Skip to content

Commit

Permalink
testtool: refactored publishing method
Browse files Browse the repository at this point in the history
Introduced callbacks for attested HTTPS and attested TLS
verification results so that testtool can further
process them.

Signed-off-by: Simon Ott <[email protected]>
  • Loading branch information
smo4201 committed Feb 16, 2024
1 parent 91a23ff commit e2735bf
Show file tree
Hide file tree
Showing 13 changed files with 91 additions and 62 deletions.
6 changes: 2 additions & 4 deletions attestedhttp/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ type Transport struct {
CmcPolicies []byte
Ca []byte
ReadTimeout time.Duration
ResultCb func(result *ar.VerificationResult)
}

// Wrapper for net/http Client
Expand Down Expand Up @@ -187,18 +188,15 @@ func prepareClient(c *Client) error {

log.Debugf("Dialing TLS address: %v", addr)

verificationResult := new(ar.VerificationResult)

conn, err := atls.Dial("tcp", addr, c.Transport.TLSClientConfig,
atls.WithCmcConfig(&cmcConfig),
atls.WithResult(verificationResult))
atls.WithResultCb(c.Transport.ResultCb))
if err != nil {
return nil, fmt.Errorf("failed to dial server: %w", err)
}
if c.Transport.ReadTimeout != 0 {
_ = conn.SetReadDeadline(time.Now().Add(c.Transport.ReadTimeout))
}
// TODO store verification result for retrieval

log.Debugf("aHTTPS connection established")

Expand Down
9 changes: 3 additions & 6 deletions attestedhttp/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import (

// Wrapper for http.Server
type Server struct {
Server *http.Server
*http.Server

// Additional aTLS parameters
Attest string
Expand All @@ -38,6 +38,7 @@ type Server struct {
Cmc *cmc.Cmc
CmcPolicies []byte
Ca []byte
ResultCb func(result *ar.VerificationResult)
}

func (s *Server) ListenAndServe() error {
Expand All @@ -46,8 +47,6 @@ func (s *Server) ListenAndServe() error {
return errors.New("failed to listen: no TLS config provided")
}

verificationResult := new(ar.VerificationResult)

// Listen: TLS connection
ln, err := atls.Listen("tcp", s.Server.Addr, s.Server.TLSConfig,
atls.WithCmcAddr(s.CmcAddr),
Expand All @@ -57,15 +56,13 @@ func (s *Server) ListenAndServe() error {
atls.WithMtls(s.MutualTls),
atls.WithAttest(s.Attest),
atls.WithCmcNetwork(s.CmcNetwork),
atls.WithResult(verificationResult),
atls.WithResultCb(s.ResultCb),
atls.WithCmc(s.Cmc))
if err != nil {
log.Fatalf("Failed to listen for connections: %v", err)
}
defer ln.Close()

// TODO store verification result

log.Infof("Serving HTTPS under %v", s.Server.Addr)

err = s.Server.Serve(ln)
Expand Down
3 changes: 1 addition & 2 deletions attestedtls/attestation.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,14 +102,13 @@ func attestListener(conn *tls.Conn, chbindings []byte, cc CmcConfig) error {
log.Debug("Skipping server-side attestation")
}

readValue, err := readValue(conn, cc.Attest, false)
report, err := readValue(conn, cc.Attest, false)
if err != nil {
return err
}

// optional: Wait for attestation report from client
if cc.Attest == Attest_Mutual || cc.Attest == Attest_Client {
report := readValue
// Verify AR from dialer with own channel bindings
log.Trace("Verifying attestation report from dialer...")
err = cc.CmcApi.verifyAR(chbindings, report, cc)
Expand Down
15 changes: 10 additions & 5 deletions attestedtls/coap.go
Original file line number Diff line number Diff line change
Expand Up @@ -134,16 +134,21 @@ func (a CoapApi) verifyAR(chbindings, report []byte, cc CmcConfig) error {
}

// Parse VerificationResult
if cc.Result == nil {
cc.Result = new(ar.VerificationResult)
}
err = json.Unmarshal(verifyResp.VerificationResult, cc.Result)
result := new(ar.VerificationResult)
err = json.Unmarshal(verifyResp.VerificationResult, result)
if err != nil {
return fmt.Errorf("could not parse verification result: %w", err)
}

// Return attestation result via callback if specified
if cc.ResultCb != nil {
cc.ResultCb(result)
} else {
log.Tracef("Will not return attestation result: no callback specified")
}

// check results
if !cc.Result.Success {
if !result.Success {
return errors.New("attestation report verification failed")
}

Expand Down
9 changes: 4 additions & 5 deletions attestedtls/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ type CmcConfig struct {
Policies []byte
Mtls bool
Attest AttestSelect
Result *ar.VerificationResult
ResultCb func(result *ar.VerificationResult)
Cmc *cmc.Cmc
}

Expand Down Expand Up @@ -124,11 +124,10 @@ func WithAttest(mAttest string) ConnectionOption[CmcConfig] {
}
}

// WithResult takes an attestation result by reference as input parameter
// and writes the attestation result
func WithResult(result *ar.VerificationResult) ConnectionOption[CmcConfig] {
// WithResultCb is a callback for further processing of attestation results
func WithResultCb(cb func(result *ar.VerificationResult)) ConnectionOption[CmcConfig] {
return func(c *CmcConfig) {
c.Result = result
c.ResultCb = cb
}
}

Expand Down
15 changes: 10 additions & 5 deletions attestedtls/grpc.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,16 +111,21 @@ func (a GrpcApi) verifyAR(chbindings, report []byte, cc CmcConfig) error {
}

// Parse VerificationResult
if cc.Result == nil {
cc.Result = new(ar.VerificationResult)
}
err = json.Unmarshal(resp.GetVerificationResult(), cc.Result)
result := new(ar.VerificationResult)
err = json.Unmarshal(resp.GetVerificationResult(), result)
if err != nil {
return fmt.Errorf("could not parse verification result: %w", err)
}

// Return attestation result via callback if specified
if cc.ResultCb != nil {
cc.ResultCb(result)
} else {
log.Tracef("Will not return attestation result: no callback specified")
}

// check results
if !cc.Result.Success {
if !result.Success {
return errors.New("attestation report verification failed")
}
return nil
Expand Down
7 changes: 5 additions & 2 deletions attestedtls/libapi.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,11 @@ func (a LibApi) verifyAR(chbindings, report []byte, cc CmcConfig) error {
log.Debug("Verifier: Verifying Attestation Report")
result := ar.Verify(report, chbindings, cc.Ca, nil, cc.Cmc.PolicyEngineSelect, cc.Cmc.IntelStorage)

if cc.Result != nil {
*cc.Result = result
// Return attestation result via callback if specified
if cc.ResultCb != nil {
cc.ResultCb(&result)
} else {
log.Tracef("Will not return attestation result: no callback specified")
}

if !result.Success {
Expand Down
5 changes: 4 additions & 1 deletion attestedtls/listener.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,10 @@ func (ln Listener) Accept() (net.Conn, error) {
}

cs := tlsConn.ConnectionState()
log.Tracef("TLS Handshake Complete: %v, generating channel bindings", cs.HandshakeComplete)
if !cs.HandshakeComplete {
return nil, errors.New("internal error: handshake not complete")
}
log.Trace("TLS handshake complete, generating channel bindings")
chbindings, err := cs.ExportKeyingMaterial("EXPORTER-Channel-Binding", nil, 32)
if err != nil {
return nil, fmt.Errorf("failed to export keying material for channel binding: %w", err)
Expand Down
15 changes: 10 additions & 5 deletions attestedtls/socket.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,16 +123,21 @@ func (a SocketApi) verifyAR(chbindings, report []byte, cc CmcConfig) error {
}

// Parse VerificationResult
if cc.Result == nil {
cc.Result = new(ar.VerificationResult)
}
err = json.Unmarshal(verifyResp.VerificationResult, cc.Result)
result := new(ar.VerificationResult)
err = json.Unmarshal(verifyResp.VerificationResult, result)
if err != nil {
return fmt.Errorf("could not parse verification result: %w", err)
}

// Return attestation result via callback if specified
if cc.ResultCb != nil {
cc.ResultCb(result)
} else {
log.Tracef("Will not return attestation result: no callback specified")
}

// Check results
if !cc.Result.Success {
if !result.Success {
return errors.New("attestation report verification failed")
}
return nil
Expand Down
1 change: 1 addition & 0 deletions testtool/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,7 @@ func getConfig() *config {
Api: "grpc",
LogLevel: "info",
IntervalStr: "0s",
Attest: "mutual",
Method: "GET",
}

Expand Down
19 changes: 19 additions & 0 deletions testtool/http.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,12 @@ import (
"io"
"net/http"
"strings"
"sync"
"time"

// local modules

ar "github.com/Fraunhofer-AISEC/cmc/attestationreport"
ahttp "github.com/Fraunhofer-AISEC/cmc/attestedhttp"
atls "github.com/Fraunhofer-AISEC/cmc/attestedtls"
"github.com/Fraunhofer-AISEC/cmc/cmc"
Expand Down Expand Up @@ -101,6 +103,16 @@ func requestInternal(c *config, api atls.CmcApiSelect, cmc *cmc.Cmc) error {
Cmc: cmc,
Ca: c.ca,
CmcPolicies: c.policies,
ResultCb: func(result *ar.VerificationResult) {
// Publish the attestation result asynchronously if publishing address was specified and
// and attestation was performed
if c.Publish != "" && (c.Attest == "mutual" || c.Attest == "server") {
wg := new(sync.WaitGroup)
wg.Add(1)
defer wg.Wait()
go publishResultAsync(c.Publish, result, wg)
}
},
}

// Create an attested HTTPS Client
Expand Down Expand Up @@ -214,6 +226,13 @@ func serveInternal(c *config, api atls.CmcApiSelect, cmc *cmc.Cmc) {
Cmc: cmc,
Ca: c.ca,
CmcPolicies: c.policies,
ResultCb: func(result *ar.VerificationResult) {
if c.Publish != "" && (c.Attest == "mutual" || c.Attest == "client") {
// Publish the attestation result if publishing address was specified
// and result is not empty
go publishResult(c.Publish, result)
}
},
}

// Use the golang net/http module functions to configure the server
Expand Down
4 changes: 4 additions & 0 deletions testtool/publish.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ func publishResultAsync(addr string, result *ar.VerificationResult, wg *sync.Wai

func publishResult(addr string, result *ar.VerificationResult) {

if result == nil {
log.Trace("Will not publish result: not present")
return
}
if result.Prover == "" {
log.Trace("Will not publish result: prover is empty (this happens if connection could not be established)")
return
Expand Down
45 changes: 18 additions & 27 deletions testtool/tls.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ import (
// Creates TLS connection between this client and a server and performs a remote
// attestation of the server before exchanging few a exemplary messages with it
func dialInternalAddr(c *config, api atls.CmcApiSelect, addr string, tlsConf *tls.Config, cmc *cmc.Cmc) error {
verificationResult := new(ar.VerificationResult)

conn, err := atls.Dial("tcp", addr, tlsConf,
atls.WithCmcAddr(c.CmcAddr),
Expand All @@ -45,16 +44,17 @@ func dialInternalAddr(c *config, api atls.CmcApiSelect, addr string, tlsConf *tl
atls.WithMtls(c.Mtls),
atls.WithAttest(c.Attest),
atls.WithCmcNetwork(c.Network),
atls.WithResult(verificationResult),
atls.WithResultCb(func(result *ar.VerificationResult) {
// Publish the attestation result asynchronously if publishing address was specified and
// and attestation was performed
if c.Publish != "" && (c.Attest == "mutual" || c.Attest == "server") {
wg := new(sync.WaitGroup)
wg.Add(1)
defer wg.Wait()
go publishResultAsync(c.Publish, result, wg)
}
}),
atls.WithCmc(cmc))
// Publish the attestation result asynchronously if publishing address was specified and
// and attestation was performed
if c.Publish != "" && (c.Attest == "mutual" || c.Attest == "server") {
wg := new(sync.WaitGroup)
wg.Add(1)
defer wg.Wait()
go publishResultAsync(c.Publish, verificationResult, wg)
}
if err != nil {
return fmt.Errorf("failed to dial server: %v", err)
}
Expand Down Expand Up @@ -181,12 +181,8 @@ func listenInternal(c *config, api atls.CmcApiSelect, cmc *cmc.Cmc) {
Renegotiation: tls.RenegotiateNever,
}

atls.WithAttest(c.Attest)

internal.PrintTlsConfig(tlsConf, c.ca)

verificationResult := new(ar.VerificationResult)

addr := ""
if len(c.Addr) > 0 {
addr = c.Addr[0]
Expand All @@ -201,7 +197,13 @@ func listenInternal(c *config, api atls.CmcApiSelect, cmc *cmc.Cmc) {
atls.WithMtls(c.Mtls),
atls.WithAttest(c.Attest),
atls.WithCmcNetwork(c.Network),
atls.WithResult(verificationResult),
atls.WithResultCb(func(result *ar.VerificationResult) {
if c.Publish != "" && (c.Attest == "mutual" || c.Attest == "client") {
// Publish the attestation result if publishing address was specified
// and result is not empty
go publishResult(c.Publish, result)
}
}),
atls.WithCmc(cmc))
if err != nil {
log.Fatalf("Failed to listen for connections: %v", err)
Expand All @@ -213,23 +215,12 @@ func listenInternal(c *config, api atls.CmcApiSelect, cmc *cmc.Cmc) {
// Accept connection and perform remote attestation
conn, err := ln.Accept()
if err != nil {
log.Errorf("Failed to establish connection: %v", err)
if c.Mtls {
// Publish the attestation result if publishing address was specified
// and result is not empty
go publishResult(c.Publish, verificationResult)
}
log.Warnf("Failed to establish connection: %v", err)
continue
}

// Handle established connections
go handleConnection(conn)

if c.Publish != "" && (c.Attest == "mutual" || c.Attest == "client") {
// Publish the attestation result if publishing address was specified
// and result is not empty
go publishResult(c.Publish, verificationResult)
}
}
}

Expand Down

0 comments on commit e2735bf

Please sign in to comment.