Created
May 16, 2018 15:12
-
-
Save apowers313/8660902ffbcae31abcbc252220fce18d to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var challengeResponseAttestationTpmB64UrlMsg = { | |
"fmt": "tpm", | |
"authData": "ACH1_AuFzSLmBiO819HKSJSJCSSbR3brUVFU5XtmrhJFAAAAAAiYcFjK3EuBtuEw3lDcvpYAICichPudWAHSGBGutbra6sponHJq46QSqYSTvuECv9TypAEDAzkBACBZAQDIy_NkHfALX9bo4IcTFhfTYqiN5oTA6fLeYWSdYuRDl0Kc36xJlsmUn7684N-H1LiUjc2ikyVKQOEvcXWt_M_8m3hf9hnPF5srGVb9PJy7Hu_Al5c0AKvDW8MvuWQtLdoyqyjc_K2zufHb-p3JAwas-ASJmBNTKC5N5I372SUk4h_POnUIBcS2ILeANcrz1IMKwkMpPVbWviOoZBOmJlpHW-gmGStCgXNZkipAwIf_iyf3O9psN8aNY-2xq6iwBBkoK5RejNcJu29Hd5boCIpWN2eGrYb77EVI_tdpmgftwqdUkeF4f8eUIIB9EIF8bsCAAHQETDVoWaMVezcfwmsDIUMBAAE", | |
"attStmt": { | |
"ver": "2.0", | |
"alg": -262, | |
"sig": "ZJhH97wfhLNjAspXDakD_cW5ciDRPmKQf58PBSCAusj02nD49gRdDJVCk0-oDZ-z0yYSXL0Odyl2pTsAaIPyobFuN4LX4-WzoZzp1P93xQhE5IsRSTuk4R2K7FBu6VRQ10oc0GkEk_vniHtDkfssxjcolicVxHTrB2Ozs4GkJeiyz2I6H1apfZaUFJRJS8PbUTdEtSTEbKUGV9ZoxOgwTj0yeP0MxlZaA_xnrZEF3LH4XeOgTge1T4HRjkb0_68nFmnI7icqVe9YTdb2ItV2C2-FDBdyfhPPsQ95MAciDcNOe9JSjG3Mb9Wkkl6u-9YGfXUwA8rioISXGyuS1kCXVA", | |
"x5c": ["MIIEsjCCA5qgAwIBAgIQR5Ytn5Z0QAe2iJH35QrP1jANBgkqhkiG9w0BAQsFADBBMT8wPQYDVQQDEzZOQ1UtTlRDLUtFWUlELTE1OTFENEI2RUFGOThEMDEwNDg2NEI2OTAzQTQ4REQwMDI2MDc3RDMwHhcNMTcxMDE2MTg0MDQ0WhcNMjcxMDE2MTg0MDQ0WjAAMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwYSx7L2yfVC-GKaX2Mbdw7TKUyRXb4ymOo4w967_UFx_S5uDMpM00dTGt_MsOlpAo_UVvSLyBs-4eOgOeGFj2LDmcYEOinUZuefyxYtLPgrd7sE2JBfrnRtR8rJ-_DGIbzV15hfkzaeKABbsgKNnMGraKcVVhDgENMoT-fmH-4nTtX1Gh9mKVO_693WGSNg29bP2KUGn6F2EBQq08YfswydfqEXlwF3nuy1V3bMoKr_uNatQk5Kk0nS5rvmfxbjku3bLJIKsA5hkYHD2sQJ708VQ5jeO_Pufaru_8a9Z1q5tErdAMjzTHFJ3UuTmpI_ZHHhZ-1ooHSKQYG3PvvFzVwIDAQABo4IB5TCCAeEwDgYDVR0PAQH_BAQDAgeAMAwGA1UdEwEB_wQCMAAwbQYDVR0gAQH_BGMwYTBfBgkrBgEEAYI3FR8wUjBQBggrBgEFBQcCAjBEHkIAVABDAFAAQQAgACAAVAByAHUAcwB0AGUAZAAgACAAUABsAGEAdABmAG8AcgBtACAAIABJAGQAZQBuAHQAaQB0AHkwEAYDVR0lBAkwBwYFZ4EFCAMwSgYDVR0RAQH_BEAwPqQ8MDoxODAOBgVngQUCAwwFaWQ6MTMwEAYFZ4EFAgIMB05QQ1Q2eHgwFAYFZ4EFAgEMC2lkOjRFNTQ0MzAwMB8GA1UdIwQYMBaAFMISqVvO-lb4wMFvsVvdAzRHs3qjMB0GA1UdDgQWBBRALYmx3IcOe-liGxJPle4H_d9BEDCBswYIKwYBBQUHAQEEgaYwgaMwgaAGCCsGAQUFBzAChoGTaHR0cHM6Ly9hemNzcHJvZG5jdWFpa3B1Ymxpc2guYmxvYi5jb3JlLndpbmRvd3MubmV0L25jdS1udGMta2V5aWQtMTU5MWQ0YjZlYWY5OGQwMTA0ODY0YjY5MDNhNDhkZDAwMjYwNzdkMy8zYjkxOGFlNC0wN2UxLTQwNTktOTQ5MS0wYWQyNDgxOTA4MTguY2VyMA0GCSqGSIb3DQEBCwUAA4IBAQCs7BOMAuiEPEM4cJ2AKzhNnJiQ9geUkhOXf7Ja0mO_9oe6c2ie4QswGccRYVIkY3sZCA54qVaGkVRp3bEDNHrwI57Q8oY9GpBVv04JtbTdmGeJmnlAV8qPUBMibraU2MaT0cRh1k3lZhax0KncAnPCrTyRInWdzKvItoHpBj1ybVWCDRUZFSxLFUMyk_afsAm-rK6R-EBl7uzsXB14lQx04FrLiYqCKab1zbdwcedM7G54Pm06wW5r59ZrkJtLMWTHugdCpr61M1h22bsAlr3HavZRoIg-dX0j6o0A8dDd7mKUeo7twWdZEwYjKK3yMxzOLleD3uFgIxxlbAag6r0S", "MIIF6DCCA9CgAwIBAgITMwAAAQDiBsSROVGXhwAAAAABADANBgkqhkiG9w0BAQsFADCBjDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjE2MDQGA1UEAxMtTWljcm9zb2Z0IFRQTSBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAyMDE0MB4XDTE3MDIwMTE3NDAyNFoXDTI5MTIzMTE3NDAyNFowQTE_MD0GA1UEAxM2TkNVLU5UQy1LRVlJRC0xNTkxRDRCNkVBRjk4RDAxMDQ4NjRCNjkwM0E0OEREMDAyNjA3N0QzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA9IwUMSiQUbrQR0NLkKR-9RB8zfHYdlmDB0XN_m8qrNHKRJ__lBOR-mwU_h3MFRZF6X3ZZwka1DtwBdzLFV8lVu33bc15stjSd6B22HRRKQ3sIns5AYQxg0eX2PtWCJuIhxdM_jDjP2hq9Yvx-ibt1IO9UZwj83NGxXc7Gk2UvCs9lcFSp6U8zzl5fGFCKYcxIKH0qbPrzjlyVyZTKwGGSTeoMMEdsZiq-m_xIcrehYuHg-FAVaPLLTblS1h5cu80-ruFUm5Xzl61YjVU9tAV_Y4joAsJ5QP3VPocFhr5YVsBVYBiBcQtr5JFdJXZWWEgYcFLdAFUk8nJERS7-5xLuQIDAQABo4IBizCCAYcwCwYDVR0PBAQDAgGGMBsGA1UdJQQUMBIGCSsGAQQBgjcVJAYFZ4EFCAMwFgYDVR0gBA8wDTALBgkrBgEEAYI3FR8wEgYDVR0TAQH_BAgwBgEB_wIBADAdBgNVHQ4EFgQUwhKpW876VvjAwW-xW90DNEezeqMwHwYDVR0jBBgwFoAUeowKzi9IYhfilNGuVcFS7HF0pFYwcAYDVR0fBGkwZzBloGOgYYZfaHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9jcmwvTWljcm9zb2Z0JTIwVFBNJTIwUm9vdCUyMENlcnRpZmljYXRlJTIwQXV0aG9yaXR5JTIwMjAxNC5jcmwwfQYIKwYBBQUHAQEEcTBvMG0GCCsGAQUFBzAChmFodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NlcnRzL01pY3Jvc29mdCUyMFRQTSUyMFJvb3QlMjBDZXJ0aWZpY2F0ZSUyMEF1dGhvcml0eSUyMDIwMTQuY3J0MA0GCSqGSIb3DQEBCwUAA4ICAQAKc9z1UUBAaybIVnK8yL1N1iGJFFFFw_PpkxW76hgQhUcCxNFQskfahfFzkBD05odVC1DKyk2PyOle0G86FCmZiJa14MtKNsiu66nVqk2hr8iIcu-cYEsgb446yIGd1NblQKA1C_28F2KHm8YRgcFtRSkWEMuDiVMa0HDU8aI6ZHO04Naj86nXeULJSZsA0pQwNJ04-QJP3MFQzxQ7md6D-pCx-LVA-WUdGxT1ofaO5NFxq0XjubnZwRjQazy_m93dKWp19tbBzTUKImgUKLYGcdmVWXAxUrkxHN2FbZGOYWfmE2TGQXS2Z-g4YAQo1PleyOav3HNB8ti7u5HpI3t9a73xuECy2gFcZQ24DJuBaQe4mU5I_hPiAa-822nPPL6w8m1eegxhHf7ziRW_hW8s1cvAZZ5Jpev96zL_zRv34MsRWhKwLbu2oOCSEYYh8D8DbQZjmsxlUYR_q1cP8JKiIo6NNJ85g7sjTZgXxeanA9wZwqwJB-P98VdVslC17PmVu0RHOqRtxrht7OFT7Z10ecz0tj9ODXrv5nmBktmbgHRirRMl84wp7-PJhTXdHbxZv-OoL4HP6FxyDbHxLB7QmR4-VoEZN0vsybb1A8KEj2pkNY_tmxHH6k87euM99bB8FHrW9FNrXCGL1p6-PYtiky52a5YQZGT8Hz-ZnxobTg"], | |
"certInfo": "_1RDR4AXACIACxHmjtRNtTcuFCluL4Ssx4OYdRiBkh4w_CKgb4tzx5RTABQaCtAxc_7NUMbYJrPXp-boJN_r-wAAAAFHcBdIVWl7S8aFYKUBc375jTRWVfsAIgALycjv5SUvmOS-5QCTo-NeCZEPrZ0sT2Otuqi_GKPJ5oIAIgAL0leq1oNrtzlP67MKHW9hh6epJPh2higlQCaOdtivlmE", | |
"pubArea": "AAEACwAGBHIAIJ3_y_NsODrmmfuYaNxty4nXFTiEvigDkiwSQVi_rSKuABAAEAgAAAAAAAEAyMvzZB3wC1_W6OCHExYX02KojeaEwOny3mFknWLkQ5dCnN-sSZbJlJ--vODfh9S4lI3NopMlSkDhL3F1rfzP_Jt4X_YZzxebKxlW_Tycux7vwJeXNACrw1vDL7lkLS3aMqso3Pyts7nx2_qdyQMGrPgEiZgTUyguTeSN-9klJOIfzzp1CAXEtiC3gDXK89SDCsJDKT1W1r4jqGQTpiZaR1voJhkrQoFzWZIqQMCH_4sn9zvabDfGjWPtsauosAQZKCuUXozXCbtvR3eW6AiKVjdnhq2G--xFSP7XaZoH7cKnVJHheH_HlCCAfRCBfG7AgAB0BEw1aFmjFXs3H8JrAw" | |
} | |
}; | |
function tpmParseFn() { | |
var certInfo = coerceToArrayBuffer(challengeResponseAttestationTpmB64UrlMsg.attStmt.certInfo, "certInfo"); | |
var pubArea = coerceToArrayBuffer(challengeResponseAttestationTpmB64UrlMsg.attStmt.pubArea, "pubArea"); | |
parseCertInfo(certInfo); | |
parsePubArea(pubArea); | |
} | |
function parseCertInfo(certInfo) { | |
if (!(certInfo instanceof ArrayBuffer)) { | |
throw new Error("tpm attestation: expected certInfo to be ArrayBuffer"); | |
} | |
var dv = new DataView(certInfo); | |
var offset = 0; | |
var ret; | |
var ci = new Map(); | |
// TPM_GENERATED_VALUE magic number | |
ci.set("magic", dv.getUint32(offset)); | |
offset += 4; | |
// TPMI_ST_ATTEST type | |
ci.set("type", dv.getUint16(offset)); | |
offset += 2; | |
// TPM2B_NAME qualifiedSigner | |
ret = getTpm2bName(dv, offset); | |
ci.set("qualifiedSignerHashType", ret.hashType); | |
ci.set("qualifiedSigner", ret.nameHash); | |
offset = ret.offset; | |
// TPM2B_DATA extraData | |
ret = getSizedElement(dv, offset); | |
ci.set("extraData", ret.dv); | |
offset = ret.offset; | |
// TPMS_CLOCK_INFO clockInfo | |
// UINT64 clock | |
ci.set("clock", dv.buffer.slice(offset, offset + 8)); | |
offset += 8; | |
// UINT32 resetCount | |
ci.set("resetCount", dv.getUint32(offset)); | |
offset += 4; | |
// UINT32 restartCount | |
ci.set("restartCount", dv.getUint32(offset)); | |
offset += 4; | |
// boolean safe | |
ci.set("safe", !!dv.getUint8(offset)); | |
offset++; | |
// UINT64 firmwareVersion | |
ci.set("firmwareVersion", dv.buffer.slice(offset, offset + 8)); | |
offset += 8; | |
// TPMU_ATTEST attested | |
// TPM2B_NAME name | |
ret = getTpm2bName(dv, offset); | |
ci.set("nameHashType", ret.hashType); | |
ci.set("name", ret.nameHash); | |
offset = ret.offset; | |
// TPM2B_NAME qualifiedName | |
ret = getTpm2bName(dv, offset); | |
ci.set("qualifiedNameHashType", ret.hashType); | |
ci.set("qualifiedName", ret.nameHash); | |
offset = ret.offset; | |
if (offset !== certInfo.byteLength) { | |
throw new Error("tpm attestation: left over bytes when parsing cert info"); | |
} | |
return ci; | |
} | |
function parsePubArea(pubArea) { | |
if (!(pubArea instanceof ArrayBuffer)) { | |
throw new Error("tpm attestation: expected pubArea to be ArrayBuffer"); | |
} | |
var dv = new DataView(pubArea); | |
var offset = 0; | |
var ret; | |
var pa = new Map(); | |
// TPMI_ALG_PUBLIC type | |
pa.set("type", algIdToStr(dv.getUint16(offset))); | |
offset += 2; | |
// TPMI_ALG_HASH nameAlg | |
pa.set("nameAlg", algIdToStr(dv.getUint16(offset))); | |
offset += 2; | |
// TPMA_OBJECT objectAttributes | |
pa.set("objectAttributes", decodeObjectAttributes(dv.getUint32(offset))); | |
offset += 4; | |
// TPM2B_DIGEST authPolicy | |
ret = getSizedElement(dv, offset); | |
pa.set("authPolicy", ret.dv); | |
offset = ret.offset; | |
// TPMU_PUBLIC_PARMS parameters | |
pa.set("symmetric", algIdToStr(dv.getUint16(offset))); | |
offset += 2; | |
pa.set("scheme", algIdToStr(dv.getUint16(offset))); | |
offset += 2; | |
pa.set("keyBits", dv.getUint16(offset)); | |
offset += 2; | |
pa.set("exponent", dv.getUint32(offset)); | |
offset += 4; | |
// TPMU_PUBLIC_ID unique | |
ret = getSizedElement(dv, offset); | |
pa.set("unique", ret.dv); | |
offset = ret.offset; | |
if (offset !== pubArea.byteLength) { | |
throw new Error("tpm attestation: left over bytes when parsing public area"); | |
} | |
return pa; | |
} | |
function decodeObjectAttributes(oa) { | |
var attrList = [ | |
"RESERVED_0", | |
"FIXED_TPM", | |
"ST_CLEAR", | |
"RESERVED_3", | |
"FIXED_PARENT", | |
"SENSITIVE_DATA_ORIGIN", | |
"USER_WITH_AUTH", | |
"ADMIN_WITH_POLICY", | |
"RESERVED_8", | |
"RESERVED_9", | |
"NO_DA", | |
"ENCRYPTED_DUPLICATION", | |
"RESERVED_12", | |
"RESERVED_13", | |
"RESERVED_14", | |
"RESERVED_15", | |
"RESTRICTED", | |
"DECRYPT", | |
"SIGN_ENCRYPT", | |
"RESERVED_19", | |
"RESERVED_20", | |
"RESERVED_21", | |
"RESERVED_22", | |
"RESERVED_23", | |
"RESERVED_24", | |
"RESERVED_25", | |
"RESERVED_26", | |
"RESERVED_27", | |
"RESERVED_28", | |
"RESERVED_29", | |
"RESERVED_30", | |
"RESERVED_31" | |
]; | |
var ret = new Set(); | |
for (let i = 0; i < 32; i++) { | |
let bit = 1 << i; | |
if (oa & bit) { | |
ret.add(attrList[i]); | |
} | |
} | |
return ret; | |
} | |
function getSizedElement(dv, offset) { | |
var size = dv.getUint16(offset); | |
offset += 2; | |
var buf = dv.buffer.slice(offset, offset + size); | |
dv = new DataView(buf); | |
offset += size; | |
return { | |
size, | |
dv, | |
offset | |
}; | |
} | |
function getTpm2bName(dvIn, oIn) { | |
var { | |
offset, | |
dv | |
} = getSizedElement(dvIn, oIn); | |
var hashType = algIdToStr(dv.getUint16(0)); | |
var nameHash = dv.buffer.slice(2); | |
return { | |
hashType, | |
nameHash, | |
offset | |
}; | |
} | |
function algIdToStr(hashType) { | |
var hashList = [ | |
"TPM_ALG_ERROR", // 0 | |
"TPM_ALG_RSA", // 1 | |
null, | |
null, | |
"TPM_ALG_SHA1", // 4 | |
"TPM_ALG_HMAC", // 5 | |
"TPM_ALG_AES", // 6 | |
"TPM_ALG_MGF1", // 7 | |
null, | |
"TPM_ALG_KEYEDHASH", // 8 | |
"TPM_ALG_XOR", // A | |
"TPM_ALG_SHA256", // B | |
"TPM_ALG_SHA384", // C | |
"TPM_ALG_SHA512", // D | |
null, | |
null, | |
"TPM_ALG_NULL", // 10 | |
null, | |
"TPM_ALG_SM3_256", // 12 | |
"TPM_ALG_SM4", // 13 | |
"TPM_ALG_RSASSA", // 14 | |
"TPM_ALG_RSAES", // 15 | |
"TPM_ALG_RSAPSS", // 16 | |
"TPM_ALG_OAEP", // 17 | |
"TPM_ALG_ECDSA" // 18 | |
]; | |
return hashList[hashType]; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment