Commit 1ee45458fc76043ffafb1f7c730e1376a012bdf4

Authored by Jay Berkenbilt
1 parent 70b8c41f

Update docs for crypto providers

ChangeLog
  1 +2019-11-05 Jay Berkenbilt <ejb@ql.org>
  2 +
  3 + * Add support for pluggable crypto providers, enabling multiple
  4 + implementations of the cryptographic functions needed by qpdf.
  5 + This feature was added by request of Red Hat, which recognized the
  6 + use of qpdf's native crypto implementations as a potential
  7 + security liability, preferring instead to get all crypto
  8 + functionality from a third-party library that receives a lot of
  9 + scrutiny. However it was also important to me to not impose any
  10 + unnecessary third party depdendencies on my users or packagers,
  11 + some of which build qpdf for lots of environments, some of which
  12 + may not easily support gnutls. Starting in qpdf 9.1.0, it is be
  13 + possible to build qpdf with both the native and gnutls crypto
  14 + providers or with either in isolation. In support of this feature,
  15 + new classes QPDFCryptoProvider and QPDFCryptoImpl have been added
  16 + to the public interface. See QPDFCryptoImpl.hh for details about
  17 + adding your own crypto provider and QPDFCryptoProvider.hh for
  18 + details about choosing which one is used. Note that selection of
  19 + crypto providers is invisible to anyone who doesn't explicitly
  20 + care. Neither end users nor developers have to be concerned about
  21 + it.
  22 +
  23 + * The environment variable QPDF_CRYPTO_PROVIDER can be used to
  24 + override qpdf's default choice of crypto provider. The
  25 + --show-crypto flag to the qpdf CLI can be used to present a list
  26 + of supported crypto providers with the default provider always
  27 + listed first.
  28 +
  29 + * Add gnutls crypto provider. Thanks to Zdenek Dohnal for
  30 + contributing the code that I ultimately used in the gnutls crypto
  31 + provider and for engaging in an extended discussion about this
  32 + feature. Fixes #218.
  33 +
