All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.veraxsystems.vxipmi.coding.commands.session.Rakp3 Maven / Gradle / Ivy

The newest version!
/*
 * Rakp3.java 
 * Created on 2011-07-26
 *
 * Copyright (c) Verax Systems 2011.
 * All rights reserved.
 *
 * This software is furnished under a license. Use, duplication,
 * disclosure and all other uses are restricted to the rights
 * specified in the written license agreement.
 */
package com.veraxsystems.vxipmi.coding.commands.session;

import com.veraxsystems.vxipmi.coding.commands.IpmiCommandCoder;
import com.veraxsystems.vxipmi.coding.commands.IpmiVersion;
import com.veraxsystems.vxipmi.coding.commands.ResponseData;
import com.veraxsystems.vxipmi.coding.payload.CompletionCode;
import com.veraxsystems.vxipmi.coding.payload.IpmiPayload;
import com.veraxsystems.vxipmi.coding.payload.PlainMessage;
import com.veraxsystems.vxipmi.coding.payload.lan.IPMIException;
import com.veraxsystems.vxipmi.coding.payload.lan.NetworkFunction;
import com.veraxsystems.vxipmi.coding.protocol.AuthenticationType;
import com.veraxsystems.vxipmi.coding.protocol.IpmiMessage;
import com.veraxsystems.vxipmi.coding.protocol.Ipmiv20Message;
import com.veraxsystems.vxipmi.coding.protocol.PayloadType;
import com.veraxsystems.vxipmi.coding.protocol.encoder.Protocolv20Encoder;
import com.veraxsystems.vxipmi.coding.security.CipherSuite;
import com.veraxsystems.vxipmi.coding.security.ConfidentialityNone;
import com.veraxsystems.vxipmi.coding.security.SecurityConstants;
import com.veraxsystems.vxipmi.common.TypeConverter;

import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;

/**
 * A wrapper for RMCP+ RAKP3 message and it's response - RAKP4 message.
 */
public class Rakp3 extends IpmiCommandCoder {

    /**
     * Status of the previous message.
     */
    private byte statusCode;

    /**
     * The Managed System's Session ID for this session. Must be as returned by
     * the Managed System in the Open Session Response message.
     */
    private int managedSystemSessionId;

    private Rakp1 rakp1;

    private Rakp1ResponseData rakp1ResponseData;

    public void setStatusCode(byte statusCode) {
        this.statusCode = statusCode;
    }

    public byte getStatusCode() {
        return statusCode;
    }

    public void setManagedSystemSessionId(int managedSystemSessionId) {
        this.managedSystemSessionId = managedSystemSessionId;
    }

    public int getManagedSystemSessionId() {
        return managedSystemSessionId;
    }

    /**
     * Initiates class for decoding. Sets IPMI version to
     * {@link IpmiVersion#V20} since RAKP1 is a RMCP+ command. Sets
     * Authentication Type to RMCP+.
     *
     * @param cipherSuite
     *            {@link CipherSuite} containing authentication,
     *            confidentiality and integrity algorithms for this session.
     *            Only authentication algorithm is used at this point of
     *            creating a session.
     * @param rakp1
     *            RAKP Message 1 sent earlier in the authentification process
     * @param rakp1ResponseData
     *            RAKP Message 2 received earlier in the authentification
     *            process
     *
     */
    public Rakp3(CipherSuite cipherSuite, Rakp1 rakp1,
            Rakp1ResponseData rakp1ResponseData) {
        super(IpmiVersion.V20, cipherSuite, AuthenticationType.RMCPPlus);
        this.rakp1 = rakp1;
        this.rakp1ResponseData = rakp1ResponseData;
        setCipherSuite(new CipherSuite((byte) 0, cipherSuite
                .getAuthenticationAlgorithm().getCode(), (byte) 0, (byte) 0));
    }

    /**
     * Initiates class for encoding and decoding. Sets IPMI version to
     * {@link IpmiVersion#V20} since RAKP1 is a RMCP+ command. Sets
     * Authentication Type to RMCP+.
     *
     * @param statusCode
     *            Status of the previous message.
     * @param managedSystemSessionId
     *            The Managed System's Session ID for this session. Must be as
     *            returned by the Managed System in the Open Session Response
     *            message.
     * @param cipherSuite
     *            {@link CipherSuite} containing authentication,
     *            confidentiality and integrity algorithms for this session.
     *            Only authentication algorithm is used at this point of
     *            creating a session.
     * @param rakp1
     *            RAKP Message 1 sent earlier in the authentification process
     * @param rakp1ResponseData
     *            RAKP Message 2 received earlier in the authentification
     *            process
     */
    public Rakp3(byte statusCode, int managedSystemSessionId,
            CipherSuite cipherSuite, Rakp1 rakp1,
            Rakp1ResponseData rakp1ResponseData) {
        super(IpmiVersion.V20, cipherSuite, AuthenticationType.RMCPPlus);
        setStatusCode(statusCode);
        setManagedSystemSessionId(managedSystemSessionId);
        this.rakp1 = rakp1;
        this.rakp1ResponseData = rakp1ResponseData;
        setCipherSuite(new CipherSuite((byte) 0, cipherSuite
                .getAuthenticationAlgorithm().getCode(), (byte) 0, (byte) 0));
    }

