From 2ba527f190e3a3b322d86b5e82387ab53610bb48 Mon Sep 17 00:00:00 2001 From: Ian Oliver Date: Sun, 12 Nov 2023 20:26:45 +0200 Subject: [PATCH] Added called parameters to claim header. Allows use of nonce --- ga10/operations/attestation.go | 4 +-- ga10/protocols/a10httprestv2/public.go | 38 +++++++++++------------- ga10/protocols/netconfprotocol/public.go | 17 ++++++++--- ga10/protocols/nullprotocol/public.go | 15 ++++++++-- ga10/services/webui/templates/claim.html | 2 ++ ga10/structures/claims.go | 11 ++++--- ga10/structures/protocols.go | 2 +- 7 files changed, 55 insertions(+), 34 deletions(-) diff --git a/ga10/operations/attestation.go b/ga10/operations/attestation.go index b4becb08..5ef10a93 100644 --- a/ga10/operations/attestation.go +++ b/ga10/operations/attestation.go @@ -46,7 +46,7 @@ func Attest(element structures.Element, policy structures.Policy, session struct // Step 3 ****************************************************** aCALL := protocolObject.CallFunction - returnedBody,bodytype := aCALL( element, policy, session, aps ) + returnedBody, ips, bodytype := aCALL( element, policy, session, aps ) if bodytype == "*ERROR" { body["ERROR"] = returnedBody @@ -62,7 +62,7 @@ func Attest(element structures.Element, policy structures.Policy, session struct // NB: we have body and bodytype from above timing := structures.Timing{ claimTimerStart, claimTimerFinish } - header := structures.ClaimHeader{element, policy, session, timing} + header := structures.ClaimHeader{element, policy, session, timing, aps, ips} footer,_ := hashAndSignClaim(hashablePartClaim{ bodytype, header, body }) c := structures.Claim{ "", bodytype, header, body, footer } diff --git a/ga10/protocols/a10httprestv2/public.go b/ga10/protocols/a10httprestv2/public.go index 83fd7c4f..e57710d6 100644 --- a/ga10/protocols/a10httprestv2/public.go +++ b/ga10/protocols/a10httprestv2/public.go @@ -25,16 +25,14 @@ func Registration() structures.Protocol { // It returns a "json" structure and a string with the body type. // If requestFromTA returns and error, then it is encoded here and returned. // The body type is *ERROR in these situations and the body should have a field "error": -func Call(e structures.Element, p structures.Policy, s structures.Session, aps map[string]interface{}) (map[string]interface{}, string) { - rtn, err := requestFromTA(e, p, s, aps) +func Call(e structures.Element, p structures.Policy, s structures.Session, aps map[string]interface{}) (map[string]interface{}, map[string]interface{}, string) { + rtn, ips, err := requestFromTA(e, p, s, aps) if err != nil { - //rtn["error"] = structures.ClaimError{ "error", err.Error() } rtn["error"] = err.Error() - - return rtn, structures.CLAIMERROR + return rtn, ips, structures.CLAIMERROR } else { - return rtn, p.Intent + return rtn, ips, p.Intent } } @@ -51,7 +49,7 @@ func mergeMaps(m1 map[string]interface{}, m2 map[string]interface{}) map[string] // This function performs the actual interaction with the TA // This will be highly specific to the actual protocol and its implemented intents -func requestFromTA(e structures.Element, p structures.Policy, s structures.Session, aps map[string]interface{}) (map[string]interface{}, error) { +func requestFromTA(e structures.Element, p structures.Policy, s structures.Session, aps map[string]interface{}) (map[string]interface{}, map[string]interface{}, error) { var empty map[string]interface{} = make(map[string]interface{}) // this is an *instantiated* empty map used for error situations var bodymap map[string]interface{} // this is used to store the result of the final unmarshalling of the body received from the TA @@ -97,13 +95,13 @@ func requestFromTA(e structures.Element, p structures.Policy, s structures.Sessi // merge ips with policy parameters. The policy parameters take precidence pps := mergeMaps(ips, p.Parameters) - cps := mergeMaps(pps, aps) + cps := mergeMaps(pps, aps) // this is the final set of call parameters and should be returned to be part of the claim // Construct the call postbody, err := json.Marshal(cps) if err != nil { - return empty, fmt.Errorf("JSON Marshalling failed: %w", err) + return empty, cps, fmt.Errorf("JSON Marshalling failed: %w", err) } url := e.Endpoint + "/" + p.Intent @@ -113,7 +111,7 @@ func requestFromTA(e structures.Element, p structures.Policy, s structures.Sessi resp, err := client.Do(req) if err != nil { - return empty, err // err will be the error from http.client.Do + return empty, cps, err // err will be the error from http.client.Do } defer resp.Body.Close() @@ -126,38 +124,38 @@ func requestFromTA(e structures.Element, p structures.Policy, s structures.Sessi fmt.Println("*****************") if err != nil { - return empty, fmt.Errorf("JSON Unmarshalling reponse from TA: %w", err) + return empty, cps, fmt.Errorf("JSON Unmarshalling reponse from TA: %w", err) } if resp.Status != "200 OK" { // is it always 200 ? This might cause issues later if the TA reponds otherwise! - return bodymap, fmt.Errorf("TA reports error %v with response %v", resp.Status, taResponse) + return bodymap, cps, fmt.Errorf("TA reports error %v with response %v", resp.Status, taResponse) } if p.Intent == "tpm2/quote" { quoteValue, ok := bodymap["quote"] if !ok { - return bodymap, fmt.Errorf("missing quote data in response") + return bodymap, cps, fmt.Errorf("missing quote data in response") } quoteStr, ok := quoteValue.(string) if !ok { - return bodymap, fmt.Errorf("quote value is not a string") + return bodymap, cps, fmt.Errorf("quote value is not a string") } quoteBytes, err := base64.StdEncoding.DecodeString(quoteStr) if err != nil { - return nil, fmt.Errorf("could not base64 decode quote") + return nil, cps, fmt.Errorf("could not base64 decode quote") } signatureValue, ok := bodymap["signature"] if !ok { - return bodymap, fmt.Errorf("missing signature data in response") + return bodymap, cps, fmt.Errorf("missing signature data in response") } signatureStr, ok := signatureValue.(string) if !ok { - return bodymap, fmt.Errorf("signature value is not a string") + return bodymap, cps, fmt.Errorf("signature value is not a string") } signatureBytes, err := base64.StdEncoding.DecodeString(signatureStr) if err != nil { - return nil, fmt.Errorf("could not base64 decode signature") + return nil, cps, fmt.Errorf("could not base64 decode signature") } var attestableData utilities.AttestableData @@ -166,11 +164,11 @@ func requestFromTA(e structures.Element, p structures.Policy, s structures.Sessi // Try to parse the quote into a map representation for display purposes parsed, err := attestableData.Parse() if err != nil { - return bodymap, err + return bodymap, cps, err } bodymap["parsed"] = parsed } - return bodymap, nil + return bodymap, cps, nil } diff --git a/ga10/protocols/netconfprotocol/public.go b/ga10/protocols/netconfprotocol/public.go index 673e39a9..21aba8fe 100644 --- a/ga10/protocols/netconfprotocol/public.go +++ b/ga10/protocols/netconfprotocol/public.go @@ -3,10 +3,12 @@ package netconfprotocol import( "fmt" "log" + "crypto/rand" "a10/structures" ) +const nonceSize int = 32 func Registration() (structures.Protocol) { intents := []string{"null/good","null/test"} @@ -14,7 +16,7 @@ func Registration() (structures.Protocol) { return structures.Protocol{"A10NETCONF","POC protocol module for NetConf",Call, intents} } -func Call(e structures.Element, p structures.Policy, s structures.Session, cps map[string]interface{}) (map[string]interface{}, string) { +func Call(e structures.Element, p structures.Policy, s structures.Session, cps map[string]interface{}) (map[string]interface{}, map[string]interface{},string) { // Create a test body @@ -23,7 +25,14 @@ func Call(e structures.Element, p structures.Policy, s structures.Session, cps m "calling": fmt.Sprintf("with protocol %v I would send an intent to %v",e.Protocol,p.Intent), "aNumber": 42, } - + + nce := make([]byte, nonceSize) + _, _ = rand.Read(nce) + + ips := map[string]interface{}{ + "nonce":nce, + } + // Check if the policy intent was null/null, if so then return with the bodytype being set to null/test // or error if the above is false. // @@ -32,10 +41,10 @@ func Call(e structures.Element, p structures.Policy, s structures.Session, cps m if p.Intent=="null/null" { log.Println(" null call worked ") rtn["worked"] = true - return rtn,"null/test" + return rtn,ips,"null/test" } else { log.Println(" null call bad error ") rtn["error"] = "Error here" - return rtn,structures.CLAIMERROR + return rtn,ips,structures.CLAIMERROR } } \ No newline at end of file diff --git a/ga10/protocols/nullprotocol/public.go b/ga10/protocols/nullprotocol/public.go index c3bbb453..fc4861d1 100644 --- a/ga10/protocols/nullprotocol/public.go +++ b/ga10/protocols/nullprotocol/public.go @@ -3,10 +3,12 @@ package nullprotocol import( "fmt" "log" + "crypto/rand" "a10/structures" ) +const nonceSize int = 32 func Registration() (structures.Protocol) { intents := []string{"*/*"} @@ -14,7 +16,7 @@ func Registration() (structures.Protocol) { return structures.Protocol{"A10NULLPROTOCOL","Testing protocol, always returns a test claim",Call, intents} } -func Call(e structures.Element, p structures.Policy, s structures.Session, cps map[string]interface{}) (map[string]interface{}, string) { +func Call(e structures.Element, p structures.Policy, s structures.Session, cps map[string]interface{}) (map[string]interface{}, map[string]interface{}, string) { // Create a test body @@ -24,6 +26,13 @@ func Call(e structures.Element, p structures.Policy, s structures.Session, cps m "aNumber": 42, } + nce := make([]byte, nonceSize) + _, _ = rand.Read(nce) + + ips := map[string]interface{}{ + "nonce":nce, + } + // Check if the policy intent was null/null, if so then return with the bodytype being set to null/test // or error if the above is false. // @@ -32,10 +41,10 @@ func Call(e structures.Element, p structures.Policy, s structures.Session, cps m if p.Intent=="null/null" { log.Println(" null call worked ") rtn["worked"] = true - return rtn,"null/test" + return rtn,ips,"null/test" } else { log.Println(" null call bad error ") rtn["error"] = "Error here" - return rtn,structures.CLAIMERROR + return rtn,ips,structures.CLAIMERROR } } \ No newline at end of file diff --git a/ga10/services/webui/templates/claim.html b/ga10/services/webui/templates/claim.html index e36180f4..ad9e421c 100644 --- a/ga10/services/webui/templates/claim.html +++ b/ga10/services/webui/templates/claim.html @@ -23,6 +23,8 @@
Header
Policy {{ .Header.Policy.Name }} -- Intent {{ .Header.Policy.Intent }} Session {{ .Header.Session.ItemID }} + Additional Parameters {{ .Header.AdditionalParameters }} + Call Parameters {{ .Header.CallParameters }} Requested {{ epochToUTC .Header.Timing.Requested }} Received {{ epochToUTC .Header.Timing.Received }} diff --git a/ga10/structures/claims.go b/ga10/structures/claims.go index 652ef9e3..6e7fd8e9 100644 --- a/ga10/structures/claims.go +++ b/ga10/structures/claims.go @@ -12,10 +12,13 @@ type Claim struct { type ClaimHeader struct { - Element Element `json:"element",bson:"element"` - Policy Policy `json:"policy",bson:"policy"` - Session Session `json:"session",bson:"session"` - Timing Timing `json:"timing",bson:"timing"` + Element Element `json:"element",bson:"element"` + Policy Policy `json:"policy",bson:"policy"` + Session Session `json:"session",bson:"session"` + Timing Timing `json:"timing",bson:"timing"` + AdditionalParameters map[string]interface{} `json:"aps",bson:"aps"` + CallParameters map[string]interface{} `json:"cps",bson:"cps"` + } type Timing struct { diff --git a/ga10/structures/protocols.go b/ga10/structures/protocols.go index 7a532968..911b7050 100644 --- a/ga10/structures/protocols.go +++ b/ga10/structures/protocols.go @@ -4,7 +4,7 @@ package structures // // In useage it takes the element, policy, session and a "json" structure of parameters // Return is "json" and a string containing any error messages -type ProtocolCall func(Element, Policy, Session, map[string]interface{}) (map[string]interface{}, string) +type ProtocolCall func(Element, Policy, Session, map[string]interface{}) (map[string]interface{}, map[string]interface{}, string) type Protocol struct {