org.openuat.authentication
Class DHWithVerification

java.lang.Object
  extended by org.openuat.authentication.AuthenticationEventSender
      extended by org.openuat.authentication.DHWithVerification
Direct Known Subclasses:
RelateAuthenticationProtocol, ShakeWellBeforeUseProtocol1

public abstract class DHWithVerification
extends AuthenticationEventSender

This is an abstract class that implements the basics of all protocols based on Diffie-Hellman key exchange over streams with subsequent verification of the key material to check that it is equal on both sides. This verification is necessary to prevent man-in-the-middle attacks. Derived classed need to implement this specific check that the authentication key provided by SimpleKeyAgreement matches by implementing the method startVerification. Either this method can asynchronously start the verification step, i.e. not block the caller, or the internal KeyManager object can be used at any time to verify remote hosts that are in STATE_VERIFICATION. After the respective key verification procedure has been performed, the derived class should call either verificationSuccess or verificationFailure depending on the outcome of the check. Upon calling one of the methods, a status exchange with the remote host will be done over the communication channel to arrive at a common decision if the whole protocol succeeded. The final verdict will be signaled by emitting standard authentication events (as defined by AuthenticationProgressHandler) and by calling either the protocolSucceededHook or the protocolFailedHook function. In short, the whole authentication protocol should be used as follows: 1. Construct the object. Either: 2a. Start the server. This may be done via the startServer method offered by a subclass or another object that can accept incoming connections. Either way, this class's KeyManager instance must be registered to receive authentication events. 3b. Start an authentication protocol to a remote device by calling startAuthentication. This may be done explicitly or by a background process, as e.g. implemented by BluetoothOpportunisticConnector. Note that, when setting concurrentVerificationSupported=false, only one remote host can be in verified at the same time. 4. After the key agreement phase succeeded, the abstract startVerification method is called. In this method, derived classes may asynchronously start whatever is necessary to verify the provided shared authentication key. If not using this explicit event for immediately starting verification, derived classes can query the internal KeyManager component to verify hosts that are in STATE_VERIFICATION at opportune moments. 5. When a local decision about the key verification for a specific host has been made, call either verificationSucceess or verificationFailure. 6. The local decisions will be communicated over the communication channel and if both devices signaled success, the protocolSucceededHook will be called. In any other case (both or either of the devices signaled failure on verification), the protocolFailedHook will be called. Generally, events will be emitted by this class to all registered listeners.

Version:
1.5, changes to 1.4: now support Mana IV and MA-DH in addition to SimpleKeyAgreement as the basic key agreement protocol changes to 1.3: can now distinguish between hard and soft failure changes to 1.2: can now deal with arbitrary servers as long as they implement the new HostAuthenticationServer interface changes to 1.1: made independent of TCP, but provide a subclass with the same old interface; changes to 1.0: replaced InetAddress and Socket objects passed to events with String and RemoteConnection objects.
Author:
Rene Mayrhofer

Nested Class Summary
protected  class DHWithVerification.HostAuthenticationEventHandler
          A helper class for handling the events from KeyManager to forward failure and progress events.
protected  class DHWithVerification.StartVerificationHandler
          This helper class is only there for visibility purposes: it calls the outer class startVerificationAsync method with the arguments passed to its startVerification method.
 
Field Summary
protected  java.lang.String instanceId
          This may be set to distinguish multiple instances running on the same machine.
protected  KeyManager keyManager
          The key manager instance we are using to keep track of keys and states.
protected  HostAuthenticationServer server
          This represents the server component that reacts to incoming authentication requests.
protected  boolean useJSSE
          If set to true, the JSSE will be used, if set to false, the Bouncycastle Lightweight API.
 
Fields inherited from class org.openuat.authentication.AuthenticationEventSender
eventsHandlers
 
Constructor Summary
protected DHWithVerification(HostAuthenticationServer server, boolean keepConnectedOnSuccess, boolean keepConnectedOnFailure, boolean concurrentVerificationSupported, java.lang.String instanceId, boolean useJSSE)
          Construct the object by initializing basic variables.
 
Method Summary
protected  void authenticationFailed(boolean failHard, RemoteConnection remote, java.lang.Object optionalVerificationId, java.lang.Exception e, java.lang.String message)
          Small helper function to raise an authentication failure event and set state as well as wipe sharedKey.
 boolean isIdle()
          This method returns true if this object is idle or if it is currently running the authentication protocol with a remote host.
protected abstract  void protocolFailedHook(boolean failHard, RemoteConnection remote, java.lang.Object optionalVerificationId, java.lang.Exception e, java.lang.String message)
          This hook will be called when the whole authentication protocol has failed.
protected abstract  void protocolProgressHook(RemoteConnection remote, int cur, int max, java.lang.String message)
          This hook will be called when the whole authentication protocol has made some progress.
protected abstract  void protocolStartedHook(RemoteConnection remote)
          This hook will be called when the whole authentication protocol has been started.
protected abstract  void protocolSucceededHook(RemoteConnection remote, java.lang.Object optionalVerificationId, java.lang.String optionalParameterFromRemote, byte[] sharedSessionKey)
          This hook will be called when the final verdict is that the whole authentication protocol succeeded, i.e. both hosts signaled success on key verification.
protected  void reset(RemoteConnection remote)
          Resets the object to its idle state.
protected abstract  void resetHook(RemoteConnection remote)
          This hook will be called when the object is reset to its "idle" state, i.e. so that subsequent authentications can be performed.
 boolean startAuthentication(RemoteConnection remote, int protocolTimeoutMs, java.lang.String param)
          Starts the authentication protocol in the background.
 void startListening()
          This simply starts the server part so that it will listen for incoming authentication requests.
protected abstract  void startVerificationAsync(byte[] sharedAuthenticationKey, java.lang.String optionalParam, RemoteConnection toRemote)
          This method must be implemented by derived classes.
 void stopListening()
          This stops the server part.
protected  void verificationFailure(boolean failHard, RemoteConnection remote, java.lang.Object optionalVerificationId, java.lang.String optionalParameterToRemote, java.lang.Exception e, java.lang.String msg)
          This method should be called by derived classes after key verification has been started with the startVerification method.
protected  void verificationSuccess(RemoteConnection remote, java.lang.Object optionalVerificationId, java.lang.String optionalParameterToRemote)
          This method should be called by derived classes after key verification has been started with the startVerification method.
 
Methods inherited from class org.openuat.authentication.AuthenticationEventSender
addAuthenticationProgressHandler, raiseAuthenticationFailureEvent, raiseAuthenticationProgressEvent, raiseAuthenticationStartedEvent, raiseAuthenticationSuccessEvent, removeAuthenticationProgressHandler, setAuthenticationProgressHandlers
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

useJSSE

protected boolean useJSSE
If set to true, the JSSE will be used, if set to false, the Bouncycastle Lightweight API.


keyManager

protected KeyManager keyManager
The key manager instance we are using to keep track of keys and states. We don't support concurrent key verification with different hosts at this time. This may change in the future.


server

protected HostAuthenticationServer server
This represents the server component that reacts to incoming authentication requests.


instanceId

protected java.lang.String instanceId
This may be set to distinguish multiple instances running on the same machine.

Constructor Detail

DHWithVerification

protected DHWithVerification(HostAuthenticationServer server,
                             boolean keepConnectedOnSuccess,
                             boolean keepConnectedOnFailure,
                             boolean concurrentVerificationSupported,
                             java.lang.String instanceId,
                             boolean useJSSE)
Construct the object by initializing basic variables.

Parameters:
useJSSE - If set to true, the JSSE API with the default JCE provider of the JVM will be used for cryptographic operations. If set to false, an internal copy of the Bouncycastle Lightweight API classes will be used.
keepConnectedOnSuccess - If set to true, the opened client connection is passed to the authentication success event (in the results parameter) for further re-use of the connection (e.g. passing additional information about further protocol steps). If set to false, the socket will be closed when this protocol is done with it. The socket will always be closed on authentication failures unless keepConnectedOnFailure is also set to true. If in doubt, set to false.
keepConnectedOnFailure - If set to true, the opened client connected will not be closed even on high-level authentication failure (i.e. when the verificationFailure method is called by derived classes) to support graceful retry. If in doubt, set to false.
concurrentVerificationSupported - If set to false, then only one remote host can be in STATE_VERIFICATION at any time. This can be used when the sensor hardware used for key verification can only interact with one remote host at the same time.
server - The server implementation to use. This will be started by startListening and stopped by stopListening.
instanceId - This parameter may be used to distinguish different instances of this class running on the same machine. It will be used in logging and error messages. May be set to null.
Method Detail

startListening

public void startListening()
                    throws java.io.IOException
This simply starts the server part so that it will listen for incoming authentication requests.

Throws:
java.io.IOException

stopListening

public void stopListening()
This stops the server part.


isIdle

public boolean isIdle()
This method returns true if this object is idle or if it is currently running the authentication protocol with a remote host. Callers should check that it is idle before calling startAuthentication, because only one protocol can be run at a time (this might change in the future at least for the host authentication phase, but right now, we only accept new authentication runs to be started when idle).

Returns:
true when the object is idle, i.e. when a new authentication can be started.

startAuthentication

public boolean startAuthentication(RemoteConnection remote,
                                   int protocolTimeoutMs,
                                   java.lang.String param)
                            throws java.io.IOException
Starts the authentication protocol in the background. Listeners should subscribe to authentication events to get notified about the progress of authentication.

Parameters:
remote - An already open connection to the remote host.
param - An optional parameter that should be exchanged with the host, usually describing some parameter(s) of the subsequent verification step.
protocolTimeoutMs - The maximum duration in milliseconds that this authentication protocol may take before it will abort with an AuthenticationFailed exception. Set to -1 to disable the timeout.
Returns:
true if the authentication could be started, false otherwise.
Throws:
java.io.IOException
See Also:
AuthenticationEventSender.addAuthenticationProgressHandler(org.openuat.authentication.AuthenticationProgressHandler)

reset

protected void reset(RemoteConnection remote)
Resets the object to its idle state. After calling reset, incoming as well as outgoing authentication protocol runs are again possible.


authenticationFailed

protected void authenticationFailed(boolean failHard,
                                    RemoteConnection remote,
                                    java.lang.Object optionalVerificationId,
                                    java.lang.Exception e,
                                    java.lang.String message)
Small helper function to raise an authentication failure event and set state as well as wipe sharedKey.

Parameters:
failHard - If true, then the protocol has failed hard, meaning that there can be no retry without another key agreement protocol run. Key material shoud be be wiped. If false, only a soft failure occured, meaning that the connection should be closed, but key material should not be wiped yet. Retrying key verification (i.e. authenticating the key agreement) should be possible.
remote - The remote device with which the authentication failed.
optionalVerificationId - If the key verification step yielded any ID or reference that can be referred to, this should be set by the derived class.
e - If not null, the exception describing the failure.
message - If not null, the message describing the failure.

verificationSuccess

protected void verificationSuccess(RemoteConnection remote,
                                   java.lang.Object optionalVerificationId,
                                   java.lang.String optionalParameterToRemote)
This method should be called by derived classes after key verification has been started with the startVerification method. Calling this method signals a local success of the key verification, but the whole authentication protocol can still fail when the other host signals a failure. After calling this method, either the protocolSucceededHook or the protocolFailedHook will be called.

Parameters:
remote - The remote host which has been successfully verified.
optionalVerificationId - If the key verification step yielded any ID or reference that can be referred to, this should be set by the derived class.
optionalParameterToRemote - An optional parameter that should be sent to the remote device alongside the success status message. This will also be forwarded to the hook functions.
-

verificationFailure

protected void verificationFailure(boolean failHard,
                                   RemoteConnection remote,
                                   java.lang.Object optionalVerificationId,
                                   java.lang.String optionalParameterToRemote,
                                   java.lang.Exception e,
                                   java.lang.String msg)
This method should be called by derived classes after key verification has been started with the startVerification method. Calling this method signals a local failure of the key verification, so the whole authentication protocol must fail (it can only succeed when both hosts signal success). After calling this method, the protocolFailedHook will be called.

