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  }