From cb5a13c0107697ccc3392685e617f23b93a321f0 Mon Sep 17 00:00:00 2001 From: Safae Ajib Date: Fri, 24 Jan 2025 17:29:08 +0100 Subject: [PATCH 01/11] Issue #46: Add support for SHA-256 and MD5 authentication algorithms * Updated IpmiClientConfiguration, AuthenticationAlgorithm, CipherSuite and ConfidentialityAlgorithm * Added AuthenticationRakpHmacMd5, AuthenticationRakpHmacSha256, IntegrityHmacMd5_128, IntegrityHmacSha256_128 --- .../ipmi/client/IpmiClientConfiguration.java | 3 + .../security/AuthenticationAlgorithm.java | 5 + .../security/AuthenticationRakpHmacMd5.java | 104 ++++++++++++ .../security/AuthenticationRakpHmacSha1.java | 5 + .../AuthenticationRakpHmacSha256.java | 104 ++++++++++++ .../security/AuthenticationRakpNone.java | 5 + .../core/coding/security/CipherSuite.java | 149 ++++++++++++++---- .../security/ConfidentialityAesCbc128.java | 8 +- .../security/ConfidentialityAlgorithm.java | 4 +- .../coding/security/IntegrityAlgorithm.java | 4 + .../coding/security/IntegrityHmacMd5_128.java | 86 ++++++++++ .../coding/security/IntegrityHmacSha1_96.java | 17 +- .../security/IntegrityHmacSha256_128.java | 86 ++++++++++ 13 files changed, 531 insertions(+), 49 deletions(-) create mode 100644 src/main/java/org/sentrysoftware/ipmi/core/coding/security/AuthenticationRakpHmacMd5.java create mode 100644 src/main/java/org/sentrysoftware/ipmi/core/coding/security/AuthenticationRakpHmacSha256.java create mode 100644 src/main/java/org/sentrysoftware/ipmi/core/coding/security/IntegrityHmacMd5_128.java create mode 100644 src/main/java/org/sentrysoftware/ipmi/core/coding/security/IntegrityHmacSha256_128.java diff --git a/src/main/java/org/sentrysoftware/ipmi/client/IpmiClientConfiguration.java b/src/main/java/org/sentrysoftware/ipmi/client/IpmiClientConfiguration.java index 8ef2c94..bb5af8b 100644 --- a/src/main/java/org/sentrysoftware/ipmi/client/IpmiClientConfiguration.java +++ b/src/main/java/org/sentrysoftware/ipmi/client/IpmiClientConfiguration.java @@ -1,5 +1,8 @@ package org.sentrysoftware.ipmi.client; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeoutException; + /*- * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲ * IPMI Java Client diff --git a/src/main/java/org/sentrysoftware/ipmi/core/coding/security/AuthenticationAlgorithm.java b/src/main/java/org/sentrysoftware/ipmi/core/coding/security/AuthenticationAlgorithm.java index 68d2298..f05a55d 100644 --- a/src/main/java/org/sentrysoftware/ipmi/core/coding/security/AuthenticationAlgorithm.java +++ b/src/main/java/org/sentrysoftware/ipmi/core/coding/security/AuthenticationAlgorithm.java @@ -104,4 +104,9 @@ public abstract byte[] getKeyExchangeAuthenticationCode(byte[] data, */ public abstract boolean doIntegrityCheck(byte[] data, byte[] reference, byte[] sik) throws InvalidKeyException, NoSuchAlgorithmException; + + /** + * @return the name of the algorithm as a {@code String}. + */ + public abstract String getAlgorithmName(); } diff --git a/src/main/java/org/sentrysoftware/ipmi/core/coding/security/AuthenticationRakpHmacMd5.java b/src/main/java/org/sentrysoftware/ipmi/core/coding/security/AuthenticationRakpHmacMd5.java new file mode 100644 index 0000000..039067f --- /dev/null +++ b/src/main/java/org/sentrysoftware/ipmi/core/coding/security/AuthenticationRakpHmacMd5.java @@ -0,0 +1,104 @@ +package org.sentrysoftware.ipmi.core.coding.security; + +/*- + * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲ + * IPMI Java Client + * ჻჻჻჻჻჻ + * Copyright 2023 Verax Systems, Sentry Software + * ჻჻჻჻჻჻ + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * . + * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱ + */ + +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; +import java.util.Arrays; + +import javax.crypto.Mac; +import javax.crypto.spec.SecretKeySpec; + + +/** + * RAKP-HMAC-MD5 authentication algorithm. + */ +public class AuthenticationRakpHmacMd5 extends AuthenticationAlgorithm { + + private static final String ALGORITHM_NAME = "HmacMD5"; + + private Mac mac; + + /** + * Initiates RAKP-HMAC-MD5 authentication algorithm. + * + * @throws NoSuchAlgorithmException - when initiation of the algorithm fails + */ + public AuthenticationRakpHmacMd5() throws NoSuchAlgorithmException { + mac = Mac.getInstance(ALGORITHM_NAME); + } + + @Override + public byte getCode() { + return SecurityConstants.AA_RAKP_HMAC_MD5; + } + + @Override + public boolean checkKeyExchangeAuthenticationCode(byte[] data, byte[] key, String password) + throws NoSuchAlgorithmException, InvalidKeyException { + byte[] check = getKeyExchangeAuthenticationCode(data, password); + return Arrays.equals(check, key); + } + + @Override + public byte[] getKeyExchangeAuthenticationCode(byte[] data, String password) + throws NoSuchAlgorithmException, InvalidKeyException { + + byte[] key = password.getBytes(); + + SecretKeySpec sKey = new SecretKeySpec(key, ALGORITHM_NAME); + mac.init(sKey); + + return mac.doFinal(data); + } + + @Override + public boolean doIntegrityCheck(byte[] data, byte[] reference, byte[] sik) + throws InvalidKeyException, NoSuchAlgorithmException { + + SecretKeySpec sKey = new SecretKeySpec(sik, ALGORITHM_NAME); + mac.init(sKey); + + byte[] result = new byte[getIntegrityCheckBaseLength()]; + + System.arraycopy(mac.doFinal(data), 0, result, 0, getIntegrityCheckBaseLength()); + + return Arrays.equals(result, reference); + } + + @Override + public int getKeyLength() { + return 16; + } + + @Override + public int getIntegrityCheckBaseLength() { + return 12; + } + + @Override + public String getAlgorithmName() { + return ALGORITHM_NAME; + } + +} diff --git a/src/main/java/org/sentrysoftware/ipmi/core/coding/security/AuthenticationRakpHmacSha1.java b/src/main/java/org/sentrysoftware/ipmi/core/coding/security/AuthenticationRakpHmacSha1.java index f3e025a..452bdd7 100644 --- a/src/main/java/org/sentrysoftware/ipmi/core/coding/security/AuthenticationRakpHmacSha1.java +++ b/src/main/java/org/sentrysoftware/ipmi/core/coding/security/AuthenticationRakpHmacSha1.java @@ -96,4 +96,9 @@ public int getIntegrityCheckBaseLength() { return 12; } + @Override + public String getAlgorithmName() { + return ALGORITHM_NAME; + } + } diff --git a/src/main/java/org/sentrysoftware/ipmi/core/coding/security/AuthenticationRakpHmacSha256.java b/src/main/java/org/sentrysoftware/ipmi/core/coding/security/AuthenticationRakpHmacSha256.java new file mode 100644 index 0000000..6dd44d1 --- /dev/null +++ b/src/main/java/org/sentrysoftware/ipmi/core/coding/security/AuthenticationRakpHmacSha256.java @@ -0,0 +1,104 @@ +package org.sentrysoftware.ipmi.core.coding.security; + +/*- + * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲ + * IPMI Java Client + * ჻჻჻჻჻჻ + * Copyright 2023 Verax Systems, Sentry Software + * ჻჻჻჻჻჻ + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * . + * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱ + */ + +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; +import java.util.Arrays; + +import javax.crypto.Mac; +import javax.crypto.spec.SecretKeySpec; + +/** + * RAKP-HMAC-SHA256 authentication algorithm. + */ +public class AuthenticationRakpHmacSha256 extends AuthenticationAlgorithm { + + private static final String ALGORITHM_NAME = "HmacSHA256"; + + private Mac mac; + + /** + * Initiates RAKP-HMAC-SHA256 authentication algorithm. + * + * @throws NoSuchAlgorithmException + * - when initiation of the algorithm fails + */ + public AuthenticationRakpHmacSha256() throws NoSuchAlgorithmException { + mac = Mac.getInstance(ALGORITHM_NAME); + } + + @Override + public byte getCode() { + return SecurityConstants.AA_RAKP_HMAC_SHA256; + } + + @Override + public boolean checkKeyExchangeAuthenticationCode(byte[] data, byte[] key, String password) + throws NoSuchAlgorithmException, InvalidKeyException { + byte[] check = getKeyExchangeAuthenticationCode(data, password); + return Arrays.equals(check, key); + } + + @Override + public byte[] getKeyExchangeAuthenticationCode(byte[] data, String password) + throws NoSuchAlgorithmException, InvalidKeyException { + + byte[] key = password.getBytes(); + + SecretKeySpec sKey = new SecretKeySpec(key, ALGORITHM_NAME); + mac.init(sKey); + + return mac.doFinal(data); + } + + @Override + public boolean doIntegrityCheck(byte[] data, byte[] reference, byte[] sik) + throws InvalidKeyException, NoSuchAlgorithmException { + + SecretKeySpec sKey = new SecretKeySpec(sik, ALGORITHM_NAME); + mac.init(sKey); + + byte[] result = new byte[getIntegrityCheckBaseLength()]; + + System.arraycopy(mac.doFinal(data), 0, result, 0, getIntegrityCheckBaseLength()); + + return Arrays.equals(result, reference); + } + + @Override + public int getKeyLength() { + return 32; + } + + @Override + public int getIntegrityCheckBaseLength() { + return 16; + } + + @Override + public String getAlgorithmName() { + return ALGORITHM_NAME; + } + +} diff --git a/src/main/java/org/sentrysoftware/ipmi/core/coding/security/AuthenticationRakpNone.java b/src/main/java/org/sentrysoftware/ipmi/core/coding/security/AuthenticationRakpNone.java index 5630ac3..b40e32b 100644 --- a/src/main/java/org/sentrysoftware/ipmi/core/coding/security/AuthenticationRakpNone.java +++ b/src/main/java/org/sentrysoftware/ipmi/core/coding/security/AuthenticationRakpNone.java @@ -70,4 +70,9 @@ public int getIntegrityCheckBaseLength() { return 0; } + @Override + public String getAlgorithmName() { + return ""; + } + } diff --git a/src/main/java/org/sentrysoftware/ipmi/core/coding/security/CipherSuite.java b/src/main/java/org/sentrysoftware/ipmi/core/coding/security/CipherSuite.java index d615abd..b3b5524 100644 --- a/src/main/java/org/sentrysoftware/ipmi/core/coding/security/CipherSuite.java +++ b/src/main/java/org/sentrysoftware/ipmi/core/coding/security/CipherSuite.java @@ -78,7 +78,7 @@ public CipherSuite(byte id, byte authenticationAlgorithm, */ public void initializeAlgorithms(byte[] sik) throws InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException { getIntegrityAlgorithm().initialize(sik); - getConfidentialityAlgorithm().initialize(sik); + getConfidentialityAlgorithm().initialize(sik, getAuthenticationAlgorithm()); } /** @@ -99,25 +99,13 @@ public AuthenticationAlgorithm getAuthenticationAlgorithm() { } return aa; case SecurityConstants.AA_RAKP_HMAC_SHA1: - if (aa == null) { - try { - aa = new AuthenticationRakpHmacSha1(); - } catch (NoSuchAlgorithmException e) { - throw new IllegalArgumentException( - "Initiation of the algorithm failed", e); - } - } - return aa; + return instantiateRakpHmacSha1Algorithm(); case SecurityConstants.AA_RAKP_HMAC_MD5: - // TODO: RAKP HMAC MD5 - throw new IllegalArgumentException(NOT_YET_IMPLEMENTED_MESSAGE); + return instantiateRakpHmacMd5Algorithm(); case SecurityConstants.AA_RAKP_HMAC_SHA256: - // TODO: RAKP HMAC Sha256 - throw new IllegalArgumentException(NOT_YET_IMPLEMENTED_MESSAGE); + return instantiateRakpHmacSha256Algorithm(); default: - throw new IllegalArgumentException( - "Invalid authentication algorithm."); - + throw new IllegalArgumentException("Invalid authentication algorithm."); } } @@ -127,7 +115,7 @@ public AuthenticationAlgorithm getAuthenticationAlgorithm() { * @throws IllegalArgumentException * when integrity algorithm code is incorrect. */ - public IntegrityAlgorithm getIntegrityAlgorithm() { + public IntegrityAlgorithm getIntegrityAlgorithm(){ if (ia != null && ia.getCode() != integrityAlgorithm) { throw new IllegalArgumentException( "Invalid integrity algorithm code"); @@ -139,31 +127,20 @@ public IntegrityAlgorithm getIntegrityAlgorithm() { } return ia; case SecurityConstants.IA_HMAC_SHA1_96: - if (ia == null) { - try { - ia = new IntegrityHmacSha1_96(); - } catch (NoSuchAlgorithmException e) { - throw new IllegalArgumentException( - "Initiation of the algorithm failed", e); - } - } - return ia; - case SecurityConstants.IA_HMAC_SHA256_128: - // TODO: HMAC SHA256-128 - throw new IllegalArgumentException(NOT_YET_IMPLEMENTED_MESSAGE); + return instantiateIntegrityHmacSha196Algorithm(); case SecurityConstants.IA_MD5_128: // TODO: MD5-128 - throw new IllegalArgumentException(NOT_YET_IMPLEMENTED_MESSAGE); case SecurityConstants.IA_HMAC_MD5_128: - // TODO: HMAC MD5-128 - throw new IllegalArgumentException(NOT_YET_IMPLEMENTED_MESSAGE); + return instantiateIntegrityHmacMd5128Algorithm(); + case SecurityConstants.IA_HMAC_SHA256_128: + return instantiateIntegrityHmacSha256128Algorithm(); default: throw new IllegalArgumentException("Invalid integrity algorithm."); } } - /** + /** * Returns instance of ConfidentialityAlgorithm class. * * @throws IllegalArgumentException @@ -252,4 +229,108 @@ public static List getCipherSuites(byte[] bytes) { public static CipherSuite getEmpty() { return new CipherSuite((byte) 0, (byte) 0, (byte) 0, (byte) 0); } + + /** + * Creates an instance of AuthenticationRakpHmacSha1. + * + * @return An instance of {@code AuthenticationRakpHmacSha1}. + * @throws IllegalArgumentException if algorithm initialization fails. + */ + private AuthenticationAlgorithm instantiateRakpHmacSha1Algorithm() { + if (aa == null) { + try { + aa = new AuthenticationRakpHmacSha1(); + } catch (NoSuchAlgorithmException e) { + throw new IllegalArgumentException("Initiation of the algorithm failed", e); + } + } + return aa; + } + + /** + * Creates an instance of AuthenticationRakpHmacMd5. + * + * @return An instance of {@code AuthenticationRakpHmacMd5}. + * @throws IllegalArgumentException if algorithm initialization fails. + */ + private AuthenticationAlgorithm instantiateRakpHmacMd5Algorithm() { + if (aa == null) { + try { + aa = new AuthenticationRakpHmacMd5(); + } catch (NoSuchAlgorithmException e) { + throw new IllegalArgumentException("Initiation of the algorithm failed", e); + } + } + return aa; + } + + /** + * Creates an instance of AuthenticationRakpHmacSha256. + * + * @return An instance of {@code AuthenticationRakpHmacSha256}. + * @throws IllegalArgumentException if algorithm initialization fails. + */ + private AuthenticationAlgorithm instantiateRakpHmacSha256Algorithm() { + if (aa == null) { + try { + aa = new AuthenticationRakpHmacSha256(); + } catch (NoSuchAlgorithmException e) { + throw new IllegalArgumentException("Initiation of the algorithm failed", e); + } + } + return aa; + } + + /** + * Creates an instance of IntegrityHmacSha1_96. + * + * @return An instance of {@code IntegrityHmacSha1_96}. + * @throws IllegalArgumentException if the algorithm initiation fails. + */ + private IntegrityAlgorithm instantiateIntegrityHmacSha196Algorithm() { + if (ia == null) { + try { + ia = new IntegrityHmacSha1_96(); + } catch (NoSuchAlgorithmException e) { + throw new IllegalArgumentException("Initiation of the algorithm failed", e); + } + } + return ia; + } + + /** + * Creates an instance of IntegrityHmacMd5_128. + * + * @return An instance of {@code IntegrityHmacMd5_128}. + * @throws IllegalArgumentException if the algorithm initiation fails. + */ + private IntegrityAlgorithm instantiateIntegrityHmacMd5128Algorithm() { + if (ia == null) { + try { + ia = new IntegrityHmacMd5_128(); + } catch (NoSuchAlgorithmException e) { + throw new IllegalArgumentException( + "Initiation of the algorithm failed", e); + } + } + return ia; + } + + /** + * Creates an instance of IntegrityHmacSha256_128. + * + * @return An instance of {@code IntegrityHmacSha256_128}. + * @throws IllegalArgumentException if the algorithm initiation fails. + */ + private IntegrityAlgorithm instantiateIntegrityHmacSha256128Algorithm() { + if (ia == null) { + try { + ia = new IntegrityHmacSha256_128(); + } catch (NoSuchAlgorithmException e) { + throw new IllegalArgumentException( + "Initiation of the algorithm failed", e); + } + } + return ia; + } } diff --git a/src/main/java/org/sentrysoftware/ipmi/core/coding/security/ConfidentialityAesCbc128.java b/src/main/java/org/sentrysoftware/ipmi/core/coding/security/ConfidentialityAesCbc128.java index b8021ed..5a2338a 100644 --- a/src/main/java/org/sentrysoftware/ipmi/core/coding/security/ConfidentialityAesCbc128.java +++ b/src/main/java/org/sentrysoftware/ipmi/core/coding/security/ConfidentialityAesCbc128.java @@ -51,13 +51,13 @@ public byte getCode() { } @Override - public void initialize(byte[] sik) throws InvalidKeyException, + public void initialize(byte[] sik, AuthenticationAlgorithm authenticationAlgorithm) throws InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException { - super.initialize(sik); + super.initialize(sik, authenticationAlgorithm); - SecretKeySpec k2 = new SecretKeySpec(sik, "HmacSHA1"); + SecretKeySpec k2 = new SecretKeySpec(sik, authenticationAlgorithm.getAlgorithmName()); - Mac mac = Mac.getInstance("HmacSHA1"); + Mac mac = Mac.getInstance(authenticationAlgorithm.getAlgorithmName()); mac.init(k2); byte[] ckey = mac.doFinal(CONST2); diff --git a/src/main/java/org/sentrysoftware/ipmi/core/coding/security/ConfidentialityAlgorithm.java b/src/main/java/org/sentrysoftware/ipmi/core/coding/security/ConfidentialityAlgorithm.java index 2bd4be1..e5a943e 100644 --- a/src/main/java/org/sentrysoftware/ipmi/core/coding/security/ConfidentialityAlgorithm.java +++ b/src/main/java/org/sentrysoftware/ipmi/core/coding/security/ConfidentialityAlgorithm.java @@ -39,6 +39,8 @@ public abstract class ConfidentialityAlgorithm { * @param sik * - Session Integrity Key calculated during the opening of the * session or user password if 'one-key' logins are enabled. + * @param authenticationAlgorithm + * - Algorithm used for authentication. * @throws InvalidKeyException * - when initiation of the algorithm fails * @throws NoSuchAlgorithmException @@ -46,7 +48,7 @@ public abstract class ConfidentialityAlgorithm { * @throws NoSuchPaddingException * - when initiation of the algorithm fails */ - public void initialize(byte[] sik) throws InvalidKeyException, + public void initialize(byte[] sik, AuthenticationAlgorithm authenticationAlgorithm) throws InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException { this.sik = sik; } diff --git a/src/main/java/org/sentrysoftware/ipmi/core/coding/security/IntegrityAlgorithm.java b/src/main/java/org/sentrysoftware/ipmi/core/coding/security/IntegrityAlgorithm.java index 6fd7fb1..feb2f46 100644 --- a/src/main/java/org/sentrysoftware/ipmi/core/coding/security/IntegrityAlgorithm.java +++ b/src/main/java/org/sentrysoftware/ipmi/core/coding/security/IntegrityAlgorithm.java @@ -39,6 +39,10 @@ public IntegrityAlgorithm() { } + protected static final byte[] CONST1 = new byte[] { + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,1 + }; + /** * Initializes Integrity Algorithm * diff --git a/src/main/java/org/sentrysoftware/ipmi/core/coding/security/IntegrityHmacMd5_128.java b/src/main/java/org/sentrysoftware/ipmi/core/coding/security/IntegrityHmacMd5_128.java new file mode 100644 index 0000000..38092ad --- /dev/null +++ b/src/main/java/org/sentrysoftware/ipmi/core/coding/security/IntegrityHmacMd5_128.java @@ -0,0 +1,86 @@ +package org.sentrysoftware.ipmi.core.coding.security; + +/*- + * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲ + * IPMI Java Client + * ჻჻჻჻჻჻ + * Copyright 2023 Verax Systems, Sentry Software + * ჻჻჻჻჻჻ + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * . + * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱ + */ + +import javax.crypto.Mac; +import javax.crypto.spec.SecretKeySpec; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; + +/** + * HMAC-MD5-128 integrity algorithm. + */ +public class IntegrityHmacMd5_128 extends IntegrityAlgorithm { + + public static final String ALGORITHM_NAME = "HmacMD5"; + private Mac mac; + + /** + * Initiates HMAC-MD5-128 integrity algorithm. + * + * @throws NoSuchAlgorithmException + * - when initiation of the algorithm fails + */ + public IntegrityHmacMd5_128() throws NoSuchAlgorithmException { + mac = Mac.getInstance(ALGORITHM_NAME); + + } + + @Override + public void initialize(byte[] sik) throws InvalidKeyException { + super.initialize(sik); + + SecretKeySpec k1 = new SecretKeySpec(sik, ALGORITHM_NAME); + + mac.init(k1); + byte[] derivedKey = mac.doFinal(CONST1); + k1 = new SecretKeySpec(derivedKey, ALGORITHM_NAME); + + mac.init(k1); + } + + @Override + public byte getCode() { + return SecurityConstants.IA_HMAC_MD5_128; + } + + @Override + public byte[] generateAuthCode(final byte[] base) { + if (sik == null) { + throw new NullPointerException("Algorithm not initialized."); + } + + byte[] result = new byte[16]; + byte[] updatedBase; + + if(base[base.length - 2] == 0 /*there are no integrity pad bytes*/) { + updatedBase = injectIntegrityPad(base,16); + } else { + updatedBase = base; + } + + System.arraycopy(mac.doFinal(updatedBase), 0, result, 0, 16); + + return result; + } +} \ No newline at end of file diff --git a/src/main/java/org/sentrysoftware/ipmi/core/coding/security/IntegrityHmacSha1_96.java b/src/main/java/org/sentrysoftware/ipmi/core/coding/security/IntegrityHmacSha1_96.java index 0fe7284..47c842c 100644 --- a/src/main/java/org/sentrysoftware/ipmi/core/coding/security/IntegrityHmacSha1_96.java +++ b/src/main/java/org/sentrysoftware/ipmi/core/coding/security/IntegrityHmacSha1_96.java @@ -1,5 +1,10 @@ package org.sentrysoftware.ipmi.core.coding.security; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; +import javax.crypto.Mac; +import javax.crypto.spec.SecretKeySpec; + /*- * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲ * IPMI Java Client @@ -22,11 +27,6 @@ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱ */ -import javax.crypto.Mac; -import javax.crypto.spec.SecretKeySpec; -import java.security.InvalidKeyException; -import java.security.NoSuchAlgorithmException; - /** * HMAC-SHA1-96 integrity algorithm. */ @@ -35,9 +35,6 @@ public class IntegrityHmacSha1_96 extends IntegrityAlgorithm { public static final String ALGORITHM_NAME = "HmacSHA1"; private Mac mac; - private static final byte[] CONST1 = new byte[] { 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; - /** * Initiates HMAC-SHA1-96 integrity algorithm. * @@ -55,8 +52,8 @@ public void initialize(byte[] sik) throws InvalidKeyException { SecretKeySpec k1 = new SecretKeySpec(sik, ALGORITHM_NAME); mac.init(k1); - - k1 = new SecretKeySpec(mac.doFinal(CONST1), ALGORITHM_NAME); + byte[] derivedKey = mac.doFinal(CONST1); + k1 = new SecretKeySpec(derivedKey, ALGORITHM_NAME); mac.init(k1); } diff --git a/src/main/java/org/sentrysoftware/ipmi/core/coding/security/IntegrityHmacSha256_128.java b/src/main/java/org/sentrysoftware/ipmi/core/coding/security/IntegrityHmacSha256_128.java new file mode 100644 index 0000000..60f74e0 --- /dev/null +++ b/src/main/java/org/sentrysoftware/ipmi/core/coding/security/IntegrityHmacSha256_128.java @@ -0,0 +1,86 @@ +package org.sentrysoftware.ipmi.core.coding.security; + +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; +import javax.crypto.Mac; +import javax.crypto.spec.SecretKeySpec; + +/*- + * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲ + * IPMI Java Client + * ჻჻჻჻჻჻ + * Copyright 2023 Verax Systems, Sentry Software + * ჻჻჻჻჻჻ + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * . + * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱ + */ + +/** + * HMAC-SHA256-128 integrity algorithm. + */ +public class IntegrityHmacSha256_128 extends IntegrityAlgorithm { + + private static final String ALGORITHM_NAME = "HmacSHA256"; + private Mac mac; + + /** + * Initiates HMAC-SHA1-96 integrity algorithm. + * + * @throws NoSuchAlgorithmException when initiation of the algorithm fails + */ + public IntegrityHmacSha256_128() throws NoSuchAlgorithmException { + mac = Mac.getInstance(ALGORITHM_NAME); + } + + @Override + public void initialize(byte[] sik) throws InvalidKeyException { + super.initialize(sik); + + SecretKeySpec k1 = new SecretKeySpec(sik, ALGORITHM_NAME); + + mac.init(k1); + byte[] derivedKey = mac.doFinal(CONST1); + k1 = new SecretKeySpec(derivedKey, ALGORITHM_NAME); + + mac.init(k1); + } + + @Override + public byte getCode() { + return SecurityConstants.IA_HMAC_SHA256_128; + } + + @Override + public byte[] generateAuthCode(byte[] base) { + + if (sik == null) { + throw new NullPointerException("Algorithm not initialized."); + } + + byte[] result = new byte[16]; + byte[] updatedBase; + + if (base[base.length - 2] == 0 /* there are no integrity pad bytes */) { + updatedBase = injectIntegrityPad(base, 16); + } else { + updatedBase = base; + } + + System.arraycopy(mac.doFinal(updatedBase), 0, result, 0, 16); + + return result; + } + +} From 4ec19f2524b07704e242aa54c6f4e0a3196f14ec Mon Sep 17 00:00:00 2001 From: Safae Ajib Date: Wed, 5 Feb 2025 11:17:02 +0100 Subject: [PATCH 02/11] Issue #46: Add support for SHA-256 and MD5 authentication algorithms * Fix style --- .../ipmi/client/IpmiClientConfiguration.java | 3 --- .../core/coding/security/IntegrityHmacSha1_96.java | 10 +++++----- .../core/coding/security/IntegrityHmacSha256_128.java | 10 +++++----- 3 files changed, 10 insertions(+), 13 deletions(-) diff --git a/src/main/java/org/sentrysoftware/ipmi/client/IpmiClientConfiguration.java b/src/main/java/org/sentrysoftware/ipmi/client/IpmiClientConfiguration.java index bb5af8b..8ef2c94 100644 --- a/src/main/java/org/sentrysoftware/ipmi/client/IpmiClientConfiguration.java +++ b/src/main/java/org/sentrysoftware/ipmi/client/IpmiClientConfiguration.java @@ -1,8 +1,5 @@ package org.sentrysoftware.ipmi.client; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.TimeoutException; - /*- * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲ * IPMI Java Client diff --git a/src/main/java/org/sentrysoftware/ipmi/core/coding/security/IntegrityHmacSha1_96.java b/src/main/java/org/sentrysoftware/ipmi/core/coding/security/IntegrityHmacSha1_96.java index 47c842c..3de4438 100644 --- a/src/main/java/org/sentrysoftware/ipmi/core/coding/security/IntegrityHmacSha1_96.java +++ b/src/main/java/org/sentrysoftware/ipmi/core/coding/security/IntegrityHmacSha1_96.java @@ -1,10 +1,5 @@ package org.sentrysoftware.ipmi.core.coding.security; -import java.security.InvalidKeyException; -import java.security.NoSuchAlgorithmException; -import javax.crypto.Mac; -import javax.crypto.spec.SecretKeySpec; - /*- * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲ * IPMI Java Client @@ -27,6 +22,11 @@ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱ */ +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; +import javax.crypto.Mac; +import javax.crypto.spec.SecretKeySpec; + /** * HMAC-SHA1-96 integrity algorithm. */ diff --git a/src/main/java/org/sentrysoftware/ipmi/core/coding/security/IntegrityHmacSha256_128.java b/src/main/java/org/sentrysoftware/ipmi/core/coding/security/IntegrityHmacSha256_128.java index 60f74e0..14479e6 100644 --- a/src/main/java/org/sentrysoftware/ipmi/core/coding/security/IntegrityHmacSha256_128.java +++ b/src/main/java/org/sentrysoftware/ipmi/core/coding/security/IntegrityHmacSha256_128.java @@ -1,10 +1,5 @@ package org.sentrysoftware.ipmi.core.coding.security; -import java.security.InvalidKeyException; -import java.security.NoSuchAlgorithmException; -import javax.crypto.Mac; -import javax.crypto.spec.SecretKeySpec; - /*- * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲ * IPMI Java Client @@ -27,6 +22,11 @@ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱ */ +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; +import javax.crypto.Mac; +import javax.crypto.spec.SecretKeySpec; + /** * HMAC-SHA256-128 integrity algorithm. */ From 718efe447bdbca33577cc2e8b2f4b8b17ec18cfd Mon Sep 17 00:00:00 2001 From: Safae Ajib Date: Wed, 5 Feb 2025 11:33:54 +0100 Subject: [PATCH 03/11] Issue #46: Add support for SHA-256 and MD5 authentication algorithms * Fix java doc --- .../ipmi/core/coding/security/CipherSuite.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/main/java/org/sentrysoftware/ipmi/core/coding/security/CipherSuite.java b/src/main/java/org/sentrysoftware/ipmi/core/coding/security/CipherSuite.java index b3b5524..9ce4fdf 100644 --- a/src/main/java/org/sentrysoftware/ipmi/core/coding/security/CipherSuite.java +++ b/src/main/java/org/sentrysoftware/ipmi/core/coding/security/CipherSuite.java @@ -140,7 +140,7 @@ public IntegrityAlgorithm getIntegrityAlgorithm(){ } } - /** + /** * Returns instance of ConfidentialityAlgorithm class. * * @throws IllegalArgumentException @@ -301,9 +301,9 @@ private IntegrityAlgorithm instantiateIntegrityHmacSha196Algorithm() { /** * Creates an instance of IntegrityHmacMd5_128. * - * @return An instance of {@code IntegrityHmacMd5_128}. - * @throws IllegalArgumentException if the algorithm initiation fails. - */ + * @return An instance of {@code IntegrityHmacMd5_128}. + * @throws IllegalArgumentException if the algorithm initiation fails. + */ private IntegrityAlgorithm instantiateIntegrityHmacMd5128Algorithm() { if (ia == null) { try { @@ -319,9 +319,9 @@ private IntegrityAlgorithm instantiateIntegrityHmacMd5128Algorithm() { /** * Creates an instance of IntegrityHmacSha256_128. * - * @return An instance of {@code IntegrityHmacSha256_128}. - * @throws IllegalArgumentException if the algorithm initiation fails. - */ + * @return An instance of {@code IntegrityHmacSha256_128}. + * @throws IllegalArgumentException if the algorithm initiation fails. + */ private IntegrityAlgorithm instantiateIntegrityHmacSha256128Algorithm() { if (ia == null) { try { From 9f6db80d6f03c52388b9412f3bebdde1384cbf30 Mon Sep 17 00:00:00 2001 From: Safae Ajib Date: Wed, 5 Feb 2025 11:50:11 +0100 Subject: [PATCH 04/11] Issue #46: Add support for SHA-256 and MD5 authentication algorithms * Updated IntegrityHmacMd5_128, IntegrityHmacSha1_96 and IntegrityHmacSha256_128 --- .../ipmi/core/coding/security/IntegrityHmacMd5_128.java | 3 +-- .../ipmi/core/coding/security/IntegrityHmacSha1_96.java | 3 +-- .../ipmi/core/coding/security/IntegrityHmacSha256_128.java | 3 +-- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/src/main/java/org/sentrysoftware/ipmi/core/coding/security/IntegrityHmacMd5_128.java b/src/main/java/org/sentrysoftware/ipmi/core/coding/security/IntegrityHmacMd5_128.java index 38092ad..98533fa 100644 --- a/src/main/java/org/sentrysoftware/ipmi/core/coding/security/IntegrityHmacMd5_128.java +++ b/src/main/java/org/sentrysoftware/ipmi/core/coding/security/IntegrityHmacMd5_128.java @@ -53,8 +53,7 @@ public void initialize(byte[] sik) throws InvalidKeyException { SecretKeySpec k1 = new SecretKeySpec(sik, ALGORITHM_NAME); mac.init(k1); - byte[] derivedKey = mac.doFinal(CONST1); - k1 = new SecretKeySpec(derivedKey, ALGORITHM_NAME); + k1 = new SecretKeySpec(mac.doFinal(CONST1), ALGORITHM_NAME); mac.init(k1); } diff --git a/src/main/java/org/sentrysoftware/ipmi/core/coding/security/IntegrityHmacSha1_96.java b/src/main/java/org/sentrysoftware/ipmi/core/coding/security/IntegrityHmacSha1_96.java index 3de4438..db51f23 100644 --- a/src/main/java/org/sentrysoftware/ipmi/core/coding/security/IntegrityHmacSha1_96.java +++ b/src/main/java/org/sentrysoftware/ipmi/core/coding/security/IntegrityHmacSha1_96.java @@ -52,8 +52,7 @@ public void initialize(byte[] sik) throws InvalidKeyException { SecretKeySpec k1 = new SecretKeySpec(sik, ALGORITHM_NAME); mac.init(k1); - byte[] derivedKey = mac.doFinal(CONST1); - k1 = new SecretKeySpec(derivedKey, ALGORITHM_NAME); + k1 = new SecretKeySpec(mac.doFinal(CONST1), ALGORITHM_NAME); mac.init(k1); } diff --git a/src/main/java/org/sentrysoftware/ipmi/core/coding/security/IntegrityHmacSha256_128.java b/src/main/java/org/sentrysoftware/ipmi/core/coding/security/IntegrityHmacSha256_128.java index 14479e6..af59074 100644 --- a/src/main/java/org/sentrysoftware/ipmi/core/coding/security/IntegrityHmacSha256_128.java +++ b/src/main/java/org/sentrysoftware/ipmi/core/coding/security/IntegrityHmacSha256_128.java @@ -51,8 +51,7 @@ public void initialize(byte[] sik) throws InvalidKeyException { SecretKeySpec k1 = new SecretKeySpec(sik, ALGORITHM_NAME); mac.init(k1); - byte[] derivedKey = mac.doFinal(CONST1); - k1 = new SecretKeySpec(derivedKey, ALGORITHM_NAME); + k1 = new SecretKeySpec(mac.doFinal(CONST1), ALGORITHM_NAME); mac.init(k1); } From e8126c186470859df3aae224476d3d12e8a7622e Mon Sep 17 00:00:00 2001 From: Safae Ajib Date: Wed, 5 Feb 2025 12:06:02 +0100 Subject: [PATCH 05/11] Issue #46: Add support for SHA-256 and MD5 authentication algorithms * Fix Style --- .../security/AuthenticationRakpHmacMd5.java | 10 +- .../core/coding/security/CipherSuite.java | 136 +++++++++--------- 2 files changed, 72 insertions(+), 74 deletions(-) diff --git a/src/main/java/org/sentrysoftware/ipmi/core/coding/security/AuthenticationRakpHmacMd5.java b/src/main/java/org/sentrysoftware/ipmi/core/coding/security/AuthenticationRakpHmacMd5.java index 039067f..a5e7fff 100644 --- a/src/main/java/org/sentrysoftware/ipmi/core/coding/security/AuthenticationRakpHmacMd5.java +++ b/src/main/java/org/sentrysoftware/ipmi/core/coding/security/AuthenticationRakpHmacMd5.java @@ -39,11 +39,11 @@ public class AuthenticationRakpHmacMd5 extends AuthenticationAlgorithm { private Mac mac; - /** - * Initiates RAKP-HMAC-MD5 authentication algorithm. - * - * @throws NoSuchAlgorithmException - when initiation of the algorithm fails - */ + /** + * Initiates RAKP-HMAC-MD5 authentication algorithm. + * + * @throws NoSuchAlgorithmException - when initiation of the algorithm fails + */ public AuthenticationRakpHmacMd5() throws NoSuchAlgorithmException { mac = Mac.getInstance(ALGORITHM_NAME); } diff --git a/src/main/java/org/sentrysoftware/ipmi/core/coding/security/CipherSuite.java b/src/main/java/org/sentrysoftware/ipmi/core/coding/security/CipherSuite.java index 9ce4fdf..143c890 100644 --- a/src/main/java/org/sentrysoftware/ipmi/core/coding/security/CipherSuite.java +++ b/src/main/java/org/sentrysoftware/ipmi/core/coding/security/CipherSuite.java @@ -230,63 +230,63 @@ public static CipherSuite getEmpty() { return new CipherSuite((byte) 0, (byte) 0, (byte) 0, (byte) 0); } - /** - * Creates an instance of AuthenticationRakpHmacSha1. - * - * @return An instance of {@code AuthenticationRakpHmacSha1}. - * @throws IllegalArgumentException if algorithm initialization fails. - */ - private AuthenticationAlgorithm instantiateRakpHmacSha1Algorithm() { - if (aa == null) { - try { - aa = new AuthenticationRakpHmacSha1(); - } catch (NoSuchAlgorithmException e) { - throw new IllegalArgumentException("Initiation of the algorithm failed", e); - } - } - return aa; - } + /** + * Creates an instance of AuthenticationRakpHmacSha1. + * + * @return An instance of {@code AuthenticationRakpHmacSha1}. + * @throws IllegalArgumentException if algorithm initialization fails. + */ + private AuthenticationAlgorithm instantiateRakpHmacSha1Algorithm() { + if (aa == null) { + try { + aa = new AuthenticationRakpHmacSha1(); + } catch (NoSuchAlgorithmException e) { + throw new IllegalArgumentException("Initiation of the algorithm failed", e); + } + } + return aa; + } - /** - * Creates an instance of AuthenticationRakpHmacMd5. - * - * @return An instance of {@code AuthenticationRakpHmacMd5}. - * @throws IllegalArgumentException if algorithm initialization fails. - */ - private AuthenticationAlgorithm instantiateRakpHmacMd5Algorithm() { - if (aa == null) { - try { - aa = new AuthenticationRakpHmacMd5(); - } catch (NoSuchAlgorithmException e) { - throw new IllegalArgumentException("Initiation of the algorithm failed", e); - } - } - return aa; - } + /** + * Creates an instance of AuthenticationRakpHmacMd5. + * + * @return An instance of {@code AuthenticationRakpHmacMd5}. + * @throws IllegalArgumentException if algorithm initialization fails. + */ + private AuthenticationAlgorithm instantiateRakpHmacMd5Algorithm() { + if (aa == null) { + try { + aa = new AuthenticationRakpHmacMd5(); + } catch (NoSuchAlgorithmException e) { + throw new IllegalArgumentException("Initiation of the algorithm failed", e); + } + } + return aa; + } - /** - * Creates an instance of AuthenticationRakpHmacSha256. - * - * @return An instance of {@code AuthenticationRakpHmacSha256}. - * @throws IllegalArgumentException if algorithm initialization fails. - */ - private AuthenticationAlgorithm instantiateRakpHmacSha256Algorithm() { - if (aa == null) { - try { - aa = new AuthenticationRakpHmacSha256(); - } catch (NoSuchAlgorithmException e) { - throw new IllegalArgumentException("Initiation of the algorithm failed", e); - } - } - return aa; - } + /** + * Creates an instance of AuthenticationRakpHmacSha256. + * + * @return An instance of {@code AuthenticationRakpHmacSha256}. + * @throws IllegalArgumentException if algorithm initialization fails. + */ + private AuthenticationAlgorithm instantiateRakpHmacSha256Algorithm() { + if (aa == null) { + try { + aa = new AuthenticationRakpHmacSha256(); + } catch (NoSuchAlgorithmException e) { + throw new IllegalArgumentException("Initiation of the algorithm failed", e); + } + } + return aa; + } - /** - * Creates an instance of IntegrityHmacSha1_96. - * - * @return An instance of {@code IntegrityHmacSha1_96}. - * @throws IllegalArgumentException if the algorithm initiation fails. - */ + /** + * Creates an instance of IntegrityHmacSha1_96. + * + * @return An instance of {@code IntegrityHmacSha1_96}. + * @throws IllegalArgumentException if the algorithm initiation fails. + */ private IntegrityAlgorithm instantiateIntegrityHmacSha196Algorithm() { if (ia == null) { try { @@ -305,14 +305,13 @@ private IntegrityAlgorithm instantiateIntegrityHmacSha196Algorithm() { * @throws IllegalArgumentException if the algorithm initiation fails. */ private IntegrityAlgorithm instantiateIntegrityHmacMd5128Algorithm() { - if (ia == null) { - try { - ia = new IntegrityHmacMd5_128(); - } catch (NoSuchAlgorithmException e) { - throw new IllegalArgumentException( - "Initiation of the algorithm failed", e); - } - } + if (ia == null) { + try { + ia = new IntegrityHmacMd5_128(); + } catch (NoSuchAlgorithmException e) { + throw new IllegalArgumentException("Initiation of the algorithm failed", e); + } + } return ia; } @@ -324,13 +323,12 @@ private IntegrityAlgorithm instantiateIntegrityHmacMd5128Algorithm() { */ private IntegrityAlgorithm instantiateIntegrityHmacSha256128Algorithm() { if (ia == null) { - try { - ia = new IntegrityHmacSha256_128(); - } catch (NoSuchAlgorithmException e) { - throw new IllegalArgumentException( - "Initiation of the algorithm failed", e); - } - } + try { + ia = new IntegrityHmacSha256_128(); + } catch (NoSuchAlgorithmException e) { + throw new IllegalArgumentException("Initiation of the algorithm failed", e); + } + } return ia; } } From e8bacbcbd0082cd497790874f2ee6d2d4a8a9d27 Mon Sep 17 00:00:00 2001 From: Safae Ajib Date: Wed, 5 Feb 2025 13:04:32 +0100 Subject: [PATCH 06/11] Issue #46: Add support for SHA-256 and MD5 authentication algorithms * Factorize the code for integrity and authentication algorithms * Updated ConfidentialityAesCbc128 --- .../security/AuthenticationAlgorithm.java | 181 +++++++++------- .../security/AuthenticationRakpHmacMd5.java | 85 ++------ .../security/AuthenticationRakpHmacSha1.java | 87 ++------ .../AuthenticationRakpHmacSha256.java | 45 +--- .../security/AuthenticationRakpNone.java | 86 ++++---- .../security/ConfidentialityAesCbc128.java | 7 +- .../coding/security/IntegrityAlgorithm.java | 205 +++++++++++------- .../coding/security/IntegrityHmacMd5_128.java | 78 +++---- .../coding/security/IntegrityHmacSha1_96.java | 43 +--- .../security/IntegrityHmacSha256_128.java | 41 +--- .../core/coding/security/IntegrityNone.java | 39 +++- 11 files changed, 403 insertions(+), 494 deletions(-) diff --git a/src/main/java/org/sentrysoftware/ipmi/core/coding/security/AuthenticationAlgorithm.java b/src/main/java/org/sentrysoftware/ipmi/core/coding/security/AuthenticationAlgorithm.java index f05a55d..7155488 100644 --- a/src/main/java/org/sentrysoftware/ipmi/core/coding/security/AuthenticationAlgorithm.java +++ b/src/main/java/org/sentrysoftware/ipmi/core/coding/security/AuthenticationAlgorithm.java @@ -24,6 +24,10 @@ import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; +import java.util.Arrays; + +import javax.crypto.Mac; +import javax.crypto.spec.SecretKeySpec; import org.sentrysoftware.ipmi.core.coding.commands.session.Rakp1; @@ -33,80 +37,105 @@ */ public abstract class AuthenticationAlgorithm { - /** - * @return algorithm-specific code - */ - public abstract byte getCode(); - - /** - * @return length of the key for the RAKP2 message - */ - public abstract int getKeyLength(); - - /** - * @return length of the integrity check base for RAKP4 message - */ - public abstract int getIntegrityCheckBaseLength(); - - /** - * Checks value of the Key Exchange Authentication Code in RAKP messages - * - * @param data - * - The base for authentication algorithm. Depends on RAKP - * Message. - * @param key - * - the Key Exchange Authentication Code to check. - * @param password - * - password of the user establishing a session - * @return True if authentication check was successful, false otherwise. - * @throws NoSuchAlgorithmException - * when initiation of the algorithm fails - * @throws InvalidKeyException - * when creating of the algorithm key failsS - */ - public abstract boolean checkKeyExchangeAuthenticationCode(byte[] data, - byte[] key, String password) throws NoSuchAlgorithmException, - InvalidKeyException; - - /** - * Calculates value of the Key Exchange Authentication Code in RAKP messages - * - * @param data - * - The base for authentication algorithm. Depends on RAKP - * Message. - * @param password - * - password of the user establishing a session - * @throws NoSuchAlgorithmException - * when initiation of the algorithm fails - * @throws InvalidKeyException - * when creating of the algorithm key fails - */ - public abstract byte[] getKeyExchangeAuthenticationCode(byte[] data, - String password) throws NoSuchAlgorithmException, - InvalidKeyException; - - /** - * Validates Integrity Check Value in RAKP Message 4. - * - * @param data - * - The base for authentication algorithm. - * @param reference - * - The Integrity Check Value to validate. - * @param sik - * - The Session Integrity Key generated on base of RAKP Messages - * 1 and 2. - * @see Rakp1#calculateSik(org.sentrysoftware.ipmi.core.coding.commands.session.Rakp1ResponseData) - * @return True if integrity check was successful, false otherwise. - * @throws NoSuchAlgorithmException - * when initiation of the algorithm fails - * @throws InvalidKeyException - * when creating of the algorithm key fails - */ - public abstract boolean doIntegrityCheck(byte[] data, byte[] reference, - byte[] sik) throws InvalidKeyException, NoSuchAlgorithmException; - - /** - * @return the name of the algorithm as a {@code String}. - */ - public abstract String getAlgorithmName(); + private final Mac mac; + + /** + * Constructs an authentication algorithm + * + * @throws NoSuchAlgorithmException + */ + protected AuthenticationAlgorithm() throws NoSuchAlgorithmException { + this.mac = Mac.getInstance(getAlgorithmName()); + } + + /** + * Constructs an authentication algorithm instance without initializing the MAC. + * + * @param noMacInit If {@code true}, the MAC instance will not be initialized. + */ + protected AuthenticationAlgorithm(boolean noMacInit) { + this.mac = null; + } + + /** + * @return algorithm-specific code + */ + public abstract byte getCode(); + + /** + * @return length of the key for the RAKP2 message + */ + public abstract int getKeyLength(); + + /** + * @return length of the integrity check base for RAKP4 message + */ + public abstract int getIntegrityCheckBaseLength(); + + /** + * Checks value of the Key Exchange Authentication Code in RAKP messages + * + * @param data - The base for authentication algorithm. Depends on RAKP + * Message. + * @param key - the Key Exchange Authentication Code to check. + * @param password - password of the user establishing a session + * @return True if authentication check was successful, false otherwise. + * @throws NoSuchAlgorithmException when initiation of the algorithm fails + * @throws InvalidKeyException when creating of the algorithm key fails + */ + public boolean checkKeyExchangeAuthenticationCode(byte[] data, byte[] key, String password) + throws NoSuchAlgorithmException, InvalidKeyException { + byte[] check = getKeyExchangeAuthenticationCode(data, password); + return Arrays.equals(check, key); + } + + /** + * Calculates value of the Key Exchange Authentication Code in RAKP messages + * + * @param data - The base for authentication algorithm. Depends on RAKP + * Message. + * @param password - password of the user establishing a session + * @throws NoSuchAlgorithmException when initiation of the algorithm fails + * @throws InvalidKeyException when creating of the algorithm key fails + */ + public byte[] getKeyExchangeAuthenticationCode(byte[] data, String password) + throws NoSuchAlgorithmException, InvalidKeyException { + + byte[] key = password.getBytes(); + + SecretKeySpec sKey = new SecretKeySpec(key, getAlgorithmName()); + mac.init(sKey); + + return mac.doFinal(data); + } + + /** + * Validates Integrity Check Value in RAKP Message 4. + * + * @param data - The base for authentication algorithm. + * @param reference - The Integrity Check Value to validate. + * @param sik - The Session Integrity Key generated on base of RAKP + * Messages 1 and 2. + * @see Rakp1#calculateSik(org.sentrysoftware.ipmi.core.coding.commands.session.Rakp1ResponseData) + * @return True if integrity check was successful, false otherwise. + * @throws NoSuchAlgorithmException when initiation of the algorithm fails + * @throws InvalidKeyException when creating of the algorithm key fails + */ + public boolean doIntegrityCheck(byte[] data, byte[] reference, byte[] sik) + throws InvalidKeyException, NoSuchAlgorithmException { + + SecretKeySpec sKey = new SecretKeySpec(sik, getAlgorithmName()); + mac.init(sKey); + + byte[] result = new byte[getIntegrityCheckBaseLength()]; + + System.arraycopy(mac.doFinal(data), 0, result, 0, getIntegrityCheckBaseLength()); + + return Arrays.equals(result, reference); + } + + /** + * @return the name of the algorithm as a {@code String}. + */ + public abstract String getAlgorithmName(); } diff --git a/src/main/java/org/sentrysoftware/ipmi/core/coding/security/AuthenticationRakpHmacMd5.java b/src/main/java/org/sentrysoftware/ipmi/core/coding/security/AuthenticationRakpHmacMd5.java index a5e7fff..a97639e 100644 --- a/src/main/java/org/sentrysoftware/ipmi/core/coding/security/AuthenticationRakpHmacMd5.java +++ b/src/main/java/org/sentrysoftware/ipmi/core/coding/security/AuthenticationRakpHmacMd5.java @@ -22,81 +22,40 @@ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱ */ -import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; -import java.util.Arrays; - -import javax.crypto.Mac; -import javax.crypto.spec.SecretKeySpec; - /** * RAKP-HMAC-MD5 authentication algorithm. */ public class AuthenticationRakpHmacMd5 extends AuthenticationAlgorithm { - private static final String ALGORITHM_NAME = "HmacMD5"; - - private Mac mac; - - /** - * Initiates RAKP-HMAC-MD5 authentication algorithm. - * - * @throws NoSuchAlgorithmException - when initiation of the algorithm fails - */ - public AuthenticationRakpHmacMd5() throws NoSuchAlgorithmException { - mac = Mac.getInstance(ALGORITHM_NAME); - } - - @Override - public byte getCode() { - return SecurityConstants.AA_RAKP_HMAC_MD5; - } - - @Override - public boolean checkKeyExchangeAuthenticationCode(byte[] data, byte[] key, String password) - throws NoSuchAlgorithmException, InvalidKeyException { - byte[] check = getKeyExchangeAuthenticationCode(data, password); - return Arrays.equals(check, key); - } - - @Override - public byte[] getKeyExchangeAuthenticationCode(byte[] data, String password) - throws NoSuchAlgorithmException, InvalidKeyException { - - byte[] key = password.getBytes(); - - SecretKeySpec sKey = new SecretKeySpec(key, ALGORITHM_NAME); - mac.init(sKey); + private static final String ALGORITHM_NAME = "HmacMD5"; - return mac.doFinal(data); - } - - @Override - public boolean doIntegrityCheck(byte[] data, byte[] reference, byte[] sik) - throws InvalidKeyException, NoSuchAlgorithmException { - - SecretKeySpec sKey = new SecretKeySpec(sik, ALGORITHM_NAME); - mac.init(sKey); - - byte[] result = new byte[getIntegrityCheckBaseLength()]; - - System.arraycopy(mac.doFinal(data), 0, result, 0, getIntegrityCheckBaseLength()); + /** + * Initiates RAKP-HMAC-MD5 authentication algorithm. + * + * @throws NoSuchAlgorithmException - when initiation of the algorithm fails + */ + public AuthenticationRakpHmacMd5() throws NoSuchAlgorithmException { + super(); + } - return Arrays.equals(result, reference); - } + @Override + public byte getCode() { + return SecurityConstants.AA_RAKP_HMAC_MD5; + } - @Override - public int getKeyLength() { - return 16; - } + @Override + public int getKeyLength() { + return 16; + } - @Override - public int getIntegrityCheckBaseLength() { - return 12; - } + @Override + public int getIntegrityCheckBaseLength() { + return 12; + } - @Override + @Override public String getAlgorithmName() { return ALGORITHM_NAME; } diff --git a/src/main/java/org/sentrysoftware/ipmi/core/coding/security/AuthenticationRakpHmacSha1.java b/src/main/java/org/sentrysoftware/ipmi/core/coding/security/AuthenticationRakpHmacSha1.java index 452bdd7..9a61af4 100644 --- a/src/main/java/org/sentrysoftware/ipmi/core/coding/security/AuthenticationRakpHmacSha1.java +++ b/src/main/java/org/sentrysoftware/ipmi/core/coding/security/AuthenticationRakpHmacSha1.java @@ -22,82 +22,41 @@ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱ */ -import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; -import java.util.Arrays; - -import javax.crypto.Mac; -import javax.crypto.spec.SecretKeySpec; /** * RAKP-HMAC-SHA1 authentication algorithm. */ public class AuthenticationRakpHmacSha1 extends AuthenticationAlgorithm { - private static final String ALGORITHM_NAME = "HmacSHA1"; - - private Mac mac; - - /** - * Initiates RAKP-HMAC-SHA1 authentication algorithm. - * @throws NoSuchAlgorithmException - * - when initiation of the algorithm fails - */ - public AuthenticationRakpHmacSha1() throws NoSuchAlgorithmException { - mac = Mac.getInstance(ALGORITHM_NAME); - } - - @Override - public byte getCode() { - return SecurityConstants.AA_RAKP_HMAC_SHA1; - } - - @Override - public boolean checkKeyExchangeAuthenticationCode(byte[] data, byte[] key, - String password) throws NoSuchAlgorithmException, - InvalidKeyException { - byte[] check = getKeyExchangeAuthenticationCode(data, password); - return Arrays.equals(check, key); - } - - @Override - public byte[] getKeyExchangeAuthenticationCode(byte[] data, - String password) - throws NoSuchAlgorithmException, InvalidKeyException { - - byte[] key = password.getBytes(); - - SecretKeySpec sKey = new SecretKeySpec(key, ALGORITHM_NAME); - mac.init(sKey); - - return mac.doFinal(data); - } - - @Override - public boolean doIntegrityCheck(byte[] data, byte[] reference, byte[] sik) throws InvalidKeyException, NoSuchAlgorithmException { - - SecretKeySpec sKey = new SecretKeySpec(sik, ALGORITHM_NAME); - mac.init(sKey); - - byte[] result = new byte[getIntegrityCheckBaseLength()]; + /** + * Initiates RAKP-HMAC-SHA1 authentication algorithm. + * + * @throws NoSuchAlgorithmException - when initiation of the algorithm fails + */ + public AuthenticationRakpHmacSha1() throws NoSuchAlgorithmException { + super(); + } - System.arraycopy(mac.doFinal(data), 0, result, 0, getIntegrityCheckBaseLength()); + private static final String ALGORITHM_NAME = "HmacSHA1"; - return Arrays.equals(result, reference); - } + @Override + public byte getCode() { + return SecurityConstants.AA_RAKP_HMAC_SHA1; + } - @Override - public int getKeyLength() { - return 20; - } + @Override + public int getKeyLength() { + return 20; + } - @Override - public int getIntegrityCheckBaseLength() { - return 12; - } + @Override + public int getIntegrityCheckBaseLength() { + return 12; + } - @Override - public String getAlgorithmName() { + @Override + public String getAlgorithmName() { return ALGORITHM_NAME; } diff --git a/src/main/java/org/sentrysoftware/ipmi/core/coding/security/AuthenticationRakpHmacSha256.java b/src/main/java/org/sentrysoftware/ipmi/core/coding/security/AuthenticationRakpHmacSha256.java index 6dd44d1..2880e7d 100644 --- a/src/main/java/org/sentrysoftware/ipmi/core/coding/security/AuthenticationRakpHmacSha256.java +++ b/src/main/java/org/sentrysoftware/ipmi/core/coding/security/AuthenticationRakpHmacSha256.java @@ -22,12 +22,7 @@ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱ */ -import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; -import java.util.Arrays; - -import javax.crypto.Mac; -import javax.crypto.spec.SecretKeySpec; /** * RAKP-HMAC-SHA256 authentication algorithm. @@ -36,16 +31,13 @@ public class AuthenticationRakpHmacSha256 extends AuthenticationAlgorithm { private static final String ALGORITHM_NAME = "HmacSHA256"; - private Mac mac; - /** * Initiates RAKP-HMAC-SHA256 authentication algorithm. * - * @throws NoSuchAlgorithmException - * - when initiation of the algorithm fails + * @throws NoSuchAlgorithmException - when initiation of the algorithm fails */ public AuthenticationRakpHmacSha256() throws NoSuchAlgorithmException { - mac = Mac.getInstance(ALGORITHM_NAME); + super(); } @Override @@ -53,39 +45,6 @@ public byte getCode() { return SecurityConstants.AA_RAKP_HMAC_SHA256; } - @Override - public boolean checkKeyExchangeAuthenticationCode(byte[] data, byte[] key, String password) - throws NoSuchAlgorithmException, InvalidKeyException { - byte[] check = getKeyExchangeAuthenticationCode(data, password); - return Arrays.equals(check, key); - } - - @Override - public byte[] getKeyExchangeAuthenticationCode(byte[] data, String password) - throws NoSuchAlgorithmException, InvalidKeyException { - - byte[] key = password.getBytes(); - - SecretKeySpec sKey = new SecretKeySpec(key, ALGORITHM_NAME); - mac.init(sKey); - - return mac.doFinal(data); - } - - @Override - public boolean doIntegrityCheck(byte[] data, byte[] reference, byte[] sik) - throws InvalidKeyException, NoSuchAlgorithmException { - - SecretKeySpec sKey = new SecretKeySpec(sik, ALGORITHM_NAME); - mac.init(sKey); - - byte[] result = new byte[getIntegrityCheckBaseLength()]; - - System.arraycopy(mac.doFinal(data), 0, result, 0, getIntegrityCheckBaseLength()); - - return Arrays.equals(result, reference); - } - @Override public int getKeyLength() { return 32; diff --git a/src/main/java/org/sentrysoftware/ipmi/core/coding/security/AuthenticationRakpNone.java b/src/main/java/org/sentrysoftware/ipmi/core/coding/security/AuthenticationRakpNone.java index b40e32b..396460f 100644 --- a/src/main/java/org/sentrysoftware/ipmi/core/coding/security/AuthenticationRakpNone.java +++ b/src/main/java/org/sentrysoftware/ipmi/core/coding/security/AuthenticationRakpNone.java @@ -1,5 +1,7 @@ package org.sentrysoftware.ipmi.core.coding.security; +import java.security.NoSuchAlgorithmException; + /*- * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲ * IPMI Java Client @@ -27,52 +29,60 @@ */ public class AuthenticationRakpNone extends AuthenticationAlgorithm { - @Override - public byte getCode() { - return SecurityConstants.AA_RAKP_NONE; - } - - /** - * Checks value of the Key Exchange Authentication Code in RAKP messages - * using the RAKP-None algorithm. + /** + * Constructs an instance of the RAKP-None authentication algorithm. + * + * Since this algorithm does not require cryptographic operations, it uses + * {@code super(true)} to skip MAC initialization in the parent class. + * */ - @Override - public boolean checkKeyExchangeAuthenticationCode(byte[] data, byte[] key, String password) { - return true; - } + public AuthenticationRakpNone() { + super(true); + } - /** - * Calculates value of the Key Exchange Authentication Code in RAKP messages - * using the RAKP-None algorithm. - */ - @Override - public byte[] getKeyExchangeAuthenticationCode(byte[] data, - String password) { - return new byte[0]; - } + @Override + public byte getCode() { + return SecurityConstants.AA_RAKP_NONE; + } - /** - * Performs Integrity Check in RAKP 4 message - * using the RAKP-None algorithm. - */ - @Override - public boolean doIntegrityCheck(byte[] data, byte[] reference, byte[] sik) { - return true; - } + /** + * Checks value of the Key Exchange Authentication Code in RAKP messages using + * the RAKP-None algorithm. + */ + @Override + public boolean checkKeyExchangeAuthenticationCode(byte[] data, byte[] key, String password) { + return true; + } + + /** + * Calculates value of the Key Exchange Authentication Code in RAKP messages + * using the RAKP-None algorithm. + */ + @Override + public byte[] getKeyExchangeAuthenticationCode(byte[] data, String password) { + return new byte[0]; + } + + /** + * Performs Integrity Check in RAKP 4 message using the RAKP-None algorithm. + */ + @Override + public boolean doIntegrityCheck(byte[] data, byte[] reference, byte[] sik) { + return true; + } - @Override - public int getKeyLength() { - return 0; - } + @Override + public int getKeyLength() { + return 0; + } - @Override - public int getIntegrityCheckBaseLength() { - return 0; - } + @Override + public int getIntegrityCheckBaseLength() { + return 0; + } @Override public String getAlgorithmName() { return ""; } - } diff --git a/src/main/java/org/sentrysoftware/ipmi/core/coding/security/ConfidentialityAesCbc128.java b/src/main/java/org/sentrysoftware/ipmi/core/coding/security/ConfidentialityAesCbc128.java index 5a2338a..1d29919 100644 --- a/src/main/java/org/sentrysoftware/ipmi/core/coding/security/ConfidentialityAesCbc128.java +++ b/src/main/java/org/sentrysoftware/ipmi/core/coding/security/ConfidentialityAesCbc128.java @@ -24,6 +24,7 @@ import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; +import java.util.Arrays; import javax.crypto.Cipher; import javax.crypto.Mac; @@ -38,8 +39,10 @@ */ public class ConfidentialityAesCbc128 extends ConfidentialityAlgorithm { - private static final byte[] CONST2 = new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 }; + protected static final byte[] CONST2 = new byte[20]; + static { + Arrays.fill(CONST2, (byte) 2); + } private Cipher cipher; diff --git a/src/main/java/org/sentrysoftware/ipmi/core/coding/security/IntegrityAlgorithm.java b/src/main/java/org/sentrysoftware/ipmi/core/coding/security/IntegrityAlgorithm.java index feb2f46..4f017e6 100644 --- a/src/main/java/org/sentrysoftware/ipmi/core/coding/security/IntegrityAlgorithm.java +++ b/src/main/java/org/sentrysoftware/ipmi/core/coding/security/IntegrityAlgorithm.java @@ -26,6 +26,11 @@ import org.sentrysoftware.ipmi.core.common.TypeConverter; import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; +import java.util.Arrays; + +import javax.crypto.Mac; +import javax.crypto.spec.SecretKeySpec; /** * Interface for Integrity Algorithms. All classes extending this one must @@ -33,79 +38,129 @@ */ public abstract class IntegrityAlgorithm { - protected byte[] sik; - - public IntegrityAlgorithm() { - - } - - protected static final byte[] CONST1 = new byte[] { - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,1 - }; - - /** - * Initializes Integrity Algorithm - * - * @param sik - * - Session Integrity Key calculated during the opening of the - * session or user password if 'one-key' logins are enabled. - */ - public void initialize(byte[] sik) throws InvalidKeyException { - this.sik = sik; - } - - /** - * Returns the algorithm's ID. - */ - public abstract byte getCode(); - - /** - * Creates AuthCode field for message. - * - * @param base - * - data starting with the AuthType/Format field up to and - * including the field that immediately precedes the AuthCode - * field - * @return AuthCode field. Might be null if empty AuthCOde field is - * generated. - * - * @see Rakp1#calculateSik(org.sentrysoftware.ipmi.core.coding.commands.session.Rakp1ResponseData) - */ - public abstract byte[] generateAuthCode(byte[] base); - - /** - * Modifies the algorithm base since with null Auth Code during encoding - * Integrity Pad isn't calculated. - * - * @param base - * - integrity algorithm base without Integrity Pad. - * @param authCodeLength - * - expected length of the Auth Code field. - * @return - integrity algorithm base with Integrity Pad and updated Pad - * Length field. - */ - protected byte[] injectIntegrityPad(byte[] base, int authCodeLength) { - int pad = 0; - if ((base.length + authCodeLength) % 4 != 0) { - pad = 4 - (base.length + authCodeLength) % 4; - } - - if (pad != 0) { - byte[] newBase = new byte[base.length + pad]; - - System.arraycopy(base, 0, newBase, 0, base.length - 2); - - for (int i = base.length - 2; i < base.length - 2 + pad; ++i) { - newBase[i] = TypeConverter.intToByte(0xff); - } - - newBase[newBase.length - 2] = TypeConverter.intToByte(pad); - - newBase[newBase.length - 1] = base[base.length - 1]; - - return newBase; - } else { - return base; - } - } + protected static final byte[] CONST1 = new byte[20]; + static { + Arrays.fill(CONST1, (byte) 1); + } + + protected byte[] sik; + private final Mac mac; + + /** + * Constructs an integrity algorithm + * + * @throws NoSuchAlgorithmException - when initiation of the algorithm fails + */ + protected IntegrityAlgorithm() throws NoSuchAlgorithmException { + mac = Mac.getInstance(getAlgorithmName()); + } + + /** + * Constructor that allows skipping HMAC initialization. + * + * @param noMacInit If {@code true}, HMAC will not be initialized. + */ + protected IntegrityAlgorithm(boolean noMacInit) { + this.mac = null; + } + + /** + * Initializes Integrity Algorithm + * + * @param sik - Session Integrity Key calculated during the opening of the + * session or user password if 'one-key' logins are enabled. + */ + public void initialize(byte[] sik) throws InvalidKeyException { + this.sik = sik; + + SecretKeySpec k1 = new SecretKeySpec(sik, getAlgorithmName()); + + mac.init(k1); + k1 = new SecretKeySpec(mac.doFinal(CONST1), getAlgorithmName()); + + mac.init(k1); + } + + /** + * Returns the algorithm's ID. + */ + public abstract byte getCode(); + + /** + * Creates AuthCode field for message. + * + * @param base - data starting with the AuthType/Format field up to and + * including the field that immediately precedes the AuthCode field + * @return AuthCode field. Might be null if empty AuthCOde field is generated. + * + * @see Rakp1#calculateSik(org.sentrysoftware.ipmi.core.coding.commands.session.Rakp1ResponseData) + */ + public byte[] generateAuthCode(final byte[] base) { + + if (sik == null) { + throw new NullPointerException("Algorithm not initialized."); + } + + byte[] result = new byte[getAuthCodeLength()]; + byte[] updatedBase; + + if (base[base.length - 2] == 0) { // pas de padding + updatedBase = injectIntegrityPad(base, getAuthCodeLength()); + } else { + updatedBase = base; + } + + System.arraycopy(mac.doFinal(updatedBase), 0, result, 0, getAuthCodeLength()); + + return result; + } + + /** + * Modifies the algorithm base since with null Auth Code during encoding + * Integrity Pad isn't calculated. + * + * @param base - integrity algorithm base without Integrity Pad. + * @param authCodeLength - expected length of the Auth Code field. + * @return - integrity algorithm base with Integrity Pad and updated Pad Length + * field. + */ + protected byte[] injectIntegrityPad(byte[] base, int authCodeLength) { + int pad = 0; + if ((base.length + authCodeLength) % 4 != 0) { + pad = 4 - (base.length + authCodeLength) % 4; + } + + if (pad != 0) { + byte[] newBase = new byte[base.length + pad]; + + System.arraycopy(base, 0, newBase, 0, base.length - 2); + + for (int i = base.length - 2; i < base.length - 2 + pad; ++i) { + newBase[i] = TypeConverter.intToByte(0xff); + } + + newBase[newBase.length - 2] = TypeConverter.intToByte(pad); + + newBase[newBase.length - 1] = base[base.length - 1]; + + return newBase; + } else { + return base; + } + } + + /** + * Returns the name of the algorithm. + * + * @return The algorithm name as a {@code String}. + */ + public abstract String getAlgorithmName(); + + /** + * Returns the length of the authentication code + * + * @return The length of the authentication code in bytes. + */ + public abstract int getAuthCodeLength(); + } diff --git a/src/main/java/org/sentrysoftware/ipmi/core/coding/security/IntegrityHmacMd5_128.java b/src/main/java/org/sentrysoftware/ipmi/core/coding/security/IntegrityHmacMd5_128.java index 98533fa..61b2fa0 100644 --- a/src/main/java/org/sentrysoftware/ipmi/core/coding/security/IntegrityHmacMd5_128.java +++ b/src/main/java/org/sentrysoftware/ipmi/core/coding/security/IntegrityHmacMd5_128.java @@ -22,9 +22,6 @@ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱ */ -import javax.crypto.Mac; -import javax.crypto.spec.SecretKeySpec; -import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; /** @@ -32,54 +29,29 @@ */ public class IntegrityHmacMd5_128 extends IntegrityAlgorithm { - public static final String ALGORITHM_NAME = "HmacMD5"; - private Mac mac; - - /** - * Initiates HMAC-MD5-128 integrity algorithm. - * - * @throws NoSuchAlgorithmException - * - when initiation of the algorithm fails - */ - public IntegrityHmacMd5_128() throws NoSuchAlgorithmException { - mac = Mac.getInstance(ALGORITHM_NAME); - - } - - @Override - public void initialize(byte[] sik) throws InvalidKeyException { - super.initialize(sik); - - SecretKeySpec k1 = new SecretKeySpec(sik, ALGORITHM_NAME); - - mac.init(k1); - k1 = new SecretKeySpec(mac.doFinal(CONST1), ALGORITHM_NAME); - - mac.init(k1); - } - - @Override - public byte getCode() { - return SecurityConstants.IA_HMAC_MD5_128; - } - - @Override - public byte[] generateAuthCode(final byte[] base) { - if (sik == null) { - throw new NullPointerException("Algorithm not initialized."); - } - - byte[] result = new byte[16]; - byte[] updatedBase; - - if(base[base.length - 2] == 0 /*there are no integrity pad bytes*/) { - updatedBase = injectIntegrityPad(base,16); - } else { - updatedBase = base; - } - - System.arraycopy(mac.doFinal(updatedBase), 0, result, 0, 16); - - return result; - } + public static final String ALGORITHM_NAME = "HmacMD5"; + + /** + * Initiates HMAC-MD5-128 integrity algorithm. + * + * @throws NoSuchAlgorithmException - when initiation of the algorithm fails + */ + public IntegrityHmacMd5_128() throws NoSuchAlgorithmException { + super(); + } + + @Override + public byte getCode() { + return SecurityConstants.IA_HMAC_MD5_128; + } + + @Override + public String getAlgorithmName() { + return ALGORITHM_NAME; + } + + @Override + public int getAuthCodeLength() { + return 16; + } } \ No newline at end of file diff --git a/src/main/java/org/sentrysoftware/ipmi/core/coding/security/IntegrityHmacSha1_96.java b/src/main/java/org/sentrysoftware/ipmi/core/coding/security/IntegrityHmacSha1_96.java index db51f23..cef543d 100644 --- a/src/main/java/org/sentrysoftware/ipmi/core/coding/security/IntegrityHmacSha1_96.java +++ b/src/main/java/org/sentrysoftware/ipmi/core/coding/security/IntegrityHmacSha1_96.java @@ -22,10 +22,7 @@ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱ */ -import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; -import javax.crypto.Mac; -import javax.crypto.spec.SecretKeySpec; /** * HMAC-SHA1-96 integrity algorithm. @@ -33,7 +30,6 @@ public class IntegrityHmacSha1_96 extends IntegrityAlgorithm { public static final String ALGORITHM_NAME = "HmacSHA1"; - private Mac mac; /** * Initiates HMAC-SHA1-96 integrity algorithm. @@ -42,19 +38,7 @@ public class IntegrityHmacSha1_96 extends IntegrityAlgorithm { * - when initiation of the algorithm fails */ public IntegrityHmacSha1_96() throws NoSuchAlgorithmException { - mac = Mac.getInstance(ALGORITHM_NAME); - } - - @Override - public void initialize(byte[] sik) throws InvalidKeyException { - super.initialize(sik); - - SecretKeySpec k1 = new SecretKeySpec(sik, ALGORITHM_NAME); - - mac.init(k1); - k1 = new SecretKeySpec(mac.doFinal(CONST1), ALGORITHM_NAME); - - mac.init(k1); + super(); } @Override @@ -63,23 +47,12 @@ public byte getCode() { } @Override - public byte[] generateAuthCode(final byte[] base) { - if (sik == null) { - throw new NullPointerException("Algorithm not initialized."); - } - - byte[] result = new byte[12]; - byte[] updatedBase; - - if(base[base.length - 2] == 0 /*there are no integrity pad bytes*/) { - updatedBase = injectIntegrityPad(base,12); - } else { - updatedBase = base; - } - - System.arraycopy(mac.doFinal(updatedBase), 0, result, 0, 12); - - return result; + public String getAlgorithmName() { + return ALGORITHM_NAME; } - + + @Override + public int getAuthCodeLength() { + return 12; + } } diff --git a/src/main/java/org/sentrysoftware/ipmi/core/coding/security/IntegrityHmacSha256_128.java b/src/main/java/org/sentrysoftware/ipmi/core/coding/security/IntegrityHmacSha256_128.java index af59074..7d1a64d 100644 --- a/src/main/java/org/sentrysoftware/ipmi/core/coding/security/IntegrityHmacSha256_128.java +++ b/src/main/java/org/sentrysoftware/ipmi/core/coding/security/IntegrityHmacSha256_128.java @@ -22,10 +22,7 @@ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱ */ -import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; -import javax.crypto.Mac; -import javax.crypto.spec.SecretKeySpec; /** * HMAC-SHA256-128 integrity algorithm. @@ -33,7 +30,6 @@ public class IntegrityHmacSha256_128 extends IntegrityAlgorithm { private static final String ALGORITHM_NAME = "HmacSHA256"; - private Mac mac; /** * Initiates HMAC-SHA1-96 integrity algorithm. @@ -41,19 +37,7 @@ public class IntegrityHmacSha256_128 extends IntegrityAlgorithm { * @throws NoSuchAlgorithmException when initiation of the algorithm fails */ public IntegrityHmacSha256_128() throws NoSuchAlgorithmException { - mac = Mac.getInstance(ALGORITHM_NAME); - } - - @Override - public void initialize(byte[] sik) throws InvalidKeyException { - super.initialize(sik); - - SecretKeySpec k1 = new SecretKeySpec(sik, ALGORITHM_NAME); - - mac.init(k1); - k1 = new SecretKeySpec(mac.doFinal(CONST1), ALGORITHM_NAME); - - mac.init(k1); + super(); } @Override @@ -62,24 +46,13 @@ public byte getCode() { } @Override - public byte[] generateAuthCode(byte[] base) { - - if (sik == null) { - throw new NullPointerException("Algorithm not initialized."); - } - - byte[] result = new byte[16]; - byte[] updatedBase; - - if (base[base.length - 2] == 0 /* there are no integrity pad bytes */) { - updatedBase = injectIntegrityPad(base, 16); - } else { - updatedBase = base; - } - - System.arraycopy(mac.doFinal(updatedBase), 0, result, 0, 16); + public String getAlgorithmName() { + return ALGORITHM_NAME; + } - return result; + @Override + public int getAuthCodeLength() { + return 16; } } diff --git a/src/main/java/org/sentrysoftware/ipmi/core/coding/security/IntegrityNone.java b/src/main/java/org/sentrysoftware/ipmi/core/coding/security/IntegrityNone.java index f3088ab..baf7ec3 100644 --- a/src/main/java/org/sentrysoftware/ipmi/core/coding/security/IntegrityNone.java +++ b/src/main/java/org/sentrysoftware/ipmi/core/coding/security/IntegrityNone.java @@ -22,23 +22,40 @@ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱ */ +import java.security.InvalidKeyException; + /** * Class representing RAKP-None integrity algorithm */ public class IntegrityNone extends IntegrityAlgorithm { - public IntegrityNone() { - super(); - } + public IntegrityNone() { + super(true); + } + + @Override + public void initialize(byte[] sik) throws InvalidKeyException { + this.sik = sik; + } + + @Override + public byte getCode() { + return SecurityConstants.IA_NONE; + } + + @Override + public byte[] generateAuthCode(byte[] base) { + return new byte[0]; + } - @Override - public byte getCode() { - return SecurityConstants.IA_NONE; - } + @Override + public String getAlgorithmName() { + return ""; + } - @Override - public byte[] generateAuthCode(byte[] base) { - return null; - } + @Override + public int getAuthCodeLength() { + return 0; + } } From 5754f3fd7505e8343648ac0de9491f0b5549a318 Mon Sep 17 00:00:00 2001 From: Safae Ajib Date: Fri, 7 Feb 2025 09:11:43 +0100 Subject: [PATCH 07/11] Issue #46: Add support for SHA-256 and MD5 authentication algorithms * Updated IntegrityNone --- .../sentrysoftware/ipmi/core/coding/security/IntegrityNone.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/sentrysoftware/ipmi/core/coding/security/IntegrityNone.java b/src/main/java/org/sentrysoftware/ipmi/core/coding/security/IntegrityNone.java index baf7ec3..a0ebc52 100644 --- a/src/main/java/org/sentrysoftware/ipmi/core/coding/security/IntegrityNone.java +++ b/src/main/java/org/sentrysoftware/ipmi/core/coding/security/IntegrityNone.java @@ -45,7 +45,7 @@ public byte getCode() { @Override public byte[] generateAuthCode(byte[] base) { - return new byte[0]; + return null; } @Override From 9de3231c99b3449437e10760e19dcf3f8437c691 Mon Sep 17 00:00:00 2001 From: Safae Ajib Date: Fri, 7 Feb 2025 13:54:24 +0100 Subject: [PATCH 08/11] Issue #46 : Add support for SHA-256 and MD5 authentication algorithms * Updated CipherSuite, ConfidentialityAesCbc128, AuthenticationRakpNone, AuthenticatioRakpHmacSha1, IntegrityAlgorithm, AuthenticationAlgorithm, and IntegrityHmacSha1_96. --- .../security/AuthenticationAlgorithm.java | 40 ++-- .../security/AuthenticationRakpHmacMd5.java | 6 +- .../security/AuthenticationRakpHmacSha1.java | 12 +- .../AuthenticationRakpHmacSha256.java | 6 +- .../security/AuthenticationRakpNone.java | 6 +- .../core/coding/security/CipherSuite.java | 203 +++++------------- .../coding/security/IntegrityAlgorithm.java | 51 +++-- .../coding/security/IntegrityHmacMd5_128.java | 6 +- .../coding/security/IntegrityHmacSha1_96.java | 7 +- .../security/IntegrityHmacSha256_128.java | 6 +- .../core/coding/security/IntegrityNone.java | 5 +- 11 files changed, 141 insertions(+), 207 deletions(-) diff --git a/src/main/java/org/sentrysoftware/ipmi/core/coding/security/AuthenticationAlgorithm.java b/src/main/java/org/sentrysoftware/ipmi/core/coding/security/AuthenticationAlgorithm.java index 7155488..a003f1c 100644 --- a/src/main/java/org/sentrysoftware/ipmi/core/coding/security/AuthenticationAlgorithm.java +++ b/src/main/java/org/sentrysoftware/ipmi/core/coding/security/AuthenticationAlgorithm.java @@ -40,21 +40,36 @@ public abstract class AuthenticationAlgorithm { private final Mac mac; /** - * Constructs an authentication algorithm + * Constructs an authentication algorithm. + */ + protected AuthenticationAlgorithm(String algorithmName) { + this(newMacInstance(algorithmName)); + } + + /** + * Constructs an authentication algorithm with the provided MAC. * - * @throws NoSuchAlgorithmException + * @param mac the MAC instance to use */ - protected AuthenticationAlgorithm() throws NoSuchAlgorithmException { - this.mac = Mac.getInstance(getAlgorithmName()); + private AuthenticationAlgorithm(Mac mac) { + this.mac = mac; } /** - * Constructs an authentication algorithm instance without initializing the MAC. + * Constructs a Mac object that implements the given MAC algorithm. * - * @param noMacInit If {@code true}, the MAC instance will not be initialized. + * @param algorithmName the name of the algorithm to use + * @return The Mac object that implements the specified MAC algorithm. */ - protected AuthenticationAlgorithm(boolean noMacInit) { - this.mac = null; + private static Mac newMacInstance(final String algorithmName) { + if (algorithmName == null || algorithmName.trim().isEmpty()) { + return null; + } + try { + return Mac.getInstance(algorithmName); + } catch (NoSuchAlgorithmException e) { + throw new IllegalArgumentException("Algorithm " + algorithmName + " is not available", e); + } } /** @@ -101,7 +116,7 @@ public boolean checkKeyExchangeAuthenticationCode(byte[] data, byte[] key, Strin public byte[] getKeyExchangeAuthenticationCode(byte[] data, String password) throws NoSuchAlgorithmException, InvalidKeyException { - byte[] key = password.getBytes(); + final byte[] key = password.getBytes(); SecretKeySpec sKey = new SecretKeySpec(key, getAlgorithmName()); mac.init(sKey); @@ -126,10 +141,11 @@ public boolean doIntegrityCheck(byte[] data, byte[] reference, byte[] sik) SecretKeySpec sKey = new SecretKeySpec(sik, getAlgorithmName()); mac.init(sKey); + + final int integrityCheckLength = getIntegrityCheckBaseLength(); + final byte[] result = new byte[integrityCheckLength]; - byte[] result = new byte[getIntegrityCheckBaseLength()]; - - System.arraycopy(mac.doFinal(data), 0, result, 0, getIntegrityCheckBaseLength()); + System.arraycopy(mac.doFinal(data), 0, result, 0, integrityCheckLength); return Arrays.equals(result, reference); } diff --git a/src/main/java/org/sentrysoftware/ipmi/core/coding/security/AuthenticationRakpHmacMd5.java b/src/main/java/org/sentrysoftware/ipmi/core/coding/security/AuthenticationRakpHmacMd5.java index a97639e..946c7ac 100644 --- a/src/main/java/org/sentrysoftware/ipmi/core/coding/security/AuthenticationRakpHmacMd5.java +++ b/src/main/java/org/sentrysoftware/ipmi/core/coding/security/AuthenticationRakpHmacMd5.java @@ -33,11 +33,9 @@ public class AuthenticationRakpHmacMd5 extends AuthenticationAlgorithm { /** * Initiates RAKP-HMAC-MD5 authentication algorithm. - * - * @throws NoSuchAlgorithmException - when initiation of the algorithm fails */ - public AuthenticationRakpHmacMd5() throws NoSuchAlgorithmException { - super(); + public AuthenticationRakpHmacMd5() { + super(ALGORITHM_NAME); } @Override diff --git a/src/main/java/org/sentrysoftware/ipmi/core/coding/security/AuthenticationRakpHmacSha1.java b/src/main/java/org/sentrysoftware/ipmi/core/coding/security/AuthenticationRakpHmacSha1.java index 9a61af4..4f3a5cd 100644 --- a/src/main/java/org/sentrysoftware/ipmi/core/coding/security/AuthenticationRakpHmacSha1.java +++ b/src/main/java/org/sentrysoftware/ipmi/core/coding/security/AuthenticationRakpHmacSha1.java @@ -28,18 +28,16 @@ * RAKP-HMAC-SHA1 authentication algorithm. */ public class AuthenticationRakpHmacSha1 extends AuthenticationAlgorithm { - + + private static final String ALGORITHM_NAME = "HmacSHA1"; + /** * Initiates RAKP-HMAC-SHA1 authentication algorithm. - * - * @throws NoSuchAlgorithmException - when initiation of the algorithm fails */ - public AuthenticationRakpHmacSha1() throws NoSuchAlgorithmException { - super(); + public AuthenticationRakpHmacSha1() { + super(ALGORITHM_NAME); } - private static final String ALGORITHM_NAME = "HmacSHA1"; - @Override public byte getCode() { return SecurityConstants.AA_RAKP_HMAC_SHA1; diff --git a/src/main/java/org/sentrysoftware/ipmi/core/coding/security/AuthenticationRakpHmacSha256.java b/src/main/java/org/sentrysoftware/ipmi/core/coding/security/AuthenticationRakpHmacSha256.java index 2880e7d..ce8447d 100644 --- a/src/main/java/org/sentrysoftware/ipmi/core/coding/security/AuthenticationRakpHmacSha256.java +++ b/src/main/java/org/sentrysoftware/ipmi/core/coding/security/AuthenticationRakpHmacSha256.java @@ -33,11 +33,9 @@ public class AuthenticationRakpHmacSha256 extends AuthenticationAlgorithm { /** * Initiates RAKP-HMAC-SHA256 authentication algorithm. - * - * @throws NoSuchAlgorithmException - when initiation of the algorithm fails */ - public AuthenticationRakpHmacSha256() throws NoSuchAlgorithmException { - super(); + public AuthenticationRakpHmacSha256() { + super(ALGORITHM_NAME); } @Override diff --git a/src/main/java/org/sentrysoftware/ipmi/core/coding/security/AuthenticationRakpNone.java b/src/main/java/org/sentrysoftware/ipmi/core/coding/security/AuthenticationRakpNone.java index 396460f..efcff51 100644 --- a/src/main/java/org/sentrysoftware/ipmi/core/coding/security/AuthenticationRakpNone.java +++ b/src/main/java/org/sentrysoftware/ipmi/core/coding/security/AuthenticationRakpNone.java @@ -31,13 +31,9 @@ public class AuthenticationRakpNone extends AuthenticationAlgorithm { /** * Constructs an instance of the RAKP-None authentication algorithm. - * - * Since this algorithm does not require cryptographic operations, it uses - * {@code super(true)} to skip MAC initialization in the parent class. - * */ public AuthenticationRakpNone() { - super(true); + super(""); } @Override diff --git a/src/main/java/org/sentrysoftware/ipmi/core/coding/security/CipherSuite.java b/src/main/java/org/sentrysoftware/ipmi/core/coding/security/CipherSuite.java index 143c890..fab9682 100644 --- a/src/main/java/org/sentrysoftware/ipmi/core/coding/security/CipherSuite.java +++ b/src/main/java/org/sentrysoftware/ipmi/core/coding/security/CipherSuite.java @@ -31,6 +31,7 @@ import java.security.NoSuchAlgorithmException; import java.util.ArrayList; import java.util.List; +import java.util.function.Supplier; /** * Provides cipher suite (authentication, confidentiality and integrity @@ -81,64 +82,54 @@ public void initializeAlgorithms(byte[] sik) throws InvalidKeyException, NoSuchA getConfidentialityAlgorithm().initialize(sik, getAuthenticationAlgorithm()); } - /** - * Returns instance of AuthenticationAlgorithm class. - * - * @throws IllegalArgumentException - * when authentication algorithm code is incorrect. - */ - public AuthenticationAlgorithm getAuthenticationAlgorithm() { - if (aa != null && aa.getCode() != authenticationAlgorithm) { - throw new IllegalArgumentException( - "Invalid authentication algorithm code"); - } - switch (authenticationAlgorithm) { - case SecurityConstants.AA_RAKP_NONE: - if (aa == null) { - aa = new AuthenticationRakpNone(); - } - return aa; - case SecurityConstants.AA_RAKP_HMAC_SHA1: - return instantiateRakpHmacSha1Algorithm(); - case SecurityConstants.AA_RAKP_HMAC_MD5: - return instantiateRakpHmacMd5Algorithm(); - case SecurityConstants.AA_RAKP_HMAC_SHA256: - return instantiateRakpHmacSha256Algorithm(); - default: - throw new IllegalArgumentException("Invalid authentication algorithm."); - } - } - - /** - * Returns instance of IntegrityAlgorithm class. - * - * @throws IllegalArgumentException - * when integrity algorithm code is incorrect. - */ - public IntegrityAlgorithm getIntegrityAlgorithm(){ - if (ia != null && ia.getCode() != integrityAlgorithm) { - throw new IllegalArgumentException( - "Invalid integrity algorithm code"); - } - switch (integrityAlgorithm) { - case SecurityConstants.IA_NONE: - if (ia == null) { - ia = new IntegrityNone(); - } - return ia; - case SecurityConstants.IA_HMAC_SHA1_96: - return instantiateIntegrityHmacSha196Algorithm(); - case SecurityConstants.IA_MD5_128: - // TODO: MD5-128 - case SecurityConstants.IA_HMAC_MD5_128: - return instantiateIntegrityHmacMd5128Algorithm(); - case SecurityConstants.IA_HMAC_SHA256_128: - return instantiateIntegrityHmacSha256128Algorithm(); - default: - throw new IllegalArgumentException("Invalid integrity algorithm."); + /** + * Returns instance of AuthenticationAlgorithm class. + * + * @throws IllegalArgumentException when authentication algorithm code is + * incorrect. + */ + public AuthenticationAlgorithm getAuthenticationAlgorithm() { + if (aa != null && aa.getCode() != authenticationAlgorithm) { + throw new IllegalArgumentException("Invalid authentication algorithm code"); + } + switch (authenticationAlgorithm) { + case SecurityConstants.AA_RAKP_NONE: + return instantiateAuthenticationAlgorithm(AuthenticationRakpNone::new); + case SecurityConstants.AA_RAKP_HMAC_SHA1: + return instantiateAuthenticationAlgorithm(AuthenticationRakpHmacSha1::new); + case SecurityConstants.AA_RAKP_HMAC_MD5: + return instantiateAuthenticationAlgorithm(AuthenticationRakpHmacMd5::new); + case SecurityConstants.AA_RAKP_HMAC_SHA256: + return instantiateAuthenticationAlgorithm(AuthenticationRakpHmacSha256::new); + default: + throw new IllegalArgumentException("Invalid authentication algorithm."); + } + } - } - } + /** + * Returns instance of IntegrityAlgorithm class. + * + * @throws IllegalArgumentException when integrity algorithm code is incorrect. + */ + public IntegrityAlgorithm getIntegrityAlgorithm() { + if (ia != null && ia.getCode() != integrityAlgorithm) { + throw new IllegalArgumentException("Invalid integrity algorithm code"); + } + switch (integrityAlgorithm) { + case SecurityConstants.IA_NONE: + return instantiateIntegrityAlgorithm(IntegrityNone::new); + case SecurityConstants.IA_HMAC_SHA1_96: + return instantiateIntegrityAlgorithm(IntegrityHmacSha1_96::new); + case SecurityConstants.IA_MD5_128: + // TODO: MD5-128 + case SecurityConstants.IA_HMAC_MD5_128: + return instantiateIntegrityAlgorithm(IntegrityHmacMd5_128::new); + case SecurityConstants.IA_HMAC_SHA256_128: + return instantiateIntegrityAlgorithm(IntegrityHmacSha256_128::new); + default: + throw new IllegalArgumentException("Invalid integrity algorithm."); + } + } /** * Returns instance of ConfidentialityAlgorithm class. @@ -231,104 +222,28 @@ public static CipherSuite getEmpty() { } /** - * Creates an instance of AuthenticationRakpHmacSha1. + * Creates an instance of AuthenticationAlgorithm. * - * @return An instance of {@code AuthenticationRakpHmacSha1}. - * @throws IllegalArgumentException if algorithm initialization fails. + * @param supplier constructor of the algorithm */ - private AuthenticationAlgorithm instantiateRakpHmacSha1Algorithm() { + private AuthenticationAlgorithm instantiateAuthenticationAlgorithm( + final Supplier constructor) { if (aa == null) { - try { - aa = new AuthenticationRakpHmacSha1(); - } catch (NoSuchAlgorithmException e) { - throw new IllegalArgumentException("Initiation of the algorithm failed", e); - } + aa = constructor.get(); } return aa; } - - /** - * Creates an instance of AuthenticationRakpHmacMd5. - * - * @return An instance of {@code AuthenticationRakpHmacMd5}. - * @throws IllegalArgumentException if algorithm initialization fails. - */ - private AuthenticationAlgorithm instantiateRakpHmacMd5Algorithm() { - if (aa == null) { - try { - aa = new AuthenticationRakpHmacMd5(); - } catch (NoSuchAlgorithmException e) { - throw new IllegalArgumentException("Initiation of the algorithm failed", e); - } - } - return aa; - } - - /** - * Creates an instance of AuthenticationRakpHmacSha256. - * - * @return An instance of {@code AuthenticationRakpHmacSha256}. - * @throws IllegalArgumentException if algorithm initialization fails. - */ - private AuthenticationAlgorithm instantiateRakpHmacSha256Algorithm() { - if (aa == null) { - try { - aa = new AuthenticationRakpHmacSha256(); - } catch (NoSuchAlgorithmException e) { - throw new IllegalArgumentException("Initiation of the algorithm failed", e); - } - } - return aa; - } - - /** - * Creates an instance of IntegrityHmacSha1_96. - * - * @return An instance of {@code IntegrityHmacSha1_96}. - * @throws IllegalArgumentException if the algorithm initiation fails. - */ - private IntegrityAlgorithm instantiateIntegrityHmacSha196Algorithm() { - if (ia == null) { - try { - ia = new IntegrityHmacSha1_96(); - } catch (NoSuchAlgorithmException e) { - throw new IllegalArgumentException("Initiation of the algorithm failed", e); - } - } - return ia; - } - - /** - * Creates an instance of IntegrityHmacMd5_128. - * - * @return An instance of {@code IntegrityHmacMd5_128}. - * @throws IllegalArgumentException if the algorithm initiation fails. - */ - private IntegrityAlgorithm instantiateIntegrityHmacMd5128Algorithm() { - if (ia == null) { - try { - ia = new IntegrityHmacMd5_128(); - } catch (NoSuchAlgorithmException e) { - throw new IllegalArgumentException("Initiation of the algorithm failed", e); - } - } - return ia; - } - + /** - * Creates an instance of IntegrityHmacSha256_128. + * Creates an instance of IntegrityAlgorithm. * - * @return An instance of {@code IntegrityHmacSha256_128}. - * @throws IllegalArgumentException if the algorithm initiation fails. + * @param supplier constructor of the algorithm */ - private IntegrityAlgorithm instantiateIntegrityHmacSha256128Algorithm() { + private IntegrityAlgorithm instantiateIntegrityAlgorithm(final Supplier constructor) { if (ia == null) { - try { - ia = new IntegrityHmacSha256_128(); - } catch (NoSuchAlgorithmException e) { - throw new IllegalArgumentException("Initiation of the algorithm failed", e); - } + ia = constructor.get(); } return ia; } + } diff --git a/src/main/java/org/sentrysoftware/ipmi/core/coding/security/IntegrityAlgorithm.java b/src/main/java/org/sentrysoftware/ipmi/core/coding/security/IntegrityAlgorithm.java index 4f017e6..6c3f612 100644 --- a/src/main/java/org/sentrysoftware/ipmi/core/coding/security/IntegrityAlgorithm.java +++ b/src/main/java/org/sentrysoftware/ipmi/core/coding/security/IntegrityAlgorithm.java @@ -47,21 +47,36 @@ public abstract class IntegrityAlgorithm { private final Mac mac; /** - * Constructs an integrity algorithm - * - * @throws NoSuchAlgorithmException - when initiation of the algorithm fails + * Constructs an integrity algorithm. */ - protected IntegrityAlgorithm() throws NoSuchAlgorithmException { - mac = Mac.getInstance(getAlgorithmName()); + protected IntegrityAlgorithm(String algorithmName) { + this(newMacInstance(algorithmName)); } /** - * Constructor that allows skipping HMAC initialization. - * - * @param noMacInit If {@code true}, HMAC will not be initialized. + * Constructs an integrity algorithm with the provided MAC. + * + * @param mac the MAC instance to use + */ + private IntegrityAlgorithm(Mac mac) { + this.mac = mac; + } + + /** + * Constructs a Mac object that implements the given MAC algorithm. + * + * @param algorithmName the name of the algorithm to use + * @return The Mac object that implements the specified MAC algorithm. */ - protected IntegrityAlgorithm(boolean noMacInit) { - this.mac = null; + private static Mac newMacInstance(final String algorithmName) { + if (algorithmName == null || algorithmName.trim().isEmpty()) { + return null; + } + try { + return Mac.getInstance(algorithmName); + } catch (NoSuchAlgorithmException e) { + throw new IllegalArgumentException("Algorithm " + algorithmName + " is not available", e); + } } /** @@ -72,11 +87,12 @@ protected IntegrityAlgorithm(boolean noMacInit) { */ public void initialize(byte[] sik) throws InvalidKeyException { this.sik = sik; - - SecretKeySpec k1 = new SecretKeySpec(sik, getAlgorithmName()); + final String algorithmName = getAlgorithmName(); + + SecretKeySpec k1 = new SecretKeySpec(sik, algorithmName); mac.init(k1); - k1 = new SecretKeySpec(mac.doFinal(CONST1), getAlgorithmName()); + k1 = new SecretKeySpec(mac.doFinal(CONST1), algorithmName); mac.init(k1); } @@ -100,17 +116,18 @@ public byte[] generateAuthCode(final byte[] base) { if (sik == null) { throw new NullPointerException("Algorithm not initialized."); } - - byte[] result = new byte[getAuthCodeLength()]; + + final int authCodeLength = getAuthCodeLength(); + final byte[] result = new byte[authCodeLength]; byte[] updatedBase; if (base[base.length - 2] == 0) { // pas de padding - updatedBase = injectIntegrityPad(base, getAuthCodeLength()); + updatedBase = injectIntegrityPad(base, authCodeLength); } else { updatedBase = base; } - System.arraycopy(mac.doFinal(updatedBase), 0, result, 0, getAuthCodeLength()); + System.arraycopy(mac.doFinal(updatedBase), 0, result, 0, authCodeLength); return result; } diff --git a/src/main/java/org/sentrysoftware/ipmi/core/coding/security/IntegrityHmacMd5_128.java b/src/main/java/org/sentrysoftware/ipmi/core/coding/security/IntegrityHmacMd5_128.java index 61b2fa0..7cf3649 100644 --- a/src/main/java/org/sentrysoftware/ipmi/core/coding/security/IntegrityHmacMd5_128.java +++ b/src/main/java/org/sentrysoftware/ipmi/core/coding/security/IntegrityHmacMd5_128.java @@ -33,11 +33,9 @@ public class IntegrityHmacMd5_128 extends IntegrityAlgorithm { /** * Initiates HMAC-MD5-128 integrity algorithm. - * - * @throws NoSuchAlgorithmException - when initiation of the algorithm fails */ - public IntegrityHmacMd5_128() throws NoSuchAlgorithmException { - super(); + public IntegrityHmacMd5_128() { + super(ALGORITHM_NAME); } @Override diff --git a/src/main/java/org/sentrysoftware/ipmi/core/coding/security/IntegrityHmacSha1_96.java b/src/main/java/org/sentrysoftware/ipmi/core/coding/security/IntegrityHmacSha1_96.java index cef543d..5a1e9e2 100644 --- a/src/main/java/org/sentrysoftware/ipmi/core/coding/security/IntegrityHmacSha1_96.java +++ b/src/main/java/org/sentrysoftware/ipmi/core/coding/security/IntegrityHmacSha1_96.java @@ -33,12 +33,9 @@ public class IntegrityHmacSha1_96 extends IntegrityAlgorithm { /** * Initiates HMAC-SHA1-96 integrity algorithm. - * - * @throws NoSuchAlgorithmException - * - when initiation of the algorithm fails */ - public IntegrityHmacSha1_96() throws NoSuchAlgorithmException { - super(); + public IntegrityHmacSha1_96() { + super(ALGORITHM_NAME); } @Override diff --git a/src/main/java/org/sentrysoftware/ipmi/core/coding/security/IntegrityHmacSha256_128.java b/src/main/java/org/sentrysoftware/ipmi/core/coding/security/IntegrityHmacSha256_128.java index 7d1a64d..8b49665 100644 --- a/src/main/java/org/sentrysoftware/ipmi/core/coding/security/IntegrityHmacSha256_128.java +++ b/src/main/java/org/sentrysoftware/ipmi/core/coding/security/IntegrityHmacSha256_128.java @@ -33,11 +33,9 @@ public class IntegrityHmacSha256_128 extends IntegrityAlgorithm { /** * Initiates HMAC-SHA1-96 integrity algorithm. - * - * @throws NoSuchAlgorithmException when initiation of the algorithm fails */ - public IntegrityHmacSha256_128() throws NoSuchAlgorithmException { - super(); + public IntegrityHmacSha256_128() { + super(ALGORITHM_NAME); } @Override diff --git a/src/main/java/org/sentrysoftware/ipmi/core/coding/security/IntegrityNone.java b/src/main/java/org/sentrysoftware/ipmi/core/coding/security/IntegrityNone.java index a0ebc52..77cd196 100644 --- a/src/main/java/org/sentrysoftware/ipmi/core/coding/security/IntegrityNone.java +++ b/src/main/java/org/sentrysoftware/ipmi/core/coding/security/IntegrityNone.java @@ -29,8 +29,11 @@ */ public class IntegrityNone extends IntegrityAlgorithm { + /** + * Initiates the IntegrityNone algorithm + */ public IntegrityNone() { - super(true); + super(""); } @Override From c4ad2e038a4e66ec44be94f81b8ad44eef1c70b9 Mon Sep 17 00:00:00 2001 From: Safae Ajib Date: Fri, 7 Feb 2025 14:03:17 +0100 Subject: [PATCH 09/11] Issue #46 : Add support for SHA-256 and MD5 authentication algorithms * Updated Connection.java --- .../ipmi/core/connection/Connection.java | 21 ++++++++----------- 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/src/main/java/org/sentrysoftware/ipmi/core/connection/Connection.java b/src/main/java/org/sentrysoftware/ipmi/core/connection/Connection.java index 7c8fbb5..c200bc9 100644 --- a/src/main/java/org/sentrysoftware/ipmi/core/connection/Connection.java +++ b/src/main/java/org/sentrysoftware/ipmi/core/connection/Connection.java @@ -665,17 +665,14 @@ public int getNextSessionSequenceNumber() { return result; } - /** - * @return Default cipher suite (3) - */ - public static CipherSuite getDefaultCipherSuite() { - try { - return new CipherSuite((byte) DEFAULT_CIPHER_SUITE, new AuthenticationRakpHmacSha1().getCode(), - new ConfidentialityAesCbc128().getCode(), new IntegrityHmacSha1_96().getCode()); - } catch (NoSuchAlgorithmException e) { - logger.error("Wrong algorithm in default Cipher suite - SHOULD NOT HAPPEN!!!", e); - return null; - } - } + /** + * @return Default cipher suite (3) + */ + public static CipherSuite getDefaultCipherSuite() { + + return new CipherSuite((byte) DEFAULT_CIPHER_SUITE, new AuthenticationRakpHmacSha1().getCode(), + new ConfidentialityAesCbc128().getCode(), new IntegrityHmacSha1_96().getCode()); + + } } From d54d3da3409ba6e5ff017658485d6272f3cf97c4 Mon Sep 17 00:00:00 2001 From: Safae Ajib Date: Fri, 7 Feb 2025 14:31:17 +0100 Subject: [PATCH 10/11] Issue #46 : Add support for SHA-256 and MD5 authentication algorithms * remove unused imports --- .../ipmi/core/coding/security/AuthenticationRakpHmacMd5.java | 2 -- .../ipmi/core/coding/security/AuthenticationRakpHmacSha1.java | 2 -- .../ipmi/core/coding/security/AuthenticationRakpHmacSha256.java | 2 -- .../ipmi/core/coding/security/AuthenticationRakpNone.java | 2 -- .../ipmi/core/coding/security/IntegrityHmacMd5_128.java | 2 -- .../ipmi/core/coding/security/IntegrityHmacSha1_96.java | 2 -- .../ipmi/core/coding/security/IntegrityHmacSha256_128.java | 2 -- 7 files changed, 14 deletions(-) diff --git a/src/main/java/org/sentrysoftware/ipmi/core/coding/security/AuthenticationRakpHmacMd5.java b/src/main/java/org/sentrysoftware/ipmi/core/coding/security/AuthenticationRakpHmacMd5.java index 946c7ac..1cfe947 100644 --- a/src/main/java/org/sentrysoftware/ipmi/core/coding/security/AuthenticationRakpHmacMd5.java +++ b/src/main/java/org/sentrysoftware/ipmi/core/coding/security/AuthenticationRakpHmacMd5.java @@ -22,8 +22,6 @@ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱ */ -import java.security.NoSuchAlgorithmException; - /** * RAKP-HMAC-MD5 authentication algorithm. */ diff --git a/src/main/java/org/sentrysoftware/ipmi/core/coding/security/AuthenticationRakpHmacSha1.java b/src/main/java/org/sentrysoftware/ipmi/core/coding/security/AuthenticationRakpHmacSha1.java index 4f3a5cd..1016ca6 100644 --- a/src/main/java/org/sentrysoftware/ipmi/core/coding/security/AuthenticationRakpHmacSha1.java +++ b/src/main/java/org/sentrysoftware/ipmi/core/coding/security/AuthenticationRakpHmacSha1.java @@ -22,8 +22,6 @@ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱ */ -import java.security.NoSuchAlgorithmException; - /** * RAKP-HMAC-SHA1 authentication algorithm. */ diff --git a/src/main/java/org/sentrysoftware/ipmi/core/coding/security/AuthenticationRakpHmacSha256.java b/src/main/java/org/sentrysoftware/ipmi/core/coding/security/AuthenticationRakpHmacSha256.java index ce8447d..dc53b07 100644 --- a/src/main/java/org/sentrysoftware/ipmi/core/coding/security/AuthenticationRakpHmacSha256.java +++ b/src/main/java/org/sentrysoftware/ipmi/core/coding/security/AuthenticationRakpHmacSha256.java @@ -22,8 +22,6 @@ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱ */ -import java.security.NoSuchAlgorithmException; - /** * RAKP-HMAC-SHA256 authentication algorithm. */ diff --git a/src/main/java/org/sentrysoftware/ipmi/core/coding/security/AuthenticationRakpNone.java b/src/main/java/org/sentrysoftware/ipmi/core/coding/security/AuthenticationRakpNone.java index efcff51..5035348 100644 --- a/src/main/java/org/sentrysoftware/ipmi/core/coding/security/AuthenticationRakpNone.java +++ b/src/main/java/org/sentrysoftware/ipmi/core/coding/security/AuthenticationRakpNone.java @@ -1,7 +1,5 @@ package org.sentrysoftware.ipmi.core.coding.security; -import java.security.NoSuchAlgorithmException; - /*- * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲ * IPMI Java Client diff --git a/src/main/java/org/sentrysoftware/ipmi/core/coding/security/IntegrityHmacMd5_128.java b/src/main/java/org/sentrysoftware/ipmi/core/coding/security/IntegrityHmacMd5_128.java index 7cf3649..3518904 100644 --- a/src/main/java/org/sentrysoftware/ipmi/core/coding/security/IntegrityHmacMd5_128.java +++ b/src/main/java/org/sentrysoftware/ipmi/core/coding/security/IntegrityHmacMd5_128.java @@ -22,8 +22,6 @@ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱ */ -import java.security.NoSuchAlgorithmException; - /** * HMAC-MD5-128 integrity algorithm. */ diff --git a/src/main/java/org/sentrysoftware/ipmi/core/coding/security/IntegrityHmacSha1_96.java b/src/main/java/org/sentrysoftware/ipmi/core/coding/security/IntegrityHmacSha1_96.java index 5a1e9e2..f971f55 100644 --- a/src/main/java/org/sentrysoftware/ipmi/core/coding/security/IntegrityHmacSha1_96.java +++ b/src/main/java/org/sentrysoftware/ipmi/core/coding/security/IntegrityHmacSha1_96.java @@ -22,8 +22,6 @@ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱ */ -import java.security.NoSuchAlgorithmException; - /** * HMAC-SHA1-96 integrity algorithm. */ diff --git a/src/main/java/org/sentrysoftware/ipmi/core/coding/security/IntegrityHmacSha256_128.java b/src/main/java/org/sentrysoftware/ipmi/core/coding/security/IntegrityHmacSha256_128.java index 8b49665..5e2f35a 100644 --- a/src/main/java/org/sentrysoftware/ipmi/core/coding/security/IntegrityHmacSha256_128.java +++ b/src/main/java/org/sentrysoftware/ipmi/core/coding/security/IntegrityHmacSha256_128.java @@ -22,8 +22,6 @@ * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱ */ -import java.security.NoSuchAlgorithmException; - /** * HMAC-SHA256-128 integrity algorithm. */ From 02ee28950743fd3873d92c9a7c1ed0da903a8e69 Mon Sep 17 00:00:00 2001 From: Nassim Boutekedjiret Date: Fri, 7 Feb 2025 16:01:26 +0100 Subject: [PATCH 11/11] Issue #46 : Add support for SHA-256 and MD5 authentication algorithms * Factorization before merge. --- .../security/AuthenticationAlgorithm.java | 19 +------------------ .../core/coding/security/CipherSuite.java | 19 ++++++++++++++++++- .../security/ConfidentialityAesCbc128.java | 5 +++-- .../coding/security/IntegrityAlgorithm.java | 19 +------------------ 4 files changed, 23 insertions(+), 39 deletions(-) diff --git a/src/main/java/org/sentrysoftware/ipmi/core/coding/security/AuthenticationAlgorithm.java b/src/main/java/org/sentrysoftware/ipmi/core/coding/security/AuthenticationAlgorithm.java index a003f1c..d74d6fa 100644 --- a/src/main/java/org/sentrysoftware/ipmi/core/coding/security/AuthenticationAlgorithm.java +++ b/src/main/java/org/sentrysoftware/ipmi/core/coding/security/AuthenticationAlgorithm.java @@ -43,7 +43,7 @@ public abstract class AuthenticationAlgorithm { * Constructs an authentication algorithm. */ protected AuthenticationAlgorithm(String algorithmName) { - this(newMacInstance(algorithmName)); + this(CipherSuite.newMacInstance(algorithmName)); } /** @@ -55,23 +55,6 @@ private AuthenticationAlgorithm(Mac mac) { this.mac = mac; } - /** - * Constructs a Mac object that implements the given MAC algorithm. - * - * @param algorithmName the name of the algorithm to use - * @return The Mac object that implements the specified MAC algorithm. - */ - private static Mac newMacInstance(final String algorithmName) { - if (algorithmName == null || algorithmName.trim().isEmpty()) { - return null; - } - try { - return Mac.getInstance(algorithmName); - } catch (NoSuchAlgorithmException e) { - throw new IllegalArgumentException("Algorithm " + algorithmName + " is not available", e); - } - } - /** * @return algorithm-specific code */ diff --git a/src/main/java/org/sentrysoftware/ipmi/core/coding/security/CipherSuite.java b/src/main/java/org/sentrysoftware/ipmi/core/coding/security/CipherSuite.java index fab9682..61f457c 100644 --- a/src/main/java/org/sentrysoftware/ipmi/core/coding/security/CipherSuite.java +++ b/src/main/java/org/sentrysoftware/ipmi/core/coding/security/CipherSuite.java @@ -26,6 +26,7 @@ import org.sentrysoftware.ipmi.core.coding.commands.session.GetChannelCipherSuitesResponseData; import org.sentrysoftware.ipmi.core.common.TypeConverter; +import javax.crypto.Mac; import javax.crypto.NoSuchPaddingException; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; @@ -245,5 +246,21 @@ private IntegrityAlgorithm instantiateIntegrityAlgorithm(final Supplier