diff mbox series

[11/21] doc: PKEX support for DPP

Message ID 20231012200150.338401-12-prestwoj@gmail.com (mailing list archive)
State New
Headers show
Series DPP PKEX Changes | expand

Commit Message

James Prestwood Oct. 12, 2023, 8:01 p.m. UTC
PKEX is part of the WFA EasyConnect specification and is
an additional boostrapping method (like QR codes) for
exchanging public keys between a configurator and enrollee.

PKEX operates over wifi and requires a key/code be exchanged
prior to the protocol. The key is used to encrypt the exchange
of the boostrapping information, then DPP authentication is
started immediately aftewards.

This can be useful for devices which don't have the ability to
scan a QR code, or even as a more convenient way to share
wireless credentials if the PSK is very secure (i.e. not a
human readable string).

PKEX would be used via the two DBus APIs on a new interface
SharedCodeDeviceProvisioning.

StartConfigurator() will start listening and wait for an
Enrollee to send a PKEX exchange request.

StartEnrollee() will initiate the exchange.

PKEX would proceed and once done DPP Authentication will start
using the boostrapping keys exchanged.
---
 doc/device-provisioning-api.txt | 30 ++++++++++++++++++++++++++++++
 1 file changed, 30 insertions(+)

Comments

Denis Kenzior Oct. 19, 2023, 2:59 p.m. UTC | #1
Hi James,

On 10/12/23 15:01, James Prestwood wrote:
> PKEX is part of the WFA EasyConnect specification and is
> an additional boostrapping method (like QR codes) for
> exchanging public keys between a configurator and enrollee.
> 
> PKEX operates over wifi and requires a key/code be exchanged
> prior to the protocol. The key is used to encrypt the exchange
> of the boostrapping information, then DPP authentication is
> started immediately aftewards.
> 
> This can be useful for devices which don't have the ability to
> scan a QR code, or even as a more convenient way to share
> wireless credentials if the PSK is very secure (i.e. not a
> human readable string).
> 
> PKEX would be used via the two DBus APIs on a new interface
> SharedCodeDeviceProvisioning.
> 
> StartConfigurator() will start listening and wait for an
> Enrollee to send a PKEX exchange request.
> 
> StartEnrollee() will initiate the exchange.
> 
> PKEX would proceed and once done DPP Authentication will start
> using the boostrapping keys exchanged.
> ---
>   doc/device-provisioning-api.txt | 30 ++++++++++++++++++++++++++++++
>   1 file changed, 30 insertions(+)
> 
> diff --git a/doc/device-provisioning-api.txt b/doc/device-provisioning-api.txt
> index ac204f46..4c0ecb28 100644
> --- a/doc/device-provisioning-api.txt
> +++ b/doc/device-provisioning-api.txt
> @@ -71,3 +71,33 @@ Properties	boolean Started [readonly]
>   
>   			Indicates the DPP URI. This property is only available
>   			when Started is true.
> +
> +
> +Interface	net.connman.iwd.DeviceProvisioning [Experimental]

nit: [experimental]

> +Object path	/net/connman/iwd/{phy0,phy1,...}/{1,2,...}
> +
> +		StartConfigurator()
> +			Start a PKEX configurator. IWD must be currently
> +			connected to a BSS and have at least the

To a network?

> +			[Security].DeviceProvisioningSharedCode option set in
> +			the network profile. An identifier can be set with
> +			[Security].DeviceProvisioningIdentifier.

I would think [DeviceProvisioning] SharedCode and Identifier?

But I do have to ask, this is used for PSK networks where profiles are rarely 
touched by the user.  Do you really expect someone to muck around in them?  I 
wonder if autogenerating such codes / identifiers or an Agent API is more 
appropriate?

> +
> +			Possible errors:	net.connman.iwd.Busy
> +						net.connman.iwd.NotConnected
> +						net.connman.iwd.InvalidArguments
> +						net.connman.iwd.NotConfigured
> +
> +		StartEnrollee(a{sv} args)
> +			The 'args' dictionary contains parameters for the PKEX
> +			enrollee.
> +
> +			string Key - The PKEX key. This is required and must
> +			match the configurer's key.

Why is this not symmetric with Configurator role?  I assume this should be 
SharedCode?

> +
> +			string Identifier - The PKEX key identifier. This is > +			optional, but if used both the Configurer and enrollee

Configurator?

> +			must use the same value.
> +
> +			Possible errors:	net.connman.iwd.Busy
> +						net.connman.iwd.InvalidArguments
> \ No newline at end of file

