This required moving files around in the repository and shifting from a master.adoc structure to _topic_map.yml, etc. README and Makefile modified slightly to reflect new build process
617 lines
No EOL
36 KiB
HTML
617 lines
No EOL
36 KiB
HTML
<!DOCTYPE html>
|
|
<html>
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<meta content="IE=edge" http-equiv="X-UA-Compatible">
|
|
<meta content="width=device-width, initial-scale=1.0" name="viewport">
|
|
<title>Defensive Coding Guide | Defensive Coding Guide | Implementing Security Features | Hardware Security Modules and Smart Cards</title>
|
|
|
|
<!-- Bootstrap -->
|
|
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
|
|
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap-theme.min.css">
|
|
|
|
<!-- Overpass Font -->
|
|
<link rel="stylesheet" href="https://overpass-30e2.kxcdn.com/overpass.css">
|
|
|
|
<link href="../../../master/_stylesheets/asciibinder.css" rel="stylesheet" />
|
|
|
|
<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
|
|
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
|
|
<!--[if lt IE 9]>
|
|
<script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
|
|
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
|
|
<![endif]-->
|
|
|
|
<link href="../../../master/_images/favicon32x32.png" rel="shortcut icon" type="text/css">
|
|
<!--[if IE]><link rel="shortcut icon" href="../../../master/_images/favicon.ico"><![endif]-->
|
|
<meta content="AsciiBinder" name="application-name">
|
|
</head>
|
|
<body>
|
|
<div class="navbar navbar-default" role="navigation">
|
|
<div class="container-fluid">
|
|
<div class="navbar-header">
|
|
<a class="navbar-brand" href="https://docs.fedoraproject.org/"><img alt="Fedora Documentation" src="../../../master/_images/fedora.svg"></a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="container">
|
|
<p class="toggle-nav visible-xs pull-left">
|
|
<button class="btn btn-default btn-sm" type="button" data-toggle="offcanvas">Toggle nav</button>
|
|
</p>
|
|
<ol class="breadcrumb">
|
|
<li class="sitename">
|
|
<a href="../../../index.html">Home</a>
|
|
</li>
|
|
<li class="hidden-xs active">
|
|
<a href="../../en-US/index.html">Defensive Coding Guide </a>
|
|
</li>
|
|
<li class="hidden-xs active">
|
|
<a href="../../en-US/index.html">Defensive Coding Guide</a>
|
|
</li>
|
|
<li class="hidden-xs active"><a href="../../en-US/features/Features-Authentication.html">Implementing Security Features</a></li>
|
|
<li class="hidden-xs active">
|
|
Hardware Security Modules and Smart Cards
|
|
</li>
|
|
</ol>
|
|
<div class="row row-offcanvas row-offcanvas-left">
|
|
<div class="col-xs-8 col-sm-3 col-md-3 sidebar sidebar-offcanvas">
|
|
<ul class="nav nav-sidebar">
|
|
<li class="nav-header">
|
|
<a class="" href="#" data-toggle="collapse" data-target="#topicGroup0">
|
|
<span id="tgSpan0" class="fa fa-angle-down"></span>Defensive Coding Guide
|
|
</a>
|
|
<ul id="topicGroup0" class="collapse in list-unstyled">
|
|
<li><a class="" href="../../en-US/index.html">Book Information</a></li>
|
|
<li class="nav-header">
|
|
<a class="" href="#" data-toggle="collapse" data-target="#topicSubGroup-0-1">
|
|
<span id="sgSpan-0-1" class="fa fa-caret-right"></span> Programming Languages
|
|
</a>
|
|
<ul id="topicSubGroup-0-1" class="nav-tertiary list-unstyled collapse">
|
|
<li><a class="" href="../../en-US/programming-languages/C.html">The C Programming Language</a></li>
|
|
<li><a class="" href="../../en-US/programming-languages/CXX.html">The C++ Programming Language</a></li>
|
|
<li><a class="" href="../../en-US/programming-languages/Java.html">The Java Programming Language</a></li>
|
|
<li><a class="" href="../../en-US/programming-languages/Python.html">The Python Programming Language</a></li>
|
|
<li><a class="" href="../../en-US/programming-languages/Shell.html">Shell Programming and bash</a></li>
|
|
<li><a class="" href="../../en-US/programming-languages/Go.html">The Go Programming Language</a></li>
|
|
<li><a class="" href="../../en-US/programming-languages/Vala.html">The Vala Programming Language</a></li>
|
|
</ul>
|
|
</li>
|
|
<li class="nav-header">
|
|
<a class="" href="#" data-toggle="collapse" data-target="#topicSubGroup-0-2">
|
|
<span id="sgSpan-0-2" class="fa fa-caret-right"></span> Specific Programming Tasks
|
|
</a>
|
|
<ul id="topicSubGroup-0-2" class="nav-tertiary list-unstyled collapse">
|
|
<li><a class="" href="../../en-US/tasks/Tasks-Library_Design.html">Library Design</a></li>
|
|
<li><a class="" href="../../en-US/tasks/Tasks-Descriptors.html">File Descriptor Management</a></li>
|
|
<li><a class="" href="../../en-US/tasks/Tasks-File_System.html">File System Manipulation</a></li>
|
|
<li><a class="" href="../../en-US/tasks/Tasks-Temporary_Files.html">Temporary Files</a></li>
|
|
<li><a class="" href="../../en-US/tasks/Tasks-Processes.html">Processes</a></li>
|
|
<li><a class="" href="../../en-US/tasks/Tasks-Serialization.html">Serialization and Deserialization</a></li>
|
|
<li><a class="" href="../../en-US/tasks/Tasks-Cryptography.html">Cryptography</a></li>
|
|
<li><a class="" href="../../en-US/tasks/Tasks-Packaging.html">RPM Packaging</a></li>
|
|
</ul>
|
|
</li>
|
|
<li class="nav-header">
|
|
<a class="" href="#" data-toggle="collapse" data-target="#topicSubGroup-0-3">
|
|
<span id="sgSpan-0-3" class="fa fa-caret-down"></span> Implementing Security Features
|
|
</a>
|
|
<ul id="topicSubGroup-0-3" class="nav-tertiary list-unstyled collapse in">
|
|
<li><a class="" href="../../en-US/features/Features-Authentication.html">Authentication and Authorization</a></li>
|
|
<li><a class="" href="../../en-US/features/Features-TLS.html">Transport Layer Security (TLS)</a></li>
|
|
<li><a class=" active" href="../../en-US/features/Features-HSM.html">Hardware Security Modules and Smart Cards</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a class="" href="../../en-US/Revision_History.html">Revision History</a></li>
|
|
</ul>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="col-xs-12 col-sm-9 col-md-9 main">
|
|
<div class="page-header">
|
|
<h2>Hardware Security Modules and Smart Cards</h2>
|
|
</div>
|
|
<div id="preamble">
|
|
<div class="sectionbody">
|
|
<div class="paragraph">
|
|
<p>Hardware Security Modules (HSMs) are specialized hardware intended
|
|
to protect private keys on server systems. They store internally
|
|
the private keys (e.g., RSA keys), and provide access to operations
|
|
with the keys without exposing the keys. That access, is provided using
|
|
a standardized API, which across Fedora is PKCS#11.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Smart cards are small cards with a micro processor, often combined with a
|
|
USB reader resembling a USB stick. They are very similar in nature with
|
|
HSMs as they can also be used to protect private keys and are almost
|
|
universally accessed via the PKCS#11 API. The main distinguishers from HSMs
|
|
is their inferior performance and often, the available hardware protection mechanisms.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Typically a smart card or HSM relies on a shared library to provide functionality.
|
|
This shared library follows the PKCS#11 API and thus is often referred to as
|
|
a PKCS#11 module. In Fedora the <code>opensc</code>
|
|
shared module (<code>opensc-pkcs11.so</code>) can be used for the majority
|
|
of smart cards available in the market. By convention these modules are located
|
|
at <code>/usr/lib64/pkcs11</code>. They can be used directly, or via
|
|
a higher level library.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>All the major crypto libraries (NSS, GnuTLS and OpenSSL in Fedora) support
|
|
hardware security modules and smart cards, by providing wrappers over the
|
|
PKCS#11 API. However, the level of support varies, as well as the ease of
|
|
use of such modules and its integration to the overall library API.</p>
|
|
</div>
|
|
<div class="ulist">
|
|
<ul>
|
|
<li>
|
|
<p>The PKCS#11 API does provide an API to access HSMs or smart cards, but
|
|
does not provide any method of discovering which HSMs or smart cards are
|
|
available in the system. In Fedora and modules are registered via <a href="https://p11-glue.freedesktop.org/doc/p11-kit/pkcs11-conf.html">p11-kit
|
|
configuration files</a>, stored at <code>/etc/pkcs11/modules/</code>. For applications using
|
|
<code>engine_pkcs11</code> or GnuTLS the registered modules are
|
|
available without further configuration. Other applications will have to load
|
|
the <code>p11-kit-proxy.so</code> module.</p>
|
|
</li>
|
|
<li>
|
|
<p>Most crypto libraries support the <a href="https://tools.ietf.org/html/rfc7512">PKCS#11 URLs scheme</a>
|
|
to identify objects stored in an HSM, however that support is not yet universal.
|
|
Some support transparent usage of PKCS#11 objects, e.g., specifying
|
|
a PKCS#11 object instead of a file, while others require to use
|
|
specialized APIs for such objects.</p>
|
|
</li>
|
|
<li>
|
|
<p>Objects stored in an HSM or smart card can be protected with a PIN. As such,
|
|
libraries typically require to set a PIN handling function for accessing private keys,
|
|
or the PIN can be passed along with a PKCS#11 URL and the pin-value parameter.</p>
|
|
</li>
|
|
<li>
|
|
<p>Obtaining a Hardware Security Module, or including it on a continuous integration
|
|
testing is not always feasible. For testing purposes smart cards supported by the OpenSC
|
|
project can be used, as well as software modules like <code>softhsm</code> which
|
|
provides a tool to setup a software HSM, and a PKCS#11 library.</p>
|
|
</li>
|
|
<li>
|
|
<p>The PKCS#11 API requires applications that use fork to reinitialize the used PKCS#11
|
|
modules. This is an uncommon requirement, which has led to several bugs across
|
|
applications in Fedora which used PKCS#11 directly. To make things more complicated
|
|
software PKCS#11 module like <code>softhsm</code> do not require this re-initialization
|
|
leading to applications working against software modules but failing with hardware
|
|
modules or smart cards. The wrapper PKCS#11 APIs provided by NSS, GnuTLS and
|
|
engine_pkcs11 (OpenSSL) handle the reinitialization after fork requirement transparently.</p>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect1">
|
|
<h2 id="sect-Defensive_Coding-HSM-OpenSSL"><a class="anchor" href="#sect-Defensive_Coding-HSM-OpenSSL"></a>OpenSSL HSM Support</h2>
|
|
<div class="sectionbody">
|
|
<div class="paragraph">
|
|
<p>OpenSSL does not have native support for PKCS#11. It can
|
|
provide PKCS#11 support through the OpenSC’s project
|
|
<code>pkcs11</code> engine (formerly known as <code>engine_pkcs11</code>).
|
|
As such software intended to use HSMs, must utilize that engine.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Engine <code>pkcs11</code> supports loading stored objects via PKCS#11 URLs.
|
|
If no PKCS#11 module is specified the engine will use the system-wide registered
|
|
modules via <code>p11-kit-proxy.so</code>.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>The following example demonstrates the initialization of the pkcs11 engine
|
|
and its usage to sign data.</p>
|
|
</div>
|
|
<div id="ex-Defensive_Coding-HSM-OpenSSL" class="exampleblock">
|
|
<div class="title">Example 1. Signing data with HSM and OpenSSL</div>
|
|
<div class="content">
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="CodeRay highlight"><code data-lang="c">OpenSSL_add_all_algorithms();
|
|
ERR_load_crypto_strings();
|
|
ERR_clear_error();
|
|
ENGINE_load_builtin_engines();
|
|
|
|
e = ENGINE_by_id(<span style="background-color:hsla(0,100%,50%,0.05)"><span style="color:#710">"</span><span style="color:#D20">pkcs11</span><span style="color:#710">"</span></span>);
|
|
<span style="color:#080;font-weight:bold">if</span> (!e) {
|
|
display_openssl_errors(__LINE__);
|
|
exit(<span style="color:#00D">1</span>);
|
|
}
|
|
|
|
<span style="color:#080;font-weight:bold">if</span> (module_path) {
|
|
fprintf(stderr, <span style="background-color:hsla(0,100%,50%,0.05)"><span style="color:#710">"</span><span style="color:#D20">loading: %s</span><span style="color:#b0b">\n</span><span style="color:#710">"</span></span>, module_path);
|
|
<span style="color:#080;font-weight:bold">if</span> (!ENGINE_ctrl_cmd_string(e, <span style="background-color:hsla(0,100%,50%,0.05)"><span style="color:#710">"</span><span style="color:#D20">MODULE_PATH</span><span style="color:#710">"</span></span>, module_path, <span style="color:#00D">0</span>)) {
|
|
display_openssl_errors(__LINE__);
|
|
exit(<span style="color:#00D">1</span>);
|
|
}
|
|
}
|
|
|
|
<span style="color:#080;font-weight:bold">if</span> (!ENGINE_init(e)) {
|
|
display_openssl_errors(__LINE__);
|
|
exit(<span style="color:#00D">1</span>);
|
|
}
|
|
|
|
<span style="color:#080;font-weight:bold">if</span> (key_pass && !ENGINE_ctrl_cmd_string(e, <span style="background-color:hsla(0,100%,50%,0.05)"><span style="color:#710">"</span><span style="color:#D20">PIN</span><span style="color:#710">"</span></span>, key_pass, <span style="color:#00D">0</span>)) {
|
|
display_openssl_errors(__LINE__);
|
|
exit(<span style="color:#00D">1</span>);
|
|
}
|
|
|
|
private_key = ENGINE_load_private_key(e, private_key_name, <span style="color:#069">NULL</span>, <span style="color:#069">NULL</span>);
|
|
<span style="color:#080;font-weight:bold">if</span> (!private_key) {
|
|
fprintf(stderr, <span style="background-color:hsla(0,100%,50%,0.05)"><span style="color:#710">"</span><span style="color:#D20">cannot load: %s</span><span style="color:#b0b">\n</span><span style="color:#710">"</span></span>, private_key_name);
|
|
display_openssl_errors(__LINE__);
|
|
exit(<span style="color:#00D">1</span>);
|
|
}
|
|
|
|
display_openssl_errors(__LINE__);
|
|
|
|
digest_algo = EVP_get_digestbyname(<span style="background-color:hsla(0,100%,50%,0.05)"><span style="color:#710">"</span><span style="color:#D20">sha256</span><span style="color:#710">"</span></span>);
|
|
|
|
EVP_MD_CTX_init(&ctx);
|
|
<span style="color:#080;font-weight:bold">if</span> (EVP_DigestInit(&ctx, digest_algo) <= <span style="color:#00D">0</span>) {
|
|
display_openssl_errors(__LINE__);
|
|
exit(<span style="color:#00D">1</span>);
|
|
}
|
|
|
|
EVP_SignInit(&ctx, digest_algo);
|
|
|
|
<span style="color:#579">#define</span> TEST_DATA <span style="background-color:hsla(0,100%,50%,0.05)"><span style="color:#710">"</span><span style="color:#D20">test data</span><span style="color:#710">"</span></span>
|
|
<span style="color:#080;font-weight:bold">if</span> (EVP_SignUpdate(&ctx, TEST_DATA, <span style="color:#080;font-weight:bold">sizeof</span>(TEST_DATA) - <span style="color:#00D">1</span>) <= <span style="color:#00D">0</span>) {
|
|
display_openssl_errors(__LINE__);
|
|
exit(<span style="color:#00D">1</span>);
|
|
}
|
|
|
|
n = <span style="color:#080;font-weight:bold">sizeof</span>(buf);
|
|
<span style="color:#080;font-weight:bold">if</span> (EVP_SignFinal(&ctx, buf, &n, private_key) <= <span style="color:#00D">0</span>) {
|
|
display_openssl_errors(__LINE__);
|
|
exit(<span style="color:#00D">1</span>);
|
|
}
|
|
|
|
EVP_PKEY_free(private_key);
|
|
ENGINE_finish(e);</code></pre>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect1">
|
|
<h2 id="sect-Defensive_Coding-HSM-GNUTLS"><a class="anchor" href="#sect-Defensive_Coding-HSM-GNUTLS"></a>GnuTLS HSM Support</h2>
|
|
<div class="sectionbody">
|
|
<div class="paragraph">
|
|
<p>GnuTLS supports PKCS#11 natively. Most of the API functions
|
|
accepting certificate files, can also accept PKCS#11 URLs, thus
|
|
requiring minor or no modifications to applications in order
|
|
to support HSMs. In most cases applications must be modified
|
|
to install a PIN callback function.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>The following example demonstrates the initialization of the pkcs11 engine
|
|
and its usage to sign data.</p>
|
|
</div>
|
|
<div id="ex-Defensive_Coding-HSM-GNUTLS" class="exampleblock">
|
|
<div class="title">Example 2. Signing data with HSM and GnuTLS</div>
|
|
<div class="content">
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="CodeRay highlight"><code data-lang="c"><span style="color:#080;font-weight:bold">if</span> (module_path) {
|
|
ret = gnutls_pkcs11_init(GNUTLS_PKCS11_FLAG_MANUAL, <span style="color:#069">NULL</span>);
|
|
<span style="color:#080;font-weight:bold">if</span> (ret < <span style="color:#00D">0</span>) {
|
|
fprintf(stderr, <span style="background-color:hsla(0,100%,50%,0.05)"><span style="color:#710">"</span><span style="color:#D20">error in %d: %s</span><span style="color:#b0b">\n</span><span style="color:#710">"</span></span>, __LINE__, gnutls_strerror(ret));
|
|
exit(<span style="color:#00D">1</span>);
|
|
}
|
|
|
|
ret = gnutls_pkcs11_add_provider(module_path, <span style="color:#069">NULL</span>);
|
|
<span style="color:#080;font-weight:bold">if</span> (ret < <span style="color:#00D">0</span>) {
|
|
fprintf(stderr, <span style="background-color:hsla(0,100%,50%,0.05)"><span style="color:#710">"</span><span style="color:#D20">error in %d: %s</span><span style="color:#b0b">\n</span><span style="color:#710">"</span></span>, __LINE__, gnutls_strerror(ret));
|
|
exit(<span style="color:#00D">1</span>);
|
|
}
|
|
}
|
|
|
|
<span style="color:#080;font-weight:bold">if</span> (key_pass)
|
|
gnutls_pkcs11_set_pin_function(pin_function, key_pass);
|
|
|
|
ret = gnutls_privkey_init(&private_key);
|
|
<span style="color:#080;font-weight:bold">if</span> (ret < <span style="color:#00D">0</span>) {
|
|
fprintf(stderr, <span style="background-color:hsla(0,100%,50%,0.05)"><span style="color:#710">"</span><span style="color:#D20">error in %d: %s</span><span style="color:#b0b">\n</span><span style="color:#710">"</span></span>, __LINE__, gnutls_strerror(ret));
|
|
exit(<span style="color:#00D">1</span>);
|
|
}
|
|
|
|
ret = gnutls_privkey_import_url(private_key, private_key_name, <span style="color:#00D">0</span>);
|
|
<span style="color:#080;font-weight:bold">if</span> (ret < <span style="color:#00D">0</span>) {
|
|
fprintf(stderr, <span style="background-color:hsla(0,100%,50%,0.05)"><span style="color:#710">"</span><span style="color:#D20">error in %d: %s</span><span style="color:#b0b">\n</span><span style="color:#710">"</span></span>, __LINE__, gnutls_strerror(ret));
|
|
exit(<span style="color:#00D">1</span>);
|
|
}
|
|
|
|
ret = gnutls_privkey_sign_data(private_key, GNUTLS_DIG_SHA256, <span style="color:#00D">0</span>,
|
|
&testdata, &signature);
|
|
<span style="color:#080;font-weight:bold">if</span> (ret < <span style="color:#00D">0</span>) {
|
|
fprintf(stderr, <span style="background-color:hsla(0,100%,50%,0.05)"><span style="color:#710">"</span><span style="color:#D20">error in %d: %s</span><span style="color:#b0b">\n</span><span style="color:#710">"</span></span>, __LINE__, gnutls_strerror(ret));
|
|
exit(<span style="color:#00D">1</span>);
|
|
}
|
|
|
|
gnutls_privkey_deinit(private_key);
|
|
gnutls_free(signature.data);</code></pre>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>The PIN callback function can be either set globally as in
|
|
the example above or locally by utilizing functions such as <code>gnutls_privkey_set_pin_function</code>.
|
|
An example PIN callback function is shown below.</p>
|
|
</div>
|
|
<div id="ex-Defensive_Coding-HSM-GNUTLS-PIN" class="exampleblock">
|
|
<div class="title">Example 3. An example PIN callback with GNUTLS</div>
|
|
<div class="content">
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="CodeRay highlight"><code data-lang="c"><span style="color:#0a8;font-weight:bold">int</span> pin_function(<span style="color:#088;font-weight:bold">void</span> *userdata, <span style="color:#0a8;font-weight:bold">int</span> attempt, <span style="color:#088;font-weight:bold">const</span> <span style="color:#0a8;font-weight:bold">char</span> *token_url,
|
|
<span style="color:#088;font-weight:bold">const</span> <span style="color:#0a8;font-weight:bold">char</span> *token_label, <span style="color:#0a8;font-weight:bold">unsigned</span> flags, <span style="color:#0a8;font-weight:bold">char</span> *pin, size_t pin_max)
|
|
{
|
|
<span style="color:#080;font-weight:bold">if</span> (flags & GNUTLS_PIN_FINAL_TRY)
|
|
printf(<span style="background-color:hsla(0,100%,50%,0.05)"><span style="color:#710">"</span><span style="color:#D20">This is the final try before locking!</span><span style="color:#b0b">\n</span><span style="color:#710">"</span></span>);
|
|
<span style="color:#080;font-weight:bold">if</span> (flags & GNUTLS_PIN_COUNT_LOW)
|
|
printf(<span style="background-color:hsla(0,100%,50%,0.05)"><span style="color:#710">"</span><span style="color:#D20">Only few tries left before locking!</span><span style="color:#b0b">\n</span><span style="color:#710">"</span></span>);
|
|
<span style="color:#080;font-weight:bold">if</span> (flags & GNUTLS_PIN_WRONG)
|
|
printf(<span style="background-color:hsla(0,100%,50%,0.05)"><span style="color:#710">"</span><span style="color:#D20">Wrong PIN has been provided in the previous attempt</span><span style="color:#b0b">\n</span><span style="color:#710">"</span></span>);
|
|
|
|
<span style="color:#777">/* userdata is the second value passed to gnutls_pkcs11_set_pin_function()
|
|
* in this example we passed the PIN as a null terminated value.
|
|
*/</span>
|
|
snprintf(pin, pin_max, <span style="background-color:hsla(0,100%,50%,0.05)"><span style="color:#710">"</span><span style="color:#D20">%s</span><span style="color:#710">"</span></span>, (<span style="color:#0a8;font-weight:bold">char</span>*)userdata);
|
|
<span style="color:#080;font-weight:bold">return</span> <span style="color:#00D">0</span>;
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect1">
|
|
<h2 id="sect-Defensive_Coding-HSM-NSS"><a class="anchor" href="#sect-Defensive_Coding-HSM-NSS"></a>NSS HSM Support</h2>
|
|
<div class="sectionbody">
|
|
<div class="paragraph">
|
|
<p>NSS supports PKCS#11 natively. In fact all NSS crypto operations,
|
|
including built-in operations, go through PKCS #11 modules. NSS provides
|
|
its own software PKCS #11 module called softoken. NSS automatically
|
|
loads any PKCS #11 module specified in its module database, which can
|
|
be manipulated with the modutil command. NSS uses the PKCS #11 module
|
|
that contains the requested keys to do the crypto operations. As long as
|
|
the application opens an NSS database and properly sets a pin callback. If
|
|
it runs with native NSS, it should be able to use HSMs that provide PKCS #11
|
|
modules. Modules can also be loaded programatically, though this is less common.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>The following example demonstrates a typical NSS application for signing.</p>
|
|
</div>
|
|
<div id="ex-Defensive_Coding-HSM-NSS" class="exampleblock">
|
|
<div class="title">Example 4. Signing data with HSM and NSS</div>
|
|
<div class="content">
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="CodeRay highlight"><code data-lang="c">SECStatus rv;
|
|
CERTCertificate *cert = <span style="color:#069">NULL</span>;
|
|
SECKEYPrivateKey *pvtkey = <span style="color:#069">NULL</span>;
|
|
SECItem signature = { siBuffer, <span style="color:#069">NULL</span>, <span style="color:#00D">0</span> };
|
|
SECOidTag algTag;
|
|
<span style="color:#0a8;font-weight:bold">int</span> r = <span style="color:#00D">1</span>;
|
|
<span style="color:#0a8;font-weight:bold">unsigned</span> <span style="color:#0a8;font-weight:bold">char</span> buf[] = <span style="background-color:hsla(0,100%,50%,0.05)"><span style="color:#710">"</span><span style="color:#D20">test data to sign</span><span style="color:#710">"</span></span>;
|
|
<span style="color:#088;font-weight:bold">const</span> <span style="color:#0a8;font-weight:bold">char</span> *cert_name;
|
|
<span style="color:#0a8;font-weight:bold">unsigned</span> i;
|
|
|
|
<span style="color:#080;font-weight:bold">if</span> (argc < <span style="color:#00D">3</span>) {
|
|
fprintf(stderr, <span style="background-color:hsla(0,100%,50%,0.05)"><span style="color:#710">"</span><span style="color:#D20">usage: %s [cert name] [PIN]</span><span style="color:#b0b">\n</span><span style="color:#b0b">\n</span><span style="color:#710">"</span></span>, argv[<span style="color:#00D">0</span>]);
|
|
exit(<span style="color:#00D">1</span>);
|
|
}
|
|
|
|
cert_name = argv[<span style="color:#00D">1</span>];
|
|
pin = argv[<span style="color:#00D">2</span>];
|
|
|
|
PK11_SetPasswordFunc(passwdcb);
|
|
NSS_InitializePRErrorTable();
|
|
rv = NSS_Init(<span style="background-color:hsla(0,100%,50%,0.05)"><span style="color:#710">"</span><span style="color:#D20">.</span><span style="color:#710">"</span></span>);
|
|
<span style="color:#080;font-weight:bold">if</span> (rv != SECSuccess) {
|
|
fprintf(stderr, <span style="background-color:hsla(0,100%,50%,0.05)"><span style="color:#710">"</span><span style="color:#D20">NSS initialization failed (err %d)</span><span style="color:#b0b">\n</span><span style="color:#710">"</span></span>, PR_GetError());
|
|
<span style="color:#080;font-weight:bold">goto</span> cleanup;
|
|
}
|
|
|
|
cert = PK11_FindCertFromNickname(cert_name, <span style="color:#069">NULL</span>);
|
|
<span style="color:#080;font-weight:bold">if</span> (cert == <span style="color:#069">NULL</span>) {
|
|
fprintf(stderr, <span style="background-color:hsla(0,100%,50%,0.05)"><span style="color:#710">"</span><span style="color:#D20">Couldn't find cert %s in NSS db (err %d: %s)</span><span style="color:#b0b">\n</span><span style="color:#710">"</span></span>,
|
|
cert_name, PR_GetError(), PORT_ErrorToString(PR_GetError()));
|
|
<span style="color:#080;font-weight:bold">goto</span> cleanup;
|
|
}
|
|
|
|
fprintf(stderr, <span style="background-color:hsla(0,100%,50%,0.05)"><span style="color:#710">"</span><span style="color:#D20">Buffer being signed = </span><span style="color:#b0b">\n</span><span style="color:#D20">%s</span><span style="color:#b0b">\n</span><span style="color:#710">"</span></span>, buf);
|
|
|
|
pvtkey = PK11_FindKeyByAnyCert(cert, <span style="color:#069">NULL</span>);
|
|
<span style="color:#080;font-weight:bold">if</span> (pvtkey == <span style="color:#069">NULL</span>) {
|
|
fprintf(stderr, <span style="background-color:hsla(0,100%,50%,0.05)"><span style="color:#710">"</span><span style="color:#D20">Couldn't find private key for cert %s (err %d: %s)</span><span style="color:#b0b">\n</span><span style="color:#710">"</span></span>,
|
|
cert_name, PR_GetError(), PORT_ErrorToString(PR_GetError()));
|
|
<span style="color:#080;font-weight:bold">goto</span> cleanup;
|
|
}
|
|
|
|
<span style="color:#777">/* get the algtag. Pick the default hash algorithm */</span>
|
|
algTag = SEC_GetSignatureAlgorithmOidTag(pvtkey->keyType, SEC_OID_UNKNOWN);
|
|
|
|
fprintf(stderr, <span style="background-color:hsla(0,100%,50%,0.05)"><span style="color:#710">"</span><span style="color:#D20">Signing with alg = %s (%d)</span><span style="color:#b0b">\n</span><span style="color:#710">"</span></span>,
|
|
SECOID_FindOIDTagDescription(algTag), algTag);
|
|
|
|
rv = SEC_SignData(&signature, buf, <span style="color:#080;font-weight:bold">sizeof</span>(buf)-<span style="color:#00D">1</span>, pvtkey, algTag);
|
|
<span style="color:#080;font-weight:bold">if</span> (rv != SECSuccess) {
|
|
fprintf(stderr, <span style="background-color:hsla(0,100%,50%,0.05)"><span style="color:#710">"</span><span style="color:#D20">sign with Private Key failed (err %d: %s)</span><span style="color:#b0b">\n</span><span style="color:#710">"</span></span>,
|
|
PR_GetError(), PORT_ErrorToString(PR_GetError()));
|
|
<span style="color:#080;font-weight:bold">goto</span> cleanup;
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>To use the example above with an HSM or smart card you will need to do the following.</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="CodeRay highlight"><code data-lang="bash"># add your HSM or token library to an NSS database (in the sample code the database is
|
|
# located in the current directory'.')
|
|
$ modutil -add "My HSM" -libfile ${path_to_pkcs11_file} -dbdir .
|
|
# Find the token name on your HSM
|
|
$ modutil -list -dbdir .
|
|
# find the cert on your token
|
|
$ certutil -L -h ${token_name} -d .
|
|
# pass the cert to your signing program
|
|
$ NSS_Sign_Example "${token_name}:${cert_name}"</code></pre>
|
|
</div>
|
|
</div>
|
|
<div id="ex-Defensive_Coding-HSM-NSS-PIN" class="exampleblock">
|
|
<div class="title">Example 5. An example PIN callback with NSS</div>
|
|
<div class="content">
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="CodeRay highlight"><code data-lang="c"><span style="color:#0a8;font-weight:bold">char</span> *passwdcb(PK11SlotInfo * slot, PRBool retry, <span style="color:#088;font-weight:bold">void</span> *arg)
|
|
{
|
|
<span style="color:#080;font-weight:bold">if</span> (!isatty(STDIN_FILENO) && retry) {
|
|
<span style="color:#777">/* we're just reading from a file, and the value is known to be wrong,
|
|
* don't keep bounding the token with the wrong password. */</span>
|
|
<span style="color:#080;font-weight:bold">return</span> <span style="color:#069">NULL</span>;
|
|
}
|
|
|
|
<span style="color:#080;font-weight:bold">if</span> (retry) {
|
|
printf(<span style="background-color:hsla(0,100%,50%,0.05)"><span style="color:#710">"</span><span style="color:#D20">Warning: Wrong PIN has been provided in the previous attempt</span><span style="color:#b0b">\n</span><span style="color:#710">"</span></span>);
|
|
<span style="color:#080;font-weight:bold">if</span> (PK11_IsHW(slot)) {
|
|
printf
|
|
(<span style="background-color:hsla(0,100%,50%,0.05)"><span style="color:#710">"</span><span style="color:#D20"> NOTE: multiple pin failures could result in locking your device</span><span style="color:#b0b">\n</span><span style="color:#710">"</span></span>);
|
|
}
|
|
}
|
|
|
|
<span style="color:#080;font-weight:bold">if</span> (pin == <span style="color:#069">NULL</span>)
|
|
<span style="color:#080;font-weight:bold">return</span> pin;
|
|
<span style="color:#080;font-weight:bold">else</span>
|
|
<span style="color:#080;font-weight:bold">return</span> strdup(pin);
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div id="bottom" class="text-muted py-3" >
|
|
<div class="foot">
|
|
<div class="container">
|
|
<div class="row footerlinks">
|
|
<div class="col-sm-3 col-xs-6 widget">
|
|
<h3 class="widget-title">About</h3>
|
|
<div class="widget-body">
|
|
<dl>
|
|
<dd><a href="https://fedoraproject.org/wiki/Overview">About Fedora</a></dd>
|
|
<dd><a href="https://getfedora.org/en/sponsors">Sponsors</a></dd>
|
|
<dd><a href="https://fedoramagazine.org">Fedora Magazine</a></dd>
|
|
<dd><a href="https://fedoraproject.org/wiki/Legal:Main#Legal">Legal</a></dd>
|
|
</dl>
|
|
<ul class="list-inline">
|
|
<li>
|
|
<a href="https://www.facebook.com/TheFedoraProject" class="btn-social btn-outline"><i class="fa fa-fw fa-facebook"></i></a>
|
|
</li>
|
|
<li>
|
|
<a href="https://plus.google.com/112917221531140868607" class="btn-social btn-outline"><i class="fa fa-fw fa-google-plus"></i></a>
|
|
</li>
|
|
<li>
|
|
<a href="https://twitter.com/fedora" class="btn-social btn-outline"><i class="fa fa-fw fa-twitter"></i></a>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="col-sm-3 col-xs-6 widget">
|
|
<h3 class="widget-title uppercase">Download</h3>
|
|
<div class="widget-body">
|
|
<dl>
|
|
<dd><a href="https://getfedora.org/en/workstation/download">Get Fedora Workstation</a></dd>
|
|
<dd><a href="https://getfedora.org/en/server/download">Get Fedora Server</a></dd>
|
|
<dd><a href="https://getfedora.org/en/atomic/download">Get Fedora Atomic</a></dd>
|
|
<dd><a href="https://spins.fedoraproject.org">Fedora Spins</a></dd>
|
|
<dd><a href="https://labs.fedoraproject.org">Fedora Labs</a></dd>
|
|
<dd><a href="https://arm.fedoraproject.org">Fedora ARM<span class="sup">®</span></a></dd>
|
|
<dd><a href="https://alt.fedoraproject.org/">Alternative Downloads</a></dd>
|
|
|
|
</dl>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="col-sm-3 col-xs-6 widget">
|
|
<h3 class="widget-title">Support</h3>
|
|
<div class="widget-body">
|
|
<dl>
|
|
<dd><a href="https://fedoraproject.org/wiki/Communicating_and_getting_help">Get Help</a></dd>
|
|
<dd><a href="https://ask.fedoraproject.org/">Ask Fedora</a></dd>
|
|
<dd><a href="https://fedoraproject.org/wiki/Common_F27_bugs">Common Bugs</a></dd>
|
|
<dd><a href="https://developer.fedoraproject.org/">Fedora Developer Portal</a></dd>
|
|
<dd><a href="https://docs.fedoraproject.org/f27/install-guide/index.html">Installation Guide</a></dd>
|
|
</dl>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="col-sm-3 col-xs-6 widget">
|
|
<h3 class="widget-title">Join</h3>
|
|
<div class="widget-body">
|
|
<dl>
|
|
<dd><a href="https://fedoraproject.org/wiki/Join">Join Fedora</a></dd>
|
|
<dd><a href="http://fedoraplanet.org">Planet Fedora</a></dd>
|
|
<dd><a href="https://fedoraproject.org/wiki/SIGs">Fedora SIGs</a></dd>
|
|
<dd><a href="https://admin.fedoraproject.org/accounts/">Fedora Account System</a></dd>
|
|
<dd><a href="https://fedoracommunity.org/">Fedora Community</a></dd>
|
|
</dl>
|
|
</div>
|
|
</div>
|
|
</div> <!-- /row of widgets -->
|
|
|
|
<div class="row">
|
|
<div class="col-md-2">
|
|
<div class="widget-body">
|
|
<a href="https://www.redhat.com/"><img class="rh-logo" src="../../../master/_images/redhat-logo.png" alt="Red Hat Logo" /></a>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-7">
|
|
<div class="widget-body">
|
|
<p class="sponsor">Fedora is sponsored by Red Hat.</p>
|
|
<p class="sponsor"><a href="https://www.redhat.com/en/technologies/linux-platforms/articles/relationship-between-fedora-and-rhel">Learn more about the relationship between Red Hat and Fedora »</a></p>
|
|
<p class="copy">© 2017 Red Hat, Inc. and others. Please send any comments or corrections to the <a href="https://pagure.io/fedora-docs/docs-fp-o">documentation team</a></p>
|
|
</div>
|
|
</div>
|
|
</div> <!-- /row of widgets -->
|
|
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
|
|
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
|
|
<!-- Latest compiled and minified JavaScript -->
|
|
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
|
|
<script src="../../../master/_javascripts/bootstrap-offcanvas.js" type="text/javascript"></script>
|
|
<script type="text/javascript">
|
|
/*<![CDATA[*/
|
|
$(document).ready(function() {
|
|
$("[id^='topicGroup']").on('show.bs.collapse', function (event) {
|
|
if (!($(event.target).attr('id').match(/^topicSubGroup/))) {
|
|
$(this).parent().find("[id^='tgSpan']").toggleClass("fa-angle-right fa-angle-down");
|
|
}
|
|
});
|
|
$("[id^='topicGroup']").on('hide.bs.collapse', function (event) {
|
|
if (!($(event.target).attr('id').match(/^topicSubGroup/))) {
|
|
$(this).parent().find("[id^='tgSpan']").toggleClass("fa-angle-right fa-angle-down");
|
|
}
|
|
});
|
|
$("[id^='topicSubGroup']").on('show.bs.collapse', function () {
|
|
$(this).parent().find("[id^='sgSpan']").toggleClass("fa-caret-right fa-caret-down");
|
|
});
|
|
$("[id^='topicSubGroup']").on('hide.bs.collapse', function () {
|
|
$(this).parent().find("[id^='sgSpan']").toggleClass("fa-caret-right fa-caret-down");
|
|
});
|
|
});
|
|
/*]]>*/
|
|
</script>
|
|
</body>
|
|
</html> |