// This function helps process a certificate revocation request. // It expects serAtt to be a serialized attestation signed by the domain policy key, // with a statement of the form: // policyKey says revoke certificateSerialNumber // This function gets a list of revoked certificates, updates it if the cert revocation // request is valid, and returns the updated list. func RevokeCertificate(serAtt []byte, revokedCerts []pkix.RevokedCertificate, domain *tao.Domain) ([]pkix.RevokedCertificate, error) { var policyAtt tao.Attestation err := proto.Unmarshal(serAtt, &policyAtt) if err != nil { return revokedCerts, err } if signer, err := policyAtt.ValidSigner(); err != nil { return revokedCerts, err } else if !signer.Identical(domain.Keys.SigningKey.ToPrincipal()) { return revokedCerts, errors.New("revoke cert request not signed by the policy key") } saysStmt, err := policyAtt.Validate() if err != nil { return revokedCerts, err } if saysStmt.Message == nil { return revokedCerts, errors.New("policy attestation 'Says' does not have a message") } pred, ok := saysStmt.Message.(auth.Pred) if !ok { return revokedCerts, errors.New("policy attestation 'Says' does not have a auth.Pred message") } if pred.Name != "revoke" { return revokedCerts, errors.New("policy attestation predicate name is not 'revoke'") } if len(pred.Arg) != 1 { return revokedCerts, errors.New("policy attestation predicate has more or less than one Arg") } serialNumberBytes, ok := pred.Arg[0].(auth.Bytes) if !ok { return revokedCerts, errors.New("policy attestation serial number is not bytes") } serialNumber := new(big.Int) serialNumber.SetBytes(serialNumberBytes) revokedCert := pkix.RevokedCertificate{ SerialNumber: serialNumber, RevocationTime: time.Now()} return append(revokedCerts, revokedCert), nil }