LyoKICogQ29weXJpZ2h0IChjKSAyMDAyIEp1aGEgWXJq9mzkLiAgQWxsIHJpZ2h0cyByZXNlcnZlZC4KICogQ29weXJpZ2h0IChjKSAyMDAxIE1hcmt1cyBGcmllZGwuCiAqCiAqIFJlZGlzdHJpYnV0aW9uIGFuZCB1c2UgaW4gc291cmNlIGFuZCBiaW5hcnkgZm9ybXMsIHdpdGggb3Igd2l0aG91dAogKiBtb2RpZmljYXRpb24sIGFyZSBwZXJtaXR0ZWQgcHJvdmlkZWQgdGhhdCB0aGUgZm9sbG93aW5nIGNvbmRpdGlvbnMKICogYXJlIG1ldDoKICogMS4gUmVkaXN0cmlidXRpb25zIG9mIHNvdXJjZSBjb2RlIG11c3QgcmV0YWluIHRoZSBhYm92ZSBjb3B5cmlnaHQKICogICAgbm90aWNlLCB0aGlzIGxpc3Qgb2YgY29uZGl0aW9ucyBhbmQgdGhlIGZvbGxvd2luZyBkaXNjbGFpbWVyLgogKiAyLiBSZWRpc3RyaWJ1dGlvbnMgaW4gYmluYXJ5IGZvcm0gbXVzdCByZXByb2R1Y2UgdGhlIGFib3ZlIGNvcHlyaWdodAogKiAgICBub3RpY2UsIHRoaXMgbGlzdCBvZiBjb25kaXRpb25zIGFuZCB0aGUgZm9sbG93aW5nIGRpc2NsYWltZXIgaW4gdGhlCiAqICAgIGRvY3VtZW50YXRpb24gYW5kL29yIG90aGVyIG1hdGVyaWFscyBwcm92aWRlZCB3aXRoIHRoZSBkaXN0cmlidXRpb24uCiAqCiAqIFRISVMgU09GVFdBUkUgSVMgUFJPVklERUQgQlkgVEhFIEFVVEhPUiBgYEFTIElTJycgQU5EIEFOWSBFWFBSRVNTIE9SCiAqIElNUExJRUQgV0FSUkFOVElFUywgSU5DTFVESU5HLCBCVVQgTk9UIExJTUlURUQgVE8sIFRIRSBJTVBMSUVEIFdBUlJBTlRJRVMKICogT0YgTUVSQ0hBTlRBQklMSVRZIEFORCBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSBBUkUgRElTQ0xBSU1FRC4KICogSU4gTk8gRVZFTlQgU0hBTEwgVEhFIEFVVEhPUiBCRSBMSUFCTEUgRk9SIEFOWSBESVJFQ1QsIElORElSRUNULAogKiBJTkNJREVOVEFMLCBTUEVDSUFMLCBFWEVNUExBUlksIE9SIENPTlNFUVVFTlRJQUwgREFNQUdFUyAoSU5DTFVESU5HLCBCVVQKICogTk9UIExJTUlURUQgVE8sIFBST0NVUkVNRU5UIE9GIFNVQlNUSVRVVEUgR09PRFMgT1IgU0VSVklDRVM7IExPU1MgT0YgVVNFLAogKiBEQVRBLCBPUiBQUk9GSVRTOyBPUiBCVVNJTkVTUyBJTlRFUlJVUFRJT04pIEhPV0VWRVIgQ0FVU0VEIEFORCBPTiBBTlkKICogVEhFT1JZIE9GIExJQUJJTElUWSwgV0hFVEhFUiBJTiBDT05UUkFDVCwgU1RSSUNUIExJQUJJTElUWSwgT1IgVE9SVAogKiAoSU5DTFVESU5HIE5FR0xJR0VOQ0UgT1IgT1RIRVJXSVNFKSBBUklTSU5HIElOIEFOWSBXQVkgT1VUIE9GIFRIRSBVU0UgT0YKICogVEhJUyBTT0ZUV0FSRSwgRVZFTiBJRiBBRFZJU0VEIE9GIFRIRSBQT1NTSUJJTElUWSBPRiBTVUNIIERBTUFHRS4KICovCgojaW5jbHVkZSAiaW5jbHVkZXMuaCIKI2lmIGRlZmluZWQoU01BUlRDQVJEKSAmJiBkZWZpbmVkKFVTRV9PUEVOU0MpCgojaW5jbHVkZSA8b3BlbnNzbC9ldnAuaD4KI2luY2x1ZGUgPG9wZW5zc2wveDUwOS5oPgoKI2luY2x1ZGUgPG9wZW5zYy9vcGVuc2MuaD4KI2luY2x1ZGUgPG9wZW5zYy9wa2NzMTUuaD4KCiNpbmNsdWRlICJrZXkuaCIKI2luY2x1ZGUgImxvZy5oIgojaW5jbHVkZSAieG1hbGxvYy5oIgojaW5jbHVkZSAicmVhZHBhc3MuaCIKI2luY2x1ZGUgInNjYXJkLmgiCgojaWYgT1BFTlNTTF9WRVJTSU9OX05VTUJFUiA8IDB4MDA5MDcwMDBMICYmIGRlZmluZWQoQ1JZUFRPX0xPQ0tfRU5HSU5FKQojZGVmaW5lIFVTRV9FTkdJTkUKI2RlZmluZSBSU0FfZ2V0X2RlZmF1bHRfbWV0aG9kIFJTQV9nZXRfZGVmYXVsdF9vcGVuc3NsX21ldGhvZAojZWxzZQojZW5kaWYKCiNpZmRlZiBVU0VfRU5HSU5FCiNpbmNsdWRlIDxvcGVuc3NsL2VuZ2luZS5oPgojZGVmaW5lIHNjX2dldF9yc2Egc2NfZ2V0X2VuZ2luZQojZWxzZQojZGVmaW5lIHNjX2dldF9yc2Egc2NfZ2V0X3JzYV9tZXRob2QKI2VuZGlmCgpzdGF0aWMgaW50IHNjX3JlYWRlcl9pZDsKc3RhdGljIHNjX2NvbnRleHRfdCAqY3R4ID0gTlVMTDsKc3RhdGljIHNjX2NhcmRfdCAqY2FyZCA9IE5VTEw7CnN0YXRpYyBzY19wa2NzMTVfY2FyZF90ICpwMTVjYXJkID0gTlVMTDsKCnN0YXRpYyBjaGFyICpzY19waW4gPSBOVUxMOwoKc3RydWN0IHNjX3ByaXZfZGF0YQp7CglzdHJ1Y3Qgc2NfcGtjczE1X2lkIGNlcnRfaWQ7CglpbnQgcmVmX2NvdW50Owp9OwoKdm9pZApzY19jbG9zZSh2b2lkKQp7CglpZiAocDE1Y2FyZCkgewoJCXNjX3BrY3MxNV91bmJpbmQocDE1Y2FyZCk7CgkJcDE1Y2FyZCA9IE5VTEw7Cgl9CglpZiAoY2FyZCkgewoJCXNjX2Rpc2Nvbm5lY3RfY2FyZChjYXJkLCAwKTsKCQljYXJkID0gTlVMTDsKCX0KCWlmIChjdHgpIHsKCQlzY19yZWxlYXNlX2NvbnRleHQoY3R4KTsKCQljdHggPSBOVUxMOwoJfQp9CgpzdGF0aWMgaW50CnNjX2luaXQodm9pZCkKewoJaW50IHI7CgoJciA9IHNjX2VzdGFibGlzaF9jb250ZXh0KCZjdHgsICJvcGVuc3NoIik7CglpZiAocikKCQlnb3RvIGVycjsKCWlmIChzY19yZWFkZXJfaWQgPj0gY3R4LT5yZWFkZXJfY291bnQpIHsKCQlyID0gU0NfRVJST1JfTk9fUkVBREVSU19GT1VORDsKCQllcnJvcigiSWxsZWdhbCByZWFkZXIgbnVtYmVyICVkIChtYXggJWQpIiwgc2NfcmVhZGVyX2lkLAoJCSAgICBjdHgtPnJlYWRlcl9jb3VudCAtMSk7CgkJZ290byBlcnI7Cgl9CglyID0gc2NfY29ubmVjdF9jYXJkKGN0eC0+cmVhZGVyW3NjX3JlYWRlcl9pZF0sIDAsICZjYXJkKTsKCWlmIChyKQoJCWdvdG8gZXJyOwoJciA9IHNjX3BrY3MxNV9iaW5kKGNhcmQsICZwMTVjYXJkKTsKCWlmIChyKQoJCWdvdG8gZXJyOwoJcmV0dXJuIDA7CmVycjoKCXNjX2Nsb3NlKCk7CglyZXR1cm4gcjsKfQoKLyogcHJpdmF0ZSBrZXkgb3BlcmF0aW9ucyAqLwoKc3RhdGljIGludApzY19wcmtleV9vcF9pbml0KFJTQSAqcnNhLCBzdHJ1Y3Qgc2NfcGtjczE1X29iamVjdCAqKmtleV9vYmpfb3V0LAoJdW5zaWduZWQgaW50IHVzYWdlKQp7CglpbnQgcjsKCXN0cnVjdCBzY19wcml2X2RhdGEgKnByaXY7CglzdHJ1Y3Qgc2NfcGtjczE1X29iamVjdCAqa2V5X29iajsKCXN0cnVjdCBzY19wa2NzMTVfcHJrZXlfaW5mbyAqa2V5OwoJc3RydWN0IHNjX3BrY3MxNV9vYmplY3QgKnBpbl9vYmo7CglzdHJ1Y3Qgc2NfcGtjczE1X3Bpbl9pbmZvICpwaW47CgoJcHJpdiA9IChzdHJ1Y3Qgc2NfcHJpdl9kYXRhICopIFJTQV9nZXRfYXBwX2RhdGEocnNhKTsKCWlmIChwcml2ID09IE5VTEwpCgkJcmV0dXJuIC0xOwoJaWYgKHAxNWNhcmQgPT0gTlVMTCkgewoJCXNjX2Nsb3NlKCk7CgkJciA9IHNjX2luaXQoKTsKCQlpZiAocikgewoJCQllcnJvcigiU21hcnRDYXJkIGluaXQgZmFpbGVkOiAlcyIsIHNjX3N0cmVycm9yKHIpKTsKCQkJZ290byBlcnI7CgkJfQoJfQoJciA9IHNjX3BrY3MxNV9maW5kX3Bya2V5X2J5X2lkX3VzYWdlKHAxNWNhcmQsICZwcml2LT5jZXJ0X2lkLAoJCXVzYWdlLCAma2V5X29iaik7CglpZiAocikgewoJCWVycm9yKCJVbmFibGUgdG8gZmluZCBwcml2YXRlIGtleSBmcm9tIFNtYXJ0Q2FyZDogJXMiLAoJCSAgICAgIHNjX3N0cmVycm9yKHIpKTsKCQlnb3RvIGVycjsKCX0KCWtleSA9IGtleV9vYmotPmRhdGE7CglyID0gc2NfcGtjczE1X2ZpbmRfcGluX2J5X2F1dGhfaWQocDE1Y2FyZCwgJmtleV9vYmotPmF1dGhfaWQsCgkJCQkJICAmcGluX29iaik7CglpZiAociA9PSBTQ19FUlJPUl9PQkpFQ1RfTk9UX0ZPVU5EKSB7CgkJLyogbm8gcGluIHJlcXVpcmVkICovCgkJciA9IHNjX2xvY2soY2FyZCk7CgkJaWYgKHIpIHsKCQkJZXJyb3IoIlVuYWJsZSB0byBsb2NrIHNtYXJ0Y2FyZDogJXMiLCBzY19zdHJlcnJvcihyKSk7CgkJCWdvdG8gZXJyOwoJCX0KCQkqa2V5X29ial9vdXQgPSBrZXlfb2JqOwoJCXJldHVybiAwOwoJfSBlbHNlIGlmIChyKSB7CgkJZXJyb3IoIlVuYWJsZSB0byBmaW5kIFBJTiBvYmplY3QgZnJvbSBTbWFydENhcmQ6ICVzIiwKCQkgICAgICBzY19zdHJlcnJvcihyKSk7CgkJZ290byBlcnI7Cgl9CglwaW4gPSBwaW5fb2JqLT5kYXRhOwoJciA9IHNjX2xvY2soY2FyZCk7CglpZiAocikgewoJCWVycm9yKCJVbmFibGUgdG8gbG9jayBzbWFydGNhcmQ6ICVzIiwgc2Nfc3RyZXJyb3IocikpOwoJCWdvdG8gZXJyOwoJfQoJaWYgKHNjX3BpbiAhPSBOVUxMKSB7CgkJciA9IHNjX3BrY3MxNV92ZXJpZnlfcGluKHAxNWNhcmQsIHBpbiwgc2NfcGluLAoJCQkJCSBzdHJsZW4oc2NfcGluKSk7CgkJaWYgKHIpIHsKCQkJc2NfdW5sb2NrKGNhcmQpOwoJCQllcnJvcigiUElOIGNvZGUgdmVyaWZpY2F0aW9uIGZhaWxlZDogJXMiLAoJCQkgICAgICBzY19zdHJlcnJvcihyKSk7CgkJCWdvdG8gZXJyOwoJCX0KCX0KCSprZXlfb2JqX291dCA9IGtleV9vYmo7CglyZXR1cm4gMDsKZXJyOgoJc2NfY2xvc2UoKTsKCXJldHVybiAtMTsKfQoKI2RlZmluZSBTQ19VU0FHRV9ERUNSWVBUCVNDX1BLQ1MxNV9QUktFWV9VU0FHRV9ERUNSWVBUIHwgXAoJCQkJU0NfUEtDUzE1X1BSS0VZX1VTQUdFX1VOV1JBUAoKc3RhdGljIGludApzY19wcml2YXRlX2RlY3J5cHQoaW50IGZsZW4sIHVfY2hhciAqZnJvbSwgdV9jaGFyICp0bywgUlNBICpyc2EsCiAgICBpbnQgcGFkZGluZykKewoJc3RydWN0IHNjX3BrY3MxNV9vYmplY3QgKmtleV9vYmo7CglpbnQgcjsKCglpZiAocGFkZGluZyAhPSBSU0FfUEtDUzFfUEFERElORykKCQlyZXR1cm4gLTE7CglyID0gc2NfcHJrZXlfb3BfaW5pdChyc2EsICZrZXlfb2JqLCBTQ19VU0FHRV9ERUNSWVBUKTsKCWlmIChyKQoJCXJldHVybiAtMTsKCXIgPSBzY19wa2NzMTVfZGVjaXBoZXIocDE1Y2FyZCwga2V5X29iaiwgU0NfQUxHT1JJVEhNX1JTQV9QQURfUEtDUzEsCgkgICAgZnJvbSwgZmxlbiwgdG8sIGZsZW4pOwoJc2NfdW5sb2NrKGNhcmQpOwoJaWYgKHIgPCAwKSB7CgkJZXJyb3IoInNjX3BrY3MxNV9kZWNpcGhlcigpIGZhaWxlZDogJXMiLCBzY19zdHJlcnJvcihyKSk7CgkJZ290byBlcnI7Cgl9CglyZXR1cm4gcjsKZXJyOgoJc2NfY2xvc2UoKTsKCXJldHVybiAtMTsKfQoKI2RlZmluZSBTQ19VU0FHRV9TSUdOIAkJU0NfUEtDUzE1X1BSS0VZX1VTQUdFX1NJR04gfCBcCgkJCQlTQ19QS0NTMTVfUFJLRVlfVVNBR0VfU0lHTlJFQ09WRVIKCnN0YXRpYyBpbnQKc2Nfc2lnbihpbnQgdHlwZSwgdV9jaGFyICptLCB1bnNpZ25lZCBpbnQgbV9sZW4sCgl1bnNpZ25lZCBjaGFyICpzaWdyZXQsIHVuc2lnbmVkIGludCAqc2lnbGVuLCBSU0EgKnJzYSkKewoJc3RydWN0IHNjX3BrY3MxNV9vYmplY3QgKmtleV9vYmo7CglpbnQgcjsKCXVuc2lnbmVkIGxvbmcgZmxhZ3MgPSAwOwoKCS8qIFhYWDogc2NfcHJrZXlfb3BfaW5pdCB3aWxsIHNlYXJjaCBmb3IgYSBwa2NzMTUgcHJpdmF0ZQoJICoga2V5IG9iamVjdCB3aXRoIHRoZSBzaWduIG9yIHNpZ25yZWNvdmVyIHVzYWdlIGZsYWcgc2V0LgoJICogSWYgdGhlIHNpZ25pbmcga2V5IGhhcyBvbmx5IHRoZSBub24tcmVwdWRpYXRpb24gZmxhZyBzZXQKCSAqIHRoZSBrZXkgd2lsbCBiZSByZWplY3RlZCBhcyB1c2luZyBhIG5vbi1yZXB1ZGlhdGlvbiBrZXkKCSAqIGZvciBhdXRoZW50aWNhdGlvbiBpcyBub3QgcmVjb21tZW5kZWQuIE5vdGU6IFRoaXMgZG9lcyBub3QKCSAqIHByZXZlbnQgdGhlIHVzZSBvZiBhIG5vbi1yZXB1ZGlhdGlvbiBrZXkgZm9yIGF1dGhlbnRpY2F0aW9uCgkgKiBpZiB0aGUgc2lnbiBvciBzaWducmVjb3ZlciBmbGFnIGlzIHNldCBhcyB3ZWxsLgoJICovCglyID0gc2NfcHJrZXlfb3BfaW5pdChyc2EsICZrZXlfb2JqLCBTQ19VU0FHRV9TSUdOKTsKCWlmIChyKQoJCXJldHVybiAtMTsKCS8qIEZJWE1FOiBsZW5ndGggb2Ygc2lncmV0IGNvcnJlY3Q/ICovCgkvKiBGSVhNRTogY2hlY2sgJ3R5cGUnIGFuZCBtb2RpZnkgZmxhZ3MgYWNjb3JkaW5nbHkgKi8KCWZsYWdzID0gU0NfQUxHT1JJVEhNX1JTQV9QQURfUEtDUzEgfCBTQ19BTEdPUklUSE1fUlNBX0hBU0hfU0hBMTsKCXIgPSBzY19wa2NzMTVfY29tcHV0ZV9zaWduYXR1cmUocDE1Y2FyZCwga2V5X29iaiwgZmxhZ3MsCgkJCQkJbSwgbV9sZW4sIHNpZ3JldCwgUlNBX3NpemUocnNhKSk7CglzY191bmxvY2soY2FyZCk7CglpZiAociA8IDApIHsKCQllcnJvcigic2NfcGtjczE1X2NvbXB1dGVfc2lnbmF0dXJlKCkgZmFpbGVkOiAlcyIsCgkJICAgICAgc2Nfc3RyZXJyb3IocikpOwoJCWdvdG8gZXJyOwoJfQoJKnNpZ2xlbiA9IHI7CglyZXR1cm4gMTsKZXJyOgoJc2NfY2xvc2UoKTsKCXJldHVybiAwOwp9CgpzdGF0aWMgaW50CnNjX3ByaXZhdGVfZW5jcnlwdChpbnQgZmxlbiwgdV9jaGFyICpmcm9tLCB1X2NoYXIgKnRvLCBSU0EgKnJzYSwKICAgIGludCBwYWRkaW5nKQp7CgllcnJvcigiUHJpdmF0ZSBrZXkgZW5jcnlwdGlvbiBub3Qgc3VwcG9ydGVkIik7CglyZXR1cm4gLTE7Cn0KCi8qIGNhbGxlZCBvbiBmcmVlICovCgpzdGF0aWMgaW50ICgqb3JpZ19maW5pc2gpKFJTQSAqcnNhKSA9IE5VTEw7CgpzdGF0aWMgaW50CnNjX2ZpbmlzaChSU0EgKnJzYSkKewoJc3RydWN0IHNjX3ByaXZfZGF0YSAqcHJpdjsKCglwcml2ID0gUlNBX2dldF9hcHBfZGF0YShyc2EpOwoJcHJpdi0+cmVmX2NvdW50LS07CglpZiAocHJpdi0+cmVmX2NvdW50ID09IDApIHsKCQlmcmVlKHByaXYpOwoJCXNjX2Nsb3NlKCk7Cgl9CglpZiAob3JpZ19maW5pc2gpCgkJb3JpZ19maW5pc2gocnNhKTsKCXJldHVybiAxOwp9CgovKiBlbmdpbmUgZm9yIG92ZXJsb2FkaW5nIHByaXZhdGUga2V5IG9wZXJhdGlvbnMgKi8KCnN0YXRpYyBSU0FfTUVUSE9EICoKc2NfZ2V0X3JzYV9tZXRob2Qodm9pZCkKewoJc3RhdGljIFJTQV9NRVRIT0Qgc21hcnRfcnNhOwoJY29uc3QgUlNBX01FVEhPRCAqZGVmID0gUlNBX2dldF9kZWZhdWx0X21ldGhvZCgpOwoKCS8qIHVzZSB0aGUgT3BlblNTTCB2ZXJzaW9uICovCgltZW1jcHkoJnNtYXJ0X3JzYSwgZGVmLCBzaXplb2Yoc21hcnRfcnNhKSk7CgoJc21hcnRfcnNhLm5hbWUJCT0gIm9wZW5zYyI7CgoJLyogb3ZlcmxvYWQgKi8KCXNtYXJ0X3JzYS5yc2FfcHJpdl9lbmMJPSBzY19wcml2YXRlX2VuY3J5cHQ7CglzbWFydF9yc2EucnNhX3ByaXZfZGVjCT0gc2NfcHJpdmF0ZV9kZWNyeXB0OwoJc21hcnRfcnNhLnJzYV9zaWduCT0gc2Nfc2lnbjsKCgkvKiBzYXZlIG9yaWdpbmFsICovCglvcmlnX2ZpbmlzaAkJPSBkZWYtPmZpbmlzaDsKCXNtYXJ0X3JzYS5maW5pc2gJPSBzY19maW5pc2g7CgoJcmV0dXJuICZzbWFydF9yc2E7Cn0KCiNpZmRlZiBVU0VfRU5HSU5FCnN0YXRpYyBFTkdJTkUgKgpzY19nZXRfZW5naW5lKHZvaWQpCnsKCXN0YXRpYyBFTkdJTkUgKnNtYXJ0X2VuZ2luZSA9IE5VTEw7CgoJaWYgKChzbWFydF9lbmdpbmUgPSBFTkdJTkVfbmV3KCkpID09IE5VTEwpCgkJZmF0YWwoIkVOR0lORV9uZXcgZmFpbGVkIik7CgoJRU5HSU5FX3NldF9pZChzbWFydF9lbmdpbmUsICJvcGVuc2MiKTsKCUVOR0lORV9zZXRfbmFtZShzbWFydF9lbmdpbmUsICJPcGVuU0MiKTsKCglFTkdJTkVfc2V0X1JTQShzbWFydF9lbmdpbmUsIHNjX2dldF9yc2FfbWV0aG9kKCkpOwoJRU5HSU5FX3NldF9EU0Eoc21hcnRfZW5naW5lLCBEU0FfZ2V0X2RlZmF1bHRfb3BlbnNzbF9tZXRob2QoKSk7CglFTkdJTkVfc2V0X0RIKHNtYXJ0X2VuZ2luZSwgREhfZ2V0X2RlZmF1bHRfb3BlbnNzbF9tZXRob2QoKSk7CglFTkdJTkVfc2V0X1JBTkQoc21hcnRfZW5naW5lLCBSQU5EX1NTTGVheSgpKTsKCUVOR0lORV9zZXRfQk5fbW9kX2V4cChzbWFydF9lbmdpbmUsIEJOX21vZF9leHApOwoKCXJldHVybiBzbWFydF9lbmdpbmU7Cn0KI2VuZGlmCgpzdGF0aWMgdm9pZApjb252ZXJ0X3JzYV90b19yc2ExKEtleSAqIGluLCBLZXkgKiBvdXQpCnsKCXN0cnVjdCBzY19wcml2X2RhdGEgKnByaXY7CgoJb3V0LT5yc2EtPmZsYWdzID0gaW4tPnJzYS0+ZmxhZ3M7CglvdXQtPmZsYWdzID0gaW4tPmZsYWdzOwoJUlNBX3NldF9tZXRob2Qob3V0LT5yc2EsIFJTQV9nZXRfbWV0aG9kKGluLT5yc2EpKTsKCUJOX2NvcHkob3V0LT5yc2EtPm4sIGluLT5yc2EtPm4pOwoJQk5fY29weShvdXQtPnJzYS0+ZSwgaW4tPnJzYS0+ZSk7Cglwcml2ID0gUlNBX2dldF9hcHBfZGF0YShpbi0+cnNhKTsKCXByaXYtPnJlZl9jb3VudCsrOwoJUlNBX3NldF9hcHBfZGF0YShvdXQtPnJzYSwgcHJpdik7CglyZXR1cm47Cn0KCnN0YXRpYyBpbnQKc2NfcmVhZF9wdWJrZXkoS2V5ICogaywgY29uc3Qgc3RydWN0IHNjX3BrY3MxNV9vYmplY3QgKmNlcnRfb2JqKQp7CglpbnQgcjsKCXNjX3BrY3MxNV9jZXJ0X3QgKmNlcnQgPSBOVUxMOwoJc3RydWN0IHNjX3ByaXZfZGF0YSAqcHJpdiA9IE5VTEw7CglzY19wa2NzMTVfY2VydF9pbmZvX3QgKmNpbmZvID0gY2VydF9vYmotPmRhdGE7CgoJWDUwOSAqeDUwOSA9IE5VTEw7CglFVlBfUEtFWSAqcHVia2V5ID0gTlVMTDsKCXU4ICpwOwoJY2hhciAqdG1wOwoKCWRlYnVnKCJzY19yZWFkX3B1YmtleSgpIHdpdGggY2VydCBpZCAlMDJYIiwgY2luZm8tPmlkLnZhbHVlWzBdKTsKCXIgPSBzY19wa2NzMTVfcmVhZF9jZXJ0aWZpY2F0ZShwMTVjYXJkLCBjaW5mbywgJmNlcnQpOwoJaWYgKHIpIHsKCQlsb2dpdCgiQ2VydGlmaWNhdGUgcmVhZCBmYWlsZWQ6ICVzIiwgc2Nfc3RyZXJyb3IocikpOwoJCWdvdG8gZXJyOwoJfQoJeDUwOSA9IFg1MDlfbmV3KCk7CglpZiAoeDUwOSA9PSBOVUxMKSB7CgkJciA9IC0xOwoJCWdvdG8gZXJyOwoJfQoJcCA9IGNlcnQtPmRhdGE7CglpZiAoIWQyaV9YNTA5KCZ4NTA5LCAmcCwgY2VydC0+ZGF0YV9sZW4pKSB7CgkJbG9naXQoIlVuYWJsZSB0byBwYXJzZSBYLjUwOSBjZXJ0aWZpY2F0ZSIpOwoJCXIgPSAtMTsKCQlnb3RvIGVycjsKCX0KCXNjX3BrY3MxNV9mcmVlX2NlcnRpZmljYXRlKGNlcnQpOwoJY2VydCA9IE5VTEw7CglwdWJrZXkgPSBYNTA5X2dldF9wdWJrZXkoeDUwOSk7CglYNTA5X2ZyZWUoeDUwOSk7Cgl4NTA5ID0gTlVMTDsKCWlmIChwdWJrZXktPnR5cGUgIT0gRVZQX1BLRVlfUlNBKSB7CgkJbG9naXQoIlB1YmxpYyBrZXkgaXMgb2YgdW5rbm93biB0eXBlIik7CgkJciA9IC0xOwoJCWdvdG8gZXJyOwoJfQoJay0+cnNhID0gRVZQX1BLRVlfZ2V0MV9SU0EocHVia2V5KTsKCUVWUF9QS0VZX2ZyZWUocHVia2V5KTsKCglrLT5yc2EtPmZsYWdzIHw9IFJTQV9GTEFHX1NJR05fVkVSOwoJUlNBX3NldF9tZXRob2Qoay0+cnNhLCBzY19nZXRfcnNhX21ldGhvZCgpKTsKCXByaXYgPSB4bWFsbG9jKHNpemVvZihzdHJ1Y3Qgc2NfcHJpdl9kYXRhKSk7Cglwcml2LT5jZXJ0X2lkID0gY2luZm8tPmlkOwoJcHJpdi0+cmVmX2NvdW50ID0gMTsKCVJTQV9zZXRfYXBwX2RhdGEoay0+cnNhLCBwcml2KTsKCglrLT5mbGFncyA9IEtFWV9GTEFHX0VYVDsKCXRtcCA9IGtleV9maW5nZXJwcmludChrLCBTU0hfRlBfTUQ1LCBTU0hfRlBfSEVYKTsKCWRlYnVnKCJmaW5nZXJwcmludCAlZCAlcyIsIGtleV9zaXplKGspLCB0bXApOwoJeGZyZWUodG1wKTsKCglyZXR1cm4gMDsKZXJyOgoJaWYgKGNlcnQpCgkJc2NfcGtjczE1X2ZyZWVfY2VydGlmaWNhdGUoY2VydCk7CglpZiAocHVia2V5KQoJCUVWUF9QS0VZX2ZyZWUocHVia2V5KTsKCWlmICh4NTA5KQoJCVg1MDlfZnJlZSh4NTA5KTsKCXJldHVybiByOwp9CgpLZXkgKioKc2NfZ2V0X2tleXMoY29uc3QgY2hhciAqaWQsIGNvbnN0IGNoYXIgKnBpbikKewoJS2V5ICprLCAqKmtleXM7CglpbnQgaSwgciwgcmVhbF9jb3VudCA9IDAsIGtleV9jb3VudDsKCXNjX3BrY3MxNV9pZF90IGNlcnRfaWQ7CglzY19wa2NzMTVfb2JqZWN0X3QgKmNlcnRzWzMyXTsKCWNoYXIgKmJ1ZiA9IHhzdHJkdXAoaWQpLCAqcDsKCglkZWJ1Zygic2NfZ2V0X2tleXMgY2FsbGVkOiBpZCA9ICVzIiwgaWQpOwoKCWlmIChzY19waW4gIT0gTlVMTCkKCQl4ZnJlZShzY19waW4pOwoJc2NfcGluID0gKHBpbiA9PSBOVUxMKSA/IE5VTEwgOiB4c3RyZHVwKHBpbik7CgoJY2VydF9pZC5sZW4gPSAwOwoJaWYgKChwID0gc3RyY2hyKGJ1ZiwgJzonKSkgIT0gTlVMTCkgewoJCSpwID0gMDsKCQlwKys7CgkJc2NfcGtjczE1X2hleF9zdHJpbmdfdG9faWQocCwgJmNlcnRfaWQpOwoJfQoJciA9IHNzY2FuZihidWYsICIlZCIsICZzY19yZWFkZXJfaWQpOwoJeGZyZWUoYnVmKTsKCWlmIChyICE9IDEpCgkJZ290byBlcnI7CglpZiAocDE1Y2FyZCA9PSBOVUxMKSB7CgkJc2NfY2xvc2UoKTsKCQlyID0gc2NfaW5pdCgpOwoJCWlmIChyKSB7CgkJCWVycm9yKCJTbWFydGNhcmQgaW5pdCBmYWlsZWQ6ICVzIiwgc2Nfc3RyZXJyb3IocikpOwoJCQlnb3RvIGVycjsKCQl9Cgl9CglpZiAoY2VydF9pZC5sZW4pIHsKCQlyID0gc2NfcGtjczE1X2ZpbmRfY2VydF9ieV9pZChwMTVjYXJkLCAmY2VydF9pZCwgJmNlcnRzWzBdKTsKCQlpZiAociA8IDApCgkJCWdvdG8gZXJyOwoJCWtleV9jb3VudCA9IDE7Cgl9IGVsc2UgewoJCXIgPSBzY19wa2NzMTVfZ2V0X29iamVjdHMocDE1Y2FyZCwgU0NfUEtDUzE1X1RZUEVfQ0VSVF9YNTA5LAoJCQkJCSAgY2VydHMsIDMyKTsKCQlpZiAociA9PSAwKSB7CgkJCWxvZ2l0KCJObyBjZXJ0aWZpY2F0ZXMgZm91bmQgb24gc21hcnRjYXJkIik7CgkJCXIgPSAtMTsKCQkJZ290byBlcnI7CgkJfSBlbHNlIGlmIChyIDwgMCkgewoJCQllcnJvcigiQ2VydGlmaWNhdGUgZW51bWVyYXRpb24gZmFpbGVkOiAlcyIsCgkJCSAgICAgIHNjX3N0cmVycm9yKHIpKTsKCQkJZ290byBlcnI7CgkJfQoJCWtleV9jb3VudCA9IHI7Cgl9CglrZXlzID0geG1hbGxvYyhzaXplb2YoS2V5ICopICogKGtleV9jb3VudCoyKzEpKTsKCWZvciAoaSA9IDA7IGkgPCBrZXlfY291bnQ7IGkrKykgewoJCXNjX3BrY3MxNV9vYmplY3RfdCAqdG1wX29iaiA9IE5VTEw7CgkJY2VydF9pZCA9ICgoc2NfcGtjczE1X2NlcnRfaW5mb190ICopKGNlcnRzW2ldLT5kYXRhKSktPmlkOwoJCWlmIChzY19wa2NzMTVfZmluZF9wcmtleV9ieV9pZChwMTVjYXJkLCAmY2VydF9pZCwgJnRtcF9vYmopKQoJCQkvKiBza2lwIHRoZSBwdWJsaWMga2V5IChjZXJ0aWZpY2F0ZSkgaWYgbm8KCQkJICogY29ycmVzcG9uZGluZyBwcml2YXRlIGtleSBpcyBwcmVzZW50ICovCgkJCWNvbnRpbnVlOwoJCWsgPSBrZXlfbmV3KEtFWV9SU0EpOwoJCWlmIChrID09IE5VTEwpCgkJCWJyZWFrOwoJCXIgPSBzY19yZWFkX3B1YmtleShrLCBjZXJ0c1tpXSk7CgkJaWYgKHIpIHsKCQkJZXJyb3IoInNjX3JlYWRfcHVia2V5IGZhaWxlZDogJXMiLCBzY19zdHJlcnJvcihyKSk7CgkJCWtleV9mcmVlKGspOwoJCQljb250aW51ZTsKCQl9CgkJa2V5c1tyZWFsX2NvdW50XSA9IGs7CgkJcmVhbF9jb3VudCsrOwoJCWsgPSBrZXlfbmV3KEtFWV9SU0ExKTsKCQlpZiAoayA9PSBOVUxMKQoJCQlicmVhazsKCQljb252ZXJ0X3JzYV90b19yc2ExKGtleXNbcmVhbF9jb3VudC0xXSwgayk7CgkJa2V5c1tyZWFsX2NvdW50XSA9IGs7CgkJcmVhbF9jb3VudCsrOwoJfQoJa2V5c1tyZWFsX2NvdW50XSA9IE5VTEw7CgoJcmV0dXJuIGtleXM7CmVycjoKCXNjX2Nsb3NlKCk7CglyZXR1cm4gTlVMTDsKfQoKaW50CnNjX3B1dF9rZXkoS2V5ICpwcnYsIGNvbnN0IGNoYXIgKmlkKQp7CgllcnJvcigia2V5IHVwbG9hZGluZyBub3QgeWV0IHN1cHBvcnRlZCIpOwoJcmV0dXJuIC0xOwp9CgpjaGFyICoKc2NfZ2V0X2tleV9sYWJlbChLZXkgKmtleSkKewoJaW50IHI7Cgljb25zdCBzdHJ1Y3Qgc2NfcHJpdl9kYXRhICpwcml2OwoJc3RydWN0IHNjX3BrY3MxNV9vYmplY3QgKmtleV9vYmo7CgoJcHJpdiA9IChjb25zdCBzdHJ1Y3Qgc2NfcHJpdl9kYXRhICopIFJTQV9nZXRfYXBwX2RhdGEoa2V5LT5yc2EpOwoJaWYgKHByaXYgPT0gTlVMTCB8fCBwMTVjYXJkID09IE5VTEwpIHsKCQlsb2dpdCgiU21hcnRDYXJkIGtleSBub3QgbG9hZGVkIik7CgkJLyogaW50ZXJuYWwgZXJyb3IgPT4gcmV0dXJuIGRlZmF1bHQgbGFiZWwgKi8KCQlyZXR1cm4geHN0cmR1cCgic21hcnRjYXJkIGtleSIpOwoJfQoJciA9IHNjX3BrY3MxNV9maW5kX3Bya2V5X2J5X2lkKHAxNWNhcmQsICZwcml2LT5jZXJ0X2lkLCAma2V5X29iaik7CglpZiAocikgewoJCWxvZ2l0KCJVbmFibGUgdG8gZmluZCBwcml2YXRlIGtleSBmcm9tIFNtYXJ0Q2FyZDogJXMiLAoJCSAgICAgIHNjX3N0cmVycm9yKHIpKTsKCQlyZXR1cm4geHN0cmR1cCgic21hcnRjYXJkIGtleSIpOwoJfQoJaWYgKGtleV9vYmogPT0gTlVMTCB8fCBrZXlfb2JqLT5sYWJlbCA9PSBOVUxMKQoJCS8qIHRoZSBvcHRpb25hbCBQS0NTIzE1IGxhYmVsIGRvZXMgbm90IGV4aXN0cwoJCSAqID0+IHJldHVybiB0aGUgZGVmYXVsdCBsYWJlbCAqLwoJCXJldHVybiB4c3RyZHVwKCJzbWFydGNhcmQga2V5Iik7CglyZXR1cm4geHN0cmR1cChrZXlfb2JqLT5sYWJlbCk7Cn0KCiNlbmRpZiAvKiBTTUFSVENBUkQgKi8K