Beispiel #1
0
// Checks the following:
// (1) cert is valid according to one of the rootCerts.
// (2) the subject key of cert corresponds to kPrin.
// (3) the subject CommonName of cert is allowed by guard.
func validateEndorsementCertificate(cert *x509.Certificate, guard tao.Guard,
	kPrin *auth.Prin, rootCerts *x509.CertPool) error {
	verifyOptions := x509.VerifyOptions{Roots: rootCerts}
	_, err := cert.Verify(verifyOptions)
	if err != nil {
		return err
	}
	var hwPublicKey *rsa.PublicKey
	hwPublicKey, ok := cert.PublicKey.(*rsa.PublicKey)
	if !ok {
		key, ok := cert.PublicKey.(rsa.PublicKey)
		if !ok {
			return errors.New("endorsement cert does not contain a valid RSA public key")
		}
		hwPublicKey = &key
	}
	ek, err := x509.MarshalPKIXPublicKey(hwPublicKey)
	if err != nil {
		return err
	}
	hashedCertKey := sha256.Sum256(ek)
	if kPrin.Type != "tpm" && kPrin.Type != "tpm2" {
		return errors.New("key principal to be endorsed is not a TPM key, but it's expected to be")
	}
	hashedBytes, ok := kPrin.KeyHash.(auth.Bytes)
	if !ok {
		return errors.New("key principal to be endorsed does not have bytes as its auth.Term")
	}
	if !bytes.Equal(hashedBytes, hashedCertKey[:]) {
		return errors.New(fmt.Sprintf(
			"endorsement cert endorses %v but needs to endorse %v", hashedCertKey, hashedBytes))
	}
	machinePrin := auth.Prin{
		Type:    "MachineInfo",
		KeyHash: auth.Str(cert.Subject.CommonName),
	}
	if !guard.IsAuthorized(machinePrin, "Root", []string{}) {
		return errors.New(
			"machine endorsed by certificate is not authorized by policy")
	}
	return nil
}
Beispiel #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
}
// First return is terminate flag.
func handleRequest(conn net.Conn, policyKey *tao.Keys, guard tao.Guard) error {
	// Expect an attestation from the client.
	ms := util.NewMessageStream(conn)
	var a tao.Attestation
	if err := ms.ReadMessage(&a); err != nil {
		return err
	}

	peerCert := conn.(*tls.Conn).ConnectionState().PeerCertificates[0]
	p, err := tao.ValidatePeerAttestation(&a, peerCert)
	if err != nil {
		return err
	}
	// TODO(kwalsh) most of this duplicates the work of tao.Conn
	if !guard.IsAuthorized(p, "Execute", nil) {
		return fmt.Errorf("peer is not authorized to execute, hence not authorized to connect either")
	}

	// Sign cert and put it in attestation statement
	// a consists of serialized statement, sig and SignerInfo
	// a is a says speaksfor, Delegate of speaksfor is cert and should be DER encoded

	// Get underlying says
	f, err := auth.UnmarshalForm(a.SerializedStatement)
	if err != nil {
		return err
	}

	var saysStatement *auth.Says
	if ptr, ok := f.(*auth.Says); ok {
		saysStatement = ptr
	} else if val, ok := f.(auth.Says); ok {
		saysStatement = &val
	}
	sf, ok := saysStatement.Message.(auth.Speaksfor)
	if ok != true {
		return fmt.Errorf("keynegoserver: says doesn't have a speaksfor message\n")
	}

	kprin, ok := sf.Delegate.(auth.Prin)
	if ok != true {
		return fmt.Errorf("keynegoserver: speaksfor Delegate is not auth.Prin\n")
	}
	subjectPrin, ok := sf.Delegator.(auth.Prin)
	if ok != true {
		return fmt.Errorf("keynegoserver: can't get subject principal\n")
	}
	subjectName := subjectPrin.String()
	details := &tao.X509Details{
		Country:            proto.String("US"),
		Organization:       proto.String("Google"),
		OrganizationalUnit: proto.String(subjectName),
		CommonName:         proto.String("localhost"),
	}
	subjectname := tao.NewX509Name(details)
	SerialNumber = SerialNumber + 1
	verifier, err := tao.FromPrincipal(kprin)
	if err != nil {
		return errors.New("can't get principal from kprin")
	}
	template := policyKey.SigningKey.X509Template(subjectname)
	template.IsCA = false
	clientCert, err := policyKey.CreateSignedX509(verifier, template, "default")
	if err != nil {
		return fmt.Errorf("keynegoserver: can't create client certificate: %s\n", err)
	}
	clientDERCert := clientCert.Raw
	err = ioutil.WriteFile("ClientCert", clientDERCert, os.ModePerm)

	nowTime := time.Now().UnixNano()
	expireTime := time.Now().AddDate(1, 0, 0).UnixNano()
	// Replace self signed cert in attest request
	newSpeaksFor := &auth.Speaksfor{
		Delegate:  auth.Bytes(clientDERCert),
		Delegator: sf.Delegator,
	}
	keyNegoSays := auth.Says{
		Speaker:    policyKey.SigningKey.ToPrincipal(),
		Time:       &nowTime,
		Expiration: &expireTime,
		Message:    newSpeaksFor,
	}

	delegator, ok := sf.Delegator.(auth.Prin)
	if !ok {
		return fmt.Errorf("keynegoserver: the delegator must be a principal")
	}
	found := false
	for _, sprin := range delegator.Ext {
		if !found && (sprin.Name == "Program") {
			found = true
		}
		if found {
			kprin.Ext = append(kprin.Ext, sprin)
		}
	}
	ra, err := tao.GenerateAttestation(policyKey.SigningKey, nil, keyNegoSays)
	if err != nil {
		return fmt.Errorf("Couldn't attest to the new says statement: %s", err)
	}

	if _, err := ms.WriteMessage(ra); err != nil {
		return fmt.Errorf("Couldn't return the attestation on the channel: %s", err)
	}

	return nil
}