    @Override
    public IpmiMessage encodePayload(int messageSequenceNumber, int sessionSequenceNumber, int sessionId)
            throws NoSuchAlgorithmException, InvalidKeyException {

        if (sessionId != 0) {
            throw new IllegalArgumentException("Session ID must be 0");
        }

        Ipmiv20Message message = new Ipmiv20Message(new ConfidentialityNone());

        message.setPayloadType(PayloadType.Rakp3);
        message.setSessionID(0);
        message.setSessionSequenceNumber(0);
        message.setAuthenticationType(getAuthenticationType());
        message.setPayloadAuthenticated(getCipherSuite()
                .getIntegrityAlgorithm().getCode() != SecurityConstants.IA_NONE);
        message.setPayloadEncrypted(false);

        message.setPayload(preparePayload(messageSequenceNumber));

        message.setAuthCode(getCipherSuite()
                .getIntegrityAlgorithm()
                .generateAuthCode(
                        message.getIntegrityAlgorithmBase(new Protocolv20Encoder())));

        return message;
    }

    @Override
    protected IpmiPayload preparePayload(int sequenceNumber)
            throws NoSuchAlgorithmException, InvalidKeyException {
        byte[] payload = new byte[8];

        payload[0] = TypeConverter.intToByte(sequenceNumber); // message
                                                                    // tag

        payload[1] = getStatusCode(); // last message status code

        payload[2] = 0; // reserved
        payload[3] = 0; // reserved

        byte[] manSesId = TypeConverter
                .intToLittleEndianByteArray(getManagedSystemSessionId());

        System.arraycopy(manSesId, 0, payload, 4, 4); // managed system session
                                                        // id

        byte[] exchangeAuthCode = getCipherSuite().getAuthenticationAlgorithm()
                .getKeyExchangeAuthenticationCode(
                        prepareKeyExchangeAuthenticationCodeBase(rakp1,
                                rakp1ResponseData), rakp1.getPassword());

        byte[] result = null;

        if (exchangeAuthCode != null) {
            result = new byte[8 + exchangeAuthCode.length];
            System.arraycopy(exchangeAuthCode, 0, result, 8,
                    exchangeAuthCode.length);
        } else {
            result = new byte[8];
        }

        System.arraycopy(payload, 0, result, 0, 8);

        return new PlainMessage(result);
    }

    /**
     * @return byte array holding prepared base for calculating
     *         KeyExchangeAuthenticationCode for RAKP Message 3
     */
    private byte[] prepareKeyExchangeAuthenticationCodeBase(Rakp1 rakp1,
            Rakp1ResponseData responseData) {
        int length = 22;
        if (rakp1.getUsername() != null) {
            length += rakp1.getUsername().length();
        }
        byte[] keac = new byte[length];

        System.arraycopy(responseData.getManagedSystemRandomNumber(), 0, keac,
                0, 16);

        System.arraycopy(TypeConverter.intToLittleEndianByteArray(responseData
                .getRemoteConsoleSessionId()), 0, keac, 16, 4);

        keac[20] = TypeConverter.intToByte(encodePrivilegeLevel(rakp1
                .getRequestedMaximumPrivilegeLevel()) | 0x10);

        if (rakp1.getUsername() != null) {
            keac[21] = TypeConverter.intToByte(rakp1.getUsername().length());
            if (rakp1.getUsername().length() > 0) {
                System.arraycopy(rakp1.getUsername().getBytes(), 0, keac, 22,
                        rakp1.getUsername().length());
            }
        } else {
            keac[21] = 0;
        }

        return keac;
    }

    @Override
    public byte getCommandCode() {
        return 0;
    }

    @Override
    public NetworkFunction getNetworkFunction() {
        return null;
    }

    @Override
    public ResponseData getResponseData(IpmiMessage message) throws IPMIException, InvalidKeyException, NoSuchAlgorithmException {

        if (!isCommandResponse(message)) {
            throw new IllegalArgumentException("This is not RAKP 4 message!");
        }

        byte[] payload = message.getPayload().getPayloadData();

        Rakp3ResponseData data = new Rakp3ResponseData();

        data.setMessageTag(payload[0]);

        data.setStatusCode(payload[1]);

        if (payload[1] != 0) {
            throw new IPMIException(CompletionCode.parseInt(TypeConverter
                    .byteToInt(payload[1])));
        }

        if (payload.length < 8) {
            throw new IllegalArgumentException("Invalid payload length");
        }

        byte[] buffer = new byte[4];

        System.arraycopy(payload, 4, buffer, 0, 4);

        data.setConsoleSessionId(TypeConverter
                .littleEndianByteArrayToInt(buffer));

        byte[] integrityCheck = null;

        if (payload.length > 8) {
            integrityCheck = new byte[getCipherSuite()
                    .getAuthenticationAlgorithm().getIntegrityCheckBaseLength()];
            System.arraycopy(payload, 8, integrityCheck, 0, getCipherSuite()
                    .getAuthenticationAlgorithm().getIntegrityCheckBaseLength());
        }

        if (!getCipherSuite().getAuthenticationAlgorithm().doIntegrityCheck(
                prepareIntegrityCheckBase(rakp1, rakp1ResponseData),
                integrityCheck, rakp1.calculateSik(rakp1ResponseData))) {
            throw new IllegalArgumentException("Integrity check failed");
        }

        return data;
    }

    /**
     * @return byte array holding prepared base for calculating Integrity Check
     */
    private byte[] prepareIntegrityCheckBase(Rakp1 rakp1,
            Rakp1ResponseData responseData) {
        byte[] icb = new byte[36];

        System.arraycopy(rakp1.getConsoleRandomNumber(), 0, icb, 0, 16);

        System.arraycopy(TypeConverter.intToLittleEndianByteArray(rakp1
                .getManagedSystemSessionId()), 0, icb, 16, 4);

        System.arraycopy(responseData.getManagedSystemGuid(), 0, icb, 20, 16);

        return icb;
    }

    @Override
    public boolean isCommandResponse(IpmiMessage message) {
        return message instanceof Ipmiv20Message && ((Ipmiv20Message) message).getPayloadType() == PayloadType.Rakp4;
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy