summaryrefslogtreecommitdiff
path: root/doc/cha-crypto.texi
blob: 06c3c5ca981a91fc6e9c62e4bbbdea9fcae3d45b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
@node Using GnuTLS as a cryptographic library
@chapter Using GnuTLS as a cryptographic library

@acronym{GnuTLS} is not a low-level cryptographic library, i.e., 
it does not provide access to basic cryptographic primitives. However
it abstracts the internal cryptographic back-end (see @ref{Cryptographic Backend}),
providing symmetric crypto, hash and HMAC algorithms, as well access
to the random number generation. For a low-level crypto API the usage of nettle
@footnote{See @uref{http://www.lysator.liu.se/~nisse/nettle/}.} library is recommended.

@menu
* Symmetric algorithms::
* Public key algorithms::
* Hash and MAC functions::
* Random number generation::
* Overriding algorithms::
@end menu

@node Symmetric algorithms
@section Symmetric algorithms
@cindex symmetric algorithms
@cindex symmetric cryptography

The available functions to access symmetric crypto algorithms operations
are shown below. The supported algorithms are the algorithms required by the TLS protocol.
They are listed in @ref{gnutls_cipher_algorithm_t}.

@showenumdesc{gnutls_cipher_algorithm_t,The supported ciphers.}

@showfuncE{gnutls_cipher_init,gnutls_cipher_encrypt2,gnutls_cipher_decrypt2,gnutls_cipher_set_iv,gnutls_cipher_deinit}

@showfuncB{gnutls_cipher_add_auth,gnutls_cipher_tag}
While the latter two functions allow the same API can be used with authenticated encryption ciphers, 
it is recommended to use the following functions which are solely for AEAD ciphers. The latter
API is designed to be simple to use and also hard to misuse, by handling the tag verification
and addition in transparent way.

@showfuncD{gnutls_aead_cipher_init,gnutls_aead_cipher_encrypt,gnutls_aead_cipher_decrypt,gnutls_aead_cipher_deinit}

@node Public key algorithms
@section Public key algorithms
@cindex public key algorithms

Public key cryptography algorithms such as RSA, DSA and ECDSA, can be
accessed using the abstract key API in @ref{Abstract key types}. This
is a high level API with the advantage of transparently handling keys
in memory and keys present in smart cards.

@subsection PKCS #7 signing
@cindex PKCS #7
@cindex file signing

The PKCS #7 format is common format used for digital signatures. It allows to sign
by embedding the data into the signature, or creating detached signatures of the data,
including a timestamp, additional certificates etc. In certain cases this format is also
used to transport lists of certificates and CRLs.

The basic functions to initialize, deinitialize, import, export or print information
about a PKCS #7 structure are shown below.
@showfuncE{gnutls_pkcs7_init,gnutls_pkcs7_deinit,gnutls_pkcs7_export2,gnutls_pkcs7_import,gnutls_pkcs7_print}

The following functions allow the verification of a structure using either a trust list, or
individual certificates. The @funcref{gnutls_pkcs7_sign} function is the data signing function.

@showfuncB{gnutls_pkcs7_verify_direct,gnutls_pkcs7_verify}
@showfuncdesc{gnutls_pkcs7_sign}

@showenumdesc{gnutls_pkcs7_sign_flags,Flags applicable to gnutls_pkcs7_sign()}

Other helper functions which allow to access the signatures, or certificates attached
in the structure are listed below.

@showfuncF{gnutls_pkcs7_get_signature_count,gnutls_pkcs7_get_signature_info,gnutls_pkcs7_get_crt_count,gnutls_pkcs7_get_crt_raw2,gnutls_pkcs7_get_crl_count,gnutls_pkcs7_get_crl_raw2}

To append certificates, or CRLs in the structure the following functions are provided.
@showfuncD{gnutls_pkcs7_set_crt_raw,gnutls_pkcs7_set_crt,gnutls_pkcs7_set_crl_raw,gnutls_pkcs7_set_crl}

@node Hash and MAC functions
@section Hash and MAC functions
@cindex hash functions
@cindex HMAC functions
@cindex MAC functions

The available operations to access hash functions and hash-MAC (HMAC) algorithms
are shown below. HMAC algorithms provided keyed hash functionality. The supported MAC and HMAC
algorithms are listed in @ref{gnutls_mac_algorithm_t}. Note that, despite the @code{hmac} part 
in the name of the MAC functions listed below, they can be used either for HMAC or MAC operations.

@showenumdesc{gnutls_mac_algorithm_t,The supported MAC and HMAC algorithms.}

@showfuncF{gnutls_hmac_init,gnutls_hmac,gnutls_hmac_output,gnutls_hmac_deinit,gnutls_hmac_get_len,gnutls_hmac_fast}

The available functions to access hash functions are shown below. The supported hash functions
are shown in @ref{gnutls_digest_algorithm_t}.

@showfuncF{gnutls_hash_init,gnutls_hash,gnutls_hash_output,gnutls_hash_deinit,gnutls_hash_get_len,gnutls_hash_fast}
@showfuncA{gnutls_fingerprint}

@showenumdesc{gnutls_digest_algorithm_t,The supported hash algorithms.}

@node Random number generation
@section Random number generation
@cindex random numbers

Access to the random number generator is provided using the @funcref{gnutls_rnd}
function. It allows obtaining random data of various levels.

@showenumdesc{gnutls_rnd_level_t,The random number levels.}
@showfuncdesc{gnutls_rnd}

@subsection Inner workings

The random number levels map to three CHACHA-based random generators which
are initially seeded using the OS random device, e.g., @code{/dev/urandom}
or @code{getrandom()}. These random generators are unique per thread, and
are automatically re-seeded when a fork is detected.

The reason the CHACHA cipher was selected for the GnuTLS' PRNG is the fact
that CHACHA is considered a secure and fast stream cipher, and is already
defined for use in TLS protocol. As such, the utilization of it would
not stress the CPU caches, and would allow for better performance on busy
servers, irrespective of their architecture (e.g., even if AES is not
available with an optimized instruction set).

The generators are unique per thread to allow lock-free operation. That
induces a cost of around 140-bytes for the state of the generators per
thread, on threads that would utilize @funcref{gnutls_rnd}. At the same time
it allows fast and lock-free access to the generators. That benefits servers 
which utilize more than 4 threads, while imposes no cost on single threaded
processes.

On the first call to @funcref{gnutls_rnd} they are seeded with three independent
keys obtained from the OS random device. Their seed is used to output a fixed amount
of bytes. The lower the level of the random generator the more bytes the
generator will output without reseeding, providing it better performance.
For the @code{GNUTLS_RND_KEY} and @code{GNUTLS_RND_RANDOM} levels, a
re-seed xor's data obtained from the OS random device with the old key,
while the @code{GNUTLS_RND_NONCE} levels utilizes
the generator of the @code{GNUTLS_RND_RANDOM} level to obtain a new seed
(which is also combined with the old key to produce the new).
That is, the @code{GNUTLS_RND_NONCE}
level is re-seeded using the @code{GNUTLS_RND_RANDOM}, and
@code{GNUTLS_RND_RANDOM}, @code{GNUTLS_RND_KEY} using the system random
generator.

@subsection Defense against PRNG attacks

This section describes the counter-measures available in the Pseudo-random number generator (PRNG)
of GnuTLS for known attacks as described in @xcite{PRNGATTACKS}. Note that, the attacks on a PRNG such as
state-compromise, assume a quite powerful adversary which has in practice
access to the PRNG state.

@subsubheading Cryptanalytic

To defend against cryptanalytic attacks GnuTLS' PRNG is a stream cipher
designed to defend against the same attacks. As such, GnuTLS' PRNG strength
with regards to this attack relies on the underlying crypto block,
which at the time of writing is CHACHA. That is easily replaceable in
the future if required.

@subsubheading Input-based attacks

These attacks assume that the attacker can influence the input that is used
to form the state of the PRNG. To counter these attacks GnuTLS does not
gather input from the system environment but rather relies on the OS
provided random generator. That is the @code{/dev/urandom} or
@code{getentropy}/@code{getrandom} system calls. As such, GnuTLS' PRNG
is as strong as the system random generator can ensure with regards to
input-based attacks.

@subsubheading State-compromise: Backtracking

A backtracking attack, assumes that an adversary obtains at some point of time
access to the generator state, and wants to recover past bytes. As the
GnuTLS generator is fine-tuned to provide multiple levels, such an attack
mainly concerns levels @code{GNUTLS_RND_RANDOM} and @code{GNUTLS_RND_KEY},
since @code{GNUTLS_RND_NONCE} is intended to output non-secret data.
The @code{GNUTLS_RND_RANDOM} generator at the time of writing can output
16kb prior to being re-seeded thus this is its upper bound for previously
generated data recovered using this attack. That assumes that the state
of the system random generator is unknown to the attacker

That attack reflects a real world scenario where application's memory is
temporarily compromised, while kernel's memory is inaccessible.

@subsubheading State-compromise: Permanent Compromise Attack

A permanent compromise attack implies that once an attacker compromises the
state of GnuTLS' random generator on specific time, all future and past
outputs from the generator can be compromised. For past outputs the
previous paragraph applies. For future outputs, both the @code{GNUTLS_RND_RANDOM}
and the @code{GNUTLS_RND_KEY} with recover on 16kb or 1kb respectively
have been generated. The @code{GNUTLS_RND_NONCE} level generator
will recover after several megabytes of output is generated.
As the nonce level is intended for non-secret but unpredictable output,
the above is a compromise to improve performance.

@subsubheading State-compromise: Iterative guessing

This attack assumes that after an attacker obtained the PRNG state
at some point, is able to recover the state at a later time by observing
outputs of the PRNG. That is countered by switching the key to generators
using a combination of a fresh key and the old one (using XOR), at
re-seed time. All levels are immune to such attack.

@subsubheading State-compromise: Meet-in-the-Middle

This attack assumes that the attacker obtained the PRNG state at
two distinct times, and being able to recover the state at the third time
after observing the output of the PRNG. Given the approach described
on the above paragraph, all levels are immune to such attack.


@node Overriding algorithms
@section Overriding algorithms
@cindex overriding algorithms

In systems which provide a hardware accelerated cipher implementation
that is not directly supported by GnuTLS, it is possible to utilize it.
There are functions which allow overriding the default cipher, digest and MAC
implementations. Those are described below.

To override public key operations see @ref{Abstract private keys}.

@showfuncdesc{gnutls_crypto_register_cipher}
@showfuncdesc{gnutls_crypto_register_aead_cipher}
@showfuncdesc{gnutls_crypto_register_mac}
@showfuncdesc{gnutls_crypto_register_digest}