mbox series

[PATCHv5,00/12] nvme: In-band authentication support

Message ID 20211112125928.97318-1-hare@suse.de (mailing list archive)
Headers show
Series nvme: In-band authentication support | expand

Message

Hannes Reinecke Nov. 12, 2021, 12:59 p.m. UTC
Hi all,

recent updates to the NVMe spec have added definitions for in-band
authentication, and seeing that it provides some real benefit
especially for NVMe-TCP here's an attempt to implement it.

Tricky bit here is that the specification orients itself on TLS 1.3,
but supports only the FFDHE groups. Which of course the kernel doesn't
support. I've been able to come up with a patch for this, but as this
is my first attempt to fix anything in the crypto area I would invite
people more familiar with these matters to have a look.

Also note that this is just for in-band authentication. Secure
concatenation (ie starting TLS with the negotiated parameters) is not
implemented; one would need to update the kernel TLS implementation
for this, which at this time is beyond scope.

As usual, comments and reviews are welcome.

Changes to v4:
- Validate against blktest suite
- Fixup base64 decoding
- Transform secret with correct hmac algorithm

Changes to v3:
- Renamed parameter to 'dhchap_ctrl_key'
- Fixed bi-directional authentication
- Included reviews from Sagi
- Fixed base64 algorithm for transport encoding

Changes to v2:
- Dropped non-standard algorithms
- Reworked base64 based on fs/crypto/fname.c
- Fixup crash with no keys

Changes to the original submission:
- Included reviews from Vladislav
- Included reviews from Sagi
- Implemented re-authentication support
- Fixed up key handling

Hannes Reinecke (12):
  crypto: add crypto_has_shash()
  crypto: add crypto_has_kpp()
  crypto/ffdhe: Finite Field DH Ephemeral Parameters
  lib/base64: RFC4648-compliant base64 encoding
  nvme: add definitions for NVMe In-Band authentication
  nvme-fabrics: decode 'authentication required' connect error
  nvme: Implement In-Band authentication
  nvme-auth: Diffie-Hellman key exchange support
  nvmet: Parse fabrics commands on all queues
  nvmet: Implement basic In-Band Authentication
  nvmet-auth: Diffie-Hellman key exchange support
  nvmet-auth: expire authentication sessions

 crypto/Kconfig                         |    8 +
 crypto/Makefile                        |    1 +
 crypto/ffdhe_helper.c                  |  880 +++++++++++++
 crypto/kpp.c                           |    6 +
 crypto/shash.c                         |    6 +
 drivers/nvme/host/Kconfig              |   12 +
 drivers/nvme/host/Makefile             |    1 +
 drivers/nvme/host/auth.c               | 1564 ++++++++++++++++++++++++
 drivers/nvme/host/auth.h               |   34 +
 drivers/nvme/host/core.c               |  133 +-
 drivers/nvme/host/fabrics.c            |   83 +-
 drivers/nvme/host/fabrics.h            |    7 +
 drivers/nvme/host/nvme.h               |   36 +
 drivers/nvme/host/tcp.c                |    1 +
 drivers/nvme/host/trace.c              |   32 +
 drivers/nvme/target/Kconfig            |   12 +
 drivers/nvme/target/Makefile           |    1 +
 drivers/nvme/target/admin-cmd.c        |    4 +
 drivers/nvme/target/auth.c             |  544 +++++++++
 drivers/nvme/target/configfs.c         |  138 ++-
 drivers/nvme/target/core.c             |   10 +
 drivers/nvme/target/fabrics-cmd-auth.c |  513 ++++++++
 drivers/nvme/target/fabrics-cmd.c      |   30 +-
 drivers/nvme/target/nvmet.h            |   77 ++
 include/crypto/ffdhe.h                 |   24 +
 include/crypto/hash.h                  |    2 +
 include/crypto/kpp.h                   |    2 +
 include/linux/base64.h                 |   16 +
 include/linux/nvme.h                   |  186 ++-
 lib/Makefile                           |    2 +-
 lib/base64.c                           |  103 ++
 31 files changed, 4456 insertions(+), 12 deletions(-)
 create mode 100644 crypto/ffdhe_helper.c
 create mode 100644 drivers/nvme/host/auth.c
 create mode 100644 drivers/nvme/host/auth.h
 create mode 100644 drivers/nvme/target/auth.c
 create mode 100644 drivers/nvme/target/fabrics-cmd-auth.c
 create mode 100644 include/crypto/ffdhe.h
 create mode 100644 include/linux/base64.h
 create mode 100644 lib/base64.c

Comments

Sagi Grimberg Nov. 14, 2021, 10:40 a.m. UTC | #1
On 11/12/21 2:59 PM, Hannes Reinecke wrote:
> Hi all,
> 
> recent updates to the NVMe spec have added definitions for in-band
> authentication, and seeing that it provides some real benefit
> especially for NVMe-TCP here's an attempt to implement it.
> 
> Tricky bit here is that the specification orients itself on TLS 1.3,
> but supports only the FFDHE groups. Which of course the kernel doesn't
> support. I've been able to come up with a patch for this, but as this
> is my first attempt to fix anything in the crypto area I would invite
> people more familiar with these matters to have a look.
> 
> Also note that this is just for in-band authentication. Secure
> concatenation (ie starting TLS with the negotiated parameters) is not
> implemented; one would need to update the kernel TLS implementation
> for this, which at this time is beyond scope.
> 
> As usual, comments and reviews are welcome.
> 
> Changes to v4:
> - Validate against blktest suite

Nice! thanks hannes, this is going to be very useful moving
forward.

> - Fixup base64 decoding

What was fixed up there?

> - Transform secret with correct hmac algorithm

Is that what I reported last time? Can you perhaps
point me to the exact patch that fixes this?
Hannes Reinecke Nov. 14, 2021, 1:44 p.m. UTC | #2
On 11/14/21 11:40 AM, Sagi Grimberg wrote:
> 
> 
> On 11/12/21 2:59 PM, Hannes Reinecke wrote:
>> Hi all,
>>
>> recent updates to the NVMe spec have added definitions for in-band
>> authentication, and seeing that it provides some real benefit
>> especially for NVMe-TCP here's an attempt to implement it.
>>
>> Tricky bit here is that the specification orients itself on TLS 1.3,
>> but supports only the FFDHE groups. Which of course the kernel doesn't
>> support. I've been able to come up with a patch for this, but as this
>> is my first attempt to fix anything in the crypto area I would invite
>> people more familiar with these matters to have a look.
>>
>> Also note that this is just for in-band authentication. Secure
>> concatenation (ie starting TLS with the negotiated parameters) is not
>> implemented; one would need to update the kernel TLS implementation
>> for this, which at this time is beyond scope.
>>
>> As usual, comments and reviews are welcome.
>>
>> Changes to v4:
>> - Validate against blktest suite
> 
> Nice! thanks hannes, this is going to be very useful moving
> forward.
> 
Oh, definitely. The number of issue these tests found...

>> - Fixup base64 decoding
> 
> What was fixed up there?
> 
The padding character '=' wasn't handled correctly on decoding (the 
character itself was skipped, by the 'bits' value wasn't increased, 
leading to a spurious error in decoding an any key longer than 32 bit 
not being accepted.

>> - Transform secret with correct hmac algorithm
> 
> Is that what I reported last time? Can you perhaps
> point me to the exact patch that fixes this?

Well, no, not really; the patch itself got squashed in the main patches.
But problem here was that the key transformation from section 8.13.5.7 
had been using the hash algorithm from the initial challenge, not the 
one specified in the key itself.
This lead to decoding errors when using a key with a different length 
than the hash algorithm.

Cheers,

Hannes
Sagi Grimberg Nov. 15, 2021, 10:20 a.m. UTC | #3
>>> Changes to v4:
>>> - Validate against blktest suite
>>
>> Nice! thanks hannes, this is going to be very useful moving
>> forward.
>>
> Oh, definitely. The number of issue these tests found...

Great, good that this was useful for you.

>>> - Fixup base64 decoding
>>
>> What was fixed up there?
>>
> The padding character '=' wasn't handled correctly on decoding (the 
> character itself was skipped, by the 'bits' value wasn't increased, 
> leading to a spurious error in decoding an any key longer than 32 bit 
> not being accepted.

I see.

>>> - Transform secret with correct hmac algorithm
>>
>> Is that what I reported last time? Can you perhaps
>> point me to the exact patch that fixes this?
> 
> Well, no, not really; the patch itself got squashed in the main patches.
> But problem here was that the key transformation from section 8.13.5.7 
> had been using the hash algorithm from the initial challenge, not the 
> one specified in the key itself.
> This lead to decoding errors when using a key with a different length 
> than the hash algorithm.

That is exactly what I reported, changing the key length leads to
authentication errors.
Hannes Reinecke Nov. 15, 2021, 11:34 a.m. UTC | #4
On 11/15/21 11:20 AM, Sagi Grimberg wrote:
> 
>>>> Changes to v4:
>>>> - Validate against blktest suite
>>>
>>> Nice! thanks hannes, this is going to be very useful moving
>>> forward.
>>>
>> Oh, definitely. The number of issue these tests found...
> 
> Great, good that this was useful for you.
> 
>>>> - Fixup base64 decoding
>>>
>>> What was fixed up there?
>>>
>> The padding character '=' wasn't handled correctly on decoding (the
>> character itself was skipped, by the 'bits' value wasn't increased,
>> leading to a spurious error in decoding an any key longer than 32 bit
>> not being accepted.
> 
> I see.
> 
>>>> - Transform secret with correct hmac algorithm
>>>
>>> Is that what I reported last time? Can you perhaps
>>> point me to the exact patch that fixes this?
>>
>> Well, no, not really; the patch itself got squashed in the main patches.
>> But problem here was that the key transformation from section 8.13.5.7
>> had been using the hash algorithm from the initial challenge, not the
>> one specified in the key itself.
>> This lead to decoding errors when using a key with a different length
>> than the hash algorithm.
> 
> That is exactly what I reported, changing the key length leads to
> authentication errors.

Right-o. So it should be sorted then.

BTW, I've created a pull request for nvme-cli
(https://github.com/linux-nvme/nvme-cli/pull/1237)
to add a new command-line option 'dump-config'; can you check if that's
what you had in mind or whether it needs to be improved further?

Cheers,

Hannes
Sagi Grimberg Nov. 15, 2021, 1:12 p.m. UTC | #5
> BTW, I've created a pull request for nvme-cli
> (https://github.com/linux-nvme/nvme-cli/pull/1237)
> to add a new command-line option 'dump-config'; can you check if that's
> what you had in mind or whether it needs to be improved further?

The dump is nice, thanks. I gave a couple of comments on the PR.
I do suspect that people will want to populate this file outside
of dump-config, hence we need a markdown documentation for it
or in this case a json schema...
Sagi Grimberg Nov. 16, 2021, 10:18 a.m. UTC | #6
>>>>> - Transform secret with correct hmac algorithm
>>>>
>>>> Is that what I reported last time? Can you perhaps
>>>> point me to the exact patch that fixes this?
>>>
>>> Well, no, not really; the patch itself got squashed in the main patches.
>>> But problem here was that the key transformation from section 8.13.5.7
>>> had been using the hash algorithm from the initial challenge, not the
>>> one specified in the key itself.
>>> This lead to decoding errors when using a key with a different length
>>> than the hash algorithm.
>>
>> That is exactly what I reported, changing the key length leads to
>> authentication errors.
> 
> Right-o. So it should be sorted then.

Hannes, was the issue on the host side or the controller side?

I'm a little lost into what was the actual fix...
Hannes Reinecke Nov. 16, 2021, 10:23 a.m. UTC | #7
On 11/16/21 11:18 AM, Sagi Grimberg wrote:
> 
>>>>>> - Transform secret with correct hmac algorithm
>>>>>
>>>>> Is that what I reported last time? Can you perhaps
>>>>> point me to the exact patch that fixes this?
>>>>
>>>> Well, no, not really; the patch itself got squashed in the main
>>>> patches.
>>>> But problem here was that the key transformation from section 8.13.5.7
>>>> had been using the hash algorithm from the initial challenge, not the
>>>> one specified in the key itself.
>>>> This lead to decoding errors when using a key with a different length
>>>> than the hash algorithm.
>>>
>>> That is exactly what I reported, changing the key length leads to
>>> authentication errors.
>>
>> Right-o. So it should be sorted then.
> 
> Hannes, was the issue on the host side or the controller side?
> 
The issue was actually on the host side.

> I'm a little lost into what was the actual fix...

The basic fix was this:

@@ -927,13 +944,17 @@ static int nvme_auth_dhchap_host_response(struct
nvme_ctrl
 *ctrl,

        if (!chap->host_response) {
                chap->host_response =
nvme_auth_transform_key(ctrl->dhchap_key,
-                                       ctrl->dhchap_key_len, chap->hash_id,
+                                       ctrl->dhchap_key_len,
+                                       ctrl->dhchap_key_hash,
                                        ctrl->opts->host->nqn);
                if (IS_ERR(chap->host_response)) {
                        ret = PTR_ERR(chap->host_response);
                        chap->host_response = NULL;
                        return ret;
                }


(minus the linebreaks, of course).
'chap->hash_id' is the hash selected by the initial negotiation, which
is wrong as we should have used the hash function selected by the key
itself.

Cheers,

Hannes
Sagi Grimberg Nov. 16, 2021, 10:36 a.m. UTC | #8
>> Hannes, was the issue on the host side or the controller side?
>>
> The issue was actually on the host side.
> 
>> I'm a little lost into what was the actual fix...
> 
> The basic fix was this:
> 
> @@ -927,13 +944,17 @@ static int nvme_auth_dhchap_host_response(struct
> nvme_ctrl
>   *ctrl,
> 
>          if (!chap->host_response) {
>                  chap->host_response =
> nvme_auth_transform_key(ctrl->dhchap_key,
> -                                       ctrl->dhchap_key_len, chap->hash_id,
> +                                       ctrl->dhchap_key_len,
> +                                       ctrl->dhchap_key_hash,
>                                          ctrl->opts->host->nqn);
>                  if (IS_ERR(chap->host_response)) {
>                          ret = PTR_ERR(chap->host_response);
>                          chap->host_response = NULL;
>                          return ret;
>                  }
> 
> 
> (minus the linebreaks, of course).
> 'chap->hash_id' is the hash selected by the initial negotiation, which
> is wrong as we should have used the hash function selected by the key
> itself.

Makes sense. thanks.