github.com/jlmucb/cloudproxy@v0.0.0-20170830161738-b5aa0b619bc4/go/support_infrastructure/domain_service/domain_service.go (about) 1 // Copyright (c) 2016, 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 // http://www.apache.org/licenses/LICENSE-2.0 7 // Unless required by applicable law or agreed to in writing, software 8 // distributed under the License is distributed on an "AS IS" BASIS, 9 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 // See the License for the specific language governing permissions and 11 // limitations under the License. 12 13 package domain_service 14 15 import ( 16 "bytes" 17 "crypto/rsa" 18 "crypto/sha256" 19 "crypto/x509" 20 "crypto/x509/pkix" 21 "errors" 22 "fmt" 23 "io/ioutil" 24 "log" 25 "math/big" 26 "time" 27 28 "github.com/golang/protobuf/proto" 29 "github.com/jlmucb/cloudproxy/go/tao" 30 "github.com/jlmucb/cloudproxy/go/tao/auth" 31 ) 32 33 func VerifyAttestation(serializedHostAttestation []byte, domain *tao.Domain) (*auth.Prin, 34 *auth.Prin, *auth.Prin, error) { 35 var hostAttestation tao.Attestation 36 err := proto.Unmarshal(serializedHostAttestation, &hostAttestation) 37 if err != nil { 38 return nil, nil, nil, err 39 } 40 signer, err := hostAttestation.ValidSigner() 41 if err != nil { 42 return nil, nil, nil, err 43 } 44 f, err := auth.UnmarshalForm(hostAttestation.SerializedStatement) 45 if err != nil { 46 return nil, nil, nil, err 47 } 48 var stmt *auth.Says 49 if ptr, ok := f.(*auth.Says); ok { 50 stmt = ptr 51 } else if val, ok := f.(auth.Says); ok { 52 stmt = &val 53 } else { 54 return nil, nil, nil, errors.New(fmt.Sprintf( 55 "tao: attestation statement has wrong type: %T", f)) 56 } 57 speaker, key, program, err := parseSaysStatement(stmt) 58 if err != nil { 59 return nil, nil, nil, err 60 } 61 // Validate signer 62 if auth.SubprinOrIdentical(speaker, signer) { 63 // Case 1: speaker is identical or subprincipal of signing principal. 64 // Check if signer is either 65 // - policy key 66 // - TPM key with valid hardware endorsement cert signed by policy key. 67 if signer.Identical(domain.Keys.SigningKey.ToPrincipal()) { 68 return speaker, key, program, nil 69 } 70 if *hostAttestation.SignerType == "tpm" || *hostAttestation.SignerType == "tpm2" { 71 if hostAttestation.RootEndorsement == nil { 72 return nil, nil, nil, errors.New("TPM attestation is missing HW endorsement cert") 73 } 74 cert, err := x509.ParseCertificate(hostAttestation.RootEndorsement) 75 if err != nil { 76 return nil, nil, nil, err 77 } 78 certPool := x509.NewCertPool() 79 certPool.AddCert(domain.Keys.Cert) 80 verifyOptions := x509.VerifyOptions{Roots: certPool} 81 _, err = cert.Verify(verifyOptions) 82 if err != nil { 83 return nil, nil, nil, err 84 } 85 hwPublicKey, ok := cert.PublicKey.(*rsa.PublicKey) 86 if !ok { 87 key, ok := cert.PublicKey.(rsa.PublicKey) 88 if !ok { 89 return nil, nil, nil, 90 errors.New("endorsement cert does not contain a valid RSA public key") 91 } 92 hwPublicKey = &key 93 } 94 tpmKey, err := x509.MarshalPKIXPublicKey(hwPublicKey) 95 if err != nil { 96 return nil, nil, nil, err 97 } 98 if !bytes.Equal(hostAttestation.SignerKey, tpmKey) { 99 return nil, nil, nil, errors.New("HW endorsement cert public key does not match signer key") 100 } 101 return speaker, key, program, nil 102 } 103 // SignerType is a Tao key principal. Check if the key is endorsed by the policy key. 104 if hostAttestation.RootEndorsement != nil { 105 cert, err := x509.ParseCertificate(hostAttestation.RootEndorsement) 106 if err != nil { 107 return nil, nil, nil, err 108 } 109 certPool := x509.NewCertPool() 110 certPool.AddCert(domain.Keys.Cert) 111 verifyOptions := x509.VerifyOptions{Roots: certPool} 112 _, err = cert.Verify(verifyOptions) 113 if err != nil { 114 return nil, nil, nil, err 115 } 116 verifier, err := tao.UnmarshalKey(hostAttestation.SignerKey) 117 if err != nil { 118 return nil, nil, nil, err 119 } 120 if !verifier.KeyEqual(cert) { 121 return nil, nil, nil, errors.New("Endorsement cert is irrelevant to attestation signer") 122 } 123 return speaker, key, program, nil 124 } 125 return nil, nil, nil, errors.New("attestation signer is not endorsed by policy key") 126 } else { 127 // Case 2: speaker is not a subprincipal of the signing principal. 128 // Look for delegation and require that: 129 // - delegation conveys delegator says delegate speaksfor delegator, 130 // - a.signer speaks for delegate 131 // - and delegator speaks for s.Speaker 132 if hostAttestation.SerializedDelegation == nil { 133 return nil, nil, nil, errors.New("attestation missing delegation") 134 } 135 var da tao.Attestation 136 if err := proto.Unmarshal(hostAttestation.SerializedDelegation, &da); err != nil { 137 return nil, nil, nil, err 138 } 139 delegationStatement, err := da.Validate() 140 if err != nil { 141 return nil, nil, nil, err 142 } 143 var delegation *auth.Speaksfor 144 if ptr, ok := delegationStatement.Message.(*auth.Speaksfor); ok { 145 delegation = ptr 146 } else if val, ok := delegationStatement.Message.(auth.Speaksfor); ok { 147 delegation = &val 148 } else { 149 return nil, nil, nil, errors.New("tao: attestation delegation is wrong type") 150 } 151 if !delegationStatement.Speaker.Identical(delegation.Delegator) { 152 return nil, nil, nil, errors.New("tao: attestation delegation is invalid") 153 } 154 if !auth.SubprinOrIdentical(delegation.Delegate, signer) { 155 return nil, nil, nil, errors.New("tao: attestation delegation irrelevant to signer") 156 } 157 if !auth.SubprinOrIdentical(stmt.Speaker, delegation.Delegator) { 158 return nil, nil, nil, errors.New("tao: attestation delegation irrelevant to issuer") 159 } 160 return speaker, key, program, nil 161 } 162 } 163 164 // This function makes the following checks 165 // (1) Checks if the attestation signature is valid and the statement is of the form 166 // 'Speaker says Key speaks for Program'. 167 // (2) Checks that 'Program' in the above statement is allowed to Execute in the domain policy. 168 // In particular, the policy should allow the predicate: 169 // Authorized(ProgramTaoName, "Execute") 170 // (3) Checks that 'Speaker' in the above statement is a key principal endorsed by the policy key, 171 // or rootCerts, via an endorsement chain. Each endorsement in this chain endorses the key 172 // signing the previous endorsement (starting with the 'Speaker' key). 173 // 174 // An endorsement endorses either a host key, in which case it is an attestation, 175 // or the root hardware key, in which case it is certificate. 176 // This function also checks that each host or root hardware encoutered along this endorsement 177 // chain is allowed as per domain policy. In particular the policy should allow the predicates 178 // Authorized(HostTaoName, "Host") and Authorized(EncodedMachineInformation, "Root") 179 // 180 // A valid attestation chain must either end in a attestation signed by the policy key 181 // or a certificate signed by one of the rootCerts. 182 // 183 // If all above checks go through, the function returns the principals: Speaker, Key, Program. 184 func VerifyHostAttestation(serializedHostAttestation []byte, domain *tao.Domain, 185 rootCerts *x509.CertPool) (*auth.Prin, *auth.Prin, *auth.Prin, error) { 186 var hostAttestation tao.Attestation 187 err := proto.Unmarshal(serializedHostAttestation, &hostAttestation) 188 if err != nil { 189 return nil, nil, nil, errors.New( 190 "domain_service: error deserialiaizng host attestation: " + err.Error()) 191 } 192 193 // First check if attestation is valid. 194 statement, err := hostAttestation.Validate() 195 if err != nil { 196 return nil, nil, nil, errors.New( 197 "host attestation fails validation check: " + err.Error()) 198 } 199 200 // Next, check if SpeaksFor delegator is authorized to execute (i.e. the program is allowed to 201 // run as per policy). 202 speaker, key, prog, err := parseSaysStatement(&statement) 203 if err != nil { 204 return nil, nil, nil, err 205 } 206 if !domain.Guard.IsAuthorized(*prog, "Execute", []string{}) { 207 return nil, nil, nil, errors.New( 208 "program not authorized to run in this domain") 209 } 210 211 // Look for endorsement cert(s), rooted in the policy key, that ultimately certify the 212 // key of the signer. 213 signingKey := hostAttestation.GetSignerKey() 214 if hostAttestation.SignerType == nil { 215 return nil, nil, nil, errors.New("host attestation missing SignerType field") 216 } 217 signingPrin := auth.NewPrin(*hostAttestation.SignerType, signingKey) 218 if !speaker.Identical(signingPrin) { 219 // TODO: endorsement endorses speaker or signer? 220 } 221 222 // Look for endorsement(s) of signer, rooted in policy key. 223 serializedEndorsements := hostAttestation.GetSerializedEndorsements() 224 var realErr error 225 var kPrin *auth.Prin 226 kPrin = &signingPrin 227 for _, serializedEndorsement := range serializedEndorsements { 228 // serializedEndorsement could be X.509 certificate or Tao attestation. 229 var attestation tao.Attestation 230 err := proto.Unmarshal(serializedEndorsement, &attestation) 231 if err == nil { 232 kPrin, realErr = validateEndorsementAttestation(&attestation, domain.Guard, kPrin) 233 if realErr != nil { 234 return nil, nil, nil, realErr 235 } 236 } else if cert, err1 := x509.ParseCertificate(serializedEndorsement); err1 == nil { 237 realErr = validateEndorsementCertificate(cert, domain.Guard, kPrin, rootCerts) 238 if realErr != nil { 239 return nil, nil, nil, realErr 240 } else { 241 // Endorsement certs are the root of the endorsement chain. 242 // If they are valid, then no more checking is required. 243 return speaker, key, prog, nil 244 } 245 246 } else { 247 return nil, nil, nil, errors.New("error parsing host endorsement") 248 } 249 } 250 if domain.Keys.SigningKey.ToPrincipal().Identical(*kPrin) { 251 return speaker, key, prog, nil 252 } 253 return nil, nil, nil, errors.New("endorsement chain does not terminate in policy key") 254 255 } 256 257 // Checks the following: 258 // (1) the endorsement attestation is valid 259 // (2) the key being endorsed is kPrin 260 // (3) the subject being endorsed is a trusted host 261 // Finally the function returns the key principal signing the endorsement 262 func validateEndorsementAttestation(attestation *tao.Attestation, guard tao.Guard, 263 kPrin *auth.Prin) (*auth.Prin, error) { 264 saysStatement, err := attestation.Validate() 265 if err != nil { 266 return nil, err 267 } 268 _, key, host, err := parseSaysStatement(&saysStatement) 269 if err != nil { 270 return nil, err 271 } 272 if !key.Identical(kPrin) { 273 return nil, errors.New("endorsement does not endorse signer of (previous) attestaton") 274 } 275 if !guard.IsAuthorized(*host, "Host", []string{}) { 276 return nil, errors.New("endorsement host not authorized to run in this domain") 277 } 278 signerType := attestation.SignerType 279 if signerType == nil { 280 return nil, errors.New("endorsement chain has attestation with missing SignerType") 281 } 282 signerPrin := auth.NewPrin(*signerType, attestation.SignerKey) 283 return &signerPrin, nil 284 } 285 286 // Checks the following: 287 // (1) cert is valid according to one of the rootCerts. 288 // (2) the subject key of cert corresponds to kPrin. 289 // (3) the subject CommonName of cert is allowed by guard. 290 func validateEndorsementCertificate(cert *x509.Certificate, guard tao.Guard, 291 kPrin *auth.Prin, rootCerts *x509.CertPool) error { 292 verifyOptions := x509.VerifyOptions{Roots: rootCerts} 293 _, err := cert.Verify(verifyOptions) 294 if err != nil { 295 return err 296 } 297 var hwPublicKey *rsa.PublicKey 298 hwPublicKey, ok := cert.PublicKey.(*rsa.PublicKey) 299 if !ok { 300 key, ok := cert.PublicKey.(rsa.PublicKey) 301 if !ok { 302 return errors.New("endorsement cert does not contain a valid RSA public key") 303 } 304 hwPublicKey = &key 305 } 306 ek, err := x509.MarshalPKIXPublicKey(hwPublicKey) 307 if err != nil { 308 return err 309 } 310 hashedCertKey := sha256.Sum256(ek) 311 if kPrin.Type != "tpm" && kPrin.Type != "tpm2" { 312 return errors.New("key principal to be endorsed is not a TPM key, but it's expected to be") 313 } 314 hashedBytes, ok := kPrin.KeyHash.(auth.Bytes) 315 if !ok { 316 return errors.New("key principal to be endorsed does not have bytes as its auth.Term") 317 } 318 if !bytes.Equal(hashedBytes, hashedCertKey[:]) { 319 return errors.New(fmt.Sprintf( 320 "endorsement cert endorses %v but needs to endorse %v", hashedCertKey, hashedBytes)) 321 } 322 machinePrin := auth.Prin{ 323 Type: "MachineInfo", 324 KeyHash: auth.Str(cert.Subject.CommonName), 325 } 326 if !guard.IsAuthorized(machinePrin, "Root", []string{}) { 327 return errors.New( 328 "machine endorsed by certificate is not authorized by policy") 329 } 330 return nil 331 } 332 333 func parseSaysStatement(saysStatement *auth.Says) (*auth.Prin, *auth.Prin, *auth.Prin, error) { 334 if saysStatement.Speaker == nil { 335 return nil, nil, nil, 336 errors.New("attestation 'Says' does not have a speaker") 337 } 338 speaker, ok := saysStatement.Speaker.(auth.Prin) 339 if !ok { 340 return nil, nil, nil, errors.New( 341 "attestation 'Says' speaker is not a auth.Prin") 342 } 343 if saysStatement.Message == nil { 344 return nil, nil, nil, errors.New( 345 "attestation 'Says' does not have a message") 346 } 347 sf, ok := saysStatement.Message.(auth.Speaksfor) 348 if !ok { 349 return nil, nil, nil, errors.New( 350 "attestation statement does not have a 'SpeaksFor'") 351 } 352 if sf.Delegator == nil { 353 return nil, nil, nil, errors.New( 354 "attestation 'speaksFor' has no delegator") 355 } 356 delegator, ok := sf.Delegator.(auth.Prin) 357 if !ok { 358 return nil, nil, nil, errors.New( 359 "attestation 'speaksFor' delegator is not a auth.Prin") 360 } 361 if sf.Delegate == nil { 362 return nil, nil, nil, errors.New( 363 "attestation 'speaksFor' has no delegate.") 364 } 365 delegate, ok := sf.Delegate.(auth.Prin) 366 if !ok { 367 return nil, nil, nil, errors.New( 368 "ttestation 'speaksFor' delegate is not a auth.Prin") 369 } 370 return &speaker, &delegate, &delegator, nil 371 } 372 373 // This function generates a Program Certificate. In particular, it generates an attestation 374 // signed by the domain policy key, with a statement of the form 375 // 'policyKey says programCert speaksFor program' 376 // where programCert is a X509 cert signed by the policy key with subject CommonName being the 377 // Tao name of the program and subject public key being programKey. 378 // Certificate expiration time is one year from issuing time. 379 func GenerateProgramCert(domain *tao.Domain, serialNumber int, programPrin *auth.Prin, 380 verifier *tao.Verifier, now, expiry time.Time) (*x509.Certificate, error) { 381 382 policyCert := domain.Keys.Cert 383 x509Info := domain.Config.GetX509Info() 384 programName := programPrin.String() 385 localhost := "localhost" 386 x509Info.CommonName = &localhost 387 x509Info.OrganizationalUnit = &programName 388 subjectName := tao.NewX509Name(x509Info) 389 pkInt := tao.PublicKeyAlgFromSignerAlg(*domain.Keys.SigningKey.Header.KeyType) 390 sigInt := tao.SignatureAlgFromSignerAlg(*domain.Keys.SigningKey.Header.KeyType) 391 clientCert, err := domain.Keys.SigningKey.CreateSignedX509( 392 policyCert, serialNumber, verifier, pkInt, sigInt, subjectName) 393 if err != nil { 394 return nil, err 395 } 396 return clientCert, nil 397 } 398 399 // This function reads in trusted entities from a file at trustedEntitiesPath. In particular, 400 // this file contains the text representation of a trusted_entities proto message, which contains 401 // the Tao names of trusted programs and hosts, information about trusted machines and trusted 402 // machine certificates. 403 // For each such trusted entity, this function adds ACL rules to the domain guard, and saves 404 // the changes before returning. 405 func InitAcls(domain *tao.Domain, trustedEntitiesPath string) error { 406 text, err := ioutil.ReadFile(trustedEntitiesPath) 407 if err != nil { 408 log.Printf("Can't open trusted entities file: %s", trustedEntitiesPath) 409 return err 410 } 411 trustedEntities := TrustedEntities{} 412 err = proto.UnmarshalText(string(text), &trustedEntities) 413 if err != nil { 414 log.Printf("Can't parse trusted entities file: %s", trustedEntitiesPath) 415 return err 416 } 417 for _, programTaoName := range trustedEntities.GetTrustedProgramTaoNames() { 418 var programPrin auth.Prin 419 _, err := fmt.Sscanf(programTaoName, "%v", &programPrin) 420 if err != nil { 421 log.Printf("Can't create program principal from: %s\nError: %s", 422 programTaoName, err) 423 return err 424 } 425 err = domain.Guard.Authorize(programPrin, "Execute", []string{}) 426 if err != nil { 427 log.Printf("Can't authorize principal: %s\nError: %s", programPrin, err) 428 return err 429 } 430 } 431 for _, hostTaoName := range trustedEntities.GetTrustedHostTaoNames() { 432 var hostPrin auth.Prin 433 _, err := fmt.Sscanf(hostTaoName, "%v", &hostPrin) 434 if err != nil { 435 log.Printf("Can't create host principal from: %s\nError: %s", 436 hostTaoName, err) 437 return err 438 } 439 err = domain.Guard.Authorize(hostPrin, "Host", []string{}) 440 if err != nil { 441 log.Printf("Can't authorize principal: %s\nError: %s", hostPrin, err) 442 return err 443 } 444 } 445 for _, machineInfo := range trustedEntities.GetTrustedMachineInfos() { 446 machinePrin := auth.Prin{ 447 Type: "MachineInfo", 448 KeyHash: auth.Str(machineInfo), 449 } 450 err = domain.Guard.Authorize(machinePrin, "Root", []string{}) 451 if err != nil { 452 log.Printf("Can't authorize principal: %s\nError: %s", machinePrin, err) 453 return err 454 } 455 } 456 err = domain.Save() 457 if err != nil { 458 log.Println("Can't save domain.", err) 459 } 460 return err 461 } 462 463 // This function helps process a certificate revocation request. 464 // It expects serAtt to be a serialized attestation signed by the domain policy key, 465 // with a statement of the form: 466 // policyKey says revoke certificateSerialNumber 467 // This function gets a list of revoked certificates, updates it if the cert revocation 468 // request is valid, and returns the updated list. 469 func RevokeCertificate(serAtt []byte, revokedCerts []pkix.RevokedCertificate, 470 domain *tao.Domain) ([]pkix.RevokedCertificate, error) { 471 472 var policyAtt tao.Attestation 473 err := proto.Unmarshal(serAtt, &policyAtt) 474 if err != nil { 475 return revokedCerts, err 476 } 477 if signer, err := policyAtt.ValidSigner(); err != nil { 478 return revokedCerts, err 479 } else if !signer.Identical(domain.Keys.SigningKey.ToPrincipal()) { 480 return revokedCerts, errors.New("revoke cert request not signed by the policy key") 481 } 482 saysStmt, err := policyAtt.Validate() 483 if err != nil { 484 return revokedCerts, err 485 } 486 if saysStmt.Message == nil { 487 return revokedCerts, errors.New("policy attestation 'Says' does not have a message") 488 } 489 pred, ok := saysStmt.Message.(auth.Pred) 490 if !ok { 491 return revokedCerts, 492 errors.New("policy attestation 'Says' does not have a auth.Pred message") 493 } 494 if pred.Name != "revoke" { 495 return revokedCerts, errors.New("policy attestation predicate name is not 'revoke'") 496 } 497 if len(pred.Arg) != 1 { 498 return revokedCerts, 499 errors.New("policy attestation predicate has more or less than one Arg") 500 } 501 serialNumberBytes, ok := pred.Arg[0].(auth.Bytes) 502 if !ok { 503 return revokedCerts, 504 errors.New("policy attestation serial number is not bytes") 505 } 506 serialNumber := new(big.Int) 507 serialNumber.SetBytes(serialNumberBytes) 508 revokedCert := pkix.RevokedCertificate{ 509 SerialNumber: serialNumber, 510 RevocationTime: time.Now()} 511 return append(revokedCerts, revokedCert), nil 512 }