LyoKICogQ29weXJpZ2h0IChjKSAyMDAyIEp1aGEgWXJq9mzkLiAgQWxsIHJpZ2h0cyByZXNlcnZlZC4KICogQ29weXJpZ2h0IChjKSAyMDAxIE1hcmt1cyBGcmllZGwuCiAqCiAqIFJlZGlzdHJpYnV0aW9uIGFuZCB1c2UgaW4gc291cmNlIGFuZCBiaW5hcnkgZm9ybXMsIHdpdGggb3Igd2l0aG91dAogKiBtb2RpZmljYXRpb24sIGFyZSBwZXJtaXR0ZWQgcHJvdmlkZWQgdGhhdCB0aGUgZm9sbG93aW5nIGNvbmRpdGlvbnMKICogYXJlIG1ldDoKICogMS4gUmVkaXN0cmlidXRpb25zIG9mIHNvdXJjZSBjb2RlIG11c3QgcmV0YWluIHRoZSBhYm92ZSBjb3B5cmlnaHQKICogICAgbm90aWNlLCB0aGlzIGxpc3Qgb2YgY29uZGl0aW9ucyBhbmQgdGhlIGZvbGxvd2luZyBkaXNjbGFpbWVyLgogKiAyLiBSZWRpc3RyaWJ1dGlvbnMgaW4gYmluYXJ5IGZvcm0gbXVzdCByZXByb2R1Y2UgdGhlIGFib3ZlIGNvcHlyaWdodAogKiAgICBub3RpY2UsIHRoaXMgbGlzdCBvZiBjb25kaXRpb25zIGFuZCB0aGUgZm9sbG93aW5nIGRpc2NsYWltZXIgaW4gdGhlCiAqICAgIGRvY3VtZW50YXRpb24gYW5kL29yIG90aGVyIG1hdGVyaWFscyBwcm92aWRlZCB3aXRoIHRoZSBkaXN0cmlidXRpb24uCiAqCiAqIFRISVMgU09GVFdBUkUgSVMgUFJPVklERUQgQlkgVEhFIEFVVEhPUiBgYEFTIElTJycgQU5EIEFOWSBFWFBSRVNTIE9SCiAqIElNUExJRUQgV0FSUkFOVElFUywgSU5DTFVESU5HLCBCVVQgTk9UIExJTUlURUQgVE8sIFRIRSBJTVBMSUVEIFdBUlJBTlRJRVMKICogT0YgTUVSQ0hBTlRBQklMSVRZIEFORCBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSBBUkUgRElTQ0xBSU1FRC4KICogSU4gTk8gRVZFTlQgU0hBTEwgVEhFIEFVVEhPUiBCRSBMSUFCTEUgRk9SIEFOWSBESVJFQ1QsIElORElSRUNULAogKiBJTkNJREVOVEFMLCBTUEVDSUFMLCBFWEVNUExBUlksIE9SIENPTlNFUVVFTlRJQUwgREFNQUdFUyAoSU5DTFVESU5HLCBCVVQKICogTk9UIExJTUlURUQgVE8sIFBST0NVUkVNRU5UIE9GIFNVQlNUSVRVVEUgR09PRFMgT1IgU0VSVklDRVM7IExPU1MgT0YgVVNFLAogKiBEQVRBLCBPUiBQUk9GSVRTOyBPUiBCVVNJTkVTUyBJTlRFUlJVUFRJT04pIEhPV0VWRVIgQ0FVU0VEIEFORCBPTiBBTlkKICogVEhFT1JZIE9GIExJQUJJTElUWSwgV0hFVEhFUiBJTiBDT05UUkFDVCwgU1RSSUNUIExJQUJJTElUWSwgT1IgVE9SVAogKiAoSU5DTFVESU5HIE5FR0xJR0VOQ0UgT1IgT1RIRVJXSVNFKSBBUklTSU5HIElOIEFOWSBXQVkgT1VUIE9GIFRIRSBVU0UgT0YKICogVEhJUyBTT0ZUV0FSRSwgRVZFTiBJRiBBRFZJU0VEIE9GIFRIRSBQT1NTSUJJTElUWSBPRiBTVUNIIERBTUFHRS4KICovCgojaW5jbHVkZSAiaW5jbHVkZXMuaCIKI2lmIGRlZmluZWQoU01BUlRDQVJEKSAmJiBkZWZpbmVkKFVTRV9PUEVOU0MpCgojaW5jbHVkZSA8c3lzL3R5cGVzLmg+CgojaW5jbHVkZSA8b3BlbnNzbC9ldnAuaD4KI2luY2x1ZGUgPG9wZW5zc2wveDUwOS5oPgoKI2luY2x1ZGUgPHN0ZGFyZy5oPgojaW5jbHVkZSA8c3RyaW5nLmg+CgojaW5jbHVkZSA8b3BlbnNjL29wZW5zYy5oPgojaW5jbHVkZSA8b3BlbnNjL3BrY3MxNS5oPgoKI2luY2x1ZGUgImtleS5oIgojaW5jbHVkZSAibG9nLmgiCiNpbmNsdWRlICJ4bWFsbG9jLmgiCiNpbmNsdWRlICJtaXNjLmgiCiNpbmNsdWRlICJzY2FyZC5oIgoKI2lmIE9QRU5TU0xfVkVSU0lPTl9OVU1CRVIgPCAweDAwOTA3MDAwTCAmJiBkZWZpbmVkKENSWVBUT19MT0NLX0VOR0lORSkKI2RlZmluZSBVU0VfRU5HSU5FCiNkZWZpbmUgUlNBX2dldF9kZWZhdWx0X21ldGhvZCBSU0FfZ2V0X2RlZmF1bHRfb3BlbnNzbF9tZXRob2QKI2Vsc2UKI2VuZGlmCgojaWZkZWYgVVNFX0VOR0lORQojaW5jbHVkZSA8b3BlbnNzbC9lbmdpbmUuaD4KI2RlZmluZSBzY19nZXRfcnNhIHNjX2dldF9lbmdpbmUKI2Vsc2UKI2RlZmluZSBzY19nZXRfcnNhIHNjX2dldF9yc2FfbWV0aG9kCiNlbmRpZgoKc3RhdGljIGludCBzY19yZWFkZXJfaWQ7CnN0YXRpYyBzY19jb250ZXh0X3QgKmN0eCA9IE5VTEw7CnN0YXRpYyBzY19jYXJkX3QgKmNhcmQgPSBOVUxMOwpzdGF0aWMgc2NfcGtjczE1X2NhcmRfdCAqcDE1Y2FyZCA9IE5VTEw7CgpzdGF0aWMgY2hhciAqc2NfcGluID0gTlVMTDsKCnN0cnVjdCBzY19wcml2X2RhdGEKewoJc3RydWN0IHNjX3BrY3MxNV9pZCBjZXJ0X2lkOwoJaW50IHJlZl9jb3VudDsKfTsKCnZvaWQKc2NfY2xvc2Uodm9pZCkKewoJaWYgKHAxNWNhcmQpIHsKCQlzY19wa2NzMTVfdW5iaW5kKHAxNWNhcmQpOwoJCXAxNWNhcmQgPSBOVUxMOwoJfQoJaWYgKGNhcmQpIHsKCQlzY19kaXNjb25uZWN0X2NhcmQoY2FyZCwgMCk7CgkJY2FyZCA9IE5VTEw7Cgl9CglpZiAoY3R4KSB7CgkJc2NfcmVsZWFzZV9jb250ZXh0KGN0eCk7CgkJY3R4ID0gTlVMTDsKCX0KfQoKc3RhdGljIGludApzY19pbml0KHZvaWQpCnsKCWludCByOwoKCXIgPSBzY19lc3RhYmxpc2hfY29udGV4dCgmY3R4LCAib3BlbnNzaCIpOwoJaWYgKHIpCgkJZ290byBlcnI7CglpZiAoc2NfcmVhZGVyX2lkID49IGN0eC0+cmVhZGVyX2NvdW50KSB7CgkJciA9IFNDX0VSUk9SX05PX1JFQURFUlNfRk9VTkQ7CgkJZXJyb3IoIklsbGVnYWwgcmVhZGVyIG51bWJlciAlZCAobWF4ICVkKSIsIHNjX3JlYWRlcl9pZCwKCQkgICAgY3R4LT5yZWFkZXJfY291bnQgLTEpOwoJCWdvdG8gZXJyOwoJfQoJciA9IHNjX2Nvbm5lY3RfY2FyZChjdHgtPnJlYWRlcltzY19yZWFkZXJfaWRdLCAwLCAmY2FyZCk7CglpZiAocikKCQlnb3RvIGVycjsKCXIgPSBzY19wa2NzMTVfYmluZChjYXJkLCAmcDE1Y2FyZCk7CglpZiAocikKCQlnb3RvIGVycjsKCXJldHVybiAwOwplcnI6CglzY19jbG9zZSgpOwoJcmV0dXJuIHI7Cn0KCi8qIHByaXZhdGUga2V5IG9wZXJhdGlvbnMgKi8KCnN0YXRpYyBpbnQKc2NfcHJrZXlfb3BfaW5pdChSU0EgKnJzYSwgc3RydWN0IHNjX3BrY3MxNV9vYmplY3QgKiprZXlfb2JqX291dCwKCXVuc2lnbmVkIGludCB1c2FnZSkKewoJaW50IHI7CglzdHJ1Y3Qgc2NfcHJpdl9kYXRhICpwcml2OwoJc3RydWN0IHNjX3BrY3MxNV9vYmplY3QgKmtleV9vYmo7CglzdHJ1Y3Qgc2NfcGtjczE1X3Bya2V5X2luZm8gKmtleTsKCXN0cnVjdCBzY19wa2NzMTVfb2JqZWN0ICpwaW5fb2JqOwoJc3RydWN0IHNjX3BrY3MxNV9waW5faW5mbyAqcGluOwoKCXByaXYgPSAoc3RydWN0IHNjX3ByaXZfZGF0YSAqKSBSU0FfZ2V0X2FwcF9kYXRhKHJzYSk7CglpZiAocHJpdiA9PSBOVUxMKQoJCXJldHVybiAtMTsKCWlmIChwMTVjYXJkID09IE5VTEwpIHsKCQlzY19jbG9zZSgpOwoJCXIgPSBzY19pbml0KCk7CgkJaWYgKHIpIHsKCQkJZXJyb3IoIlNtYXJ0Q2FyZCBpbml0IGZhaWxlZDogJXMiLCBzY19zdHJlcnJvcihyKSk7CgkJCWdvdG8gZXJyOwoJCX0KCX0KCXIgPSBzY19wa2NzMTVfZmluZF9wcmtleV9ieV9pZF91c2FnZShwMTVjYXJkLCAmcHJpdi0+Y2VydF9pZCwKCQl1c2FnZSwgJmtleV9vYmopOwoJaWYgKHIpIHsKCQllcnJvcigiVW5hYmxlIHRvIGZpbmQgcHJpdmF0ZSBrZXkgZnJvbSBTbWFydENhcmQ6ICVzIiwKCQkgICAgICBzY19zdHJlcnJvcihyKSk7CgkJZ290byBlcnI7Cgl9CglrZXkgPSBrZXlfb2JqLT5kYXRhOwoJciA9IHNjX3BrY3MxNV9maW5kX3Bpbl9ieV9hdXRoX2lkKHAxNWNhcmQsICZrZXlfb2JqLT5hdXRoX2lkLAoJCQkJCSAgJnBpbl9vYmopOwoJaWYgKHIgPT0gU0NfRVJST1JfT0JKRUNUX05PVF9GT1VORCkgewoJCS8qIG5vIHBpbiByZXF1aXJlZCAqLwoJCXIgPSBzY19sb2NrKGNhcmQpOwoJCWlmIChyKSB7CgkJCWVycm9yKCJVbmFibGUgdG8gbG9jayBzbWFydGNhcmQ6ICVzIiwgc2Nfc3RyZXJyb3IocikpOwoJCQlnb3RvIGVycjsKCQl9CgkJKmtleV9vYmpfb3V0ID0ga2V5X29iajsKCQlyZXR1cm4gMDsKCX0gZWxzZSBpZiAocikgewoJCWVycm9yKCJVbmFibGUgdG8gZmluZCBQSU4gb2JqZWN0IGZyb20gU21hcnRDYXJkOiAlcyIsCgkJICAgICAgc2Nfc3RyZXJyb3IocikpOwoJCWdvdG8gZXJyOwoJfQoJcGluID0gcGluX29iai0+ZGF0YTsKCXIgPSBzY19sb2NrKGNhcmQpOwoJaWYgKHIpIHsKCQllcnJvcigiVW5hYmxlIHRvIGxvY2sgc21hcnRjYXJkOiAlcyIsIHNjX3N0cmVycm9yKHIpKTsKCQlnb3RvIGVycjsKCX0KCWlmIChzY19waW4gIT0gTlVMTCkgewoJCXIgPSBzY19wa2NzMTVfdmVyaWZ5X3BpbihwMTVjYXJkLCBwaW4sIHNjX3BpbiwKCQkJCQkgc3RybGVuKHNjX3BpbikpOwoJCWlmIChyKSB7CgkJCXNjX3VubG9jayhjYXJkKTsKCQkJZXJyb3IoIlBJTiBjb2RlIHZlcmlmaWNhdGlvbiBmYWlsZWQ6ICVzIiwKCQkJICAgICAgc2Nfc3RyZXJyb3IocikpOwoJCQlnb3RvIGVycjsKCQl9Cgl9Cgkqa2V5X29ial9vdXQgPSBrZXlfb2JqOwoJcmV0dXJuIDA7CmVycjoKCXNjX2Nsb3NlKCk7CglyZXR1cm4gLTE7Cn0KCiNkZWZpbmUgU0NfVVNBR0VfREVDUllQVAlTQ19QS0NTMTVfUFJLRVlfVVNBR0VfREVDUllQVCB8IFwKCQkJCVNDX1BLQ1MxNV9QUktFWV9VU0FHRV9VTldSQVAKCnN0YXRpYyBpbnQKc2NfcHJpdmF0ZV9kZWNyeXB0KGludCBmbGVuLCB1X2NoYXIgKmZyb20sIHVfY2hhciAqdG8sIFJTQSAqcnNhLAogICAgaW50IHBhZGRpbmcpCnsKCXN0cnVjdCBzY19wa2NzMTVfb2JqZWN0ICprZXlfb2JqOwoJaW50IHI7CgoJaWYgKHBhZGRpbmcgIT0gUlNBX1BLQ1MxX1BBRERJTkcpCgkJcmV0dXJuIC0xOwoJciA9IHNjX3Bya2V5X29wX2luaXQocnNhLCAma2V5X29iaiwgU0NfVVNBR0VfREVDUllQVCk7CglpZiAocikKCQlyZXR1cm4gLTE7CglyID0gc2NfcGtjczE1X2RlY2lwaGVyKHAxNWNhcmQsIGtleV9vYmosIFNDX0FMR09SSVRITV9SU0FfUEFEX1BLQ1MxLAoJICAgIGZyb20sIGZsZW4sIHRvLCBmbGVuKTsKCXNjX3VubG9jayhjYXJkKTsKCWlmIChyIDwgMCkgewoJCWVycm9yKCJzY19wa2NzMTVfZGVjaXBoZXIoKSBmYWlsZWQ6ICVzIiwgc2Nfc3RyZXJyb3IocikpOwoJCWdvdG8gZXJyOwoJfQoJcmV0dXJuIHI7CmVycjoKCXNjX2Nsb3NlKCk7CglyZXR1cm4gLTE7Cn0KCiNkZWZpbmUgU0NfVVNBR0VfU0lHTiAJCVNDX1BLQ1MxNV9QUktFWV9VU0FHRV9TSUdOIHwgXAoJCQkJU0NfUEtDUzE1X1BSS0VZX1VTQUdFX1NJR05SRUNPVkVSCgpzdGF0aWMgaW50CnNjX3NpZ24oaW50IHR5cGUsIHVfY2hhciAqbSwgdW5zaWduZWQgaW50IG1fbGVuLAoJdW5zaWduZWQgY2hhciAqc2lncmV0LCB1bnNpZ25lZCBpbnQgKnNpZ2xlbiwgUlNBICpyc2EpCnsKCXN0cnVjdCBzY19wa2NzMTVfb2JqZWN0ICprZXlfb2JqOwoJaW50IHI7Cgl1bnNpZ25lZCBsb25nIGZsYWdzID0gMDsKCgkvKiBYWFg6IHNjX3Bya2V5X29wX2luaXQgd2lsbCBzZWFyY2ggZm9yIGEgcGtjczE1IHByaXZhdGUKCSAqIGtleSBvYmplY3Qgd2l0aCB0aGUgc2lnbiBvciBzaWducmVjb3ZlciB1c2FnZSBmbGFnIHNldC4KCSAqIElmIHRoZSBzaWduaW5nIGtleSBoYXMgb25seSB0aGUgbm9uLXJlcHVkaWF0aW9uIGZsYWcgc2V0CgkgKiB0aGUga2V5IHdpbGwgYmUgcmVqZWN0ZWQgYXMgdXNpbmcgYSBub24tcmVwdWRpYXRpb24ga2V5CgkgKiBmb3IgYXV0aGVudGljYXRpb24gaXMgbm90IHJlY29tbWVuZGVkLiBOb3RlOiBUaGlzIGRvZXMgbm90CgkgKiBwcmV2ZW50IHRoZSB1c2Ugb2YgYSBub24tcmVwdWRpYXRpb24ga2V5IGZvciBhdXRoZW50aWNhdGlvbgoJICogaWYgdGhlIHNpZ24gb3Igc2lnbnJlY292ZXIgZmxhZyBpcyBzZXQgYXMgd2VsbC4KCSAqLwoJciA9IHNjX3Bya2V5X29wX2luaXQocnNhLCAma2V5X29iaiwgU0NfVVNBR0VfU0lHTik7CglpZiAocikKCQlyZXR1cm4gLTE7CgkvKiBGSVhNRTogbGVuZ3RoIG9mIHNpZ3JldCBjb3JyZWN0PyAqLwoJLyogRklYTUU6IGNoZWNrICd0eXBlJyBhbmQgbW9kaWZ5IGZsYWdzIGFjY29yZGluZ2x5ICovCglmbGFncyA9IFNDX0FMR09SSVRITV9SU0FfUEFEX1BLQ1MxIHwgU0NfQUxHT1JJVEhNX1JTQV9IQVNIX1NIQTE7CglyID0gc2NfcGtjczE1X2NvbXB1dGVfc2lnbmF0dXJlKHAxNWNhcmQsIGtleV9vYmosIGZsYWdzLAoJCQkJCW0sIG1fbGVuLCBzaWdyZXQsIFJTQV9zaXplKHJzYSkpOwoJc2NfdW5sb2NrKGNhcmQpOwoJaWYgKHIgPCAwKSB7CgkJZXJyb3IoInNjX3BrY3MxNV9jb21wdXRlX3NpZ25hdHVyZSgpIGZhaWxlZDogJXMiLAoJCSAgICAgIHNjX3N0cmVycm9yKHIpKTsKCQlnb3RvIGVycjsKCX0KCSpzaWdsZW4gPSByOwoJcmV0dXJuIDE7CmVycjoKCXNjX2Nsb3NlKCk7CglyZXR1cm4gMDsKfQoKc3RhdGljIGludApzY19wcml2YXRlX2VuY3J5cHQoaW50IGZsZW4sIHVfY2hhciAqZnJvbSwgdV9jaGFyICp0bywgUlNBICpyc2EsCiAgICBpbnQgcGFkZGluZykKewoJZXJyb3IoIlByaXZhdGUga2V5IGVuY3J5cHRpb24gbm90IHN1cHBvcnRlZCIpOwoJcmV0dXJuIC0xOwp9CgovKiBjYWxsZWQgb24gZnJlZSAqLwoKc3RhdGljIGludCAoKm9yaWdfZmluaXNoKShSU0EgKnJzYSkgPSBOVUxMOwoKc3RhdGljIGludApzY19maW5pc2goUlNBICpyc2EpCnsKCXN0cnVjdCBzY19wcml2X2RhdGEgKnByaXY7CgoJcHJpdiA9IFJTQV9nZXRfYXBwX2RhdGEocnNhKTsKCXByaXYtPnJlZl9jb3VudC0tOwoJaWYgKHByaXYtPnJlZl9jb3VudCA9PSAwKSB7CgkJZnJlZShwcml2KTsKCQlzY19jbG9zZSgpOwoJfQoJaWYgKG9yaWdfZmluaXNoKQoJCW9yaWdfZmluaXNoKHJzYSk7CglyZXR1cm4gMTsKfQoKLyogZW5naW5lIGZvciBvdmVybG9hZGluZyBwcml2YXRlIGtleSBvcGVyYXRpb25zICovCgpzdGF0aWMgUlNBX01FVEhPRCAqCnNjX2dldF9yc2FfbWV0aG9kKHZvaWQpCnsKCXN0YXRpYyBSU0FfTUVUSE9EIHNtYXJ0X3JzYTsKCWNvbnN0IFJTQV9NRVRIT0QgKmRlZiA9IFJTQV9nZXRfZGVmYXVsdF9tZXRob2QoKTsKCgkvKiB1c2UgdGhlIE9wZW5TU0wgdmVyc2lvbiAqLwoJbWVtY3B5KCZzbWFydF9yc2EsIGRlZiwgc2l6ZW9mKHNtYXJ0X3JzYSkpOwoKCXNtYXJ0X3JzYS5uYW1lCQk9ICJvcGVuc2MiOwoKCS8qIG92ZXJsb2FkICovCglzbWFydF9yc2EucnNhX3ByaXZfZW5jCT0gc2NfcHJpdmF0ZV9lbmNyeXB0OwoJc21hcnRfcnNhLnJzYV9wcml2X2RlYwk9IHNjX3ByaXZhdGVfZGVjcnlwdDsKCXNtYXJ0X3JzYS5yc2Ffc2lnbgk9IHNjX3NpZ247CgoJLyogc2F2ZSBvcmlnaW5hbCAqLwoJb3JpZ19maW5pc2gJCT0gZGVmLT5maW5pc2g7CglzbWFydF9yc2EuZmluaXNoCT0gc2NfZmluaXNoOwoKCXJldHVybiAmc21hcnRfcnNhOwp9CgojaWZkZWYgVVNFX0VOR0lORQpzdGF0aWMgRU5HSU5FICoKc2NfZ2V0X2VuZ2luZSh2b2lkKQp7CglzdGF0aWMgRU5HSU5FICpzbWFydF9lbmdpbmUgPSBOVUxMOwoKCWlmICgoc21hcnRfZW5naW5lID0gRU5HSU5FX25ldygpKSA9PSBOVUxMKQoJCWZhdGFsKCJFTkdJTkVfbmV3IGZhaWxlZCIpOwoKCUVOR0lORV9zZXRfaWQoc21hcnRfZW5naW5lLCAib3BlbnNjIik7CglFTkdJTkVfc2V0X25hbWUoc21hcnRfZW5naW5lLCAiT3BlblNDIik7CgoJRU5HSU5FX3NldF9SU0Eoc21hcnRfZW5naW5lLCBzY19nZXRfcnNhX21ldGhvZCgpKTsKCUVOR0lORV9zZXRfRFNBKHNtYXJ0X2VuZ2luZSwgRFNBX2dldF9kZWZhdWx0X29wZW5zc2xfbWV0aG9kKCkpOwoJRU5HSU5FX3NldF9ESChzbWFydF9lbmdpbmUsIERIX2dldF9kZWZhdWx0X29wZW5zc2xfbWV0aG9kKCkpOwoJRU5HSU5FX3NldF9SQU5EKHNtYXJ0X2VuZ2luZSwgUkFORF9TU0xlYXkoKSk7CglFTkdJTkVfc2V0X0JOX21vZF9leHAoc21hcnRfZW5naW5lLCBCTl9tb2RfZXhwKTsKCglyZXR1cm4gc21hcnRfZW5naW5lOwp9CiNlbmRpZgoKc3RhdGljIHZvaWQKY29udmVydF9yc2FfdG9fcnNhMShLZXkgKiBpbiwgS2V5ICogb3V0KQp7CglzdHJ1Y3Qgc2NfcHJpdl9kYXRhICpwcml2OwoKCW91dC0+cnNhLT5mbGFncyA9IGluLT5yc2EtPmZsYWdzOwoJb3V0LT5mbGFncyA9IGluLT5mbGFnczsKCVJTQV9zZXRfbWV0aG9kKG91dC0+cnNhLCBSU0FfZ2V0X21ldGhvZChpbi0+cnNhKSk7CglCTl9jb3B5KG91dC0+cnNhLT5uLCBpbi0+cnNhLT5uKTsKCUJOX2NvcHkob3V0LT5yc2EtPmUsIGluLT5yc2EtPmUpOwoJcHJpdiA9IFJTQV9nZXRfYXBwX2RhdGEoaW4tPnJzYSk7Cglwcml2LT5yZWZfY291bnQrKzsKCVJTQV9zZXRfYXBwX2RhdGEob3V0LT5yc2EsIHByaXYpOwoJcmV0dXJuOwp9CgpzdGF0aWMgaW50CnNjX3JlYWRfcHVia2V5KEtleSAqIGssIGNvbnN0IHN0cnVjdCBzY19wa2NzMTVfb2JqZWN0ICpjZXJ0X29iaikKewoJaW50IHI7CglzY19wa2NzMTVfY2VydF90ICpjZXJ0ID0gTlVMTDsKCXN0cnVjdCBzY19wcml2X2RhdGEgKnByaXYgPSBOVUxMOwoJc2NfcGtjczE1X2NlcnRfaW5mb190ICpjaW5mbyA9IGNlcnRfb2JqLT5kYXRhOwoKCVg1MDkgKng1MDkgPSBOVUxMOwoJRVZQX1BLRVkgKnB1YmtleSA9IE5VTEw7Cgl1OCAqcDsKCWNoYXIgKnRtcDsKCglkZWJ1Zygic2NfcmVhZF9wdWJrZXkoKSB3aXRoIGNlcnQgaWQgJTAyWCIsIGNpbmZvLT5pZC52YWx1ZVswXSk7CglyID0gc2NfcGtjczE1X3JlYWRfY2VydGlmaWNhdGUocDE1Y2FyZCwgY2luZm8sICZjZXJ0KTsKCWlmIChyKSB7CgkJbG9naXQoIkNlcnRpZmljYXRlIHJlYWQgZmFpbGVkOiAlcyIsIHNjX3N0cmVycm9yKHIpKTsKCQlnb3RvIGVycjsKCX0KCXg1MDkgPSBYNTA5X25ldygpOwoJaWYgKHg1MDkgPT0gTlVMTCkgewoJCXIgPSAtMTsKCQlnb3RvIGVycjsKCX0KCXAgPSBjZXJ0LT5kYXRhOwoJaWYgKCFkMmlfWDUwOSgmeDUwOSwgJnAsIGNlcnQtPmRhdGFfbGVuKSkgewoJCWxvZ2l0KCJVbmFibGUgdG8gcGFyc2UgWC41MDkgY2VydGlmaWNhdGUiKTsKCQlyID0gLTE7CgkJZ290byBlcnI7Cgl9CglzY19wa2NzMTVfZnJlZV9jZXJ0aWZpY2F0ZShjZXJ0KTsKCWNlcnQgPSBOVUxMOwoJcHVia2V5ID0gWDUwOV9nZXRfcHVia2V5KHg1MDkpOwoJWDUwOV9mcmVlKHg1MDkpOwoJeDUwOSA9IE5VTEw7CglpZiAocHVia2V5LT50eXBlICE9IEVWUF9QS0VZX1JTQSkgewoJCWxvZ2l0KCJQdWJsaWMga2V5IGlzIG9mIHVua25vd24gdHlwZSIpOwoJCXIgPSAtMTsKCQlnb3RvIGVycjsKCX0KCWstPnJzYSA9IEVWUF9QS0VZX2dldDFfUlNBKHB1YmtleSk7CglFVlBfUEtFWV9mcmVlKHB1YmtleSk7CgoJay0+cnNhLT5mbGFncyB8PSBSU0FfRkxBR19TSUdOX1ZFUjsKCVJTQV9zZXRfbWV0aG9kKGstPnJzYSwgc2NfZ2V0X3JzYV9tZXRob2QoKSk7Cglwcml2ID0geG1hbGxvYyhzaXplb2Yoc3RydWN0IHNjX3ByaXZfZGF0YSkpOwoJcHJpdi0+Y2VydF9pZCA9IGNpbmZvLT5pZDsKCXByaXYtPnJlZl9jb3VudCA9IDE7CglSU0Ffc2V0X2FwcF9kYXRhKGstPnJzYSwgcHJpdik7CgoJay0+ZmxhZ3MgPSBLRVlfRkxBR19FWFQ7Cgl0bXAgPSBrZXlfZmluZ2VycHJpbnQoaywgU1NIX0ZQX01ENSwgU1NIX0ZQX0hFWCk7CglkZWJ1ZygiZmluZ2VycHJpbnQgJWQgJXMiLCBrZXlfc2l6ZShrKSwgdG1wKTsKCXhmcmVlKHRtcCk7CgoJcmV0dXJuIDA7CmVycjoKCWlmIChjZXJ0KQoJCXNjX3BrY3MxNV9mcmVlX2NlcnRpZmljYXRlKGNlcnQpOwoJaWYgKHB1YmtleSkKCQlFVlBfUEtFWV9mcmVlKHB1YmtleSk7CglpZiAoeDUwOSkKCQlYNTA5X2ZyZWUoeDUwOSk7CglyZXR1cm4gcjsKfQoKS2V5ICoqCnNjX2dldF9rZXlzKGNvbnN0IGNoYXIgKmlkLCBjb25zdCBjaGFyICpwaW4pCnsKCUtleSAqaywgKiprZXlzOwoJaW50IGksIHIsIHJlYWxfY291bnQgPSAwLCBrZXlfY291bnQ7CglzY19wa2NzMTVfaWRfdCBjZXJ0X2lkOwoJc2NfcGtjczE1X29iamVjdF90ICpjZXJ0c1szMl07CgljaGFyICpidWYgPSB4c3RyZHVwKGlkKSwgKnA7CgoJZGVidWcoInNjX2dldF9rZXlzIGNhbGxlZDogaWQgPSAlcyIsIGlkKTsKCglpZiAoc2NfcGluICE9IE5VTEwpCgkJeGZyZWUoc2NfcGluKTsKCXNjX3BpbiA9IChwaW4gPT0gTlVMTCkgPyBOVUxMIDogeHN0cmR1cChwaW4pOwoKCWNlcnRfaWQubGVuID0gMDsKCWlmICgocCA9IHN0cmNocihidWYsICc6JykpICE9IE5VTEwpIHsKCQkqcCA9IDA7CgkJcCsrOwoJCXNjX3BrY3MxNV9oZXhfc3RyaW5nX3RvX2lkKHAsICZjZXJ0X2lkKTsKCX0KCXIgPSBzc2NhbmYoYnVmLCAiJWQiLCAmc2NfcmVhZGVyX2lkKTsKCXhmcmVlKGJ1Zik7CglpZiAociAhPSAxKQoJCWdvdG8gZXJyOwoJaWYgKHAxNWNhcmQgPT0gTlVMTCkgewoJCXNjX2Nsb3NlKCk7CgkJciA9IHNjX2luaXQoKTsKCQlpZiAocikgewoJCQllcnJvcigiU21hcnRjYXJkIGluaXQgZmFpbGVkOiAlcyIsIHNjX3N0cmVycm9yKHIpKTsKCQkJZ290byBlcnI7CgkJfQoJfQoJaWYgKGNlcnRfaWQubGVuKSB7CgkJciA9IHNjX3BrY3MxNV9maW5kX2NlcnRfYnlfaWQocDE1Y2FyZCwgJmNlcnRfaWQsICZjZXJ0c1swXSk7CgkJaWYgKHIgPCAwKQoJCQlnb3RvIGVycjsKCQlrZXlfY291bnQgPSAxOwoJfSBlbHNlIHsKCQlyID0gc2NfcGtjczE1X2dldF9vYmplY3RzKHAxNWNhcmQsIFNDX1BLQ1MxNV9UWVBFX0NFUlRfWDUwOSwKCQkJCQkgIGNlcnRzLCAzMik7CgkJaWYgKHIgPT0gMCkgewoJCQlsb2dpdCgiTm8gY2VydGlmaWNhdGVzIGZvdW5kIG9uIHNtYXJ0Y2FyZCIpOwoJCQlyID0gLTE7CgkJCWdvdG8gZXJyOwoJCX0gZWxzZSBpZiAociA8IDApIHsKCQkJZXJyb3IoIkNlcnRpZmljYXRlIGVudW1lcmF0aW9uIGZhaWxlZDogJXMiLAoJCQkgICAgICBzY19zdHJlcnJvcihyKSk7CgkJCWdvdG8gZXJyOwoJCX0KCQlrZXlfY291bnQgPSByOwoJfQoJaWYgKGtleV9jb3VudCA+IDEwMjQpCgkJZmF0YWwoIlRvbyBtYW55IGtleXMgKCV1KSwgZXhwZWN0ZWQgPD0gMTAyNCIsIGtleV9jb3VudCk7CglrZXlzID0geGNhbGxvYyhrZXlfY291bnQgKiAyICsgMSwgc2l6ZW9mKEtleSAqKSk7Cglmb3IgKGkgPSAwOyBpIDwga2V5X2NvdW50OyBpKyspIHsKCQlzY19wa2NzMTVfb2JqZWN0X3QgKnRtcF9vYmogPSBOVUxMOwoJCWNlcnRfaWQgPSAoKHNjX3BrY3MxNV9jZXJ0X2luZm9fdCAqKShjZXJ0c1tpXS0+ZGF0YSkpLT5pZDsKCQlpZiAoc2NfcGtjczE1X2ZpbmRfcHJrZXlfYnlfaWQocDE1Y2FyZCwgJmNlcnRfaWQsICZ0bXBfb2JqKSkKCQkJLyogc2tpcCB0aGUgcHVibGljIGtleSAoY2VydGlmaWNhdGUpIGlmIG5vCgkJCSAqIGNvcnJlc3BvbmRpbmcgcHJpdmF0ZSBrZXkgaXMgcHJlc2VudCAqLwoJCQljb250aW51ZTsKCQlrID0ga2V5X25ldyhLRVlfUlNBKTsKCQlpZiAoayA9PSBOVUxMKQoJCQlicmVhazsKCQlyID0gc2NfcmVhZF9wdWJrZXkoaywgY2VydHNbaV0pOwoJCWlmIChyKSB7CgkJCWVycm9yKCJzY19yZWFkX3B1YmtleSBmYWlsZWQ6ICVzIiwgc2Nfc3RyZXJyb3IocikpOwoJCQlrZXlfZnJlZShrKTsKCQkJY29udGludWU7CgkJfQoJCWtleXNbcmVhbF9jb3VudF0gPSBrOwoJCXJlYWxfY291bnQrKzsKCQlrID0ga2V5X25ldyhLRVlfUlNBMSk7CgkJaWYgKGsgPT0gTlVMTCkKCQkJYnJlYWs7CgkJY29udmVydF9yc2FfdG9fcnNhMShrZXlzW3JlYWxfY291bnQtMV0sIGspOwoJCWtleXNbcmVhbF9jb3VudF0gPSBrOwoJCXJlYWxfY291bnQrKzsKCX0KCWtleXNbcmVhbF9jb3VudF0gPSBOVUxMOwoKCXJldHVybiBrZXlzOwplcnI6CglzY19jbG9zZSgpOwoJcmV0dXJuIE5VTEw7Cn0KCmludApzY19wdXRfa2V5KEtleSAqcHJ2LCBjb25zdCBjaGFyICppZCkKewoJZXJyb3IoImtleSB1cGxvYWRpbmcgbm90IHlldCBzdXBwb3J0ZWQiKTsKCXJldHVybiAtMTsKfQoKY2hhciAqCnNjX2dldF9rZXlfbGFiZWwoS2V5ICprZXkpCnsKCWludCByOwoJY29uc3Qgc3RydWN0IHNjX3ByaXZfZGF0YSAqcHJpdjsKCXN0cnVjdCBzY19wa2NzMTVfb2JqZWN0ICprZXlfb2JqOwoKCXByaXYgPSAoY29uc3Qgc3RydWN0IHNjX3ByaXZfZGF0YSAqKSBSU0FfZ2V0X2FwcF9kYXRhKGtleS0+cnNhKTsKCWlmIChwcml2ID09IE5VTEwgfHwgcDE1Y2FyZCA9PSBOVUxMKSB7CgkJbG9naXQoIlNtYXJ0Q2FyZCBrZXkgbm90IGxvYWRlZCIpOwoJCS8qIGludGVybmFsIGVycm9yID0+IHJldHVybiBkZWZhdWx0IGxhYmVsICovCgkJcmV0dXJuIHhzdHJkdXAoInNtYXJ0Y2FyZCBrZXkiKTsKCX0KCXIgPSBzY19wa2NzMTVfZmluZF9wcmtleV9ieV9pZChwMTVjYXJkLCAmcHJpdi0+Y2VydF9pZCwgJmtleV9vYmopOwoJaWYgKHIpIHsKCQlsb2dpdCgiVW5hYmxlIHRvIGZpbmQgcHJpdmF0ZSBrZXkgZnJvbSBTbWFydENhcmQ6ICVzIiwKCQkgICAgICBzY19zdHJlcnJvcihyKSk7CgkJcmV0dXJuIHhzdHJkdXAoInNtYXJ0Y2FyZCBrZXkiKTsKCX0KCWlmIChrZXlfb2JqID09IE5VTEwgfHwga2V5X29iai0+bGFiZWwgPT0gTlVMTCkKCQkvKiB0aGUgb3B0aW9uYWwgUEtDUyMxNSBsYWJlbCBkb2VzIG5vdCBleGlzdHMKCQkgKiA9PiByZXR1cm4gdGhlIGRlZmF1bHQgbGFiZWwgKi8KCQlyZXR1cm4geHN0cmR1cCgic21hcnRjYXJkIGtleSIpOwoJcmV0dXJuIHhzdHJkdXAoa2V5X29iai0+bGFiZWwpOwp9CgojZW5kaWYgLyogU01BUlRDQVJEICovCg==