1 2019-10-22 Jay Berkenbilt <ejb@ql.org> 34 2019-10-22 Jay Berkenbilt <ejb@ql.org>
2 35
3 * Incorporate changes from Masamichi Hosoda <trueroad@trueroad.jp> 36 * Incorporate changes from Masamichi Hosoda <trueroad@trueroad.jp>
README.md
@@ -31,12 +31,33 @@ QPDF requires a C++ compiler that supports C++-11. @@ -31,12 +31,33 @@ QPDF requires a C++ compiler that supports C++-11.
31 31
32 QPDF depends on the external libraries [zlib](http://www.zlib.net/) and [jpeg](http://www.ijg.org/files/). The [libjpeg-turbo](https://libjpeg-turbo.org/) library is also known to work since it is compatible with the regular jpeg library, and QPDF doesn't use any interfaces that aren't present in the straight jpeg8 API. These are part of every Linux distribution and are readily available. Download information appears in the documentation. For Windows, you can download pre-built binary versions of these libraries for some compilers; see [README-windows.md](README-windows.md) for additional details. 32 QPDF depends on the external libraries [zlib](http://www.zlib.net/) and [jpeg](http://www.ijg.org/files/). The [libjpeg-turbo](https://libjpeg-turbo.org/) library is also known to work since it is compatible with the regular jpeg library, and QPDF doesn't use any interfaces that aren't present in the straight jpeg8 API. These are part of every Linux distribution and are readily available. Download information appears in the documentation. For Windows, you can download pre-built binary versions of these libraries for some compilers; see [README-windows.md](README-windows.md) for additional details.
33 33
  34 +If the optional gnutls crypto provider is enabled, then gnutls is also required. This is discussed more in `Crypto providers` below.
  35 +
34 # Licensing terms of embedded software 36 # Licensing terms of embedded software
35 37
36 -QPDF makes use of zlib and jpeg libraries for its functionality. These packages can be downloaded separately from their own download locations, or they can be downloaded in the external-libs area of the qpdf download site. 38 +QPDF makes use of zlib and jpeg libraries for its functionality. These packages can be downloaded separately from their own download locations, or they can be downloaded in the external-libs area of the qpdf download site. If the optional gnutls crypto provider is enabled, then gnutls is also required.
37 39
38 Please see the [NOTICE](NOTICE.md) file for information on licenses of embedded software. 40 Please see the [NOTICE](NOTICE.md) file for information on licenses of embedded software.
39 41
  42 +# Crypto providers
  43 +
  44 +As of version 9.1.0, qpdf can use different crypto implementations. These can be selected at compile time or at runtime. The native crypto implementations that were used in all versions prior to 9.1.0 are still present and enabled by default.
  45 +
  46 +Initially, the following providers are available:
  47 +* `native`: a native implementation where all the source is embedded in qpdf and no external dependencies are required
  48 +* `gnutls`: an implementation that uses the gnutls library to provide cyrpto; causes libqpdf to link with the gnutls library
  49 +
  50 +The default behavior is for ./configure to discover which other crypto providers can be supported based on available external libraries, to build all available crypto providers, and to use an external provider as the default over the native one. This behavior can be changed with the following flags to ./configure:
  51 +
  52 +* `--enable-crypto-x` -- (where `x` is a supported crypto provider): enable the `x` crypto provider, requiring any external dependencies it needs
  53 +* `--disable-crypto-x` -- disable the `x` provider, and do not link against its dependencies even if they are available
  54 +* `--with-default-crypto=x` -- make `x` the default provider even if a higher priority one is available
  55 +* `--disable-implicit-crypto` -- only build crypto providers that are explicitly requested with an `--enable-crypto-x` option
  56 +
  57 +For example, if you want to guarantee that the gnutls crypto provider is used, you could run ./configure with `--enable-crypto-gnutls --disable-implicit-crypto`.
  58 +
  59 +Please see the section on cyrpto providers in the manual for more details.
  60 +
40 # Building from a pristine checkout 61 # Building from a pristine checkout
41 62
42 When building qpdf from a pristine checkout from version control, generated documentation files are not present. You may either generate them (by passing `--enable-doc-maintenance` to `./configure` and satisfying the extra build-time dependencies) or obtain them from a released source package, which includes them. If you want to grab just the files that are in the source distribution but not in the repository, extract a source distribution in a temporary directory, and run `make CLEAN=1 distfiles.zip`. This will create a file called `distfiles.zip`, which can you can extract in a checkout of the source repository. This step is optional unless you are running make install and want the html and PDF versions of the documentation to be installed. 63 When building qpdf from a pristine checkout from version control, generated documentation files are not present. You may either generate them (by passing `--enable-doc-maintenance` to `./configure` and satisfying the extra build-time dependencies) or obtain them from a released source package, which includes them. If you want to grab just the files that are in the source distribution but not in the repository, extract a source distribution in a temporary directory, and run `make CLEAN=1 distfiles.zip`. This will create a file called `distfiles.zip`, which can you can extract in a checkout of the source repository. This step is optional unless you are running make install and want the html and PDF versions of the documentation to be installed.
@@ -59,7 +80,7 @@ QPDF is known to build and pass its test suite with mingw (latest version tested @@ -59,7 +80,7 @@ QPDF is known to build and pass its test suite with mingw (latest version tested
59 80
60 # Additional Notes on Build 81 # Additional Notes on Build
61 82
62 -QPDF's build system, inspired by [abuild](http://www.abuild.org), can optionally use its own built-in rules rather than using libtool and obeying the compiler specified with configure. This can be enabled by passing `--with-buildrules=buildrules` where buildrules corresponds to one of the `.mk` files (other than `rules.mk`) in the make directory. This should never be necessary on a UNIX system, but may be necessary on a Windows system. See [README-windows.md](README-windows.md) for details. 83 +QPDF's build system, inspired by [abuild](http://www.qbilt.org/abuild), can optionally use its own built-in rules rather than using libtool and obeying the compiler specified with configure. This can be enabled by passing `--with-buildrules=buildrules` where buildrules corresponds to one of the `.mk` files (other than `rules.mk`) in the make directory. This should never be necessary on a UNIX system, but may be necessary on a Windows system. See [README-windows.md](README-windows.md) for details.
63 84
64 The QPDF package provides some executables and a software library. A user manual can be found in the "doc" directory. The docbook sources to the user manual can be found in the `manual` directory. 85 The QPDF package provides some executables and a software library. A user manual can be found in the "doc" directory. The docbook sources to the user manual can be found in the `manual` directory.
65 86
@@ -272,10 +272,13 @@ I find it useful to make reference to them in this list @@ -272,10 +272,13 @@ I find it useful to make reference to them in this list
272 to add any dependencies on threading libraries. 272 to add any dependencies on threading libraries.
273 273
274 * Study what's required to support savable forms that can be saved by 274 * Study what's required to support savable forms that can be saved by
275 - Adobe Reader. Does this require actually signing the document with  
276 - an Adobe private key? Search for "Digital signatures" in the PDF 275 + Adobe Reader. Does this require actually signing the document with
  276 + an Adobe private key? Search for "Digital signatures" in the PDF
277 spec, and look at ~/Q/pdf-collection/form-with-full-save.pdf, which 277 spec, and look at ~/Q/pdf-collection/form-with-full-save.pdf, which
278 - came from Adobe's example site. 278 + came from Adobe's example site. See also
  279 + ../misc/digital-sign-from-trueroad/. If digital signatures are
  280 + implemented, update the docs on crytpo providers, which mention
  281 + that this may happen in the future.
279 282
280 * See if we can avoid preserving unreferenced objects in object 283 * See if we can avoid preserving unreferenced objects in object
281 streams even when preserving the object streams. 284 streams even when preserving the object streams.
manual/qpdf-manual.xml
@@ -242,6 +242,224 @@ make @@ -242,6 +242,224 @@ make
242 top-level <filename>Makefile</filename>. 242 top-level <filename>Makefile</filename>.
243 </para> 243 </para>
244 </sect1> 244 </sect1>
  245 + <sect1 id="ref.crypto">
  246 + <title>Crypto Providers</title>
  247 + <para>
  248 + Starting with qpdf 9.1.0, the qpdf library can be built with
  249 + multiple implementations of providers of cryptographic functions,
  250 + which we refer to as &ldquo;crypto providers.&rdquo; At the time
  251 + of writing, a crypto implementation must provide MD5 and SHA2
  252 + (256, 384, and 512-bit) hashes and RC4 and AES256 with and without
  253 + CBC encryption. In the future, if digital signature is added to
  254 + qpdf, there may be additional requirements beyond this.
  255 + </para>
  256 + <para>
  257 + Starting with qpdf version 9.1.0, the available implementations
  258 + are <literal>native</literal> and <literal>gnutls</literal>.
  259 + Additional implementations may be added if needed. It is also
  260 + possible for a developer to provide their own implementation
  261 + without modifying the qpdf library.
  262 + </para>
  263 + <sect2 id="ref.crypto.build">
  264 + <title>Build Support For Cyrpto Providers</title>
  265 + <para>
  266 + When building with qpdf's build system, crypto providers can be
  267 + enabled at build time using various
  268 + <command>./configure</command> options. The default behavior is
  269 + for <command>./configure</command> to discover which crypto
  270 + providers can be supported based on available external libraries,
  271 + to build all available crypto providers, and to use an external
  272 + provider as the default over the native one. This behavior can be
  273 + changed with the following flags to
  274 + <command>./configure</command>:
  275 + <itemizedlist>
  276 + <listitem>
  277 + <para>
  278 + <option>--enable-crypto-<replaceable>x</replaceable></option>
  279 + (where <replaceable>x</replaceable> is a supported crypto
  280 + provider): enable the <replaceable>x</replaceable> crypto
  281 + provider, requiring any external dependencies it needs
  282 + </para>
  283 + </listitem>
  284 + <listitem>
  285 + <para>
  286 + <option>--disable-crypto-<replaceable>x</replaceable></option>:
  287 + disable the <replaceable>x</replaceable> provider, and do not
  288 + link against its dependencies even if they are available
  289 + </para>
  290 + </listitem>
  291 + <listitem>
  292 + <para>
  293 + <option>--with-default-crypto=<replaceable>x</replaceable></option>:
  294 + make <replaceable>x</replaceable> the default provider even if
  295 + a higher priority one is available
  296 + </para>
  297 + </listitem>
  298 + <listitem>
  299 + <para>
  300 + <option>--disable-implicit-crypto</option>: only build crypto
  301 + providers that are explicitly requested with an
  302 + <option>--enable-crypto-<replaceable>x</replaceable></option>
  303 + option
  304 + </para>
  305 + </listitem>
  306 + </itemizedlist>
  307 + </para>
  308 + <para>
  309 + For example, if you want to guarantee that the gnutls crypto
  310 + provider is used and that the native provider is not built, you
  311 + could run <command>./configure --enable-crypto-gnutls
  312 + --disable-implicit-crypto</command>.
  313 + </para>
  314 + <para>
  315 + If you build qpdf using your own build system, in order for qpdf
  316 + to work at all, you need to enable at least one crypto provider.
  317 + The file <filename>include/qpdf/qpdf-config.h.in</filename>
  318 + provides macros <literal>DEFAULT_CRYPTO</literal>, whose value
  319 + must be a string naming the default crypto provider, and various
  320 + symbols starting with <literal>USE_CRYPTO_</literal>, at least
  321 + one of which has to be enabled. Additionally, you must compile
  322 + the source files that implement a crypto provider. To get a list
  323 + of those files, look at <filename>libqpdf/build.mk</filename>. If
  324 + you want to omit a particular crypto provider, as long as its
  325 + <literal>USE_CRYPTO_</literal> symbol is undefined, you can
  326 + completely ignore the source files that belong to a particular
  327 + crypto provider. Additionally, crypto providers may have their
  328 + own external dependencies that can be omitted if the crypto
  329 + provider is not used. For example, if you are building qpdf
  330 + yourself and are using an environment that does not support
  331 + gnutls, you can ensure that <literal>USE_CRYPTO_NATIVE</literal>
  332 + is defined, <literal>USE_CRYPTO_GNUTLS</literal> is not defined,
  333 + and <literal>DEFAULT_CRYPTO</literal> is defined to
  334 + <literal>"native"</literal>. Then you must include the source
  335 + files used in the native implementation, some of which were added
  336 + or renamed from earlier versions, to your build, and you can
  337 + ignore <filename>QPDFCrypto_gnutls.cc</filename>. Always consult
  338 + <filename>libqpdf/build.mk</filename> to get the list of source
  339 + files you need to build.
  340 + </para>
  341 + </sect2>
  342 + <sect2 id="ref.crypto.runtime">
  343 + <title>Runtime Cryto Provider Selection</title>
  344 + <para>
  345 + You can use the <option>--show-crypto</option> option to
  346 + <command>qpdf</command> to get a list of available crypto
  347 + providers. The default provider is always listed first, and the
  348 + rest are listed in lexical order. Each crypto provider is listed
  349 + on a line by itself with no other text, enabling the output of
  350 + this command to be used easily in scripts.
  351 + </para>
  352 + <para>
  353 + You can override which crypto provider is used by setting the
  354 + <literal>QPDF_CRYPTO_PROVIDER</literal> environment variable.
  355 + There are few reasons to ever do this, but you might want to do
  356 + it if you were explicitly trying to compare behavior of two
  357 + different crypto providers while testing performance or
  358 + reproducing a bug. It could also be useful for people who are
  359 + implementing their own crypto providers.
  360 + </para>
  361 + </sect2>
  362 + <sect2 id="ref.crypto.develop">
  363 + <title>Cryto Provider Information for Developers</title>
  364 + <para>
  365 + If you are writing code that uses libqpdf and you want to force a
  366 + certain crypto provider to be used, you can call the method
  367 + <function>QPDFCryptoProvider::setDefaultProvider</function>. The
  368 + argument is the name of a built-in or developer-supplied
  369 + provider. To add your own crypto provider, you have to create a
  370 + class derived from <classname>QPDFCryptoImpl</classname> and
  371 + register it with <classname>QPDFCryptoProvider</classname>. For
  372 + additional information, see comments in
  373 + <filename>include/qpdf/QPDFCryptoImpl.hh</filename>.
  374 + </para>
  375 + </sect2>
  376 + <sect2 id="ref.crypto.design">
  377 + <title>Crypto Provider Design Notes</title>
  378 + <para>
  379 + This section describes a few bits of rationale for why the crypto
  380 + provider interface was set up the way it was. You don't need to
  381 + know any of this information, but it's provided for the record
  382 + and in case it's interesting.
  383 + </para>
  384 + <para>
  385 + As a general rule, I want to avoid as much as possible including
  386 + large blocks of code that are conditionally compiled such that,
  387 + in most builds, some code is never built. This is dangerous
  388 + because it makes it very easy for invalid code to creep in
  389 + unnoticed. As such, I want it to be possible to build qpdf with
  390 + all available crypto providers, and this is the way I build qpdf
  391 + for local development. At the same time, if a particular packager
  392 + feels that it is a security liability for qpdf to use crypto
  393 + functionality from other than a library that gets considerable
  394 + scrutiny for this specific purpose (such as gnutls, openssl, or
  395 + nettle), then I want to give that packager the ability to
  396 + completely disable qpdf's native implementation. Or if someone
  397 + wants to avoid adding a dependency on one of the external crypto
  398 + providers, I don't want the availability of the provider to
  399 + impose additional external dependencies within that environment.
  400 + Both of these are situations that I know to be true for some
  401 + users of qpdf.
  402 + </para>
  403 + <para>
  404 + I want registration and selection of crypto providers to be
  405 + thread-safe, and I want it to work deterministically for a
  406 + developer to provide their own crypto provider and be able to set
  407 + it up as the default. This was the primary motivation behind
  408 + requiring C++-11 as doing so enabled me to exploit the guaranteed
  409 + thread safety of local block static initialization. The
  410 + <classname>QPDFCryptoProvider</classname> class uses a singleton
  411 + pattern with thread-safe initialization to create the singleton
  412 + instance of <classname>QPDFCryptoProvider</classname> and exposes
  413 + only static methods in its public interface. In this way, if a
  414 + developer wants to call any
  415 + <classname>QPDFCryptoProvider</classname> methods, the library
  416 + guarantees the <classname>QPDFCryptoProvider</classname> is fully
  417 + initialized and all built-in crypto providers are registered.
  418 + Making <classname>QPDFCryptoProvider</classname> actually know
  419 + about all the built-in providers may seem a bit sad at first, but
  420 + this choice makes it extremely clear exactly what the
  421 + initialization behavior is. There's no question about provider
  422 + implementations automatically registering themselves in a
  423 + nondeterministic order. It also means that implementations do not
  424 + need to know anything about the provider interface, which makes
  425 + them easier to test in isolation. Another advantage of this
  426 + approach is that a developer who wants to develop their own
  427 + crypto provider can do so in complete isolation from the qpdf
  428 + library and, with just two calls, can make qpdf use their
  429 + provider in their application. If they decided to contribute
  430 + their code, plugging it into the qpdf library would require a
  431 + very small change to qpdf's source code.
  432 + </para>
  433 + <para>
  434 + The decision to make the crypto provider selectable at runtime
  435 + was one I struggled with a little, but I decided to do it for
  436 + various reasons. Allowing an end user to switch crypto providers
  437 + easily could be very useful for reproducing a potential bug. If a
  438 + user reports a bug that some cryptographic thing is broken, I can
  439 + easily ask that person to try with the
  440 + <literal>QPDF_CRYPTO_PROVIDER</literal> variable set to different
  441 + values. The same could apply in the event of a performance
  442 + problem. This also makes it easier for qpdf's own test suite to
  443 + exercise code with different providers without having to make
  444 + every program that links with qpdf aware of the possibility of
  445 + multiple providers. In qpdf's continuous integration environment,
  446 + the entire test suite is run for each supported crypto provider.
  447 + This is made simple by being able to select the provider using an
  448 + environment variable.
  449 + </para>
  450 + <para>
  451 + Finally, making crypto providers selectable in this way establish
  452 + a pattern that I may follow again in the future for stream filter
  453 + providers. One could imagine a future enhancement where someone
  454 + could provide their own implementations for basic filters like
  455 + <literal>/FlateDecode</literal> or for other filters that qpdf
  456 + doesn't support. Implementing the registration functions and
  457 + internal storage of registered providers was also easier using
  458 + C++-11's functional interfaces, which was another reason to
  459 + require C++-11 at this time.
  460 + </para>
  461 + </sect2>
  462 + </sect1>
245 <sect1 id="ref.packaging"> 463 <sect1 id="ref.packaging">
246 <title>Notes for Packagers</title> 464 <title>Notes for Packagers</title>
247 <para> 465 <para>
@@ -250,6 +468,13 @@ make @@ -250,6 +468,13 @@ make
250 <itemizedlist> 468 <itemizedlist>
251 <listitem> 469 <listitem>
252 <para> 470 <para>
  471 + Make sure you are getting the intended behavior with regard to
  472 + crypto providers. Read <xref linkend="ref.crypto.build"/> for
  473 + details.
  474 + </para>
  475 + </listitem>
  476 + <listitem>
  477 + <para>
253 Passing <option>--enable-show-failed-test-output</option> to 478 Passing <option>--enable-show-failed-test-output</option> to
254 <command>./configure</command> will cause any failed test 479 <command>./configure</command> will cause any failed test
255 output to be written to the console. This can be very useful 480 output to be written to the console. This can be very useful
@@ -387,6 +612,17 @@ make @@ -387,6 +612,17 @@ make
387 </listitem> 612 </listitem>
388 </varlistentry> 613 </varlistentry>
389 <varlistentry> 614 <varlistentry>
  615 + <term><option>--show-crypto</option></term>
  616 + <listitem>
  617 + <para>
  618 + Show a list of available crypto providers, each on a line by
  619 + itself. The default provider is always listed first. See <xref
  620 + linkend="ref.crypto"/> for more information about crypto
  621 + providers.
  622 + </para>
  623 + </listitem>
  624 + </varlistentry>
  625 + <varlistentry>
390 <term><option>--completion-bash</option></term> 626 <term><option>--completion-bash</option></term>
391 <listitem> 627 <listitem>
392 <para> 628 <para>