View Javadoc
1   package org.metricshub.ipmi.core.coding.commands.session;
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.commands.CommandCodes;
26  import org.metricshub.ipmi.core.coding.commands.IpmiCommandCoder;
27  import org.metricshub.ipmi.core.coding.payload.lan.IPMIException;
28  import org.metricshub.ipmi.core.coding.payload.lan.IpmiLanMessage;
29  import org.metricshub.ipmi.core.coding.payload.lan.IpmiLanRequest;
30  import org.metricshub.ipmi.core.coding.payload.lan.NetworkFunction;
31  import org.metricshub.ipmi.core.coding.protocol.IpmiMessage;
32  import org.metricshub.ipmi.core.coding.protocol.Ipmiv20Message;
33  import org.metricshub.ipmi.core.coding.protocol.PayloadType;
34  import org.metricshub.ipmi.core.coding.security.ConfidentialityNone;
35  import org.metricshub.ipmi.core.common.TypeConverter;
36  
37  import java.security.InvalidKeyException;
38  import java.security.NoSuchAlgorithmException;
39  
40  /**
41   * Wrapper for RMCP+ Get Channel Cipher Suites command. This command can be
42   * executed prior to establishing a session with the BMC.
43   */
44  public class GetChannelCipherSuites extends IpmiCommandCoder<GetChannelCipherSuitesResponseData> {
45  
46  	private byte channelNumber;
47  
48  	private byte index;
49  
50  	/**
51  	 * Sets the channel number that will be put into IPMI command.
52  	 *
53  	 * @param channelNumber
54  	 *        - must be 0h-Bh or Eh-Fh <br>
55  	 *        Eh = retrieve information for channel this request was issued
56  	 *        on
57  	 * @throws IllegalArgumentException
58  	 */
59  	public void setChannelNumber(int channelNumber) {
60  		if (channelNumber < 0 || channelNumber > 0xF || channelNumber == 0xC || channelNumber == 0xD) {
61  			throw new IllegalArgumentException("Invalid channel number");
62  		}
63  		this.channelNumber = TypeConverter.intToByte(channelNumber);
64  	}
65  
66  	public int getChannelNumber() {
67  		return TypeConverter.byteToInt(channelNumber);
68  	}
69  
70  	public void setIndex(byte index) {
71  		if (index > 0x3F || index < 0) {
72  			throw new IllegalArgumentException("Index " + index + " invalid must be (00h-3Fh).");
73  		}
74  		this.index = index;
75  	}
76  
77  	public byte getIndex() {
78  		return index;
79  	}
80  
81  	/**
82  	 * Initiates class for decoding.
83  	 */
84  	public GetChannelCipherSuites() {}
85  
86  	/**
87  	 * Initiates class for both encoding and decoding.
88  	 *
89  	 * @param channelNumber
90  	 *        - must be 0h-Bh or Eh-Fh <br>
91  	 *        Eh = retrieve information for channel this request was issued
92  	 *        on
93  	 * @param index
94  	 *        - (00h-3Fh). 0h selects the first set of 16 cipher suites, 1h
95  	 *        selects the next set of 16, and so on
96  	 */
97  	public GetChannelCipherSuites(byte channelNumber, byte index) {
98  		setChannelNumber(channelNumber);
99  		setIndex(index);
100 	}
101 
102 	@Override
103 	public IpmiMessage encodePayload(int messageSequenceNumber, int sessionSequenceNumber, int sessionId)
104 			throws NoSuchAlgorithmException,
105 			InvalidKeyException {
106 		Ipmiv20Message message = new Ipmiv20Message(new ConfidentialityNone());
107 
108 		message.setAuthenticationType(getAuthenticationType());
109 
110 		message.setSessionID(0);
111 
112 		message.setPayloadEncrypted(false);
113 
114 		message.setPayloadAuthenticated(false);
115 
116 		message.setSessionSequenceNumber(0);
117 
118 		message.setPayloadType(PayloadType.Ipmi);
119 
120 		message.setPayload(preparePayload(messageSequenceNumber));
121 
122 		return message;
123 	}
124 
125 	@Override
126 	protected IpmiLanMessage preparePayload(int sequenceNumber) {
127 		byte[] requestData = new byte[3];
128 
129 		requestData[0] = channelNumber;
130 
131 		requestData[1] = 0; // payload type = IPMI
132 
133 		requestData[2] = TypeConverter.intToByte(0x80 | getIndex());
134 
135 		return new IpmiLanRequest(
136 				getNetworkFunction(),
137 				getCommandCode(),
138 				requestData,
139 				TypeConverter.intToByte(sequenceNumber));
140 	}
141 
142 	@Override
143 	public byte getCommandCode() {
144 		return CommandCodes.GET_CHANNEL_CIPHER_SUITES;
145 	}
146 
147 	@Override
148 	public NetworkFunction getNetworkFunction() {
149 		return NetworkFunction.ApplicationRequest;
150 	}
151 
152 	@Override
153 	public GetChannelCipherSuitesResponseData getResponseData(IpmiMessage message)
154 			throws IPMIException,
155 			NoSuchAlgorithmException,
156 			InvalidKeyException {
157 
158 		GetChannelCipherSuitesResponseData data = new GetChannelCipherSuitesResponseData();
159 
160 		byte[] raw = validateResponse(message);
161 
162 		data.setChannelNumber(raw[0]);
163 
164 		if (raw.length > 1) {
165 			byte[] cssData = new byte[raw.length - 1];
166 
167 			System.arraycopy(raw, 1, cssData, 0, cssData.length);
168 
169 			data.setCipherSuiteData(cssData);
170 		} else if (raw.length == 1) {
171 			data.setCipherSuiteData(new byte[0]);
172 		}
173 
174 		return data;
175 	}
176 
177 }