LyoKICogRE9TIGludGVycnVwdCAwOWggaGFuZGxlciAoSVJRMSAtIEtFWUJPQVJEKQogKgogKiBDb3B5cmlnaHQgMTk5OSBPdmUgS+V2ZW4KICoKICogVGhpcyBsaWJyYXJ5IGlzIGZyZWUgc29mdHdhcmU7IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vcgogKiBtb2RpZnkgaXQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgTGVzc2VyIEdlbmVyYWwgUHVibGljCiAqIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5IHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb247IGVpdGhlcgogKiB2ZXJzaW9uIDIuMSBvZiB0aGUgTGljZW5zZSwgb3IgKGF0IHlvdXIgb3B0aW9uKSBhbnkgbGF0ZXIgdmVyc2lvbi4KICoKICogVGhpcyBsaWJyYXJ5IGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsCiAqIGJ1dCBXSVRIT1VUIEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mCiAqIE1FUkNIQU5UQUJJTElUWSBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gIFNlZSB0aGUgR05VCiAqIExlc3NlciBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuCiAqCiAqIFlvdSBzaG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBMZXNzZXIgR2VuZXJhbCBQdWJsaWMKICogTGljZW5zZSBhbG9uZyB3aXRoIHRoaXMgbGlicmFyeTsgaWYgbm90LCB3cml0ZSB0byB0aGUgRnJlZSBTb2Z0d2FyZQogKiBGb3VuZGF0aW9uLCBJbmMuLCA1MSBGcmFua2xpbiBTdCwgRmlmdGggRmxvb3IsIEJvc3RvbiwgTUEgMDIxMTAtMTMwMSwgVVNBCiAqLwoKI2luY2x1ZGUgPHN0ZGFyZy5oPgojaW5jbHVkZSA8c3RkbGliLmg+CiNpbmNsdWRlIDxzdHJpbmcuaD4KCiNpbmNsdWRlICJ3aW5kZWYuaCIKI2luY2x1ZGUgIndpbmJhc2UuaCIKI2luY2x1ZGUgIndpbmdkaS5oIgojaW5jbHVkZSAid2ludXNlci5oIgojaW5jbHVkZSAid2luZS9kZWJ1Zy5oIgojaW5jbHVkZSAiZG9zZXhlLmgiCgpXSU5FX0RFRkFVTFRfREVCVUdfQ0hBTk5FTChpbnQpOwoKI2RlZmluZSBRVUVVRUxFTiAzMQoKc3RhdGljIHN0cnVjdAp7CiAgQllURSBxdWV1ZWxlbixxdWV1ZVtRVUVVRUxFTl0sYXNjaWlbUVVFVUVMRU5dOwp9IGtiZGluZm87CgoKLyoKICogVXBkYXRlIHRoZSBCSU9TIGRhdGEgc2VnbWVudCdzIGtleWJvYXJkIHN0YXR1cyBmbGFncyAobWVtIDB4NDA6MHgxNy8weDE4KQogKiBpZiBtb2RpZmllci9zcGVjaWFsIGtleXMgaGF2ZSBiZWVuIHByZXNzZWQuCiAqIEZJWE1FOiB3ZSBtZXJlbHkgdG9nZ2xlIGtleSBzdGF0dXMgYW5kIGRvbid0IGFjdGl2ZWx5IHNldCBpdCBpbnN0ZWFkLAogKiBzbyB3ZSBtaWdodCBiZSBvdXQgb2Ygc3luYyB3aXRoIHRoZSByZWFsIGN1cnJlbnQgc3lzdGVtIHN0YXR1cyBvZiB0aGVzZSBrZXlzLgogKiBQcm9iYWJseSBkb2Vzbid0IG1hdHRlciB0b28gbXVjaCwgdGhvdWdoLgogKi8Kc3RhdGljIHZvaWQgRE9TVk1fSW50MDlVcGRhdGVLYmRTdGF0dXNGbGFncyhCWVRFIHNjYW4sIEJPT0wgZXh0ZW5kZWQsIEJJT1NEQVRBICpkYXRhLCBCT09MICptb2RpZmllcikKewogICAgQllURSByZWFsc2NhbiA9IHNjYW4gJiAweDdmOyAvKiByZW1vdmUgMHg4MCBtYWtlL2JyZWFrIGZsYWcgKi8KICAgIEJZVEUgYml0MSA9IDI1NSwgYml0MiA9IDI1NTsKICAgIElOUFVUX1JFQ09SRCBtc2c7CiAgICBEV09SRCByZXM7CgogICAgKm1vZGlmaWVyID0gVFJVRTsKCiAgICBzd2l0Y2ggKHJlYWxzY2FuKQogICAgewogICAgICBjYXNlIDB4MzY6IC8qIHIgc2hpZnQgKi8KCSAgICAgIGJpdDEgPSAwOwoJICAgICAgYnJlYWs7CiAgICAgIGNhc2UgMHgyYTogLyogbCBzaGlmdCAqLwoJICAgICAgYml0MSA9IDE7CgkgICAgICBicmVhazsKICAgICAgY2FzZSAweDFkOiAvKiBsL3IgY29udHJvbCAqLwoJICAgICAgYml0MSA9IDI7CgkgICAgICBpZiAoIWV4dGVuZGVkKSAvKiBsZWZ0IGNvbnRyb2wgb25seSAqLwoJCSAgYml0MiA9IDA7CgkgICAgICBicmVhazsKICAgICAgY2FzZSAweDM3OiAvKiBTeXNScSBpbm5lciBwYXJ0cyAqLwoJICAgICAgLyogU3lzUnEgc2NhbiBjb2RlIHNlcXVlbmNlOiAzOCwgZTAsIDM3LCBlMCwgYjcsIGI4ICovCgkgICAgICBGSVhNRSgiU3lzUnEgbm90IGhhbmRsZWQgeWV0LlxuIik7CgkgICAgICBicmVhazsKICAgICAgY2FzZSAweDM4OiAvKiBsL3IgbWVudS9hbHQsIFN5c1JxIG91dGVyIHBhcnRzICovCgkgICAgICBiaXQxID0gMzsKCSAgICAgIGlmICghZXh0ZW5kZWQpIC8qIGxlZnQgYWx0IG9ubHkgKi8KCSAgICAgICAgICBiaXQyID0gMTsKCSAgICAgIGJyZWFrOwogICAgICBjYXNlIDB4NDY6IC8qIHNjcm9sbCBsb2NrICovCgkgICAgICBiaXQxID0gNDsKCSAgICAgIGlmICghZXh0ZW5kZWQpIC8qIGxlZnQgY3RybCBvbmx5ICovCgkgICAgICAgICAgYml0MiA9IDQ7CgkgICAgICBicmVhazsKICAgICAgY2FzZSAweDQ1OiAvKiBudW0gbG9jaywgcGF1c2UgKi8KCSAgICAgIGlmIChleHRlbmRlZCkgLyogZGlzdGluZ3Vpc2ggZnJvbSBub24tZXh0ZW5kZWQgUGF1c2Uga2V5ICovCiAgICAgICAgICAgICAgeyAvKiBudW0gbG9jayAqLwoJICAgICAgICAgIGJpdDEgPSA1OwoJICAgICAgICAgIGJpdDIgPSA1OwogICAgICAgICAgICAgIH0KCSAgICAgIGVsc2UKICAgICAgICAgICAgICB7IC8qIHBhdXNlICovCiAgICAgICAgICAgICAgICAgIGlmICghKHNjYW4gJiAweDgwKSkgLyogIm1ha2UiIGNvZGUgKi8KICAgICAgICAgICAgICAgICAgICAgIGJpdDIgPSAzOwogICAgICAgICAgICAgIH0KCSAgICAgIGJyZWFrOwogICAgICBjYXNlIDB4M2E6IC8qIGNhcHMgbG9jayAqLwoJICAgICAgYml0MSA9IDY7CgkgICAgICBiaXQyID0gNjsKCSAgICAgIGJyZWFrOwogICAgICBjYXNlIDB4NTI6IC8qIGluc2VydCAqLwoJICAgICAgYml0MSA9IDc7CgkgICAgICBiaXQyID0gNzsKCSAgICAgICptb2RpZmllciA9IEZBTFNFOyAvKiBpbnNlcnQgaXMgbm8gbW9kaWZpZXI6IHRodXMgcGFzcyB0byBpbnQxNiAqLwoJICAgICAgYnJlYWs7CiAgICB9CiAgICAvKiBub3cgdGhhdCB3ZSBrbm93IHdoaWNoIGJpdHMgdG8gc2V0LCB1cGRhdGUgdGhlbSAqLwogICAgaWYgKCEoc2NhbiAmIDB4ODApKSAvKiAibWFrZSIgY29kZSAoa2V5cHJlc3MpICovCiAgICB7CiAgICAgICAgaWYgKGJpdDIgIT0gMjU1KQogICAgICAgIHsKCSAgICBpZiAoYml0MiA9PSAzKQoJICAgIHsKICAgICAgICAgICAgICAgIGRhdGEtPktiZEZsYWdzMiB8PSAxIDw8IGJpdDI7IC8qIHNldCAiUGF1c2UiIGZsYWcgKi8KICAgICAgICAgICAgICAgIFRSQUNFKCJQQVVTRSBrZXksIHNsZWVwaW5nICFcbiIpOwogICAgICAgICAgICAgICAgLyogd2FpdCBmb3Iga2V5cHJlc3MgdG8gdW5sb2NrIHBhdXNlICovCgkJZG8gewogICAgICAgICAgICAgICAgICAgIFNsZWVwKDU1KTsKCQl9IHdoaWxlICghKFJlYWRDb25zb2xlSW5wdXRBKEdldFN0ZEhhbmRsZShTVERfSU5QVVRfSEFORExFKSwmbXNnLDEsJnJlcykgJiYgKG1zZy5FdmVudFR5cGUgPT0gS0VZX0VWRU5UKSkpOwogICAgICAgICAgICAgICAgZGF0YS0+S2JkRmxhZ3MyICY9IH4oMSA8PCBiaXQyKTsgLyogcmVsZWFzZSAiUGF1c2UiIGZsYWcgKi8KICAgICAgICAgICAgfQoJICAgIGVsc2UKICAgICAgICAgICAgICAgIGRhdGEtPktiZEZsYWdzMiB8PSAxIDw8IGJpdDI7CiAgICAgICAgfQogICAgICAgIGlmIChiaXQxICE9IDI1NSkKICAgICAgICB7CiAgICAgICAgICAgIGlmIChiaXQxIDwgNCkgLyoga2V5ICJwcmVzc2VkIiBmbGFnICovCgkgICAgICAgIGRhdGEtPktiZEZsYWdzMSB8PSAxIDw8IGJpdDE7CiAgICAgICAgICAgIGVsc2UgLyoga2V5ICJhY3RpdmUiIGZsYWcgKi8KICAgICAgICAgICAgICAgIGRhdGEtPktiZEZsYWdzMSBePSAxIDw8IGJpdDE7CiAgICAgICAgfQogICAgfQogICAgZWxzZSAvKiAiYnJlYWsiIC8gcmVsZWFzZSAqLwogICAgewogICAgICAgIGlmIChiaXQyICE9IDI1NSkKICAgICAgICAgICAgZGF0YS0+S2JkRmxhZ3MyICY9IH4oMSA8PCBiaXQyKTsKICAgICAgICBpZiAoYml0MSA8IDQpIC8qIGlzIGl0IGEga2V5ICJwcmVzc2VkIiBiaXQgPyAqLwoJICAgIGRhdGEtPktiZEZsYWdzMSAmPSB+KDEgPDwgYml0MSk7CiAgICB9CiAgICBUUkFDRSgiZXh0LiAlZCwgYml0cyAlZC8lZCwgS2JkRmxhZ3MgJTAyeC8lMDJ4XG4iLCBleHRlbmRlZCwgYml0MSwgYml0MiwgZGF0YS0+S2JkRmxhZ3MxLCBkYXRhLT5LYmRGbGFnczIpOwp9CgovKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKgogKgkgICAgRE9TVk1fSW50MDlIYW5kbGVyIChXSU5FRE9TMTYuMTA5KQogKgogKiBIYW5kbGVyIGZvciBpbnQgMDloLgogKiBTZWUgaHR0cDovL3d3dy5leGVjcGMuY29tL35nZWV6ZXIvb3NkL2tiZC8gZm9yIGEgdmVyeSBnb29kIGRlc2NyaXB0aW9uCiAqIG9mIGtleWJvYXJkIG1hcHBpbmcgbW9kZXMuCiAqLwp2b2lkIFdJTkFQSSBET1NWTV9JbnQwOUhhbmRsZXIoIENPTlRFWFQ4NiAqY29udGV4dCApCnsKICBCSU9TREFUQSAqZGF0YSA9IERPU1ZNX0Jpb3NEYXRhKCk7CiAgQllURSBhc2NpaSwgc2NhbiA9IERPU1ZNX0ludDA5UmVhZFNjYW4oJmFzY2lpKTsKICBCWVRFIHJlYWxzY2FuID0gc2NhbiAmIDB4N2Y7IC8qIHJlbW92ZSAweDgwIG1ha2UvYnJlYWsgZmxhZyAqLwogIEJPT0wgbW9kaWZpZXIgPSBGQUxTRTsKICBzdGF0aWMgQk9PTCBleHRlbmRlZCA9IEZBTFNFOyAvKiBpbmRpY2F0ZXMgc3RhcnQgb2YgZXh0ZW5kZWQga2V5IHNlcXVlbmNlICovCiAgQllURSBjaFsyXTsKICBpbnQgY250LCBjMjsKCiAgVFJBQ0UoInNjYW49JTAyeCwgYXNjaWk9JTAyeFslY11cbiIsc2NhbiwgYXNjaWksIGFzY2lpID8gYXNjaWkgOiAnICcpOwoKICBpZiAoc2NhbiA9PSAweGUwKSAvKiBleHRlbmRlZCBrZXljb2RlICovCiAgICAgIGV4dGVuZGVkID0gVFJVRTsKICAKICAvKiBjaGVjayBmb3Iga2V5cyBjb25jZXJuaW5nIGtleWJvYXJkIHN0YXR1cyBmbGFncyAqLwogIGlmICgocmVhbHNjYW4gPT0gMHg1MiAvKiBpbnNlcnQgKi8pCiAgfHwgIChyZWFsc2NhbiA9PSAweDNhIC8qIGNhcHMgbG9jayAqLykKICB8fCAgKHJlYWxzY2FuID09IDB4NDUgLyogbnVtIGxvY2sgKGV4dGVuZGVkKSBvciBwYXVzZS9icmVhayAqLykKICB8fCAgKHJlYWxzY2FuID09IDB4NDYgLyogc2Nyb2xsIGxvY2sgKi8pCiAgfHwgIChyZWFsc2NhbiA9PSAweDJhIC8qIGwgc2hpZnQgKi8pCiAgfHwgIChyZWFsc2NhbiA9PSAweDM2IC8qIHIgc2hpZnQgKi8pCiAgfHwgIChyZWFsc2NhbiA9PSAweDM3IC8qIFN5c1JxICovKQogIHx8ICAocmVhbHNjYW4gPT0gMHgzOCAvKiBsL3IgbWVudS9hbHQsIFN5c1JxICovKQogIHx8ICAocmVhbHNjYW4gPT0gMHgxZCAvKiBsL3IgY29udHJvbCAqLykpCiAgICAgIERPU1ZNX0ludDA5VXBkYXRlS2JkU3RhdHVzRmxhZ3Moc2NhbiwgZXh0ZW5kZWQsIGRhdGEsICZtb2RpZmllcik7CgogIGlmIChzY2FuICE9IDB4ZTApCiAgICAgIGV4dGVuZGVkID0gRkFMU0U7IC8qIHJlc2V0IGV4dGVuZGVkIGZsYWcgbm93ICovCgogIC8qIG9ubHkgaW50ZXJlc3RlZCBpbiAibWFrZSIgKHByZXNzKSBjb2Rlcywgbm90ICJicmVhayIgKHJlbGVhc2UpLAogICAqIGFuZCBhbHNvIG5vdCBpbiAibW9kaWZpZXIga2V5IG9ubHkiICh3L28gYXNjaWkpIG5vdGlmaWNhdGlvbnMgKi8KICBpZiAoIShzY2FuICYgMHg4MCkgJiYgIShtb2RpZmllciAmJiAhYXNjaWkpKQogIHsKICAgIGlmIChhc2NpaSkgewogICAgICAvKiB3ZSBhbHJlYWR5IGhhdmUgYW4gQVNDSUkgY29kZSwgbm8gdHJhbnNsYXRpb24gbmVjZXNzYXJ5ICovCiAgICAgIGlmIChkYXRhLT5LYmRGbGFnczEgJiA4KSAvKiBBbHQga2V5ID8gKi8KCWNoWzBdID0gMDsgLyogQVNDSUkgY29kZSBuZWVkcyB0byBiZSAwIGlmIEFsdCBhbHNvIHByZXNzZWQgKi8KICAgICAgZWxzZQogICAgICAgIGNoWzBdID0gYXNjaWk7CiAgICAgIC8qIEZJWE1FOiBuZWVkIHRvIGhhbmRsZSB0aGluZ3Mgc3VjaCBhcyBTaGlmdC1GMSBldGMuICovCiAgICAgIGNudCA9IDE7CiAgICB9IGVsc2UgewogICAgICAvKiB0cmFuc2xhdGUgKi8KICAgICAgVUlOVCB2a2V5ID0gTWFwVmlydHVhbEtleUEoc2NhbiYweDdmLCAxKTsKICAgICAgQllURSBrZXlzdGF0ZVsyNTZdOwogICAgICBHZXRLZXlib2FyZFN0YXRlKGtleXN0YXRlKTsKICAgICAgY250ID0gVG9Bc2NpaSh2a2V5LCBzY2FuLCBrZXlzdGF0ZSwgKExQV09SRCljaCwgMCk7CiAgICB9CiAgICBpZiAoY250PjApIHsKICAgICAgZm9yIChjMj0wOyBjMjxjbnQ7IGMyKyspCiAgICAgICAgRE9TVk1fSW50MTZBZGRDaGFyKGNoW2MyXSwgc2Nhbik7CiAgICB9IGVsc2UKICAgIGlmIChjbnQ9PTApIHsKICAgICAgLyogRklYTUU6IG5lZWQgdG8gaGFuZGxlIHRoaW5ncyBsaWtlIHNoaWZ0LUYta2V5cywKICAgICAgICogMHhFMCBleHRlbmRlZCBrZXlzLCBldGMgKi8KICAgICAgRE9TVk1fSW50MTZBZGRDaGFyKDAsIHNjYW4pOwogICAgfQogIH0KCiAgRE9TVk1fQWNrbm93bGVkZ2VJUlEoIGNvbnRleHQgKTsKfQoKc3RhdGljIHZvaWQgS2JkUmVsYXkoIENPTlRFWFQ4NiAqY29udGV4dCwgdm9pZCAqZGF0YSApCnsKICBpZiAoa2JkaW5mby5xdWV1ZWxlbikgewogICAgLyogY2xlYW51cCBvcGVyYXRpb24sIGNhbGxlZCBmcm9tIERPU1ZNX1BJQ19pb3BvcnRfb3V0OgogICAgICogd2UnbGwgcmVtb3ZlIGN1cnJlbnQgc2NhbmNvZGUgZnJvbSBrZXlib2FyZCBidWZmZXIgaGVyZSwKICAgICAqIHJhdGhlciB0aGFuIGluIFJlYWRTY2FuLCBiZWNhdXNlIHNvbWUgRE9TIGFwcHMgZGVwZW5kIG9uCiAgICAgKiB0aGUgc2NhbmNvZGUgYmVpbmcgYXZhaWxhYmxlIGZvciByZWFkaW5nIG11bHRpcGxlIHRpbWVzLi4uICovCiAgICBpZiAoLS1rYmRpbmZvLnF1ZXVlbGVuKSB7CiAgICAgIG1lbW1vdmUoa2JkaW5mby5xdWV1ZSxrYmRpbmZvLnF1ZXVlKzEsa2JkaW5mby5xdWV1ZWxlbik7CiAgICAgIG1lbW1vdmUoa2JkaW5mby5hc2NpaSxrYmRpbmZvLmFzY2lpKzEsa2JkaW5mby5xdWV1ZWxlbik7CiAgICB9CiAgfQp9Cgp2b2lkIFdJTkFQSSBET1NWTV9JbnQwOVNlbmRTY2FuKCBCWVRFIHNjYW4sIEJZVEUgYXNjaWkgKQp7CiAgaWYgKGtiZGluZm8ucXVldWVsZW4gPT0gUVVFVUVMRU4pIHsKICAgIEVSUigia2V5Ym9hcmQgcXVldWUgb3ZlcmZsb3dcbiIpOwogICAgcmV0dXJuOwogIH0KICAvKiBhZGQgc2NhbmNvZGUgdG8gcXVldWUgKi8KICBrYmRpbmZvLnF1ZXVlW2tiZGluZm8ucXVldWVsZW5dID0gc2NhbjsKICBrYmRpbmZvLmFzY2lpW2tiZGluZm8ucXVldWVsZW4rK10gPSBhc2NpaTsKICAvKiB0ZWxsIGFwcCB0byByZWFkIGl0IGJ5IHRyaWdnZXJpbmcgSVJRIDEgKGludCAwOSkgKi8KICBET1NWTV9RdWV1ZUV2ZW50KDEsRE9TX1BSSU9SSVRZX0tFWUJPQVJELEtiZFJlbGF5LE5VTEwpOwp9CgovKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKgogKgkgICAgS2JkUmVhZFNjYW4gKFdJTkVET1MuQCkKICovCkJZVEUgV0lOQVBJIERPU1ZNX0ludDA5UmVhZFNjYW4oIEJZVEUqYXNjaWkgKQp7CiAgICBpZiAoYXNjaWkpICphc2NpaSA9IGtiZGluZm8uYXNjaWlbMF07CiAgICByZXR1cm4ga2JkaW5mby5xdWV1ZVswXTsKfQo=