LyoKICogRE9TIGludGVycnVwdCAwOWggaGFuZGxlciAoSVJRMSAtIEtFWUJPQVJEKQogKgogKiBDb3B5cmlnaHQgMTk5OSBPdmUgS+V2ZW4KICoKICogVGhpcyBsaWJyYXJ5IGlzIGZyZWUgc29mdHdhcmU7IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vcgogKiBtb2RpZnkgaXQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgTGVzc2VyIEdlbmVyYWwgUHVibGljCiAqIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5IHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb247IGVpdGhlcgogKiB2ZXJzaW9uIDIuMSBvZiB0aGUgTGljZW5zZSwgb3IgKGF0IHlvdXIgb3B0aW9uKSBhbnkgbGF0ZXIgdmVyc2lvbi4KICoKICogVGhpcyBsaWJyYXJ5IGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsCiAqIGJ1dCBXSVRIT1VUIEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mCiAqIE1FUkNIQU5UQUJJTElUWSBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gIFNlZSB0aGUgR05VCiAqIExlc3NlciBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuCiAqCiAqIFlvdSBzaG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBMZXNzZXIgR2VuZXJhbCBQdWJsaWMKICogTGljZW5zZSBhbG9uZyB3aXRoIHRoaXMgbGlicmFyeTsgaWYgbm90LCB3cml0ZSB0byB0aGUgRnJlZSBTb2Z0d2FyZQogKiBGb3VuZGF0aW9uLCBJbmMuLCA1OSBUZW1wbGUgUGxhY2UsIFN1aXRlIDMzMCwgQm9zdG9uLCBNQSAgMDIxMTEtMTMwNyAgVVNBCiAqLwoKI2luY2x1ZGUgPHN0ZGFyZy5oPgojaW5jbHVkZSA8c3RkbGliLmg+CiNpbmNsdWRlIDxzdHJpbmcuaD4KCiNpbmNsdWRlICJ3aW5kZWYuaCIKI2luY2x1ZGUgIndpbmJhc2UuaCIKI2luY2x1ZGUgIndpbmdkaS5oIgojaW5jbHVkZSAid2ludXNlci5oIgojaW5jbHVkZSAid2luZS9kZWJ1Zy5oIgojaW5jbHVkZSAiZG9zZXhlLmgiCgpXSU5FX0RFRkFVTFRfREVCVUdfQ0hBTk5FTChpbnQpOwoKI2RlZmluZSBRVUVVRUxFTiAzMQoKc3RhdGljIHN0cnVjdAp7CiAgQllURSBxdWV1ZWxlbixxdWV1ZVtRVUVVRUxFTl0sYXNjaWlbUVVFVUVMRU5dOwp9IGtiZGluZm87CgoKLyoKICogVXBkYXRlIHRoZSBCSU9TIGRhdGEgc2VnbWVudCdzIGtleWJvYXJkIHN0YXR1cyBmbGFncyAobWVtIDB4NDA6MHgxNy8weDE4KQogKiBpZiBtb2RpZmllci9zcGVjaWFsIGtleXMgaGF2ZSBiZWVuIHByZXNzZWQuCiAqIEZJWE1FOiB3ZSBtZXJlbHkgdG9nZ2xlIGtleSBzdGF0dXMgYW5kIGRvbid0IGFjdGl2ZWx5IHNldCBpdCBpbnN0ZWFkLAogKiBzbyB3ZSBtaWdodCBiZSBvdXQgb2Ygc3luYyB3aXRoIHRoZSByZWFsIGN1cnJlbnQgc3lzdGVtIHN0YXR1cyBvZiB0aGVzZSBrZXlzLgogKiBQcm9iYWJseSBkb2Vzbid0IG1hdHRlciB0b28gbXVjaCwgdGhvdWdoLgogKi8Kdm9pZCBET1NWTV9JbnQwOVVwZGF0ZUtiZFN0YXR1c0ZsYWdzKEJZVEUgc2NhbiwgQk9PTCBleHRlbmRlZCwgQklPU0RBVEEgKmRhdGEsIEJPT0wgKm1vZGlmaWVyKQp7CiAgICBCWVRFIHJlYWxzY2FuID0gc2NhbiAmIDB4N2Y7IC8qIHJlbW92ZSAweDgwIG1ha2UvYnJlYWsgZmxhZyAqLwogICAgQllURSBiaXQxID0gMjU1LCBiaXQyID0gMjU1OwogICAgSU5QVVRfUkVDT1JEIG1zZzsKICAgIERXT1JEIHJlczsKCiAgICAqbW9kaWZpZXIgPSBUUlVFOwoKICAgIHN3aXRjaCAocmVhbHNjYW4pCiAgICB7CiAgICAgIGNhc2UgMHgzNjogLyogciBzaGlmdCAqLwoJICAgICAgYml0MSA9IDA7CgkgICAgICBicmVhazsKICAgICAgY2FzZSAweDJhOiAvKiBsIHNoaWZ0ICovCgkgICAgICBiaXQxID0gMTsKCSAgICAgIGJyZWFrOwogICAgICBjYXNlIDB4MWQ6IC8qIGwvciBjb250cm9sICovCgkgICAgICBiaXQxID0gMjsKCSAgICAgIGlmICghZXh0ZW5kZWQpIC8qIGxlZnQgY29udHJvbCBvbmx5ICovCgkJICBiaXQyID0gMDsKCSAgICAgIGJyZWFrOwogICAgICBjYXNlIDB4Mzc6IC8qIFN5c1JxIGlubmVyIHBhcnRzICovCgkgICAgICAvKiBTeXNScSBzY2FuIGNvZGUgc2VxdWVuY2U6IDM4LCBlMCwgMzcsIGUwLCBiNywgYjggKi8KCSAgICAgIEZJWE1FKCJTeXNScSBub3QgaGFuZGxlZCB5ZXQuXG4iKTsKCSAgICAgIGJyZWFrOwogICAgICBjYXNlIDB4Mzg6IC8qIGwvciBtZW51L2FsdCwgU3lzUnEgb3V0ZXIgcGFydHMgKi8KCSAgICAgIGJpdDEgPSAzOwoJICAgICAgaWYgKCFleHRlbmRlZCkgLyogbGVmdCBhbHQgb25seSAqLwoJICAgICAgICAgIGJpdDIgPSAxOwoJICAgICAgYnJlYWs7CiAgICAgIGNhc2UgMHg0NjogLyogc2Nyb2xsIGxvY2sgKi8KCSAgICAgIGJpdDEgPSA0OwoJICAgICAgaWYgKCFleHRlbmRlZCkgLyogbGVmdCBjdHJsIG9ubHkgKi8KCSAgICAgICAgICBiaXQyID0gNDsKCSAgICAgIGJyZWFrOwogICAgICBjYXNlIDB4NDU6IC8qIG51bSBsb2NrLCBwYXVzZSAqLwoJICAgICAgaWYgKGV4dGVuZGVkKSAvKiBkaXN0aW5ndWlzaCBmcm9tIG5vbi1leHRlbmRlZCBQYXVzZSBrZXkgKi8KICAgICAgICAgICAgICB7IC8qIG51bSBsb2NrICovCgkgICAgICAgICAgYml0MSA9IDU7CgkgICAgICAgICAgYml0MiA9IDU7CiAgICAgICAgICAgICAgfQoJICAgICAgZWxzZQogICAgICAgICAgICAgIHsgLyogcGF1c2UgKi8KICAgICAgICAgICAgICAgICAgaWYgKCEoc2NhbiAmIDB4ODApKSAvKiAibWFrZSIgY29kZSAqLwogICAgICAgICAgICAgICAgICAgICAgYml0MiA9IDM7CiAgICAgICAgICAgICAgfQoJICAgICAgYnJlYWs7CiAgICAgIGNhc2UgMHgzYTogLyogY2FwcyBsb2NrICovCgkgICAgICBiaXQxID0gNjsKCSAgICAgIGJpdDIgPSA2OwoJICAgICAgYnJlYWs7CiAgICAgIGNhc2UgMHg1MjogLyogaW5zZXJ0ICovCgkgICAgICBiaXQxID0gNzsKCSAgICAgIGJpdDIgPSA3OwoJICAgICAgKm1vZGlmaWVyID0gRkFMU0U7IC8qIGluc2VydCBpcyBubyBtb2RpZmllcjogdGh1cyBwYXNzIHRvIGludDE2ICovCgkgICAgICBicmVhazsKICAgIH0KICAgIC8qIG5vdyB0aGF0IHdlIGtub3cgd2hpY2ggYml0cyB0byBzZXQsIHVwZGF0ZSB0aGVtICovCiAgICBpZiAoIShzY2FuICYgMHg4MCkpIC8qICJtYWtlIiBjb2RlIChrZXlwcmVzcykgKi8KICAgIHsKICAgICAgICBpZiAoYml0MiAhPSAyNTUpCiAgICAgICAgewoJICAgIGlmIChiaXQyID09IDMpCgkgICAgewogICAgICAgICAgICAgICAgZGF0YS0+S2JkRmxhZ3MyIHw9IDEgPDwgYml0MjsgLyogc2V0ICJQYXVzZSIgZmxhZyAqLwogICAgICAgICAgICAgICAgVFJBQ0UoIlBBVVNFIGtleSwgc2xlZXBpbmcgIVxuIik7CiAgICAgICAgICAgICAgICAvKiB3YWl0IGZvciBrZXlwcmVzcyB0byB1bmxvY2sgcGF1c2UgKi8KCQlkbyB7CiAgICAgICAgICAgICAgICAgICAgU2xlZXAoNTUpOwoJCX0gd2hpbGUgKCEoUmVhZENvbnNvbGVJbnB1dEEoR2V0U3RkSGFuZGxlKFNURF9JTlBVVF9IQU5ETEUpLCZtc2csMSwmcmVzKSAmJiAobXNnLkV2ZW50VHlwZSA9PSBLRVlfRVZFTlQpKSk7CiAgICAgICAgICAgICAgICBkYXRhLT5LYmRGbGFnczIgJj0gfigxIDw8IGJpdDIpOyAvKiByZWxlYXNlICJQYXVzZSIgZmxhZyAqLwogICAgICAgICAgICB9CgkgICAgZWxzZQogICAgICAgICAgICAgICAgZGF0YS0+S2JkRmxhZ3MyIHw9IDEgPDwgYml0MjsKICAgICAgICB9CiAgICAgICAgaWYgKGJpdDEgIT0gMjU1KQogICAgICAgIHsKICAgICAgICAgICAgaWYgKGJpdDEgPCA0KSAvKiBrZXkgInByZXNzZWQiIGZsYWcgKi8KCSAgICAgICAgZGF0YS0+S2JkRmxhZ3MxIHw9IDEgPDwgYml0MTsKICAgICAgICAgICAgZWxzZSAvKiBrZXkgImFjdGl2ZSIgZmxhZyAqLwogICAgICAgICAgICAgICAgZGF0YS0+S2JkRmxhZ3MxIF49IDEgPDwgYml0MTsKICAgICAgICB9CiAgICB9CiAgICBlbHNlIC8qICJicmVhayIgLyByZWxlYXNlICovCiAgICB7CiAgICAgICAgaWYgKGJpdDIgIT0gMjU1KQogICAgICAgICAgICBkYXRhLT5LYmRGbGFnczIgJj0gfigxIDw8IGJpdDIpOwogICAgICAgIGlmIChiaXQxIDwgNCkgLyogaXMgaXQgYSBrZXkgInByZXNzZWQiIGJpdCA/ICovCgkgICAgZGF0YS0+S2JkRmxhZ3MxICY9IH4oMSA8PCBiaXQxKTsKICAgIH0KICAgIFRSQUNFKCJleHQuICVkLCBiaXRzICVkLyVkLCBLYmRGbGFncyAlMDJ4LyUwMnhcbiIsIGV4dGVuZGVkLCBiaXQxLCBiaXQyLCBkYXRhLT5LYmRGbGFnczEsIGRhdGEtPktiZEZsYWdzMik7Cn0KCi8qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqCiAqCSAgICBET1NWTV9JbnQwOUhhbmRsZXIgKFdJTkVET1MxNi4xMDkpCiAqCiAqIEhhbmRsZXIgZm9yIGludCAwOWguCiAqIFNlZSBodHRwOi8vd3d3LmV4ZWNwYy5jb20vfmdlZXplci9vc2Qva2JkLyBmb3IgYSB2ZXJ5IGdvb2QgZGVzY3JpcHRpb24KICogb2Yga2V5Ym9hcmQgbWFwcGluZyBtb2Rlcy4KICovCnZvaWQgV0lOQVBJIERPU1ZNX0ludDA5SGFuZGxlciggQ09OVEVYVDg2ICpjb250ZXh0ICkKewogIEJJT1NEQVRBICpkYXRhID0gRE9TVk1fQmlvc0RhdGEoKTsKICBCWVRFIGFzY2lpLCBzY2FuID0gRE9TVk1fSW50MDlSZWFkU2NhbigmYXNjaWkpOwogIEJZVEUgcmVhbHNjYW4gPSBzY2FuICYgMHg3ZjsgLyogcmVtb3ZlIDB4ODAgbWFrZS9icmVhayBmbGFnICovCiAgQk9PTCBtb2RpZmllciA9IEZBTFNFOwogIHN0YXRpYyBCT09MIGV4dGVuZGVkID0gRkFMU0U7IC8qIGluZGljYXRlcyBzdGFydCBvZiBleHRlbmRlZCBrZXkgc2VxdWVuY2UgKi8KICBCWVRFIGNoWzJdOwogIGludCBjbnQsIGMyOwoKICBUUkFDRSgic2Nhbj0lMDJ4LCBhc2NpaT0lMDJ4WyVjXVxuIixzY2FuLCBhc2NpaSwgYXNjaWkgPyBhc2NpaSA6ICcgJyk7CgogIGlmIChzY2FuID09IDB4ZTApIC8qIGV4dGVuZGVkIGtleWNvZGUgKi8KICAgICAgZXh0ZW5kZWQgPSBUUlVFOwogIAogIC8qIGNoZWNrIGZvciBrZXlzIGNvbmNlcm5pbmcga2V5Ym9hcmQgc3RhdHVzIGZsYWdzICovCiAgaWYgKChyZWFsc2NhbiA9PSAweDUyIC8qIGluc2VydCAqLykKICB8fCAgKHJlYWxzY2FuID09IDB4M2EgLyogY2FwcyBsb2NrICovKQogIHx8ICAocmVhbHNjYW4gPT0gMHg0NSAvKiBudW0gbG9jayAoZXh0ZW5kZWQpIG9yIHBhdXNlL2JyZWFrICovKQogIHx8ICAocmVhbHNjYW4gPT0gMHg0NiAvKiBzY3JvbGwgbG9jayAqLykKICB8fCAgKHJlYWxzY2FuID09IDB4MmEgLyogbCBzaGlmdCAqLykKICB8fCAgKHJlYWxzY2FuID09IDB4MzYgLyogciBzaGlmdCAqLykKICB8fCAgKHJlYWxzY2FuID09IDB4MzcgLyogU3lzUnEgKi8pCiAgfHwgIChyZWFsc2NhbiA9PSAweDM4IC8qIGwvciBtZW51L2FsdCwgU3lzUnEgKi8pCiAgfHwgIChyZWFsc2NhbiA9PSAweDFkIC8qIGwvciBjb250cm9sICovKSkKICAgICAgRE9TVk1fSW50MDlVcGRhdGVLYmRTdGF0dXNGbGFncyhzY2FuLCBleHRlbmRlZCwgZGF0YSwgJm1vZGlmaWVyKTsKCiAgaWYgKHNjYW4gIT0gMHhlMCkKICAgICAgZXh0ZW5kZWQgPSBGQUxTRTsgLyogcmVzZXQgZXh0ZW5kZWQgZmxhZyBub3cgKi8KCiAgLyogb25seSBpbnRlcmVzdGVkIGluICJtYWtlIiAocHJlc3MpIGNvZGVzLCBub3QgImJyZWFrIiAocmVsZWFzZSksCiAgICogYW5kIGFsc28gbm90IGluICJtb2RpZmllciBrZXkgb25seSIgKHcvbyBhc2NpaSkgbm90aWZpY2F0aW9ucyAqLwogIGlmICghKHNjYW4gJiAweDgwKSAmJiAhKG1vZGlmaWVyICYmICFhc2NpaSkpCiAgewogICAgaWYgKGFzY2lpKSB7CiAgICAgIC8qIHdlIGFscmVhZHkgaGF2ZSBhbiBBU0NJSSBjb2RlLCBubyB0cmFuc2xhdGlvbiBuZWNlc3NhcnkgKi8KICAgICAgaWYgKGRhdGEtPktiZEZsYWdzMSAmIDgpIC8qIEFsdCBrZXkgPyAqLwoJY2hbMF0gPSAwOyAvKiBBU0NJSSBjb2RlIG5lZWRzIHRvIGJlIDAgaWYgQWx0IGFsc28gcHJlc3NlZCAqLwogICAgICBlbHNlCiAgICAgICAgY2hbMF0gPSBhc2NpaTsKICAgICAgLyogRklYTUU6IG5lZWQgdG8gaGFuZGxlIHRoaW5ncyBzdWNoIGFzIFNoaWZ0LUYxIGV0Yy4gKi8KICAgICAgY250ID0gMTsKICAgIH0gZWxzZSB7CiAgICAgIC8qIHRyYW5zbGF0ZSAqLwogICAgICBVSU5UIHZrZXkgPSBNYXBWaXJ0dWFsS2V5QShzY2FuJjB4N2YsIDEpOwogICAgICBCWVRFIGtleXN0YXRlWzI1Nl07CiAgICAgIEdldEtleWJvYXJkU3RhdGUoa2V5c3RhdGUpOwogICAgICBjbnQgPSBUb0FzY2lpKHZrZXksIHNjYW4sIGtleXN0YXRlLCAoTFBXT1JEKWNoLCAwKTsKICAgIH0KICAgIGlmIChjbnQ+MCkgewogICAgICBmb3IgKGMyPTA7IGMyPGNudDsgYzIrKykKICAgICAgICBET1NWTV9JbnQxNkFkZENoYXIoY2hbYzJdLCBzY2FuKTsKICAgIH0gZWxzZQogICAgaWYgKGNudD09MCkgewogICAgICAvKiBGSVhNRTogbmVlZCB0byBoYW5kbGUgdGhpbmdzIGxpa2Ugc2hpZnQtRi1rZXlzLAogICAgICAgKiAweEUwIGV4dGVuZGVkIGtleXMsIGV0YyAqLwogICAgICBET1NWTV9JbnQxNkFkZENoYXIoMCwgc2Nhbik7CiAgICB9CiAgfQoKICBET1NWTV9BY2tub3dsZWRnZUlSUSggY29udGV4dCApOwp9CgpzdGF0aWMgdm9pZCBLYmRSZWxheSggQ09OVEVYVDg2ICpjb250ZXh0LCB2b2lkICpkYXRhICkKewogIGlmIChrYmRpbmZvLnF1ZXVlbGVuKSB7CiAgICAvKiBjbGVhbnVwIG9wZXJhdGlvbiwgY2FsbGVkIGZyb20gRE9TVk1fUElDX2lvcG9ydF9vdXQ6CiAgICAgKiB3ZSdsbCByZW1vdmUgY3VycmVudCBzY2FuY29kZSBmcm9tIGtleWJvYXJkIGJ1ZmZlciBoZXJlLAogICAgICogcmF0aGVyIHRoYW4gaW4gUmVhZFNjYW4sIGJlY2F1c2Ugc29tZSBET1MgYXBwcyBkZXBlbmQgb24KICAgICAqIHRoZSBzY2FuY29kZSBiZWluZyBhdmFpbGFibGUgZm9yIHJlYWRpbmcgbXVsdGlwbGUgdGltZXMuLi4gKi8KICAgIGlmICgtLWtiZGluZm8ucXVldWVsZW4pIHsKICAgICAgbWVtbW92ZShrYmRpbmZvLnF1ZXVlLGtiZGluZm8ucXVldWUrMSxrYmRpbmZvLnF1ZXVlbGVuKTsKICAgICAgbWVtbW92ZShrYmRpbmZvLmFzY2lpLGtiZGluZm8uYXNjaWkrMSxrYmRpbmZvLnF1ZXVlbGVuKTsKICAgIH0KICB9Cn0KCnZvaWQgV0lOQVBJIERPU1ZNX0ludDA5U2VuZFNjYW4oIEJZVEUgc2NhbiwgQllURSBhc2NpaSApCnsKICBpZiAoa2JkaW5mby5xdWV1ZWxlbiA9PSBRVUVVRUxFTikgewogICAgRVJSKCJrZXlib2FyZCBxdWV1ZSBvdmVyZmxvd1xuIik7CiAgICByZXR1cm47CiAgfQogIC8qIGFkZCBzY2FuY29kZSB0byBxdWV1ZSAqLwogIGtiZGluZm8ucXVldWVba2JkaW5mby5xdWV1ZWxlbl0gPSBzY2FuOwogIGtiZGluZm8uYXNjaWlba2JkaW5mby5xdWV1ZWxlbisrXSA9IGFzY2lpOwogIC8qIHRlbGwgYXBwIHRvIHJlYWQgaXQgYnkgdHJpZ2dlcmluZyBJUlEgMSAoaW50IDA5KSAqLwogIERPU1ZNX1F1ZXVlRXZlbnQoMSxET1NfUFJJT1JJVFlfS0VZQk9BUkQsS2JkUmVsYXksTlVMTCk7Cn0KCi8qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqCiAqCSAgICBLYmRSZWFkU2NhbiAoV0lORURPUy5AKQogKi8KQllURSBXSU5BUEkgRE9TVk1fSW50MDlSZWFkU2NhbiggQllURSphc2NpaSApCnsKICAgIGlmIChhc2NpaSkgKmFzY2lpID0ga2JkaW5mby5hc2NpaVswXTsKICAgIHJldHVybiBrYmRpbmZvLnF1ZXVlWzBdOwp9Cg==