Skip to content

salrashid123/tpmrand

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

13 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

TPM backed crypto/rand Reader

A crypto.rand reader that uses a Trusted Platform Module (TPM) as the source of randomness.

Basically, its just a source of randomness used to create RSA keys or just get bits for use anywhere else. With tpm2-tools, its like this:

$ tpm2_getrandom --hex 32 
   8c20c96c56d3ac200881ac86505020a0dafcfe0224fbc51b843e07625cc779fc

As background, the default rand generator with golang uses the following sources by default in rand.go

The implementation uses go-tpm's tpm2.GetRandom function as the source of randomness from the hardware.

From there, the usage is simple:

package main

import (
	"github.com/google/go-tpm/tpmutil"
	//"github.com/cenkalti/backoff/v4"
	tpmrand "github.com/salrashid123/tpmrand"
)

var ()

func main() {

	rwc, err := tpmutil.OpenTPM("/dev/tpm0")
	defer rwc.Close()

	randomBytes := make([]byte, 32)
	r, err := tpmrand.NewTPMRand(&tpmrand.Reader{
		TpmDevice: rwc,
		//Scheme:    backoff.NewConstantBackOff(time.Millisecond * 10),
	})

	// Rand read
	_, err = r.Read(randomBytes)

	fmt.Printf("Random String :%s\n", base64.StdEncoding.EncodeToString(randomBytes))

	// /// RSA keygen
	privkey, err := rsa.GenerateKey(r, 2048)

	keyPEM := pem.EncodeToMemory(
		&pem.Block{
			Type:  "RSA PRIVATE KEY",
			Bytes: x509.MarshalPKCS1PrivateKey(privkey),
		},
	)
	fmt.Printf("RSA Key: \n%s\n", keyPEM)
}

for a quick demo, use the simulator:

cd example/tpm/

$ go run main.go --tpm-path=simulator
	Random String :0e0078720751bdebc5551276b68601312f4b34ac808c5b5ab263c5a760bc9253

	RSA Key: 
	-----BEGIN RSA PRIVATE KEY-----
	MIIEogIBAAKCAQEAtOSZC/BAzoB1/diSSffzfZbztXvfYViXmPrAhdKulOf/kx7S
	oxf6sQ7PBdrS5611an3Eg8FfxuqWdFO7FM42xmWUi95av5TrdbDwUz792qOtGB0v
	q216wJPJg8GmJ1R9ckBdPJyI6fVm2OjwJWKZaYywmyyyCwQX/etclGBC2z+/kq3J
	/CJmZBsOHhoB/o3jd+9pEeIYVihtJvQcDMzUcXGSM8MZOb5csIo8FUEYIheM3Bds
	vNjxtG5WeNWDtO6HaUAs3yn1+b8ilAa5uSmNfSVlQl8N/Um4ezrdvZ3WGbh1Z97z
	FpahYt5D2eOy6roX5QK+jOInfA/2w81D7+6N6wIDAQABAoIBAEn+mHxBssDF234S
	8QRA4OEmtlouaZmwW5LAP7B+FdvjarALk64TSQDURernMA6E7dq5x4D9wOflXdYH
	yicgk1dkhfcQ5Z4olIh38FadFcox2cRba/x7tBLCYVP8CrNb5FSv73OztG2/bGqe
	Hl2sj4SVgEh5Z/sJmabMd/pZxf9YzDwr68nQYNBCaPEs+fpYFBfCEYrY/n29gGtn
	8oeN1HkAVWgmYnR2lJKA204PtHEQKGqNTGN6YM2O1qwcdlSaKNmEMhdz+tvsaL4P
	Z3REKV0AhKMqPzLzYoWDaQsBpB3PsOSuF2M+pPHXyvgcmZZpsscfHjf+6vi/do0E
	aIIL0oECgYEA1OrKO0WifC5gRRX67KoWcczWrozqmaALZRmvDH1DrghrazJmPgZH
	c8M4X70RElO420EjBYDxDWYJY1m0TcKTSlYOTxUAmyDVFe/1noyr6khe5+R46sQp
	QimPFTlhOR1JNfmKXIPtnnNonXHVuiRSRKBnarogz500W4l35O59i5kCgYEA2X7w
	i4ai9IRixELQD4fI0dnxwTH6O37rAp5+TOkkzghDDfFvs3LJQQAPpafqU5GrEyLO
	mQlEhKkAmj704NUXpzqkk83sXpdzXPwmI3c/Ps/W5iVNBOvKUAlYOIbijUEAQhAl
	G6PxvOBdT3hBI+jUENWptxGn4BYReLsbfLzzOCMCgYA3/W4k3BD4evGR+U+9AJVa
	Y7VovWHL+ExGz9Q6go5Tq58j12MPmHMdvA6NDpj4qs+HyL8+6UN6dISvfZ1ufWZi
	O/MTVMCOCro+RJXglbl3qIRckrZBdkgrP+aCfE5WyJ7B9NcvsPnBmzO9g3visT55
	EX1gkYWjUwG7uJCwwQ5+sQKBgHUvhw22QjC677hNQ2tKvvIKms58ThYmYRttKCHq
	cHEuVGq7znKCg1spXETmP0Q9tU4/L8+XBbrwkCmLiEdnqTHqT+hvSE8DDR5poWb0
	hjgipegk6uWe4cfT8Rur2X9AKZJuvn+xCru4q6343igp97EGXkYMFkaPvWQudDX2
	XJm/AoGANVOlB3WM8vshEe/iGsxYlAVWTDQiDScLcrrnIZgauXTRmkWEiQNr0VIk
	Hr4ZneTlLU6913NYscYXADgS+ns9Q+EACt7UhgCdLCTpWkjwA0TDRwQgeK+9BlYP
	L4drKWRgsXFxLTtDD+VflKYLPKXos0ZMWKHruOs1/VXs2y6/yOU=
	-----END RSA PRIVATE KEY-----

Encrypted Session

tpmrand also supports encrypted transports as described here:

Transport encryption is disabled by default so to enable it, pass a known asymmetric key in first that you know to be on the TPM (eg an EK) as the EncryptionHandle and EncryptionPub.

for reference with tpm2_tools, you can find the test cases here

As a demo, you see the TPM API calls Using software TPM (swtpm) to trace API calls with TCPDump

## setup swtpm
mkdir /tmp/myvtpm
sudo swtpm socket --tpmstate dir=/tmp/myvtpm --tpm2 --server type=tcp,port=2321 --ctrl type=tcp,port=2322 --flags not-need-init,startup-clear
## start traces
sudo tcpdump -s0 -ilo -w encrypted.cap port 2321

Without encryption:

$ go run main.go  --tpm-path="127.0.0.1:2321"
    Random String :2c0be4244301100bc77ae94655eb86a426c6685481993d71d28a74355602ec29

note that the bytes returned is in the clear:

example/images/clear.png

With encryption:

Then

$ go run main.go  --tpm-path="127.0.0.1:2321"
   Random String :b9302b856c03466ec90e65f8c9817becab7e3e0a7523fabd7169607b2de55d60

example/images/encrypted.png


While you're here, some other references on TPMs and usage:


PKCS-11

ThalesIgnite crypto11.NewRandomReader() is an alternative to this library but requires installing tpm2-pkcs11 first on the library....and critically, i'm not sure if it supports TPM session encryption (it may)

I've left some examples of using that library here for reference