opiproject / sztp

Secure Zero Touch Provisioning (sZTP) in OPI
Apache License 2.0
20 stars 14 forks source link

TPM2 using QEMU #402

Open glimchb opened 3 months ago

glimchb commented 3 months ago
glimchb commented 3 months ago

need to add how to generate and save into tpm iDEVID (private and public keys) of the devices

glimchb commented 3 months ago

See as reference tls config using tpm

https://github.com/folbricht/tpmk?tab=readme-ov-file#establishing-a-mutual-tls-connection-using-a-tpm-key

glimchb commented 2 months ago

useful TPM constants: https://github.com/lf-edge/eve/blob/12be0c21435e09a9d396bb9795398d43c2b8ba4f/pkg/pillar/evetpm/tpm.go#L29-L72

const (
    //TpmPasswdHdl is the well known TPM NVIndex for TPM Credentials
    TpmPasswdHdl tpmutil.Handle = 0x1600000

    //TpmEKHdl is the well known TPM permanent handle for Endorsement key
    TpmEKHdl tpmutil.Handle = 0x81000001

    //TpmSRKHdl is the well known TPM permanent handle for Storage key
    TpmSRKHdl tpmutil.Handle = 0x81000002

    //TpmAKHdl is the well known TPM permanent handle for AIK key
    TpmAKHdl tpmutil.Handle = 0x81000003

    //TpmQuoteKeyHdl is the well known TPM permanent handle for PCR Quote signing key
    TpmQuoteKeyHdl tpmutil.Handle = 0x81000004

    //TpmEcdhKeyHdl is the well known TPM permanent handle for ECDH key
    TpmEcdhKeyHdl tpmutil.Handle = 0x81000005

    //TpmDeviceKeyHdl is the well known TPM permanent handle for device key
    TpmDeviceKeyHdl tpmutil.Handle = 0x817FFFFF

    //TpmCredentialsFileName is the file that holds the dynamically created TPM credentials
    TpmCredentialsFileName = types.IdentityDirname + "/tpm_credential"

    //MaxPasswdLength is the max length allowed for a TPM password
    MaxPasswdLength = 7 //limit TPM password to this length

    //TpmDiskKeyHdl is the handle for constructing disk encryption key
    TpmDiskKeyHdl tpmutil.Handle = 0x1700000

    //TpmDeviceCertHdl is the well known TPM NVIndex for device cert
    TpmDeviceCertHdl tpmutil.Handle = 0x1500000

    //TpmSealedDiskPrivHdl is the handle for constructing disk encryption key
    TpmSealedDiskPrivHdl tpmutil.Handle = 0x1800000

    //TpmSealedDiskPubHdl is the handle for constructing disk encryption key
    TpmSealedDiskPubHdl tpmutil.Handle = 0x1900000

    //EmptyPassword is an empty string
    EmptyPassword  = ""
    vaultKeyLength = 32 //Bytes
)
glimchb commented 2 months ago

will try without QEMU like this https://github.com/opiproject/sztp/blob/main/doc/swtpm.md

sudo apt-get install swtpm tpm2-tools -y
mkdir /tmp/emulated_tpm
mkdir /tmp/emulated_tpm
swtpm socket --tpm2 \
    --server type=unixio,path=/tmp/emulated_tpm/swtpm.sock \
    --ctrl type=unixio,path=/tmp/emulated_tpm/swtpm.sock.ctrl \
    --tpmstate dir=/tmp/emulated_tpm \
    --log file="swtpm.log" \
    --log level=20 \
    --flags not-need-init,startup-clear &

export TPM2TOOLS_TCTI="swtpm:path=/tmp/emulated_tpm/swtpm.sock" tpm2 clear

or

docker run --rm -it -v sztp_tpm-data:/swtpm -e TPM2TOOLS_TCTI="swtpm:path=/swtpm/swtpm.sock" docker.io/strongx509/tpm:5.9.13 tpm2 clear

and then in golang:

package main

import (
        "io/ioutil"
        "log"
        "net"

        "github.com/google/go-tpm/legacy/tpm2"
        "github.com/google/go-tpm/tpmutil"
)

