| 
									
										
										
										
											2018-12-15 00:17:22 +08:00
										 |  |  | =pod | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | =head1 NAME | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-13 06:35:45 +08:00
										 |  |  | OSSL_trace_enabled, OSSL_trace_begin, OSSL_trace_end, | 
					
						
							| 
									
										
										
										
											2019-06-24 01:25:50 +08:00
										 |  |  | OSSL_TRACE_BEGIN, OSSL_TRACE_END, OSSL_TRACE_CANCEL, | 
					
						
							|  |  |  | OSSL_TRACE, OSSL_TRACE1, OSSL_TRACE2, OSSL_TRACE3, OSSL_TRACE4, | 
					
						
							|  |  |  | OSSL_TRACE5, OSSL_TRACE6, OSSL_TRACE7, OSSL_TRACE8, OSSL_TRACE9, | 
					
						
							|  |  |  | OSSL_TRACEV, | 
					
						
							|  |  |  | OSSL_TRACE_ENABLED | 
					
						
							| 
									
										
										
										
											2018-12-15 00:17:22 +08:00
										 |  |  | - OpenSSL Tracing API | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | =head1 SYNOPSIS | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-29 23:10:59 +08:00
										 |  |  | =for openssl generic | 
					
						
							| 
									
										
										
										
											2019-06-24 01:25:50 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-15 00:17:22 +08:00
										 |  |  |  #include <openssl/trace.h> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |  int OSSL_trace_enabled(int category); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |  BIO *OSSL_trace_begin(int category); | 
					
						
							|  |  |  |  void OSSL_trace_end(int category, BIO *channel); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-13 06:35:45 +08:00
										 |  |  |  /* trace group macros */ | 
					
						
							|  |  |  |  OSSL_TRACE_BEGIN(category) { | 
					
						
							| 
									
										
										
										
											2019-06-24 01:25:50 +08:00
										 |  |  |      ... | 
					
						
							|  |  |  |      if (some_error) { | 
					
						
							|  |  |  |          /* Leave trace group prematurely in case of an error */ | 
					
						
							|  |  |  |          OSSL_TRACE_CANCEL(category); | 
					
						
							|  |  |  |          goto err; | 
					
						
							|  |  |  |      } | 
					
						
							|  |  |  |      ... | 
					
						
							| 
									
										
										
										
											2019-03-13 06:35:45 +08:00
										 |  |  |  } OSSL_TRACE_END(category); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |  /* one-shot trace macros */ | 
					
						
							|  |  |  |  OSSL_TRACE1(category, format, arg1) | 
					
						
							|  |  |  |  OSSL_TRACE2(category, format, arg1, arg2) | 
					
						
							|  |  |  |  ... | 
					
						
							|  |  |  |  OSSL_TRACE9(category, format, arg1, ..., arg9) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-24 01:25:50 +08:00
										 |  |  |  /* check whether a trace category is enabled */ | 
					
						
							|  |  |  |  if (OSSL_TRACE_ENABLED(category)) { | 
					
						
							|  |  |  |      ... | 
					
						
							|  |  |  |  } | 
					
						
							| 
									
										
										
										
											2019-03-13 06:35:45 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-15 00:17:22 +08:00
										 |  |  | =head1 DESCRIPTION | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The functions described here are mainly interesting for those who provide | 
					
						
							|  |  |  | OpenSSL functionality, either in OpenSSL itself or in engine modules | 
					
						
							|  |  |  | or similar. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-14 06:16:29 +08:00
										 |  |  | If tracing is enabled (see L</NOTES> below), these functions are used to | 
					
						
							| 
									
										
										
										
											2018-12-15 00:17:22 +08:00
										 |  |  | generate free text tracing output. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The tracing output is divided into types which are enabled | 
					
						
							|  |  |  | individually by the application. | 
					
						
							|  |  |  | The tracing types are described in detail in | 
					
						
							|  |  |  | L<OSSL_trace_set_callback(3)/Trace types>. | 
					
						
							| 
									
										
										
										
											2019-03-22 01:59:13 +08:00
										 |  |  | The fallback type C<OSSL_TRACE_CATEGORY_ALL> should I<not> be used | 
					
						
							| 
									
										
										
										
											2018-12-15 00:17:22 +08:00
										 |  |  | with the functions described here. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-13 06:35:45 +08:00
										 |  |  | Tracing for a specific category is enabled if a so called | 
					
						
							|  |  |  | I<trace channel> is attached to it. A trace channel is simply a | 
					
						
							|  |  |  | BIO object to which the application can write its trace output. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The application has two different ways of registering a trace channel, | 
					
						
							|  |  |  | either by directly providing a BIO object using OSSL_trace_set_channel(), | 
					
						
							|  |  |  | or by providing a callback routine using OSSL_trace_set_callback(). | 
					
						
							|  |  |  | The latter is wrapped internally by a dedicated BIO object, so for the | 
					
						
							|  |  |  | tracing code both channel types are effectively indistinguishable. | 
					
						
							|  |  |  | We call them a I<simple trace channel> and a I<callback trace channel>, | 
					
						
							|  |  |  | respectively. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | To produce trace output, it is necessary to obtain a pointer to the | 
					
						
							|  |  |  | trace channel (i.e., the BIO object) using OSSL_trace_begin(), write | 
					
						
							|  |  |  | to it using arbitrary BIO output routines, and finally releases the | 
					
						
							|  |  |  | channel using OSSL_trace_end(). The OSSL_trace_begin()/OSSL_trace_end() | 
					
						
							|  |  |  | calls surrounding the trace output create a group, which acts as a | 
					
						
							|  |  |  | critical section (guarded by a mutex) to ensure that the trace output | 
					
						
							|  |  |  | of different threads does not get mixed up. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The tracing code normally does not call OSSL_trace_{begin,end}() directly, | 
					
						
							|  |  |  | but rather uses a set of convenience macros, see the L</Macros> section below. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-15 00:17:22 +08:00
										 |  |  | =head2 Functions | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | OSSL_trace_enabled() can be used to check if tracing for the given | 
					
						
							|  |  |  | C<category> is enabled. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | OSSL_trace_begin() is used to starts a tracing section, and get the | 
					
						
							|  |  |  | channel for the given C<category> in form of a BIO. | 
					
						
							|  |  |  | This BIO can only be used for output. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | OSSL_trace_end() is used to end a tracing section. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Using OSSL_trace_begin() and OSSL_trace_end() to wrap tracing sections | 
					
						
							|  |  |  | is I<mandatory>. | 
					
						
							|  |  |  | The result of trying to produce tracing output outside of such | 
					
						
							|  |  |  | sections is undefined. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-13 06:35:45 +08:00
										 |  |  | =head2 Macros | 
					
						
							| 
									
										
										
										
											2018-12-15 00:17:22 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | There are a number of convenience macros defined, to make tracing | 
					
						
							|  |  |  | easy and consistent. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | C<OSSL_TRACE_BEGIN(category)> and C<OSSL_TRACE_END(category)> reserve | 
					
						
							|  |  |  | the B<BIO> C<trc_out> and are used as follows to wrap a trace section: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |  OSSL_TRACE_BEGIN(TLS) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |      BIO_fprintf(trc_out, ... ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |  } OSSL_TRACE_END(TLS); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-13 06:35:45 +08:00
										 |  |  | This will normally expand to: | 
					
						
							| 
									
										
										
										
											2018-12-15 00:17:22 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |  do { | 
					
						
							|  |  |  |      BIO *trc_out = OSSL_trace_begin(OSSL_TRACE_CATEGORY_TLS); | 
					
						
							|  |  |  |      if (trc_out != NULL) { | 
					
						
							|  |  |  |          ... | 
					
						
							|  |  |  |          BIO_fprintf(trc_out, ...); | 
					
						
							|  |  |  |      } | 
					
						
							|  |  |  |      OSSL_trace_end(OSSL_TRACE_CATEGORY_TLS, trc_out); | 
					
						
							|  |  |  |  } while (0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | C<OSSL_TRACE_CANCEL(category)> must be used before returning from or | 
					
						
							|  |  |  | jumping out of a trace section: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |  OSSL_TRACE_BEGIN(TLS) { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-24 01:25:50 +08:00
										 |  |  |      if (some_error) { | 
					
						
							| 
									
										
										
										
											2018-12-15 00:17:22 +08:00
										 |  |  |          OSSL_TRACE_CANCEL(TLS); | 
					
						
							|  |  |  |          goto err; | 
					
						
							|  |  |  |      } | 
					
						
							|  |  |  |      BIO_fprintf(trc_out, ... ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |  } OSSL_TRACE_END(TLS); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | This will normally expand to: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |  do { | 
					
						
							|  |  |  |      BIO *trc_out = OSSL_trace_begin(OSSL_TRACE_CATEGORY_TLS); | 
					
						
							|  |  |  |      if (trc_out != NULL) { | 
					
						
							| 
									
										
										
										
											2019-06-24 01:25:50 +08:00
										 |  |  |          if (some_error) { | 
					
						
							| 
									
										
										
										
											2018-12-15 00:17:22 +08:00
										 |  |  |              OSSL_trace_end(OSSL_TRACE_CATEGORY_TLS, trc_out); | 
					
						
							|  |  |  |              goto err; | 
					
						
							|  |  |  |          } | 
					
						
							|  |  |  |          BIO_fprintf(trc_out, ... ); | 
					
						
							|  |  |  |      } | 
					
						
							|  |  |  |      OSSL_trace_end(OSSL_TRACE_CATEGORY_TLS, trc_out); | 
					
						
							|  |  |  |  } while (0); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-13 06:35:45 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-24 01:25:50 +08:00
										 |  |  | C<OSSL_TRACE()> and C<OSSL_TRACE1()>, C<OSSL_TRACE2()>, ... C<OSSL_TRACE9()> are | 
					
						
							|  |  |  | so-called one-shot macros: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The macro call C<OSSL_TRACE(category, text)>, produces literal text trace output. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The macro call C<OSSL_TRACEn(category, format, arg1, ..., argn)> produces | 
					
						
							|  |  |  | printf-style trace output with n format field arguments (n=1,...,9). | 
					
						
							|  |  |  | It expands to: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |  OSSL_TRACE_BEGIN(category) { | 
					
						
							|  |  |  |      BIO_printf(trc_out, format, arg1, ..., argN) | 
					
						
							|  |  |  |  } OSSL_TRACE_END(category) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Internally, all one-shot macros are implemented using a generic C<OSSL_TRACEV()> | 
					
						
							|  |  |  | macro, since C90 does not support variadic macros. This helper macro has a rather | 
					
						
							|  |  |  | weird synopsis and should not be used directly. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The C<OSSL_TRACE_ENABLED(category)> macro can be used to conditionally execute | 
					
						
							|  |  |  | some code only if a specific trace category is enabled. | 
					
						
							|  |  |  | In some situations this is simpler than entering a trace section using | 
					
						
							|  |  |  | C<OSSL_TRACE_BEGIN(category)> and C<OSSL_TRACE_END(category)>. | 
					
						
							|  |  |  | For example, the code | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |  if (OSSL_TRACE_ENABLED(TLS)) { | 
					
						
							|  |  |  |      ... | 
					
						
							|  |  |  |  } | 
					
						
							| 
									
										
										
										
											2019-03-13 06:35:45 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-24 01:25:50 +08:00
										 |  |  | expands to | 
					
						
							| 
									
										
										
										
											2019-03-13 06:35:45 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-24 01:25:50 +08:00
										 |  |  |  if (OSSL_trace_enabled(OSSL_TRACE_CATEGORY_TLS) { | 
					
						
							|  |  |  |      ... | 
					
						
							|  |  |  |  } | 
					
						
							| 
									
										
										
										
											2019-03-13 06:35:45 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-15 00:17:22 +08:00
										 |  |  | =head1 NOTES | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-24 01:25:50 +08:00
										 |  |  | If producing the trace output requires carrying out auxiliary calculations, | 
					
						
							|  |  |  | this auxiliary code should be placed inside a conditional block which is | 
					
						
							|  |  |  | executed only if the trace category is enabled. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The most natural way to do this is to place the code inside the trace section | 
					
						
							|  |  |  | itself because it already introduces such a conditional block. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |  OSSL_TRACE_BEGIN(TLS) { | 
					
						
							|  |  |  |      int var = do_some_auxiliary_calculation(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |      BIO_printf(trc_out, "var = %d\n", var); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |  } OSSL_TRACE_END(TLS); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | In some cases it is more advantageous to use a simple conditional group instead | 
					
						
							|  |  |  | of a trace section. This is the case if calculations and tracing happen in | 
					
						
							|  |  |  | different locations of the code, or if the calculations are so time consuming | 
					
						
							|  |  |  | that placing them inside a (critical) trace section would create too much | 
					
						
							|  |  |  | contention. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |  if (OSSL_TRACE_ENABLED(TLS)) { | 
					
						
							|  |  |  |      int var = do_some_auxiliary_calculation(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |      OSSL_TRACE1("var = %d\n", var); | 
					
						
							|  |  |  |  } | 
					
						
							| 
									
										
										
										
											2018-12-15 00:17:22 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-24 01:25:50 +08:00
										 |  |  | Note however that premature optimization of tracing code is in general futile | 
					
						
							|  |  |  | and it's better to keep the tracing code as simple as possible. | 
					
						
							|  |  |  | Because most often the limiting factor for the application's speed is the time | 
					
						
							|  |  |  | it takes to print the trace output, not to calculate it. | 
					
						
							| 
									
										
										
										
											2018-12-15 00:17:22 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-14 06:16:29 +08:00
										 |  |  | =head2 Configure Tracing | 
					
						
							| 
									
										
										
										
											2018-12-15 00:17:22 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-14 06:16:29 +08:00
										 |  |  | By default, the OpenSSL library is built with tracing disabled. To | 
					
						
							|  |  |  | use the tracing functionality documented here, it is therefore | 
					
						
							|  |  |  | necessary to configure and build OpenSSL with the 'enable-trace' option. | 
					
						
							| 
									
										
										
										
											2018-12-15 00:17:22 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | When the library is built with tracing disabled: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | =over 4 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | =item * | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The macro C<OPENSSL_NO_TRACE> is defined in C<openssl/opensslconf.h>. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | =item * | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | all functions are still present, bu OSSL_trace_enabled() will always | 
					
						
							|  |  |  | report the categories as disabled, and all other functions will do | 
					
						
							|  |  |  | nothing. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | =item * | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | the convenience macros are defined to produce dead code. | 
					
						
							| 
									
										
										
										
											2019-03-13 06:35:45 +08:00
										 |  |  | For example, take this example from L</Macros> section above: | 
					
						
							| 
									
										
										
										
											2018-12-15 00:17:22 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |  OSSL_TRACE_BEGIN(TLS) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |      if (condition) { | 
					
						
							|  |  |  |          OSSL_TRACE_CANCEL(TLS); | 
					
						
							|  |  |  |          goto err; | 
					
						
							|  |  |  |      } | 
					
						
							|  |  |  |      BIO_fprintf(trc_out, ... ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |  } OSSL_TRACE_END(TLS); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | When the tracing API isn't operational, that will expand to: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |  do { | 
					
						
							|  |  |  |      BIO *trc_out = NULL; | 
					
						
							|  |  |  |      if (0) { | 
					
						
							|  |  |  |          if (condition) { | 
					
						
							|  |  |  |              ((void)0); | 
					
						
							|  |  |  |              goto err; | 
					
						
							|  |  |  |          } | 
					
						
							|  |  |  |          BIO_fprintf(trc_out, ... ); | 
					
						
							|  |  |  |      } | 
					
						
							|  |  |  |  } while (0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | =back | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | =head1 RETURN VALUES | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | OSSL_trace_enabled() returns 1 if tracing for the given B<type> is | 
					
						
							|  |  |  | operational and enabled, otherwise 0. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | OSSL_trace_begin() returns a C<BIO *> if the given B<type> is enabled, | 
					
						
							|  |  |  | otherwise C<NULL>. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | =head1 HISTORY | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-15 21:03:44 +08:00
										 |  |  | The OpenSSL Tracing API was added ino OpenSSL 3.0. | 
					
						
							| 
									
										
										
										
											2018-12-15 00:17:22 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | =head1 COPYRIGHT | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Copyright 2019 The OpenSSL Project Authors. All Rights Reserved. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Licensed under the Apache License 2.0 (the "License").  You may not use | 
					
						
							|  |  |  | this file except in compliance with the License.  You can obtain a copy | 
					
						
							|  |  |  | in the file LICENSE in the source distribution or at | 
					
						
							|  |  |  | L<https://www.openssl.org/source/license.html>. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | =cut |