xref: /aosp_15_r20/external/cronet/third_party/netty-tcnative/src/c/sslutils.c (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 /*
2  * Copyright 2016 The Netty Project
3  *
4  * The Netty Project licenses this file to you under the Apache License,
5  * version 2.0 (the "License"); you may not use this file except in compliance
6  * with the License. You may obtain a copy of the License at:
7  *
8  *   http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13  * License for the specific language governing permissions and limitations
14  * under the License.
15  */
16 /* Licensed to the Apache Software Foundation (ASF) under one or more
17  * contributor license agreements.  See the NOTICE file distributed with
18  * this work for additional information regarding copyright ownership.
19  * The ASF licenses this file to You under the Apache License, Version 2.0
20  * (the "License"); you may not use this file except in compliance with
21  * the License.  You may obtain a copy of the License at
22  *
23  *     http://www.apache.org/licenses/LICENSE-2.0
24  *
25  * Unless required by applicable law or agreed to in writing, software
26  * distributed under the License is distributed on an "AS IS" BASIS,
27  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
28  * See the License for the specific language governing permissions and
29  * limitations under the License.
30  */
31 
32 #include "tcn.h"
33 
34 #include "ssl_private.h"
35 
36 /*  _________________________________________________________________
37 **
38 **  Additional High-Level Functions for OpenSSL
39 **  _________________________________________________________________
40 */
41 
42 
43 /*
44  * Adapted from OpenSSL:
45  * http://osxr.org/openssl/source/ssl/ssl_locl.h#0291
46  */
47 /* Bits for algorithm_mkey (key exchange algorithm) */
48 #define SSL_kRSA        0x00000001L /* RSA key exchange */
49 #define SSL_kDHr        0x00000002L /* DH cert, RSA CA cert */ /* no such ciphersuites supported! */
50 #define SSL_kDHd        0x00000004L /* DH cert, DSA CA cert */ /* no such ciphersuite supported! */
51 #define SSL_kEDH        0x00000008L /* tmp DH key no DH cert */
52 #define SSL_kKRB5       0x00000010L /* Kerberos5 key exchange */
53 #define SSL_kECDHr      0x00000020L /* ECDH cert, RSA CA cert */
54 #define SSL_kECDHe      0x00000040L /* ECDH cert, ECDSA CA cert */
55 #define SSL_kEECDH      0x00000080L /* ephemeral ECDH */
56 #define SSL_kPSK        0x00000100L /* PSK */
57 #define SSL_kGOST       0x00000200L /* GOST key exchange */
58 #define SSL_kSRP        0x00000400L /* SRP */
59 
60 /* Bits for algorithm_auth (server authentication) */
61 #define SSL_aRSA        0x00000001L /* RSA auth */
62 #define SSL_aDSS        0x00000002L /* DSS auth */
63 #define SSL_aNULL       0x00000004L /* no auth (i.e. use ADH or AECDH) */
64 #define SSL_aDH         0x00000008L /* Fixed DH auth (kDHd or kDHr) */ /* no such ciphersuites supported! */
65 #define SSL_aECDH       0x00000010L /* Fixed ECDH auth (kECDHe or kECDHr) */
66 #define SSL_aKRB5       0x00000020L /* KRB5 auth */
67 #define SSL_aECDSA      0x00000040L /* ECDSA auth*/
68 #define SSL_aPSK        0x00000080L /* PSK auth */
69 #define SSL_aGOST94     0x00000100L /* GOST R 34.10-94 signature auth */
70 #define SSL_aGOST01     0x00000200L /* GOST R 34.10-2001 signature auth */
71 
72 const char* TCN_UNKNOWN_AUTH_METHOD = "UNKNOWN";
73 
74 /* OpenSSL end */
75 
76 /*
77  * Adapted from Android:
78  * https://android.googlesource.com/platform/external/openssl/+/master/patches/0003-jsse.patch
79  */
SSL_cipher_authentication_method(const SSL_CIPHER * cipher)80 const char* SSL_cipher_authentication_method(const SSL_CIPHER* cipher){
81 #ifndef OPENSSL_IS_BORINGSSL
82     switch (cipher->algorithm_mkey)
83         {
84     case SSL_kRSA:
85         return SSL_TXT_RSA;
86     case SSL_kDHr:
87         return SSL_TXT_DH "_" SSL_TXT_RSA;
88 
89     case SSL_kDHd:
90         return SSL_TXT_DH "_" SSL_TXT_DSS;
91     case SSL_kEDH:
92         switch (cipher->algorithm_auth)
93             {
94         case SSL_aDSS:
95             return "DHE_" SSL_TXT_DSS;
96         case SSL_aRSA:
97             return "DHE_" SSL_TXT_RSA;
98         case SSL_aNULL:
99             return SSL_TXT_DH "_anon";
100         default:
101             return TCN_UNKNOWN_AUTH_METHOD;
102             }
103     case SSL_kKRB5:
104         return SSL_TXT_KRB5;
105     case SSL_kECDHr:
106         return SSL_TXT_ECDH "_" SSL_TXT_RSA;
107     case SSL_kECDHe:
108         return SSL_TXT_ECDH "_" SSL_TXT_ECDSA;
109     case SSL_kEECDH:
110         switch (cipher->algorithm_auth)
111             {
112         case SSL_aECDSA:
113             return "ECDHE_" SSL_TXT_ECDSA;
114         case SSL_aRSA:
115             return "ECDHE_" SSL_TXT_RSA;
116         case SSL_aNULL:
117             return SSL_TXT_ECDH "_anon";
118         default:
119             return TCN_UNKNOWN_AUTH_METHOD;
120             }
121     default:
122         return TCN_UNKNOWN_AUTH_METHOD;
123     }
124 #else
125     return SSL_CIPHER_get_kx_name(cipher);
126 #endif
127 
128 }
129 
130 /* we initialize this index at startup time
131  * and never write to it at request time,
132  * so this static is thread safe.
133  * also note that OpenSSL increments at static variable when
134  * SSL_get_ex_new_index() is called, so we _must_ do this at startup.
135  */
136 static int SSL_app_data2_idx = -1;
137 static int SSL_app_data3_idx = -1;
138 static int SSL_app_data4_idx = -1;
SSL_init_app_data_idx()139 void SSL_init_app_data_idx()
140 {
141     int i;
142 
143     if (SSL_app_data2_idx == -1) {
144         /* we _do_ need to call this two times */
145         for (i = 0; i <= 1; i++) {
146             SSL_app_data2_idx = SSL_get_ex_new_index(0, "tcn_ssl_ctxt_t*", NULL, NULL, NULL);
147         }
148     }
149 
150     if (SSL_app_data3_idx == -1) {
151         SSL_app_data3_idx = SSL_get_ex_new_index(0, "int* handshakeCount", NULL, NULL, NULL);
152     }
153 
154     if (SSL_app_data4_idx == -1) {
155         SSL_app_data4_idx = SSL_get_ex_new_index(0, "tcn_ssl_verify_config_t*", NULL, NULL, NULL);
156     }
157 }
158 
SSL_get_app_data2(SSL * ssl)159 void *SSL_get_app_data2(SSL *ssl)
160 {
161     return (void *)SSL_get_ex_data(ssl, SSL_app_data2_idx);
162 }
163 
SSL_set_app_data2(SSL * ssl,void * arg)164 void SSL_set_app_data2(SSL *ssl, void *arg)
165 {
166     SSL_set_ex_data(ssl, SSL_app_data2_idx, (char *)arg);
167     return;
168 }
169 
SSL_get_app_data3(SSL * ssl)170 void *SSL_get_app_data3(SSL *ssl)
171 {
172     return SSL_get_ex_data(ssl, SSL_app_data3_idx);
173 }
174 
SSL_set_app_data3(SSL * ssl,void * arg)175 void SSL_set_app_data3(SSL *ssl, void *arg)
176 {
177     SSL_set_ex_data(ssl, SSL_app_data3_idx, arg);
178 }
179 
SSL_get_app_data4(SSL * ssl)180 void *SSL_get_app_data4(SSL *ssl)
181 {
182     return SSL_get_ex_data(ssl, SSL_app_data4_idx);
183 }
184 
SSL_set_app_data4(SSL * ssl,void * arg)185 void SSL_set_app_data4(SSL *ssl, void *arg)
186 {
187     SSL_set_ex_data(ssl, SSL_app_data4_idx, arg);
188 }
189 
SSL_password_callback(char * buf,int bufsiz,int verify,void * cb)190 int SSL_password_callback(char *buf, int bufsiz, int verify,
191                           void *cb)
192 {
193     char *password = (char *) cb;
194 
195     if (buf == NULL || password == NULL)
196         return 0;
197     *buf = '\0';
198 
199     if (password[0]) {
200         /* Return already obtained password */
201         strncpy(buf, password, bufsiz);
202     }
203 
204     buf[bufsiz - 1] = '\0';
205     return (int)strlen(buf);
206 }
207 
208 #if (OPENSSL_VERSION_NUMBER < 0x10100000L) || defined(OPENSSL_USE_DEPRECATED) || defined(LIBRESSL_VERSION_NUMBER)
209 
210 static unsigned char dh0512_p[]={
211     0xD9,0xBA,0xBF,0xFD,0x69,0x38,0xC9,0x51,0x2D,0x19,0x37,0x39,
212     0xD7,0x7D,0x7E,0x3E,0x25,0x58,0x55,0x94,0x90,0x60,0x93,0x7A,
213     0xF2,0xD5,0x61,0x5F,0x06,0xE8,0x08,0xB4,0x57,0xF4,0xCF,0xB4,
214     0x41,0xCC,0xC4,0xAC,0xD4,0xF0,0x45,0x88,0xC9,0xD1,0x21,0x4C,
215     0xB6,0x72,0x48,0xBD,0x73,0x80,0xE0,0xDD,0x88,0x41,0xA0,0xF1,
216     0xEA,0x4B,0x71,0x13
217 };
218 static unsigned char dh1024_p[]={
219     0xA2,0x95,0x7E,0x7C,0xA9,0xD5,0x55,0x1D,0x7C,0x77,0x11,0xAC,
220     0xFD,0x48,0x8C,0x3B,0x94,0x1B,0xC5,0xC0,0x99,0x93,0xB5,0xDC,
221     0xDC,0x06,0x76,0x9E,0xED,0x1E,0x3D,0xBB,0x9A,0x29,0xD6,0x8B,
222     0x1F,0xF6,0xDA,0xC9,0xDF,0xD5,0x02,0x4F,0x09,0xDE,0xEC,0x2C,
223     0x59,0x1E,0x82,0x32,0x80,0x9B,0xED,0x51,0x68,0xD2,0xFB,0x1E,
224     0x25,0xDB,0xDF,0x9C,0x11,0x70,0xDF,0xCA,0x19,0x03,0x3D,0x3D,
225     0xC1,0xAC,0x28,0x88,0x4F,0x13,0xAF,0x16,0x60,0x6B,0x5B,0x2F,
226     0x56,0xC7,0x5B,0x5D,0xDE,0x8F,0x50,0x08,0xEC,0xB1,0xB9,0x29,
227     0xAA,0x54,0xF4,0x05,0xC9,0xDF,0x95,0x9D,0x79,0xC6,0xEA,0x3F,
228     0xC9,0x70,0x42,0xDA,0x90,0xC7,0xCC,0x12,0xB9,0x87,0x86,0x39,
229     0x1E,0x1A,0xCE,0xF7,0x3F,0x15,0xB5,0x2B
230 };
231 static unsigned char dh2048_p[]={
232     0xF2,0x4A,0xFC,0x7E,0x73,0x48,0x21,0x03,0xD1,0x1D,0xA8,0x16,
233     0x87,0xD0,0xD2,0xDC,0x42,0xA8,0xD2,0x73,0xE3,0xA9,0x21,0x31,
234     0x70,0x5D,0x69,0xC7,0x8F,0x95,0x0C,0x9F,0xB8,0x0E,0x37,0xAE,
235     0xD1,0x6F,0x36,0x1C,0x26,0x63,0x2A,0x36,0xBA,0x0D,0x2A,0xF5,
236     0x1A,0x0F,0xE8,0xC0,0xEA,0xD1,0xB5,0x52,0x47,0x1F,0x9A,0x0C,
237     0x0F,0xED,0x71,0x51,0xED,0xE6,0x62,0xD5,0xF8,0x81,0x93,0x55,
238     0xC1,0x0F,0xB4,0x72,0x64,0xB3,0x73,0xAA,0x90,0x9A,0x81,0xCE,
239     0x03,0xFD,0x6D,0xB1,0x27,0x7D,0xE9,0x90,0x5E,0xE2,0x10,0x74,
240     0x4F,0x94,0xC3,0x05,0x21,0x73,0xA9,0x12,0x06,0x9B,0x0E,0x20,
241     0xD1,0x5F,0xF7,0xC9,0x4C,0x9D,0x4F,0xFA,0xCA,0x4D,0xFD,0xFF,
242     0x6A,0x62,0x9F,0xF0,0x0F,0x3B,0xA9,0x1D,0xF2,0x69,0x29,0x00,
243     0xBD,0xE9,0xB0,0x9D,0x88,0xC7,0x4A,0xAE,0xB0,0x53,0xAC,0xA2,
244     0x27,0x40,0x88,0x58,0x8F,0x26,0xB2,0xC2,0x34,0x7D,0xA2,0xCF,
245     0x92,0x60,0x9B,0x35,0xF6,0xF3,0x3B,0xC3,0xAA,0xD8,0x58,0x9C,
246     0xCF,0x5D,0x9F,0xDB,0x14,0x93,0xFA,0xA3,0xFA,0x44,0xB1,0xB2,
247     0x4B,0x0F,0x08,0x70,0x44,0x71,0x3A,0x73,0x45,0x8E,0x6D,0x9C,
248     0x56,0xBC,0x9A,0xB5,0xB1,0x3D,0x8B,0x1F,0x1E,0x2B,0x0E,0x93,
249     0xC2,0x9B,0x84,0xE2,0xE8,0xFC,0x29,0x85,0x83,0x8D,0x2E,0x5C,
250     0xDD,0x9A,0xBB,0xFD,0xF0,0x87,0xBF,0xAF,0xC4,0xB6,0x1D,0xE7,
251     0xF9,0x46,0x50,0x7F,0xC3,0xAC,0xFD,0xC9,0x8C,0x9D,0x66,0x6B,
252     0x4C,0x6A,0xC9,0x3F,0x0C,0x0A,0x74,0x94,0x41,0x85,0x26,0x8F,
253     0x9F,0xF0,0x7C,0x0B
254 };
255 static unsigned char dh4096_p[] = {
256     0x8D,0xD3,0x8F,0x77,0x6F,0x6F,0xB0,0x74,0x3F,0x22,0xE9,0xD1,
257     0x17,0x15,0x69,0xD8,0x24,0x85,0xCD,0xC4,0xE4,0x0E,0xF6,0x52,
258     0x40,0xF7,0x1C,0x34,0xD0,0xA5,0x20,0x77,0xE2,0xFC,0x7D,0xA1,
259     0x82,0xF1,0xF3,0x78,0x95,0x05,0x5B,0xB8,0xDB,0xB3,0xE4,0x17,
260     0x93,0xD6,0x68,0xA7,0x0A,0x0C,0xC5,0xBB,0x9C,0x5E,0x1E,0x83,
261     0x72,0xB3,0x12,0x81,0xA2,0xF5,0xCD,0x44,0x67,0xAA,0xE8,0xAD,
262     0x1E,0x8F,0x26,0x25,0xF2,0x8A,0xA0,0xA5,0xF4,0xFB,0x95,0xAE,
263     0x06,0x50,0x4B,0xD0,0xE7,0x0C,0x55,0x88,0xAA,0xE6,0xB8,0xF6,
264     0xE9,0x2F,0x8D,0xA7,0xAD,0x84,0xBC,0x8D,0x4C,0xFE,0x76,0x60,
265     0xCD,0xC8,0xED,0x7C,0xBF,0xF3,0xC1,0xF8,0x6A,0xED,0xEC,0xE9,
266     0x13,0x7D,0x4E,0x72,0x20,0x77,0x06,0xA4,0x12,0xF8,0xD2,0x34,
267     0x6F,0xDC,0x97,0xAB,0xD3,0xA0,0x45,0x8E,0x7D,0x21,0xA9,0x35,
268     0x6E,0xE4,0xC9,0xC4,0x53,0xFF,0xE5,0xD9,0x72,0x61,0xC4,0x8A,
269     0x75,0x78,0x36,0x97,0x1A,0xAB,0x92,0x85,0x74,0x61,0x7B,0xE0,
270     0x92,0xB8,0xC6,0x12,0xA1,0x72,0xBB,0x5B,0x61,0xAA,0xE6,0x2C,
271     0x2D,0x9F,0x45,0x79,0x9E,0xF4,0x41,0x93,0x93,0xEF,0x8B,0xEF,
272     0xB7,0xBF,0x6D,0xF0,0x91,0x11,0x4F,0x7C,0x71,0x84,0xB5,0x88,
273     0xA3,0x8C,0x1A,0xD5,0xD0,0x81,0x9C,0x50,0xAC,0xA9,0x2B,0xE9,
274     0x92,0x2D,0x73,0x7C,0x0A,0xA3,0xFA,0xD3,0x6C,0x91,0x43,0xA6,
275     0x80,0x7F,0xD7,0xC4,0xD8,0x6F,0x85,0xF8,0x15,0xFD,0x08,0xA6,
276     0xF8,0x7B,0x3A,0xF4,0xD3,0x50,0xB4,0x2F,0x75,0xC8,0x48,0xB8,
277     0xA8,0xFD,0xCA,0x8F,0x62,0xF1,0x4C,0x89,0xB7,0x18,0x67,0xB2,
278     0x93,0x2C,0xC4,0xD4,0x71,0x29,0xA9,0x26,0x20,0xED,0x65,0x37,
279     0x06,0x87,0xFC,0xFB,0x65,0x02,0x1B,0x3C,0x52,0x03,0xA1,0xBB,
280     0xCF,0xE7,0x1B,0xA4,0x1A,0xE3,0x94,0x97,0x66,0x06,0xBF,0xA9,
281     0xCE,0x1B,0x07,0x10,0xBA,0xF8,0xD4,0xD4,0x05,0xCF,0x53,0x47,
282     0x16,0x2C,0xA1,0xFC,0x6B,0xEF,0xF8,0x6C,0x23,0x34,0xEF,0xB7,
283     0xD3,0x3F,0xC2,0x42,0x5C,0x53,0x9A,0x00,0x52,0xCF,0xAC,0x42,
284     0xD3,0x3B,0x2E,0xB6,0x04,0x32,0xE1,0x09,0xED,0x64,0xCD,0x6A,
285     0x63,0x58,0xB8,0x43,0x56,0x5A,0xBE,0xA4,0x9F,0x68,0xD4,0xF7,
286     0xC9,0x04,0xDF,0xCD,0xE5,0x93,0xB0,0x2F,0x06,0x19,0x3E,0xB8,
287     0xAB,0x7E,0xF8,0xE7,0xE7,0xC8,0x53,0xA2,0x06,0xC3,0xC7,0xF9,
288     0x18,0x3B,0x51,0xC3,0x9B,0xFF,0x8F,0x00,0x0E,0x87,0x19,0x68,
289     0x2F,0x40,0xC0,0x68,0xFA,0x12,0xAE,0x57,0xB5,0xF0,0x97,0xCA,
290     0x78,0x23,0x31,0xAB,0x67,0x7B,0x10,0x6B,0x59,0x32,0x9C,0x64,
291     0x20,0x38,0x1F,0xC5,0x07,0x84,0x9E,0xC4,0x49,0xB1,0xDF,0xED,
292     0x7A,0x8A,0xC3,0xE0,0xDD,0x30,0x55,0xFF,0x95,0x45,0xA6,0xEE,
293     0xCB,0xE4,0x26,0xB9,0x8E,0x89,0x37,0x63,0xD4,0x02,0x3D,0x5B,
294     0x4F,0xE5,0x90,0xF6,0x72,0xF8,0x10,0xEE,0x31,0x04,0x54,0x17,
295     0xE3,0xD5,0x63,0x84,0x80,0x62,0x54,0x46,0x85,0x6C,0xD2,0xC1,
296     0x3E,0x19,0xBD,0xE2,0x80,0x11,0x86,0xC7,0x4B,0x7F,0x67,0x86,
297     0x47,0xD2,0x38,0xCD,0x8F,0xFE,0x65,0x3C,0x11,0xCD,0x96,0x99,
298     0x4E,0x45,0xEB,0xEC,0x1D,0x94,0x8C,0x53,
299 };
300 static unsigned char dhxxx2_g[]={
301     0x02
302 };
303 
get_dh(int idx)304 static DH *get_dh(int idx)
305 {
306     DH *dh;
307     if ((dh = DH_new()) == NULL)
308         return NULL;
309     switch (idx) {
310         case SSL_TMP_KEY_DH_512:
311             dh->p = BN_bin2bn(dh0512_p, sizeof(dh0512_p), NULL);
312         break;
313         case SSL_TMP_KEY_DH_1024:
314             dh->p = BN_bin2bn(dh1024_p, sizeof(dh1024_p), NULL);
315         break;
316         case SSL_TMP_KEY_DH_2048:
317             dh->p = BN_bin2bn(dh2048_p, sizeof(dh2048_p), NULL);
318         break;
319         case SSL_TMP_KEY_DH_4096:
320             dh->p = BN_bin2bn(dh4096_p, sizeof(dh2048_p), NULL);
321         break;
322     }
323     dh->g = BN_bin2bn(dhxxx2_g, sizeof(dhxxx2_g), NULL);
324     if ((dh->p == NULL) || (dh->g == NULL)) {
325         DH_free(dh);
326         return NULL;
327     }
328     else
329         return dh;
330     return NULL;
331 }
332 #else
get_dh(int idx)333 static DH *get_dh(int idx)
334 {
335     return NULL;
336 }
337 #endif
338 
SSL_dh_get_tmp_param(int key_len)339 DH *SSL_dh_get_tmp_param(int key_len)
340 {
341     DH *dh;
342 
343     if (key_len == 512)
344         dh = get_dh(SSL_TMP_KEY_DH_512);
345     else if (key_len == 1024)
346         dh = get_dh(SSL_TMP_KEY_DH_1024);
347     else if (key_len == 2048)
348         dh = get_dh(SSL_TMP_KEY_DH_2048);
349     else if (key_len == 4096)
350         dh = get_dh(SSL_TMP_KEY_DH_4096);
351     else
352         dh = get_dh(SSL_TMP_KEY_DH_1024);
353     return dh;
354 }
355 
356 /*
357  * Hand out the already generated DH parameters...
358  */
SSL_callback_tmp_DH(SSL * ssl,int export,int keylen)359 DH *SSL_callback_tmp_DH(SSL *ssl, int export, int keylen)
360 {
361     int idx;
362     switch (keylen) {
363         case 512:
364             idx = SSL_TMP_KEY_DH_512;
365         break;
366         case 2048:
367             idx = SSL_TMP_KEY_DH_2048;
368         break;
369         case 4096:
370             idx = SSL_TMP_KEY_DH_4096;
371         break;
372         case 1024:
373         default:
374             idx = SSL_TMP_KEY_DH_1024;
375         break;
376     }
377     return (DH *)SSL_temp_keys[idx];
378 }
379 
SSL_callback_tmp_DH_512(SSL * ssl,int export,int keylen)380 DH *SSL_callback_tmp_DH_512(SSL *ssl, int export, int keylen)
381 {
382     return (DH *)SSL_temp_keys[SSL_TMP_KEY_DH_512];
383 }
384 
SSL_callback_tmp_DH_1024(SSL * ssl,int export,int keylen)385 DH *SSL_callback_tmp_DH_1024(SSL *ssl, int export, int keylen)
386 {
387     return (DH *)SSL_temp_keys[SSL_TMP_KEY_DH_1024];
388 }
389 
SSL_callback_tmp_DH_2048(SSL * ssl,int export,int keylen)390 DH *SSL_callback_tmp_DH_2048(SSL *ssl, int export, int keylen)
391 {
392     return (DH *)SSL_temp_keys[SSL_TMP_KEY_DH_2048];
393 }
394 
SSL_callback_tmp_DH_4096(SSL * ssl,int export,int keylen)395 DH *SSL_callback_tmp_DH_4096(SSL *ssl, int export, int keylen)
396 {
397     return (DH *)SSL_temp_keys[SSL_TMP_KEY_DH_4096];
398 }
399 
400 /*
401  * Read a file that optionally contains the server certificate in PEM
402  * format, possibly followed by a sequence of CA certificates that
403  * should be sent to the peer in the SSL Certificate message.
404  */
SSL_CTX_use_certificate_chain(SSL_CTX * ctx,const char * file,bool skipfirst)405 int SSL_CTX_use_certificate_chain(SSL_CTX *ctx, const char *file, bool skipfirst)
406 {
407     BIO *bio;
408     int n;
409 
410     if ((bio = BIO_new(BIO_s_file())) == NULL)
411         return -1;
412     if (BIO_read_filename(bio, file) <= 0) {
413         BIO_free(bio);
414         return -1;
415     }
416     n = SSL_CTX_use_certificate_chain_bio(ctx, bio, skipfirst);
417     BIO_free(bio);
418     return n;
419 }
420 
SSL_CTX_setup_certs(SSL_CTX * ctx,BIO * bio,bool skipfirst,bool ca)421 static int SSL_CTX_setup_certs(SSL_CTX *ctx, BIO *bio, bool skipfirst, bool ca)
422 {
423     X509 *x509;
424     unsigned long err;
425     int n;
426 
427     /* optionally skip a leading server certificate */
428     if (skipfirst) {
429         if ((x509 = PEM_read_bio_X509(bio, NULL, NULL, NULL)) == NULL) {
430             return -1;
431         }
432         X509_free(x509);
433     }
434 
435     n = 0;
436     if (ca) {
437         while ((x509 = PEM_read_bio_X509(bio, NULL, NULL, NULL)) != NULL) {
438             if (SSL_CTX_add_client_CA(ctx, x509) != 1) {
439                 X509_free(x509);
440                 return -1;
441             }
442             // SSL_CTX_add_client_CA does not take ownership of the x509. It just calls X509_get_subject_name
443             // and make a duplicate of this value. So we should always free the x509 after this call.
444             // See https://github.com/netty/netty/issues/6249.
445             X509_free(x509);
446             n++;
447         }
448     } else {
449         /* free a perhaps already configured extra chain */
450         SSL_CTX_clear_extra_chain_certs(ctx);
451 
452         /* create new extra chain by loading the certs */
453         while ((x509 = PEM_read_bio_X509(bio, NULL, NULL, NULL)) != NULL) {
454             // SSL_CTX_add_extra_chain_cert transfers ownership of the x509 certificate if the method succeeds.
455             if (SSL_CTX_add_extra_chain_cert(ctx, x509) != 1) {
456                 X509_free(x509);
457                 return -1;
458             }
459             n++;
460         }
461     }
462 
463     /* Make sure that only the error is just an EOF */
464     if ((err = ERR_peek_error()) > 0) {
465         if (!(   ERR_GET_LIB(err) == ERR_LIB_PEM
466               && ERR_GET_REASON(err) == PEM_R_NO_START_LINE)) {
467             return -1;
468         }
469         ERR_clear_error();
470     }
471     return n;
472 }
473 
SSL_CTX_use_certificate_chain_bio(SSL_CTX * ctx,BIO * bio,bool skipfirst)474 int SSL_CTX_use_certificate_chain_bio(SSL_CTX *ctx, BIO *bio, bool skipfirst)
475 {
476     return SSL_CTX_setup_certs(ctx, bio, skipfirst, false);
477 }
478 
479 
SSL_CTX_use_client_CA_bio(SSL_CTX * ctx,BIO * bio)480 int SSL_CTX_use_client_CA_bio(SSL_CTX *ctx, BIO *bio)
481 {
482     return SSL_CTX_setup_certs(ctx, bio, false, true);
483 }
484 
SSL_use_certificate_chain_bio(SSL * ssl,BIO * bio,bool skipfirst)485 int SSL_use_certificate_chain_bio(SSL *ssl, BIO *bio, bool skipfirst)
486 {
487 #if OPENSSL_VERSION_NUMBER < 0x10002000L || defined(LIBRESSL_VERSION_NUMBER)
488     // Only supported on openssl 1.0.2+
489     return -1;
490 #else
491     X509 *x509;
492     unsigned long err;
493     int n;
494 
495     /* optionally skip a leading server certificate */
496     if (skipfirst) {
497         if ((x509 = PEM_read_bio_X509(bio, NULL, NULL, NULL)) == NULL) {
498             return -1;
499         }
500         X509_free(x509);
501     }
502 
503     /* create new extra chain by loading the certs */
504     n = 0;
505 
506     while ((x509 = PEM_read_bio_X509(bio, NULL, NULL, NULL)) != NULL) {
507         if (SSL_add0_chain_cert(ssl, x509) != 1) {
508             X509_free(x509);
509             return -1;
510         }
511         n++;
512     }
513     /* Make sure that only the error is just an EOF */
514     if ((err = ERR_peek_error()) > 0) {
515         if (!(   ERR_GET_LIB(err) == ERR_LIB_PEM
516               && ERR_GET_REASON(err) == PEM_R_NO_START_LINE)) {
517             return -1;
518         }
519         ERR_clear_error();
520     }
521     return n;
522 #endif
523 }
524 
load_pem_cert_bio(const char * password,const BIO * bio)525 X509 *load_pem_cert_bio(const char *password, const BIO *bio)
526 {
527     X509 *cert = PEM_read_bio_X509_AUX((BIO*) bio, NULL,
528                 (pem_password_cb *)SSL_password_callback,
529                 (void *)password);
530     if (cert == NULL &&
531        (ERR_GET_REASON(ERR_peek_last_error()) == PEM_R_NO_START_LINE)) {
532         ERR_clear_error();
533         BIO_ctrl((BIO*) bio, BIO_CTRL_RESET, 0, NULL);
534         cert = d2i_X509_bio((BIO*) bio, NULL);
535     }
536     return cert;
537 }
538 
load_pem_key_bio(const char * password,const BIO * bio)539 EVP_PKEY *load_pem_key_bio(const char *password, const BIO *bio)
540 {
541     EVP_PKEY *key = PEM_read_bio_PrivateKey((BIO*) bio, NULL,
542                     (pem_password_cb *)SSL_password_callback,
543                     (void *)password);
544 
545     BIO_ctrl((BIO*) bio, BIO_CTRL_RESET, 0, NULL);
546     return key;
547 }
548 
tcn_EVP_PKEY_up_ref(EVP_PKEY * pkey)549 int tcn_EVP_PKEY_up_ref(EVP_PKEY* pkey) {
550 #if defined(OPENSSL_IS_BORINGSSL)
551     // Workaround for https://bugs.chromium.org/p/boringssl/issues/detail?id=89#
552     EVP_PKEY_up_ref(pkey);
553     return 1;
554 #elif OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
555     return CRYPTO_add(&pkey->references, 1, CRYPTO_LOCK_EVP_PKEY);
556 #else
557     return EVP_PKEY_up_ref(pkey);
558 #endif
559 }
560 
tcn_X509_up_ref(X509 * cert)561 int tcn_X509_up_ref(X509* cert) {
562 #if defined(OPENSSL_IS_BORINGSSL)
563     // Workaround for https://bugs.chromium.org/p/boringssl/issues/detail?id=89#
564     X509_up_ref(cert);
565     return 1;
566 #elif OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
567     return CRYPTO_add(&cert->references, 1, CRYPTO_LOCK_X509);
568 #else
569     return X509_up_ref(cert);
570 #endif
571 }
572 
tcn_set_verify_config(tcn_ssl_verify_config_t * c,jint tcn_mode,jint depth)573 int tcn_set_verify_config(tcn_ssl_verify_config_t* c, jint tcn_mode, jint depth) {
574     if (depth >= 0) {
575         c->verify_depth = depth;
576     }
577 
578     switch (tcn_mode) {
579       case SSL_CVERIFY_IGNORED:
580         switch (c->verify_mode) {
581           case SSL_CVERIFY_NONE:
582             return SSL_VERIFY_NONE;
583           case SSL_CVERIFY_OPTIONAL:
584             return SSL_VERIFY_PEER;
585           default:
586             return (SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT);
587         }
588       case SSL_CVERIFY_NONE:
589         c->verify_mode = SSL_CVERIFY_NONE;
590         return SSL_VERIFY_NONE;
591       case SSL_CVERIFY_OPTIONAL:
592         c->verify_mode = SSL_CVERIFY_OPTIONAL;
593         return SSL_VERIFY_PEER;
594       default:
595         c->verify_mode = SSL_CVERIFY_REQUIRED;
596         return SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
597     }
598 }
599 
SSL_callback_next_protos(SSL * ssl,const unsigned char ** data,unsigned int * len,void * arg)600 int SSL_callback_next_protos(SSL *ssl, const unsigned char **data,
601                              unsigned int *len, void *arg)
602 {
603     tcn_ssl_ctxt_t *ssl_ctxt = arg;
604 
605     *data = ssl_ctxt->next_proto_data;
606     *len = ssl_ctxt->next_proto_len;
607 
608     return SSL_TLSEXT_ERR_OK;
609 }
610 
611 /* The code here is inspired by nghttp2
612  *
613  * See https://github.com/tatsuhiro-t/nghttp2/blob/ae0100a9abfcf3149b8d9e62aae216e946b517fb/src/shrpx_ssl.cc#L244 */
select_next_proto(SSL * ssl,const unsigned char ** out,unsigned char * outlen,const unsigned char * in,unsigned int inlen,unsigned char * supported_protos,unsigned int supported_protos_len,int failure_behavior)614 int select_next_proto(SSL *ssl, const unsigned char **out, unsigned char *outlen,
615         const unsigned char *in, unsigned int inlen, unsigned char *supported_protos,
616         unsigned int supported_protos_len, int failure_behavior) {
617 
618     unsigned int i = 0;
619     unsigned char target_proto_len;
620     unsigned char *p;
621     const unsigned char *end;
622     unsigned char *proto;
623     unsigned char proto_len;
624 
625     while (i < supported_protos_len) {
626         target_proto_len = *supported_protos;
627         ++supported_protos;
628 
629         p = (unsigned char*) in;
630         end = p + inlen;
631 
632         while (p < end) {
633             proto_len = *p;
634             proto = ++p;
635 
636             if (proto + proto_len <= end && target_proto_len == proto_len &&
637                     memcmp(supported_protos, proto, proto_len) == 0) {
638 
639                 // We found a match, so set the output and return with OK!
640                 *out = proto;
641                 *outlen = proto_len;
642 
643                 return SSL_TLSEXT_ERR_OK;
644             }
645             // Move on to the next protocol.
646             p += proto_len;
647         }
648 
649         // increment len and pointers.
650         i += target_proto_len;
651         supported_protos += target_proto_len;
652     }
653 
654     if (failure_behavior == SSL_SELECTOR_FAILURE_CHOOSE_MY_LAST_PROTOCOL) {
655          // There were no match but we just select our last protocol and hope the other peer support it.
656          //
657          // decrement the pointer again so the pointer points to the start of the protocol.
658          p -= proto_len;
659          *out = p;
660          *outlen = proto_len;
661          return SSL_TLSEXT_ERR_OK;
662     }
663     // TODO: OpenSSL currently not support to fail with fatal error. Once this changes we can also support it here.
664     //       Issue https://github.com/openssl/openssl/issues/188 has been created for this.
665     // Nothing matched so not select anything and just accept.
666     return SSL_TLSEXT_ERR_NOACK;
667 }
668 
SSL_callback_select_next_proto(SSL * ssl,unsigned char ** out,unsigned char * outlen,const unsigned char * in,unsigned int inlen,void * arg)669 int SSL_callback_select_next_proto(SSL *ssl, unsigned char **out, unsigned char *outlen,
670                          const unsigned char *in, unsigned int inlen,
671                          void *arg) {
672     tcn_ssl_ctxt_t *ssl_ctxt = arg;
673     return select_next_proto(ssl, (const unsigned char**) out, outlen, in, inlen, ssl_ctxt->next_proto_data, ssl_ctxt->next_proto_len, ssl_ctxt->next_selector_failure_behavior);
674 }
675 
SSL_callback_alpn_select_proto(SSL * ssl,const unsigned char ** out,unsigned char * outlen,const unsigned char * in,unsigned int inlen,void * arg)676 int SSL_callback_alpn_select_proto(SSL* ssl, const unsigned char **out, unsigned char *outlen,
677         const unsigned char *in, unsigned int inlen, void *arg) {
678     tcn_ssl_ctxt_t *ssl_ctxt = arg;
679     return select_next_proto(ssl, out, outlen, in, inlen, ssl_ctxt->alpn_proto_data, ssl_ctxt->alpn_proto_len, ssl_ctxt->alpn_selector_failure_behavior);
680 }
681