提交 445375dc 编写于 作者: Y YiLin.Li 提交者: jia zhang

rune/libenclave/attestation: Add ias.GetVerifiedReport service

Signed-off-by: NYilin Li <YiLin.Li@linux.alibaba.com>
上级 b27065b4
package attestation // import "github.com/opencontainers/runc/libenclave/attestation"
func (svc *Service) GetVerifiedReport(q []byte) (*Status, map[string]string, error) {
return svc.Attester.GetVerifiedReport(q)
}
......@@ -17,6 +17,7 @@ type Attester interface {
PrepareChallenge() (*pb.AttestChallenge, error)
HandleChallengeResponse(r *pb.AttestResponse) (*Quote, error)
Check([]byte) error
GetVerifiedReport([]byte) (*Status, map[string]string, error)
Verify([]byte) *Status
ShowStatus(status *Status)
}
......
......@@ -187,7 +187,7 @@ func (ias *iasService) Check(q []byte) error {
return nil
}
func (ias *iasService) Verify(quote []byte) *attest.Status {
func (ias *iasService) getIasReport(quote []byte) (*attest.Status, map[string]string, error) {
nonce := strconv.FormatUint(rand.Uint64(), 16) + strconv.FormatUint(rand.Uint64(), 16)
p := &evidencePayload{
IsvEnclaveQuote: base64.StdEncoding.EncodeToString(quote),
......@@ -204,20 +204,36 @@ func (ias *iasService) Verify(quote []byte) *attest.Status {
var err error
if resp, err = ias.reportAttestationEvidence(p); err != nil {
status.ErrorMessage = fmt.Sprintf("%s", err)
return status
return status, nil, err
}
defer resp.Body.Close()
var reportStatus *reportStatus
if reportStatus, err = checkVerificationReport(resp, quote, nonce); err != nil {
reportStatus, rawReport, err := checkVerificationReport(resp, quote, nonce)
if err != nil {
status.ErrorMessage = fmt.Sprintf("%s", err)
return status
return status, nil, err
}
iasReport := formatIasReport(resp, rawReport)
status.SpecificStatus = reportStatus
return status, iasReport, nil
}
func (ias *iasService) Verify(quote []byte) *attest.Status {
status, _, err := ias.getIasReport(quote)
if err != nil {
return nil
}
return status
}
func (ias *iasService) GetVerifiedReport(quote []byte) (*attest.Status, map[string]string, error) {
return ias.getIasReport(quote)
}
func (ias *iasService) ShowStatus(status *attest.Status) {
s, ok := status.SpecificStatus.(*reportStatus)
if ok {
......@@ -279,7 +295,21 @@ func (ias *iasService) reportAttestationEvidence(p *evidencePayload) (*http.Resp
return resp, nil
}
func checkVerificationReport(resp *http.Response, quote []byte, nonce string) (*reportStatus, error) {
func formatIasReport(resp *http.Response, rawReport string) map[string]string {
iasReport := make(map[string]string)
iasReport["Body"] = rawReport
iasReport["StatusCode"] = strconv.FormatUint(uint64(resp.StatusCode), 10)
iasReport["Request-ID"] = resp.Header.Get("Request-ID")
iasReport["X-Iasreport-Signature"] = resp.Header.Get("X-Iasreport-Signature")
iasReport["X-Iasreport-Signing-Certificate"] = resp.Header.Get("X-Iasreport-Signing-Certificate")
iasReport["ContentLength"] = strconv.FormatUint(uint64(resp.ContentLength), 10)
iasReport["Content-Type"] = resp.Header.Get("Content-Type")
return iasReport
}
func checkVerificationReport(resp *http.Response, quote []byte, nonce string) (*reportStatus, string, error) {
status := &reportStatus{
requestId: "",
reportId: "",
......@@ -301,43 +331,43 @@ func checkVerificationReport(resp *http.Response, quote []byte, nonce string) (*
default:
}
return status, fmt.Errorf("%s: %s", resp.Status, errMsg)
return status, "", fmt.Errorf("%s: %s", resp.Status, errMsg)
}
reqId := resp.Header.Get("Request-ID")
if reqId == "" {
return status, fmt.Errorf("No Request-ID in response header")
return status, "", fmt.Errorf("No Request-ID in response header")
}
status.requestId = reqId
if resp.Header.Get("X-Iasreport-Signature") == "" {
return status, fmt.Errorf("No X-Iasreport-Signature in response header")
return status, "", fmt.Errorf("No X-Iasreport-Signature in response header")
}
if resp.Header.Get("X-Iasreport-Signing-Certificate") == "" {
return status, fmt.Errorf("No X-Iasreport-Signing-Certificate in response header")
return status, "", fmt.Errorf("No X-Iasreport-Signing-Certificate in response header")
}
if resp.ContentLength == -1 {
return status, fmt.Errorf("Unknown length of response body")
return status, "", fmt.Errorf("Unknown length of response body")
}
if resp.Header.Get("Content-Type") != "application/json" {
return status, fmt.Errorf("Invalid content type (%s) in response",
return status, "", fmt.Errorf("Invalid content type (%s) in response",
resp.Header.Get("Content-Type"))
}
var err error
rawReport := make([]byte, resp.ContentLength)
if _, err = io.ReadFull(resp.Body, rawReport); err != nil {
return status, fmt.Errorf("Failed to read reponse body (%d-byte): %s",
return status, "", fmt.Errorf("Failed to read reponse body (%d-byte): %s",
resp.ContentLength, err)
}
var report verificationReport
if err = json.Unmarshal(rawReport, &report); err != nil {
return status, fmt.Errorf("Failed to unmarshal attestation verification report: %s: %s",
return status, "", fmt.Errorf("Failed to unmarshal attestation verification report: %s: %s",
rawReport, err)
}
......@@ -346,19 +376,19 @@ func checkVerificationReport(resp *http.Response, quote []byte, nonce string) (*
status.quoteStatus = report.IsvEnclaveQuoteStatus
if report.Version != (uint32)(apiVersion) {
return status, fmt.Errorf("Unsupported attestation API version %d in attesation verification report",
return status, "", fmt.Errorf("Unsupported attestation API version %d in attesation verification report",
report.Version)
}
if report.Nonce != nonce {
return status, fmt.Errorf("Invalid nonce in attestation verification report: %s",
return status, "", fmt.Errorf("Invalid nonce in attestation verification report: %s",
report.Nonce)
}
if report.Id == "" || report.Timestamp == "" ||
report.IsvEnclaveQuoteStatus == "" ||
report.IsvEnclaveQuoteBody == "" {
return status, fmt.Errorf("Required fields in attestation verification report is not present: %s",
return status, "", fmt.Errorf("Required fields in attestation verification report is not present: %s",
string(rawReport))
}
......@@ -366,27 +396,27 @@ func checkVerificationReport(resp *http.Response, quote []byte, nonce string) (*
report.IsvEnclaveQuoteStatus == "CONFIGURATION_NEEDED" {
if report.Version == apiV3 {
if resp.Header.Get("Advisory-Ids") == "" || resp.Header.Get("Advisory-Url") == "" {
return status, fmt.Errorf("Advisory-Ids or Advisory-Url is not present in response header")
return status, "", fmt.Errorf("Advisory-Ids or Advisory-Url is not present in response header")
}
} else if report.Version == apiV4 && (report.AdvisoryIds == "" || report.AdvisoryUrl == nil) {
return status, fmt.Errorf("Advisory-Ids or Advisory-Url is not present in attestation verification report")
return status, "", fmt.Errorf("Advisory-Ids or Advisory-Url is not present in attestation verification report")
}
}
var quoteBody []byte
if quoteBody, err = base64.StdEncoding.DecodeString(report.IsvEnclaveQuoteBody); err != nil {
return status, fmt.Errorf("Invalid isvEnclaveQuoteBody: %s",
return status, "", fmt.Errorf("Invalid isvEnclaveQuoteBody: %s",
report.IsvEnclaveQuoteBody)
}
if len(quoteBody) != intelsgx.QuoteBodyLength+intelsgx.ReportBodyLength {
return status, fmt.Errorf("Invalid length of isvEnclaveQuoteBody: %d-byte",
return status, "", fmt.Errorf("Invalid length of isvEnclaveQuoteBody: %d-byte",
len(quoteBody))
}
for i, v := range quoteBody {
if v != quote[i] {
return status, fmt.Errorf("Unexpected isvEnclaveQuoteBody: %s",
return status, "", fmt.Errorf("Unexpected isvEnclaveQuoteBody: %s",
report.IsvEnclaveQuoteBody)
}
}
......@@ -394,14 +424,14 @@ func checkVerificationReport(resp *http.Response, quote []byte, nonce string) (*
var sig []byte
if sig, err = base64.StdEncoding.DecodeString(
resp.Header.Get("X-Iasreport-Signature")); err != nil {
return status, fmt.Errorf("Invalid X-Iasreport-Signature in response header: %s",
return status, "", fmt.Errorf("Invalid X-Iasreport-Signature in response header: %s",
resp.Header.Get("X-Iasreport-Signature"))
}
var pemCerts string
if pemCerts, err = url.QueryUnescape(
resp.Header.Get("X-Iasreport-Signing-Certificate")); err != nil {
return status, fmt.Errorf("Failed to unescape X-Iasreport-Signing-Certificate in response header: %s: %s",
return status, "", fmt.Errorf("Failed to unescape X-Iasreport-Signing-Certificate in response header: %s: %s",
resp.Header.Get("X-Iasreport-Signing-Certificate"), err)
}
......@@ -413,7 +443,7 @@ func checkVerificationReport(resp *http.Response, quote []byte, nonce string) (*
var b *pem.Block
if b, rawPemCerts = pem.Decode(rawPemCerts); err != nil {
return status, fmt.Errorf("Failed to convert PEM certificate to DER format: %s: %s",
return status, "", fmt.Errorf("Failed to convert PEM certificate to DER format: %s: %s",
pemCerts, err)
}
......@@ -422,7 +452,7 @@ func checkVerificationReport(resp *http.Response, quote []byte, nonce string) (*
}
if b.Type != "CERTIFICATE" {
return status, fmt.Errorf("Returned content is not PEM certificate: %s",
return status, "", fmt.Errorf("Returned content is not PEM certificate: %s",
b.Type)
}
......@@ -431,25 +461,25 @@ func checkVerificationReport(resp *http.Response, quote []byte, nonce string) (*
var x509Certs []*x509.Certificate
if x509Certs, err = x509.ParseCertificates(derCerts); err != nil {
return status, fmt.Errorf("Failed to parse certificates: %s", err)
return status, "", fmt.Errorf("Failed to parse certificates: %s", err)
}
cert := x509Certs[0]
if err = cert.CheckSignature(x509.SHA256WithRSA, rawReport, sig); err != nil {
return status, fmt.Errorf("Failed to verify the attestation verification report: %s",
return status, "", fmt.Errorf("Failed to verify the attestation verification report: %s",
err)
}
for _, parentCert := range x509Certs[1:] {
if err = cert.CheckSignatureFrom(parentCert); err != nil {
return status, fmt.Errorf("Failed to verify the certificate (%s) with parent certificate (%s): %s",
return status, "", fmt.Errorf("Failed to verify the certificate (%s) with parent certificate (%s): %s",
cert.Subject.String(), parentCert.Subject.String(), err)
}
cert = parentCert
}
return status, nil
return status, string(rawReport), nil
}
func init() {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册