8000 Access for peer credentials from initial DTLS connection to later phases · Issue #861 · eclipse-leshan/leshan · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Access for peer credentials from initial DTLS connection to later phases #861

New issue

Have a question about this project 8000 ? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
dachaac opened this issue Jul 8, 2020 · 11 comments
Closed

Comments

@dachaac
Copy link
Contributor
dachaac commented Jul 8, 2020

In order to support deployments with automated device registration during device bootstrapping one needs to have access to TLS Client Certificate detail in order to approve auto registration.

Due to nature of bootstrapping process with the need to support different kind of authentication methods this decision cannot be made at time when DTLS is first validated but needs to be carried later so that rule based analysis can be performed by bootstrap service.

This is also required in for the EST support: #859

@dachaac
Copy link
Contributor Author
dachaac commented Jul 8, 2020

This seems to be most challening problem to solve as it touched quite a many places. An advice is asked where to store this properly.

To get forward I have added it to Identity class but that kind feels incorrect but then again feels only place it could be placed:

As:

    /**
     * Note: peerCertificate is only needed during runtime (transient) and does not need to be serialized.
     */
    private final transient X509Certificate peerCertificate;
    /**
     * Note: peerCertPath is only needed during runtime (transient) and does not need to be serialized.
     */
    private final transient CertPath peerCertPath;

@sbernard31
Copy link
Contributor

I'm not sure to get the point. Could you explain this a bit more maybe with an exemple or point me some code where this is used ?

@dachaac
Copy link
Contributor Author
dachaac commented Jul 8, 2020

I am currently having a workout with test suite after some changes so not everything is nice and tidy yet... but just pushed by local version here:
https://github.com/dachaac/leshan/commits/est-support

Perhaps most related points are:

Those declarations are in here:
dachaac@d11067a#diff-8040b506e90c042422eaf1be4805f9e2R39

Capturing of the peer credentials:
dachaac@d11067a#diff-286c42661669116cbe1fdeec53ea4080R72

Then in here I think the actual checking if device is allowed in or not (still needs work):
dachaac@d11067a#diff-e6d76e95d80a1d82c3aed465e374e89fR47

More or less the changes all around are somehow related to this :|

One part of the changes is related to getting trust store a bit more configurable so that this information can be used later.

Code flow kinda happens something like this:

  • Client connects to server
  • Server gets new DTLS connection but cannot do PKIX validation in normal point as there is a need to support other authentication types AND we need Endpoint client name also in the play and that we receive in LWM2M protocol level later on.
  • If x509 client certificate is provided by the client it and its chain is recorded in Identity class
  • Then code goes forward where it we start to actually check that is client allowed in or not
  • In future in this point there would be analysis on certificate chain and some rules to in example allow auto-registration of client.

@sbernard31
Copy link
Contributor

Then in here I think the actual checking if device is allowed in or not (still needs work):
dachaac/leshan@d11067a#diff-e6d76e95d80a1d82c3aed465e374e89fR47

The API will depends a lot of what we want to do here. (This is the part which is not clear to me)

My vision is that DTLS layer ensure authentication. It ensure that the device is really who it pretends to be, then at LWM2M layer we only have the DTLS Identity.

Adding the whole certificate + certificates chain in Identity could be OK to me. (This maybe brings more flexibility)
But If we need less we can maybe find a better abstraction. E.G. maybe we don't need the whole certificate but just the whole Subject DN ?

I don't know if you aware about this class CertificateVerifier but this could also be a good place for PKIX validation. (We need to define which part of PKIX validation must be done in CertificateVerifier and which part should be done in SecurityChecker)

@dachaac
Copy link
Contributor Author
dachaac commented Jul 10, 2020

Then in here I think the actual checking if device is allowed in or not (still needs work):
dachaac/leshan@d11067a#diff-e6d76e95d80a1d82c3aed465e374e89fR47

The API will depends a lot of what we want to do here. (This is the part which is not clear to me)

My vision is that DTLS layer ensure authentication. It ensure that the device is really who it pretends to be, then at LWM2M layer we only have the DTLS Identity.

Adding the whole certificate + certificates chain in Identity could be OK to me. (This maybe brings more flexibility)
But If we need less we can maybe find a better abstraction. E.G. maybe we don't need the whole certificate but just the whole Subject DN ?

For normal TLS Server Certificates where there is server location in Subject DN's CN field or in Subject Alternative Name then just having a list of trusted Root CA's is enough. There is set of rules that just need to be matched and we are fine.

