LyoKKiBDb3B5cmlnaHQgqSB7MTk5Ni0xOTk5fSwgSW50ZXJuYXRpb25hbCBCdXNpbmVzcyBNYWNoaW5lcyBDb3Jwb3JhdGlvbiBhbmQgb3RoZXJzLiBBbGwgUmlnaHRzIFJlc2VydmVkLgoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKgoqLwovLz09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0KLy8KLy8gRmlsZSBzb3J0a2V5LmgKLy8KLy8gCi8vCi8vIENyZWF0ZWQgYnk6IEhlbGVuYSBTaGloCi8vCi8vIE1vZGlmaWNhdGlvbiBIaXN0b3J5OgovLwovLyAgRGF0ZSAgICAgICAgIE5hbWUgICAgICAgICAgRGVzY3JpcHRpb24KLy8KLy8gIDYvMjAvOTcgICAgIGhlbGVuYSAgICAgIEphdmEgY2xhc3MgbmFtZSBjaGFuZ2UuCi8vICA4LzE4Lzk3ICAgICBoZWxlbmEgICAgICBBZGRlZCBpbnRlcm5hbCBBUEkgZG9jdW1lbnRhdGlvbi4KLy8gIDYvMjYvOTggICAgIGVybSAgICAgICAgIENoYW5nZWQgdG8gdXNlIGJ5dGUgYXJyYXlzIGFuZCBtZW1jbXAuIAovLz09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0KCiNpZm5kZWYgU09SVEtFWV9ICiNkZWZpbmUgU09SVEtFWV9ICgoKI2luY2x1ZGUgInVuaWNvZGUvdXR5cGVzLmgiCiNpbmNsdWRlICJ1bmljb2RlL3VuaXN0ci5oIgojaW5jbHVkZSAidW5pY29kZS9jb2xsLmgiCgovKiBmb3J3YXJkIGRlY2xhcmF0aW9uICovCmNsYXNzIFJ1bGVCYXNlZENvbGxhdG9yOwoKLyoqCiAqIENvbGxhdGlvbiBrZXlzIGFyZSBnZW5lcmF0ZWQgYnkgdGhlIENvbGxhdG9yIGNsYXNzLiAgVXNlIHRoZSBDb2xsYXRpb25LZXkgb2JqZWN0cwogKiBpbnN0ZWFkIG9mIENvbGxhdG9yIHRvIGNvbXBhcmUgc3RyaW5ncyBtdWx0aXBsZSB0aW1lcy4gIEEgQ29sbGF0aW9uS2V5CiAqIHByZXByb2Nlc3NlcyB0aGUgY29tcGFyaXNvbiBpbmZvcm1hdGlvbiBmcm9tIHRoZSBDb2xsYXRvciBvYmplY3QgdG8KICogbWFrZSB0aGUgY29tcGFyaXNvbiBmYXN0ZXIuICBJZiB5b3UgYXJlIG5vdCBnb2luZyB0byBjb21wYXJpbmcgc3RyaW5ncwogKiBtdWx0aXBsZSB0aW1lcywgdGhlbiB1c2luZyB0aGUgQ29sbGF0b3Igb2JqZWN0IGlzIGdlbmVyYWxseSBmYXN0ZXIsCiAqIHNpbmNlIGl0IG9ubHkgcHJvY2Vzc2VzIGFzIG11Y2ggb2YgdGhlIHN0cmluZyBhcyBuZWVkZWQgdG8gbWFrZSBhCiAqIGNvbXBhcmlzb24uCiAqIDxwPiBGb3IgZXhhbXBsZSAod2l0aCBzdHJlbmd0aCA9PSB0ZXJ0aWFyeSkKICogPHA+V2hlbiBjb21wYXJpbmcgIkFiZXJuYXRoeSIgdG8gIkJhZ2dpbnMtU215dGh3b3J0aHkiLCBDb2xsYXRvcgogKiBvbmx5IG5lZWRzIHRvIHByb2Nlc3MgYSBjb3VwbGUgb2YgY2hhcmFjdGVycywgd2hpbGUgYSBjb21wYXJpc29uCiAqIHdpdGggQ29sbGF0aW9uS2V5cyB3aWxsIHByb2Nlc3MgYWxsIG9mIHRoZSBjaGFyYWN0ZXJzLiAgT24gdGhlIG90aGVyIGhhbmQsCiAqIGlmIHlvdSBhcmUgZG9pbmcgYSBzb3J0IG9mIGEgbnVtYmVyIG9mIGZpZWxkcywgaXQgaXMgbXVjaCBmYXN0ZXIgdG8gdXNlCiAqIENvbGxhdGlvbktleXMsIHNpbmNlIHlvdSB3aWxsIGJlIGNvbXBhcmluZyBzdHJpbmdzIG11bHRpcGxlIHRpbWVzLgogKiA8cD5UeXBpY2FsIHVzZSBvZiBDb2xsYXRpb25LZXlzIGFyZSBpbiBkYXRhYmFzZXMsIHdoZXJlIHlvdSBzdG9yZSBhIENvbGxhdGlvbktleQogKiBpbiBhIGhpZGRlbiBmaWVsZCwgYW5kIHVzZSBpdCBmb3Igc29ydGluZyBvciBpbmRleGluZy4KICoKICogPHA+RXhhbXBsZSBvZiB1c2U6CiAqIDxwcmU+CiAqIC4gICAgVUVycm9yQ29kZSBzdWNjZXNzID0gVV9aRVJPX0VSUk9SOwogKiAuICAgIENvbGxhdG9yKiBteUNvbGxhdG9yID0gQ29sbGF0b3I6OmNyZWF0ZUluc3RhbmNlKHN1Y2Nlc3MpOwogKiAuICAgIENvbGxhdGlvbktleSoga2V5cyA9IG5ldyBDb2xsYXRpb25LZXkgWzNdOwogKiAuICAgIG15Q29sbGF0b3ItPmdldENvbGxhdGlvbktleSgiVG9tIiwga2V5c1swXSwgc3VjY2VzcyApOwogKiAuICAgIG15Q29sbGF0b3ItPmdldENvbGxhdGlvbktleSgiRGljayIsIGtleXNbMV0sIHN1Y2Nlc3MgKTsKICogLiAgICBteUNvbGxhdG9yLT5nZXRDb2xsYXRpb25LZXkoIkhhcnJ5Iiwga2V5c1syXSwgc3VjY2VzcyApOwogKiAuIAogKiAuICAgIC8vIEluc2lkZSBib2R5IG9mIHNvcnQgcm91dGluZSwgY29tcGFyZSBrZXlzIHRoaXMgd2F5OgogKiAuICAgIENvbGxhdGlvbktleSB0bXA7CiAqIC4gICAgaWYoa2V5c1swXS5jb21wYXJlVG8oIGtleXNbMV0gKSA+IDAgKSB7CiAqIC4gICAgICAgIHRtcCA9IGtleXNbMF07IGtleXNbMF0gPSBrZXlzWzFdOyBrZXlzWzFdID0gdG1wOwogKiAuICAgIH0KICogLiAgICAvLy4uLgogKiA8L3ByZT4KICogPHA+QmVjYXVzZSBDb2xsYXRvcjo6Y29tcGFyZSgpJ3MgYWxnb3JpdGhtIGlzIGNvbXBsZXgsIGl0IGlzIGZhc3RlciB0byBzb3J0CiAqIGxvbmcgbGlzdHMgb2Ygd29yZHMgYnkgcmV0cmlldmluZyBjb2xsYXRpb24ga2V5cyB3aXRoIENvbGxhdG9yOjpnZXRDb2xsYXRpb25LZXkoKS4KICogWW91IGNhbiB0aGVuIGNhY2hlIHRoZSBjb2xsYXRpb24ga2V5cyBhbmQgY29tcGFyZSB0aGVtIHVzaW5nIENvbGxhdGlvbktleTo6Y29tcGFyZVRvKCkuCiAqIDxwPgogKiA8c3Ryb25nPk5vdGU6PC9zdHJvbmc+IDxjb2RlPkNvbGxhdG9yPC9jb2RlPnMgd2l0aCBkaWZmZXJlbnQgTG9jYWxlLAogKiBDb2xsYXRpb25TdHJlbmd0aCBhbmQgRGVjb21wb3NpdGlvbk1vZGUgc2V0dGluZ3Mgd2lsbCByZXR1cm4gZGlmZmVyZW50CiAqIENvbGxhdGlvbktleXMgZm9yIHRoZSBzYW1lIHNldCBvZiBzdHJpbmdzLiBMb2NhbGVzIGhhdmUgc3BlY2lmaWMgCiAqIGNvbGxhdGlvbiBydWxlcywgYW5kIHRoZSB3YXkgaW4gd2hpY2ggc2Vjb25kYXJ5IGFuZCB0ZXJ0aWFyeSBkaWZmZXJlbmNlcyAKICogYXJlIHRha2VuIGludG8gYWNjb3VudCwgZm9yIGV4YW1wbGUsIHdpbGwgcmVzdWx0IGluIGRpZmZlcmVudCBDb2xsYXRpb25LZXlzCiAqIGZvciBzYW1lIHN0cmluZ3MuCiAqIDxwPgoKICogQHNlZSAgICAgICAgICBDb2xsYXRvcgogKiBAc2VlICAgICAgICAgIFJ1bGVCYXNlZENvbGxhdG9yCiAqIEB2ZXJzaW9uICAgICAgMS4zIDEyLzE4Lzk2CiAqIEBhdXRob3IgICAgICAgSGVsZW5hIFNoaWgKICogQGRlcHJlY2F0ZWQKICovCmNsYXNzIFVfSTE4Tl9BUEkgQ29sbGF0aW9uS2V5IHsKcHVibGljOgogICAgLyoqCiAgICAgKiBUaGlzIGNyZWF0ZXMgYW4gZW1wdHkgY29sbGF0aW9uIGtleSBiYXNlZCBvbiB0aGUgbnVsbCBzdHJpbmcuICBBbiBlbXB0eSAKICAgICAqIGNvbGxhdGlvbiBrZXkgY29udGFpbnMgbm8gc29ydGluZyBpbmZvcm1hdGlvbi4gIFdoZW4gY29tcGFyaW5nIHR3byBlbXB0eQogICAgICogY29sbGF0aW9uIGtleXMsIHRoZSByZXN1bHQgaXMgQ29sbGF0b3I6OkVRVUFMLiAgQ29tcGFyaW5nIGVtcHR5IGNvbGxhdGlvbiBrZXkKICAgICAqIHdpdGggbm9uLWVtcHR5IGNvbGxhdGlvbiBrZXkgaXMgYWx3YXlzIENvbGxhdG9yOjpMRVNTLgoJICogQGRlcHJlY2F0ZWQKICAgICAqLwogICAgIENvbGxhdGlvbktleSgpOwogICAgLyoqCiAgICAgKiBDcmVhdGVzIGEgY29sbGF0aW9uIGtleSBiYXNlZCBvbiB0aGUgY29sbGF0aW9uIGtleSB2YWx1ZXMuICAKICAgICAqIEBwYXJhbSB2YWx1ZXMgdGhlIGNvbGxhdGlvbiBrZXkgdmFsdWVzCiAgICAgKiBAcGFyYW0gY291bnQgbnVtYmVyIG9mIGNvbGxhdGlvbiBrZXkgdmFsdWVzLCBpbmNsdWRpbmcgdHJhaWxpbmcgbnVsbHMuCiAgICAgKiBAc2VlICNjcmVhdGVCaXRzCgkgKiBAZGVwcmVjYXRlZAogICAgICovCiAgICAgQ29sbGF0aW9uS2V5KGNvbnN0ICB1aW50OF90KiAgICB2YWx1ZXMsCgkJCQkJaW50MzJfdCAgICAgY291bnQpOwoKICAgIC8qKgogICAgICogQ29weSBjb25zdHJ1Y3Rvci4KCSAqIEBkZXByZWNhdGVkCiAgICAgKi8KICAgICBDb2xsYXRpb25LZXkoY29uc3QgQ29sbGF0aW9uS2V5JiBvdGhlcik7CiAgICAvKiogCiAgICAgKiBTb3J0IGtleSBkZXN0cnVjdG9yLgoJICogQGRlcHJlY2F0ZWQKICAgICAqLwogICAgIH5Db2xsYXRpb25LZXkoKTsKCiAgICAvKioKICAgICAqIEFzc2lnbm1lbnQgb3BlcmF0b3IKCSAqIEBkZXByZWNhdGVkCiAgICAgKi8KICAgIGNvbnN0ICAgQ29sbGF0aW9uS2V5JiAgICAgICAgICAgb3BlcmF0b3I9KGNvbnN0IENvbGxhdGlvbktleSYgb3RoZXIpOwoKICAgIC8qKgogICAgICogQ29tcGFyZSBpZiB0d28gY29sbGF0aW9uIGtleXMgYXJlIHRoZSBzYW1lLgogICAgICogQHBhcmFtIHNvdXJjZSB0aGUgY29sbGF0aW9uIGtleSB0byBjb21wYXJlIHRvLgogICAgICogQHJldHVybiBSZXR1cm5zIHRydWUgaWYgdHdvIGNvbGxhdGlvbiBrZXlzIGFyZSBlcXVhbCwgZmFsc2Ugb3RoZXJ3aXNlLgoJICogQGRlcHJlY2F0ZWQKICAgICAqLwogICAgIGJvb2xfdCAgICAgICAgICAgICAgICAgIG9wZXJhdG9yPT0oY29uc3QgQ29sbGF0aW9uS2V5JiBzb3VyY2UpIGNvbnN0OwoKICAgIC8qKgogICAgICogQ29tcGFyZSBpZiB0d28gY29sbGF0aW9uIGtleXMgYXJlIG5vdCB0aGUgc2FtZS4KICAgICAqIEBwYXJhbSBzb3VyY2UgdGhlIGNvbGxhdGlvbiBrZXkgdG8gY29tcGFyZSB0by4KICAgICAqIEByZXR1cm4gUmV0dXJucyBUUlVFIGlmIHR3byBjb2xsYXRpb24ga2V5cyBhcmUgZGlmZmVyZW50LCBGQUxTRSBvdGhlcndpc2UuCgkgKiBAZGVwcmVjYXRlZAogICAgICovCiAgICAgYm9vbF90ICAgICAgICAgICAgICAgICAgb3BlcmF0b3IhPShjb25zdCBDb2xsYXRpb25LZXkmIHNvdXJjZSkgY29uc3Q7CgoKICAgIC8qKgogICAgICogVGVzdCB0byBzZWUgaWYgdGhlIGtleSBpcyBpbiBhbiBpbnZhbGlkIHN0YXRlLiBUaGUga2V5IHdpbGwgYmUgaW4gYW4KICAgICAqIGludmFsaWQgc3RhdGUgaWYgaXQgY291bGRuJ3QgYWxsb2NhdGUgbWVtb3J5IGZvciBzb21lIG9wZXJhdGlvbi4KICAgICAqIEByZXR1cm4gUmV0dXJucyBUUlVFIGlmIHRoZSBrZXkgaXMgaW4gYW4gaW52YWxpZCwgRkFMU0Ugb3RoZXJ3aXNlLgoJICogQGRlcHJlY2F0ZWQKICAgICAqLwogICAgIGJvb2xfdCAgICAgICAgICAgICAgICAgIGlzQm9ndXModm9pZCkgY29uc3Q7CgogICAgLyoqIAogICAgICogUmV0dXJucyBhIHBvaW50ZXIgdG8gdGhlIGNvbGxhdGlvbiBrZXkgdmFsdWVzLiBUaGUgc3RvcmFnZSBpcyBvd25lZAogICAgICogYnkgdGhlIGNvbGxhdGlvbiBrZXkgYW5kIHRoZSBwb2ludGVyIHdpbGwgYmVjb21lIGludmFsaWQgaWYgdGhlIGtleQogICAgICogaXMgZGVsZXRlZC4KICAgICAqIEBwYXJhbSBjb3VudCB0aGUgb3V0cHV0IHBhcmFtZXRlciBvZiBudW1iZXIgb2YgY29sbGF0aW9uIGtleSB2YWx1ZXMsCiAgICAgKiBpbmNsdWRpbmcgYW55IHRyYWlsaW5nIG51bGxzLgoJICogQGRlcHJlY2F0ZWQKICAgICAqLwoJIGNvbnN0ICAgIHVpbnQ4X3QqICAgICAgICAgICAgICAgIGdldEJ5dGVBcnJheShpbnQzMl90JiBjb3VudCkgY29uc3Q7CgogICAgLyoqIAogICAgICogRXh0cmFjdHMgdGhlIGNvbGxhdGlvbiBrZXkgdmFsdWVzIGludG8gYSBuZXcgYXJyYXkuIFRoZSBjYWxsZXIgb3ducwogICAgICogdGhpcyBzdG9yYWdlIGFuZCBzaG91bGQgZnJlZSBpdC4KICAgICAqIEBwYXJhbSBjb3VudCB0aGUgb3V0cHV0IHBhcmFtZXRlciBvZiBudW1iZXIgb2YgY29sbGF0aW9uIGtleSB2YWx1ZXMsCiAgICAgKiBpbmNsdWRpbmcgYW55IHRyYWlsaW5nIG51bGxzLgoJICogQGRlcHJlY2F0ZWQKICAgICAqLwogICAgIHVpbnQ4X3QqICAgICAgICAgICAgICAgIHRvQnl0ZUFycmF5KGludDMyX3QmIGNvdW50KSBjb25zdDsKCiAgICAvKioKICAgICAqIENvbnZlbmllbmNlIG1ldGhvZCB3aGljaCBkb2VzIGEgc3RyaW5nKGJpdC13aXNlKSBjb21wYXJpc29uIG9mIHRoZQogICAgICogdHdvIGNvbGxhdGlvbiBrZXlzLgogICAgICogQHBhcmFtIHNvdXJjZUtleSBzb3VyY2UgY29sbGF0aW9uIGtleQogICAgICogQHBhcmFtIHRhcmdldEtleSB0YXJnZXQgY29sbGF0aW9uIGtleQogICAgICogQHJldHVybiBSZXR1cm5zIENvbGxhdG9yOjpMRVNTIGlmIHNvdXJjZUtleSAmbHQ7IHRhcmdldEtleSwgCiAgICAgKiBDb2xsYXRvcjo6R1JFQVRFUiBpZiBzb3VyY2VLZXkgPiB0YXJnZXRLZXkgYW5kIENvbGxhdG9yOjpFUVVBTAogICAgICogb3RoZXJ3aXNlLgoJICogQGRlcHJlY2F0ZWQKICAgICAqLwogICAgIENvbGxhdG9yOjpFQ29tcGFyaXNvblJlc3VsdCAgICBjb21wYXJlVG8oY29uc3QgQ29sbGF0aW9uS2V5JiB0YXJnZXQpIGNvbnN0OwoKICAgIC8qKgogICAgICogQ3JlYXRlcyBhbiBpbnRlZ2VyIHRoYXQgaXMgdW5pcXVlIHRvIHRoZSBjb2xsYXRpb24ga2V5LiAgTk9URTogdGhpcwogICAgICogaXMgbm90IHRoZSBzYW1lIGFzIFN0cmluZy5oYXNoQ29kZS4KICAgICAqIDxwPkV4YW1wbGUgb2YgdXNlOgogICAgICogPHByZT4KICAgICAqIC4gICAgVUVycm9yQ29kZSBzdGF0dXMgPSBVX1pFUk9fRVJST1I7CiAgICAgKiAuICAgIENvbGxhdG9yICpteUNvbGxhdGlvbiA9IENvbGxhdG9yOjpjcmVhdGVJbnN0YW5jZShMb2NhbGU6OlVTLCBzdGF0dXMpOwogICAgICogLiAgICBpZiAoVV9GQUlMVVJFKHN0YXR1cykpIHJldHVybjsKICAgICAqIC4gICAgQ29sbGF0aW9uS2V5IGtleTEsIGtleTI7CiAgICAgKiAuICAgIFVFcnJvckNvZGUgc3RhdHVzMSA9IFVfWkVST19FUlJPUiwgc3RhdHVzMiA9IFVfWkVST19FUlJPUjsKICAgICAqIC4gICAgbXlDb2xsYXRpb24tPmdldENvbGxhdGlvbktleSgiYWJjIiwga2V5MSwgc3RhdHVzMSk7CiAgICAgKiAuICAgIGlmIChVX0ZBSUxVUkUoc3RhdHVzMSkpIHsgZGVsZXRlIG15Q29sbGF0aW9uOyByZXR1cm47IH0KICAgICAqIC4gICAgbXlDb2xsYXRpb24tPmdldENvbGxhdGlvbktleSgiQUJDIiwga2V5Miwgc3RhdHVzMik7CiAgICAgKiAuICAgIGlmIChVX0ZBSUxVUkUoc3RhdHVzMikpIHsgZGVsZXRlIG15Q29sbGF0aW9uOyByZXR1cm47IH0KICAgICAqIC4gICAgLy8ga2V5MS5oYXNoQ29kZSgpICE9IGtleTIuaGFzaENvZGUoKQogICAgICogPC9wcmU+CiAgICAgKiBAcmV0dXJuIHRoZSBoYXNoIHZhbHVlIGJhc2VkIG9uIHRoZSBzdHJpbmcncyBjb2xsYXRpb24gb3JkZXIuCiAgICAgKiBAc2VlIFVuaWNvZGVTdHJpbmcjaGFzaENvZGUKCSAqIEBkZXByZWNhdGVkCiAgICAgKi8KICAgICBpbnQzMl90ICAgICAgICAgICAgICAgICBoYXNoQ29kZSh2b2lkKSBjb25zdDsKCnByaXZhdGU6CiAgICAvKioKICAgICogUmV0dXJucyBhbiBhcnJheSBvZiB0aGUgY29sbGF0aW9uIGtleSB2YWx1ZXMgYXMgMTYtYml0IGludGVnZXJzLgogICAgKiBUaGUgY2FsbGVyIG93bnMgdGhlIHN0b3JhZ2UgYW5kIG11c3QgZGVsZXRlIGl0LgogICAgKiBAcGFyYW0gc2l6ZSBvdXRwdXQgcGFyYW1ldGVyIG9mIHRoZSBudW1iZXIgb2YgY29sbGF0aW9uIGtleSB2YWx1ZXMKICAgICogQHJldHVybiBhIHBvaW50ZXIgdG8gYW4gYXJyYXkgb2YgMTYtYml0IGNvbGxhdGlvbiBrZXkgdmFsdWVzLgogICAgKi8KICAgICAgICAgICAgdWludDE2X3QqICAgICAgICAgICAgICAgY29weVZhbHVlcyhpbnQzMl90ICZzaXplKSBjb25zdDsKCiAgICAvKgogICAgICogQ3JlYXRlcyBhIGNvbGxhdGlvbiBrZXkgd2l0aCBhIHN0cmluZy4KICAgICAqLwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBDb2xsYXRpb25LZXkoY29uc3QgVW5pY29kZVN0cmluZyYgdmFsdWUpOwoKICAgICAgICAgICAgaW50MzJfdCAgICAgICAgICAgICAgICAgc3RvcmVCeXRlcyhpbnQzMl90IGN1cnNvciwgdWludDMyX3QgYnl0ZVZhbHVlKTsKICAgICAgICAgICAgaW50MzJfdCAgICAgICAgICAgICAgICAgICAgc3RvcmVVbmljb2RlU3RyaW5nKGludDMyX3QgY3Vyc29yLCBjb25zdCBVbmljb2RlU3RyaW5nICZ2YWx1ZSk7CiAgICAgICAgICAgIHZvaWQgICAgICAgICAgICAgICAgICAgIHJldmVyc2VCeXRlcyhpbnQzMl90IGZyb20sIGludDMyX3QgdG8pOwogICAgICAgICAgICBDb2xsYXRpb25LZXkmICAgICAgICAgICBlbnN1cmVDYXBhY2l0eShpbnQzMl90IG5ld1NpemUpOwogICAgICAgICAgICBDb2xsYXRpb25LZXkmICAgICAgICAgICBjb3B5VW5pY29kZVN0cmluZyhjb25zdCBVbmljb2RlU3RyaW5nICZ2YWx1ZSk7CiAgICAgICAgICAgIENvbGxhdGlvbktleSYgICAgICAgICAgIHNldFRvQm9ndXModm9pZCk7CiAgICAgICAgICAgIENvbGxhdGlvbktleSYgICAgICAgICAgIHJlc2V0KHZvaWQpOwoKICAgIGZyaWVuZCAgY2xhc3MgICAgICAgICAgICAgICAgICAgUnVsZUJhc2VkQ29sbGF0b3I7CgogICAgc3RhdGljIGNvbnN0IGludDMyX3QgICAgICAgICAgICBrSW52YWxpZEhhc2hDb2RlOwogICAgc3RhdGljIGNvbnN0IGludDMyX3QgICAgICAgICAgICBrRW1wdHlIYXNoQ29kZTsKCiAgICAgICAgICAgIGJvb2xfdCAgICAgICAgICAgICAgICAgIGZCb2d1czsKICAgICAgICAgICAgaW50MzJfdCAgICAgICAgICAgICAgICAgZkNvdW50OwogICAgICAgICAgICBpbnQzMl90ICAgICAgICAgICAgICAgICBmQ2FwYWNpdHk7CiAgICAgICAgICAgIGludDMyX3QgICAgICAgICAgICAgICAgIGZIYXNoQ29kZTsKICAgICAgICAgICAgdWludDhfdCogICAgICAgICAgICAgICAgZkJ5dGVzOwp9OwoKaW5saW5lIGJvb2xfdApDb2xsYXRpb25LZXk6Om9wZXJhdG9yIT0oY29uc3QgQ29sbGF0aW9uS2V5JiBvdGhlcikgY29uc3QKewogICAgcmV0dXJuICEoKnRoaXMgPT0gb3RoZXIpOwp9CgppbmxpbmUgYm9vbF90CkNvbGxhdGlvbktleTo6aXNCb2d1cygpIGNvbnN0CnsKICAgIHJldHVybiBmQm9ndXM7Cn0KCmlubGluZSBjb25zdCB1aW50OF90KgpDb2xsYXRpb25LZXk6OmdldEJ5dGVBcnJheShpbnQzMl90ICZjb3VudCkgY29uc3QKewogICAgY291bnQgPSBmQ291bnQ7CiAgICByZXR1cm4gZkJ5dGVzOwp9CgppbmxpbmUgVVRleHRPZmZzZXQKQ29sbGF0aW9uS2V5OjpzdG9yZUJ5dGVzKFVUZXh0T2Zmc2V0IGN1cnNvciwgdWludDMyX3QgYnl0ZVZhbHVlKQp7CiAgICBmQnl0ZXNbY3Vyc29yKytdID0gKHVpbnQ4X3QpIChieXRlVmFsdWUgPj4gOCk7CiAgICBmQnl0ZXNbY3Vyc29yKytdID0gKHVpbnQ4X3QpIGJ5dGVWYWx1ZTsKCiAgICByZXR1cm4gY3Vyc29yOwp9CgojZW5kaWYK