1 package org.sentrysoftware.ipmi.core.coding.security;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25 import org.sentrysoftware.ipmi.core.coding.commands.session.GetChannelCipherSuites;
26 import org.sentrysoftware.ipmi.core.coding.commands.session.GetChannelCipherSuitesResponseData;
27 import org.sentrysoftware.ipmi.core.common.TypeConverter;
28
29 import javax.crypto.Mac;
30 import javax.crypto.NoSuchPaddingException;
31 import java.security.InvalidKeyException;
32 import java.security.NoSuchAlgorithmException;
33 import java.util.ArrayList;
34 import java.util.List;
35 import java.util.function.Supplier;
36
37
38
39
40
41 public class CipherSuite {
42
43 public static final String NOT_YET_IMPLEMENTED_MESSAGE = "Not yet implemented.";
44
45 private byte id;
46
47 private byte authenticationAlgorithm;
48 private byte integrityAlgorithm;
49 private byte confidentialityAlgorithm;
50
51 private AuthenticationAlgorithm aa;
52 private ConfidentialityAlgorithm ca;
53 private IntegrityAlgorithm ia;
54
55 public byte getId() {
56 return id;
57 }
58
59 public CipherSuite(byte id, byte authenticationAlgorithm,
60 byte confidentialityAlgorithm, byte integrityAlgorithm) {
61 this.id = id;
62 this.authenticationAlgorithm = (authenticationAlgorithm);
63 this.confidentialityAlgorithm = (confidentialityAlgorithm);
64 this.integrityAlgorithm = (integrityAlgorithm);
65 }
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81 public void initializeAlgorithms(byte[] sik) throws InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException {
82 getIntegrityAlgorithm().initialize(sik);
83 getConfidentialityAlgorithm().initialize(sik, getAuthenticationAlgorithm());
84 }
85
86
87
88
89
90
91
92 public AuthenticationAlgorithm getAuthenticationAlgorithm() {
93 if (aa != null && aa.getCode() != authenticationAlgorithm) {
94 throw new IllegalArgumentException("Invalid authentication algorithm code");
95 }
96 switch (authenticationAlgorithm) {
97 case SecurityConstants.AA_RAKP_NONE:
98 return instantiateAuthenticationAlgorithm(AuthenticationRakpNone::new);
99 case SecurityConstants.AA_RAKP_HMAC_SHA1:
100 return instantiateAuthenticationAlgorithm(AuthenticationRakpHmacSha1::new);
101 case SecurityConstants.AA_RAKP_HMAC_MD5:
102 return instantiateAuthenticationAlgorithm(AuthenticationRakpHmacMd5::new);
103 case SecurityConstants.AA_RAKP_HMAC_SHA256:
104 return instantiateAuthenticationAlgorithm(AuthenticationRakpHmacSha256::new);
105 default:
106 throw new IllegalArgumentException("Invalid authentication algorithm.");
107 }
108 }
109
110
111
112
113
114
115 public IntegrityAlgorithm getIntegrityAlgorithm() {
116 if (ia != null && ia.getCode() != integrityAlgorithm) {
117 throw new IllegalArgumentException("Invalid integrity algorithm code");
118 }
119 switch (integrityAlgorithm) {
120 case SecurityConstants.IA_NONE:
121 return instantiateIntegrityAlgorithm(IntegrityNone::new);
122 case SecurityConstants.IA_HMAC_SHA1_96:
123 return instantiateIntegrityAlgorithm(IntegrityHmacSha1_96::new);
124 case SecurityConstants.IA_MD5_128:
125
126 throw new IllegalArgumentException("Integrity algorithm MD5-128 is not yet implemented.");
127 case SecurityConstants.IA_HMAC_MD5_128:
128 return instantiateIntegrityAlgorithm(IntegrityHmacMd5_128::new);
129 case SecurityConstants.IA_HMAC_SHA256_128:
130 return instantiateIntegrityAlgorithm(IntegrityHmacSha256_128::new);
131 default:
132 throw new IllegalArgumentException("Invalid integrity algorithm.");
133 }
134 }
135
136
137
138
139
140
141
142 public ConfidentialityAlgorithm getConfidentialityAlgorithm() {
143 if (ca != null && ca.getCode() != confidentialityAlgorithm) {
144 throw new IllegalArgumentException(
145 "Invalid confidentiality algorithm code");
146 }
147 switch (confidentialityAlgorithm) {
148 case SecurityConstants.CA_NONE:
149 if (ca == null) {
150 ca = new ConfidentialityNone();
151 }
152 return ca;
153 case SecurityConstants.CA_AES_CBC128:
154 if (ca == null) {
155 ca = new ConfidentialityAesCbc128();
156 }
157 return ca;
158 case SecurityConstants.CA_XRC4_40:
159
160 throw new IllegalArgumentException("Confidentiality algorithm XRC4-40 is not yet implemented.");
161 case SecurityConstants.CA_XRC4_128:
162
163 throw new IllegalArgumentException("Confidentiality algorithm XRC4-128 is not yet implemented.");
164 default:
165 throw new IllegalArgumentException(
166 "Invalid confidentiality algorithm.");
167
168 }
169 }
170
171
172
173
174
175
176
177
178
179
180
181
182
183 public static List<CipherSuite> getCipherSuites(byte[] bytes) {
184 ArrayList<CipherSuite> suites = new ArrayList<CipherSuite>();
185
186 int offset = 0;
187
188 while (offset < bytes.length) {
189 byte id = bytes[offset + 1];
190 if (bytes[offset] == TypeConverter.intToByte(0xC0)) {
191 offset += 2;
192 } else {
193 offset += 5;
194 }
195 byte aa = bytes[offset];
196 byte ca = -1;
197 byte ia = -1;
198 ++offset;
199 while (offset < bytes.length
200 && bytes[offset] != TypeConverter.intToByte(0xC0)
201 && bytes[offset] != TypeConverter.intToByte(0xC1)) {
202 if ((TypeConverter.byteToInt(bytes[offset]) & 0xC0) == 0x80) {
203 ca = TypeConverter.intToByte(TypeConverter
204 .byteToInt(bytes[offset]) & 0x3f);
205 } else if ((TypeConverter.byteToInt(bytes[offset]) & 0xC0) == 0x40) {
206 ia = TypeConverter.intToByte(TypeConverter
207 .byteToInt(bytes[offset]) & 0x3f);
208 }
209 ++offset;
210 }
211 suites.add(new CipherSuite(id, aa, ca, ia));
212 }
213
214 return suites;
215 }
216
217
218
219
220
221
222 public static CipherSuite getEmpty() {
223 return new CipherSuite((byte) 0, (byte) 0, (byte) 0, (byte) 0);
224 }
225
226
227
228
229
230
231 private AuthenticationAlgorithm instantiateAuthenticationAlgorithm(
232 final Supplier<AuthenticationAlgorithm> constructor) {
233 if (aa == null) {
234 aa = constructor.get();
235 }
236 return aa;
237 }
238
239
240
241
242
243
244 private IntegrityAlgorithm instantiateIntegrityAlgorithm(final Supplier<IntegrityAlgorithm> constructor) {
245 if (ia == null) {
246 ia = constructor.get();
247 }
248 return ia;
249 }
250
251
252
253
254
255
256
257 public static Mac newMacInstance(final String algorithmName) {
258 if (algorithmName == null || algorithmName.trim().isEmpty()) {
259 return null;
260 }
261 try {
262 return Mac.getInstance(algorithmName);
263 } catch (NoSuchAlgorithmException e) {
264 throw new IllegalArgumentException("Algorithm " + algorithmName + " is not available", e);
265 }
266 }
267 }