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

net.luminis.tls.handshake.CertificateRequestMessage Maven / Gradle / Ivy

/*
 * Copyright © 2021, 2022, 2023, 2024 Peter Doornbosch
 *
 * This file is part of Agent15, an implementation of TLS 1.3 in Java.
 *
 * Agent15 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.
 *
 * Agent15 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 Lesser General Public License for
 * more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program. If not, see .
 */
package net.luminis.tls.handshake;

import net.luminis.tls.TlsConstants;
import net.luminis.tls.TlsProtocolException;
import net.luminis.tls.alert.BadCertificateAlert;
import net.luminis.tls.alert.DecodeErrorException;
import net.luminis.tls.extension.CertificateAuthoritiesExtension;
import net.luminis.tls.extension.ClientHelloPreSharedKeyExtension;
import net.luminis.tls.extension.Extension;

import java.nio.ByteBuffer;
import java.util.List;

// https://tools.ietf.org/html/rfc8446#section-4.3.2
public class CertificateRequestMessage extends HandshakeMessage {

    private static final int MINIMUM_MESSAGE_SIZE = 1 + 3 + 1 + 2;

    private byte[] certificateRequestContext;
    private List extensions;
    private byte[] raw;

    public CertificateRequestMessage() {
    }

    public CertificateRequestMessage(Extension extension) {
        extensions = List.of(extension);
        certificateRequestContext = new byte[0];

        serialize();
    }

    public CertificateRequestMessage parse(ByteBuffer buffer) throws TlsProtocolException {
        int startPosition = buffer.position();
        int remainingLength = parseHandshakeHeader(buffer, TlsConstants.HandshakeType.certificate_request, MINIMUM_MESSAGE_SIZE);

        int contextLength = buffer.get();
        certificateRequestContext = new byte[contextLength];
        if (contextLength > 0) {
            buffer.get(certificateRequestContext);
        }

        extensions = parseExtensions(buffer, TlsConstants.HandshakeType.certificate_request, null);

        if (buffer.position() - (startPosition + 4) != remainingLength) {
            throw new DecodeErrorException("inconsistent length");
        }

        // Update state.
        raw = new byte[4 + remainingLength];
        buffer.position(startPosition);
        buffer.get(raw);

        return this;
    }

    private void serialize() {
        int extensionsLength = extensions.stream().mapToInt(ext -> ext.getBytes().length).sum();
        int messageLength = 4 + 1 + certificateRequestContext.length + 2 + extensionsLength;
        ByteBuffer buffer = ByteBuffer.allocate(messageLength);
        buffer.put(TlsConstants.HandshakeType.certificate_request.value);
        buffer.put((byte) 0x00);
        buffer.putShort((short) (messageLength - 4));
        buffer.put((byte) certificateRequestContext.length);
        if (certificateRequestContext.length > 0) {
            buffer.put(certificateRequestContext);
        }
        buffer.putShort((short) extensionsLength);
        for (Extension extension: extensions) {
            buffer.put(extension.getBytes());
        }
        raw = buffer.array();
    }


    @Override
    public TlsConstants.HandshakeType getType() {
        return TlsConstants.HandshakeType.certificate_request;
    }

    @Override
    public byte[] getBytes() {
        return raw;
    }

    public List getExtensions() {
        return extensions;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy