1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package io.netty.handler.codec.quic;
17
18 import io.netty.handler.ssl.util.LazyX509Certificate;
19 import org.jetbrains.annotations.Nullable;
20
21 import java.io.ByteArrayOutputStream;
22 import java.io.IOException;
23 import java.nio.charset.StandardCharsets;
24 import java.security.cert.X509Certificate;
25
26 final class BoringSSL {
27
28 static final int SSL_VERIFY_NONE = BoringSSLNativeStaticallyReferencedJniMethods.ssl_verify_none();
29 static final int SSL_VERIFY_FAIL_IF_NO_PEER_CERT = BoringSSLNativeStaticallyReferencedJniMethods
30 .ssl_verify_fail_if_no_peer_cert();
31 static final int SSL_VERIFY_PEER = BoringSSLNativeStaticallyReferencedJniMethods.ssl_verify_peer();
32 static final int X509_V_OK = BoringSSLNativeStaticallyReferencedJniMethods.x509_v_ok();
33 static final int X509_V_ERR_CERT_HAS_EXPIRED =
34 BoringSSLNativeStaticallyReferencedJniMethods.x509_v_err_cert_has_expired();
35 static final int X509_V_ERR_CERT_NOT_YET_VALID =
36 BoringSSLNativeStaticallyReferencedJniMethods.x509_v_err_cert_not_yet_valid();
37 static final int X509_V_ERR_CERT_REVOKED = BoringSSLNativeStaticallyReferencedJniMethods.x509_v_err_cert_revoked();
38 static final int X509_V_ERR_UNSPECIFIED = BoringSSLNativeStaticallyReferencedJniMethods.x509_v_err_unspecified();
39
40 static long SSLContext_new(boolean server, String[] applicationProtocols,
41 BoringSSLHandshakeCompleteCallback handshakeCompleteCallback,
42 BoringSSLCertificateCallback certificateCallback,
43 BoringSSLCertificateVerifyCallback verifyCallback,
44 @Nullable BoringSSLTlsextServernameCallback servernameCallback,
45 @Nullable BoringSSLKeylogCallback keylogCallback,
46 @Nullable BoringSSLSessionCallback sessionCallback,
47 @Nullable BoringSSLPrivateKeyMethod privateKeyMethod,
48 BoringSSLSessionTicketCallback sessionTicketCallback,
49 int verifyMode,
50 byte[][] subjectNames) {
51 return SSLContext_new0(server, toWireFormat(applicationProtocols),
52 handshakeCompleteCallback, certificateCallback, verifyCallback, servernameCallback,
53 keylogCallback, sessionCallback, privateKeyMethod, sessionTicketCallback, verifyMode, subjectNames);
54 }
55
56 private static byte @Nullable [] toWireFormat(String @Nullable [] applicationProtocols) {
57 if (applicationProtocols == null) {
58 return null;
59 }
60 try (ByteArrayOutputStream out = new ByteArrayOutputStream()) {
61 for (String p : applicationProtocols) {
62 byte[] bytes = p.getBytes(StandardCharsets.US_ASCII);
63 out.write(bytes.length);
64 out.write(bytes);
65 }
66 return out.toByteArray();
67 } catch (IOException e) {
68 throw new IllegalStateException(e);
69 }
70 }
71
72 static native long SSLContext_new();
73
74 private static native long SSLContext_new0(boolean server,
75 byte @Nullable [] applicationProtocols, Object handshakeCompleteCallback,
76 Object certificateCallback, Object verifyCallback,
77 @Nullable Object servernameCallback, @Nullable Object keylogCallback,
78 @Nullable Object sessionCallback,
79 @Nullable Object privateKeyMethod,
80 Object sessionTicketCallback,
81 int verifyDepth, byte[][] subjectNames);
82 static native void SSLContext_set_early_data_enabled(long context, boolean enabled);
83 static native long SSLContext_setSessionCacheSize(long context, long size);
84 static native long SSLContext_setSessionCacheTimeout(long context, long size);
85
86 static native void SSLContext_setSessionTicketKeys(long context, boolean enableCallback);
87
88 static int SSLContext_set1_groups_list(long ctx, String... groups) {
89 if (groups == null) {
90 throw new NullPointerException("curves");
91 }
92 if (groups.length == 0) {
93 throw new IllegalArgumentException();
94 }
95 StringBuilder sb = new StringBuilder();
96 for (String group: groups) {
97 sb.append(group);
98
99 sb.append(':');
100 }
101 sb.setLength(sb.length() - 1);
102 return SSLContext_set1_groups_list(ctx, sb.toString());
103 }
104
105 static int SSLContext_set1_sigalgs_list(long ctx, String... sigalgs) {
106 if (sigalgs.length == 0) {
107 throw new IllegalArgumentException();
108 }
109 StringBuilder sb = new StringBuilder();
110 for (String sigalg: sigalgs) {
111 sb.append(sigalg);
112
113 sb.append(':');
114 }
115 sb.setLength(sb.length() - 1);
116 return SSLContext_set1_sigalgs_list(ctx, sb.toString());
117 }
118
119 private static native int SSLContext_set1_sigalgs_list(long context, String sigalgs);
120
121 private static native int SSLContext_set1_groups_list(long context, String groups);
122 static native void SSLContext_free(long context);
123 static long SSL_new(long context, boolean server, String hostname) {
124 return SSL_new0(context, server, tlsExtHostName(hostname));
125 }
126 static native long SSL_new0(long context, boolean server, @Nullable String hostname);
127 static native void SSL_free(long ssl);
128
129 static native Runnable SSL_getTask(long ssl);
130
131 static native void SSL_cleanup(long ssl);
132
133 static native long EVP_PKEY_parse(byte[] bytes, String pass);
134 static native void EVP_PKEY_free(long key);
135
136 static native long CRYPTO_BUFFER_stack_new(long ssl, byte[][] bytes);
137 static native void CRYPTO_BUFFER_stack_free(long chain);
138
139 @Nullable
140 static native String ERR_last_error();
141
142 @Nullable
143 private static String tlsExtHostName(@Nullable String hostname) {
144 if (hostname != null && hostname.endsWith(".")) {
145
146
147 hostname = hostname.substring(0, hostname.length() - 1);
148 }
149 return hostname;
150 }
151
152 static X509Certificate[] certificates(byte[][] chain) {
153 X509Certificate[] peerCerts = new X509Certificate[chain.length];
154 for (int i = 0; i < peerCerts.length; i++) {
155 peerCerts[i] = new LazyX509Certificate(chain[i]);
156 }
157 return peerCerts;
158 }
159
160 static byte[][] subjectNames(X509Certificate[] certificates) {
161 byte[][] subjectNames = new byte[certificates.length][];
162 for (int i = 0; i < certificates.length; i++) {
163 subjectNames[i] = certificates[i].getSubjectX500Principal().getEncoded();
164 }
165 return subjectNames;
166 }
167
168 private BoringSSL() { }
169 }