From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 36916C433F5 for ; Mon, 27 Sep 2021 07:55:59 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 16C5560F70 for ; Mon, 27 Sep 2021 07:55:59 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233354AbhI0H5f (ORCPT ); Mon, 27 Sep 2021 03:57:35 -0400 Received: from mail-ed1-f43.google.com ([209.85.208.43]:41959 "EHLO mail-ed1-f43.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233248AbhI0H5f (ORCPT ); Mon, 27 Sep 2021 03:57:35 -0400 Received: by mail-ed1-f43.google.com with SMTP id s17so46925381edd.8 for ; Mon, 27 Sep 2021 00:55:57 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:subject:to:cc:references:from:message-id:date :user-agent:mime-version:in-reply-to:content-language :content-transfer-encoding; bh=CEfyV3bO4REPvQLYiyX7K5tvvC78lPlojdNMt9eiWt8=; b=qIW/bGunvtGpTgNXP/kFkiAxaXj9pcKI8jgI3uyFfzB7CIEfz+ZqpX29DGWAFmY96s qaXcPyjS6G7/Z/WZJur1moiUfoVDUrnTKv2WMbX6gfiM3stiD2jf7GI6WKBTaMZnIK6g AAE0H414HoBun1Dxyfs8FcktDJDSJTnzcS5zIJQfrnIxk8sSWbKLO4RRkSwxM8rMdPFI B9KHyyv0hJm+Oh4AR6gxN62bF7Gb7fWCSsLXy3KntbXZvMM9VA+qiB5nj8CPhUzABUjP l+4BGxUw6ZvNJvpmd/yFf1kVkB03OHMs1+Isfcdly0rI3KGj6zQzFgkD2zzJauZbKow7 Ot6Q== X-Gm-Message-State: AOAM531mrI0ddT3IiblwY1KbGQKp8u0fEiSxJuzpucpyDXFz7fQ4GxRY R55EgriTnpytuK4pb0Fs3iJ34AHK22w= X-Google-Smtp-Source: ABdhPJx2hY5NCWmUhNrON4GRHig9d7ViASTdB3IxTNx61QXk86vkU8zOWZx9Y6CgaXdG0IPV0CyY5A== X-Received: by 2002:a17:906:9401:: with SMTP id q1mr26000067ejx.313.1632729356447; Mon, 27 Sep 2021 00:55:56 -0700 (PDT) Received: from [10.100.102.14] (109-186-240-23.bb.netvision.net.il. [109.186.240.23]) by smtp.gmail.com with ESMTPSA id q18sm8370620ejc.84.2021.09.27.00.55.55 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Mon, 27 Sep 2021 00:55:56 -0700 (PDT) Subject: Re: [PATCH 10/12] nvmet: Implement basic In-Band Authentication To: Hannes Reinecke , Christoph Hellwig Cc: Keith Busch , Herbert Xu , "David S . Miller" , linux-nvme@lists.infradead.org, linux-crypto@vger.kernel.org References: <20210910064322.67705-1-hare@suse.de> <20210910064322.67705-11-hare@suse.de> <79742bd7-a41c-0abc-e7de-8d222b146d02@grimberg.me> From: Sagi Grimberg Message-ID: <32d8f860-9fdb-606c-62b7-ad89837d8e71@grimberg.me> Date: Mon, 27 Sep 2021 10:55:54 +0300 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Thunderbird/78.13.0 MIME-Version: 1.0 In-Reply-To: Content-Type: text/plain; charset=utf-8; format=flowed Content-Language: en-US Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: linux-crypto@vger.kernel.org On 9/27/21 10:17 AM, Hannes Reinecke wrote: > On 9/27/21 8:40 AM, Hannes Reinecke wrote: >> On 9/27/21 12:51 AM, Sagi Grimberg wrote: >>> >>>> +void nvmet_execute_auth_send(struct nvmet_req *req) >>>> +{ >>>> +    struct nvmet_ctrl *ctrl = req->sq->ctrl; >>>> +    struct nvmf_auth_dhchap_success2_data *data; >>>> +    void *d; >>>> +    u32 tl; >>>> +    u16 status = 0; >>>> + >>>> +    if (req->cmd->auth_send.secp != >>>> NVME_AUTH_DHCHAP_PROTOCOL_IDENTIFIER) { >>>> +        status = NVME_SC_INVALID_FIELD | NVME_SC_DNR; >>>> +        req->error_loc = >>>> +            offsetof(struct nvmf_auth_send_command, secp); >>>> +        goto done; >>>> +    } >>>> +    if (req->cmd->auth_send.spsp0 != 0x01) { >>>> +        status = NVME_SC_INVALID_FIELD | NVME_SC_DNR; >>>> +        req->error_loc = >>>> +            offsetof(struct nvmf_auth_send_command, spsp0); >>>> +        goto done; >>>> +    } >>>> +    if (req->cmd->auth_send.spsp1 != 0x01) { >>>> +        status = NVME_SC_INVALID_FIELD | NVME_SC_DNR; >>>> +        req->error_loc = >>>> +            offsetof(struct nvmf_auth_send_command, spsp1); >>>> +        goto done; >>>> +    } >>>> +    tl = le32_to_cpu(req->cmd->auth_send.tl); >>>> +    if (!tl) { >>>> +        status = NVME_SC_INVALID_FIELD | NVME_SC_DNR; >>>> +        req->error_loc = >>>> +            offsetof(struct nvmf_auth_send_command, tl); >>>> +        goto done; >>>> +    } >>>> +    if (!nvmet_check_transfer_len(req, tl)) { >>>> +        pr_debug("%s: transfer length mismatch (%u)\n", __func__, tl); >>>> +        return; >>>> +    } >>>> + >>>> +    d = kmalloc(tl, GFP_KERNEL); >>>> +    if (!d) { >>>> +        status = NVME_SC_INTERNAL; >>>> +        goto done; >>>> +    } >>>> + >>>> +    status = nvmet_copy_from_sgl(req, 0, d, tl); >>>> +    if (status) { >>>> +        kfree(d); >>>> +        goto done; >>>> +    } >>>> + >>>> +    data = d; >>>> +    pr_debug("%s: ctrl %d qid %d type %d id %d step %x\n", __func__, >>>> +         ctrl->cntlid, req->sq->qid, data->auth_type, data->auth_id, >>>> +         req->sq->dhchap_step); >>>> +    if (data->auth_type != NVME_AUTH_COMMON_MESSAGES && >>>> +        data->auth_type != NVME_AUTH_DHCHAP_MESSAGES) >>>> +        goto done_failure1; >>>> +    if (data->auth_type == NVME_AUTH_COMMON_MESSAGES) { >>>> +        if (data->auth_id == NVME_AUTH_DHCHAP_MESSAGE_NEGOTIATE) { >>>> +            /* Restart negotiation */ >>>> +            pr_debug("%s: ctrl %d qid %d reset negotiation\n", >>>> __func__, >>>> +                 ctrl->cntlid, req->sq->qid); >>> >>> This is the point where you need to reset also auth config as this may >>> have changed and the host will not create a new controller but rather >>> re-authenticate on the existing controller. >>> >>> i.e. >>> >>> +                       if (!req->sq->qid) { >>> +                               nvmet_destroy_auth(ctrl); >>> +                               if (nvmet_setup_auth(ctrl) < 0) { >>> +                                       pr_err("Failed to setup >>> re-authentication\n"); >>> +                                       goto done_failure1; >>> +                               } >>> +                       } >>> >>> >>> >> >> Not sure. We have two paths how re-authentication can be triggered. >> The one is from the host, which sends a 'negotiate' command to the >> controller (ie this path).  Then nothing on the controller has >> changed, and we just need to ensure that we restart negotiation. >> IE we should _not_ reset the authentication (as that would also remove >> the controller keys, which haven't changed). We should just ensure >> that all ephemeral data is regenerated. But that should be handled >> in-line, and I _think_ I have covered all of that. >> The other path to trigger re-authentication is when changing values on >> the controller via configfs. Then sure we need to reset the controller >> data, and trigger reauthentication. >> And there I do agree, that path isn't fully implemented / tested. >> But should be started whenever the configfs values change. >> > Actually, having re-read the spec I'm not sure if the second path is > correct. > As per spec only the _host_ can trigger re-authentication. There is no > provision for the controller to trigger re-authentication, and given > that re-auth is a soft-state anyway (ie the current authentication stays > valid until re-auth enters a final state) I _think_ we should be good > with the current implementation, where we can change the controller keys > via configfs, but they will only become active once the host triggers > re-authentication. Agree, so the proposed addition is good with you? > And indeed, that's the only way how it could work, otherwise it'll be > tricky to change keys in a running connection. > If we were to force renegotiation when changing controller keys we would > immediately fail the connection, as we cannot guarantee that controller > _and_ host keys are changed at the same time. Exactly, changing the hostkey in the controller must not trigger re-auth, the host will remain connected and operational as it authenticated before. As the host re-authenticates or reconnect it needs to authenticate against the new key. From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 9FB0AC433F5 for ; Mon, 27 Sep 2021 07:56:15 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 5937D60F6D for ; Mon, 27 Sep 2021 07:56:15 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org 5937D60F6D Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=grimberg.me Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:Content-Type: Content-Transfer-Encoding:List-Subscribe:List-Help:List-Post:List-Archive: List-Unsubscribe:List-Id:In-Reply-To:MIME-Version:Date:Message-ID:From: References:Cc:To:Subject:Reply-To:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=OLLChpqqUL4DUe+kVdovSRb7gJorYraT35etiUoQp44=; b=PN9QBxyINwYg91lqkoO9BXCnsa w2a0AmYRpFo8OcKmGD9h4Ra/wOnsESglpDPp2tvGDrDjb1EPsgoUscoquFWPB38s749KxlWmaQjKn SMSRF4MJ5tNA611h+6quZYuIrW0de+OWXj9RaxuWrn0aMcGY3zwW14xMQFejMfvCaUVHFq17z+NG3 gEroUjJIP3/Rp0VjU53Y5wJYmA2L9G6Q91MvuENwWRnAjHgZZ/cieG+tOmO0hjOztvUlbrzvPdMCL l/4RcmP03u4YvTMx+9I2xHRgj6nubK4vbtZPQ2WPXKAP5gRQ9IeeuVreQXYoklyJUWqMz2Vj4Ij5o 7lVIJurw==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1mUlUX-001ssj-PB; Mon, 27 Sep 2021 07:56:01 +0000 Received: from mail-ed1-f46.google.com ([209.85.208.46]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1mUlUU-001srq-FY for linux-nvme@lists.infradead.org; Mon, 27 Sep 2021 07:56:00 +0000 Received: by mail-ed1-f46.google.com with SMTP id dj4so65756400edb.5 for ; Mon, 27 Sep 2021 00:55:57 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:subject:to:cc:references:from:message-id:date :user-agent:mime-version:in-reply-to:content-language :content-transfer-encoding; bh=CEfyV3bO4REPvQLYiyX7K5tvvC78lPlojdNMt9eiWt8=; b=ytNU6mapANINU0YJtAahWjXUKSERRECFLveZ+OCn2ySMUWZUzaPDBoOU0JqHnf44F8 ZWPxEGxNOMOe78TcrhONHaf2GIC4eB9qt27WWH2rbviJEBppDbd8NAaKRL5ZFaYG2kpG OA5SgRVRuQC+m+Pvz6UmyP8ga5ymWZqYomzmSjeKjfK3kzzGVelDcvpvDMadW9HrDXEf lf3pnCrGrmmjz+NLtXHRJEgm7uh5L84LQcnObIC3fh/uvatoXw3yknizcs9o1zWvuswS p9zzBd2ZtbWyOS4WknJ2sOZnlQbr3ZFdTKGlQJIrziu5Vn499JmjM73LYaJIGM5VTwo2 KdOw== X-Gm-Message-State: AOAM533+f9a0Mn6ipwY5/xg2aj1rR5mudHhCRR1RqX5X7wPRN3bPoWkv 18Gy4BspJ+VX0myMatn4ZHk= X-Google-Smtp-Source: ABdhPJx2hY5NCWmUhNrON4GRHig9d7ViASTdB3IxTNx61QXk86vkU8zOWZx9Y6CgaXdG0IPV0CyY5A== X-Received: by 2002:a17:906:9401:: with SMTP id q1mr26000067ejx.313.1632729356447; Mon, 27 Sep 2021 00:55:56 -0700 (PDT) Received: from [10.100.102.14] (109-186-240-23.bb.netvision.net.il. [109.186.240.23]) by smtp.gmail.com with ESMTPSA id q18sm8370620ejc.84.2021.09.27.00.55.55 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Mon, 27 Sep 2021 00:55:56 -0700 (PDT) Subject: Re: [PATCH 10/12] nvmet: Implement basic In-Band Authentication To: Hannes Reinecke , Christoph Hellwig Cc: Keith Busch , Herbert Xu , "David S . Miller" , linux-nvme@lists.infradead.org, linux-crypto@vger.kernel.org References: <20210910064322.67705-1-hare@suse.de> <20210910064322.67705-11-hare@suse.de> <79742bd7-a41c-0abc-e7de-8d222b146d02@grimberg.me> From: Sagi Grimberg Message-ID: <32d8f860-9fdb-606c-62b7-ad89837d8e71@grimberg.me> Date: Mon, 27 Sep 2021 10:55:54 +0300 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Thunderbird/78.13.0 MIME-Version: 1.0 In-Reply-To: Content-Language: en-US X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20210927_005558_551915_ABB9AC32 X-CRM114-Status: GOOD ( 31.39 ) X-BeenThere: linux-nvme@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Content-Transfer-Encoding: base64 Content-Type: text/plain; charset="utf-8"; Format="flowed" Sender: "Linux-nvme" Errors-To: linux-nvme-bounces+linux-nvme=archiver.kernel.org@lists.infradead.org CgpPbiA5LzI3LzIxIDEwOjE3IEFNLCBIYW5uZXMgUmVpbmVja2Ugd3JvdGU6Cj4gT24gOS8yNy8y MSA4OjQwIEFNLCBIYW5uZXMgUmVpbmVja2Ugd3JvdGU6Cj4+IE9uIDkvMjcvMjEgMTI6NTEgQU0s IFNhZ2kgR3JpbWJlcmcgd3JvdGU6Cj4+Pgo+Pj4+ICt2b2lkIG52bWV0X2V4ZWN1dGVfYXV0aF9z ZW5kKHN0cnVjdCBudm1ldF9yZXEgKnJlcSkKPj4+PiArewo+Pj4+ICvCoMKgwqAgc3RydWN0IG52 bWV0X2N0cmwgKmN0cmwgPSByZXEtPnNxLT5jdHJsOwo+Pj4+ICvCoMKgwqAgc3RydWN0IG52bWZf YXV0aF9kaGNoYXBfc3VjY2VzczJfZGF0YSAqZGF0YTsKPj4+PiArwqDCoMKgIHZvaWQgKmQ7Cj4+ Pj4gK8KgwqDCoCB1MzIgdGw7Cj4+Pj4gK8KgwqDCoCB1MTYgc3RhdHVzID0gMDsKPj4+PiArCj4+ Pj4gK8KgwqDCoCBpZiAocmVxLT5jbWQtPmF1dGhfc2VuZC5zZWNwICE9IAo+Pj4+IE5WTUVfQVVU SF9ESENIQVBfUFJPVE9DT0xfSURFTlRJRklFUikgewo+Pj4+ICvCoMKgwqDCoMKgwqDCoCBzdGF0 dXMgPSBOVk1FX1NDX0lOVkFMSURfRklFTEQgfCBOVk1FX1NDX0ROUjsKPj4+PiArwqDCoMKgwqDC oMKgwqAgcmVxLT5lcnJvcl9sb2MgPQo+Pj4+ICvCoMKgwqDCoMKgwqDCoMKgwqDCoMKgIG9mZnNl dG9mKHN0cnVjdCBudm1mX2F1dGhfc2VuZF9jb21tYW5kLCBzZWNwKTsKPj4+PiArwqDCoMKgwqDC oMKgwqAgZ290byBkb25lOwo+Pj4+ICvCoMKgwqAgfQo+Pj4+ICvCoMKgwqAgaWYgKHJlcS0+Y21k LT5hdXRoX3NlbmQuc3BzcDAgIT0gMHgwMSkgewo+Pj4+ICvCoMKgwqDCoMKgwqDCoCBzdGF0dXMg PSBOVk1FX1NDX0lOVkFMSURfRklFTEQgfCBOVk1FX1NDX0ROUjsKPj4+PiArwqDCoMKgwqDCoMKg wqAgcmVxLT5lcnJvcl9sb2MgPQo+Pj4+ICvCoMKgwqDCoMKgwqDCoMKgwqDCoMKgIG9mZnNldG9m KHN0cnVjdCBudm1mX2F1dGhfc2VuZF9jb21tYW5kLCBzcHNwMCk7Cj4+Pj4gK8KgwqDCoMKgwqDC oMKgIGdvdG8gZG9uZTsKPj4+PiArwqDCoMKgIH0KPj4+PiArwqDCoMKgIGlmIChyZXEtPmNtZC0+ YXV0aF9zZW5kLnNwc3AxICE9IDB4MDEpIHsKPj4+PiArwqDCoMKgwqDCoMKgwqAgc3RhdHVzID0g TlZNRV9TQ19JTlZBTElEX0ZJRUxEIHwgTlZNRV9TQ19ETlI7Cj4+Pj4gK8KgwqDCoMKgwqDCoMKg IHJlcS0+ZXJyb3JfbG9jID0KPj4+PiArwqDCoMKgwqDCoMKgwqDCoMKgwqDCoCBvZmZzZXRvZihz dHJ1Y3QgbnZtZl9hdXRoX3NlbmRfY29tbWFuZCwgc3BzcDEpOwo+Pj4+ICvCoMKgwqDCoMKgwqDC oCBnb3RvIGRvbmU7Cj4+Pj4gK8KgwqDCoCB9Cj4+Pj4gK8KgwqDCoCB0bCA9IGxlMzJfdG9fY3B1 KHJlcS0+Y21kLT5hdXRoX3NlbmQudGwpOwo+Pj4+ICvCoMKgwqAgaWYgKCF0bCkgewo+Pj4+ICvC oMKgwqDCoMKgwqDCoCBzdGF0dXMgPSBOVk1FX1NDX0lOVkFMSURfRklFTEQgfCBOVk1FX1NDX0RO UjsKPj4+PiArwqDCoMKgwqDCoMKgwqAgcmVxLT5lcnJvcl9sb2MgPQo+Pj4+ICvCoMKgwqDCoMKg wqDCoMKgwqDCoMKgIG9mZnNldG9mKHN0cnVjdCBudm1mX2F1dGhfc2VuZF9jb21tYW5kLCB0bCk7 Cj4+Pj4gK8KgwqDCoMKgwqDCoMKgIGdvdG8gZG9uZTsKPj4+PiArwqDCoMKgIH0KPj4+PiArwqDC oMKgIGlmICghbnZtZXRfY2hlY2tfdHJhbnNmZXJfbGVuKHJlcSwgdGwpKSB7Cj4+Pj4gK8KgwqDC oMKgwqDCoMKgIHByX2RlYnVnKCIlczogdHJhbnNmZXIgbGVuZ3RoIG1pc21hdGNoICgldSlcbiIs IF9fZnVuY19fLCB0bCk7Cj4+Pj4gK8KgwqDCoMKgwqDCoMKgIHJldHVybjsKPj4+PiArwqDCoMKg IH0KPj4+PiArCj4+Pj4gK8KgwqDCoCBkID0ga21hbGxvYyh0bCwgR0ZQX0tFUk5FTCk7Cj4+Pj4g K8KgwqDCoCBpZiAoIWQpIHsKPj4+PiArwqDCoMKgwqDCoMKgwqAgc3RhdHVzID0gTlZNRV9TQ19J TlRFUk5BTDsKPj4+PiArwqDCoMKgwqDCoMKgwqAgZ290byBkb25lOwo+Pj4+ICvCoMKgwqAgfQo+ Pj4+ICsKPj4+PiArwqDCoMKgIHN0YXR1cyA9IG52bWV0X2NvcHlfZnJvbV9zZ2wocmVxLCAwLCBk LCB0bCk7Cj4+Pj4gK8KgwqDCoCBpZiAoc3RhdHVzKSB7Cj4+Pj4gK8KgwqDCoMKgwqDCoMKgIGtm cmVlKGQpOwo+Pj4+ICvCoMKgwqDCoMKgwqDCoCBnb3RvIGRvbmU7Cj4+Pj4gK8KgwqDCoCB9Cj4+ Pj4gKwo+Pj4+ICvCoMKgwqAgZGF0YSA9IGQ7Cj4+Pj4gK8KgwqDCoCBwcl9kZWJ1ZygiJXM6IGN0 cmwgJWQgcWlkICVkIHR5cGUgJWQgaWQgJWQgc3RlcCAleFxuIiwgX19mdW5jX18sCj4+Pj4gK8Kg wqDCoMKgwqDCoMKgwqAgY3RybC0+Y250bGlkLCByZXEtPnNxLT5xaWQsIGRhdGEtPmF1dGhfdHlw ZSwgZGF0YS0+YXV0aF9pZCwKPj4+PiArwqDCoMKgwqDCoMKgwqDCoCByZXEtPnNxLT5kaGNoYXBf c3RlcCk7Cj4+Pj4gK8KgwqDCoCBpZiAoZGF0YS0+YXV0aF90eXBlICE9IE5WTUVfQVVUSF9DT01N T05fTUVTU0FHRVMgJiYKPj4+PiArwqDCoMKgwqDCoMKgwqAgZGF0YS0+YXV0aF90eXBlICE9IE5W TUVfQVVUSF9ESENIQVBfTUVTU0FHRVMpCj4+Pj4gK8KgwqDCoMKgwqDCoMKgIGdvdG8gZG9uZV9m YWlsdXJlMTsKPj4+PiArwqDCoMKgIGlmIChkYXRhLT5hdXRoX3R5cGUgPT0gTlZNRV9BVVRIX0NP TU1PTl9NRVNTQUdFUykgewo+Pj4+ICvCoMKgwqDCoMKgwqDCoCBpZiAoZGF0YS0+YXV0aF9pZCA9 PSBOVk1FX0FVVEhfREhDSEFQX01FU1NBR0VfTkVHT1RJQVRFKSB7Cj4+Pj4gK8KgwqDCoMKgwqDC oMKgwqDCoMKgwqAgLyogUmVzdGFydCBuZWdvdGlhdGlvbiAqLwo+Pj4+ICvCoMKgwqDCoMKgwqDC oMKgwqDCoMKgIHByX2RlYnVnKCIlczogY3RybCAlZCBxaWQgJWQgcmVzZXQgbmVnb3RpYXRpb25c biIsIAo+Pj4+IF9fZnVuY19fLAo+Pj4+ICvCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDC oCBjdHJsLT5jbnRsaWQsIHJlcS0+c3EtPnFpZCk7Cj4+Pgo+Pj4gVGhpcyBpcyB0aGUgcG9pbnQg d2hlcmUgeW91IG5lZWQgdG8gcmVzZXQgYWxzbyBhdXRoIGNvbmZpZyBhcyB0aGlzIG1heQo+Pj4g aGF2ZSBjaGFuZ2VkIGFuZCB0aGUgaG9zdCB3aWxsIG5vdCBjcmVhdGUgYSBuZXcgY29udHJvbGxl ciBidXQgcmF0aGVyCj4+PiByZS1hdXRoZW50aWNhdGUgb24gdGhlIGV4aXN0aW5nIGNvbnRyb2xs ZXIuCj4+Pgo+Pj4gaS5lLgo+Pj4KPj4+ICvCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDC oMKgwqDCoMKgwqDCoCBpZiAoIXJlcS0+c3EtPnFpZCkgewo+Pj4gK8KgwqDCoMKgwqDCoMKgwqDC oMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoCBudm1ldF9kZXN0cm95 X2F1dGgoY3RybCk7Cj4+PiArwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDC oMKgwqDCoMKgwqDCoMKgwqDCoMKgIGlmIChudm1ldF9zZXR1cF9hdXRoKGN0cmwpIDwgMCkgewo+ Pj4gK8KgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDC oMKgwqDCoMKgwqDCoMKgwqDCoMKgwqAgcHJfZXJyKCJGYWlsZWQgdG8gc2V0dXAgCj4+PiByZS1h dXRoZW50aWNhdGlvblxuIik7Cj4+PiArwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDC oMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoCBnb3RvIGRvbmVfZmFp bHVyZTE7Cj4+PiArwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDC oMKgwqDCoMKgwqDCoMKgIH0KPj4+ICvCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKg wqDCoMKgwqDCoCB9Cj4+Pgo+Pj4KPj4+Cj4+Cj4+IE5vdCBzdXJlLiBXZSBoYXZlIHR3byBwYXRo cyBob3cgcmUtYXV0aGVudGljYXRpb24gY2FuIGJlIHRyaWdnZXJlZC4KPj4gVGhlIG9uZSBpcyBm cm9tIHRoZSBob3N0LCB3aGljaCBzZW5kcyBhICduZWdvdGlhdGUnIGNvbW1hbmQgdG8gdGhlIAo+ PiBjb250cm9sbGVyIChpZSB0aGlzIHBhdGgpLsKgIFRoZW4gbm90aGluZyBvbiB0aGUgY29udHJv bGxlciBoYXMgCj4+IGNoYW5nZWQsIGFuZCB3ZSBqdXN0IG5lZWQgdG8gZW5zdXJlIHRoYXQgd2Ug cmVzdGFydCBuZWdvdGlhdGlvbi4KPj4gSUUgd2Ugc2hvdWxkIF9ub3RfIHJlc2V0IHRoZSBhdXRo ZW50aWNhdGlvbiAoYXMgdGhhdCB3b3VsZCBhbHNvIHJlbW92ZSAKPj4gdGhlIGNvbnRyb2xsZXIg a2V5cywgd2hpY2ggaGF2ZW4ndCBjaGFuZ2VkKS4gV2Ugc2hvdWxkIGp1c3QgZW5zdXJlIAo+PiB0 aGF0IGFsbCBlcGhlbWVyYWwgZGF0YSBpcyByZWdlbmVyYXRlZC4gQnV0IHRoYXQgc2hvdWxkIGJl IGhhbmRsZWQgCj4+IGluLWxpbmUsIGFuZCBJIF90aGlua18gSSBoYXZlIGNvdmVyZWQgYWxsIG9m IHRoYXQuCj4+IFRoZSBvdGhlciBwYXRoIHRvIHRyaWdnZXIgcmUtYXV0aGVudGljYXRpb24gaXMg d2hlbiBjaGFuZ2luZyB2YWx1ZXMgb24gCj4+IHRoZSBjb250cm9sbGVyIHZpYSBjb25maWdmcy4g VGhlbiBzdXJlIHdlIG5lZWQgdG8gcmVzZXQgdGhlIGNvbnRyb2xsZXIgCj4+IGRhdGEsIGFuZCB0 cmlnZ2VyIHJlYXV0aGVudGljYXRpb24uCj4+IEFuZCB0aGVyZSBJIGRvIGFncmVlLCB0aGF0IHBh dGggaXNuJ3QgZnVsbHkgaW1wbGVtZW50ZWQgLyB0ZXN0ZWQuCj4+IEJ1dCBzaG91bGQgYmUgc3Rh cnRlZCB3aGVuZXZlciB0aGUgY29uZmlnZnMgdmFsdWVzIGNoYW5nZS4KPj4KPiBBY3R1YWxseSwg aGF2aW5nIHJlLXJlYWQgdGhlIHNwZWMgSSdtIG5vdCBzdXJlIGlmIHRoZSBzZWNvbmQgcGF0aCBp cyAKPiBjb3JyZWN0Lgo+IEFzIHBlciBzcGVjIG9ubHkgdGhlIF9ob3N0XyBjYW4gdHJpZ2dlciBy ZS1hdXRoZW50aWNhdGlvbi4gVGhlcmUgaXMgbm8gCj4gcHJvdmlzaW9uIGZvciB0aGUgY29udHJv bGxlciB0byB0cmlnZ2VyIHJlLWF1dGhlbnRpY2F0aW9uLCBhbmQgZ2l2ZW4gCj4gdGhhdCByZS1h dXRoIGlzIGEgc29mdC1zdGF0ZSBhbnl3YXkgKGllIHRoZSBjdXJyZW50IGF1dGhlbnRpY2F0aW9u IHN0YXlzIAo+IHZhbGlkIHVudGlsIHJlLWF1dGggZW50ZXJzIGEgZmluYWwgc3RhdGUpIEkgX3Ro aW5rXyB3ZSBzaG91bGQgYmUgZ29vZCAKPiB3aXRoIHRoZSBjdXJyZW50IGltcGxlbWVudGF0aW9u LCB3aGVyZSB3ZSBjYW4gY2hhbmdlIHRoZSBjb250cm9sbGVyIGtleXMKPiB2aWEgY29uZmlnZnMs IGJ1dCB0aGV5IHdpbGwgb25seSBiZWNvbWUgYWN0aXZlIG9uY2UgdGhlIGhvc3QgdHJpZ2dlcnMK PiByZS1hdXRoZW50aWNhdGlvbi4KCkFncmVlLCBzbyB0aGUgcHJvcG9zZWQgYWRkaXRpb24gaXMg Z29vZCB3aXRoIHlvdT8KCj4gQW5kIGluZGVlZCwgdGhhdCdzIHRoZSBvbmx5IHdheSBob3cgaXQg Y291bGQgd29yaywgb3RoZXJ3aXNlIGl0J2xsIGJlIAo+IHRyaWNreSB0byBjaGFuZ2Uga2V5cyBp biBhIHJ1bm5pbmcgY29ubmVjdGlvbi4KPiBJZiB3ZSB3ZXJlIHRvIGZvcmNlIHJlbmVnb3RpYXRp b24gd2hlbiBjaGFuZ2luZyBjb250cm9sbGVyIGtleXMgd2Ugd291bGQgCj4gaW1tZWRpYXRlbHkg ZmFpbCB0aGUgY29ubmVjdGlvbiwgYXMgd2UgY2Fubm90IGd1YXJhbnRlZSB0aGF0IGNvbnRyb2xs ZXIgCj4gX2FuZF8gaG9zdCBrZXlzIGFyZSBjaGFuZ2VkIGF0IHRoZSBzYW1lIHRpbWUuCgpFeGFj dGx5LCBjaGFuZ2luZyB0aGUgaG9zdGtleSBpbiB0aGUgY29udHJvbGxlciBtdXN0IG5vdCB0cmln Z2VyCnJlLWF1dGgsIHRoZSBob3N0IHdpbGwgcmVtYWluIGNvbm5lY3RlZCBhbmQgb3BlcmF0aW9u YWwgYXMgaXQKYXV0aGVudGljYXRlZCBiZWZvcmUuIEFzIHRoZSBob3N0IHJlLWF1dGhlbnRpY2F0 ZXMgb3IgcmVjb25uZWN0Cml0IG5lZWRzIHRvIGF1dGhlbnRpY2F0ZSBhZ2FpbnN0IHRoZSBuZXcg a2V5LgoKX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX18KTGlu dXgtbnZtZSBtYWlsaW5nIGxpc3QKTGludXgtbnZtZUBsaXN0cy5pbmZyYWRlYWQub3JnCmh0dHA6 Ly9saXN0cy5pbmZyYWRlYWQub3JnL21haWxtYW4vbGlzdGluZm8vbGludXgtbnZtZQo=