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

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

Go to download

A (partial) TLS 1.3 implementation in Java, suitable and intended for use in a QUIC implementation.

There is a newer version: 2.3
Show newest version
/*
 * Copyright © 2019, 2020, 2021, 2022, 2023 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.extension.ExtensionParser;
import net.luminis.tls.TlsConstants;
import net.luminis.tls.TlsProtocolException;
import net.luminis.tls.alert.DecodeErrorException;
import net.luminis.tls.extension.Extension;

import java.nio.ByteBuffer;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

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

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

    private List extensions;
    private byte[] raw;

    public EncryptedExtensions() {
        extensions = Collections.emptyList();
        serialize();
    }

    public EncryptedExtensions(List extensions) {
        this.extensions = extensions;
        serialize();
    }

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

    private void serialize() {
        List extensionBytes = extensions.stream().map(extension -> extension.getBytes()).collect(Collectors.toList());
        int extensionsSize = extensionBytes.stream().mapToInt(data -> data.length).sum();

        raw = new byte[1 + 3 + 2 + extensionsSize];
        ByteBuffer buffer = ByteBuffer.wrap(raw);
        buffer.putInt(0x08000000 | (2 + extensionsSize));
        buffer.putShort((short) extensionsSize);
        extensionBytes.forEach(bytes -> buffer.put(bytes));
    }

    public EncryptedExtensions parse(ByteBuffer buffer, int length) throws TlsProtocolException {
        return parse(buffer, length, null);
    }
    
    public EncryptedExtensions parse(ByteBuffer buffer, int length, ExtensionParser customExtensionParser) throws TlsProtocolException {
        if (buffer.remaining() < MINIMAL_MESSAGE_LENGTH) {
            throw new DecodeErrorException("Message too short");
        }

        int start = buffer.position();
        int msgLength = buffer.getInt() & 0x00ffffff;
        if (buffer.remaining() < msgLength || msgLength < 2) {
            throw new DecodeErrorException("Incorrect message length");
        }

        extensions = parseExtensions(buffer, TlsConstants.HandshakeType.server_hello, customExtensionParser);

        // Raw bytes are needed for computing the transcript hash
        buffer.position(start);
        raw = new byte[length];
        buffer.mark();
        buffer.get(raw);

        return this;
    }

    public List getExtensions() {
        return extensions;
    }

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




© 2015 - 2024 Weber Informatics LLC | Privacy Policy