Regards,
-Denis
James Prestwood Oct. 19, 2023, 3:23 p.m. UTC | #2
Hi Denis,

On 10/19/23 7:59 AM, Denis Kenzior wrote:
> Hi James,
> 
> On 10/12/23 15:01, James Prestwood wrote:
>> PKEX is part of the WFA EasyConnect specification and is
>> an additional boostrapping method (like QR codes) for
>> exchanging public keys between a configurator and enrollee.
>>
>> PKEX operates over wifi and requires a key/code be exchanged
>> prior to the protocol. The key is used to encrypt the exchange
>> of the boostrapping information, then DPP authentication is
>> started immediately aftewards.
>>
>> This can be useful for devices which don't have the ability to
>> scan a QR code, or even as a more convenient way to share
>> wireless credentials if the PSK is very secure (i.e. not a
>> human readable string).
>>
>> PKEX would be used via the two DBus APIs on a new interface
>> SharedCodeDeviceProvisioning.
>>
>> StartConfigurator() will start listening and wait for an
>> Enrollee to send a PKEX exchange request.
>>
>> StartEnrollee() will initiate the exchange.
>>
>> PKEX would proceed and once done DPP Authentication will start
>> using the boostrapping keys exchanged.
>> ---
>>   doc/device-provisioning-api.txt | 30 ++++++++++++++++++++++++++++++
>>   1 file changed, 30 insertions(+)
>>
>> diff --git a/doc/device-provisioning-api.txt 
>> b/doc/device-provisioning-api.txt
>> index ac204f46..4c0ecb28 100644
>> --- a/doc/device-provisioning-api.txt
>> +++ b/doc/device-provisioning-api.txt
>> @@ -71,3 +71,33 @@ Properties    boolean Started [readonly]
>>               Indicates the DPP URI. This property is only available
>>               when Started is true.
>> +
>> +
>> +Interface    net.connman.iwd.DeviceProvisioning [Experimental]
> 
> nit: [experimental]
> 
>> +Object path    /net/connman/iwd/{phy0,phy1,...}/{1,2,...}
>> +
>> +        StartConfigurator()
>> +            Start a PKEX configurator. IWD must be currently
>> +            connected to a BSS and have at least the
> 
> To a network?
> 
>> +            [Security].DeviceProvisioningSharedCode option set in
>> +            the network profile. An identifier can be set with
>> +            [Security].DeviceProvisioningIdentifier.
> 
> I would think [DeviceProvisioning] SharedCode and Identifier?
> 
> But I do have to ask, this is used for PSK networks where profiles are 
> rarely touched by the user.  Do you really expect someone to muck around 
> in them?  I wonder if autogenerating such codes / identifiers or an 
> Agent API is more appropriate?

Autogeneration really won't work since both peers have to match.

For my needs the code/key is baked into the device image (i.e. a config 
file) so putting it into the .psk file would work great mainly because 
IWD could encrypt it (by adding "DeviceProvisioning" to the list of 
groups for profile encryption).

But for a human user the shared code does make sense to come from an 
agent, or the StartConfigurator() API itself. The use case here that 
comes to mind is sharing wifi credentials when your PSK is a very secure 
random string and you don't want to have someone type that in.

Could we support both like how we do with PSKs already? If not in the 
config file ask the agent?

> 
>> +
>> +            Possible errors:    net.connman.iwd.Busy
>> +                        net.connman.iwd.NotConnected
>> +                        net.connman.iwd.InvalidArguments
>> +                        net.connman.iwd.NotConfigured
>> +
>> +        StartEnrollee(a{sv} args)
>> +            The 'args' dictionary contains parameters for the PKEX
>> +            enrollee.
>> +
>> +            string Key - The PKEX key. This is required and must
>> +            match the configurer's key.
> 
> Why is this not symmetric with Configurator role?  I assume this should 
> be SharedCode?
> 
>> +
>> +            string Identifier - The PKEX key identifier. This is > 
>> +            optional, but if used both the Configurer and enrollee
> 
> Configurator?
> 
>> +            must use the same value.
>> +
>> +            Possible errors:    net.connman.iwd.Busy
>> +                        net.connman.iwd.InvalidArguments
>> \ No newline at end of file
> 
> Regards,
> -Denis
Denis Kenzior Oct. 19, 2023, 3:36 p.m. UTC | #3
Hi James,

>> I would think [DeviceProvisioning] SharedCode and Identifier?
>>
>> But I do have to ask, this is used for PSK networks where profiles are rarely 
>> touched by the user.  Do you really expect someone to muck around in them?  I 
>> wonder if autogenerating such codes / identifiers or an Agent API is more 
>> appropriate?
> 
> Autogeneration really won't work since both peers have to match.
> 

WPS auto-generates a PIN, can we do the same here?

> For my needs the code/key is baked into the device image (i.e. a config file) so 
> putting it into the .psk file would work great mainly because IWD could encrypt 
> it (by adding "DeviceProvisioning" to the list of groups for profile encryption).
> 

Sure, and that's fine since we don't want to bug the user every time this 
happens.  But we have to provide some way for this to be provided outside of the 
user hacking the provisioning file.

> But for a human user the shared code does make sense to come from an agent, or 
> the StartConfigurator() API itself. The use case here that comes to mind is 
> sharing wifi credentials when your PSK is a very secure random string and you 
> don't want to have someone type that in.

Exactly.

> 
> Could we support both like how we do with PSKs already? If not in the config 
> file ask the agent?

Yes, that would be ideal.

Regards,
-Denis
James Prestwood Oct. 19, 2023, 3:45 p.m. UTC | #4
Hi Denis,

On 10/19/23 8:36 AM, Denis Kenzior wrote:
> Hi James,
> 
>>> I would think [DeviceProvisioning] SharedCode and Identifier?
>>>
>>> But I do have to ask, this is used for PSK networks where profiles 
>>> are rarely touched by the user.  Do you really expect someone to muck 
>>> around in them?  I wonder if autogenerating such codes / identifiers 
>>> or an Agent API is more appropriate?
>>
>> Autogeneration really won't work since both peers have to match.
>>
> 
> WPS auto-generates a PIN, can we do the same here?

You mean auto-generate then have the user (configurator) share that 
out-of-band? Sure, but its probably just as easy for the user to type in 
1234 or something as opposed to calling the API then reading back the 
generated code to their enrollee. Or maybe I'm not understanding what 
your talking about.

> 
>> For my needs the code/key is baked into the device image (i.e. a 
>> config file) so putting it into the .psk file would work great mainly 
>> because IWD could encrypt it (by adding "DeviceProvisioning" to the 
>> list of groups for profile encryption).
>>
> 
> Sure, and that's fine since we don't want to bug the user every time 
> this happens.  But we have to provide some way for this to be provided 
> outside of the user hacking the provisioning file.
> 
>> But for a human user the shared code does make sense to come from an 
>> agent, or the StartConfigurator() API itself. The use case here that 
>> comes to mind is sharing wifi credentials when your PSK is a very 
>> secure random string and you don't want to have someone type that in.
> 
> Exactly.
> 
>>
>> Could we support both like how we do with PSKs already? If not in the 
>> config file ask the agent?
> 
> Yes, that would be ideal.

Ok lets do it both ways.

> 
> Regards,
> -Denis
Denis Kenzior Oct. 19, 2023, 4:17 p.m. UTC | #5
Hi James,

>>
>> WPS auto-generates a PIN, can we do the same here?
> 
> You mean auto-generate then have the user (configurator) share that out-of-band? 
> Sure, but its probably just as easy for the user to type in 1234 or something as 
> opposed to calling the API then reading back the generated code to their 
> enrollee. Or maybe I'm not understanding what your talking about.
> 

I assume the shared code should be of a certain size and complexity, no?  Just 
like your web browser can auto-generate a strong password, same would apply 
here?  Also, PINs for WPS had special rules.  Don't know if this is a concern here.

Regards,
-Denis
James Prestwood Oct. 19, 2023, 4:42 p.m. UTC | #6
On 10/19/23 9:17 AM, Denis Kenzior wrote:
> Hi James,
> 
>>>
>>> WPS auto-generates a PIN, can we do the same here?
>>
>> You mean auto-generate then have the user (configurator) share that 
>> out-of-band? Sure, but its probably just as easy for the user to type 
>> in 1234 or something as opposed to calling the API then reading back 
>> the generated code to their enrollee. Or maybe I'm not understanding 
>> what your talking about.
>>
> 
> I assume the shared code should be of a certain size and complexity, 
> no?  Just like your web browser can auto-generate a strong password, 
> same would apply here?  Also, PINs for WPS had special rules.  Don't 
> know if this is a concern here.

I guess my question is really how you communicate this to the enrollee.

The use case for a human user really comes down to not wanting to type 
in a 64 character hex string :) So auto-generating a complex code 
doesn't make much sense in this regard.

For a headless device auto-generation just won't work since the password 
is baked into the image. I considered generating a single bootstrapping 
key and bake that into the image (no PKEX) but I question the 
possibility of offline attacks. With PKEX the bootstrapping keys are 
changed upon each protocol run so I think there is forward secrecy 
there. Plus PKEX uses mutual authentication to prevent someone from 
coming in and configuring the new devices who shouldn't be.

> 
> Regards,
> -Denis
Denis Kenzior Oct. 19, 2023, 6:56 p.m. UTC | #7
Hi James,

> 
> I guess my question is really how you communicate this to the enrollee.
> 
> The use case for a human user really comes down to not wanting to type in a 64 
> character hex string :) So auto-generating a complex code doesn't make much 
> sense in this regard.

Who said anything about a 64 character hex?  I'm thinking more about a 10-12 
character complex password like you see the web browser generate.  However, I'm 
pretty sure we need the ability to generate the code every time:

"If both sides have a user interface, this technique can be used to bootstrap 
trust by exchanging bootstrapping information including the bootstrapping keys 
that are to be used for a DPP exchange requiring mutual authentication. This 
bootstrapping technique shall use a fresh code each time and the same code shall 
not be used with different Peers."

Correct me if I'm wrong, but PKEX is no different than regular DPP.  It simply 
uses a code instead of a QR code for establishing the initial trust channel 
(giving high degree of confidence to both parties that the exchanged public keys 
are trusted).  The more complex the code, the better the chance that the code 
can be trusted (i.e. it wasn't guessed).  It still inherits the same basic 
attributes, roles, etc.


> 
> For a headless device auto-generation just won't work since the password is 
> baked into the image. I considered generating a single bootstrapping key and 

Doesn't this run counter to what PKEX is about?

> bake that into the image (no PKEX) but I question the possibility of offline 

With a strong password, probably eons, unless quantum computing is involved.

> attacks. With PKEX the bootstrapping keys are changed upon each protocol run so 

But you're still sharing a PSK in the end?  Why go through all this trouble?

> I think there is forward secrecy there. Plus PKEX uses mutual authentication to 

WPA3 has forward secrecy as well.  So what are you trying to achieve?

> prevent someone from coming in and configuring the new devices who shouldn't be.
> 

The gold standard is still WPA-Enterprise with EAP-TLS.

Regards,
-Denis
James Prestwood Oct. 19, 2023, 8 p.m. UTC | #8
Hi Denis,

On 10/19/23 11:56 AM, Denis Kenzior wrote:
> Hi James,
> 
>>
>> I guess my question is really how you communicate this to the enrollee.
>>
>> The use case for a human user really comes down to not wanting to type 
>> in a 64 character hex string :) So auto-generating a complex code 
>> doesn't make much sense in this regard.
> 
> Who said anything about a 64 character hex?  I'm thinking more about a 
> 10-12 character complex password like you see the web browser generate.  
> However, I'm pretty sure we need the ability to generate the code every 
> time:
> 
> "If both sides have a user interface, this technique can be used to 
> bootstrap trust by exchanging bootstrapping information including the 
> bootstrapping keys that are to be used for a DPP exchange requiring 
> mutual authentication. This bootstrapping technique shall use a fresh 
> code each time and the same code shall not be used with different Peers."
> 
> Correct me if I'm wrong, but PKEX is no different than regular DPP.  It 
> simply uses a code instead of a QR code for establishing the initial 
> trust channel (giving high degree of confidence to both parties that the 
> exchanged public keys are trusted).  The more complex the code, the 
> better the chance that the code can be trusted (i.e. it wasn't 
> guessed).  It still inherits the same basic attributes, roles, etc.

Yep, its purely a way to securely exchange bootstrapping keys.

> 
> 
>>
>> For a headless device auto-generation just won't work since the 
>> password is baked into the image. I considered generating a single 
>> bootstrapping key and 
> 
> Doesn't this run counter to what PKEX is about?

I don't think it runs counter, it just may not be _exactly_ what the 
spec intended it to be used for. Using the same code isn't any different 
than using the same PSK.

No matter what if your PSK or PKEX code gets compromised your stuck 
re-configuring all your devices. I don't see an issue using a secure but 
static PKEX code. Either way, this isn't really IWD's problem :)

> 
>> bake that into the image (no PKEX) but I question the possibility of 
>> offline 
> 
> With a strong password, probably eons, unless quantum computing is 
> involved.
> 
>> attacks. With PKEX the bootstrapping keys are changed upon each 
>> protocol run so 
> 
> But you're still sharing a PSK in the end?  Why go through all this 
> trouble?