But the TLS Client Certificate is rather problematic in sense of validating when certificate can be considered valid. It does not have source location (as that varies). When there is only one Root CA and one knows how that is managed then you could just trust in Certrificate Serial Number, or in additional OID in extended key usage, or Subject DN., and/or some other certificate details. How to build identity from here is a rather good question. In theory it is the whole certificate (and its chain).

As an example I have seen machine certificates where subject DN was empty and then in Subject Alternative Name had information. So this is completely up to PKI admin of particular Root CA to decide how things are done there. While this gives flexibility for systems operations it gives headache for anyone using the system. Some standard (or at least limited number of differences) would be really nice for this.

Now if we have multiple root CA's in picture this gets a bit messy. All those different Root CA's might behave differently.

So far the best idea I have had is that once we know the Root CA for the connecting client we can assign a policy for that Root CA. Policy might be rule set how to interpret the TLS Client Certificate and Endpoint Client Name.

If we consider bootstrapping service that can have multiple Manufacturer Root CA's registered and then force client to transition to TLS Client Certificate that is service managed (issued under Service Specific Root CA) then we kinda have complexity only in bootstrapping phase and rest of the services could just trust in Subject DN field (or so). This forced transition works for both Certificate mode and EST mode.

Now this leads us back to question to what information do we need in what phase.

I believe that in DTLS phase we have list of Root CA's so that we can verify that when client does TLS Client Certificate Authentication then it must be issued by one of those Root CA's. BUT we need to carry out this Root CA issuer information (or policy information) forward somehow so that we can then look in LWM2M protocol level whether the client is actually allowed in or not.

LWM2M Specification states following about Endpoint Client Name:

This specification recommends, but does not mandate, transmission of the endpoint client name in the BootstrapRequest and in the Register message. Since the endpoint client name is not authenticated at the application layer the
LwM2M Server MUST compare the received endpoint client name identifier with the identifier used at the TLS/DTLS
handshake. This comparison may either be an equality match or may involve a dedicated lookup table to ensure that
LwM2M Clients cannot intentionally or due to misconfiguration impersonate other LwM2M Clients. The LwM2M Server
MUST respond with a "4.00 Bad Request" to the LwM2M Client if these fields do not match.

Most important part here I believe is This comparison may either be an equality match or may involve a dedicated lookup table to ensure that LwM2M Clients cannot intentionally or due to misconfiguration impersonate other LwM2M Clients.. Meaning that if the Endpoint Client Name is somehow trusted in LWM2M service it must be verified. What I have seen so far is that Endpoint Client Name's value is used as identifier in services -- so I suppose the goal should be that the Endpoint Client Name is unique in the service.

Now in context of Leshan as it is a library for making a LWM2M software it is a bit more complex as there might be different needs in different implementors. For this reason I was thinking that if we pass whole certificate chain forward it allows one to do system of their liking.

Now for the wish of having a standard way for TLS Client Certificate there seems to be several references in RFC's (like CoAP-EST) for IEEE Std 802.1AR-2018: Secure Device Identity standard. It also seems that IEEE Secure Device Identity just got a bit bigger as it seems to be now ISO/IEC/IEEE 8802-1AR:2020 (under paywall so I have not checked it out yet) giving it even more trustworthiness.

What I see good in IEEE Secure Device Identity standard is that it tells what kind of certificate one should be making. If device manufacturer would be following IDevID specification then job gets a bit easier. It says (in 8.6 subject) that:

A certificate’s subject and subjectAltName fields comprise a unique subject name that identifies the
entity (a device in DevID certificates, and a CA in DevID intermediate certificates) associated with the
public key in the subjectPublicKeyInfo field.
The DevID certificate subject field is always present, but can be empty. If non-null it contains an X.500
Distinguished Name (DN). An IDevID certificate subject field shall be non-null and should include a
unique device serial number encoded as the serialNumber attribute (RFC 5280 X520SerialNumber). In
the case of a third-party CA or a standards certification agency, the subject field can contain information
identifying the supplier or manufacturer of the device.
NOTE 1—As stated above, the recommended serialNumber is unique within the issuer’s (8.4) domain of significance,
not just within the context of precursor DN fields.

How I interpret this is that then:
Subject DN: /CN=MyProduct/serialNumber=P1234567 (and rest details is optional).

There are couple of things to think in here:

  • If we have multiple Manufacturer Root CA's registered -- there could still be collision as Subject DN field itself does not guarantee global uniqueness. When combined in context of certificate chain it becomes unique.
  • Now this is nice that there is clear definition what to do but encoding this to Endpoint Client Name is a bit problematic.

So once again we are having a problem what information from TLS Client Certificate we use and how it relates to Endpoint Client Name.

One solution for this is to recommend manufacturer if you manufacture your device with IEEE Secure Device Identity based IDevID then when doing LWM2M then send you Endpoint Client Name in certain format. What is good in this kind of operation is that there could be standard option -- mark this Manufacturer CA operating in IEEE Secure Device Identity mode. Eg. pre-existing policy/rule that can be selected.

Best idea so far that I have is utilizing dev-urn-ops form for Endpoint Client Name as that could be easily matched to certificate.

O == organization == enterprise OID (globally unique as there is registry -- and manufacturer knows their OID)
P == product == MyProduct
S == serial number == P1234567

So this would cause following sequence to happen:

  1. Device connects to LWM2M Bootstrap service using:
  • IDevID for DTLS connection
  • In LWM2M using Endpoint Client Name in dev-urn-ops form.
  1. LWM2M Bootstrap server then determines what policy is associated to Root CA which issued TLS Client Certificate.
  • If it is IEEE Secure Device Identity it looks up for associated Enterprise OID and verifies that Endpoint Client Name matches.
  • If it is "Globally Unique Subject DN's CN value" (eg. in case on dev-urn-imei or so) then it does simple compare.
  • <your rule/policy here>
  1. LWM2M Bootstrap server stores device identity to its device registry
  2. Next trick here is to go for Service Unique credentials -- LWM2M really should have feature to configure Endpoint Client Name from bootstrap server to client (probably should be proposed) but as a backup in system where Endpoint Client Name can be guarantee to be unique one could create TLS Client Certificate for device with endpoint client name in it that is signed under Service Specific Root CA. This works for both Certificate mode and for EST mode. I assume EST mode in this sequence.
  3. Device would create a CSR with Subject DN: /CN=<endpoint client name>.
  4. Device would connect to CoAP-EST service and authenticate itself with IDevID
  5. CoAP-EST service need to verify client's credentials now. It need to lookup based on certificate details on device registry so that it can determine what is expected Endpoint Client Name for the device.
  6. CoAP-EST service need to verify that CSR does include matching Endpoint Client Name
  7. CoAP-EST service could do some other CSR validation checks too in here
  8. CoAP-EST has now approved the CSR -> sends it to EST server for actual certificate creation.
  9. CoAP-EST received certificate from EST server and provides it to device.
  10. Device stores received certificate and associates it for this particular LWM2M service. (becomes Service Specific Device Certificate)
  11. Device connects with new Service Specific Device Certificate to LWM2M Server (which was configured in bootstrap phase).
  12. LWM2M Server only trusts X.509 Certificates under Service Specific Root CA and once passed it can do simple Subject DN's comparison against Endpoint Client Name.

I don't know if you aware about this class CertificateVerifier but this could also be a good place for PKIX validation. (We need to define which part of PKIX validation must be done in CertificateVerifier and which part should be done in SecurityChecker)

Both are needed. We need to do PKIX validation and then also look on the chain later.

@sbernard31
Copy link
Contributor
sbernard31 commented Jul 15, 2020

so I suppose the goal should be that the Endpoint Client Name is unique in the service.

This is mandatory : "The Endpoint Client Name identifier MUST be unique at the server or servers it is being used with." ( see 7.3.1. Endpoint Client Name)

For this reason I was thinking that if we pass whole certificate chain forward it allows one to do system of their liking.

We can do that even if for now I have still some doubts that some part of the certificate could really be useful at LWM2M level (e.g. Public Key)

LWM2M really should have feature to configure Endpoint Client Name from bootstrap server to client

As endpoint client name MUST be unique are you agree this is finally not needed ?

Both are needed. We need to do PKIX validation and then also look on the chain later.

