// GenerateAttestation uses the signing key to generate an attestation for this
// statement.
func GenerateAttestation(s *Signer, delegation []byte, stmt auth.Says) (*Attestation, error) {
	signer := s.ToPrincipal()

	t := time.Now()
	if stmt.Time == nil {
		i := t.UnixNano()
		stmt.Time = &i
	}

	if stmt.Expiration == nil {
		i := t.Add(365 * 24 * time.Hour).UnixNano()
		stmt.Expiration = &i
	}

	ser := auth.Marshal(stmt)

	sig, err := s.Sign(ser, AttestationSigningContext)
	if err != nil {
		return nil, err
	}

	a := &Attestation{
		SerializedStatement: ser,
		Signature:           sig,
		Signer:              auth.Marshal(signer),
	}

	if len(delegation) > 0 {
		a.SerializedDelegation = delegation
	}

	return a, nil
}
// This function returns a secret disclosure directive signed by key with the statement:
// 'delegator says delegate predicate protectedObjectId'.
func CreateSecretDisclosureDirective(key *tao.Keys, delegator, delegate *auth.Prin,
	predicate string, protectedObjId *po.ObjectIdMessage) (*DirectiveMessage, error) {

	// Construct serialized 'says' statement.
	serializedObjId, err := proto.Marshal(protectedObjId)
	if err != nil {
		return nil, err
	}
	pred := auth.MakePredicate(predicate, *delegate, serializedObjId)
	statement := auth.Says{
		Speaker:    *delegator,
		Time:       nil, // TODO: For now, time and exp not implemented.
		Expiration: nil,
		Message:    pred,
	}
	serializedStatement := auth.Marshal(statement)

	// Sign serialized statement.
	signature, err := key.SigningKey.Sign(serializedStatement, SigningContext)
	if err != nil {
		return nil, err
	}

	// Construct and return directive.
	directive := &DirectiveMessage{
		Type:                DirectiveMessage_SECRET_DISCLOSURE.Enum(),
		SerializedStatement: serializedStatement,
		Signature:           signature,
		Signer:              auth.Marshal(key.SigningKey.ToPrincipal()),
		Cert:                key.Cert.Raw,
	}
	return directive, nil
}
Exemple #3
0
// Attest requests the Tao host sign a statement on behalf of the caller. The
// optional issuer, time and expiration will be given default values if nil.
func (tt *TPMTao) Attest(issuer *auth.Prin, start, expiration *int64, message auth.Form) (*Attestation, error) {
	if issuer == nil {
		issuer = &tt.name
	} else if !auth.SubprinOrIdentical(*issuer, tt.name) {
		return nil, errors.New("invalid issuer in statement")
	}

	// TODO(tmroeder): we assume here that the PCRs haven't changed (e.g., been
	// extended) since this TPMTao was created. If they have, then the PCRs will
	// be wrong when we extend the principal here with them as the first
	// component. This doesn't matter at the moment, since we don't currently
	// support extending the PCRs or clearing them, but it will need to be
	// changed when we do.
	stmt := auth.Says{
		Speaker:    *issuer,
		Time:       start,
		Expiration: expiration,
		Message:    message,
	}

	// This is done in GenerateAttestation, but the TPM attestation is signed
	// differently, so we do the time calculations here.
	t := time.Now()
	if stmt.Time == nil {
		i := t.UnixNano()
		stmt.Time = &i
	}

	if stmt.Expiration == nil {
		i := t.Add(365 * 24 * time.Hour).UnixNano()
		stmt.Expiration = &i
	}

	ser := auth.Marshal(stmt)
	// TODO(tmroeder): check the pcrVals for sanity once we support extending or
	// clearing the PCRs.
	sig, _, err := tpm.Quote(tt.tpmfile, tt.aikHandle, ser, tt.pcrNums, tt.srkAuth[:])
	if err != nil {
		return nil, err
	}

	// Pull off the extensions from the name to get the bare TPM key for the
	// signer.
	signer := auth.Prin{
		Type: tt.name.Type,
		Key:  tt.name.Key,
	}
	a := &Attestation{
		SerializedStatement: ser,
		Signature:           sig,
		Signer:              auth.Marshal(signer),
	}
	return a, nil
}
Exemple #4
0
// GenerateAttestation uses the signing key to generate an attestation for this
// statement.
func GenerateAttestation(s *Signer, delegation []byte, stmt auth.Says) (*Attestation, error) {
	t := time.Now()
	if stmt.Time == nil {
		i := t.UnixNano()
		stmt.Time = &i
	}

	if stmt.Expiration == nil {
		i := t.Add(365 * 24 * time.Hour).UnixNano()
		stmt.Expiration = &i
	}

	ser := auth.Marshal(stmt)

	sig, err := s.Sign(ser, AttestationSigningContext)
	if err != nil {
		return nil, err
	}

	a := &Attestation{
		SerializedStatement: ser,
		Signature:           sig,
		SignerType:          proto.String("key"),
		SignerKey:           s.GetVerifier().MarshalKey(),
	}

	if len(delegation) > 0 {
		a.SerializedDelegation = delegation
	}

	return a, nil
}
// StopHostedProgram is the client stub for LinuxHost.StopHostedProgram.
func (client LinuxHostAdminClient) StopHostedProgram(subprin auth.SubPrin) error {
	req := &LinuxHostAdminRPCRequest{
		Subprin: auth.Marshal(subprin),
	}
	resp := new(LinuxHostAdminRPCResponse)
	err := client.Call("LinuxHost.StopHostedProgram", req, resp)
	if err != nil {
		return err
	}
	return nil
}
// WaitHostedProgram is the client stub for LinuxHost.WaitHostedProgram.
func (client LinuxHostAdminClient) WaitHostedProgram(pid int, subprin auth.SubPrin) (int, error) {
	req := &LinuxHostAdminRPCRequest{
		Pid:     proto.Int32(int32(pid)),
		Subprin: auth.Marshal(subprin),
	}
	resp := new(LinuxHostAdminRPCResponse)
	err := client.Call("LinuxHost.WaitHostedProgram", req, resp)
	if err != nil {
		return -1, err
	}
	return int(*resp.Status), nil
}
Exemple #7
0
// Attest implements part of the Tao interface.
func (t *RPC) Attest(issuer *auth.Prin, time, expiration *int64, message auth.Form) (*Attestation, error) {
	var issuerBytes []byte
	if issuer != nil {
		issuerBytes = auth.Marshal(*issuer)
	}
	r := &RPCRequest{
		Issuer:     issuerBytes,
		Time:       time,
		Expiration: expiration,
		Data:       auth.Marshal(message),
	}
	bytes, _, err := t.call(t.serviceName+".Attest", r, wantData)
	if err != nil {
		return nil, err
	}
	var a Attestation
	err = proto.Unmarshal(bytes, &a)
	if err != nil {
		return nil, err
	}
	return &a, nil
}
// StartHostedProgram is the server stub for LinuxHost.StartHostedProgram.
func (server linuxHostAdminServerStub) StartHostedProgram(r *LinuxHostAdminRPCRequest, s *LinuxHostAdminRPCResponse) error {
	files := server.oob.SharedFiles()
	defer func() {
		for _, f := range files {
			f.Close()
		}
	}()
	ucred := server.oob.PeerCred()
	if r.Path == nil {
		return newError("missing path")
	}
	spec := HostedProgramSpec{
		Path:          *r.Path,
		Args:          r.Args,
		ContainerArgs: r.ContainerArgs,
		Dir:           *r.Dir,
		Uid:           int(ucred.Uid),
		Gid:           int(ucred.Gid),
	}
	// We do allow superuser here, since we trust the oob credentials
	spec.Superuser = (ucred.Uid == 0 || ucred.Gid == 0)
	if r.Stdin != nil {
		if int(*r.Stdin) >= len(files) {
			return newError("missing stdin")
		}
		spec.Stdin = files[*r.Stdin]
	}
	if r.Stdout != nil {
		if int(*r.Stdout) >= len(files) {
			return newError("missing stdout")
		}
		spec.Stdout = files[*r.Stdout]
	}
	if r.Stderr != nil {
		if int(*r.Stderr) >= len(files) {
			return newError("missing stderr")
		}
		spec.Stderr = files[*r.Stderr]
	}
	subprin, pid, err := server.lh.StartHostedProgram(spec)
	if err != nil {
		return err
	}
	s.Child = make([]*LinuxHostAdminRPCHostedProgram, 1)
	s.Child[0] = &LinuxHostAdminRPCHostedProgram{
		Subprin: auth.Marshal(subprin),
		Pid:     proto.Int32(int32(pid)),
	}
	return nil
}
func (g *DatalogGuard) assert(f auth.Form) error {
	rule, idx, err := g.findRule(f)
	if err != nil {
		return err
	}
	if idx >= 0 {
		return nil
	}
	err = g.dl.Assert(rule)
	if err != nil {
		return err
	}
	g.db.Rules = append(g.db.Rules, auth.Marshal(f))
	return nil
}
// ListHostedPrograms is the server stub for LinuxHost.ListHostedPrograms.
func (server linuxHostAdminServerStub) ListHostedPrograms(r *LinuxHostAdminRPCRequest, s *LinuxHostAdminRPCResponse) error {
	names, pids, err := server.lh.ListHostedPrograms()
	if err != nil {
		return err
	}
	if len(names) != len(pids) {
		return newError("invalid response")
	}
	s.Child = make([]*LinuxHostAdminRPCHostedProgram, len(names))
	for i := range names {
		s.Child[i] = &LinuxHostAdminRPCHostedProgram{
			Subprin: auth.Marshal(names[i]),
			Pid:     proto.Int32(int32(pids[i])),
		}
	}
	return nil
}
Exemple #11
0
// ExtendTaoName implements part of the Tao interface.
func (t *RPC) ExtendTaoName(subprin auth.SubPrin) error {
	r := &RPCRequest{Data: auth.Marshal(subprin)}
	_, _, err := t.call(t.serviceName+".ExtendTaoName", r, wantNothing)
	return err
}
Exemple #12
0
// Attest requests the Tao host seal a statement on behalf of the caller. The
// optional issuer, time and expiration will be given default values if nil.
func (tt *TPM2Tao) Attest(issuer *auth.Prin, start, expiration *int64,
	message auth.Form) (*Attestation, error) {
	fmt.Fprintf(os.Stderr, "About to load the quote key in attest\n")
	qh, err := tt.loadQuote()
	if err != nil {
		return nil, err
	}
	defer tpm2.FlushContext(tt.rw, qh)

	if issuer == nil {
		issuer = &tt.name
	} else if !auth.SubprinOrIdentical(*issuer, tt.name) {
		return nil, errors.New("invalid issuer in statement")
	}

	// TODO(tmroeder): we assume here that the PCRs haven't changed (e.g., been
	// extended) since this TPM2Tao was created. If they have, then the PCRs will
	// be wrong when we extend the principal here with them as the first
	// component. This doesn't matter at the moment, since we don't currently
	// support extending the PCRs or clearing them, but it will need to be
	// changed when we do.
	stmt := auth.Says{
		Speaker:    *issuer,
		Time:       start,
		Expiration: expiration,
		Message:    message,
	}

	// This is done in GenerateAttestation, but the TPM attestation is sealed
	// differently, so we do the time calculations here.
	t := time.Now()
	if stmt.Time == nil {
		i := t.UnixNano()
		stmt.Time = &i
	}

	if stmt.Expiration == nil {
		i := t.Add(365 * 24 * time.Hour).UnixNano()
		stmt.Expiration = &i
	}

	ser := auth.Marshal(stmt)

	var pcrVals [][]byte
	toQuote, err := tpm2.FormatTpm2Quote(ser, tt.pcrs, pcrVals)
	if err != nil {
		return nil, errors.New("Can't format tpm2 Quote")
	}

	// TODO(tmroeder): check the pcrVals for sanity once we support extending or
	// clearing the PCRs.
	quote_struct, sig, err := tpm2.Quote(tt.rw, qh, "", tt.password,
		toQuote, tt.pcrs, uint16(tpm2.AlgTPM_ALG_NULL))
	if err != nil {
		return nil, err
	}
	fmt.Printf("toQuote: %x\n", toQuote)
	fmt.Printf("Quote: %x\n", quote_struct)
	fmt.Printf("sig: %x\n", sig)

	quoteKey, err := x509.MarshalPKIXPublicKey(tt.verifier)
	if err != nil {
		return nil, err
	}

	// TODO(kwalsh) remove Tpm2QuoteStructure from Attestation structure
	a := &Attestation{
		SerializedStatement: ser,
		Signature:           sig,
		SignerType:          proto.String("tpm2"),
		SignerKey:           quoteKey,
		Tpm2QuoteStructure:  quote_struct,
	}

	return a, nil
}
// GetTaoName is the server stub for Tao.GetTaoName.
func (server linuxHostTaoServerStub) GetTaoName(r *RPCRequest, s *RPCResponse) error {
	s.Data = auth.Marshal(server.lh.GetTaoName(server.child))
	return nil
}
// HostName is the server stub for LinuxHost.HostName.
func (server linuxHostAdminServerStub) HostName(r *LinuxHostAdminRPCRequest, s *LinuxHostAdminRPCResponse) error {
	prin := server.lh.HostName()
	s.Prin = auth.Marshal(prin)
	return nil
}
// StartHostedProgram is the server stub for LinuxHost.StartHostedProgram.
func (server linuxHostAdminServerStub) StartHostedProgram(r *LinuxHostAdminRPCRequest, s *LinuxHostAdminRPCResponse) error {
	defer RecoverTPMResources()
	files := server.oob.SharedFiles()
	defer func() {
		for _, f := range files {
			if f != nil {
				f.Close()
			}
		}
	}()
	ucred := server.oob.PeerCred()
	if ucred == nil {
		// TODO(kwalsh): Some kernels don't pass a ucred. Figure this
		// out later...
		ucred = &syscall.Ucred{0, 0, 0}
	}
	if r.Path == nil {
		return newError("missing path")
	}
	spec := HostedProgramSpec{
		Path:          *r.Path,
		Args:          r.Args,
		ContainerType: *r.ContainerType,
		ContainerArgs: r.ContainerArgs,
		Dir:           *r.Dir,
		Uid:           int(ucred.Uid),
		Gid:           int(ucred.Gid),
	}
	// We do allow superuser here, since we trust the oob credentials
	spec.Superuser = (ucred.Uid == 0 || ucred.Gid == 0)
	if r.Stdin != nil {
		if int(*r.Stdin) >= len(files) {
			return newError("missing stdin")
		}
		spec.Stdin = files[*r.Stdin]
		files[*r.Stdin] = nil
	}
	if r.Stdout != nil {
		if int(*r.Stdout) >= len(files) {
			return newError("missing stdout")
		}
		spec.Stdout = files[*r.Stdout]
		files[*r.Stdout] = nil
	}
	if r.Stderr != nil {
		if int(*r.Stderr) >= len(files) {
			return newError("missing stderr")
		}
		spec.Stderr = files[*r.Stderr]
		files[*r.Stderr] = nil
	}
	subprin, pid, err := server.lh.StartHostedProgram(spec)
	if err != nil {
		spec.Cleanup()
		return err
	}
	s.Child = make([]*LinuxHostAdminRPCHostedProgram, 1)
	s.Child[0] = &LinuxHostAdminRPCHostedProgram{
		Subprin: auth.Marshal(subprin),
		Pid:     proto.Int32(int32(pid)),
	}
	return nil
}
func generatePolicyKeyAndSignedDirective(params Params) (*tao.Keys, *DirectiveMessage, error) {
	var programName auth.Term
	if params.Delegate != nil {
		programName = params.Delegate
	} else {
		programName = Delegate
	}
	var serializedObjectId auth.Term
	if params.SerializedObjectId != nil {
		serializedObjectId = params.SerializedObjectId
	} else {
		bytes, err := proto.Marshal(&ProtectedObjectId)
		if err != nil {
			return nil, nil, err
		}
		serializedObjectId = auth.Bytes(bytes)
	}
	terms := []auth.Term{programName, serializedObjectId}
	if params.CanReadTerms != nil {
		terms = params.CanReadTerms
	}
	var canRead auth.Form
	if params.CanRead != nil {
		canRead = params.CanRead
	} else {
		canRead = auth.Pred{
			Name: ReadPredicate,
			Arg:  terms,
		}
	}
	policyKey, err := tao.NewTemporaryKeys(tao.Signing)
	if err != nil {
		return nil, nil, err
	}
	info := x509Info
	name := policyKey.SigningKey.ToPrincipal().String()
	info.CommonName = &name
	subject := tao.NewX509Name(&info)
	policyKey.Cert, err = policyKey.SigningKey.CreateSelfSignedX509(subject)
	if err != nil {
		return nil, nil, err
	}
	var says auth.Form
	if params.Says != nil {
		says = params.Says
	} else {
		says = auth.Says{
			Speaker:    policyKey.SigningKey.ToPrincipal(),
			Time:       nil,
			Expiration: nil,
			Message:    canRead,
		}
	}
	serializedSays := auth.Marshal(says)
	var directiveType *DirectiveMessageDirectiveType
	if params.DirectiveType != nil {
		directiveType = params.DirectiveType
	} else {
		directiveType = DirectiveMessage_SECRET_DISCLOSURE.Enum()
	}
	var signature []byte
	if params.Signature != nil {
		signature = params.Signature
	} else {
		signature, err = policyKey.SigningKey.Sign(serializedSays, SigningContext)
		if err != nil {
			return nil, nil, err
		}
	}
	var signer []byte
	if params.Signer != nil {
		signer = params.Signer
	} else {
		signer = auth.Marshal(policyKey.SigningKey.ToPrincipal())
	}
	directive := &DirectiveMessage{
		Type:                directiveType,
		SerializedStatement: serializedSays,
		Signature:           signature,
		Signer:              signer,
	}
	return policyKey, directive, nil
}
// This function performs the following checks on a secret disclosure directive.
// (1) the directive signature is valid with respect to signerKey of directive
// (2) Either
//       - policyKey matches the signerKey of directive
//       - directive cert is a valid program cert (signed by policyKey) certifying the signerKey
//         of directive as belonging to 'delegator'
// (3) the directive message is a statement of the form:
//         'policyKey/'delegator' says delegate can read protectedObjectId'
//     where delegate is a Tao Principal and protectedObjectId is a (serialized) protected
//     object message id.
func VerifySecretDisclosureDirective(policyKey *tao.Keys, directive *DirectiveMessage) (*auth.Prin,
	*auth.Prin, *string, *po.ObjectIdMessage, error) {

	// Check type of directive
	if directive.Type == nil || *(directive.Type) != DirectiveMessage_SECRET_DISCLOSURE {
		return nil, nil, nil, nil, errors.New(
			"secret_disclosure: directive not of secret disclosure type.")
	}

	var verifier *tao.Verifier
	var delegatorStr string
	// Check directive signer matches policy key.
	if bytes.Compare(
		auth.Marshal(policyKey.SigningKey.ToPrincipal()), directive.GetSigner()) == 0 {
		verifier = policyKey.SigningKey.GetVerifier()
		delegatorStr = verifier.ToPrincipal().String()

	} else {
		// Check if program cert is valid, signed by policy key,
		// cert public key matches signer and cert name matches speaker
		// of says statement.
		cert, err := x509.ParseCertificate(directive.Cert)
		if err != nil {
			return nil, nil, nil, nil, errors.New(
				"error parsing directive program cert")
		}
		rootCert := x509.NewCertPool()
		rootCert.AddCert(policyKey.Cert)
		verifyOptions := x509.VerifyOptions{Roots: rootCert}
		_, err = cert.Verify(verifyOptions)
		if err != nil {
			return nil, nil, nil, nil, errors.New(
				"program cert not valid")
		}
		verifier, err = tao.FromX509(cert)
		delegatorStr = cert.Subject.CommonName
		if err != nil {
			return nil, nil, nil, nil, err
		}
		if bytes.Compare(auth.Marshal(verifier.ToPrincipal()), directive.GetSigner()) != 0 {
			return nil, nil, nil, nil, errors.New(
				"secret_disclosure: directive signer doesn't match program key.")
		}
	}

	// Verify signature.
	ok, err := verifier.Verify(directive.GetSerializedStatement(), SigningContext,
		directive.GetSignature())
	if err != nil {
		return nil, nil, nil, nil, err
	}
	if !ok {
		return nil, nil, nil, nil,
			errors.New("secret_disclosure: directive signature check failed.")
	}

	// Validate and return statement.
	statement, err := auth.UnmarshalForm(directive.GetSerializedStatement())
	if err != nil {
		return nil, nil, nil, nil, err
	}
	var saysStatement *auth.Says
	if ptr, ok := statement.(*auth.Says); ok {
		saysStatement = ptr
	} else if val, ok := statement.(auth.Says); ok {
		saysStatement = &val
	} else {
		return nil, nil, nil, nil,
			errors.New("secret_disclosure: directive statement not a 'Says'")
	}
	stmtSpeaker, ok := saysStatement.Speaker.(auth.Prin)
	if !ok {
		return nil, nil, nil, nil,
			errors.New("secret_disclosure: directive speaker not a 'Prin'")
	}
	if stmtSpeaker.String() != delegatorStr {
		return nil, nil, nil, nil, errors.New(
			"secret_disclosure: directive statement speaker does not match signer")
	}
	pred, ok := saysStatement.Message.(auth.Pred)
	if !ok {
		return nil, nil, nil, nil,
			errors.New("secret_disclosure: directive message not a 'Pred'")
	}
	predName := pred.Name
	if predName == "" {
		return nil, nil, nil, nil,
			errors.New("secret_disclosure: directive predicate name is empty")
	}
	if len(pred.Arg) != 2 {
		return nil, nil, nil, nil,
			errors.New("secret_disclosure: directive predicate doesn't have 2 terms")
	}
	delegateName, ok := pred.Arg[0].(auth.Prin)
	if !ok {
		return nil, nil, nil, nil, errors.New(
			"secret_disclosure: directive delegateName Term not of type auth.Prin.")
	}
	serializedObjId, ok := pred.Arg[1].(auth.Bytes)
	if !ok {
		return nil, nil, nil, nil, errors.New(
			"secret_disclosure: directive ObjId Term not of type []byte.")
	}
	protectedObjId := po.ObjectIdMessage{}
	err = proto.Unmarshal(serializedObjId, &protectedObjId)
	if err != nil {
		return nil, nil, nil, nil, errors.New(
			"secret_disclosure: error deserializing protected ObjId.")
	}
	return &stmtSpeaker, &delegateName, &predName, &protectedObjId, nil
}