This is a more dynamic way of configuration and allows devices to show 
up in a 'default' state and require zero manual configuration (for 
specific wifi networks). When your talking about 10, 20, 100 devices, 
manually configuring each one takes a lot of time. PKEX provided a 
"hands-off" way of doing it assuming you have other devices in the area 
with credentials.

> 
>> I think there is forward secrecy there. Plus PKEX uses mutual 
>> authentication to 
> 
> WPA3 has forward secrecy as well.  So what are you trying to achieve?

I was just comparing PKEX to using a static pre-shared bootstrapping key 
and fudging it to look like a QR code was scanned. This isn't a good 
idea, hence why I pursued PKEX.

> 
>> prevent someone from coming in and configuring the new devices who 
>> shouldn't be.
>>
> 
> The gold standard is still WPA-Enterprise with EAP-TLS.
> 
> Regards,
> -Denis
>
Denis Kenzior Oct. 19, 2023, 9:47 p.m. UTC | #9
Hi James,

>>>
>>> For a headless device auto-generation just won't work since the password is 
>>> baked into the image. I considered generating a single bootstrapping key and 
>>
>> Doesn't this run counter to what PKEX is about?
> 
> I don't think it runs counter, it just may not be _exactly_ what the spec 
> intended it to be used for. Using the same code isn't any different than using 
> the same PSK.

I don't know if I'd agree...

https://datatracker.ietf.org/doc/html/draft-harkins-pkex-05:
"The only information exposed by an active attack is whether a
       single guess of the password is correct or not."

> 
> No matter what if your PSK or PKEX code gets compromised your stuck 
> re-configuring all your devices. I don't see an issue using a secure but static 
> PKEX code. Either way, this isn't really IWD's problem :)

Well, we have to design the API with the 'right' way of using it in mind.  I 
don't think what you propose fits that.

Regards,
-Denis
James Prestwood Oct. 19, 2023, 10:22 p.m. UTC | #10
Hi Denis,

On 10/19/23 2:47 PM, Denis Kenzior wrote:
> Hi James,
> 
>>>>
>>>> For a headless device auto-generation just won't work since the 
>>>> password is baked into the image. I considered generating a single 
>>>> bootstrapping key and 
>>>
>>> Doesn't this run counter to what PKEX is about?
>>
>> I don't think it runs counter, it just may not be _exactly_ what the 
>> spec intended it to be used for. Using the same code isn't any 
>> different than using the same PSK.
> 
> I don't know if I'd agree...
> 
> https://datatracker.ietf.org/doc/html/draft-harkins-pkex-05:
> "The only information exposed by an active attack is whether a
>        single guess of the password is correct or not."

My comparison to the PSK is that there is no difference in guessing the 
PSK vs PKEX key. Both equally compromise you.

I'm not sure that quote specifically is mandating the PKEX exchange use 
a different password every time, just that an exchange will tell you 
_if_ you guessed the password correctly. But you are right that the DPP 
spec wants a different PW to be used each time.

"shall use a fresh code each time and the same code shall not be used 
with different Peers"

So we don't have to put it in the config file if you don't want to. 
Auto-generation just won't work for my purposes since I have no way of 
sharing that on a headless device, so if that's a must I'd have to do 
some thinking...

> 
>>
>> No matter what if your PSK or PKEX code gets compromised your stuck 
>> re-configuring all your devices. I don't see an issue using a secure 
>> but static PKEX code. Either way, this isn't really IWD's problem :)
> 
> Well, we have to design the API with the 'right' way of using it in 
> mind.  I don't think what you propose fits that.

I'm fine with it as an argument to the StartConfigurator API. An agent 
could work but we've also got the optional identifier to think about. 
I'd prefer to use the existing agent API for getting a passphrase rather 
than a new method.

> 
> Regards,
> -Denis
Denis Kenzior Oct. 19, 2023, 11:12 p.m. UTC | #11
Hi James,

> 
> My comparison to the PSK is that there is no difference in guessing the PSK vs 
> PKEX key. Both equally compromise you.
> 

I'm with you :)

> I'm not sure that quote specifically is mandating the PKEX exchange use a 
> different password every time, just that an exchange will tell you _if_ you 
> guessed the password correctly. But you are right that the DPP spec wants a 
> different PW to be used each time.

I'll need to do a bit more spelunking in the relevant specifications to see if 
we have a bit more leeway, but ...

The draft RFC is pretty explicit, it does not mandate 'every time', but close 
enough:

"Implementations SHALL maintain a counter of unsuccessful exchanges
    for each password in order to defend against repeated active attacks
    to determine the password.  This counter SHALL be set to zero when a
    password is provisioned and incremented each time PKEX finishes
    unsuccessfully for that password.  When the counter reaches a value
    of five (5) the password SHALL be irretrievably removed from the
    implementation."

The DPP spec is a bit more permissive in that it says 'If both sides have a user 
interface'.  But I think the intent is for the shared code to be regenerated on 
each attempt.

> 
> "shall use a fresh code each time and the same code shall not be used with 
> different Peers"
> 
> So we don't have to put it in the config file if you don't want to. 
> Auto-generation just won't work for my purposes since I have no way of sharing 
> that on a headless device, so if that's a must I'd have to do some thinking...

Fair enough, lets explore whether we can provide this via some agent API.

> 
> I'm fine with it as an argument to the StartConfigurator API. An agent could 
> work but we've also got the optional identifier to think about. I'd prefer to 
> use the existing agent API for getting a passphrase rather than a new method.
> 

But the identifier is not supposed to be secret?

Regards,
-Denis
James Prestwood Oct. 23, 2023, 1:49 p.m. UTC | #12
Hi Denis,

> 
>>
>> I'm fine with it as an argument to the StartConfigurator API. An agent 
>> could work but we've also got the optional identifier to think about. 
>> I'd prefer to use the existing agent API for getting a passphrase 
>> rather than a new method.
>>
> 
> But the identifier is not supposed to be secret?

No, the identifier is sent plaintext:

"Optionally, a non-secret identifier for the code can be transmitted to 
support the case where a PKEX implementation may be provisioned to 
connect to a plurality of devices and needs to know which code to use to 
process a received PKEX frame. If an optional code identifier is used, 
it shall be a UTF-8 string not greater than eighty (80) octets that is 
provisioned at the same time as the shared code."

> 
> Regards,
> -Denis
James Prestwood Oct. 24, 2023, 12:05 p.m. UTC | #13
Hi Denis,

On 10/19/23 4:12 PM, Denis Kenzior wrote:
> Hi James,
> 
>>
>> My comparison to the PSK is that there is no difference in guessing 
>> the PSK vs PKEX key. Both equally compromise you.
>>
> 
> I'm with you :)
> 
>> I'm not sure that quote specifically is mandating the PKEX exchange 
>> use a different password every time, just that an exchange will tell 
>> you _if_ you guessed the password correctly. But you are right that 
>> the DPP spec wants a different PW to be used each time.
> 
> I'll need to do a bit more spelunking in the relevant specifications to 
> see if we have a bit more leeway, but ...
> 
> The draft RFC is pretty explicit, it does not mandate 'every time', but 
> close enough:
> 
> "Implementations SHALL maintain a counter of unsuccessful exchanges
>     for each password in order to defend against repeated active attacks
>     to determine the password.  This counter SHALL be set to zero when a
>     password is provisioned and incremented each time PKEX finishes
>     unsuccessfully for that password.  When the counter reaches a value
>     of five (5) the password SHALL be irretrievably removed from the
>     implementation."
> 
> The DPP spec is a bit more permissive in that it says 'If both sides 
> have a user interface'.  But I think the intent is for the shared code 
> to be regenerated on each attempt.
> 
>>
>> "shall use a fresh code each time and the same code shall not be used 
>> with different Peers"
>>
>> So we don't have to put it in the config file if you don't want to. 
>> Auto-generation just won't work for my purposes since I have no way of 
>> sharing that on a headless device, so if that's a must I'd have to do 
>> some thinking...
> 
> Fair enough, lets explore whether we can provide this via some agent API.

Reading more about the identifier being used to distinguish a "plurality 
of devices" this is what I'm thinking as far as the agent interaction:

It would make sense (on the configurator side) to query an agent _after_ 
the enrollee sends the PKEX exchange request. That way the configurator 
can look up the identifier/code, somewhat the same as RequestUserPassword.

I don't see much benefit of using an agent in StartEnrollee(), and would 
rather pass via the DBus arguments for simplicity. Adding an agent for 
this doesn't really gain us anything, it just adds complexity. The 
caller of the API can still change the code/id for each call it makes to 
StartEnrollee() as it sees fit.

So something like:

StartConfigurator()
     ... waits for PKEX exchange request ...
     -> RX PKEX exchange request
         if (id)
             Agent.RequestUserPassword(id)
         else
             Agent.RequestPassphrase()

(And if we want "SharedCode" Agent APIs, that's fine, these just fit the 
need)

The one caveat here is the timing since the PKEX exchange response must 
come within 200ms, which isn't possible for a human user. A human 
configurator would need to establish the code/id completely ahead of time.

We could either:
   - Handle this from within iwctl and expect other higher level 
consumers of the API to do the same (when interacting with a human). 
I.e. ask the user ahead of time, create an agent, the call 
StartConfigurator().
   - Allow an a{sv} argument to StartConfigurator() which can be used to 
pre-load the dpp_sm with the code/id, or if empty query the agent.
   - Or if we wanted to go off-spec and e.g. wait 30 seconds for a 
response. But I'd rather not.

Thanks,
James

> 
>>
>> I'm fine with it as an argument to the StartConfigurator API. An agent 
>> could work but we've also got the optional identifier to think about. 
>> I'd prefer to use the existing agent API for getting a passphrase 
>> rather than a new method.
>>
> 
> But the identifier is not supposed to be secret?
> 
> Regards,
> -Denis
Denis Kenzior Oct. 24, 2023, 2:40 p.m. UTC | #14
Hi James,

On 10/23/23 08:49, James Prestwood wrote:
> Hi Denis,
> 
>>
>>>
>>> I'm fine with it as an argument to the StartConfigurator API. An agent could 
>>> work but we've also got the optional identifier to think about. I'd prefer to 
>>> use the existing agent API for getting a passphrase rather than a new method.
>>>
>>
>> But the identifier is not supposed to be secret?
> 
> No, the identifier is sent plaintext:
> 
> "Optionally, a non-secret identifier for the code can be transmitted to support 
> the case where a PKEX implementation may be provisioned to connect to a 
> plurality of devices and needs to know which code to use to process a received 
> PKEX frame. If an optional code identifier is used, it shall be a UTF-8 string 
> not greater than eighty (80) octets that is provisioned at the same time as the 
> shared code."
> 

Right.  Basically a unique identifier of some sort so a shared code can be 
looked up from a set.

Regards,
-Denis
Denis Kenzior Oct. 24, 2023, 3:03 p.m. UTC | #15
Hi James,

>>
>> Fair enough, lets explore whether we can provide this via some agent API.
> 
> Reading more about the identifier being used to distinguish a "plurality of 
> devices" this is what I'm thinking as far as the agent interaction:
> 
> It would make sense (on the configurator side) to query an agent _after_ the 
> enrollee sends the PKEX exchange request. That way the configurator can look up 
> the identifier/code, somewhat the same as RequestUserPassword.

Possible.  But isn't the main use case to share the code and initiate on both 
sides independently?

So..
ConfiguratorEnrollee(code, identifier)
StartEnrollee(code, identifier)

> 
> I don't see much benefit of using an agent in StartEnrollee(), and would rather 
> pass via the DBus arguments for simplicity. Adding an agent for this doesn't 
> really gain us anything, it just adds complexity. The caller of the API can 
> still change the code/id for each call it makes to StartEnrollee() as it sees fit.

Okay, sounds fair.