Of course both are needed but maybe cert chain could only be used at DTLS/Scandium level using CertificateVerifier and ApplicationLevelInfoSupplier(eclipse-californium/californium#1014).
Because theoretically you have all the information necessary to retrieve the corresponding endpoint name in certificate :

  • either because the value is already present
  • or you have data needed to retrieve endpoint name though lookup table and you can store it principal via ApplicationLevelInfoSupplier.
    (It's a possibility, I don't know if this is the best choice)

(I will bring more feedback tomorrow)

@dachaac
Copy link
Contributor Author
dachaac commented Jul 16, 2020

About Endpoint Client Name.

In Core v1.1.1 - 7.3 there is:

Endpoint Client Name

String

Identifies the LwM2M Client on one LwM2M Server (including LwM2M Bootstrap-Server).

This parameter is optional and provided to the LwM2M Server during Registration, also provided to LwM2M
Bootstrap-Server when executing the Bootstrap procedure. It MUST be provided when the security protocol does
not provide an authenticated identifier or this information is not available for the server.
The Endpoint Client Name is a string. Recommended URI and URN formats are documented in Section Endpoint
Client Name
.

It says here that it is optional if security protocol provides authenticated identity. And for (D)TLS with X.509 TLS Client Certificate we do get authenticated identity from certificate itself (and from its chain) so in theory Endpoint Client Name cloud be omitted altogether.

Then in Core v1.1.1 - 7.3.1 is a bit more verbose on that but still contains the same information but adds:

This parameter MAY be omitted when the security protocol provides to the server an authenticated identifier that is identical to this parameter. For more discussion consult the security consideration section in the [LwM2M-TRANSPORT] specification.

And then in Transport v1.1.1 - 5.2.6 - Endpoint Client Name:

This specification recommends, but does not mandate, transmission of the endpoint client name in the Bootstrap-
Request and in the Register message. Since the endpoint client name is not authenticated at the application layer the
LwM2M Server MUST compare the received endpoint client name identifier with the identifier used at the TLS/DTLS
handshake. This comparison may either be an equality match or may involve a dedicated lookup table to ensure that
LwM2M Clients cannot intentionally or due to misconfiguration impersonate other LwM2M Clients.

Where as "comparison may either be an equality match or may involve a dedicated lookup table" gives freedom how X.509 certificate details shall be interpreted.

Based on those text I would interpret it as:

  • If Endpoint Client Name is presented it must be matched for the outer layer security credentials with equality match or with lookup/rule based matcher.
  • If Endpoint Client Name is missing it shall be copied/generated from outer layer security credentials with same rules.

And resulting in-memory object related to particular connection there should be Endpoint Client Name that can be used as unique device identity in context of particular LWM2M service.

Additional problem is that if same identity is given by different (Manufacturer) Root CA's which may require us to store also issuer information in the device registry on auto-registration cases so that another device does not have possibility to steal the identity.

If we do have PSK or Raw Public Key then it must be matched with pre-registered information stored in device registry. And then either take Endpoint Client Name from registry if missing or when provided then match that it matches what is in registry.

@dachaac
Copy link
Contributor Author
dachaac commented Jul 16, 2020

About X.509 Certificate Details.

I do not know what is the right amount of details to store in-memory and in device registry.

When one does auto-registration thru the bootstrapping then it might be good enough to store issuer information in addition to subject information.

Issuer information should be in format that can be matched to information in bootstrapping trust store.

In normal operations LWM2M Server should only have smaller service specific trust store only listing services own Service Specific Device Root CA where it is issuing device certificates. When device is later connecting back to bootstrapping service it must be possible to match DTLS TLS Client Certificate either to previously stored Manufacturer Root CA (in case of factory reset or so in the device) or to Service Specific Device Root CA used by service.

Issuer information and subject information are a bit problematic as subjectAlternativeName is also in picture. This is only problem for Manufacturer Root CA issued TLS Client Certificates and Service Specific Device Root CA issued certificates can have clean and easier contents.

If we can always do whole chain verification then in device registry we could store reference to Manufacturer's Root CA and then Endpoint Client Name as generated by rules or extracted from field in certificate itself.

About Public Key in X.509 Certificate -- we don't actually care about the value -- we trust in chain and it is used only in authenticating that client posesses associated private key and then in chain validation that it was really issued under by trusted root ca.

Haven't yet though if there is a need to store "next credentials" also in device registry. Like in case when device connects back to bootstrapping service to get new credentials while the old credentials are still valid. For X.509 certificates probably not needed as Endpoint Client Name should not be changing but might be needed for PSK/Raw Public Key cases.

There may be need to have different Bootstrapping credentials (pre-registration case) vs. Given credentials (given by bootstrapping service with security object).

@dachaac
Copy link
Contributor Author
dachaac commented Jul 16, 2020

Now about this ApplicationLevelInfoSupplier:

This might do the trick -- need to play more with it.

@sbernard31
Copy link
Contributor

You thought a lot about all of this and I must to confess that It's pretty hard to me to follow you. Probably because the problem is very vast and complex and there is also some terminology which is not so clear to me.

Maybe I'm wrong but is it possible that you try to achieve too many issues/use-cases at the same time.
Maybe we should start with the simpler use case (e.g: endpoint available in Subject DN), support/implement it.
Then identify the next one and trying to support it.
1 step at a time.

(knowing that we are in development phase for the 2.0.x, so it's OK to me to break API between 2 milestone releases )

@sbernard31
Copy link
Contributor

I think we can close this one.
This is related to #1135

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants
0