github.com/jlmucb/cloudproxy@v0.0.0-20170830161738-b5aa0b619bc4/go/tpm2/tpm2_protocols.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  
    16  package tpm2
    17  
    18  import (
    19  	"bytes"
    20  	"crypto/rsa"
    21  	"crypto/sha256"
    22  	"errors"
    23  	"fmt"
    24  	"io"
    25  	"io/ioutil"
    26  	"math/big"
    27  	"time"
    28  )
    29  
    30  const (
    31  	RootKeyHandle     uint32 = 0x810003e8
    32  	QuoteKeyHandle    uint32 = 0x810003e9
    33  	RollbackKeyHandle uint32 = 0
    34  )
    35  
    36  // return handle, policy digest
    37  func AssistCreateSession(rw io.ReadWriter, hash_alg uint16,
    38  	pcrs []int) (Handle, []byte, error) {
    39  	nonceCaller := []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
    40  	var secret []byte
    41  	sym := uint16(AlgTPM_ALG_NULL)
    42  
    43  	session_handle, policy_digest, err := StartAuthSession(rw,
    44  		Handle(OrdTPM_RH_NULL),
    45  		Handle(OrdTPM_RH_NULL), nonceCaller, secret,
    46  		uint8(OrdTPM_SE_POLICY), sym, hash_alg)
    47  	if err != nil {
    48  		return Handle(0), nil, errors.New("Can't start session")
    49  	}
    50  
    51  	err = PolicyPassword(rw, session_handle)
    52  	if err != nil {
    53  		return Handle(0), nil, errors.New("PolicyPassword fails")
    54  	}
    55  	var tpm_digest []byte
    56  	err = PolicyPcr(rw, session_handle, tpm_digest, pcrs)
    57  	if err != nil {
    58  		return Handle(0), nil, errors.New("PolicyPcr fails")
    59  	}
    60  
    61  	policy_digest, err = PolicyGetDigest(rw, session_handle)
    62  	if err != nil {
    63  		return Handle(0), nil, errors.New("PolicyGetDigest fails")
    64  	}
    65  	return session_handle, policy_digest, nil
    66  }
    67  
    68  // out: private, public
    69  func AssistSeal(rw io.ReadWriter, parentHandle Handle, toSeal []byte,
    70  	parentPassword string, ownerPassword string, pcrs []int,
    71  	policy_digest []byte) ([]byte, []byte, error) {
    72  
    73  	var empty []byte
    74  	keyedhashparms := KeyedHashParams{uint16(AlgTPM_ALG_KEYEDHASH),
    75  		uint16(AlgTPM_ALG_SHA1),
    76  		FlagSealDefault, empty, uint16(AlgTPM_ALG_AES), uint16(128),
    77  		uint16(AlgTPM_ALG_CFB), uint16(AlgTPM_ALG_NULL), empty}
    78  	private_blob, public_blob, err := CreateSealed(rw, parentHandle,
    79  		policy_digest, parentPassword, ownerPassword, toSeal,
    80  		pcrs, keyedhashparms)
    81  	if err != nil {
    82  		return nil, nil, errors.New("CreateSealed fails")
    83  	}
    84  	return private_blob, public_blob, nil
    85  }
    86  
    87  // out: unsealed blob, nonce
    88  func AssistUnseal(rw io.ReadWriter, sessionHandle Handle, parentHandle Handle,
    89  	pub []byte, priv []byte, parentPassword string, ownerPassword string,
    90  	policy_digest []byte) ([]byte, []byte, error) {
    91  
    92  	// Load Sealed
    93  	sealHandle, _, err := Load(rw, parentHandle, parentPassword,
    94  		ownerPassword, pub, priv)
    95  	if err != nil {
    96  		return nil, nil, errors.New("Load failed")
    97  	}
    98  	defer FlushContext(rw, sealHandle)
    99  
   100  	// Unseal
   101  	unsealed, nonce, err := Unseal(rw, sealHandle, ownerPassword,
   102  		sessionHandle, policy_digest)
   103  	if err != nil {
   104  		return nil, nil, errors.New("Unseal failed")
   105  	}
   106  	return unsealed, nonce, err
   107  }
   108  
   109  // Call with tpm 2.0 and the quote handle, get the key back for serialization in AttestCertRequest.
   110  func GetRsaKeyFromHandle(rw io.ReadWriter, handle Handle) (*rsa.PublicKey, error) {
   111  	publicBlob, _, _, err := ReadPublic(rw, handle)
   112  	if err != nil {
   113  		return nil, errors.New("Can't get public key blob")
   114  	}
   115  	rsaParams, err := DecodeRsaBuf(publicBlob)
   116  	publicKey := new(rsa.PublicKey)
   117  	// TODO(jlm): read exponent from blob
   118  	publicKey.E = 0x00010001
   119  	M := new(big.Int)
   120  	M.SetBytes(rsaParams.Modulus)
   121  	publicKey.N = M
   122  	return publicKey, nil
   123  }
   124  
   125  func GenerateHWCert(rw io.ReadWriter, handle Handle, hardwareName string,
   126  	notBefore time.Time, notAfter time.Time, serialNumber *big.Int,
   127  	derPolicyCert []byte, policyKey *rsa.PrivateKey) ([]byte, error) {
   128  	hwPublic, err := GetRsaKeyFromHandle(rw, handle)
   129  	if err != nil {
   130  		return nil, errors.New("Can't get endorsement public key")
   131  	}
   132  	return GenerateCertFromKeys(policyKey, derPolicyCert, hwPublic,
   133  		hardwareName, hardwareName, serialNumber, notBefore, notAfter)
   134  }
   135  
   136  func CreateEndorsement(rw io.ReadWriter, modSize uint16, pcrs []int) (Handle, []byte, error) {
   137  	var empty []byte
   138  	primaryparms := RsaParams{uint16(AlgTPM_ALG_RSA),
   139  		uint16(AlgTPM_ALG_SHA1), FlagStorageDefault,
   140  		empty, uint16(AlgTPM_ALG_AES), uint16(128),
   141  		uint16(AlgTPM_ALG_CFB), uint16(AlgTPM_ALG_NULL),
   142  		uint16(0), modSize, uint32(0x00010001), empty}
   143  	return CreatePrimary(rw, uint32(OrdTPM_RH_ENDORSEMENT), pcrs,
   144  		"", "", primaryparms)
   145  }
   146  
   147  func FormatTpm2Quote(stmt []byte, pcrs []int, pcrVals [][]byte) ([]byte, error) {
   148  	sha256Hash := sha256.New()
   149  	sha256Hash.Write(stmt)
   150  	toQuote := sha256Hash.Sum(nil)
   151  	return toQuote, nil
   152  }
   153  
   154  func VerifyTpm2Quote(serialized []byte, pcrs []int, expectedPcrVal []byte,
   155  	tpm2Quote []byte, sig []byte, key *rsa.PublicKey) (bool, error) {
   156  
   157  	// TODO: fix
   158  	hash_alg_id := uint16(AlgTPM_ALG_SHA1)
   159  
   160  	attest, err := UnmarshalCertifyInfo(tpm2Quote)
   161  	if err != nil {
   162  		return false, errors.New("Can't unmarshal quote structure\n")
   163  	}
   164  
   165  	// Sha256(serialized) == Data?
   166  	sha256Hash := sha256.New()
   167  	sha256Hash.Write(serialized)
   168  	hashedData := sha256Hash.Sum(nil)
   169  	if bytes.Compare(attest.Data, hashedData) != 0 {
   170  		return false, errors.New("hashed data is not in quote structure")
   171  	}
   172  
   173  	// pcr digests match?
   174  	if bytes.Compare(expectedPcrVal, attest.PcrDigest) != 0 {
   175  		return false, errors.New("pcr digest does not match")
   176  	}
   177  
   178  	// quote_hash was the thing that was signed
   179  	quote_hash, err := ComputeHashValue(hash_alg_id, tpm2Quote)
   180  	if err != nil {
   181  		return false, errors.New("Can't compute quote\n")
   182  	}
   183  
   184  	// decrypt signature
   185  	var E *big.Int
   186  	E = new(big.Int)
   187  	E.SetBytes([]byte{0, 1, 0, 1})
   188  	x := new(big.Int)
   189  	x.SetBytes(sig)
   190  	z := new(big.Int)
   191  	z = z.Exp(x, E, key.N)
   192  	decrypted_quote := z.Bytes()
   193  	start_quote_blob := len(decrypted_quote) - SizeHash(hash_alg_id)
   194  
   195  	// quote_hash == decrypted sig?
   196  	if bytes.Compare(decrypted_quote[start_quote_blob:], quote_hash) != 0 {
   197  		return false, nil
   198  	}
   199  	return true, nil
   200  }
   201  
   202  // Loads keys from blobs.
   203  func LoadKeyFromBlobs(rw io.ReadWriter, ownerHandle Handle, ownerPw string, objectPw string,
   204  	publicBlob []byte, privateBlob []byte) (Handle, error) {
   205  	newHandle, _, err := Load(rw, ownerHandle, ownerPw, objectPw, publicBlob, privateBlob)
   206  	if err != nil {
   207  		return Handle(0), errors.New("Load failed")
   208  	}
   209  	return newHandle, nil
   210  }
   211  
   212  func CreateTpm2HierarchyRoot(rw io.ReadWriter, pcrs []int, keySize uint16, hash_alg_id uint16) (Handle, error) {
   213  	// CreatePrimary
   214  	var empty []byte
   215  	primaryparms := RsaParams{uint16(AlgTPM_ALG_RSA), hash_alg_id, FlagStorageDefault,
   216  		empty, uint16(AlgTPM_ALG_AES), uint16(128), uint16(AlgTPM_ALG_CFB), uint16(AlgTPM_ALG_NULL),
   217  		uint16(0), keySize, uint32(0x00010001), empty}
   218  	rootHandle, _, err := CreatePrimary(rw, uint32(OrdTPM_RH_OWNER), pcrs, "", "", primaryparms)
   219  	return rootHandle, err
   220  }
   221  
   222  // Create quote and seal keys under rootHandle and return in order:
   223  //	quote public blob, quote private blob, seal public blob, seal private blob
   224  func CreateTpm2HierarchySubKeys(rw io.ReadWriter, pcrs []int, keySize uint16, hash_alg_id uint16,
   225  	rootHandle Handle, quotePassword string) ([]byte, []byte, []byte, []byte, error) {
   226  
   227  	var empty []byte
   228  	// CreateKey (Quote Key)
   229  	keyparms := RsaParams{uint16(AlgTPM_ALG_RSA), hash_alg_id,
   230  		FlagSignerDefault, empty, uint16(AlgTPM_ALG_NULL), uint16(0),
   231  		uint16(AlgTPM_ALG_ECB), uint16(AlgTPM_ALG_RSASSA),
   232  		uint16(AlgTPM_ALG_SHA1), keySize, uint32(0x00010001), empty}
   233  	quote_private, quote_public, err := CreateKey(rw, uint32(rootHandle), pcrs, "", quotePassword, keyparms)
   234  	if err != nil {
   235  		return nil, nil, nil, nil, errors.New("Can't create quote key")
   236  	}
   237  
   238  	// CreateKey (storage key)
   239  	storeparms := RsaParams{uint16(AlgTPM_ALG_RSA), hash_alg_id, FlagStorageDefault,
   240  		empty, uint16(AlgTPM_ALG_AES), uint16(128), uint16(AlgTPM_ALG_CFB),
   241  		uint16(AlgTPM_ALG_NULL), uint16(0), keySize, uint32(0x00010001), empty}
   242  	store_private, store_public, err := CreateKey(rw, uint32(rootHandle), pcrs, "", quotePassword, storeparms)
   243  	if err != nil {
   244  		return nil, nil, nil, nil, errors.New("Can't create store key")
   245  	}
   246  	return quote_public, quote_private, store_public, store_private, nil
   247  }
   248  
   249  // This program creates a key hierarchy consisting of a
   250  // primary key and quoting key for cloudproxy.
   251  func CreateTpm2KeyHierarchy(rw io.ReadWriter, pcrs []int, keySize uint16, hash_alg_id uint16,
   252  	quotePassword string) (Handle, Handle, Handle, error) {
   253  
   254  	// Create Root.
   255  	rootHandle, err := CreateTpm2HierarchyRoot(rw, pcrs, keySize, uint16(AlgTPM_ALG_SHA1))
   256  	if err != nil {
   257  		return Handle(0), Handle(0), Handle(0), errors.New("CreatePrimary failed")
   258  	}
   259  
   260  	// Create sub keys.
   261  	quote_public, quote_private, seal_public, seal_private, err := CreateTpm2HierarchySubKeys(rw, pcrs, keySize,
   262  		uint16(AlgTPM_ALG_SHA1), rootHandle, quotePassword)
   263  	if err != nil {
   264  		return Handle(0), Handle(0), Handle(0), errors.New("Can't create quote key")
   265  	}
   266  
   267  	// Load
   268  	quoteHandle, err := LoadKeyFromBlobs(rw, rootHandle, "", "", quote_public, quote_private)
   269  	if err != nil {
   270  		return Handle(0), Handle(0), Handle(0), errors.New("Quote load failed")
   271  	}
   272  
   273  	// Load
   274  	sealHandle, err := LoadKeyFromBlobs(rw, rootHandle, "", "", seal_public, seal_private)
   275  	if err != nil {
   276  		return Handle(0), Handle(0), Handle(0), errors.New("Load failed")
   277  	}
   278  
   279  	return rootHandle, quoteHandle, sealHandle, nil
   280  }
   281  
   282  // Makes their handles permanent.
   283  func PersistTpm2KeyHierarchy(rw io.ReadWriter, pcrs []int, keySize int,
   284  	hash_alg_id uint16, rootHandle uint32, quoteHandle uint32, quotePassword string) error {
   285  
   286  	// Remove old permanent handles
   287  	err := EvictControl(rw, Handle(OrdTPM_RH_OWNER), Handle(rootHandle),
   288  		Handle(rootHandle))
   289  	if err != nil {
   290  		fmt.Printf("Evict existing permanant primary handle failed (OK)\n")
   291  	}
   292  	err = EvictControl(rw, Handle(OrdTPM_RH_OWNER), Handle(quoteHandle),
   293  		Handle(quoteHandle))
   294  	if err != nil {
   295  		fmt.Printf("Evict existing permanant quote handle failed (OK)\n")
   296  	}
   297  
   298  	/*
   299  		err = EvictControl(rw, Handle(OrdTPM_RH_OWNER), tmpQuoteHandle,
   300  				Handle(quoteHandle))
   301  		if err != nil {
   302  			FlushContext(rw, tmpQuoteHandle)
   303  			return errors.New("Install new quote handle failed")
   304  		}
   305  	*/
   306  	return nil
   307  }
   308  
   309  // This isnt used any more.
   310  func InitTpm2KeysandContexts(rw io.ReadWriter, pcrs []int, keySize uint16, hash_alg_id uint16,
   311  	quotePassword string, rootFileName string, quoteFileName string,
   312  	storeFileName string) error {
   313  
   314  	rootHandle, quoteHandle, storeHandle, err := CreateTpm2KeyHierarchy(rw, pcrs,
   315  		keySize, hash_alg_id, quotePassword)
   316  	if err != nil {
   317  		return errors.New("InitTpm2Keys failed")
   318  	}
   319  
   320  	rootSaveArea, err := SaveContext(rw, rootHandle)
   321  	if err != nil {
   322  		return errors.New("Save root Context fails")
   323  	}
   324  	defer FlushContext(rw, rootHandle)
   325  
   326  	quoteSaveArea, err := SaveContext(rw, quoteHandle)
   327  	if err != nil {
   328  		return errors.New("Save quote Context fails")
   329  	}
   330  	defer FlushContext(rw, quoteHandle)
   331  
   332  	storeSaveArea, err := SaveContext(rw, storeHandle)
   333  	if err != nil {
   334  		return errors.New("Save store Context fails")
   335  	}
   336  	defer FlushContext(rw, storeHandle)
   337  
   338  	ioutil.WriteFile(rootFileName, rootSaveArea, 0644)
   339  	ioutil.WriteFile(quoteFileName, quoteSaveArea, 0644)
   340  	ioutil.WriteFile(storeFileName, storeSaveArea, 0644)
   341  	return nil
   342  }
   343  
   344  func RestoreTpm2KeysFromContext(rw io.ReadWriter, quotePassword string,
   345  	rootFileName string, quoteFileName string,
   346  	storeFileName string) (Handle, Handle, Handle, error) {
   347  
   348  	rootSaveArea, err := ioutil.ReadFile(rootFileName)
   349  	if err != nil {
   350  		return Handle(0), Handle(0), Handle(0), errors.New("Can't read root store file")
   351  	}
   352  	quoteSaveArea, err := ioutil.ReadFile(quoteFileName)
   353  	if err != nil {
   354  		return Handle(0), Handle(0), Handle(0), errors.New("Can't read quote store file")
   355  	}
   356  	storeSaveArea, err := ioutil.ReadFile(storeFileName)
   357  	if err != nil {
   358  		return Handle(0), Handle(0), Handle(0), errors.New("Can't read store store file")
   359  	}
   360  	rootHandle, err := LoadContext(rw, rootSaveArea)
   361  	if err != nil {
   362  		return Handle(0), Handle(0), Handle(0), errors.New("Can't load root handle")
   363  	}
   364  	quoteHandle, err := LoadContext(rw, quoteSaveArea)
   365  	if err != nil {
   366  		FlushContext(rw, rootHandle)
   367  		return Handle(0), Handle(0), Handle(0), errors.New("Can't load quote handle")
   368  	}
   369  	storeHandle, err := LoadContext(rw, storeSaveArea)
   370  	if err != nil {
   371  		FlushContext(rw, rootHandle)
   372  		FlushContext(rw, quoteHandle)
   373  		return Handle(0), Handle(0), Handle(0), errors.New("Can't load store handle")
   374  	}
   375  	return rootHandle, quoteHandle, storeHandle, nil
   376  }