Cannot parse TPM2.0 public key

I am unsuccessfully trying to use Go to parse a TPM2.0 public key. The error that I receive seems to indicate that the parsing fail due to some sort of ‘structure error’. The full error is shown below. I also have created a minimal reproducible example and posted it below. How can I resolve this parsing issue?

Error:

{"time":"2024-09-06T18:11:36.5146545Z","level":"INFO","msg":"AK Public PEM is: ","!BADKEY":"-----BEGIN TPM2 PUBLIC KEY-----nBIIBGAABAAsABSRyAAAAEAAUAAsIAAAAAAABAJqe9l3iktbQ5bPENbFbNvOeg3upnNKvZZ+EcdUPltkibbs2N/DBfTLaOoGmkByHn16F0Sim8yV14cMQ75CBUvNCq/yFEnVPwJCCrM3kRo7Z+yPvftgtctKHRCKi9VouDaRfEIwIOMlYFtksyoXaS4Box29WiUn52Dm9O5AUChsgkeJB+e8DVZd2oZX4s7TGaGif1b4mYtKcTJqVzv55S05NW4TPoTcnXJbhdTjDqiNbaL5BUklyevYqj8XF4GzbmdGohF9wIYcuoNJo03ZcntScteFynReLn3BFVCZCNlvNoNN1QY6xKdKevDdwVBgfXWrOGGlSW4PpmJTH1tMeXx3xwlOM=n-----END TPM2 PUBLIC KEY-----n"}
{"time":"2024-09-06T18:11:36.5153675Z","level":"INFO","msg":"Block type is: ","!BADKEY":"TPM2 PUBLIC KEY"}
{"time":"2024-09-06T18:11:36.517942375Z","level":"INFO","msg":"asn1: structure error: tags don't match (16 vs {class:0 tag:4 length:280 isCompound:false}) {optional:false explicit:false application:false private:false defaultValue:<nil> tag:<nil> stringType:0 timeType:0 set:false omitEmpty:false} publicKeyInfo @4"}

Example:

package main

import (
    "crypto/x509"
    "encoding/pem"
    "fmt"
    "github.com/google/go-attestation/attest"
    "log/slog"
    "os"
)

// Global variables
var (
    port             string
    tpmPath          string
    tpm              *attest.TPM
    logger           *slog.Logger
    knownEKs         map[string][]byte
    currentChallenge []byte
)

// TPM2PublicKey represents the structure of a TPM2 public key
type TPM2PublicKey struct {
    Type       uint16
    NameAlg    uint16
    Attributes uint32
    AuthPolicy []byte
    Parameters TPM2PublicKeyParameters
    Unique     TPM2PublicKeyUnique
}

type TPM2PublicKeyParameters struct {
    SymmetricAlgorithm uint16
    Scheme             uint16
    KeyBits            uint16
    Exponent           uint32
}

type TPM2PublicKeyUnique struct {
    RSA []byte
}

func main() {

    // Initialize structured logger
    logger = slog.New(slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{Level: slog.LevelInfo}))
    
    akPubPEM := "-----BEGIN TPM2 PUBLIC KEY-----nBIIBGAABAAsABSRyAAAAEAAUAAsIAAAAAAABAJqe9l3iktbQ5bPENbFbNvOeg3upnNKvZZ+EcdUPltkibbs2N/DBfTLaOoGmkByHn16F0Sim8yV14cMQ75CBUvNCq/yFEnVPwJCCrM3kRo7Z+yPvftgtctKHRCKi9VouDaRfEIwIOMlYFtksyoXaS4Box29WiUn52Dm9O5AUChsgkeJB+e8DVZd2oZX4s7TGaGif1b4mYtKcTJqVzv55S05NW4TPoTcnXJbhdTjDqiNbaL5BUklyevYqj8XF4GzbmdGohF9wIYcuoNJo03ZcntScteFynReLn3BFVCZCNlvNoNN1QY6xKdKevDdwVBgfXWrOGGlSW4PpmJTH1tMeXx3xwlOM=n-----END TPM2 PUBLIC KEY-----n"

    logger.Info("AK Public PEM is: ", akPubPEM)

    block, _ := pem.Decode([]byte(akPubPEM))
    logger.Info("Block type is: ", block.Type)
    if block == nil || block.Type != "TPM2 PUBLIC KEY" {
        logger.Info("failed to decode PEM block containing public key")
        os.Exit(1)
    }

    pub, err := x509.ParsePKIXPublicKey(block.Bytes)
    if err != nil {
        logger.Info(err.Error())
        os.Exit(1)
    }

    fmt.Printf("Parsed public key: %vn", pub)

    // Unmarshal ASN.1 structure
    // var tpm2Pub TPM2PublicKey
    // _, err := asn1.Unmarshal(block.Bytes, &tpm2Pub)
    // if err != nil {
    //  logger.Info("ERROR: Failed to unmarshal: ", err)
    //  os.Exit(1)
    // }

    // // Convert TPM2 public key to RSA public key
    // if tpm2.Algorithm(tpm2Pub.Type) != tpm2.AlgRSA {
    //  os.Exit(1)
    // }

    os.Exit(0)

}

1

You have your key with a base64 payload:

-----BEGIN TPM2 PUBLIC KEY-----
BIIBGAABAAsABSRyAAAAEAAUAAsIAAAAAAABAJqe9l3iktbQ5bPENbFbNvOeg3up
NKvZZ+EcdUPltkibbs2N/DBfTLaOoGmkByHn16F0Sim8yV14cMQ75CBUvNCq/yFE
VPwJCCrM3kRo7Z+yPvftgtctKHRCKi9VouDaRfEIwIOMlYFtksyoXaS4Box29WiU
52Dm9O5AUChsgkeJB+e8DVZd2oZX4s7TGaGif1b4mYtKcTJqVzv55S05NW4TPoTc
XJbhdTjDqiNbaL5BUklyevYqj8XF4GzbmdGohF9wIYcuoNJo03ZcntScteFynReL
3BFVCZCNlvNoNN1QY6xKdKevDdwVBgfXWrOGGlSW4PpmJTH1tMeXx3xwlOM=
-----END TPM2 PUBLIC KEY-----

If you base64-decode the payload, you get the following binary blob (here as hex string):

048201180001000b00052472000000100014000b08000000000001009a9e
f65de292d6d0e5b3c435b15b36f39e837ba934abd967e11c7543e5b6489b
6ecd8dfc305f4cb68ea069a40721e7d7a1744a29bcc95d7870c43be42054
bcd0aaff214454fc09082accde4468ed9fb23ef7ed82d72d2874422a2f55
a2e0da45f108c0838c95816d92cca85da4b8068c76f56894e760e6f4ee40
50286c82478907e7bc0d565dda8657e2ced319a1a27f56f8998b4a71326a
573bf9e52d39356e133e84dc5c96e17538c3aa235b68be415249727af62a
8fc5c5e06cdb99d1a8845f7021872ea0d268d3765c9ed49cb5e1729d178b
dc115509908d96f36834dd5063ac4a74a7af0ddc150607d75ab3861a5496
e0fa662531f5b4c797c77c7094e3

This is ASN.1 DER. So we DER-decode this. The following is breaks it down. You see, this is just a DER octet string:

04     # this is an ASN.1 tag for an OCTET STRING.
820118 # length field. 0x82: length is encoded in two bytes, length: 0x0118 = 280 bytes
<octet string payload>

DER octet string payload:

0001000b00052472000000100014000b08000000000001009a9e
f65de292d6d0e5b3c435b15b36f39e837ba934abd967e11c7543e5b6489b
6ecd8dfc305f4cb68ea069a40721e7d7a1744a29bcc95d7870c43be42054
bcd0aaff214454fc09082accde4468ed9fb23ef7ed82d72d2874422a2f55
a2e0da45f108c0838c95816d92cca85da4b8068c76f56894e760e6f4ee40
50286c82478907e7bc0d565dda8657e2ced319a1a27f56f8998b4a71326a
573bf9e52d39356e133e84dc5c96e17538c3aa235b68be415249727af62a
8fc5c5e06cdb99d1a8845f7021872ea0d268d3765c9ed49cb5e1729d178b
dc115509908d96f36834dd5063ac4a74a7af0ddc150607d75ab3861a5496
e0fa662531f5b4c797c77c7094e3

The payload is a TPM TPMT_PUBLIC structure (which you called TPM2PublicKey). Let’s decode that:

TPMT_PUBLIC             .
TPMI_ALG_PUBLIC         |   .type                          0001      TPMI_ALG_PUBLIC.RSA
TPMI_ALG_HASH           |   .nameAlg                       000b      TPMI_ALG_HASH.SHA256
TPMA_OBJECT             |   .objectAttributes              00052472  TPMA_OBJECT.fixedTPM | TPMA_OBJECT.fixedParent | TPMA_OBJECT.sensitiveDataOrigin | TPMA_OBJECT.userWithAuth | TPMA_OBJECT.noDA | TPMA_OBJECT.reserved2 | TPMA_OBJECT.restricted | TPMA_OBJECT.sign_decrypt
                        |   |   .reserved                            ...............................0
                        |   |   .fixedTPM                            ..............................1.
                        |   |   .stClear                             .............................0..
                        |   |   .reserved0                           ............................0...
                        |   |   .fixedParent                         ...........................1....
                        |   |   .sensitiveDataOrigin                 ..........................1.....
                        |   |   .userWithAuth                        .........................1......
                        |   |   .adminWithPolicy                     ........................0.......
                        |   |   .reserved1                           ......................00........
                        |   |   .noDA                                .....................1..........
                        |   |   .encryptedDuplication                ....................0...........
                        |   |   .reserved2                           ................0010............
                        |   |   .restricted                          ...............1................
                        |   |   .decrypt                             ..............0.................
                        |   |   .sign_decrypt                        .............1..................
                        |   |   .sign                                ............0...................
                        |   |   .reserved3                           000000000000....................
TPM2B_DIGEST            |   .authPolicy
UINT16                  |   |   .size                      0000      0
list[BYTE]              |   |   .buffer
TPMU_PUBLIC_PARMS       |   .parameters
TPMS_RSA_PARMS          |   |   .rsaDetail
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_RSA_SCHEME         |   |   |   .scheme
TPMI_ALG_RSA_SCHEME     |   |   |   |   .scheme            0014      TPMI_ALG_RSA_SCHEME.RSASSA
TPMU_ASYM_SCHEME        |   |   |   |   .details
TPMS_SIG_SCHEME_RSASSA  |   |   |   |   |   .rsassa
TPMI_ALG_HASH           |   |   |   |   |   |   .hashAlg   000b      TPMI_ALG_HASH.SHA256
TPMI_RSA_KEY_BITS       |   |   |   .keyBits               0800      2048
UINT32                  |   |   |   .exponent              00000000  0
TPMU_PUBLIC_ID          |   .unique
TPM2B_PUBLIC_KEY_RSA    |   |   .rsa
UINT16                  |   |   |   .size                  0100      256
list[BYTE]              |   |   |   .buffer                9a9ef65de292d6d0e5b3c435b15b36f39e837ba934abd967e11c7543e5b6489b6ecd8dfc305f4cb68ea069a40721e7d7a1744a29bcc95d7870c43be42054bcd0aaff214454fc09082accde4468ed9fb23ef7ed82d72d2874422a2f55a2e0da45f108c0838c95816d92cca85da4b8068c76f56894e760e6f4ee4050286c82478907e7bc0d565dda8657e2ced319a1a27f56f8998b4a71326a573bf9e52d39356e133e84dc5c96e17538c3aa235b68be415249727af62a8fc5c5e06cdb99d1a8845f7021872ea0d268d3765c9ed49cb5e1729d178bdc115509908d96f36834dd5063ac4a74a7af0ddc150607d75ab3861a5496e0fa662531f5b4c797c77c7094e3 ...].......5.[6...{.4..g..uC..H.n...0_L...i..!...tJ)..]xp.;. T....!DT...*..Dh...>....-(tB*/U...E.......m...]....v.h..`...@P(l.G.....V]..W.......V...Jq2jW;..-95n.>....u8..#[h.ARIrz.*....l....._p!....h.v.....r.....U.....h4.Pc.Jt........Z...T...f%1.....|p..

2

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật