View Javadoc
1   package org.metricshub.ipmi.core.connection;
2   
3   /*-
4    * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
5    * IPMI Java Client
6    * ჻჻჻჻჻჻
7    * Copyright 2023 Verax Systems, MetricsHub
8    * ჻჻჻჻჻჻
9    * This program is free software: you can redistribute it and/or modify
10   * it under the terms of the GNU Lesser General Public License as
11   * published by the Free Software Foundation, either version 3 of the
12   * License, or (at your option) any later version.
13   *
14   * This program is distributed in the hope that it will be useful,
15   * but WITHOUT ANY WARRANTY; without even the implied warranty of
16   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   * GNU General Lesser Public License for more details.
18   *
19   * You should have received a copy of the GNU General Lesser Public
20   * License along with this program.  If not, see
21   * <http://www.gnu.org/licenses/lgpl-3.0.html>.
22   * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
23   */
24  
25  import org.metricshub.ipmi.core.coding.PayloadCoder;
26  import org.metricshub.ipmi.core.coding.commands.IpmiVersion;
27  import org.metricshub.ipmi.core.coding.commands.PrivilegeLevel;
28  import org.metricshub.ipmi.core.coding.commands.ResponseData;
29  import org.metricshub.ipmi.core.coding.commands.session.GetChannelAuthenticationCapabilitiesResponseData;
30  import org.metricshub.ipmi.core.coding.commands.session.GetChannelCipherSuitesResponseData;
31  import org.metricshub.ipmi.core.coding.commands.session.OpenSessionResponseData;
32  import org.metricshub.ipmi.core.coding.commands.session.Rakp1ResponseData;
33  import org.metricshub.ipmi.core.coding.commands.session.Rakp3ResponseData;
34  import org.metricshub.ipmi.core.coding.payload.IpmiPayload;
35  import org.metricshub.ipmi.core.coding.protocol.Ipmiv20Message;
36  import org.metricshub.ipmi.core.coding.protocol.PayloadType;
37  import org.metricshub.ipmi.core.coding.security.AuthenticationRakpHmacSha1;
38  import org.metricshub.ipmi.core.coding.security.CipherSuite;
39  import org.metricshub.ipmi.core.coding.security.ConfidentialityAesCbc128;
40  import org.metricshub.ipmi.core.coding.security.IntegrityHmacSha1_96;
41  import org.metricshub.ipmi.core.common.Constants;
42  import org.metricshub.ipmi.core.common.PropertiesManager;
43  import org.metricshub.ipmi.core.common.TypeConverter;
44  import org.metricshub.ipmi.core.sm.MachineObserver;
45  import org.metricshub.ipmi.core.sm.StateMachine;
46  import org.metricshub.ipmi.core.sm.actions.ErrorAction;
47  import org.metricshub.ipmi.core.sm.actions.GetSikAction;
48  import org.metricshub.ipmi.core.sm.actions.MessageAction;
49  import org.metricshub.ipmi.core.sm.actions.ResponseAction;
50  import org.metricshub.ipmi.core.sm.actions.StateMachineAction;
51  import org.metricshub.ipmi.core.sm.events.AuthenticationCapabilitiesReceived;
52  import org.metricshub.ipmi.core.sm.events.Authorize;
53  import org.metricshub.ipmi.core.sm.events.CloseSession;
54  import org.metricshub.ipmi.core.sm.events.Default;
55  import org.metricshub.ipmi.core.sm.events.DefaultAck;
56  import org.metricshub.ipmi.core.sm.events.GetChannelCipherSuitesPending;
57  import org.metricshub.ipmi.core.sm.events.OpenSessionAck;
58  import org.metricshub.ipmi.core.sm.events.Rakp2Ack;
59  import org.metricshub.ipmi.core.sm.events.StartSession;
60  import org.metricshub.ipmi.core.sm.events.Timeout;
61  import org.metricshub.ipmi.core.sm.states.Authcap;
62  import org.metricshub.ipmi.core.sm.states.Ciphers;
63  import org.metricshub.ipmi.core.sm.states.SessionValid;
64  import org.metricshub.ipmi.core.sm.states.Uninitialized;
65  import org.metricshub.ipmi.core.transport.Messenger;
66  
67  import org.slf4j.Logger;
68  import org.slf4j.LoggerFactory;
69  
70  import java.io.FileNotFoundException;
71  import java.io.IOException;
72  import java.net.InetAddress;
73  import java.util.ArrayList;
74  import java.util.EnumMap;
75  import java.util.List;
76  import java.util.Map;
77  import java.util.Timer;
78  import java.util.TimerTask;
79  import java.util.concurrent.atomic.AtomicInteger;
80  
81  /**
82   * A connection with the specific remote host.
83   */
84  public class Connection extends TimerTask implements MachineObserver {
85      private static final Logger logger = LoggerFactory.getLogger(Connection.class);
86  
87      private static final int DEFAULT_CIPHER_SUITE = 3;
88      private static final int SESSION_SEQUENCE_NUMBER_UPPER_BOUND = Integer.MAX_VALUE / 4;
89      private static final String ILLEGAL_CONNECTION_STATE_MESSAGE = "Illegal connection state: ";
90  
91      private List<ConnectionListener> listeners;
92      private StateMachine stateMachine;
93  
94      /**
95       * Time in ms after which a message times out.
96       */
97      private int timeout = -1;
98      private StateMachineAction lastAction;
99      private int sessionId;
100     private int managedSystemSessionId;
101     private byte[] sik;
102 
103     private int handle;
104 
105     public int getHandle() {
106         return handle;
107     }
108 
109     private Map<PayloadType, MessageHandler> messageHandlers;
110 
111     private Timer timer;
112 
113     private AtomicInteger currentSessionSequenceNumber;
114 
115     public int getTimeout() {
116         return timeout;
117     }
118 
119     public void setTimeout(int timeout) {
120         this.timeout = timeout;
121 
122         for (MessageHandler messageHandler : messageHandlers.values()) {
123             messageHandler.setTimeout(timeout);
124         }
125     }
126 
127     /**
128      * Creates the connection.
129      *
130      * @param messenger
131      *            - {@link Messenger} associated with the proper
132      *            {@link Constants#IPMI_PORT}
133      * @param handle
134      *            - id of the connection
135      */
136     public Connection(Messenger messenger, int handle) {
137         stateMachine = new StateMachine(messenger);
138         this.handle = handle;
139         listeners = new ArrayList<ConnectionListener>();
140         timeout = Integer.parseInt(PropertiesManager.getInstance().getProperty("timeout"));
141         messageHandlers = new EnumMap<PayloadType, MessageHandler>(PayloadType.class);
142         currentSessionSequenceNumber = new AtomicInteger(0);
143     }
144 
145     /**
146      * Registers the listener so it will receive notifications from this
147      * connection
148      *
149      * @param listener
150      *            - {@link ConnectionListener} to processResponse
151      */
152     public void registerListener(ConnectionListener listener) {
153         listeners.add(listener);
154     }
155 
156     /**
157      * Unregisters the {@link ConnectionListener}
158      *
159      * @param listener
160      *            {@link ConnectionListener} to unregister
161      */
162     public void unregisterListener(ConnectionListener listener) {
163         listeners.remove(listener);
164     }
165 
166     /**
167      * Starts the connection to the specified {@link InetAddress}
168      *
169      * @param address
170      *            - IP address of the managed system
171      * @param pingPeriod
172      *            - frequency of the no-op commands that will be sent to keep up
173      *            the session
174      * @throws IOException
175      *             - when properties file was not found
176      * @throws FileNotFoundException
177      *             - when properties file was not found
178      * @see #disconnect()
179      */
180     public void connect(InetAddress address, int port, long pingPeriod)
181             throws IOException {
182         connect(address, port, pingPeriod, false);
183     }
184 
185     /**
186      * Starts the connection to the specified {@link InetAddress}
187      * @param address
188      * - IP address of the managed system
189      * @param pingPeriod
190      * - frequency of the no-op commands that will be sent to keep up the session
191      * @param skipCiphers
192      * - determines if the getAvailableCipherSuites and getChannelAuthenticationCapabilities phases should be skipped
193      * @throws IOException
194      * - when properties file was not found
195      * @throws FileNotFoundException
196      * - when properties file was not found
197      * @see #disconnect()
198      */
199     public void connect(InetAddress address, int port, long pingPeriod, boolean skipCiphers) throws IOException {
200         MessageHandler ipmiMessageHandler = new IpmiMessageHandler(this, timeout);
201         messageHandlers.put(PayloadType.Ipmi, ipmiMessageHandler);
202 
203         MessageHandler solMessageHandler = new SolMessageHandler(this, timeout);
204         messageHandlers.put(PayloadType.Sol, solMessageHandler);
205 
206 		// If the pingPeriod greater than 0, start the timer otherwise don't start it
207 		// means that the connection won't be kept alive by sending no-op messages
208 		if (pingPeriod > 0) {
209 			timer = new Timer();
210 			timer.schedule(this, pingPeriod, pingPeriod);
211 		}
212 
213         stateMachine.register(this);
214         if (skipCiphers) {
215             stateMachine.start(address, port);
216             sessionId = SessionManager.generateSessionId();
217             stateMachine.setCurrent(new Authcap());
218         } else {
219             stateMachine.start(address, port);
220         }
221     }
222 
223     /**
224      * Ends the connection.
225      *
226      * @see #connect(InetAddress, int, int)
227      */
228     public void disconnect() {
229 		if (timer != null) {
230 			timer.cancel();
231 		}
232 
233         stateMachine.stop();
234 
235         for (MessageHandler messageHandler : messageHandlers.values()) {
236             messageHandler.tearDown();
237         }
238     }
239 
240     /**
241      * Checks if the connection is active
242      *
243      * @return true if the connection is active, false otherwise
244      *
245      * @see #connect(InetAddress, int, int)
246      * @see #disconnect()
247      */
248     public boolean isActive() {
249         return stateMachine.isActive();
250     }
251 
252     /**
253      * Gets from the managed system supported {@link CipherSuite}s. Should be
254      * performed only immediately after {@link #connect(InetAddress, int, int)}.
255      *
256      * @param tag
257      *            - the integer from range 0-63 to match request with response
258      *
259      * @return list of the {@link CipherSuite}s supported by the managed system.
260      * @throws ConnectionException
261      *             when connection is in the state that does not allow to
262      *             perform this operation.
263      * @throws Exception
264      *             when sending message to the managed system fails
265      */
266     public List<CipherSuite> getAvailableCipherSuites(int tag) throws Exception {
267 
268         if (stateMachine.getCurrent().getClass() != Uninitialized.class) {
269             throw new ConnectionException(ILLEGAL_CONNECTION_STATE_MESSAGE + stateMachine.getCurrent().getClass().getSimpleName());
270         }
271 
272         boolean process = true;
273 
274         ArrayList<byte[]> rawCipherSuites = new ArrayList<byte[]>();
275 
276         while (process) {
277 
278             lastAction = null;
279 
280             stateMachine.doTransition(new GetChannelCipherSuitesPending(tag));
281 
282             waitForResponse();
283 
284             ResponseAction action = (ResponseAction) lastAction;
285 
286             if (!(action.getIpmiResponseData() instanceof GetChannelCipherSuitesResponseData)) {
287                 stateMachine.doTransition(new Timeout());
288                 throw new ConnectionException(
289                         "Response data not matching Get Channel Cipher Suites command.");
290             }
291 
292             GetChannelCipherSuitesResponseData responseData = (GetChannelCipherSuitesResponseData) action
293                     .getIpmiResponseData();
294 
295             rawCipherSuites.add(responseData.getCipherSuiteData());
296 
297             if (responseData.getCipherSuiteData().length < 16) {
298                 process = false;
299             }
300         }
301 
302         stateMachine.doTransition(new DefaultAck());
303 
304         int length = 0;
305 
306         for (byte[] partial : rawCipherSuites) {
307             length += partial.length;
308         }
309 
310         byte[] csRaw = new byte[length];
311 
312         int index = 0;
313 
314         for (byte[] partial : rawCipherSuites) {
315             System.arraycopy(partial, 0, csRaw, index, partial.length);
316             index += partial.length;
317         }
318 
319         return CipherSuite.getCipherSuites(csRaw);
320     }
321 
322     private void waitForResponse() throws Exception {
323         int time = 0;
324 
325         while (time < timeout && lastAction == null) {
326             try {
327                 Thread.sleep(1);
328             } catch (InterruptedException e) {
329                 logger.error(e.getMessage(), e);
330             }
331             ++time;
332         }
333 
334         if (lastAction == null) {
335             stateMachine.doTransition(new Timeout());
336             throw new ConnectionException("Command timed out");
337         }
338         if (!(lastAction instanceof ResponseAction || lastAction instanceof GetSikAction)) {
339             if (lastAction instanceof ErrorAction) {
340                 throw ((ErrorAction) lastAction).getException();
341             }
342             throw new ConnectionException("Invalid StateMachine response: "
343                     + lastAction.getClass().getSimpleName());
344         }
345     }
346 
347     /**
348      * Queries the managed system for the details of the authentification
349      * process. Must be performed after {@link #getAvailableCipherSuites(int)}
350      *
351      * @param tag
352      *            - the integer from range 0-63 to match request with response
353      * @param cipherSuite
354      *            - {@link CipherSuite} requested for the session
355      * @param requestedPrivilegeLevel
356      *            - {@link PrivilegeLevel} requested for the session
357      * @return {@link GetChannelAuthenticationCapabilitiesResponseData}
358      * @throws ConnectionException
359      *             when connection is in the state that does not allow to
360      *             perform this operation.
361      * @throws Exception
362      *             when sending message to the managed system fails
363      */
364     public GetChannelAuthenticationCapabilitiesResponseData getChannelAuthenticationCapabilities(
365             int tag, CipherSuite cipherSuite,
366             PrivilegeLevel requestedPrivilegeLevel) throws Exception {
367 
368         if (stateMachine.getCurrent().getClass() != Ciphers.class) {
369             throw new ConnectionException(ILLEGAL_CONNECTION_STATE_MESSAGE
370                     + stateMachine.getCurrent().getClass().getSimpleName());
371         }
372 
373         lastAction = null;
374 
375         stateMachine.doTransition(new Default(cipherSuite, tag,
376                 requestedPrivilegeLevel));
377 
378         waitForResponse();
379 
380         ResponseAction action = (ResponseAction) lastAction;
381 
382         if (!(action.getIpmiResponseData() instanceof GetChannelAuthenticationCapabilitiesResponseData)) {
383             stateMachine.doTransition(new Timeout());
384             throw new ConnectionException(
385                     "Response data not matching Get Channel Authentication Capabilities command.");
386         }
387 
388         GetChannelAuthenticationCapabilitiesResponseData responseData = (GetChannelAuthenticationCapabilitiesResponseData) action
389                 .getIpmiResponseData();
390 
391         sessionId = SessionManager.generateSessionId();
392 
393         stateMachine.doTransition(new AuthenticationCapabilitiesReceived(
394                 sessionId, requestedPrivilegeLevel));
395 
396         return responseData;
397     }
398 
399     /**
400      * Initiates the session with the managed system. Must be performed after
401      * {@link #getChannelAuthenticationCapabilities(int, CipherSuite, PrivilegeLevel)}
402      * or {@link #closeSession()}
403      *
404      * @param tag
405      *            - the integer from range 0-63 to match request with response
406      * @param cipherSuite
407      *            - {@link CipherSuite} that will be used during the session
408      * @param privilegeLevel
409      *            - requested {@link PrivilegeLevel} - most of the time it will
410      *            be {@link PrivilegeLevel#User}
411      * @param username
412      *            - the username
413      * @param password
414      *            - the password matching the username
415      * @param bmcKey
416      *            - the key that should be provided if the two-key
417      *            authentication is enabled, null otherwise.
418      * @return id of the new session
419      * @throws ConnectionException
420      *             when connection is in the state that does not allow to
421      *             perform this operation.
422      * @throws Exception
423      *             when sending message to the managed system or initializing
424      *             one of the cipherSuite's algorithms fails
425      */
426     public int startSession(int tag, CipherSuite cipherSuite,
427             PrivilegeLevel privilegeLevel, String username, String password,
428             byte[] bmcKey) throws Exception {
429         if (stateMachine.getCurrent().getClass() != Authcap.class) {
430             throw new ConnectionException(ILLEGAL_CONNECTION_STATE_MESSAGE
431                     + stateMachine.getCurrent().getClass().getSimpleName());
432         }
433 
434         lastAction = null;
435 
436         // Open Session
437         stateMachine.doTransition(new Authorize(cipherSuite, tag,
438                 privilegeLevel, sessionId));
439 
440         waitForResponse();
441 
442         ResponseAction action = (ResponseAction) lastAction;
443 
444         lastAction = null;
445 
446         if (!(action.getIpmiResponseData() instanceof OpenSessionResponseData)) {
447             stateMachine.doTransition(new Timeout());
448             throw new ConnectionException(
449                     "Response data not matching OpenSession response data");
450         }
451 
452         managedSystemSessionId = ((OpenSessionResponseData) action
453                 .getIpmiResponseData()).getManagedSystemSessionId();
454 
455         stateMachine.doTransition(new DefaultAck());
456 
457         // RAKP 1
458         stateMachine.doTransition(new OpenSessionAck(cipherSuite,
459                 privilegeLevel, tag, managedSystemSessionId, username,
460                 password, bmcKey));
461 
462         waitForResponse();
463 
464         action = (ResponseAction) lastAction;
465 
466         lastAction = null;
467 
468         if (!(action.getIpmiResponseData() instanceof Rakp1ResponseData)) {
469             stateMachine.doTransition(new Timeout());
470             throw new ConnectionException(
471                     "Response data not matching RAKP Message 2: "
472                             + action.getIpmiResponseData().getClass()
473                                     .getSimpleName());
474         }
475 
476         Rakp1ResponseData rakp1ResponseData = (Rakp1ResponseData) action
477                 .getIpmiResponseData();
478 
479         stateMachine.doTransition(new DefaultAck());
480 
481         // RAKP 3
482         stateMachine.doTransition(new Rakp2Ack(cipherSuite, tag, (byte) 0,
483                 managedSystemSessionId, rakp1ResponseData));
484 
485         waitForResponse();
486 
487         action = (ResponseAction) lastAction;
488 
489         if (sik == null) {
490             throw new ConnectionException("Session Integrity Key is null");
491         }
492 
493         cipherSuite.initializeAlgorithms(sik);
494 
495         lastAction = null;
496 
497         if (!(action.getIpmiResponseData() instanceof Rakp3ResponseData)) {
498             stateMachine.doTransition(new Timeout());
499             throw new ConnectionException(
500                     "Response data not matching RAKP Message 4");
501         }
502 
503         stateMachine.doTransition(new DefaultAck());
504         stateMachine.doTransition(new StartSession(cipherSuite, sessionId));
505 
506         return sessionId;
507     }
508 
509     /**
510      * Closes the session. Can be performed only if the session is already open.
511      *
512      * @throws ConnectionException
513      *             when connection is in the state that does not allow to
514      *             perform this operation.
515      */
516     public void closeSession() throws ConnectionException {
517         if (stateMachine.getCurrent().getClass() != SessionValid.class) {
518             throw new ConnectionException(ILLEGAL_CONNECTION_STATE_MESSAGE
519                     + stateMachine.getCurrent().getClass().getSimpleName());
520         }
521 
522         stateMachine.doTransition(new CloseSession(managedSystemSessionId,
523                 messageHandlers.get(PayloadType.Ipmi).getSequenceNumber(), getNextSessionSequenceNumber()));
524     }
525 
526     /**
527      * Attempts to send IPMI request to the managed system.
528      *
529      * @param payloadCoder
530      *            - {@link PayloadCoder} representing the request
531      * @param isOneWay
532      *               - tells whether message is one way or not
533      * @return ID of the message that will be also attached to the response to
534      *         pair request with response if queue was not full and message was
535      *         sent, -1 if sending of the message failed.
536      * @throws ConnectionException
537      *             when connection isn't in state where sending commands is
538      *             allowed
539      * @throws ArithmeticException
540      *             when {@link Connection} runs out of available ID's for the
541      *             messages. If this happens session needs to be restarted.
542      */
543     public int sendMessage(PayloadCoder payloadCoder, boolean isOneWay) throws ConnectionException {
544         MessageHandler messageHandler = messageHandlers.get(payloadCoder.getSupportedPayloadType());
545 
546         if (messageHandler == null) {
547             // Handler for PayloadType.Ipmi is a default handler and in case no specific is found, we try default one.
548             messageHandler = messageHandlers.get(PayloadType.Ipmi);
549         }
550 
551         return messageHandler.sendMessage(payloadCoder, stateMachine, managedSystemSessionId, isOneWay);
552     }
553 
554     /**
555      * Attempts to retry sending a message.
556      *
557      * @param tag
558      *            - tag of the message to retry
559      * @param messagePayloadType
560      *             - {@link PayloadType} of the message that should be retried
561      * @return new tag if message was retried, -1 if operation failed
562      * @throws ConnectionException
563      *             when connection isn't in state where sending commands is
564      *             allowed
565      */
566     public int retry(int tag, PayloadType messagePayloadType) throws ConnectionException {
567 
568         MessageHandler messageHandler = messageHandlers.containsKey(messagePayloadType) ?
569                 messageHandlers.get(messagePayloadType) : messageHandlers.get(PayloadType.Ipmi);
570 
571         return messageHandler.retryMessage(tag, stateMachine, managedSystemSessionId);
572     }
573 
574     private void handleIncomingMessage(Ipmiv20Message message) {
575         MessageHandler messageHandler = messageHandlers.get(message.getPayloadType());
576         messageHandler.handleIncomingMessage(message);
577     }
578 
579     public void notifyResponseListeners(int handle, int tag, ResponseData responseData,
580                                         Exception exception) {
581         for (ConnectionListener listener : listeners) {
582             if (listener != null) {
583                 listener.processResponse(responseData, handle, tag, exception);
584             }
585         }
586     }
587 
588     public void notifyRequestListeners(IpmiPayload payload) {
589         for (ConnectionListener listener : listeners) {
590             if (listener != null) {
591                 listener.processRequest(payload);
592             }
593         }
594     }
595 
596     @Override
597     public void notify(StateMachineAction action) {
598         if (action instanceof GetSikAction) {
599             sik = ((GetSikAction) action).getSik();
600         } else if (!(action instanceof MessageAction)) {
601             lastAction = action;
602             if (action instanceof ErrorAction) {
603                 ErrorAction errorAction = (ErrorAction) action;
604                 logger.error(errorAction.getException().getMessage(), errorAction.getException());
605             }
606         } else {
607             handleIncomingMessage(((MessageAction) action).getIpmiv20Message());
608         }
609     }
610 
611 	/**
612 	 * {@link TimerTask} runner - periodically sends no-op messages to keep the
613 	 * session up
614 	 */
615 	@Override
616 	public void run() {
617 		int result = -1;
618 		while (
619 			!Thread.currentThread().isInterrupted()
620 			&& result <= 0
621 			&& stateMachine.getCurrent() instanceof SessionValid
622 		) {
623 			try {
624 
625 				result = sendMessage(
626 					new org.metricshub.ipmi.core.coding.commands.session.GetChannelAuthenticationCapabilities(
627 						IpmiVersion.V20, IpmiVersion.V20,
628 						((SessionValid) stateMachine.getCurrent()).getCipherSuite(), PrivilegeLevel.Callback,
629 						TypeConverter.intToByte(0xe)
630 					),
631 					false
632 				);
633 
634 				Thread.sleep(1000);
635 
636 			} catch (Exception e) {
637 				logger.error(e.getMessage(), e);
638 			}
639 		}
640 	}
641 
642     public InetAddress getRemoteMachineAddress() {
643         return stateMachine.getRemoteMachineAddress();
644     }
645 
646     public int getRemoteMachinePort() {
647         return stateMachine.getRemoteMachinePort();
648     }
649 
650     /**
651      * Checks if session is currently open.
652      */
653     public boolean isSessionValid() {
654         return stateMachine.getCurrent() instanceof SessionValid;
655     }
656 
657     public int getNextSessionSequenceNumber() {
658         int result = currentSessionSequenceNumber.incrementAndGet() % SESSION_SEQUENCE_NUMBER_UPPER_BOUND;
659 
660         if (result == 0) {
661             throw new ArithmeticException("Session sequence number overload. Reset session.");
662         }
663 
664         return result;
665     }
666 
667 	/**
668 	 * @return Default cipher suite (3)
669 	 */
670 	public static CipherSuite getDefaultCipherSuite() {
671 
672 		return new CipherSuite((byte) DEFAULT_CIPHER_SUITE, new AuthenticationRakpHmacSha1().getCode(),
673 				new ConfidentialityAesCbc128().getCode(), new IntegrityHmacSha1_96().getCode());
674 
675 	}
676 
677 }