LyoKICogQ29weXJpZ2h0IChjKSAyMDAyIEp1aGEgWXJq9mzkLiAgQWxsIHJpZ2h0cyByZXNlcnZlZC4KICogQ29weXJpZ2h0IChjKSAyMDAxIE1hcmt1cyBGcmllZGwuCiAqIAogKiBSZWRpc3RyaWJ1dGlvbiBhbmQgdXNlIGluIHNvdXJjZSBhbmQgYmluYXJ5IGZvcm1zLCB3aXRoIG9yIHdpdGhvdXQKICogbW9kaWZpY2F0aW9uLCBhcmUgcGVybWl0dGVkIHByb3ZpZGVkIHRoYXQgdGhlIGZvbGxvd2luZyBjb25kaXRpb25zCiAqIGFyZSBtZXQ6CiAqIDEuIFJlZGlzdHJpYnV0aW9ucyBvZiBzb3VyY2UgY29kZSBtdXN0IHJldGFpbiB0aGUgYWJvdmUgY29weXJpZ2h0CiAqICAgIG5vdGljZSwgdGhpcyBsaXN0IG9mIGNvbmRpdGlvbnMgYW5kIHRoZSBmb2xsb3dpbmcgZGlzY2xhaW1lci4KICogMi4gUmVkaXN0cmlidXRpb25zIGluIGJpbmFyeSBmb3JtIG11c3QgcmVwcm9kdWNlIHRoZSBhYm92ZSBjb3B5cmlnaHQKICogICAgbm90aWNlLCB0aGlzIGxpc3Qgb2YgY29uZGl0aW9ucyBhbmQgdGhlIGZvbGxvd2luZyBkaXNjbGFpbWVyIGluIHRoZQogKiAgICBkb2N1bWVudGF0aW9uIGFuZC9vciBvdGhlciBtYXRlcmlhbHMgcHJvdmlkZWQgd2l0aCB0aGUgZGlzdHJpYnV0aW9uLgogKgogKiBUSElTIFNPRlRXQVJFIElTIFBST1ZJREVEIEJZIFRIRSBBVVRIT1IgYGBBUyBJUycnIEFORCBBTlkgRVhQUkVTUyBPUgogKiBJTVBMSUVEIFdBUlJBTlRJRVMsIElOQ0xVRElORywgQlVUIE5PVCBMSU1JVEVEIFRPLCBUSEUgSU1QTElFRCBXQVJSQU5USUVTCiAqIE9GIE1FUkNIQU5UQUJJTElUWSBBTkQgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQVJFIERJU0NMQUlNRUQuCiAqIElOIE5PIEVWRU5UIFNIQUxMIFRIRSBBVVRIT1IgQkUgTElBQkxFIEZPUiBBTlkgRElSRUNULCBJTkRJUkVDVCwKICogSU5DSURFTlRBTCwgU1BFQ0lBTCwgRVhFTVBMQVJZLCBPUiBDT05TRVFVRU5USUFMIERBTUFHRVMgKElOQ0xVRElORywgQlVUCiAqIE5PVCBMSU1JVEVEIFRPLCBQUk9DVVJFTUVOVCBPRiBTVUJTVElUVVRFIEdPT0RTIE9SIFNFUlZJQ0VTOyBMT1NTIE9GIFVTRSwKICogREFUQSwgT1IgUFJPRklUUzsgT1IgQlVTSU5FU1MgSU5URVJSVVBUSU9OKSBIT1dFVkVSIENBVVNFRCBBTkQgT04gQU5ZCiAqIFRIRU9SWSBPRiBMSUFCSUxJVFksIFdIRVRIRVIgSU4gQ09OVFJBQ1QsIFNUUklDVCBMSUFCSUxJVFksIE9SIFRPUlQKICogKElOQ0xVRElORyBORUdMSUdFTkNFIE9SIE9USEVSV0lTRSkgQVJJU0lORyBJTiBBTlkgV0FZIE9VVCBPRiBUSEUgVVNFIE9GCiAqIFRISVMgU09GVFdBUkUsIEVWRU4gSUYgQURWSVNFRCBPRiBUSEUgUE9TU0lCSUxJVFkgT0YgU1VDSCBEQU1BR0UuCiAqLwoKI2luY2x1ZGUgImluY2x1ZGVzLmgiCiNpZiBkZWZpbmVkKFNNQVJUQ0FSRCkgJiYgZGVmaW5lZChVU0VfT1BFTlNDKQoKI2luY2x1ZGUgPG9wZW5zc2wvZXZwLmg+CiNpbmNsdWRlIDxvcGVuc3NsL3g1MDkuaD4KCiNpbmNsdWRlIDxvcGVuc2Mvb3BlbnNjLmg+CiNpbmNsdWRlIDxvcGVuc2MvcGtjczE1Lmg+CgojaW5jbHVkZSAia2V5LmgiCiNpbmNsdWRlICJsb2cuaCIKI2luY2x1ZGUgInhtYWxsb2MuaCIKI2luY2x1ZGUgInJlYWRwYXNzLmgiCiNpbmNsdWRlICJzY2FyZC5oIgoKI2lmIE9QRU5TU0xfVkVSU0lPTl9OVU1CRVIgPCAweDAwOTA3MDAwTCAmJiBkZWZpbmVkKENSWVBUT19MT0NLX0VOR0lORSkKI2RlZmluZSBVU0VfRU5HSU5FCiNkZWZpbmUgUlNBX2dldF9kZWZhdWx0X21ldGhvZCBSU0FfZ2V0X2RlZmF1bHRfb3BlbnNzbF9tZXRob2QKI2Vsc2UKI2VuZGlmCgojaWZkZWYgVVNFX0VOR0lORQojaW5jbHVkZSA8b3BlbnNzbC9lbmdpbmUuaD4KI2RlZmluZSBzY19nZXRfcnNhIHNjX2dldF9lbmdpbmUKI2Vsc2UKI2RlZmluZSBzY19nZXRfcnNhIHNjX2dldF9yc2FfbWV0aG9kCiNlbmRpZgoKc3RhdGljIGludCBzY19yZWFkZXJfaWQ7CnN0YXRpYyBzY19jb250ZXh0X3QgKmN0eCA9IE5VTEw7CnN0YXRpYyBzY19jYXJkX3QgKmNhcmQgPSBOVUxMOwpzdGF0aWMgc2NfcGtjczE1X2NhcmRfdCAqcDE1Y2FyZCA9IE5VTEw7CgpzdGF0aWMgY2hhciAqc2NfcGluID0gTlVMTDsKCnN0cnVjdCBzY19wcml2X2RhdGEKewoJc3RydWN0IHNjX3BrY3MxNV9pZCBjZXJ0X2lkOwoJaW50IHJlZl9jb3VudDsKfTsKCnZvaWQKc2NfY2xvc2Uodm9pZCkKewoJaWYgKHAxNWNhcmQpIHsKCQlzY19wa2NzMTVfdW5iaW5kKHAxNWNhcmQpOwoJCXAxNWNhcmQgPSBOVUxMOwoJfQoJaWYgKGNhcmQpIHsKCQlzY19kaXNjb25uZWN0X2NhcmQoY2FyZCwgMCk7CgkJY2FyZCA9IE5VTEw7Cgl9CglpZiAoY3R4KSB7CgkJc2NfcmVsZWFzZV9jb250ZXh0KGN0eCk7CgkJY3R4ID0gTlVMTDsKCX0KfQoKc3RhdGljIGludCAKc2NfaW5pdCh2b2lkKQp7CglpbnQgcjsKCglyID0gc2NfZXN0YWJsaXNoX2NvbnRleHQoJmN0eCwgIm9wZW5zc2giKTsKCWlmIChyKQoJCWdvdG8gZXJyOwoJaWYgKHNjX3JlYWRlcl9pZCA+PSBjdHgtPnJlYWRlcl9jb3VudCkgewoJCXIgPSBTQ19FUlJPUl9OT19SRUFERVJTX0ZPVU5EOwoJCWVycm9yKCJJbGxlZ2FsIHJlYWRlciBudW1iZXIgJWQgKG1heCAlZCkiLCBzY19yZWFkZXJfaWQsIAoJCSAgICBjdHgtPnJlYWRlcl9jb3VudCAtMSk7CgkJZ290byBlcnI7Cgl9CglyID0gc2NfY29ubmVjdF9jYXJkKGN0eC0+cmVhZGVyW3NjX3JlYWRlcl9pZF0sIDAsICZjYXJkKTsKCWlmIChyKQoJCWdvdG8gZXJyOwoJciA9IHNjX3BrY3MxNV9iaW5kKGNhcmQsICZwMTVjYXJkKTsKCWlmIChyKQoJCWdvdG8gZXJyOwoJcmV0dXJuIDA7CmVycjoKCXNjX2Nsb3NlKCk7CglyZXR1cm4gcjsKfQoKLyogcHJpdmF0ZSBrZXkgb3BlcmF0aW9ucyAqLwoKc3RhdGljIGludApzY19wcmtleV9vcF9pbml0KFJTQSAqcnNhLCBzdHJ1Y3Qgc2NfcGtjczE1X29iamVjdCAqKmtleV9vYmpfb3V0LAoJdW5zaWduZWQgaW50IHVzYWdlKQp7CglpbnQgcjsKCXN0cnVjdCBzY19wcml2X2RhdGEgKnByaXY7CglzdHJ1Y3Qgc2NfcGtjczE1X29iamVjdCAqa2V5X29iajsKCXN0cnVjdCBzY19wa2NzMTVfcHJrZXlfaW5mbyAqa2V5OwoJc3RydWN0IHNjX3BrY3MxNV9vYmplY3QgKnBpbl9vYmo7CglzdHJ1Y3Qgc2NfcGtjczE1X3Bpbl9pbmZvICpwaW47CgoJcHJpdiA9IChzdHJ1Y3Qgc2NfcHJpdl9kYXRhICopIFJTQV9nZXRfYXBwX2RhdGEocnNhKTsKCWlmIChwcml2ID09IE5VTEwpCgkJcmV0dXJuIC0xOwoJaWYgKHAxNWNhcmQgPT0gTlVMTCkgewoJCXNjX2Nsb3NlKCk7CgkJciA9IHNjX2luaXQoKTsKCQlpZiAocikgewoJCQllcnJvcigiU21hcnRDYXJkIGluaXQgZmFpbGVkOiAlcyIsIHNjX3N0cmVycm9yKHIpKTsKCQkJZ290byBlcnI7CgkJfQoJfQoJciA9IHNjX3BrY3MxNV9maW5kX3Bya2V5X2J5X2lkX3VzYWdlKHAxNWNhcmQsICZwcml2LT5jZXJ0X2lkLCAKCQl1c2FnZSwgJmtleV9vYmopOwoJaWYgKHIpIHsKCQllcnJvcigiVW5hYmxlIHRvIGZpbmQgcHJpdmF0ZSBrZXkgZnJvbSBTbWFydENhcmQ6ICVzIiwKCQkgICAgICBzY19zdHJlcnJvcihyKSk7CgkJZ290byBlcnI7Cgl9CglrZXkgPSBrZXlfb2JqLT5kYXRhOwoJciA9IHNjX3BrY3MxNV9maW5kX3Bpbl9ieV9hdXRoX2lkKHAxNWNhcmQsICZrZXlfb2JqLT5hdXRoX2lkLAoJCQkJCSAgJnBpbl9vYmopOwoJaWYgKHIgPT0gU0NfRVJST1JfT0JKRUNUX05PVF9GT1VORCkgewoJCS8qIG5vIHBpbiByZXF1aXJlZCAqLwoJCXIgPSBzY19sb2NrKGNhcmQpOwoJCWlmIChyKSB7CgkJCWVycm9yKCJVbmFibGUgdG8gbG9jayBzbWFydGNhcmQ6ICVzIiwgc2Nfc3RyZXJyb3IocikpOwoJCQlnb3RvIGVycjsKCQl9CgkJKmtleV9vYmpfb3V0ID0ga2V5X29iajsKCQlyZXR1cm4gMDsKCX0gZWxzZSBpZiAocikgewoJCWVycm9yKCJVbmFibGUgdG8gZmluZCBQSU4gb2JqZWN0IGZyb20gU21hcnRDYXJkOiAlcyIsCgkJICAgICAgc2Nfc3RyZXJyb3IocikpOwoJCWdvdG8gZXJyOwoJfQoJcGluID0gcGluX29iai0+ZGF0YTsKCXIgPSBzY19sb2NrKGNhcmQpOwoJaWYgKHIpIHsKCQllcnJvcigiVW5hYmxlIHRvIGxvY2sgc21hcnRjYXJkOiAlcyIsIHNjX3N0cmVycm9yKHIpKTsKCQlnb3RvIGVycjsKCX0KCWlmIChzY19waW4gIT0gTlVMTCkgewoJCXIgPSBzY19wa2NzMTVfdmVyaWZ5X3BpbihwMTVjYXJkLCBwaW4sIHNjX3BpbiwKCQkJCQkgc3RybGVuKHNjX3BpbikpOwoJCWlmIChyKSB7CgkJCXNjX3VubG9jayhjYXJkKTsKCQkJZXJyb3IoIlBJTiBjb2RlIHZlcmlmaWNhdGlvbiBmYWlsZWQ6ICVzIiwKCQkJICAgICAgc2Nfc3RyZXJyb3IocikpOwoJCQlnb3RvIGVycjsKCQl9Cgl9Cgkqa2V5X29ial9vdXQgPSBrZXlfb2JqOwoJcmV0dXJuIDA7CmVycjoKCXNjX2Nsb3NlKCk7CglyZXR1cm4gLTE7Cn0KCiNkZWZpbmUgU0NfVVNBR0VfREVDUllQVAlTQ19QS0NTMTVfUFJLRVlfVVNBR0VfREVDUllQVCB8IFwKCQkJCVNDX1BLQ1MxNV9QUktFWV9VU0FHRV9VTldSQVAKCnN0YXRpYyBpbnQKc2NfcHJpdmF0ZV9kZWNyeXB0KGludCBmbGVuLCB1X2NoYXIgKmZyb20sIHVfY2hhciAqdG8sIFJTQSAqcnNhLAogICAgaW50IHBhZGRpbmcpCnsKCXN0cnVjdCBzY19wa2NzMTVfb2JqZWN0ICprZXlfb2JqOwoJaW50IHI7CgoJaWYgKHBhZGRpbmcgIT0gUlNBX1BLQ1MxX1BBRERJTkcpCgkJcmV0dXJuIC0xOwkKCXIgPSBzY19wcmtleV9vcF9pbml0KHJzYSwgJmtleV9vYmosIFNDX1VTQUdFX0RFQ1JZUFQpOwoJaWYgKHIpCgkJcmV0dXJuIC0xOwoJciA9IHNjX3BrY3MxNV9kZWNpcGhlcihwMTVjYXJkLCBrZXlfb2JqLCBTQ19BTEdPUklUSE1fUlNBX1BBRF9QS0NTMSwgCgkgICAgZnJvbSwgZmxlbiwgdG8sIGZsZW4pOwoJc2NfdW5sb2NrKGNhcmQpOwoJaWYgKHIgPCAwKSB7CgkJZXJyb3IoInNjX3BrY3MxNV9kZWNpcGhlcigpIGZhaWxlZDogJXMiLCBzY19zdHJlcnJvcihyKSk7CgkJZ290byBlcnI7Cgl9CglyZXR1cm4gcjsKZXJyOgoJc2NfY2xvc2UoKTsKCXJldHVybiAtMTsKfQoKI2RlZmluZSBTQ19VU0FHRV9TSUdOIAkJU0NfUEtDUzE1X1BSS0VZX1VTQUdFX1NJR04gfCBcCgkJCQlTQ19QS0NTMTVfUFJLRVlfVVNBR0VfU0lHTlJFQ09WRVIKCnN0YXRpYyBpbnQKc2Nfc2lnbihpbnQgdHlwZSwgdV9jaGFyICptLCB1bnNpZ25lZCBpbnQgbV9sZW4sCgl1bnNpZ25lZCBjaGFyICpzaWdyZXQsIHVuc2lnbmVkIGludCAqc2lnbGVuLCBSU0EgKnJzYSkKewoJc3RydWN0IHNjX3BrY3MxNV9vYmplY3QgKmtleV9vYmo7CglpbnQgcjsKCXVuc2lnbmVkIGxvbmcgZmxhZ3MgPSAwOwoKCS8qIFhYWDogc2NfcHJrZXlfb3BfaW5pdCB3aWxsIHNlYXJjaCBmb3IgYSBwa2NzMTUgcHJpdmF0ZQoJICoga2V5IG9iamVjdCB3aXRoIHRoZSBzaWduIG9yIHNpZ25yZWNvdmVyIHVzYWdlIGZsYWcgc2V0LgoJICogSWYgdGhlIHNpZ25pbmcga2V5IGhhcyBvbmx5IHRoZSBub24tcmVwdWRpYXRpb24gZmxhZyBzZXQKCSAqIHRoZSBrZXkgd2lsbCBiZSByZWplY3RlZCBhcyB1c2luZyBhIG5vbi1yZXB1ZGlhdGlvbiBrZXkKCSAqIGZvciBhdXRoZW50aWNhdGlvbiBpcyBub3QgcmVjb21tZW5kZWQuIE5vdGU6IFRoaXMgZG9lcyBub3QKCSAqIHByZXZlbnQgdGhlIHVzZSBvZiBhIG5vbi1yZXB1ZGlhdGlvbiBrZXkgZm9yIGF1dGhlbnRpY2F0aW9uCgkgKiBpZiB0aGUgc2lnbiBvciBzaWducmVjb3ZlciBmbGFnIGlzIHNldCBhcyB3ZWxsLiAKCSAqLwoJciA9IHNjX3Bya2V5X29wX2luaXQocnNhLCAma2V5X29iaiwgU0NfVVNBR0VfU0lHTik7CglpZiAocikKCQlyZXR1cm4gLTE7CgkvKiBGSVhNRTogbGVuZ3RoIG9mIHNpZ3JldCBjb3JyZWN0PyAqLwoJLyogRklYTUU6IGNoZWNrICd0eXBlJyBhbmQgbW9kaWZ5IGZsYWdzIGFjY29yZGluZ2x5ICovCglmbGFncyA9IFNDX0FMR09SSVRITV9SU0FfUEFEX1BLQ1MxIHwgU0NfQUxHT1JJVEhNX1JTQV9IQVNIX1NIQTE7CglyID0gc2NfcGtjczE1X2NvbXB1dGVfc2lnbmF0dXJlKHAxNWNhcmQsIGtleV9vYmosIGZsYWdzLAoJCQkJCW0sIG1fbGVuLCBzaWdyZXQsIFJTQV9zaXplKHJzYSkpOwoJc2NfdW5sb2NrKGNhcmQpOwoJaWYgKHIgPCAwKSB7CgkJZXJyb3IoInNjX3BrY3MxNV9jb21wdXRlX3NpZ25hdHVyZSgpIGZhaWxlZDogJXMiLAoJCSAgICAgIHNjX3N0cmVycm9yKHIpKTsKCQlnb3RvIGVycjsKCX0KCSpzaWdsZW4gPSByOwoJcmV0dXJuIDE7CmVycjoKCXNjX2Nsb3NlKCk7CglyZXR1cm4gMDsKfQoKc3RhdGljIGludApzY19wcml2YXRlX2VuY3J5cHQoaW50IGZsZW4sIHVfY2hhciAqZnJvbSwgdV9jaGFyICp0bywgUlNBICpyc2EsCiAgICBpbnQgcGFkZGluZykKewoJZXJyb3IoIlByaXZhdGUga2V5IGVuY3J5cHRpb24gbm90IHN1cHBvcnRlZCIpOwoJcmV0dXJuIC0xOwp9CgovKiBjYWxsZWQgb24gZnJlZSAqLwoKc3RhdGljIGludCAoKm9yaWdfZmluaXNoKShSU0EgKnJzYSkgPSBOVUxMOwoKc3RhdGljIGludApzY19maW5pc2goUlNBICpyc2EpCnsKCXN0cnVjdCBzY19wcml2X2RhdGEgKnByaXY7CgoJcHJpdiA9IFJTQV9nZXRfYXBwX2RhdGEocnNhKTsKCXByaXYtPnJlZl9jb3VudC0tOwoJaWYgKHByaXYtPnJlZl9jb3VudCA9PSAwKSB7CgkJZnJlZShwcml2KTsKCQlzY19jbG9zZSgpOwoJfQoJaWYgKG9yaWdfZmluaXNoKQoJCW9yaWdfZmluaXNoKHJzYSk7CglyZXR1cm4gMTsKfQoKLyogZW5naW5lIGZvciBvdmVybG9hZGluZyBwcml2YXRlIGtleSBvcGVyYXRpb25zICovCgpzdGF0aWMgUlNBX01FVEhPRCAqCnNjX2dldF9yc2FfbWV0aG9kKHZvaWQpCnsKCXN0YXRpYyBSU0FfTUVUSE9EIHNtYXJ0X3JzYTsKCWNvbnN0IFJTQV9NRVRIT0QgKmRlZiA9IFJTQV9nZXRfZGVmYXVsdF9tZXRob2QoKTsKCgkvKiB1c2UgdGhlIE9wZW5TU0wgdmVyc2lvbiAqLwoJbWVtY3B5KCZzbWFydF9yc2EsIGRlZiwgc2l6ZW9mKHNtYXJ0X3JzYSkpOwoKCXNtYXJ0X3JzYS5uYW1lCQk9ICJvcGVuc2MiOwoKCS8qIG92ZXJsb2FkICovCglzbWFydF9yc2EucnNhX3ByaXZfZW5jCT0gc2NfcHJpdmF0ZV9lbmNyeXB0OwoJc21hcnRfcnNhLnJzYV9wcml2X2RlYwk9IHNjX3ByaXZhdGVfZGVjcnlwdDsKCXNtYXJ0X3JzYS5yc2Ffc2lnbgk9IHNjX3NpZ247CgoJLyogc2F2ZSBvcmlnaW5hbCAqLwoJb3JpZ19maW5pc2gJCT0gZGVmLT5maW5pc2g7CglzbWFydF9yc2EuZmluaXNoCT0gc2NfZmluaXNoOwoKCXJldHVybiAmc21hcnRfcnNhOwp9CgojaWZkZWYgVVNFX0VOR0lORQpzdGF0aWMgRU5HSU5FICoKc2NfZ2V0X2VuZ2luZSh2b2lkKQp7CglzdGF0aWMgRU5HSU5FICpzbWFydF9lbmdpbmUgPSBOVUxMOwoKCWlmICgoc21hcnRfZW5naW5lID0gRU5HSU5FX25ldygpKSA9PSBOVUxMKQoJCWZhdGFsKCJFTkdJTkVfbmV3IGZhaWxlZCIpOwoKCUVOR0lORV9zZXRfaWQoc21hcnRfZW5naW5lLCAib3BlbnNjIik7CglFTkdJTkVfc2V0X25hbWUoc21hcnRfZW5naW5lLCAiT3BlblNDIik7CgoJRU5HSU5FX3NldF9SU0Eoc21hcnRfZW5naW5lLCBzY19nZXRfcnNhX21ldGhvZCgpKTsKCUVOR0lORV9zZXRfRFNBKHNtYXJ0X2VuZ2luZSwgRFNBX2dldF9kZWZhdWx0X29wZW5zc2xfbWV0aG9kKCkpOwoJRU5HSU5FX3NldF9ESChzbWFydF9lbmdpbmUsIERIX2dldF9kZWZhdWx0X29wZW5zc2xfbWV0aG9kKCkpOwoJRU5HSU5FX3NldF9SQU5EKHNtYXJ0X2VuZ2luZSwgUkFORF9TU0xlYXkoKSk7CglFTkdJTkVfc2V0X0JOX21vZF9leHAoc21hcnRfZW5naW5lLCBCTl9tb2RfZXhwKTsKCglyZXR1cm4gc21hcnRfZW5naW5lOwp9CiNlbmRpZgoKc3RhdGljIHZvaWQKY29udmVydF9yc2FfdG9fcnNhMShLZXkgKiBpbiwgS2V5ICogb3V0KQp7CglzdHJ1Y3Qgc2NfcHJpdl9kYXRhICpwcml2OwoJCglvdXQtPnJzYS0+ZmxhZ3MgPSBpbi0+cnNhLT5mbGFnczsKCW91dC0+ZmxhZ3MgPSBpbi0+ZmxhZ3M7CglSU0Ffc2V0X21ldGhvZChvdXQtPnJzYSwgUlNBX2dldF9tZXRob2QoaW4tPnJzYSkpOwoJQk5fY29weShvdXQtPnJzYS0+biwgaW4tPnJzYS0+bik7CglCTl9jb3B5KG91dC0+cnNhLT5lLCBpbi0+cnNhLT5lKTsKCXByaXYgPSBSU0FfZ2V0X2FwcF9kYXRhKGluLT5yc2EpOwoJcHJpdi0+cmVmX2NvdW50Kys7CglSU0Ffc2V0X2FwcF9kYXRhKG91dC0+cnNhLCBwcml2KTsKCXJldHVybjsKfQoKc3RhdGljIGludCAKc2NfcmVhZF9wdWJrZXkoS2V5ICogaywgY29uc3Qgc3RydWN0IHNjX3BrY3MxNV9vYmplY3QgKmNlcnRfb2JqKQp7CglpbnQgcjsKCXNjX3BrY3MxNV9jZXJ0X3QgKmNlcnQgPSBOVUxMOwoJc3RydWN0IHNjX3ByaXZfZGF0YSAqcHJpdiA9IE5VTEw7CglzY19wa2NzMTVfY2VydF9pbmZvX3QgKmNpbmZvID0gY2VydF9vYmotPmRhdGE7CgoJWDUwOSAqeDUwOSA9IE5VTEw7CglFVlBfUEtFWSAqcHVia2V5ID0gTlVMTDsKCXU4ICpwOwoJY2hhciAqdG1wOwoJCglkZWJ1Zygic2NfcmVhZF9wdWJrZXkoKSB3aXRoIGNlcnQgaWQgJTAyWCIsIGNpbmZvLT5pZC52YWx1ZVswXSk7CglyID0gc2NfcGtjczE1X3JlYWRfY2VydGlmaWNhdGUocDE1Y2FyZCwgY2luZm8sICZjZXJ0KTsKCWlmIChyKSB7CgkJbG9naXQoIkNlcnRpZmljYXRlIHJlYWQgZmFpbGVkOiAlcyIsIHNjX3N0cmVycm9yKHIpKTsKCQlnb3RvIGVycjsKCX0KCXg1MDkgPSBYNTA5X25ldygpOwoJaWYgKHg1MDkgPT0gTlVMTCkgewoJCXIgPSAtMTsgCgkJZ290byBlcnI7Cgl9CglwID0gY2VydC0+ZGF0YTsKCWlmICghZDJpX1g1MDkoJng1MDksICZwLCBjZXJ0LT5kYXRhX2xlbikpIHsKCQlsb2dpdCgiVW5hYmxlIHRvIHBhcnNlIFguNTA5IGNlcnRpZmljYXRlIik7CgkJciA9IC0xOwoJCWdvdG8gZXJyOwoJfQoJc2NfcGtjczE1X2ZyZWVfY2VydGlmaWNhdGUoY2VydCk7CgljZXJ0ID0gTlVMTDsKCXB1YmtleSA9IFg1MDlfZ2V0X3B1YmtleSh4NTA5KTsKCVg1MDlfZnJlZSh4NTA5KTsKCXg1MDkgPSBOVUxMOwoJaWYgKHB1YmtleS0+dHlwZSAhPSBFVlBfUEtFWV9SU0EpIHsKCQlsb2dpdCgiUHVibGljIGtleSBpcyBvZiB1bmtub3duIHR5cGUiKTsKCQlyID0gLTE7CgkJZ290byBlcnI7Cgl9CglrLT5yc2EgPSBFVlBfUEtFWV9nZXQxX1JTQShwdWJrZXkpOwoJRVZQX1BLRVlfZnJlZShwdWJrZXkpOwoKCWstPnJzYS0+ZmxhZ3MgfD0gUlNBX0ZMQUdfU0lHTl9WRVI7CglSU0Ffc2V0X21ldGhvZChrLT5yc2EsIHNjX2dldF9yc2FfbWV0aG9kKCkpOwoJcHJpdiA9IHhtYWxsb2Moc2l6ZW9mKHN0cnVjdCBzY19wcml2X2RhdGEpKTsKCXByaXYtPmNlcnRfaWQgPSBjaW5mby0+aWQ7Cglwcml2LT5yZWZfY291bnQgPSAxOwoJUlNBX3NldF9hcHBfZGF0YShrLT5yc2EsIHByaXYpOwoKCWstPmZsYWdzID0gS0VZX0ZMQUdfRVhUOwoJdG1wID0ga2V5X2ZpbmdlcnByaW50KGssIFNTSF9GUF9NRDUsIFNTSF9GUF9IRVgpOwoJZGVidWcoImZpbmdlcnByaW50ICVkICVzIiwga2V5X3NpemUoayksIHRtcCk7Cgl4ZnJlZSh0bXApOwoJCglyZXR1cm4gMDsKZXJyOgoJaWYgKGNlcnQpCgkJc2NfcGtjczE1X2ZyZWVfY2VydGlmaWNhdGUoY2VydCk7CglpZiAocHVia2V5KQoJCUVWUF9QS0VZX2ZyZWUocHVia2V5KTsKCWlmICh4NTA5KQoJCVg1MDlfZnJlZSh4NTA5KTsKCXJldHVybiByOwp9CgpLZXkgKioKc2NfZ2V0X2tleXMoY29uc3QgY2hhciAqaWQsIGNvbnN0IGNoYXIgKnBpbikKewoJS2V5ICprLCAqKmtleXM7CglpbnQgaSwgciwgcmVhbF9jb3VudCA9IDAsIGtleV9jb3VudDsKCXNjX3BrY3MxNV9pZF90IGNlcnRfaWQ7CglzY19wa2NzMTVfb2JqZWN0X3QgKmNlcnRzWzMyXTsKCWNoYXIgKmJ1ZiA9IHhzdHJkdXAoaWQpLCAqcDsKCglkZWJ1Zygic2NfZ2V0X2tleXMgY2FsbGVkOiBpZCA9ICVzIiwgaWQpOwoKCWlmIChzY19waW4gIT0gTlVMTCkKCQl4ZnJlZShzY19waW4pOwoJc2NfcGluID0gKHBpbiA9PSBOVUxMKSA/IE5VTEwgOiB4c3RyZHVwKHBpbik7CgoJY2VydF9pZC5sZW4gPSAwOwoJaWYgKChwID0gc3RyY2hyKGJ1ZiwgJzonKSkgIT0gTlVMTCkgewoJCSpwID0gMDsKCQlwKys7CgkJc2NfcGtjczE1X2hleF9zdHJpbmdfdG9faWQocCwgJmNlcnRfaWQpOwoJfQoJciA9IHNzY2FuZihidWYsICIlZCIsICZzY19yZWFkZXJfaWQpOwoJeGZyZWUoYnVmKTsKCWlmIChyICE9IDEpCgkJZ290byBlcnI7CglpZiAocDE1Y2FyZCA9PSBOVUxMKSB7CgkJc2NfY2xvc2UoKTsKCQlyID0gc2NfaW5pdCgpOwoJCWlmIChyKSB7CgkJCWVycm9yKCJTbWFydGNhcmQgaW5pdCBmYWlsZWQ6ICVzIiwgc2Nfc3RyZXJyb3IocikpOwoJCQlnb3RvIGVycjsKCQl9Cgl9CglpZiAoY2VydF9pZC5sZW4pIHsKCQlyID0gc2NfcGtjczE1X2ZpbmRfY2VydF9ieV9pZChwMTVjYXJkLCAmY2VydF9pZCwgJmNlcnRzWzBdKTsKCQlpZiAociA8IDApCgkJCWdvdG8gZXJyOwoJCWtleV9jb3VudCA9IDE7Cgl9IGVsc2UgewoJCXIgPSBzY19wa2NzMTVfZ2V0X29iamVjdHMocDE1Y2FyZCwgU0NfUEtDUzE1X1RZUEVfQ0VSVF9YNTA5LAoJCQkJCSAgY2VydHMsIDMyKTsKCQlpZiAociA9PSAwKSB7CgkJCWxvZ2l0KCJObyBjZXJ0aWZpY2F0ZXMgZm91bmQgb24gc21hcnRjYXJkIik7CgkJCXIgPSAtMTsKCQkJZ290byBlcnI7CgkJfSBlbHNlIGlmIChyIDwgMCkgewoJCQllcnJvcigiQ2VydGlmaWNhdGUgZW51bWVyYXRpb24gZmFpbGVkOiAlcyIsCgkJCSAgICAgIHNjX3N0cmVycm9yKHIpKTsKCQkJZ290byBlcnI7CgkJfQoJCWtleV9jb3VudCA9IHI7Cgl9CglrZXlzID0geG1hbGxvYyhzaXplb2YoS2V5ICopICogKGtleV9jb3VudCoyKzEpKTsKCWZvciAoaSA9IDA7IGkgPCBrZXlfY291bnQ7IGkrKykgewoJCXNjX3BrY3MxNV9vYmplY3RfdCAqdG1wX29iaiA9IE5VTEw7CgkJY2VydF9pZCA9ICgoc2NfcGtjczE1X2NlcnRfaW5mb190ICopKGNlcnRzW2ldLT5kYXRhKSktPmlkOwoJCWlmIChzY19wa2NzMTVfZmluZF9wcmtleV9ieV9pZChwMTVjYXJkLCAmY2VydF9pZCwgJnRtcF9vYmopKQoJCQkvKiBza2lwIHRoZSBwdWJsaWMga2V5IChjZXJ0aWZpY2F0ZSkgaWYgbm8KCQkJICogY29ycmVzcG9uZGluZyBwcml2YXRlIGtleSBpcyBwcmVzZW50ICovCgkJCWNvbnRpbnVlOwoJCWsgPSBrZXlfbmV3KEtFWV9SU0EpOwoJCWlmIChrID09IE5VTEwpCgkJCWJyZWFrOwoJCXIgPSBzY19yZWFkX3B1YmtleShrLCBjZXJ0c1tpXSk7CgkJaWYgKHIpIHsKCQkJZXJyb3IoInNjX3JlYWRfcHVia2V5IGZhaWxlZDogJXMiLCBzY19zdHJlcnJvcihyKSk7CgkJCWtleV9mcmVlKGspOwoJCQljb250aW51ZTsKCQl9CgkJa2V5c1tyZWFsX2NvdW50XSA9IGs7CgkJcmVhbF9jb3VudCsrOwoJCWsgPSBrZXlfbmV3KEtFWV9SU0ExKTsKCQlpZiAoayA9PSBOVUxMKQoJCQlicmVhazsKCQljb252ZXJ0X3JzYV90b19yc2ExKGtleXNbcmVhbF9jb3VudC0xXSwgayk7CgkJa2V5c1tyZWFsX2NvdW50XSA9IGs7CgkJcmVhbF9jb3VudCsrOwoJfQoJa2V5c1tyZWFsX2NvdW50XSA9IE5VTEw7CgoJcmV0dXJuIGtleXM7CmVycjoKCXNjX2Nsb3NlKCk7CglyZXR1cm4gTlVMTDsKfQoKaW50CnNjX3B1dF9rZXkoS2V5ICpwcnYsIGNvbnN0IGNoYXIgKmlkKQp7CgllcnJvcigia2V5IHVwbG9hZGluZyBub3QgeWV0IHN1cHBvcnRlZCIpOwoJcmV0dXJuIC0xOwp9CgpjaGFyICoKc2NfZ2V0X2tleV9sYWJlbChLZXkgKmtleSkKewoJaW50IHI7Cgljb25zdCBzdHJ1Y3Qgc2NfcHJpdl9kYXRhICpwcml2OwoJc3RydWN0IHNjX3BrY3MxNV9vYmplY3QgKmtleV9vYmo7CgoJcHJpdiA9IChjb25zdCBzdHJ1Y3Qgc2NfcHJpdl9kYXRhICopIFJTQV9nZXRfYXBwX2RhdGEoa2V5LT5yc2EpOwoJaWYgKHByaXYgPT0gTlVMTCB8fCBwMTVjYXJkID09IE5VTEwpIHsKCQlsb2dpdCgiU21hcnRDYXJkIGtleSBub3QgbG9hZGVkIik7CgkJLyogaW50ZXJuYWwgZXJyb3IgPT4gcmV0dXJuIGRlZmF1bHQgbGFiZWwgKi8KCQlyZXR1cm4geHN0cmR1cCgic21hcnRjYXJkIGtleSIpOwoJfQoJciA9IHNjX3BrY3MxNV9maW5kX3Bya2V5X2J5X2lkKHAxNWNhcmQsICZwcml2LT5jZXJ0X2lkLCAma2V5X29iaik7CglpZiAocikgewoJCWxvZ2l0KCJVbmFibGUgdG8gZmluZCBwcml2YXRlIGtleSBmcm9tIFNtYXJ0Q2FyZDogJXMiLAoJCSAgICAgIHNjX3N0cmVycm9yKHIpKTsKCQlyZXR1cm4geHN0cmR1cCgic21hcnRjYXJkIGtleSIpOwoJfQoJaWYgKGtleV9vYmogPT0gTlVMTCB8fCBrZXlfb2JqLT5sYWJlbCA9PSBOVUxMKQoJCS8qIHRoZSBvcHRpb25hbCBQS0NTIzE1IGxhYmVsIGRvZXMgbm90IGV4aXN0cwoJCSAqID0+IHJldHVybiB0aGUgZGVmYXVsdCBsYWJlbCAqLwoJCXJldHVybiB4c3RyZHVwKCJzbWFydGNhcmQga2V5Iik7CglyZXR1cm4geHN0cmR1cChrZXlfb2JqLT5sYWJlbCk7Cn0KCiNlbmRpZiAvKiBTTUFSVENBUkQgKi8K