Parameters:
remote - The remote host which could not be verified.
optionalVerificationId - If the key verification step yielded any ID or reference that can be referred to, this should be set by the derived class.
optionalParameterToRemote - An optional parameter that should be sent to the remote device alongside the success status message. This will also be forwarded to the hook function.

startVerificationAsync

protected abstract void startVerificationAsync(byte[] sharedAuthenticationKey,
                                               java.lang.String optionalParam,
                                               RemoteConnection toRemote)
This method must be implemented by derived classes. It should start the verification of the shared key to make sure that the other host shared the same and thus rule out man-in-the-middle attacks during the Diffie-Hellman key agreement.

Parameters:
sharedAuthenticationKey - This key should be verified to be equal on both sides.
optionalParam - Optional parameters sent by the remote host during the key agreement phase.
socketToRemote - This socket is still open and can be used to communicate with the remote host for verifying the authentication key. When it is used, care must be taken not to consume any bytes from the remote end that are not expected during verification, because the same channel will be used for exchanging status information about the success or failure of the whole authentication protocol.

resetHook

protected abstract void resetHook(RemoteConnection remote)
This hook will be called when the object is reset to its "idle" state, i.e. so that subsequent authentications can be performed. Derived classes should implement it to react to being reset. A reset of the object will occur after both failure and after success of the whole authentication protocol.


protocolSucceededHook

protected abstract void protocolSucceededHook(RemoteConnection remote,
                                              java.lang.Object optionalVerificationId,
                                              java.lang.String optionalParameterFromRemote,
                                              byte[] sharedSessionKey)
This hook will be called when the final verdict is that the whole authentication protocol succeeded, i.e. both hosts signaled success on key verification.

Parameters:
remote - The remote host with which the key exchange succeeded. If it has not been requested that the connection should stay open (keepConnectedOnSuccess==true), then this will be closed immediately after the hook method returns.
optionalVerificationId - If the key verification step yielded any ID or reference that can be referred to, then this will be set. It is directly forwarded through from the call to verificationSuccess.
optionalParameterFromRemote - If the remote device reported an additional parameter with its success message, it will be put into this parameter. May be null.
sharedSessionKey - The shared session key (which is different from the shared authentication key used for verification) that can now be used for subsequent secure communication.

protocolFailedHook

protected abstract void protocolFailedHook(boolean failHard,
                                           RemoteConnection remote,
                                           java.lang.Object optionalVerificationId,
                                           java.lang.Exception e,
                                           java.lang.String message)
This hook will be called when the whole authentication protocol has failed. Derived classes should implement it to react to this failure.

Parameters:
failHard - If true, then the protocol has failed hard, meaning that there can be no retry without another key agreement protocol run. Key material will be wiped after this hook returns. If false, only a soft failure occurred, meaning that the connection will be closed, but key material will not be wiped yet. Retrying key verification (i.e. authenticating the key agreement) will be possible.
remote - The remote host with which the key exchange failed. If it has not been requested that the connection should stay open (keepConnectedOnFailure==true), then this will be closed immediately after the hook method returns.
optionalVerificationId - If the key verification step yielded any ID or reference that can be referred to, then this will be set. It is directly forwarded through from the call to verificationSuccess or verificationFailed. If the protocol already failed during key agreement (or the derived class did not set the parameter), then this will be null.
e - If not null, the exception describing the failure.
message - If not null, the message describing the failure.

protocolProgressHook

protected abstract void protocolProgressHook(RemoteConnection remote,
                                             int cur,
                                             int max,
                                             java.lang.String message)
This hook will be called when the whole authentication protocol has made some progress. Derived classes should implement it to react to this progress.

Parameters:
remote - The remote host with which the key exchange progressed.
cur - @see AuthenticationProgressHandler#AuthenticationProgress
max - @see AuthenticationProgressHandler#AuthenticationProgress
message - @see AuthenticationProgressHandler#AuthenticationProgress

protocolStartedHook

protected abstract void protocolStartedHook(RemoteConnection remote)
This hook will be called when the whole authentication protocol has been started. Derived classes should implement it to react to this progress.

Parameters:
remote - The remote host with which the key exchange started.


2005-2009, Rene Mayrhofer.