Skip to content
New issue

Have a question about this project? 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

Reg. Coap Server using Scandium #362

Closed
lakshT opened this issue Jul 25, 2017 · 30 comments
Closed

Reg. Coap Server using Scandium #362

lakshT opened this issue Jul 25, 2017 · 30 comments

Comments

@lakshT
Copy link

lakshT commented Jul 25, 2017

Hi,

Is there a way to extract information at server end from a client certificate sent to the server during a handshake. I've been referring to cf-secure but couldn't find a way out. Can you please help.

Thanks

@AlexITC
Copy link
Contributor

AlexITC commented Jul 25, 2017

as far as I know, there is no way, we required something similar and ended up implementing it by our selves (thought we are using an old version, so hopefully there is a way in the current one).

@boaks
Copy link
Contributor

boaks commented Jul 25, 2017

Currently (1.0, 1.1, 2.0) there is a "sender principal" in incoming request.

There are plans to extend that for other messages as well as for outgoing messages.
The one plan is to introduce a "endpoint identifier" with a "converter factory" (see PR #322) and the other one is to use the currently available artefacts (Principal and CorrelationContext) generally for Message (incoming and outgoing). There was a long discussion in issue #344 about that.

Unfortunately, I'm currently busy with the "transparent blockwise" and it will take some time to provide a PR, which shows, how a generally usage of the available artefacts will work.

See also issue:
#174
#104

@sophokles73
Copy link
Contributor

@lakshT what kind of information do you want to extract/get access to?

@boaks
Copy link
Contributor

boaks commented Jul 25, 2017

@OverRide
public void handleGET(CoapExchange exchange) {
exchange.advanced().getRequest().getSenderIdentity();
exchange.respond(ResponseCode.CONTENT, "hello security");
}

in cf-secure / SecureServer you can access the principal as above. See the different implementations of Principal to see how to get the details.

@AlexITC
Copy link
Contributor

AlexITC commented Jul 25, 2017

@boaks how would you access the X509 certificate?

@boaks
Copy link
Contributor

boaks commented Jul 25, 2017

FMPOV, the X.509 certificate chain of the client is only used, when you evaluate the trust. After the certificate is trusted, the DN should do it.
So, is your idea, to just trust the client certificate and later validate the certificate on your own?

@AlexITC
Copy link
Contributor

AlexITC commented Jul 25, 2017

@boaks that's what we are doing, another use case would be to validate the certificate and keep the information to use it for another purpose later.

@boaks
Copy link
Contributor

boaks commented Jul 25, 2017

So I would say, a "trust callback" extension will do it for the first use case.
If you checkout the 2.0 branch, the new X509CertPath may help, if you convert it to byte[] and read in the CertPath again.

CertificateFactory factory = CertificateFactory.getInstance(TYPE_X509);
CertPath certPath = factory.generateCertPath(new ByteArrayInputStream(encodedPath), "PkiPath");

(I'm not sure, why there is no accessor for the target.)

@boaks
Copy link
Contributor

boaks commented Jul 25, 2017

Issue #301 is also requesting more flexibility in the credentials management. We will see, when we can implement it.

@lakshT
Copy link
Author

lakshT commented Jul 25, 2017

@sophokles73 I would like to access SubjectDN from the client's certificate at server end.

@AlexITC
Copy link
Contributor

AlexITC commented Jul 25, 2017

@lakshT our solution could help you, basically you need to modify the source code to attach the certificate to CoAP Request, then you could get the subject related fields, you could try it or hopefully we will upload a pool request soon.

@lakshT
Copy link
Author

lakshT commented Jul 25, 2017

@AlexITC Do you mean to say that certificate goes in the body of every request or a method needs to be added for Request class, something like addCertificate(....) ?

@AlexITC
Copy link
Contributor

AlexITC commented Jul 25, 2017

@lakshT it goes something like this, CoAP ServerHandshaker receives the client certificate, you could modify it to store the peer certificate in the session, then using CoAP endpoint, you could get the certificate from the session and store it in the Request.

@sophokles73
Copy link
Contributor

@lakshT if you just want to access the subject DN then simply invoke the Principal.getName() method on the principal returned by org.eclipse.californium.core.coap.Request.getSenderIdentity().

If the client has been authenticated via DTLS using an X509 certificate, then the principal returned by getSenderIdentity will be of type org.eclipse.californium.scandium.auth.X509CertPath, which returns the certificate's subject DN as the result of getName().

@boaks
Copy link
Contributor

boaks commented Jul 26, 2017

@lakshT

#362 (comment)

See the different implementations of Principal to see how to get the details.

Depending on the californium version you use, you may get different Principal implementations (based on different credential data).
I wouldn't say, that it is a good idea, to stick on such Principal implementation details or credential details.

@lakshT
Copy link
Author

lakshT commented Jul 27, 2017

@sophokles73 I'm using X509 certificate. The principal which is returned by getSenderIdentity in my implementation is of the type org.eclipse.californium.scandium.auth.RawPublicKeyIdentity. Do you have an any idea what could I be doing wrong in my implementation?
I'm using version 1.1.0-SNAPSHOT.

@lakshT
Copy link
Author

lakshT commented Jul 27, 2017

@boaks
What I'm trying to achieve is that once the handshake is done, the client would send requests to the server. At the server I am looking for some kind of client identifier(if not the complete certificate) so as to process the payload.
Can you suggest something?

@sophokles73
Copy link
Contributor

@lakshT, if you are ok to use a non-released version then I would suggest that you use 2.0.0-SNAPSHOT instead of 1.1.0-SNAPSHOT. We currently do not have any plans to do a 1.1.0 release.

Regarding your issue with the Principal. Your server and/or client seems to be configured to use RawPublicKeys instead of X.509 certificates for client authentication. The difference between X.509 and RawPublicKey authentication is that you need to establish a trust relationship between client and server out-of-band because there is no way for the server to establish a certificate chain to the its trust anchor for the RawPublicKey provided by the client. The RawPublicKeyIdentity.getName() method returns a named information URI according to http://tools.ietf.org/html/rfc6920#section-2 which can be used to uniquely identify and refer to the RawPublicKey. If you are interested in the subject DN contained in the key, you can invoke RawPublicKeyIdentity.getSubjectInfo() and recreate a java.security.PublicKey from it using an appropriate KeyFactory. However, if I were you, I would rather design my identity management around the named information URIs returned by getName() instead of the subject DNs if you want your clients to use RawPublicKeys.

@boaks
Copy link
Contributor

boaks commented Jul 27, 2017

At the server I am looking for some kind of client identifier(if not the complete certificate) so as to process the payload.

The easiest way is add your client identification either to the "payload" or to some coap options (e.g. URI Query "name=temprature1").
As I wrote above, currently only the requests carries the sender identity. If that is sufficient, you could use the getName() as mentioned above.

@lakshT
Copy link
Author

lakshT commented Jul 31, 2017

@sophokles73 I have been following code from cf-secure to write my client and server. I think that it uses RawPublicKeys. Is there any example code which uses X.509 certificates instead?

And I am designing a light weight application for small IoT devices. Would it be better to use RawPublicKeys over X.509 certificates? I would really appreciate any suggestions.

@sophokles73
Copy link
Contributor

The cf-secure client configures the DTLS layer to use RawPublicKeys by means of

...
DtlsConnectorConfig.Builder builder = new DtlsConnectorConfig.Builder();
builder.setPskStore(new StaticPskStore("Client_identity", "secretPSK".getBytes()));
builder.setIdentity((PrivateKey)keyStore.getKey("client", KEY_STORE_PASSWORD.toCharArray()),
	keyStore.getCertificateChain("client"), true);
builder.setTrustStore(trustedCertificates);
dtlsConnector = new DTLSConnector(builder.build());
...

It already uses the client certificate from the key store but is configured to send only the RawPublicKey from the certificate for authentication.
If you want to use X.509 based authentication of the client then you simply need to replace

builder.setIdentity((PrivateKey)keyStore.getKey("client", KEY_STORE_PASSWORD.toCharArray()),
	keyStore.getCertificateChain("client"), true);

with

builder.setIdentity((PrivateKey)keyStore.getKey("client", KEY_STORE_PASSWORD.toCharArray()),
	keyStore.getCertificateChain("client"), false);

i.e. replace the true param with false.

Be aware that many (most?) constrained devices have a hard time doing an X.509 based handshake (in particular when using RSA instead of EC based keys) simply because of the CPU and memory constraints these devices usually are designed with. Such a handshake easily takes up to 30 -50 seconds, depending on the hardware platform at hand.

Most projects I am aware of therefore use PSK based cipher suites instead, i.e. a kind of username/password based approach which puts much less burden on the device during the handshake. RawPublicKey could probably considered to lie somewhere in between, be aware, though that the server needs to establish a trust relationship with the device in an out of band fashion, similar to PSK based approaches, because there is no way the server can establish a chain-of-trust up to its trust anchors ...

@lakshT
Copy link
Author

lakshT commented Aug 1, 2017

@sophokles73 Thanks for your suggestions.

I changed the boolean parameter to true in setIdentity method in both client and server code. Now when the handshake occurs, it terminates in the middle and I get the message

INFO: Aborting handshake with peer [/127.0.0.1:40140]: Certificate chain could not be validated

I'm using the script provided with demo certs to create my own certificates and using the cf-secure code for the handshake. The validity of certificates created seems to be till 24th August 2017. What could be going wrong here?

@sophokles73
Copy link
Contributor

Can you please first validate if everything works as expected when you use the provided demo certificates and keys?

@lakshT
Copy link
Author

lakshT commented Aug 1, 2017

I tired with demo certificates and keys, I got the same error message.

@sophokles73
Copy link
Contributor

which version of Cf are you using?

@lakshT
Copy link
Author

lakshT commented Aug 1, 2017

Its, 2.0.0-SNAPSHOT.

@sophokles73
Copy link
Contributor

I have taken a look, it seems you have discovered a bug :-) I also think that I know what the problem is.
Can you open an issue for this so that we can properly track and fix it?

Thanks,
Kai

@lakshT
Copy link
Author

lakshT commented Aug 1, 2017

Sure, I'll open an issue.
Thanks.

@AlexITC
Copy link
Contributor

AlexITC commented Aug 4, 2017

@lakshT you could take a look to #374, using that code you could recover the client's certificate chain calling Request#getCertPath(), that should allow you to do what you wanted.

@sophokles73
Copy link
Contributor

@lakshT is this still an issue for you? If not, can you close the issue?

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

No branches or pull requests

4 participants