var (
        tpmSrkHandle        = 0x81000001
        tpmPcrSelection     = tpm2.PCRSelection{Hash: tpm2.AlgSHA256, PCRs: []int{}}
        tpmDefaultKeyParams = tpm2.Public{
                Type:       tpm2.AlgRSA,
                NameAlg:    tpm2.AlgSHA256,
                Attributes: tpm2.FlagDecrypt | tpm2.FlagFixedTPM | tpm2.FlagFixedParent | tpm2.FlagSensitiveDataOrigin | tpm2.FlagNoDA,
                AuthPolicy: []byte{},
                RSAParameters: &tpm2.RSAParams{
                        Symmetric: &tpm2.SymScheme{
                                Alg:  tpm2.AlgNull,
                                Mode: tpm2.AlgUnknown,
                        },
                        KeyBits: 2048,
                },
        }
)

func main() {
        rwc, tpmerr := net.Dial("unix", "/tmp/emulated_tpm/swtpm.sock")
        //rwc, tpmerr := tpm2.OpenTPM("/tmp/emulated_tpm/swtpm.sock")
        if tpmerr != nil {
                log.Fatalf("[ERROR] %s", tpmerr.Error())
                return
        }
        defer rwc.Close()
        if _, err := tpm2.GetManufacturer(rwc); err != nil {
                log.Fatalf("device is not a TPM 2.0")
                return
        }
        handle := tpmutil.Handle(tpmSrkHandle)
        privKey, pubKey, _, _, _, err := tpm2.CreateKey(rwc, handle, tpmPcrSelection, "", "", tpmDefaultKeyParams)
        if err != nil {
                log.Fatalf("[ERROR] %s", err.Error())
                return
        }
        tpmKeyHandle, _, err := tpm2.Load(rwc, handle, "", pubKey, privKey)
        if err != nil {
                log.Fatalf("[ERROR] %s", err.Error())
                return
        }
        defer tpm2.FlushContext(rwc, tpmKeyHandle)
        ekhBytes, err := tpm2.ContextSave(rwc, tpmKeyHandle)
        err = ioutil.WriteFile("key.ctx", ekhBytes, 0644)
        log.Fatalf("[ERROR] %s", err.Error())
}

and run like

docker run --rm -it -v `pwd`:/app -w /app golang:alpine go mod init  github.com/opiproject/sztp/sztp-agent
docker run --rm -it -e GO111MODULE=on -v `pwd`:/app -w /app golang:alpine go get -u  github.com/google/go-tpm/tpmutil
docker run --rm -it -v /tmp/emulated_tpm:/tmp/emulated_tpm -v `pwd`:/app -w /app golang:alpine go run tpm.go

log

 SWTPM_IO_Read: length 22
 80 01 00 00 00 16 00 00 01 7A 00 00 00 06 00 00
 01 05 00 00 00 01
 SWTPM_IO_Write: length 27
 80 01 00 00 00 1B 00 00 00 00 01 00 00 00 06 00
 00 00 01 00 00 01 05 49 42 4D 00
 SWTPM_IO_Read: length 63
 80 02 00 00 00 3F 00 00 01 53 81 00 00 01 00 00
 00 09 40 00 00 09 00 00 01 00 00 00 04 00 00 00
 00 00 16 00 01 00 0B 00 02 04 32 00 00 00 10 00
 10 08 00 00 00 00 00 00 00 00 00 00 00 00 00
 SWTPM_IO_Write: length 10
 80 01 00 00 00 0A 00 00 01 8B
Data client disconnected

go: downloading github.com/google/go-tpm v0.9.1
go: downloading golang.org/x/sys v0.22.0
2024/07/15 21:13:05 [ERROR] handle 1, error code 0xb : the handle is not correct for the use
exit status 1
glimchb commented 2 months ago

added to ci https://github.com/opiproject/sztp/commit/9de78f368babee2057664cfc2d805bbd3902941a and https://github.com/opiproject/sztp/commit/243d889d0bdf257935d830fe0c991de6397e5831 and https://github.com/opiproject/sztp/commit/3c77452310bdcb3e8bb1da9bb6d8e6839f2c1dff