> 
> So something like:
> 
> StartConfigurator()
>      ... waits for PKEX exchange request ...
>      -> RX PKEX exchange request
>          if (id)
>              Agent.RequestUserPassword(id)
>          else
>              Agent.RequestPassphrase()
> 
> (And if we want "SharedCode" Agent APIs, that's fine, these just fit the need)
> 
> The one caveat here is the timing since the PKEX exchange response must come 
> within 200ms, which isn't possible for a human user. A human configurator would 
> need to establish the code/id completely ahead of time.
Well, that's why it says to retransmit 5 times.  But even then, that isn't 
enough time for a human to process this.  Hence my point above, that the 
use-case seems geared towards both sides entering the shared code without any 
'trigger' from the peer.

What you propose here is using the Agent, but only for as a way to machine 
generated a response.  Sounds like maybe:

StartConfigurator(object shared_code_agent_path)?

Regards,
-Denis
James Prestwood Oct. 24, 2023, 3:19 p.m. UTC | #16
Hi Denis,

On 10/24/23 8:03 AM, Denis Kenzior wrote:
> Hi James,
> 
>>>
>>> Fair enough, lets explore whether we can provide this via some agent 
>>> API.
>>
>> Reading more about the identifier being used to distinguish a 
>> "plurality of devices" this is what I'm thinking as far as the agent 
>> interaction:
>>
>> It would make sense (on the configurator side) to query an agent 
>> _after_ the enrollee sends the PKEX exchange request. That way the 
>> configurator can look up the identifier/code, somewhat the same as 
>> RequestUserPassword.
> 
> Possible.  But isn't the main use case to share the code and initiate on 
> both sides independently?

That's kinda what I originally thought but the quote

"where a PKEX implementation may be provisioned to connect to a 
plurality of devices and needs to know which code to use to process a 
received PKEX frame"

Makes it seem like the implementation can lookup a code based on an 
identifier after receiving a frame. Like you mentioned, only a machine 
could do this while adhering to the spec so, eh? who knows what they 
intend here...

I'd prefer to support this because it allows a unique exchange 
per-device (assuming each device sends a unique ID). Obviously, also 
support the human case, maybe two configure APIs?

ConfigureEnrollee(code, identifier)
(Though we have to make the identifier optional, either via a{sv} or an 
empty string)

StartConfigurator(object agent_path)

> 
> So..
> ConfiguratorEnrollee(code, identifier)
> StartEnrollee(code, identifier)
> 
>>
>> I don't see much benefit of using an agent in StartEnrollee(), and 
>> would rather pass via the DBus arguments for simplicity. Adding an 
>> agent for this doesn't really gain us anything, it just adds 
>> complexity. The caller of the API can still change the code/id for 
>> each call it makes to StartEnrollee() as it sees fit.
> 
> Okay, sounds fair.
> 
>>
>> So something like:
>>
>> StartConfigurator()
>>      ... waits for PKEX exchange request ...
>>      -> RX PKEX exchange request
>>          if (id)
>>              Agent.RequestUserPassword(id)
>>          else
>>              Agent.RequestPassphrase()
>>
>> (And if we want "SharedCode" Agent APIs, that's fine, these just fit 
>> the need)
>>
>> The one caveat here is the timing since the PKEX exchange response 
>> must come within 200ms, which isn't possible for a human user. A human 
>> configurator would need to establish the code/id completely ahead of 
>> time.
> Well, that's why it says to retransmit 5 times.  But even then, that 
> isn't enough time for a human to process this.  Hence my point above, 
> that the use-case seems geared towards both sides entering the shared 
> code without any 'trigger' from the peer.
> 
> What you propose here is using the Agent, but only for as a way to 
> machine generated a response.  Sounds like maybe:
> 
> StartConfigurator(object shared_code_agent_path)?
> 
> Regards,
> -Denis
>
Denis Kenzior Oct. 25, 2023, 2:46 a.m. UTC | #17
Hi James,

> I'd prefer to support this because it allows a unique exchange per-device 
> (assuming each device sends a unique ID). Obviously, also support the human 
> case, maybe two configure APIs?
> 
> ConfigureEnrollee(code, identifier)
> (Though we have to make the identifier optional, either via a{sv} or an empty 
> string)

There's nothing stopping us from having two methods on the introspection, one 
with a single argument and one with two.  But if you want to use a dictionary, 
instead, that's also fine.

> 
> StartConfigurator(object agent_path)
> 

So pretty much what I proposed.  Sounds like we are ready for another (more 
formal) API proposal.

Regards,
-Denis
diff mbox series

Patch

diff --git a/doc/device-provisioning-api.txt b/doc/device-provisioning-api.txt
index ac204f46..4c0ecb28 100644
--- a/doc/device-provisioning-api.txt
+++ b/doc/device-provisioning-api.txt
@@ -71,3 +71,33 @@  Properties	boolean Started [readonly]
 
 			Indicates the DPP URI. This property is only available
 			when Started is true.
+
+
+Interface	net.connman.iwd.DeviceProvisioning [Experimental]
+Object path	/net/connman/iwd/{phy0,phy1,...}/{1,2,...}
+
+		StartConfigurator()
+			Start a PKEX configurator. IWD must be currently
+			connected to a BSS and have at least the
+			[Security].DeviceProvisioningSharedCode option set in
+			the network profile. An identifier can be set with
+			[Security].DeviceProvisioningIdentifier.
+
+			Possible errors:	net.connman.iwd.Busy
+						net.connman.iwd.NotConnected
+						net.connman.iwd.InvalidArguments
+						net.connman.iwd.NotConfigured
+
+		StartEnrollee(a{sv} args)
+			The 'args' dictionary contains parameters for the PKEX
+			enrollee.
+
+			string Key - The PKEX key. This is required and must
+			match the configurer's key.
+
+			string Identifier - The PKEX key identifier. This is
+			optional, but if used both the Configurer and enrollee
+			must use the same value.
+
+			Possible errors:	net.connman.iwd.Busy
+						net.connman.iwd.InvalidArguments
\ No newline at end of file