Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
164 changes: 136 additions & 28 deletions jdk/test/java/security/testlibrary/CertificateBuilder.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
Expand All @@ -26,22 +26,25 @@
package sun.security.testlibrary;

import java.io.*;
import java.security.cert.*;
import java.security.cert.Extension;
import java.util.*;
import java.security.*;
import java.security.cert.X509Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.Extension;
import java.time.temporal.ChronoUnit;
import java.time.Instant;
import javax.security.auth.x500.X500Principal;
import java.math.BigInteger;

import jdk.test.lib.Utils;

import sun.security.util.DerOutputStream;
import sun.security.util.DerValue;
import sun.security.util.ObjectIdentifier;
import sun.security.x509.AccessDescription;
import sun.security.x509.AlgorithmId;
import sun.security.x509.AuthorityInfoAccessExtension;
import sun.security.x509.AuthorityKeyIdentifierExtension;
import sun.security.x509.IPAddressName;
import sun.security.x509.SubjectKeyIdentifierExtension;
import sun.security.x509.BasicConstraintsExtension;
import sun.security.x509.ExtendedKeyUsageExtension;
Expand All @@ -55,6 +58,7 @@
import sun.security.x509.KeyIdentifier;
import sun.security.x509.X500Name;


/**
* Helper class that builds and signs X.509 certificates.
*
Expand Down Expand Up @@ -99,6 +103,89 @@ public class CertificateBuilder {
private byte[] tbsCertBytes;
private byte[] signatureBytes;

public enum KeyUsage {
DIGITAL_SIGNATURE,
NONREPUDIATION,
KEY_ENCIPHERMENT,
DATA_ENCIPHERMENT,
KEY_AGREEMENT,
KEY_CERT_SIGN,
CRL_SIGN,
ENCIPHER_ONLY,
DECIPHER_ONLY;
}

/**
* Create a new CertificateBuilder instance. This method sets the subject name,
* public key, authority key id, and serial number.
*
* @param subjectName entity associated with the public key
* @param publicKey the entity's public key
* @param caKey public key of certificate signer
* @param keyUsages list of key uses
* @return
* @throws CertificateException
* @throws IOException
*/
public static CertificateBuilder newCertificateBuilder(String subjectName,
PublicKey publicKey, PublicKey caKey, KeyUsage... keyUsages)
throws CertificateException, IOException {
SecureRandom random = new SecureRandom();

boolean [] keyUsage = new boolean[KeyUsage.values().length];
for (KeyUsage ku : keyUsages) {
keyUsage[ku.ordinal()] = true;
}

CertificateBuilder builder = new CertificateBuilder()
.setSubjectName(subjectName)
.setPublicKey(publicKey)
.setSerialNumber(BigInteger.valueOf(Utils.nextLong(random, 1000000)+1))
.addSubjectKeyIdExt(publicKey)
.addAuthorityKeyIdExt(caKey);
if (keyUsages.length != 0) {
builder.addKeyUsageExt(keyUsage);
}
return builder;
}

/**
* Create a Subject Alternative Name extension for the given DNS name
* @param critical Sets the extension to critical or non-critical
* @param dnsName DNS name to use in the extension
* @throws IOException
*/
public static SubjectAlternativeNameExtension createDNSSubjectAltNameExt(
boolean critical, String dnsName) throws IOException {
GeneralNames gns = new GeneralNames();
gns.add(new GeneralName(new DNSName(dnsName)));
return new SubjectAlternativeNameExtension(critical, gns);
}

/**
* Create a Subject Alternative Name extension for the given IP address
* @param critical Sets the extension to critical or non-critical
* @param ipAddress IP address to use in the extension
* @throws IOException
*/
public static SubjectAlternativeNameExtension createIPSubjectAltNameExt(
boolean critical, String ipAddress) throws IOException {
GeneralNames gns = new GeneralNames();
gns.add(new GeneralName(new IPAddressName(ipAddress)));
return new SubjectAlternativeNameExtension(critical, gns);
}

public static void printCertificate(X509Certificate certificate, PrintStream ps) {
try {
Base64.Encoder encoder = Base64.getEncoder();
ps.println("-----BEGIN CERTIFICATE-----");
ps.println(encoder.encodeToString(certificate.getEncoded()));
ps.println("-----END CERTIFICATE-----");
} catch (CertificateEncodingException exc) {
exc.printStackTrace(ps);
}
}

/**
* Default constructor for a {@code CertificateBuilder} object.
*
Expand Down Expand Up @@ -151,8 +238,9 @@ public CertificateBuilder setSubjectName(X500Name name) {
*
* @param pubKey The {@link PublicKey} to be used on this certificate.
*/
public void setPublicKey(PublicKey pubKey) {
public CertificateBuilder setPublicKey(PublicKey pubKey) {
publicKey = Objects.requireNonNull(pubKey, "Caught null public key");
return this;
}

/**
Expand All @@ -161,9 +249,10 @@ public void setPublicKey(PublicKey pubKey) {
* @param nbDate A {@link Date} object specifying the start of the
* certificate validity period.
*/
public void setNotBefore(Date nbDate) {
public CertificateBuilder setNotBefore(Date nbDate) {
Objects.requireNonNull(nbDate, "Caught null notBefore date");
notBefore = (Date)nbDate.clone();
return this;
}

/**
Expand All @@ -172,9 +261,10 @@ public void setNotBefore(Date nbDate) {
* @param naDate A {@link Date} object specifying the end of the
* certificate validity period.
*/
public void setNotAfter(Date naDate) {
public CertificateBuilder setNotAfter(Date naDate) {
Objects.requireNonNull(naDate, "Caught null notAfter date");
notAfter = (Date)naDate.clone();
return this;
}

/**
Expand All @@ -185,19 +275,24 @@ public void setNotAfter(Date naDate) {
* @param naDate A {@link Date} object specifying the end of the
* certificate validity period.
*/
public void setValidity(Date nbDate, Date naDate) {
setNotBefore(nbDate);
setNotAfter(naDate);
public CertificateBuilder setValidity(Date nbDate, Date naDate) {
return setNotBefore(nbDate).setNotAfter(naDate);
}

public CertificateBuilder setOneHourValidity() {
return setNotBefore(Date.from(Instant.now().minus(5, ChronoUnit.MINUTES)))
.setNotAfter(Date.from(Instant.now().plus(1, ChronoUnit.HOURS)));
}

/**
* Set the serial number on the certificate.
*
* @param serial A serial number in {@link BigInteger} form.
*/
public void setSerialNumber(BigInteger serial) {
public CertificateBuilder setSerialNumber(BigInteger serial) {
Objects.requireNonNull(serial, "Caught null serial number");
serialNumber = serial;
return this;
}


Expand All @@ -206,9 +301,10 @@ public void setSerialNumber(BigInteger serial) {
*
* @param ext The extension to be added.
*/
public void addExtension(Extension ext) {
public CertificateBuilder addExtension(Extension ext) {
Objects.requireNonNull(ext, "Caught null extension");
extensions.put(ext.getId(), ext);
return this;
}

/**
Expand All @@ -217,11 +313,12 @@ public void addExtension(Extension ext) {
* @param extList The {@link List} of extensions to be added to
* the certificate.
*/
public void addExtensions(List<Extension> extList) {
public CertificateBuilder addExtensions(List<Extension> extList) {
Objects.requireNonNull(extList, "Caught null extension list");
for (Extension ext : extList) {
extensions.put(ext.getId(), ext);
}
return this;
}

/**
Expand All @@ -231,7 +328,8 @@ public void addExtensions(List<Extension> extList) {
*
* @throws IOException if an encoding error occurs.
*/
public void addSubjectAltNameDNSExt(List<String> dnsNames) throws IOException {
public CertificateBuilder addSubjectAltNameDNSExt(List<String> dnsNames)
throws IOException {
if (!dnsNames.isEmpty()) {
GeneralNames gNames = new GeneralNames();
for (String name : dnsNames) {
Expand All @@ -240,6 +338,7 @@ public void addSubjectAltNameDNSExt(List<String> dnsNames) throws IOException {
addExtension(new SubjectAlternativeNameExtension(false,
gNames));
}
return this;
}

/**
Expand All @@ -250,7 +349,7 @@ public void addSubjectAltNameDNSExt(List<String> dnsNames) throws IOException {
*
* @throws IOException if an encoding error occurs.
*/
public void addAIAExt(List<String> locations)
public CertificateBuilder addAIAExt(List<String> locations)
throws IOException {
if (!locations.isEmpty()) {
List<AccessDescription> acDescList = new ArrayList<>();
Expand All @@ -261,8 +360,10 @@ public void addAIAExt(List<String> locations)
}
addExtension(new AuthorityInfoAccessExtension(acDescList));
}
return this;
}


/**
* Set a Key Usage extension for the certificate. The extension will
* be marked critical.
Expand All @@ -272,8 +373,9 @@ public void addAIAExt(List<String> locations)
*
* @throws IOException if an encoding error occurs.
*/
public void addKeyUsageExt(boolean[] bitSettings) throws IOException {
addExtension(new KeyUsageExtension(bitSettings));
public CertificateBuilder addKeyUsageExt(boolean[] bitSettings)
throws IOException {
return addExtension(new KeyUsageExtension(bitSettings));
}

/**
Expand All @@ -288,9 +390,10 @@ public void addKeyUsageExt(boolean[] bitSettings) throws IOException {
*
* @throws IOException if an encoding error occurs.
*/
public void addBasicConstraintsExt(boolean crit, boolean isCA,
public CertificateBuilder addBasicConstraintsExt(boolean crit, boolean isCA,
int maxPathLen) throws IOException {
addExtension(new BasicConstraintsExtension(crit, isCA, maxPathLen));
return addExtension(new BasicConstraintsExtension(crit, isCA,
maxPathLen));
}

/**
Expand All @@ -300,9 +403,9 @@ public void addBasicConstraintsExt(boolean crit, boolean isCA,
*
* @throws IOException if an encoding error occurs.
*/
public void addAuthorityKeyIdExt(X509Certificate authorityCert)
public CertificateBuilder addAuthorityKeyIdExt(X509Certificate authorityCert)
throws IOException {
addAuthorityKeyIdExt(authorityCert.getPublicKey());
return addAuthorityKeyIdExt(authorityCert.getPublicKey());
}

/**
Expand All @@ -312,9 +415,11 @@ public void addAuthorityKeyIdExt(X509Certificate authorityCert)
*
* @throws IOException if an encoding error occurs.
*/
public void addAuthorityKeyIdExt(PublicKey authorityKey) throws IOException {
public CertificateBuilder addAuthorityKeyIdExt(PublicKey authorityKey)
throws IOException {
KeyIdentifier kid = new KeyIdentifier(authorityKey);
addExtension(new AuthorityKeyIdentifierExtension(kid, null, null));
return addExtension(new AuthorityKeyIdentifierExtension(kid,
null, null));
}

/**
Expand All @@ -324,9 +429,10 @@ public void addAuthorityKeyIdExt(PublicKey authorityKey) throws IOException {
*
* @throws IOException if an encoding error occurs.
*/
public void addSubjectKeyIdExt(PublicKey subjectKey) throws IOException {
public CertificateBuilder addSubjectKeyIdExt(PublicKey subjectKey)
throws IOException {
byte[] keyIdBytes = new KeyIdentifier(subjectKey).getIdentifier();
addExtension(new SubjectKeyIdentifierExtension(keyIdBytes));
return addExtension(new SubjectKeyIdentifierExtension(keyIdBytes));
}

/**
Expand All @@ -336,7 +442,7 @@ public void addSubjectKeyIdExt(PublicKey subjectKey) throws IOException {
*
* @throws IOException if an encoding error occurs.
*/
public void addExtendedKeyUsageExt(List<String> ekuOids)
public CertificateBuilder addExtendedKeyUsageExt(List<String> ekuOids)
throws IOException {
if (!ekuOids.isEmpty()) {
Vector<ObjectIdentifier> oidVector = new Vector<>();
Expand All @@ -345,13 +451,14 @@ public void addExtendedKeyUsageExt(List<String> ekuOids)
}
addExtension(new ExtendedKeyUsageExtension(oidVector));
}
return this;
}

/**
* Clear all settings and return the {@code CertificateBuilder} to
* its default state.
*/
public void reset() {
public CertificateBuilder reset() {
extensions.clear();
subjectName = null;
notBefore = null;
Expand All @@ -360,6 +467,7 @@ public void reset() {
publicKey = null;
signatureBytes = null;
tbsCertBytes = null;
return this;
}

/**
Expand Down
2 changes: 1 addition & 1 deletion jdk/test/javax/net/ssl/Stapling/HttpsUrlConnClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
* @test
* @bug 8046321 8153829
* @summary OCSP Stapling for TLS
* @library ../../../../java/security/testlibrary
* @library /test/lib ../../../../java/security/testlibrary
* @build CertificateBuilder SimpleOCSPServer
* @run main/othervm HttpsUrlConnClient
*/
Expand Down
2 changes: 1 addition & 1 deletion jdk/test/javax/net/ssl/Stapling/SSLEngineWithStapling.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
* @test
* @bug 8046321 8153829
* @summary OCSP Stapling for TLS
* @library ../../../../java/security/testlibrary
* @library /test/lib ../../../../java/security/testlibrary
* @build CertificateBuilder SimpleOCSPServer
* @run main/othervm SSLEngineWithStapling
*/
Expand Down
2 changes: 1 addition & 1 deletion jdk/test/javax/net/ssl/Stapling/SSLSocketWithStapling.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
* @test
* @bug 8046321 8153829
* @summary OCSP Stapling for TLS
* @library ../../../../java/security/testlibrary
* @library /test/lib ../../../../java/security/testlibrary
* @build CertificateBuilder SimpleOCSPServer
* @run main/othervm SSLSocketWithStapling
*/
Expand Down
2 changes: 1 addition & 1 deletion jdk/test/javax/net/ssl/Stapling/StapleEnableProps.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
* @test
* @bug 8145854 8153829
* @summary SSLContextImpl.statusResponseManager should be generated if required
* @library ../../../../java/security/testlibrary
* @library /test/lib ../../../../java/security/testlibrary
* @build CertificateBuilder SimpleOCSPServer
* @run main/othervm StapleEnableProps
*/
Expand Down
Loading