I have a DPE application and I am doing client.Sign of a message. This function returns a signature, a certificate from which we can get public key and other few things.

I have extracted the public key from this certificate and I found that that is of type ECDSA.

then I tried loading this public key into the TPM by using tpm2.loadexternal by forming tpm2.Public{} struct.

pubKey, err := x509.ParsePKIXPublicKey(publicKeyDer)
if err != nil {
    fmt.Println("Failed to parse DER-encoded public key:", err)
    os.Exit(1)
}

// Create a tpm2.Public structure from the parsed ECDSA public key
switch pubKey := pubKey.(type) {
case *ecdsa.PublicKey:
    tpmPublic = tpm2.Public{
        Type:    tpm2.AlgECDSA, // ECDSA key type
        NameAlg: tpm2.AlgSHA256,
        //Attributes: tpm2.FlagSign | tpm2.FlagRestricted | tpm2.FlagDecrypt,
        Attributes: tpm2.FlagSign | tpm2.FlagSensitiveDataOrigin | tpm2.FlagUserWithAuth,
        ECCParameters: &tpm2.ECCParams{
            Symmetric: &tpm2.SymScheme{
                Alg:     tpm2.AlgECDSA,
                KeyBits: 2048,
                Mode:    tpm2.AlgSHA256,
            },
            Sign: &tpm2.SigScheme{
                Alg:  tpm2.AlgECDSA,
                Hash: tpm2.AlgSHA256,
                //Count: 0,
            },
            //CurveID: tpm2.EllipticCurve(0x0003), // You should adjust this based on your ECDSA curve
            CurveID: tpm2.CurveNISTP256,
            Point: tpm2.ECPoint{
                XRaw: new(big.Int).SetBytes(pubKey.X.Bytes()).Bytes(),
                YRaw: new(big.Int).SetBytes(pubKey.Y.Bytes()).Bytes(),
            },
        },
    }
default:
    fmt.Println("Unsupported public key type")
    os.Exit(1)
}

fmt.Printf("TPM2 Public Key:\n%v\n", tpmPublic)

// private := tpm2.Private{
//  Type: tpm2.AlgECC,
//  //Sensitive: pk.D.Bytes(),
// }

_, _, err = tpm2.LoadExternal(rwc, tpmPublic, tpm2.Private{}, tpm2.HandleNull)
if err != nil {
    fmt.Printf("Err : %v", err)
    os.Exit(1)
}

for this loadExternal operation, I am getting below error,

Err : encoding RSAParameters, ECCParameters, SymCipherParameters or KeyedHash: unsupported type in TPMT_PUBLIC: 0x4543445341
exit status 1

if I change the type and Alg from ECDSA to ECC in all the places of the structure like,

Type:    tpm2.AlgECC
Alg:     tpm2.AlgECC

it throws,

Err : parameter 2, error code 0x16 : unsupported symmetric algorithm or key size, or not appropriate for instance
exit status 1

What am doing wrong here? first of all, Is the way I try to load a public key alone into the TPM correct? help me on this.

Note : I am not using real TPM instead I am using a TPM simulator by following (https://github.com/stefanberger/swtpm/wiki) and TPM related packages from (https://francislampayan.medium.com/how-to-setup-tpm-simulator-in-ubuntu-20-04-25ec673b88dc) this link.

Thanks..!

1

There are 1 best solutions below

0
MemAllox On

As indicated by your error (unsupported symmetric algorithm): your symmetric crypto scheme is faulty.

Symmetric: &tpm2.SymScheme{
    Alg:     tpm2.AlgECDSA,     <-- not a symmetric crypto scheme
    KeyBits: 2048,
    Mode:    tpm2.AlgSHA256,
},

You might want to try to leave that empty (tpm2.AlgNull):

https://github.com/folbricht/tpmk/blob/87ef9183fb67bc1cd4da7269f2b332c8d0991084/key.go#L24-L27

Or use AES:

https://github.com/google/go-tpm-tools/blob/44e8925789363b77e38c23bb5cf00eeae94be296/client/template.go#L35-L39

Example of a working TPM2_LoadExternal call

Command                                   .
TPMI_ST_COMMAND_TAG                       |   .tag                                       8001                 TPMI_ST_COMMAND_TAG.NO_SESSIONS
UINT32                                    |   .commandSize                               00000068             104
TPM_CC                                    |   .commandCode                               00000167             TPM_CC.LoadExternal
TPMS_COMMAND_HANDLES_LOAD_EXTERNAL        |   .handles
TPMS_COMMAND_PARAMS_LOAD_EXTERNAL         |   .parameters
TPM2B_SENSITIVE                           |   |   .inPrivate
UINT16                                    |   |   |   .size                              0000                 0
TPMT_SENSITIVE                            |   |   |   .sensitiveArea
TPM2B_PUBLIC                              |   |   .inPublic
UINT16                                    |   |   |   .size                              0056                 86
TPMT_PUBLIC                               |   |   |   .publicArea
TPMI_ALG_PUBLIC                           |   |   |   |   .type                          0023                 TPMI_ALG_PUBLIC.ECC
TPMI_ALG_HASH                             |   |   |   |   .nameAlg                       000b                 TPMI_ALG_HASH.SHA256
TPMA_OBJECT                               |   |   |   |   .objectAttributes              00060040             393280
                                          |   |   |   |   |   .reserved                                       ...............................0
                                          |   |   |   |   |   .fixedTPM                                       ..............................0.
                                          |   |   |   |   |   .stClear                                        .............................0..
                                          |   |   |   |   |   .reserved0                                      ............................0...
                                          |   |   |   |   |   .fixedParent                                    ...........................0....
                                          |   |   |   |   |   .sensitiveDataOrigin                            ..........................0.....
                                          |   |   |   |   |   .userWithAuth                                   .........................1......
                                          |   |   |   |   |   .adminWithPolicy                                ........................0.......
                                          |   |   |   |   |   .reserved1                                      ......................00........
                                          |   |   |   |   |   .noDA                                           .....................0..........
                                          |   |   |   |   |   .encryptedDuplication                           ....................0...........
                                          |   |   |   |   |   .reserved2                                      ................0000............
                                          |   |   |   |   |   .restricted                                     ...............0................
                                          |   |   |   |   |   .decrypt                                        ..............1.................
                                          |   |   |   |   |   .sign_decrypt                                   .............1..................
                                          |   |   |   |   |   .sign                                           ............0...................
                                          |   |   |   |   |   .reserved3                                      000000000000....................
TPM2B_DIGEST                              |   |   |   |   .authPolicy
UINT16                                    |   |   |   |   |   .size                      0000                 0
list[BYTE]                                |   |   |   |   |   .buffer
TPMU_PUBLIC_PARMS                         |   |   |   |   .parameters
TPMS_ECC_PARMS                            |   |   |   |   |   .eccDetail
TPMT_SYM_DEF_OBJECT                       |   |   |   |   |   |   .symmetric
TPMI_ALG_SYM_OBJECT                       |   |   |   |   |   |   |   .algorithm         0010                 TPMI_ALG_SYM_OBJECT.NULL
TPMU_SYM_KEY_BITS                         |   |   |   |   |   |   |   .keyBits
TPMU_SYM_MODE                             |   |   |   |   |   |   |   .mode
TPMU_SYM_DETAILS                          |   |   |   |   |   |   |   .details
TPMT_ECC_SCHEME                           |   |   |   |   |   |   .scheme
TPMI_ALG_ECC_SCHEME                       |   |   |   |   |   |   |   .scheme            0010                 TPMI_ALG_ECC_SCHEME.NULL
TPMU_ASYM_SCHEME                          |   |   |   |   |   |   |   .details
TPMI_ECC_CURVE                            |   |   |   |   |   |   .curveID               0003                 TPMI_ECC_CURVE.NIST_P256
TPMT_KDF_SCHEME                           |   |   |   |   |   |   .kdf
TPMI_ALG_KDF                              |   |   |   |   |   |   |   .scheme            0010                 TPMI_ALG_KDF.NULL
TPMU_KDF_SCHEME                           |   |   |   |   |   |   |   .details
TPMU_PUBLIC_ID                            |   |   |   |   .unique
TPMS_ECC_POINT                            |   |   |   |   |   .ecc
TPM2B_ECC_PARAMETER                       |   |   |   |   |   |   .x
UINT16                                    |   |   |   |   |   |   |   .size              0020                 32
list[BYTE]                                |   |   |   |   |   |   |   .buffer            f1ef85f33015e46293608004c167d9cfef3b4d37e01a19b6697930823da93d77 ....0..b.`...g...;M7....iy0.=.=w
TPM2B_ECC_PARAMETER                       |   |   |   |   |   |   .y
UINT16                                    |   |   |   |   |   |   |   .size              0020                 32
list[BYTE]                                |   |   |   |   |   |   |   .buffer            9d845395e9720dcaf765255ce321c7f588e0b5c29f6355caf99953b741f47aed ..S..r...e%\.!.......cU...S.A.z.
TPMI_RH_HIERARCHY                         |   |   .hierarchy                             40000001             TPM_RH.OWNER

Response                                  .
TPM_ST                                    |   .tag                                       8001                 TPM_ST.NO_SESSIONS
UINT32                                    |   .responseSize                              00000032             50
TPM_RC                                    |   .responseCode                              00000000             TPM_RC.SUCCESS
TPMS_RESPONSE_HANDLES_LOAD_EXTERNAL       |   .handles
TPM_HANDLE                                |   |   .objectHandle                          80000002             TPM_HR.TRANSIENT.000002
TPMS_RESPONSE_PARAMS_LOAD_EXTERNAL        |   .parameters
TPM2B_NAME                                |   |   .name
UINT16                                    |   |   |   .size                              0022                 34
list[BYTE]                                |   |   |   .name                              000b81cda27e7bb1a82b4e8b04994a856cb838329451d4f834ec74a003c2c4a0c8a6 .....~{..+N...J.l.82.Q..4.t.......

How I got it:

Start TPM simulator in its own terminal:

swtpm socket --tpm2 -p 2321 --ctrl type=tcp,port=2322 --log fd=1,level=5 --flags not-need-init --tpmstate dir=. --locality allow-set-locality

Generate key:

❯ openssl ecparam -name prime256v1 -genkey -noout -out key.pem
❯ openssl ec -in key.pem -pubout > key_public.pem
read EC key
writing EC key

Load key into TPM simulator and dump the traffic into tpm2_log.pcap (requires tpm2-tss >= v3.1.0):

❯ tpm2_startup -c -T swtpm
❯ tpm2_loadexternal -C o -Gecc -u key_public.pem -c key.ctx --tcti=swtpm
name: 000b81cda27e7bb1a82b4e8b04994a856cb838329451d4f834ec74a003c2c4a0c8a6

Decode the TPM traffic:

❯ tpmstream convert tpm2_log.pcap
# for output see above