github.com/jlmucb/cloudproxy@v0.0.0-20170830161738-b5aa0b619bc4/go/tao/ca.go (about)

     1  // Copyright (c) 2014, Google, Inc. All rights reserved.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package tao
    16  
    17  import (
    18  	"errors"
    19  	"fmt"
    20  	"net"
    21  	"os"
    22  
    23  	"github.com/golang/protobuf/proto"
    24  	"github.com/jlmucb/cloudproxy/go/tao/auth"
    25  	"github.com/jlmucb/cloudproxy/go/util"
    26  )
    27  
    28  var errVerifyFailed = errors.New("CARequest: invalid signature")
    29  var errInvalidResponse = errors.New("CARequest: unexpected response")
    30  
    31  // HandleCARequest checks a request from a program and responds with a truncated
    32  // delegation signed by the policy key.
    33  func HandleCARequest(conn net.Conn, s *Signer, guard Guard) {
    34  	defer conn.Close() // TODO(cjpatton) This should be managed by calling function.
    35  
    36  	// Get request.
    37  	ms := util.NewMessageStream(conn)
    38  	var req CARequest
    39  	if err := ms.ReadMessage(&req); err != nil {
    40  		fmt.Fprintln(os.Stderr, "Couldn't read from channel:", err)
    41  		return
    42  	}
    43  
    44  	resp := respond(&req, s, guard)
    45  
    46  	if _, err := ms.WriteMessage(resp); err != nil {
    47  		fmt.Fprintln(os.Stderr, "Couldn't write to the channel:", err)
    48  	}
    49  }
    50  
    51  // Create a response to a request.
    52  func respond(req *CARequest, s *Signer, guard Guard) (resp *CAResponse) {
    53  	resp = new(CAResponse)
    54  	resp.Type = CAType_ERROR.Enum()
    55  
    56  	if *req.Type == CAType_ATTESTATION && req.Attestation != nil {
    57  		truncSays, pe, err := TruncateAttestation(s.ToPrincipal(), req.Attestation)
    58  		if err != nil {
    59  			fmt.Fprintln(os.Stderr, "Couldn't truncate the attestation:", err)
    60  			return
    61  		}
    62  
    63  		// TODO(tmroeder): fix this to check the time and make sure we're not
    64  		// signing an unbounded attestation to this program.
    65  		ra, err := GenerateAttestation(s, nil, truncSays)
    66  		if err != nil {
    67  			fmt.Fprintln(os.Stderr, "Couldn't attest to the new says statement:", err)
    68  			return
    69  		}
    70  
    71  		// Add an endorsement to this PrinExt Program hash so the receiver can check
    72  		// it successfully against policy.
    73  		endorsement := auth.Says{
    74  			Speaker: s.ToPrincipal(),
    75  			Message: auth.Pred{
    76  				Name: "TrustedProgramHash",
    77  				Arg:  []auth.Term{auth.PrinTail{Ext: []auth.PrinExt{pe}}},
    78  			},
    79  		}
    80  		if truncSays.Time != nil {
    81  			i := *truncSays.Time
    82  			endorsement.Time = &i
    83  		}
    84  		if truncSays.Expiration != nil {
    85  			i := *truncSays.Expiration
    86  			endorsement.Expiration = &i
    87  		}
    88  		ea, err := GenerateAttestation(s, nil, endorsement)
    89  		if err != nil {
    90  			fmt.Fprintln(os.Stderr, "Couldn't generate an endorsement for this program:", err)
    91  			return
    92  		}
    93  		eab, err := proto.Marshal(ea)
    94  		if err != nil {
    95  			fmt.Fprintln(os.Stderr, "Couldn't marshal an endorsement:", err)
    96  			return
    97  		}
    98  		ra.SerializedEndorsements = [][]byte{eab}
    99  
   100  		resp.Type = CAType_ATTESTATION.Enum()
   101  		resp.Attestation = ra
   102  
   103  	} else if *req.Type == CAType_DATALOG_POLICY {
   104  		dg, ok := guard.(*DatalogGuard)
   105  		if !ok {
   106  			fmt.Fprintln(os.Stderr, "Requested wrong type")
   107  			return
   108  		}
   109  
   110  		sdb, err := dg.GetSignedDatalogRules(s)
   111  		if err != nil {
   112  			fmt.Fprintf(os.Stderr, "Couldn't get signed datalog rules: %s", err)
   113  			return
   114  		}
   115  
   116  		resp.Type = CAType_DATALOG_POLICY.Enum()
   117  		resp.SignedDatalogRules = sdb
   118  
   119  	} else if *req.Type == CAType_ACL_POLICY {
   120  		ac, ok := guard.(*ACLGuard)
   121  		if !ok {
   122  			fmt.Fprintln(os.Stderr, "Requested wrong type")
   123  			return
   124  		}
   125  
   126  		sdb, err := ac.GetSignedACLSet(s)
   127  		if err != nil {
   128  			fmt.Fprintf(os.Stderr, "Couldn't get signed ACL set: %s", err)
   129  			return
   130  		}
   131  		resp.Type = CAType_ACL_POLICY.Enum()
   132  		resp.SignedAclSet = sdb
   133  
   134  	} else {
   135  		resp.Type = CAType_UNDEFINED.Enum()
   136  	}
   137  
   138  	return
   139  }
   140  
   141  // RequestAttestation connects to a CA and gets an attestation back from it.
   142  // This might be a truncated attestation (in which case, the right next step is
   143  // to verify the truncated attesation, as in RequestTruncatedAttestation), or it
   144  // might be some other kind of attestation (like a KeyNegoServer attestation,
   145  // which provides a policy-key-signed X.509 certificate for the auth name of
   146  // this program).
   147  func RequestAttestation(network, addr string, keys *Keys, v *Verifier) (*Attestation, error) {
   148  
   149  	// Establish connection wtih the CA.
   150  	conn, err := net.Dial(network, addr)
   151  	if err != nil {
   152  		return nil, err
   153  	}
   154  	defer conn.Close()
   155  
   156  	// Create a CARequest.
   157  	req := &CARequest{
   158  		Type:        CAType_ATTESTATION.Enum(),
   159  		Attestation: keys.Delegation,
   160  	}
   161  
   162  	// Tao handshake: send client delegation.
   163  	ms := util.NewMessageStream(conn)
   164  	if _, err = ms.WriteMessage(req); err != nil {
   165  		return nil, err
   166  	}
   167  
   168  	// Read the truncated attestation and check it.
   169  	var resp CAResponse
   170  	if err := ms.ReadMessage(&resp); err != nil {
   171  		return nil, err
   172  	}
   173  
   174  	ok, err := v.Verify(resp.Attestation.SerializedStatement,
   175  		AttestationSigningContext, resp.Attestation.Signature)
   176  	if !ok {
   177  		return nil, errVerifyFailed
   178  	} else if err != nil {
   179  		return nil, err
   180  	}
   181  
   182  	if *resp.Type != CAType_ATTESTATION {
   183  		return nil, errInvalidResponse
   184  	}
   185  
   186  	return resp.Attestation, nil
   187  }
   188  
   189  // RequestTruncatedAttestation connects to a CA instance, sends the attestation
   190  // for an X.509 certificate, and gets back a truncated attestation with a new
   191  // principal name based on the policy key.
   192  func RequestTruncatedAttestation(network, addr string, keys *Keys, v *Verifier) (*Attestation, error) {
   193  	a, err := RequestAttestation(network, addr, keys, v)
   194  	if err != nil {
   195  		return nil, err
   196  	}
   197  
   198  	truncStmt, err := auth.UnmarshalForm(a.SerializedStatement)
   199  	if err != nil {
   200  		return nil, err
   201  	}
   202  
   203  	says, _, err := TruncateAttestation(v.ToPrincipal(), keys.Delegation)
   204  	if err != nil {
   205  		return nil, err
   206  	}
   207  
   208  	if !IdenticalDelegations(says, truncStmt) {
   209  		return nil, fmt.Errorf("the statement returned by the TaoCA was different than what we expected")
   210  	}
   211  
   212  	return a, nil
   213  }
   214  
   215  // RequestDatalogRules requests the policy from a TaoCA running a DatalogGuard.
   216  // Verify the signature with the public policy key `v`.
   217  func RequestDatalogRules(network, addr string, v *Verifier) (*DatalogRules, error) {
   218  
   219  	// Establish connection wtih the CA.
   220  	conn, err := net.Dial(network, addr)
   221  	if err != nil {
   222  		return nil, err
   223  	}
   224  	defer conn.Close()
   225  
   226  	// Create a CArequest.
   227  	req := &CARequest{
   228  		Type: CAType_DATALOG_POLICY.Enum(),
   229  	}
   230  
   231  	// Send request.
   232  	ms := util.NewMessageStream(conn)
   233  	if _, err = ms.WriteMessage(req); err != nil {
   234  		return nil, err
   235  	}
   236  
   237  	// Receive response.
   238  	var resp CAResponse
   239  	if err := ms.ReadMessage(&resp); err != nil {
   240  		return nil, err
   241  	}
   242  
   243  	// Verify signature.
   244  	ok, err := v.Verify(resp.SignedDatalogRules.SerializedRules,
   245  		DatalogRulesSigningContext, resp.SignedDatalogRules.Signature)
   246  	if !ok {
   247  		return nil, errVerifyFailed
   248  	} else if err != nil {
   249  		return nil, err
   250  	}
   251  
   252  	if *resp.Type != CAType_DATALOG_POLICY {
   253  		return nil, errInvalidResponse
   254  	}
   255  
   256  	var db DatalogRules
   257  	if err := proto.Unmarshal(resp.SignedDatalogRules.SerializedRules, &db); err != nil {
   258  		return nil, err
   259  	}
   260  
   261  	return &db, nil
   262  }
   263  
   264  // RequestACLSet requests the policy from a TaoCA running an ACLGuard. Verify
   265  // the signature with the public policy key `v`.
   266  func RequestACLSet(network, addr string, v *Verifier) (*ACLSet, error) {
   267  
   268  	// Establish connection wtih the CA.
   269  	conn, err := net.Dial(network, addr)
   270  	if err != nil {
   271  		return nil, err
   272  	}
   273  	defer conn.Close()
   274  
   275  	// Create a CArequest.
   276  	req := &CARequest{
   277  		Type: CAType_ACL_POLICY.Enum(),
   278  	}
   279  
   280  	// Send request.
   281  	ms := util.NewMessageStream(conn)
   282  	if _, err = ms.WriteMessage(req); err != nil {
   283  		return nil, err
   284  	}
   285  
   286  	// Receive response.
   287  	var resp CAResponse
   288  	if err := ms.ReadMessage(&resp); err != nil {
   289  		return nil, err
   290  	}
   291  
   292  	// Verify signature.
   293  	ok, err := v.Verify(resp.SignedAclSet.SerializedAclset,
   294  		ACLGuardSigningContext, resp.SignedAclSet.Signature)
   295  	if !ok {
   296  		return nil, errVerifyFailed
   297  	} else if err != nil {
   298  		return nil, err
   299  	}
   300  
   301  	if *resp.Type != CAType_ACL_POLICY {
   302  		return nil, errInvalidResponse
   303  	}
   304  
   305  	var db ACLSet
   306  	if err := proto.Unmarshal(resp.SignedAclSet.SerializedAclset, &db); err != nil {
   307  		return nil, err
   308  	}
   309  
   310  	return &db, nil
   311  }