Example #1
0
// 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
}