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 }