• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "src/core/tsi/ssl_transport_security_utils.h"
20 
21 #include <grpc/support/port_platform.h>
22 #include <openssl/bio.h>
23 #include <openssl/crypto.h>
24 #include <openssl/ec.h>
25 #include <openssl/err.h>
26 #include <openssl/evp.h>
27 #include <openssl/pem.h>
28 #include <openssl/rsa.h>
29 #include <openssl/ssl.h>
30 #include <openssl/x509.h>
31 #include <openssl/x509v3.h>
32 
33 #include "absl/log/check.h"
34 #include "absl/log/log.h"
35 #include "absl/status/status.h"
36 #include "absl/status/statusor.h"
37 #include "src/core/tsi/transport_security_interface.h"
38 
39 namespace grpc_core {
40 
SslErrorString(int error)41 const char* SslErrorString(int error) {
42   switch (error) {
43     case SSL_ERROR_NONE:
44       return "SSL_ERROR_NONE";
45     case SSL_ERROR_ZERO_RETURN:
46       return "SSL_ERROR_ZERO_RETURN";
47     case SSL_ERROR_WANT_READ:
48       return "SSL_ERROR_WANT_READ";
49     case SSL_ERROR_WANT_WRITE:
50       return "SSL_ERROR_WANT_WRITE";
51     case SSL_ERROR_WANT_CONNECT:
52       return "SSL_ERROR_WANT_CONNECT";
53     case SSL_ERROR_WANT_ACCEPT:
54       return "SSL_ERROR_WANT_ACCEPT";
55     case SSL_ERROR_WANT_X509_LOOKUP:
56       return "SSL_ERROR_WANT_X509_LOOKUP";
57     case SSL_ERROR_SYSCALL:
58       return "SSL_ERROR_SYSCALL";
59     case SSL_ERROR_SSL:
60       return "SSL_ERROR_SSL";
61     default:
62       return "Unknown error";
63   }
64 }
65 
LogSslErrorStack(void)66 void LogSslErrorStack(void) {
67   unsigned long err;
68   while ((err = ERR_get_error()) != 0) {
69     char details[256];
70     ERR_error_string_n(static_cast<uint32_t>(err), details, sizeof(details));
71     LOG(ERROR) << details;
72   }
73 }
74 
DoSslWrite(SSL * ssl,unsigned char * unprotected_bytes,size_t unprotected_bytes_size)75 tsi_result DoSslWrite(SSL* ssl, unsigned char* unprotected_bytes,
76                       size_t unprotected_bytes_size) {
77   CHECK_LE(unprotected_bytes_size, static_cast<size_t>(INT_MAX));
78   ERR_clear_error();
79   int ssl_write_result = SSL_write(ssl, unprotected_bytes,
80                                    static_cast<int>(unprotected_bytes_size));
81   if (ssl_write_result < 0) {
82     ssl_write_result = SSL_get_error(ssl, ssl_write_result);
83     if (ssl_write_result == SSL_ERROR_WANT_READ) {
84       LOG(ERROR)
85           << "Peer tried to renegotiate SSL connection. This is unsupported.";
86       return TSI_UNIMPLEMENTED;
87     } else {
88       LOG(ERROR) << "SSL_write failed with error "
89                  << SslErrorString(ssl_write_result);
90       return TSI_INTERNAL_ERROR;
91     }
92   }
93   return TSI_OK;
94 }
95 
DoSslRead(SSL * ssl,unsigned char * unprotected_bytes,size_t * unprotected_bytes_size)96 tsi_result DoSslRead(SSL* ssl, unsigned char* unprotected_bytes,
97                      size_t* unprotected_bytes_size) {
98   CHECK_LE(*unprotected_bytes_size, static_cast<size_t>(INT_MAX));
99   ERR_clear_error();
100   int read_from_ssl = SSL_read(ssl, unprotected_bytes,
101                                static_cast<int>(*unprotected_bytes_size));
102   if (read_from_ssl <= 0) {
103     read_from_ssl = SSL_get_error(ssl, read_from_ssl);
104     switch (read_from_ssl) {
105       case SSL_ERROR_ZERO_RETURN:  // Received a close_notify alert.
106       case SSL_ERROR_WANT_READ:    // We need more data to finish the frame.
107         *unprotected_bytes_size = 0;
108         return TSI_OK;
109       case SSL_ERROR_WANT_WRITE:
110         LOG(ERROR)
111             << "Peer tried to renegotiate SSL connection. This is unsupported.";
112         return TSI_UNIMPLEMENTED;
113       case SSL_ERROR_SSL:
114         LOG(ERROR) << "Corruption detected.";
115         LogSslErrorStack();
116         return TSI_DATA_CORRUPTED;
117       default:
118         LOG(ERROR) << "SSL_read failed with error "
119                    << SslErrorString(read_from_ssl);
120         return TSI_PROTOCOL_FAILURE;
121     }
122   }
123   *unprotected_bytes_size = static_cast<size_t>(read_from_ssl);
124   return TSI_OK;
125 }
126 
127 // --- 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)128 tsi_result SslProtectorProtect(const unsigned char* unprotected_bytes,
129                                const size_t buffer_size, size_t& buffer_offset,
130                                unsigned char* buffer, SSL* ssl, BIO* network_io,
131                                size_t* unprotected_bytes_size,
132                                unsigned char* protected_output_frames,
133                                size_t* protected_output_frames_size) {
134   int read_from_ssl;
135   size_t available;
136   tsi_result result = TSI_OK;
137 
138   // First see if we have some pending data in the SSL BIO.
139   int pending_in_ssl = static_cast<int>(BIO_pending(network_io));
140   if (pending_in_ssl > 0) {
141     *unprotected_bytes_size = 0;
142     CHECK_LE(*protected_output_frames_size, static_cast<size_t>(INT_MAX));
143     read_from_ssl = BIO_read(network_io, protected_output_frames,
144                              static_cast<int>(*protected_output_frames_size));
145     if (read_from_ssl < 0) {
146       LOG(ERROR) << "Could not read from BIO even though some data is pending";
147       return TSI_INTERNAL_ERROR;
148     }
149     *protected_output_frames_size = static_cast<size_t>(read_from_ssl);
150     return TSI_OK;
151   }
152 
153   // Now see if we can send a complete frame.
154   available = buffer_size - buffer_offset;
155   if (available > *unprotected_bytes_size) {
156     // If we cannot, just copy the data in our internal buffer.
157     memcpy(buffer + buffer_offset, unprotected_bytes, *unprotected_bytes_size);
158     buffer_offset += *unprotected_bytes_size;
159     *protected_output_frames_size = 0;
160     return TSI_OK;
161   }
162 
163   // If we can, prepare the buffer, send it to SSL_write and read.
164   memcpy(buffer + buffer_offset, unprotected_bytes, available);
165   result = DoSslWrite(ssl, buffer, buffer_size);
166   if (result != TSI_OK) return result;
167 
168   CHECK_LE(*protected_output_frames_size, static_cast<size_t>(INT_MAX));
169   read_from_ssl = BIO_read(network_io, protected_output_frames,
170                            static_cast<int>(*protected_output_frames_size));
171   if (read_from_ssl < 0) {
172     LOG(ERROR) << "Could not read from BIO after SSL_write.";
173     return TSI_INTERNAL_ERROR;
174   }
175   *protected_output_frames_size = static_cast<size_t>(read_from_ssl);
176   *unprotected_bytes_size = available;
177   buffer_offset = 0;
178   return TSI_OK;
179 }
180 
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)181 tsi_result SslProtectorProtectFlush(size_t& buffer_offset,
182                                     unsigned char* buffer, SSL* ssl,
183                                     BIO* network_io,
184                                     unsigned char* protected_output_frames,
185                                     size_t* protected_output_frames_size,
186                                     size_t* still_pending_size) {
187   tsi_result result = TSI_OK;
188   int read_from_ssl = 0;
189   int pending;
190 
191   if (buffer_offset != 0) {
192     result = DoSslWrite(ssl, buffer, buffer_offset);
193     if (result != TSI_OK) return result;
194     buffer_offset = 0;
195   }
196 
197   pending = static_cast<int>(BIO_pending(network_io));
198   CHECK_GE(pending, 0);
199   *still_pending_size = static_cast<size_t>(pending);
200   if (*still_pending_size == 0) return TSI_OK;
201 
202   CHECK_LE(*protected_output_frames_size, static_cast<size_t>(INT_MAX));
203   read_from_ssl = BIO_read(network_io, protected_output_frames,
204                            static_cast<int>(*protected_output_frames_size));
205   if (read_from_ssl <= 0) {
206     LOG(ERROR) << "Could not read from BIO after SSL_write.";
207     return TSI_INTERNAL_ERROR;
208   }
209   *protected_output_frames_size = static_cast<size_t>(read_from_ssl);
210   pending = static_cast<int>(BIO_pending(network_io));
211   CHECK_GE(pending, 0);
212   *still_pending_size = static_cast<size_t>(pending);
213   return TSI_OK;
214 }
215 
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)216 tsi_result SslProtectorUnprotect(const unsigned char* protected_frames_bytes,
217                                  SSL* ssl, BIO* network_io,
218                                  size_t* protected_frames_bytes_size,
219                                  unsigned char* unprotected_bytes,
220                                  size_t* unprotected_bytes_size) {
221   tsi_result result = TSI_OK;
222   int written_into_ssl = 0;
223   size_t output_bytes_size = *unprotected_bytes_size;
224   size_t output_bytes_offset = 0;
225 
226   // First, try to read remaining data from ssl.
227   result = DoSslRead(ssl, unprotected_bytes, unprotected_bytes_size);
228   if (result != TSI_OK) return result;
229   if (*unprotected_bytes_size == output_bytes_size) {
230     // We have read everything we could and cannot process any more input.
231     *protected_frames_bytes_size = 0;
232     return TSI_OK;
233   }
234   output_bytes_offset = *unprotected_bytes_size;
235   unprotected_bytes += output_bytes_offset;
236   *unprotected_bytes_size = output_bytes_size - output_bytes_offset;
237 
238   // Then, try to write some data to ssl.
239   CHECK_LE(*protected_frames_bytes_size, static_cast<size_t>(INT_MAX));
240   written_into_ssl = BIO_write(network_io, protected_frames_bytes,
241                                static_cast<int>(*protected_frames_bytes_size));
242   if (written_into_ssl < 0) {
243     LOG(ERROR) << "Sending protected frame to ssl failed with "
244                << written_into_ssl;
245     return TSI_INTERNAL_ERROR;
246   }
247   *protected_frames_bytes_size = static_cast<size_t>(written_into_ssl);
248 
249   // Now try to read some data again.
250   result = DoSslRead(ssl, unprotected_bytes, unprotected_bytes_size);
251   if (result == TSI_OK) {
252     // Don't forget to output the total number of bytes read.
253     *unprotected_bytes_size += output_bytes_offset;
254   }
255   return result;
256 }
257 
VerifyCrlSignature(X509_CRL * crl,X509 * issuer)258 bool VerifyCrlSignature(X509_CRL* crl, X509* issuer) {
259   if (issuer == nullptr || crl == nullptr) {
260     return false;
261   }
262   EVP_PKEY* ikey = X509_get_pubkey(issuer);
263   if (ikey == nullptr) {
264     // Can't verify signature because we couldn't get the pubkey, fail the
265     // check.
266     VLOG(2) << "Could not get public key from certificate.";
267     EVP_PKEY_free(ikey);
268     return false;
269   }
270   int ret = X509_CRL_verify(crl, ikey);
271   if (ret < 0) {
272     VLOG(2) << "There was an unexpected problem checking the CRL signature.";
273   } else if (ret == 0) {
274     VLOG(2) << "CRL failed verification.";
275   }
276   EVP_PKEY_free(ikey);
277   return ret == 1;
278 }
279 
VerifyCrlCertIssuerNamesMatch(X509_CRL * crl,X509 * cert)280 bool VerifyCrlCertIssuerNamesMatch(X509_CRL* crl, X509* cert) {
281   if (cert == nullptr || crl == nullptr) {
282     return false;
283   }
284   X509_NAME* cert_issuer_name = X509_get_issuer_name(cert);
285   if (cert == nullptr) {
286     return false;
287   }
288   X509_NAME* crl_issuer_name = X509_CRL_get_issuer(crl);
289   if (crl_issuer_name == nullptr) {
290     return false;
291   }
292   return X509_NAME_cmp(cert_issuer_name, crl_issuer_name) == 0;
293 }
294 
HasCrlSignBit(X509 * cert)295 bool HasCrlSignBit(X509* cert) {
296   if (cert == nullptr) {
297     return false;
298   }
299   // X509_get_key_usage was introduced in 1.1.1
300   // A missing key usage extension means all key usages are valid.
301 #if OPENSSL_VERSION_NUMBER < 0x10100000
302   // X509_check_ca sets cert->ex_flags. We dont use the return value, but those
303   // flags being set is important.
304   // https://github.com/openssl/openssl/blob/e818b74be2170fbe957a07b0da4401c2b694b3b8/crypto/x509v3/v3_purp.c#L585
305   X509_check_ca(cert);
306   if (!(cert->ex_flags & EXFLAG_KUSAGE)) {
307     return true;
308   }
309   return (cert->ex_kusage & KU_CRL_SIGN) != 0;
310 #else
311   return (X509_get_key_usage(cert) & KU_CRL_SIGN) != 0;
312 #endif  // OPENSSL_VERSION_NUMBER < 0x10100000
313 }
314 
IssuerFromCert(X509 * cert)315 absl::StatusOr<std::string> IssuerFromCert(X509* cert) {
316   if (cert == nullptr) {
317     return absl::InvalidArgumentError("cert cannot be null");
318   }
319   X509_NAME* issuer = X509_get_issuer_name(cert);
320   unsigned char* buf = nullptr;
321   int len = i2d_X509_NAME(issuer, &buf);
322   if (len < 0 || buf == nullptr) {
323     return absl::InvalidArgumentError("could not read issuer name from cert");
324   }
325   std::string ret(reinterpret_cast<char const*>(buf), len);
326   OPENSSL_free(buf);
327   return ret;
328 }
329 
AkidFromCertificate(X509 * cert)330 absl::StatusOr<std::string> AkidFromCertificate(X509* cert) {
331   if (cert == nullptr) {
332     return absl::InvalidArgumentError("cert cannot be null.");
333   }
334   ASN1_OCTET_STRING* akid = nullptr;
335   int j = X509_get_ext_by_NID(cert, NID_authority_key_identifier, -1);
336   // Can't have multiple occurrences
337   if (j >= 0) {
338     if (X509_get_ext_by_NID(cert, NID_authority_key_identifier, j) != -1) {
339       return absl::InvalidArgumentError("Could not get AKID from certificate.");
340     }
341     akid = X509_EXTENSION_get_data(X509_get_ext(cert, j));
342   } else {
343     return absl::InvalidArgumentError("Could not get AKID from certificate.");
344   }
345   unsigned char* buf = nullptr;
346   int len = i2d_ASN1_OCTET_STRING(akid, &buf);
347   if (len <= 0) {
348     return absl::InvalidArgumentError("Could not get AKID from certificate.");
349   }
350   std::string ret(reinterpret_cast<char const*>(buf), len);
351   OPENSSL_free(buf);
352   return ret;
353 }
354 
AkidFromCrl(X509_CRL * crl)355 absl::StatusOr<std::string> AkidFromCrl(X509_CRL* crl) {
356   if (crl == nullptr) {
357     return absl::InvalidArgumentError("Could not get AKID from crl.");
358   }
359   ASN1_OCTET_STRING* akid = nullptr;
360   int j = X509_CRL_get_ext_by_NID(crl, NID_authority_key_identifier, -1);
361   // Can't have multiple occurrences
362   if (j >= 0) {
363     if (X509_CRL_get_ext_by_NID(crl, NID_authority_key_identifier, j) != -1) {
364       return absl::InvalidArgumentError("Could not get AKID from crl.");
365     }
366     akid = X509_EXTENSION_get_data(X509_CRL_get_ext(crl, j));
367   } else {
368     return absl::InvalidArgumentError("Could not get AKID from crl.");
369   }
370   unsigned char* buf = nullptr;
371   int len = i2d_ASN1_OCTET_STRING(akid, &buf);
372   if (len <= 0) {
373     return absl::InvalidArgumentError("Could not get AKID from crl.");
374   }
375   std::string ret(reinterpret_cast<char const*>(buf), len);
376   OPENSSL_free(buf);
377   return ret;
378 }
379 
ParsePemCertificateChain(absl::string_view cert_chain_pem)380 absl::StatusOr<std::vector<X509*>> ParsePemCertificateChain(
381     absl::string_view cert_chain_pem) {
382   if (cert_chain_pem.empty()) {
383     return absl::InvalidArgumentError("Cert chain PEM is empty.");
384   }
385   BIO* in = BIO_new_mem_buf(cert_chain_pem.data(), cert_chain_pem.size());
386   if (in == nullptr) {
387     return absl::InternalError("BIO_new_mem_buf failed.");
388   }
389   std::vector<X509*> certs;
390   while (X509* cert = PEM_read_bio_X509(in, /*x=*/nullptr, /*cb=*/nullptr,
391                                         /*u=*/nullptr)) {
392     certs.push_back(cert);
393   }
394 
395   // We always have errors at this point because in the above loop we read until
396   // we reach the end of |cert_chain_pem|, which generates a "no start line"
397   // error. Therefore, this error is OK if we have successfully parsed some
398   // certificate data previously.
399   const int last_error = ERR_peek_last_error();
400   if (ERR_GET_LIB(last_error) != ERR_LIB_PEM ||
401       ERR_GET_REASON(last_error) != PEM_R_NO_START_LINE) {
402     for (X509* cert : certs) {
403       X509_free(cert);
404     }
405     BIO_free(in);
406     return absl::FailedPreconditionError("Invalid PEM.");
407   }
408   ERR_clear_error();
409   BIO_free(in);
410   if (certs.empty()) {
411     return absl::NotFoundError("No certificates found.");
412   }
413   return certs;
414 }
415 
ParsePemPrivateKey(absl::string_view private_key_pem)416 absl::StatusOr<EVP_PKEY*> ParsePemPrivateKey(
417     absl::string_view private_key_pem) {
418   BIO* in = BIO_new_mem_buf(private_key_pem.data(), private_key_pem.size());
419   if (in == nullptr) {
420     return absl::InvalidArgumentError("Private key PEM is empty.");
421   }
422   EVP_PKEY* pkey =
423       PEM_read_bio_PrivateKey(in, /*x=*/nullptr, /*cb=*/nullptr, /*u=*/nullptr);
424   BIO_free(in);
425   if (pkey == nullptr) {
426     return absl::NotFoundError("No private key found.");
427   }
428   return pkey;
429 }
430 
431 }  // namespace grpc_core
432