github.com/jlmucb/cloudproxy@v0.0.0-20170830161738-b5aa0b619bc4/go/support_libraries/tao_support/taosupport.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 // 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 // File: taosupport.go 14 15 package tao_support 16 17 import ( 18 "bytes" 19 "crypto/tls" 20 "crypto/x509" 21 "encoding/pem" 22 "errors" 23 "fmt" 24 "io/ioutil" 25 "log" 26 "os" 27 "path" 28 "strings" 29 30 "github.com/golang/protobuf/proto" 31 32 "github.com/jlmucb/cloudproxy/go/support_infrastructure/domain_service" 33 "github.com/jlmucb/cloudproxy/go/support_libraries/domain_policy" 34 "github.com/jlmucb/cloudproxy/go/tao" 35 "github.com/jlmucb/cloudproxy/go/tao/auth" 36 "github.com/jlmucb/cloudproxy/go/util" 37 ) 38 39 type TaoProgramData struct { 40 // true after initialization. 41 Initialized bool 42 43 // Program name. 44 TaoName string 45 46 // DER encoded policy cert for domain. 47 PolicyCert []byte 48 49 // Program Signing key. 50 ProgramSigningKey *tao.Signer 51 52 // Program Crypting Key. 53 ProgramCryptingKey *tao.Crypter 54 55 // Delegation 56 Delegation *tao.Attestation 57 58 // Program Cert. 59 ProgramCert []byte 60 61 // Cert Chain 62 CertChain [][]byte 63 64 // Path for program to read and write files. 65 ProgramFilePath *string 66 } 67 68 // This is not used now but Cloudproxy principals are in the Organization name. 69 func PrincipalNameFromDERCert(derCert []byte) *string { 70 cert, err := x509.ParseCertificate(derCert) 71 if err != nil { 72 log.Printf("PrincipalNameFromDERCert: Can't get name from certificate\n") 73 return nil 74 } 75 var name string 76 if len(cert.Subject.Organization) > 0 && cert.Subject.Organization[0] != "" { 77 name = cert.Subject.Organization[0] 78 } else { 79 name = cert.Subject.CommonName 80 } 81 return &name 82 } 83 84 func (pp *TaoProgramData) ClearTaoProgramData() { 85 pp.Initialized = false 86 tao.ZeroBytes([]byte(pp.TaoName)) 87 tao.ZeroBytes(pp.PolicyCert) 88 if pp.ProgramSigningKey != nil { 89 // TODO(manferdelli): find out how to clear signingkey. 90 // tao.ZeroBytes([]byte(*pp.ProgramKey)) 91 } 92 if pp.ProgramCryptingKey != nil { 93 // TODO(manferdelli): find out how to clear signingkey. 94 } 95 tao.ZeroBytes(pp.ProgramCert) 96 pp.ProgramFilePath = nil 97 } 98 99 // RequestDomainServiceCert requests the signed Program Cert from SimpleDomainService 100 func RequestDomainServiceCert(network, addr string, requestingKey *tao.Signer, 101 requestorCert *x509.Certificate, delegation *tao.Attestation, 102 v *tao.Verifier) (*domain_policy.DomainCertResponse, error) { 103 104 tlsCert, err := EncodeTLSCertFromSigner(requestingKey, requestorCert) 105 if err != nil { 106 return nil, err 107 } 108 conn, err := tls.Dial(network, addr, &tls.Config{ 109 RootCAs: x509.NewCertPool(), 110 Certificates: []tls.Certificate{*tlsCert}, 111 InsecureSkipVerify: true, 112 }) 113 if err != nil { 114 return nil, err 115 } 116 defer conn.Close() 117 118 var request domain_policy.DomainCertRequest 119 request.Attestation, err = proto.Marshal(delegation) 120 if err != nil { 121 return nil, err 122 } 123 request.KeyType = requestingKey.Header.KeyType 124 request.SubjectPublicKey, err = requestingKey.CanonicalKeyBytesFromSigner() 125 if err != nil { 126 return nil, err 127 } 128 129 // Tao handshake: send client delegation. 130 ms := util.NewMessageStream(conn) 131 _, err = ms.WriteMessage(&request) 132 if err != nil { 133 return nil, err 134 } 135 136 // Read the new cert 137 var response domain_policy.DomainCertResponse 138 err = ms.ReadMessage(&response) 139 if err != nil { 140 return nil, err 141 } 142 return &response, nil 143 } 144 145 func SealMaterial(material []byte) ([]byte, error) { 146 return tao.Parent().Seal(material, tao.SealPolicyDefault) 147 } 148 149 func UnsealMaterial(material []byte) ([]byte, error) { 150 unsealed, _, err := tao.Parent().Unseal(material) 151 return unsealed, err 152 } 153 154 func SerializeProgramData(programData *TaoProgramData) ([]byte, error) { 155 var pd SavedProgramData 156 pd.FilePath = programData.ProgramFilePath 157 pd.PolicyCert = programData.PolicyCert 158 pd.ProgramName = &programData.TaoName 159 pd.CryptoSuite = &tao.TaoCryptoSuite 160 pd.SignerCertChain = append(pd.SignerCertChain, programData.ProgramCert) 161 for i := 0; i < len(programData.CertChain); i++ { 162 pd.SignerCertChain = append(pd.SignerCertChain, programData.CertChain[i]) 163 } 164 sck, err := tao.CryptoKeyFromSigner(programData.ProgramSigningKey) 165 if err != nil { 166 return nil, errors.New("Can't get CryptoKey from signer") 167 } 168 cck, err := tao.CryptoKeyFromCrypter(programData.ProgramCryptingKey) 169 if err != nil { 170 return nil, errors.New("Can't get CryptoKey from crypter") 171 } 172 pd.SigningKeyBlob = tao.MarshalCryptoKey(*sck) 173 pd.CryptingKeyBlob = tao.MarshalCryptoKey(*cck) 174 pd.Delegation, err = proto.Marshal(programData.Delegation) 175 if err != nil { 176 return nil, errors.New("Can't marshal delegation") 177 } 178 unsealed, err := proto.Marshal(&pd) 179 if err != nil { 180 return nil, errors.New("Can't marshal SavedProgramData") 181 } 182 sealed, err := SealMaterial(unsealed) 183 if err != nil { 184 return nil, errors.New("Can't seal marshalled SavedProgramData") 185 } 186 return sealed, nil 187 } 188 189 func SaveProgramData(fileName string, programObject *TaoProgramData) error { 190 b, err := SerializeProgramData(programObject) 191 if err != nil { 192 return errors.New("Can't SerializeProgramData") 193 } 194 err = ioutil.WriteFile(fileName, b, os.ModePerm) 195 if err != nil { 196 return errors.New("Error writing program data") 197 } 198 certFileName := fileName + "_cert" 199 err = ioutil.WriteFile(certFileName, []byte(programObject.ProgramCert), os.ModePerm) 200 if err != nil { 201 return errors.New("Error writing cert") 202 } 203 return nil 204 } 205 206 func InitProgramKeys(d *tao.Domain, caAddr string, useSimpleDomainService bool, 207 programData *TaoProgramData) error { 208 signerKeyType := tao.SignerTypeFromSuiteName(tao.TaoCryptoSuite) 209 if signerKeyType == nil { 210 return errors.New(fmt.Sprintln("InitProgramKeys: Can't get signer type\n")) 211 } 212 crypterKeyType := tao.CrypterTypeFromSuiteName(tao.TaoCryptoSuite) 213 if crypterKeyType == nil { 214 return errors.New(fmt.Sprintln("InitProgramKeys: Can't get crypter type\n")) 215 } 216 symTotalKeySize := tao.CombinedKeySizeFromAlgorithmName(*crypterKeyType) 217 if symTotalKeySize == nil { 218 return errors.New(fmt.Sprintln("InitProgramKeys: Can't get crypto suite crypter size\n")) 219 } 220 keyName := path.Join(programData.TaoName, "_Signer") 221 keyEpoch := int32(1) 222 keyPurpose := "signing" 223 keyStatus := "active" 224 sck := tao.GenerateCryptoKey(*signerKeyType, &keyName, &keyEpoch, &keyPurpose, &keyStatus) 225 if sck == nil { 226 return errors.New("InitProgramKeys: Can't generate signer\n") 227 } 228 programData.ProgramSigningKey = tao.SignerFromCryptoKey(*sck) 229 keyName = path.Join(programData.TaoName, "_Crypter") 230 keyPurpose = "crypting" 231 cck := tao.GenerateCryptoKey(*crypterKeyType, &keyName, &keyEpoch, &keyPurpose, &keyStatus) 232 if cck == nil { 233 return errors.New("InitProgramKeys: Can't generate crypter\n") 234 } 235 programData.ProgramCryptingKey = tao.CrypterFromCryptoKey(*cck) 236 237 self, err := tao.Parent().GetTaoName() 238 if err != nil { 239 return err 240 } 241 242 publicString := strings.Replace(self.String(), "(", "", -1) 243 publicString = strings.Replace(publicString, ")", "", -1) 244 245 // publicString is now a canonicalized Tao Principal name 246 us := "US" 247 google := "Google" 248 details := tao.X509Details{ 249 Country: &us, 250 Organization: &google, 251 CommonName: &publicString} 252 subjectname := tao.NewX509Name(&details) 253 254 pkInt := tao.PublicKeyAlgFromSignerAlg(*signerKeyType) 255 sigInt := tao.SignatureAlgFromSignerAlg(*signerKeyType) 256 257 requestorCert, err := programData.ProgramSigningKey.CreateSelfSignedX509(pkInt, sigInt, int64(1), subjectname) 258 if err != nil { 259 return err 260 } 261 262 // Construct statement: "ProgramKey speaksfor Principal Name" 263 // ToPrincipal retrieves key's Tao Principal Name. 264 s := &auth.Speaksfor { 265 Delegate: programData.ProgramSigningKey.ToPrincipal(), 266 Delegator: self, 267 } 268 if s == nil { 269 return errors.New("Can't produce speaksfor") 270 } 271 272 // Sign attestation statement 273 programData.Delegation, err = tao.Parent().Attest(&self, nil, nil, s) 274 if err != nil { 275 return err 276 } 277 278 // SerializedStatement? 279 var programCert []byte 280 if useSimpleDomainService { 281 domain_response, err := RequestDomainServiceCert("tcp", caAddr, 282 programData.ProgramSigningKey, requestorCert, 283 programData.Delegation, d.Keys.VerifyingKey) 284 if err != nil || domain_response == nil { 285 log.Printf("InitProgramKeys: error from RequestDomainServiceCert\n") 286 return err 287 } 288 programCert = domain_response.SignedCert 289 for i := 0; i < len(domain_response.CertChain); i++ { 290 programData.CertChain = append(programData.CertChain, domain_response.CertChain[i]) 291 } 292 _, err = x509.ParseCertificate(programCert) 293 if err != nil { 294 log.Printf("InitProgramKeys: Can't parse certificate\n") 295 return err 296 } 297 programData.ProgramCert = programCert 298 } else { 299 signedCert, err := domain_service.RequestProgramCert(programData.Delegation, programData.ProgramSigningKey.GetVerifierFromSigner(), "tcp", caAddr) 300 if err != nil { 301 return err 302 } 303 programData.ProgramCert = signedCert.Raw 304 // Cert chains? 305 } 306 307 return nil 308 } 309 310 func DeserializeProgramData(buf []byte, programObject *TaoProgramData) error { 311 unsealed, err := UnsealMaterial(buf) 312 if err != nil { 313 return errors.New("Can't unseal program material") 314 } 315 var savedProgramData SavedProgramData 316 err = proto.Unmarshal(unsealed, &savedProgramData) 317 if err != nil { 318 return errors.New("Can't unmarshal program material") 319 } 320 if savedProgramData.FilePath != nil && 321 *programObject.ProgramFilePath != *savedProgramData.FilePath { 322 } 323 if !bytes.Equal(programObject.PolicyCert, savedProgramData.PolicyCert) { 324 } 325 if savedProgramData.ProgramName != nil && 326 programObject.TaoName != *savedProgramData.ProgramName { 327 } 328 if savedProgramData.CryptoSuite != nil && 329 *savedProgramData.CryptoSuite != tao.TaoCryptoSuite { 330 } 331 sck, err := tao.UnmarshalCryptoKey(savedProgramData.SigningKeyBlob) 332 if err != nil { 333 return errors.New("Can't get cryptokey for signing key") 334 } 335 programObject.ProgramSigningKey = tao.SignerFromCryptoKey(*sck) 336 cck, err := tao.UnmarshalCryptoKey(savedProgramData.CryptingKeyBlob) 337 if err != nil { 338 return errors.New("Can't get cryptokey for crypting key") 339 } 340 programObject.ProgramCryptingKey = tao.CrypterFromCryptoKey(*cck) 341 342 if len(savedProgramData.SignerCertChain) > 0 { 343 programObject.ProgramCert = savedProgramData.SignerCertChain[0] 344 } 345 346 for i := 0; i < len(savedProgramData.SignerCertChain) - 1; i++ { 347 programObject.CertChain= append(programObject.CertChain, savedProgramData.SignerCertChain[i + 1]) 348 } 349 programObject.Delegation = new(tao.Attestation) 350 err = proto.Unmarshal(savedProgramData.Delegation, programObject.Delegation) 351 if err != nil { 352 return err 353 } 354 return nil 355 } 356 357 func GetProgramData(d *tao.Domain, caAddr string, progPath string, useSimpleDomainService bool, 358 programObject *TaoProgramData) error { 359 360 fileName := path.Join(progPath, "protectedProgramKeys") 361 programInfoBlob, err := ioutil.ReadFile(fileName) 362 if err == nil { 363 err = DeserializeProgramData(programInfoBlob, programObject) 364 if err != nil { 365 return err 366 } 367 } else { 368 // FIX, should pass useSimpleDomainService flag 369 err := InitProgramKeys(d, caAddr, true, programObject) 370 if err != nil { 371 return err 372 } 373 _= SaveProgramData(fileName, programObject) 374 } 375 return nil 376 } 377 378 // cfg is policy domain config info 379 // filePath is path to program data 380 func TaoParadigm(cfg *string, filePath *string, useSimpleDomainService bool, caAddr string, 381 programObject *TaoProgramData) error { 382 383 // Load domain info for this domain. 384 simpleDomain, err := tao.LoadDomain(*cfg, nil) 385 if err != nil { 386 return errors.New(fmt.Sprintln("TaoParadigm: Can't load domain. Error: ", err)) 387 } 388 389 // Get policy cert. 390 if simpleDomain.Keys.Cert == nil || simpleDomain.Keys.Cert.Raw == nil { 391 return errors.New("TaoParadigm: Can't retrieve policy cert") 392 } 393 programObject.PolicyCert = simpleDomain.Keys.Cert.Raw 394 395 396 // Extend tao name with policy key 397 err = simpleDomain.ExtendTaoName(tao.Parent()) 398 if err != nil { 399 return errors.New(fmt.Sprintln("TaoParadigm: Error extending name: ", err)) 400 } 401 402 // Retrieve extended name. 403 taoName, err := tao.Parent().GetTaoName() 404 if err != nil { 405 return errors.New(fmt.Sprintln("TaoParadigm: Can't extend Tao Principal name. Error: ", err)) 406 } 407 programObject.TaoName = taoName.String() 408 programObject.ProgramFilePath = filePath 409 log.Printf("TaoParadigm: my name is %s\n", taoName) 410 411 err = GetProgramData(simpleDomain, caAddr, *filePath, useSimpleDomainService, programObject) 412 if err != nil { 413 return err 414 } 415 programObject.Initialized = true 416 return nil 417 } 418 419 // EncodeTLSCert combines a signing key and a certificate in a single tls 420 // certificate suitable for a TLS config. 421 func EncodeTLSCertFromSigner(s *tao.Signer, cert *x509.Certificate) (*tls.Certificate, error) { 422 if cert == nil { 423 return nil, fmt.Errorf("client: can't encode a nil certificate") 424 } 425 certPem := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: cert.Raw}) 426 keyBytes, err := tao.MarshalSignerDER(s) 427 if err != nil { 428 return nil, err 429 } 430 keyPem := pem.EncodeToMemory(&pem.Block{Type: "ECDSA PRIVATE KEY", Bytes: keyBytes}) 431 432 tlsCert, err := tls.X509KeyPair(certPem, keyPem) 433 if err != nil { 434 return nil, fmt.Errorf("can't parse cert: %s\n", err.Error()) 435 } 436 return &tlsCert, nil 437 } 438 439 // Establishes the Tao Channel for a client using the Program Key. 440 // This program does all the standard client side channel negotiation. 441 // After negotiation is complete. ms is the bi-directional confidentiality and 442 // integrity protected channel. OpenTaoChannel returns the stream (ms) for subsequent reads 443 // and writes as well as the server's Tao Principal Name. 444 func OpenTaoChannel(programObject *TaoProgramData, serverAddr *string) ( 445 *util.MessageStream, *string, error) { 446 447 // Parse policy cert and make it the root of our 448 // hierarchy for verifying Tao Channel peer. 449 policyCert, err := x509.ParseCertificate(programObject.PolicyCert) 450 if err != nil { 451 return nil, nil, errors.New("OpenTaoChannel: Can't ParseCertificate") 452 } 453 cert, err := x509.ParseCertificate(programObject.ProgramCert) 454 if err != nil { 455 return nil, nil, errors.New("OpenTaoChannel: Can't ParseCertificate") 456 } 457 pool := x509.NewCertPool() 458 pool.AddCert(policyCert) 459 460 // Open the Tao Channel using the Program key. 461 tlsc, err := EncodeTLSCertFromSigner(programObject.ProgramSigningKey, cert) 462 if err != nil { 463 log.Fatalln("OpenTaoChannel, encode error: ", err) 464 } 465 // TODO(manferdelli): Replace this with tao.Dial? 466 conn, err := tls.Dial("tcp", *serverAddr, &tls.Config{ 467 RootCAs: pool, 468 Certificates: []tls.Certificate{*tlsc}, 469 InsecureSkipVerify: false, 470 }) 471 if err != nil { 472 fmt.Printf("OpenTaoChannel: Can't establish channel : %v\n", err) 473 return nil, nil, errors.New("OpenTaoChannel: Can't establish channel") 474 } 475 476 peerName := policyCert.Subject.OrganizationalUnit[0] 477 478 // Stream for Tao Channel. 479 ms := util.NewMessageStream(conn) 480 return ms, &peerName, nil 481 }