xref: /aosp_15_r20/external/grpc-grpc/src/core/tsi/ssl_transport_security_utils.cc (revision cc02d7e222339f7a4f6ba5f422e6413f4bd931f2)
1 //
2 //
3 // Copyright 2022 gRPC authors.
4 //
5 // Licensed under the Apache License, Version 2.0 (the "License");
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 //     http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 //
17 //
18 
19 #include <grpc/support/port_platform.h>
20 
21 #include "src/core/tsi/ssl_transport_security_utils.h"
22 
23 #include <openssl/crypto.h>
24 #include <openssl/err.h>
25 #include <openssl/ssl.h>
26 #include <openssl/x509v3.h>
27 
28 #include "absl/status/status.h"
29 #include "absl/status/statusor.h"
30 
31 #include "src/core/tsi/transport_security_interface.h"
32 
33 namespace grpc_core {
34 
SslErrorString(int error)35 const char* SslErrorString(int error) {
36   switch (error) {
37     case SSL_ERROR_NONE:
38       return "SSL_ERROR_NONE";
39     case SSL_ERROR_ZERO_RETURN:
40       return "SSL_ERROR_ZERO_RETURN";
41     case SSL_ERROR_WANT_READ:
42       return "SSL_ERROR_WANT_READ";
43     case SSL_ERROR_WANT_WRITE:
44       return "SSL_ERROR_WANT_WRITE";
45     case SSL_ERROR_WANT_CONNECT:
46       return "SSL_ERROR_WANT_CONNECT";
47     case SSL_ERROR_WANT_ACCEPT:
48       return "SSL_ERROR_WANT_ACCEPT";
49     case SSL_ERROR_WANT_X509_LOOKUP:
50       return "SSL_ERROR_WANT_X509_LOOKUP";
51     case SSL_ERROR_SYSCALL:
52       return "SSL_ERROR_SYSCALL";
53     case SSL_ERROR_SSL:
54       return "SSL_ERROR_SSL";
55     default:
56       return "Unknown error";
57   }
58 }
59 
LogSslErrorStack(void)60 void LogSslErrorStack(void) {
61   unsigned long err;
62   while ((err = ERR_get_error()) != 0) {
63     char details[256];
64     ERR_error_string_n(static_cast<uint32_t>(err), details, sizeof(details));
65     gpr_log(GPR_ERROR, "%s", details);
66   }
67 }
68 
DoSslWrite(SSL * ssl,unsigned char * unprotected_bytes,size_t unprotected_bytes_size)69 tsi_result DoSslWrite(SSL* ssl, unsigned char* unprotected_bytes,
70                       size_t unprotected_bytes_size) {
71   GPR_ASSERT(unprotected_bytes_size <= INT_MAX);
72   ERR_clear_error();
73   int ssl_write_result = SSL_write(ssl, unprotected_bytes,
74                                    static_cast<int>(unprotected_bytes_size));
75   if (ssl_write_result < 0) {
76     ssl_write_result = SSL_get_error(ssl, ssl_write_result);
77     if (ssl_write_result == SSL_ERROR_WANT_READ) {
78       gpr_log(GPR_ERROR,
79               "Peer tried to renegotiate SSL connection. This is unsupported.");
80       return TSI_UNIMPLEMENTED;
81     } else {
82       gpr_log(GPR_ERROR, "SSL_write failed with error %s.",
83               SslErrorString(ssl_write_result));
84       return TSI_INTERNAL_ERROR;
85     }
86   }
87   return TSI_OK;
88 }
89 
DoSslRead(SSL * ssl,unsigned char * unprotected_bytes,size_t * unprotected_bytes_size)90 tsi_result DoSslRead(SSL* ssl, unsigned char* unprotected_bytes,
91                      size_t* unprotected_bytes_size) {
92   GPR_ASSERT(*unprotected_bytes_size <= INT_MAX);
93   ERR_clear_error();
94   int read_from_ssl = SSL_read(ssl, unprotected_bytes,
95                                static_cast<int>(*unprotected_bytes_size));
96   if (read_from_ssl <= 0) {
97     read_from_ssl = SSL_get_error(ssl, read_from_ssl);
98     switch (read_from_ssl) {
99       case SSL_ERROR_ZERO_RETURN:  // Received a close_notify alert.
100       case SSL_ERROR_WANT_READ:    // We need more data to finish the frame.
101         *unprotected_bytes_size = 0;
102         return TSI_OK;
103       case SSL_ERROR_WANT_WRITE:
104         gpr_log(
105             GPR_ERROR,
106             "Peer tried to renegotiate SSL connection. This is unsupported.");
107         return TSI_UNIMPLEMENTED;
108       case SSL_ERROR_SSL:
109         gpr_log(GPR_ERROR, "Corruption detected.");
110         LogSslErrorStack();
111         return TSI_DATA_CORRUPTED;
112       default:
113         gpr_log(GPR_ERROR, "SSL_read failed with error %s.",
114                 SslErrorString(read_from_ssl));
115         return TSI_PROTOCOL_FAILURE;
116     }
117   }
118   *unprotected_bytes_size = static_cast<size_t>(read_from_ssl);
119   return TSI_OK;
120 }
121 
122 // --- tsi_frame_protector util methods implementation. ---
SslProtectorProtect(const unsigned char * unprotected_bytes,const size_t buffer_size,size_t & buffer_offset,unsigned char * buffer,SSL * ssl,BIO * network_io,size_t * unprotected_bytes_size,unsigned char * protected_output_frames,size_t * protected_output_frames_size)123 tsi_result SslProtectorProtect(const unsigned char* unprotected_bytes,
124                                const size_t buffer_size, size_t& buffer_offset,
125                                unsigned char* buffer, SSL* ssl, BIO* network_io,
126                                size_t* unprotected_bytes_size,
127                                unsigned char* protected_output_frames,
128                                size_t* protected_output_frames_size) {
129   int read_from_ssl;
130   size_t available;
131   tsi_result result = TSI_OK;
132 
133   // First see if we have some pending data in the SSL BIO.
134   int pending_in_ssl = static_cast<int>(BIO_pending(network_io));
135   if (pending_in_ssl > 0) {
136     *unprotected_bytes_size = 0;
137     GPR_ASSERT(*protected_output_frames_size <= INT_MAX);
138     read_from_ssl = BIO_read(network_io, protected_output_frames,
139                              static_cast<int>(*protected_output_frames_size));
140     if (read_from_ssl < 0) {
141       gpr_log(GPR_ERROR,
142               "Could not read from BIO even though some data is pending");
143       return TSI_INTERNAL_ERROR;
144     }
145     *protected_output_frames_size = static_cast<size_t>(read_from_ssl);
146     return TSI_OK;
147   }
148 
149   // Now see if we can send a complete frame.
150   available = buffer_size - buffer_offset;
151   if (available > *unprotected_bytes_size) {
152     // If we cannot, just copy the data in our internal buffer.
153     memcpy(buffer + buffer_offset, unprotected_bytes, *unprotected_bytes_size);
154     buffer_offset += *unprotected_bytes_size;
155     *protected_output_frames_size = 0;
156     return TSI_OK;
157   }
158 
159   // If we can, prepare the buffer, send it to SSL_write and read.
160   memcpy(buffer + buffer_offset, unprotected_bytes, available);
161   result = DoSslWrite(ssl, buffer, buffer_size);
162   if (result != TSI_OK) return result;
163 
164   GPR_ASSERT(*protected_output_frames_size <= INT_MAX);
165   read_from_ssl = BIO_read(network_io, protected_output_frames,
166                            static_cast<int>(*protected_output_frames_size));
167   if (read_from_ssl < 0) {
168     gpr_log(GPR_ERROR, "Could not read from BIO after SSL_write.");
169     return TSI_INTERNAL_ERROR;
170   }
171   *protected_output_frames_size = static_cast<size_t>(read_from_ssl);
172   *unprotected_bytes_size = available;
173   buffer_offset = 0;
174   return TSI_OK;
175 }
176 
SslProtectorProtectFlush(size_t & buffer_offset,unsigned char * buffer,SSL * ssl,BIO * network_io,unsigned char * protected_output_frames,size_t * protected_output_frames_size,size_t * still_pending_size)177 tsi_result SslProtectorProtectFlush(size_t& buffer_offset,
178                                     unsigned char* buffer, SSL* ssl,
179                                     BIO* network_io,
180                                     unsigned char* protected_output_frames,
181                                     size_t* protected_output_frames_size,
182                                     size_t* still_pending_size) {
183   tsi_result result = TSI_OK;
184   int read_from_ssl = 0;
185   int pending;
186 
187   if (buffer_offset != 0) {
188     result = DoSslWrite(ssl, buffer, buffer_offset);
189     if (result != TSI_OK) return result;
190     buffer_offset = 0;
191   }
192 
193   pending = static_cast<int>(BIO_pending(network_io));
194   GPR_ASSERT(pending >= 0);
195   *still_pending_size = static_cast<size_t>(pending);
196   if (*still_pending_size == 0) return TSI_OK;
197 
198   GPR_ASSERT(*protected_output_frames_size <= INT_MAX);
199   read_from_ssl = BIO_read(network_io, protected_output_frames,
200                            static_cast<int>(*protected_output_frames_size));
201   if (read_from_ssl <= 0) {
202     gpr_log(GPR_ERROR, "Could not read from BIO after SSL_write.");
203     return TSI_INTERNAL_ERROR;
204   }
205   *protected_output_frames_size = static_cast<size_t>(read_from_ssl);
206   pending = static_cast<int>(BIO_pending(network_io));
207   GPR_ASSERT(pending >= 0);
208   *still_pending_size = static_cast<size_t>(pending);
209   return TSI_OK;
210 }
211 
SslProtectorUnprotect(const unsigned char * protected_frames_bytes,SSL * ssl,BIO * network_io,size_t * protected_frames_bytes_size,unsigned char * unprotected_bytes,size_t * unprotected_bytes_size)212 tsi_result SslProtectorUnprotect(const unsigned char* protected_frames_bytes,
213                                  SSL* ssl, BIO* network_io,
214                                  size_t* protected_frames_bytes_size,
215                                  unsigned char* unprotected_bytes,
216                                  size_t* unprotected_bytes_size) {
217   tsi_result result = TSI_OK;
218   int written_into_ssl = 0;
219   size_t output_bytes_size = *unprotected_bytes_size;
220   size_t output_bytes_offset = 0;
221 
222   // First, try to read remaining data from ssl.
223   result = DoSslRead(ssl, unprotected_bytes, unprotected_bytes_size);
224   if (result != TSI_OK) return result;
225   if (*unprotected_bytes_size == output_bytes_size) {
226     // We have read everything we could and cannot process any more input.
227     *protected_frames_bytes_size = 0;
228     return TSI_OK;
229   }
230   output_bytes_offset = *unprotected_bytes_size;
231   unprotected_bytes += output_bytes_offset;
232   *unprotected_bytes_size = output_bytes_size - output_bytes_offset;
233 
234   // Then, try to write some data to ssl.
235   GPR_ASSERT(*protected_frames_bytes_size <= INT_MAX);
236   written_into_ssl = BIO_write(network_io, protected_frames_bytes,
237                                static_cast<int>(*protected_frames_bytes_size));
238   if (written_into_ssl < 0) {
239     gpr_log(GPR_ERROR, "Sending protected frame to ssl failed with %d",
240             written_into_ssl);
241     return TSI_INTERNAL_ERROR;
242   }
243   *protected_frames_bytes_size = static_cast<size_t>(written_into_ssl);
244 
245   // Now try to read some data again.
246   result = DoSslRead(ssl, unprotected_bytes, unprotected_bytes_size);
247   if (result == TSI_OK) {
248     // Don't forget to output the total number of bytes read.
249     *unprotected_bytes_size += output_bytes_offset;
250   }
251   return result;
252 }
253 
VerifyCrlSignature(X509_CRL * crl,X509 * issuer)254 bool VerifyCrlSignature(X509_CRL* crl, X509* issuer) {
255   if (issuer == nullptr || crl == nullptr) {
256     return false;
257   }
258   EVP_PKEY* ikey = X509_get_pubkey(issuer);
259   if (ikey == nullptr) {
260     // Can't verify signature because we couldn't get the pubkey, fail the
261     // check.
262     gpr_log(GPR_DEBUG, "Could not public key from certificate.");
263     EVP_PKEY_free(ikey);
264     return false;
265   }
266   int ret = X509_CRL_verify(crl, ikey);
267   if (ret < 0) {
268     gpr_log(GPR_DEBUG,
269             "There was an unexpected problem checking the CRL signature.");
270   } else if (ret == 0) {
271     gpr_log(GPR_DEBUG, "CRL failed verification.");
272   }
273   EVP_PKEY_free(ikey);
274   return ret == 1;
275 }
276 
VerifyCrlCertIssuerNamesMatch(X509_CRL * crl,X509 * cert)277 bool VerifyCrlCertIssuerNamesMatch(X509_CRL* crl, X509* cert) {
278   if (cert == nullptr || crl == nullptr) {
279     return false;
280   }
281   X509_NAME* cert_issuer_name = X509_get_issuer_name(cert);
282   if (cert == nullptr) {
283     return false;
284   }
285   X509_NAME* crl_issuer_name = X509_CRL_get_issuer(crl);
286   if (crl_issuer_name == nullptr) {
287     return false;
288   }
289   return X509_NAME_cmp(cert_issuer_name, crl_issuer_name) == 0;
290 }
291 
HasCrlSignBit(X509 * cert)292 bool HasCrlSignBit(X509* cert) {
293   if (cert == nullptr) {
294     return false;
295   }
296   // X509_get_key_usage was introduced in 1.1.1
297   // A missing key usage extension means all key usages are valid.
298 #if OPENSSL_VERSION_NUMBER < 0x10100000
299   // X509_check_ca sets cert->ex_flags. We dont use the return value, but those
300   // flags being set is important.
301   // https://github.com/openssl/openssl/blob/e818b74be2170fbe957a07b0da4401c2b694b3b8/crypto/x509v3/v3_purp.c#L585
302   X509_check_ca(cert);
303   if (!(cert->ex_flags & EXFLAG_KUSAGE)) {
304     return true;
305   }
306   return (cert->ex_kusage & KU_CRL_SIGN) != 0;
307 #else
308   return (X509_get_key_usage(cert) & KU_CRL_SIGN) != 0;
309 #endif  // OPENSSL_VERSION_NUMBER < 0x10100000
310 }
311 
IssuerFromCert(X509 * cert)312 absl::StatusOr<std::string> IssuerFromCert(X509* cert) {
313   if (cert == nullptr) {
314     return absl::InvalidArgumentError("cert cannot be null");
315   }
316   X509_NAME* issuer = X509_get_issuer_name(cert);
317   unsigned char* buf = nullptr;
318   int len = i2d_X509_NAME(issuer, &buf);
319   if (len < 0 || buf == nullptr) {
320     return absl::InvalidArgumentError("could not read issuer name from cert");
321   }
322   std::string ret(reinterpret_cast<char const*>(buf), len);
323   OPENSSL_free(buf);
324   return ret;
325 }
326 
AkidFromCertificate(X509 * cert)327 absl::StatusOr<std::string> AkidFromCertificate(X509* cert) {
328   if (cert == nullptr) {
329     return absl::InvalidArgumentError("cert cannot be null.");
330   }
331   ASN1_OCTET_STRING* akid = nullptr;
332   int j = X509_get_ext_by_NID(cert, NID_authority_key_identifier, -1);
333   // Can't have multiple occurrences
334   if (j >= 0) {
335     if (X509_get_ext_by_NID(cert, NID_authority_key_identifier, j) != -1) {
336       return absl::InvalidArgumentError("Could not get AKID from certificate.");
337     }
338     akid = X509_EXTENSION_get_data(X509_get_ext(cert, j));
339   } else {
340     return absl::InvalidArgumentError("Could not get AKID from certificate.");
341   }
342   unsigned char* buf = nullptr;
343   int len = i2d_ASN1_OCTET_STRING(akid, &buf);
344   if (len <= 0) {
345     return absl::InvalidArgumentError("Could not get AKID from certificate.");
346   }
347   std::string ret(reinterpret_cast<char const*>(buf), len);
348   OPENSSL_free(buf);
349   return ret;
350 }
351 
AkidFromCrl(X509_CRL * crl)352 absl::StatusOr<std::string> AkidFromCrl(X509_CRL* crl) {
353   if (crl == nullptr) {
354     return absl::InvalidArgumentError("Could not get AKID from crl.");
355   }
356   ASN1_OCTET_STRING* akid = nullptr;
357   int j = X509_CRL_get_ext_by_NID(crl, NID_authority_key_identifier, -1);
358   // Can't have multiple occurrences
359   if (j >= 0) {
360     if (X509_CRL_get_ext_by_NID(crl, NID_authority_key_identifier, j) != -1) {
361       return absl::InvalidArgumentError("Could not get AKID from crl.");
362     }
363     akid = X509_EXTENSION_get_data(X509_CRL_get_ext(crl, j));
364   } else {
365     return absl::InvalidArgumentError("Could not get AKID from crl.");
366   }
367   unsigned char* buf = nullptr;
368   int len = i2d_ASN1_OCTET_STRING(akid, &buf);
369   if (len <= 0) {
370     return absl::InvalidArgumentError("Could not get AKID from crl.");
371   }
372   std::string ret(reinterpret_cast<char const*>(buf), len);
373   OPENSSL_free(buf);
374   return ret;
375 }
376 
377 }  // namespace grpc_core
378