Esempio n. 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
}
Esempio n. 2
0
// Checks the following:
// (1) the endorsement attestation is valid
// (2) the key being endorsed is kPrin
// (3) the subject being endorsed is a trusted host
// Finally the function returns the key principal signing the endorsement
func validateEndorsementAttestation(attestation *tao.Attestation, guard tao.Guard,
	kPrin *auth.Prin) (*auth.Prin, error) {
	saysStatement, err := attestation.Validate()
	if err != nil {
		return nil, err
	}
	_, key, host, err := parseSaysStatement(&saysStatement)
	if err != nil {
		return nil, err
	}
	if !key.Identical(kPrin) {
		return nil, errors.New("endorsement does not endorse signer of (previous) attestaton")
	}
	if !guard.IsAuthorized(*host, "Host", []string{}) {
		return nil, errors.New("endorsement host not authorized to run in this domain")
	}
	signerType := attestation.SignerType
	if signerType == nil {
		return nil, errors.New("endorsement chain has attestation with missing SignerType")
	}
	signerPrin := auth.NewPrin(*signerType, attestation.SignerKey)
	return &signerPrin, nil
}
Esempio n. 3
0
// This function makes the following checks
// (1) Checks if the attestation signature is valid and the statement is of the form
//     'Speaker says Key speaks for Program'.
// (2) Checks that 'Program' in the above statement is allowed to Execute in the domain policy.
//     In particular, the policy should allow the predicate:
//     Authorized(ProgramTaoName, "Execute")
// (3) Checks that 'Speaker' in the above statement is a key principal endorsed by the policy key,
//     or rootCerts, via an endorsement chain. Each endorsement in this chain endorses the key
//     signing the previous endorsement (starting with the 'Speaker' key).
//
//     An endorsement endorses either a host key, in which case it is an attestation,
//     or the root hardware key, in which case it is certificate.
//     This function also checks that each host or root hardware encoutered along this endorsement
//     chain is allowed as per domain policy. In particular the policy should allow the predicates
//     Authorized(HostTaoName, "Host") and Authorized(EncodedMachineInformation, "Root")
//
//     A valid attestation chain must either end in a attestation signed by the policy key
//     or a certificate signed by one of the rootCerts.
//
// If all above checks go through, the function returns the principals: Speaker, Key, Program.
func VerifyHostAttestation(serializedHostAttestation []byte, domain *tao.Domain,
	rootCerts *x509.CertPool) (*auth.Prin, *auth.Prin, *auth.Prin, error) {
	var hostAttestation tao.Attestation
	err := proto.Unmarshal(serializedHostAttestation, &hostAttestation)
	if err != nil {
		return nil, nil, nil, errors.New(
			"domain_service: error deserialiaizng host attestation: " + err.Error())
	}

	// First check if attestation is valid.
	statement, err := hostAttestation.Validate()
	if err != nil {
		return nil, nil, nil, errors.New(
			"host attestation fails validation check: " + err.Error())
	}

	// Next, check if SpeaksFor delegator is authorized to execute (i.e. the program is allowed to
	// run as per policy).
	speaker, key, prog, err := parseSaysStatement(&statement)
	if err != nil {
		return nil, nil, nil, err
	}
	if !domain.Guard.IsAuthorized(*prog, "Execute", []string{}) {
		return nil, nil, nil, errors.New(
			"program not authorized to run in this domain")
	}

	// Look for endorsement cert(s), rooted in the policy key, that ultimately certify the
	// key of the signer.
	signingKey := hostAttestation.GetSignerKey()
	if hostAttestation.SignerType == nil {
		return nil, nil, nil, errors.New("host attestation missing SignerType field")
	}
	signingPrin := auth.NewPrin(*hostAttestation.SignerType, signingKey)
	if !speaker.Identical(signingPrin) {
		// TODO: endorsement endorses speaker or signer?
	}

	// Look for endorsement(s) of signer, rooted in policy key.
	serializedEndorsements := hostAttestation.GetSerializedEndorsements()
	var realErr error
	var kPrin *auth.Prin
	kPrin = &signingPrin
	for _, serializedEndorsement := range serializedEndorsements {
		// serializedEndorsement could be X.509 certificate or Tao attestation.
		var attestation tao.Attestation
		err := proto.Unmarshal(serializedEndorsement, &attestation)
		if err == nil {
			kPrin, realErr = validateEndorsementAttestation(&attestation, domain.Guard, kPrin)
			if realErr != nil {
				return nil, nil, nil, realErr
			}
		} else if cert, err1 := x509.ParseCertificate(serializedEndorsement); err1 == nil {
			realErr = validateEndorsementCertificate(cert, domain.Guard, kPrin, rootCerts)
			if realErr != nil {
				return nil, nil, nil, realErr
			} else {
				// Endorsement certs are the root of the endorsement chain.
				// If they are valid, then no more checking is required.
				return speaker, key, prog, nil
			}

		} else {
			return nil, nil, nil, errors.New("error parsing host endorsement")
		}
	}
	if domain.Keys.SigningKey.ToPrincipal().Identical(*kPrin) {
		return speaker, key, prog, nil
	}
	return nil, nil, nil, errors.New("endorsement chain does not terminate in policy key")

}