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

net.luminis.tls.extension.CertificateAuthoritiesExtension 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 © 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.extension;

import net.luminis.tls.TlsConstants;
import net.luminis.tls.alert.DecodeErrorException;

import javax.security.auth.x500.X500Principal;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;

// https://tools.ietf.org/html/rfc8446#section-4.2.4
public class CertificateAuthoritiesExtension extends Extension {

    private final List authorities = new ArrayList<>();

    public CertificateAuthoritiesExtension(X500Principal x500Principal) {
        authorities.add(x500Principal);
    }

    public CertificateAuthoritiesExtension(ByteBuffer buffer) throws DecodeErrorException {
        int extensionDataLength = parseExtensionHeader(buffer, TlsConstants.ExtensionType.certificate_authorities, 2);

        int authoritiesLength = buffer.getShort();
        if (extensionDataLength != authoritiesLength + 2) {
            throw new DecodeErrorException("inconsistent length fields");
        }

        int remaining = authoritiesLength;
        while (remaining > 0) {
            if (remaining < 2) {
                throw new DecodeErrorException("inconsistent length fields");
            }
            remaining -= 2;
            int dnLength = buffer.getShort() & 0xffff;
            if (dnLength > remaining) {
                throw new DecodeErrorException("inconsistent length fields");
            }
            if (dnLength <= buffer.remaining()) {
                byte[] dn = new byte[dnLength];
                buffer.get(dn);
                remaining -= dnLength;
                try {
                    authorities.add(new X500Principal(dn));
                }
                catch (IllegalArgumentException encodingError) {
                    throw new DecodeErrorException("authority not in DER format");
                }
            }
            else {
                throw new DecodeErrorException("inconsistent length fields");
            }
        }
    }

    @Override
    public byte[] getBytes() {
        int authoritiesLength = authorities.stream().mapToInt(x500principal -> x500principal.getEncoded().length).sum();
        int extensionLength = authoritiesLength + authorities.size() * 2 + 2 + 4;
        var buffer = ByteBuffer.allocate(extensionLength);
        buffer.putShort(TlsConstants.ExtensionType.certificate_authorities.value);
        buffer.putShort((short) (extensionLength - 4));
        buffer.putShort((short) (extensionLength - 6));
        authorities.stream().forEach(authority -> {
            buffer.putShort((short) authority.getEncoded().length);
            buffer.put(authority.getEncoded());
        });
        return buffer.array();
    }

    public List getAuthorities() {
        return authorities;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy