xref: /aosp_15_r20/external/boringssl/src/ssl/bio_ssl.cc (revision 8fb009dc861624b67b6cdb62ea21f0f22d0c584b)
1*8fb009dcSAndroid Build Coastguard Worker /*
2*8fb009dcSAndroid Build Coastguard Worker  * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
3*8fb009dcSAndroid Build Coastguard Worker  *
4*8fb009dcSAndroid Build Coastguard Worker  * Licensed under the OpenSSL license (the "License").  You may not use
5*8fb009dcSAndroid Build Coastguard Worker  * this file except in compliance with the License.  You can obtain a copy
6*8fb009dcSAndroid Build Coastguard Worker  * in the file LICENSE in the source distribution or at
7*8fb009dcSAndroid Build Coastguard Worker  * https://www.openssl.org/source/license.html
8*8fb009dcSAndroid Build Coastguard Worker  */
9*8fb009dcSAndroid Build Coastguard Worker 
10*8fb009dcSAndroid Build Coastguard Worker #include <openssl/ssl.h>
11*8fb009dcSAndroid Build Coastguard Worker 
12*8fb009dcSAndroid Build Coastguard Worker #include <openssl/bio.h>
13*8fb009dcSAndroid Build Coastguard Worker 
14*8fb009dcSAndroid Build Coastguard Worker 
get_ssl(BIO * bio)15*8fb009dcSAndroid Build Coastguard Worker static SSL *get_ssl(BIO *bio) {
16*8fb009dcSAndroid Build Coastguard Worker   return reinterpret_cast<SSL *>(bio->ptr);
17*8fb009dcSAndroid Build Coastguard Worker }
18*8fb009dcSAndroid Build Coastguard Worker 
ssl_read(BIO * bio,char * out,int outl)19*8fb009dcSAndroid Build Coastguard Worker static int ssl_read(BIO *bio, char *out, int outl) {
20*8fb009dcSAndroid Build Coastguard Worker   SSL *ssl = get_ssl(bio);
21*8fb009dcSAndroid Build Coastguard Worker   if (ssl == NULL) {
22*8fb009dcSAndroid Build Coastguard Worker     return 0;
23*8fb009dcSAndroid Build Coastguard Worker   }
24*8fb009dcSAndroid Build Coastguard Worker 
25*8fb009dcSAndroid Build Coastguard Worker   BIO_clear_retry_flags(bio);
26*8fb009dcSAndroid Build Coastguard Worker 
27*8fb009dcSAndroid Build Coastguard Worker   const int ret = SSL_read(ssl, out, outl);
28*8fb009dcSAndroid Build Coastguard Worker 
29*8fb009dcSAndroid Build Coastguard Worker   switch (SSL_get_error(ssl, ret)) {
30*8fb009dcSAndroid Build Coastguard Worker     case SSL_ERROR_WANT_READ:
31*8fb009dcSAndroid Build Coastguard Worker       BIO_set_retry_read(bio);
32*8fb009dcSAndroid Build Coastguard Worker       break;
33*8fb009dcSAndroid Build Coastguard Worker 
34*8fb009dcSAndroid Build Coastguard Worker     case SSL_ERROR_WANT_WRITE:
35*8fb009dcSAndroid Build Coastguard Worker       BIO_set_retry_write(bio);
36*8fb009dcSAndroid Build Coastguard Worker       break;
37*8fb009dcSAndroid Build Coastguard Worker 
38*8fb009dcSAndroid Build Coastguard Worker     case SSL_ERROR_WANT_ACCEPT:
39*8fb009dcSAndroid Build Coastguard Worker       BIO_set_retry_special(bio);
40*8fb009dcSAndroid Build Coastguard Worker       BIO_set_retry_reason(bio, BIO_RR_ACCEPT);
41*8fb009dcSAndroid Build Coastguard Worker       break;
42*8fb009dcSAndroid Build Coastguard Worker 
43*8fb009dcSAndroid Build Coastguard Worker     case SSL_ERROR_WANT_CONNECT:
44*8fb009dcSAndroid Build Coastguard Worker       BIO_set_retry_special(bio);
45*8fb009dcSAndroid Build Coastguard Worker       BIO_set_retry_reason(bio, BIO_RR_CONNECT);
46*8fb009dcSAndroid Build Coastguard Worker       break;
47*8fb009dcSAndroid Build Coastguard Worker 
48*8fb009dcSAndroid Build Coastguard Worker     case SSL_ERROR_NONE:
49*8fb009dcSAndroid Build Coastguard Worker     case SSL_ERROR_SYSCALL:
50*8fb009dcSAndroid Build Coastguard Worker     case SSL_ERROR_SSL:
51*8fb009dcSAndroid Build Coastguard Worker     case SSL_ERROR_ZERO_RETURN:
52*8fb009dcSAndroid Build Coastguard Worker     default:
53*8fb009dcSAndroid Build Coastguard Worker       break;
54*8fb009dcSAndroid Build Coastguard Worker   }
55*8fb009dcSAndroid Build Coastguard Worker 
56*8fb009dcSAndroid Build Coastguard Worker   return ret;
57*8fb009dcSAndroid Build Coastguard Worker }
58*8fb009dcSAndroid Build Coastguard Worker 
ssl_write(BIO * bio,const char * out,int outl)59*8fb009dcSAndroid Build Coastguard Worker static int ssl_write(BIO *bio, const char *out, int outl) {
60*8fb009dcSAndroid Build Coastguard Worker   SSL *ssl = get_ssl(bio);
61*8fb009dcSAndroid Build Coastguard Worker   if (ssl == NULL) {
62*8fb009dcSAndroid Build Coastguard Worker     return 0;
63*8fb009dcSAndroid Build Coastguard Worker   }
64*8fb009dcSAndroid Build Coastguard Worker 
65*8fb009dcSAndroid Build Coastguard Worker   BIO_clear_retry_flags(bio);
66*8fb009dcSAndroid Build Coastguard Worker 
67*8fb009dcSAndroid Build Coastguard Worker   const int ret = SSL_write(ssl, out, outl);
68*8fb009dcSAndroid Build Coastguard Worker 
69*8fb009dcSAndroid Build Coastguard Worker   switch (SSL_get_error(ssl, ret)) {
70*8fb009dcSAndroid Build Coastguard Worker     case SSL_ERROR_WANT_WRITE:
71*8fb009dcSAndroid Build Coastguard Worker       BIO_set_retry_write(bio);
72*8fb009dcSAndroid Build Coastguard Worker       break;
73*8fb009dcSAndroid Build Coastguard Worker 
74*8fb009dcSAndroid Build Coastguard Worker     case SSL_ERROR_WANT_READ:
75*8fb009dcSAndroid Build Coastguard Worker       BIO_set_retry_read(bio);
76*8fb009dcSAndroid Build Coastguard Worker       break;
77*8fb009dcSAndroid Build Coastguard Worker 
78*8fb009dcSAndroid Build Coastguard Worker     case SSL_ERROR_WANT_CONNECT:
79*8fb009dcSAndroid Build Coastguard Worker       BIO_set_retry_special(bio);
80*8fb009dcSAndroid Build Coastguard Worker       BIO_set_retry_reason(bio, BIO_RR_CONNECT);
81*8fb009dcSAndroid Build Coastguard Worker       break;
82*8fb009dcSAndroid Build Coastguard Worker 
83*8fb009dcSAndroid Build Coastguard Worker     case SSL_ERROR_NONE:
84*8fb009dcSAndroid Build Coastguard Worker     case SSL_ERROR_SYSCALL:
85*8fb009dcSAndroid Build Coastguard Worker     case SSL_ERROR_SSL:
86*8fb009dcSAndroid Build Coastguard Worker     default:
87*8fb009dcSAndroid Build Coastguard Worker       break;
88*8fb009dcSAndroid Build Coastguard Worker   }
89*8fb009dcSAndroid Build Coastguard Worker 
90*8fb009dcSAndroid Build Coastguard Worker   return ret;
91*8fb009dcSAndroid Build Coastguard Worker }
92*8fb009dcSAndroid Build Coastguard Worker 
ssl_ctrl(BIO * bio,int cmd,long num,void * ptr)93*8fb009dcSAndroid Build Coastguard Worker static long ssl_ctrl(BIO *bio, int cmd, long num, void *ptr) {
94*8fb009dcSAndroid Build Coastguard Worker   SSL *ssl = get_ssl(bio);
95*8fb009dcSAndroid Build Coastguard Worker   if (ssl == NULL && cmd != BIO_C_SET_SSL) {
96*8fb009dcSAndroid Build Coastguard Worker     return 0;
97*8fb009dcSAndroid Build Coastguard Worker   }
98*8fb009dcSAndroid Build Coastguard Worker 
99*8fb009dcSAndroid Build Coastguard Worker   switch (cmd) {
100*8fb009dcSAndroid Build Coastguard Worker     case BIO_C_SET_SSL:
101*8fb009dcSAndroid Build Coastguard Worker       if (ssl != NULL) {
102*8fb009dcSAndroid Build Coastguard Worker         // OpenSSL allows reusing an SSL BIO with a different SSL object. We do
103*8fb009dcSAndroid Build Coastguard Worker         // not support this.
104*8fb009dcSAndroid Build Coastguard Worker         OPENSSL_PUT_ERROR(SSL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
105*8fb009dcSAndroid Build Coastguard Worker         return 0;
106*8fb009dcSAndroid Build Coastguard Worker       }
107*8fb009dcSAndroid Build Coastguard Worker 
108*8fb009dcSAndroid Build Coastguard Worker       // Note this differs from upstream OpenSSL, which synchronizes
109*8fb009dcSAndroid Build Coastguard Worker       // |bio->next_bio| with |ssl|'s rbio here, and on |BIO_CTRL_PUSH|. We call
110*8fb009dcSAndroid Build Coastguard Worker       // into the corresponding |BIO| directly. (We can implement the upstream
111*8fb009dcSAndroid Build Coastguard Worker       // behavior if it ends up necessary.)
112*8fb009dcSAndroid Build Coastguard Worker       bio->shutdown = static_cast<int>(num);
113*8fb009dcSAndroid Build Coastguard Worker       bio->ptr = ptr;
114*8fb009dcSAndroid Build Coastguard Worker       bio->init = 1;
115*8fb009dcSAndroid Build Coastguard Worker       return 1;
116*8fb009dcSAndroid Build Coastguard Worker 
117*8fb009dcSAndroid Build Coastguard Worker     case BIO_CTRL_GET_CLOSE:
118*8fb009dcSAndroid Build Coastguard Worker       return bio->shutdown;
119*8fb009dcSAndroid Build Coastguard Worker 
120*8fb009dcSAndroid Build Coastguard Worker     case BIO_CTRL_SET_CLOSE:
121*8fb009dcSAndroid Build Coastguard Worker       bio->shutdown = static_cast<int>(num);
122*8fb009dcSAndroid Build Coastguard Worker       return 1;
123*8fb009dcSAndroid Build Coastguard Worker 
124*8fb009dcSAndroid Build Coastguard Worker     case BIO_CTRL_WPENDING:
125*8fb009dcSAndroid Build Coastguard Worker       return BIO_ctrl(SSL_get_wbio(ssl), cmd, num, ptr);
126*8fb009dcSAndroid Build Coastguard Worker 
127*8fb009dcSAndroid Build Coastguard Worker     case BIO_CTRL_PENDING:
128*8fb009dcSAndroid Build Coastguard Worker       return SSL_pending(ssl);
129*8fb009dcSAndroid Build Coastguard Worker 
130*8fb009dcSAndroid Build Coastguard Worker     case BIO_CTRL_FLUSH: {
131*8fb009dcSAndroid Build Coastguard Worker       BIO *wbio = SSL_get_wbio(ssl);
132*8fb009dcSAndroid Build Coastguard Worker       BIO_clear_retry_flags(bio);
133*8fb009dcSAndroid Build Coastguard Worker       long ret = BIO_ctrl(wbio, cmd, num, ptr);
134*8fb009dcSAndroid Build Coastguard Worker       BIO_set_flags(bio, BIO_get_retry_flags(wbio));
135*8fb009dcSAndroid Build Coastguard Worker       BIO_set_retry_reason(bio, BIO_get_retry_reason(wbio));
136*8fb009dcSAndroid Build Coastguard Worker       return ret;
137*8fb009dcSAndroid Build Coastguard Worker     }
138*8fb009dcSAndroid Build Coastguard Worker 
139*8fb009dcSAndroid Build Coastguard Worker     case BIO_CTRL_PUSH:
140*8fb009dcSAndroid Build Coastguard Worker     case BIO_CTRL_POP:
141*8fb009dcSAndroid Build Coastguard Worker     case BIO_CTRL_DUP:
142*8fb009dcSAndroid Build Coastguard Worker       return -1;
143*8fb009dcSAndroid Build Coastguard Worker 
144*8fb009dcSAndroid Build Coastguard Worker     default:
145*8fb009dcSAndroid Build Coastguard Worker       return BIO_ctrl(SSL_get_rbio(ssl), cmd, num, ptr);
146*8fb009dcSAndroid Build Coastguard Worker   }
147*8fb009dcSAndroid Build Coastguard Worker }
148*8fb009dcSAndroid Build Coastguard Worker 
ssl_new(BIO * bio)149*8fb009dcSAndroid Build Coastguard Worker static int ssl_new(BIO *bio) {
150*8fb009dcSAndroid Build Coastguard Worker   return 1;
151*8fb009dcSAndroid Build Coastguard Worker }
152*8fb009dcSAndroid Build Coastguard Worker 
ssl_free(BIO * bio)153*8fb009dcSAndroid Build Coastguard Worker static int ssl_free(BIO *bio) {
154*8fb009dcSAndroid Build Coastguard Worker   SSL *ssl = get_ssl(bio);
155*8fb009dcSAndroid Build Coastguard Worker 
156*8fb009dcSAndroid Build Coastguard Worker   if (ssl == NULL) {
157*8fb009dcSAndroid Build Coastguard Worker     return 1;
158*8fb009dcSAndroid Build Coastguard Worker   }
159*8fb009dcSAndroid Build Coastguard Worker 
160*8fb009dcSAndroid Build Coastguard Worker   SSL_shutdown(ssl);
161*8fb009dcSAndroid Build Coastguard Worker   if (bio->shutdown) {
162*8fb009dcSAndroid Build Coastguard Worker     SSL_free(ssl);
163*8fb009dcSAndroid Build Coastguard Worker   }
164*8fb009dcSAndroid Build Coastguard Worker 
165*8fb009dcSAndroid Build Coastguard Worker   return 1;
166*8fb009dcSAndroid Build Coastguard Worker }
167*8fb009dcSAndroid Build Coastguard Worker 
ssl_callback_ctrl(BIO * bio,int cmd,bio_info_cb fp)168*8fb009dcSAndroid Build Coastguard Worker static long ssl_callback_ctrl(BIO *bio, int cmd, bio_info_cb fp) {
169*8fb009dcSAndroid Build Coastguard Worker   SSL *ssl = get_ssl(bio);
170*8fb009dcSAndroid Build Coastguard Worker   if (ssl == NULL) {
171*8fb009dcSAndroid Build Coastguard Worker     return 0;
172*8fb009dcSAndroid Build Coastguard Worker   }
173*8fb009dcSAndroid Build Coastguard Worker 
174*8fb009dcSAndroid Build Coastguard Worker   switch (cmd) {
175*8fb009dcSAndroid Build Coastguard Worker     case BIO_CTRL_SET_CALLBACK:
176*8fb009dcSAndroid Build Coastguard Worker       return -1;
177*8fb009dcSAndroid Build Coastguard Worker 
178*8fb009dcSAndroid Build Coastguard Worker     default:
179*8fb009dcSAndroid Build Coastguard Worker       return BIO_callback_ctrl(SSL_get_rbio(ssl), cmd, fp);
180*8fb009dcSAndroid Build Coastguard Worker   }
181*8fb009dcSAndroid Build Coastguard Worker }
182*8fb009dcSAndroid Build Coastguard Worker 
183*8fb009dcSAndroid Build Coastguard Worker static const BIO_METHOD ssl_method = {
184*8fb009dcSAndroid Build Coastguard Worker     BIO_TYPE_SSL, "SSL",    ssl_write, ssl_read, NULL,
185*8fb009dcSAndroid Build Coastguard Worker     NULL,         ssl_ctrl, ssl_new,   ssl_free, ssl_callback_ctrl,
186*8fb009dcSAndroid Build Coastguard Worker };
187*8fb009dcSAndroid Build Coastguard Worker 
BIO_f_ssl(void)188*8fb009dcSAndroid Build Coastguard Worker const BIO_METHOD *BIO_f_ssl(void) { return &ssl_method; }
189*8fb009dcSAndroid Build Coastguard Worker 
BIO_set_ssl(BIO * bio,SSL * ssl,int take_owership)190*8fb009dcSAndroid Build Coastguard Worker long BIO_set_ssl(BIO *bio, SSL *ssl, int take_owership) {
191*8fb009dcSAndroid Build Coastguard Worker   return BIO_ctrl(bio, BIO_C_SET_SSL, take_owership, ssl);
192*8fb009dcSAndroid Build Coastguard Worker }
193