~ubuntu-branches/ubuntu/raring/ipxe/raring

« back to all changes in this revision

Viewing changes to src/include/ipxe/entropy.h

  • Committer: Package Import Robot
  • Author(s): James Page
  • Date: 2012-11-14 15:47:31 UTC
  • mfrom: (1.1.3)
  • Revision ID: package-import@ubuntu.com-20121114154731-jhuy5d1h2jw75qe9
Tags: 1.0.0+git-4.d6b0b76-0ubuntu1
* New upstream snapshot:
  - d/p/iscsi*.patch: Dropped - included in snapshot.
  - Refreshed all other patches.
* d/p/enable-https.patch: Enable HTTPS support (LP: #1025239).

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#ifndef _IPXE_ENTROPY_H
 
2
#define _IPXE_ENTROPY_H
 
3
 
 
4
/** @file
 
5
 *
 
6
 * Entropy source
 
7
 *
 
8
 */
 
9
 
 
10
FILE_LICENCE ( GPL2_OR_LATER );
 
11
 
 
12
#include <stdint.h>
 
13
#include <string.h>
 
14
#include <assert.h>
 
15
#include <ipxe/api.h>
 
16
#include <ipxe/hash_df.h>
 
17
#include <ipxe/sha256.h>
 
18
#include <config/entropy.h>
 
19
 
 
20
/**
 
21
 * Calculate static inline entropy API function name
 
22
 *
 
23
 * @v _prefix           Subsystem prefix
 
24
 * @v _api_func         API function
 
25
 * @ret _subsys_func    Subsystem API function
 
26
 */
 
27
#define ENTROPY_INLINE( _subsys, _api_func ) \
 
28
        SINGLE_API_INLINE ( ENTROPY_PREFIX_ ## _subsys, _api_func )
 
29
 
 
30
/**
 
31
 * Provide a entropy API implementation
 
32
 *
 
33
 * @v _prefix           Subsystem prefix
 
34
 * @v _api_func         API function
 
35
 * @v _func             Implementing function
 
36
 */
 
37
#define PROVIDE_ENTROPY( _subsys, _api_func, _func ) \
 
38
        PROVIDE_SINGLE_API ( ENTROPY_PREFIX_ ## _subsys, _api_func, _func )
 
39
 
 
40
/**
 
41
 * Provide a static inline entropy API implementation
 
42
 *
 
43
 * @v _prefix           Subsystem prefix
 
44
 * @v _api_func         API function
 
45
 */
 
46
#define PROVIDE_ENTROPY_INLINE( _subsys, _api_func ) \
 
47
        PROVIDE_SINGLE_API_INLINE ( ENTROPY_PREFIX_ ## _subsys, _api_func )
 
48
 
 
49
/** A noise sample */
 
50
typedef uint8_t noise_sample_t;
 
51
 
 
52
/** An entropy sample */
 
53
typedef uint8_t entropy_sample_t;
 
54
 
 
55
/* Include all architecture-independent entropy API headers */
 
56
#include <ipxe/null_entropy.h>
 
57
#include <ipxe/linux/linux_entropy.h>
 
58
 
 
59
/* Include all architecture-dependent entropy API headers */
 
60
#include <bits/entropy.h>
 
61
 
 
62
/**
 
63
 * Enable entropy gathering
 
64
 *
 
65
 * @ret rc              Return status code
 
66
 */
 
67
int entropy_enable ( void );
 
68
 
 
69
/**
 
70
 * Disable entropy gathering
 
71
 *
 
72
 */
 
73
void entropy_disable ( void );
 
74
 
 
75
/**
 
76
 * min-entropy per sample
 
77
 *
 
78
 * @ret min_entropy     min-entropy of each sample
 
79
 *
 
80
 * min-entropy is defined in ANS X9.82 Part 1-2006 Section 8.3 and in
 
81
 * NIST SP 800-90 Appendix C.3 as
 
82
 *
 
83
 *    H_min = -log2 ( p_max )
 
84
 *
 
85
 * where p_max is the probability of the most likely sample value.
 
86
 *
 
87
 * This must be a compile-time constant.
 
88
 */
 
89
double min_entropy_per_sample ( void );
 
90
 
 
91
/**
 
92
 * Get noise sample
 
93
 *
 
94
 * @ret noise           Noise sample
 
95
 * @ret rc              Return status code
 
96
 *
 
97
 * This is the GetNoise function defined in ANS X9.82 Part 2
 
98
 * (October 2011 Draft) Section 6.5.2.
 
99
 */
 
100
int get_noise ( noise_sample_t *noise );
 
101
 
 
102
extern int get_entropy_input_tmp ( unsigned int num_samples,
 
103
                                   uint8_t *tmp, size_t tmp_len );
 
104
 
 
105
/** Use SHA-256 as the underlying hash algorithm for Hash_df
 
106
 *
 
107
 * Hash_df using SHA-256 is an Approved algorithm in ANS X9.82.
 
108
 */
 
109
#define entropy_hash_df_algorithm sha256_algorithm
 
110
 
 
111
/** Underlying hash algorithm output length (in bytes) */
 
112
#define ENTROPY_HASH_DF_OUTLEN_BYTES SHA256_DIGEST_SIZE
 
113
 
 
114
/**
 
115
 * Obtain entropy input
 
116
 *
 
117
 * @v min_entropy_bits  Minimum amount of entropy, in bits
 
118
 * @v data              Data buffer
 
119
 * @v min_len           Minimum length of entropy input, in bytes
 
120
 * @v max_len           Maximum length of entropy input, in bytes
 
121
 * @ret len             Length of entropy input, in bytes, or negative error
 
122
 *
 
123
 * This is the implementation of the Get_entropy_input function (using
 
124
 * an entropy source as the source of entropy input and condensing
 
125
 * each entropy source output after each GetEntropy call) as defined
 
126
 * in ANS X9.82 Part 4 (April 2011 Draft) Section 13.3.4.2.
 
127
 *
 
128
 * To minimise code size, the number of samples required is calculated
 
129
 * at compilation time.
 
130
 */
 
131
static inline __attribute__ (( always_inline )) int
 
132
get_entropy_input ( unsigned int min_entropy_bits, void *data, size_t min_len,
 
133
                    size_t max_len ) {
 
134
        size_t tmp_len = ( ( ( min_entropy_bits * 2 ) + 7 ) / 8 );
 
135
        uint8_t tmp_buf[ tmp_len ];
 
136
        uint8_t *tmp = ( ( tmp_len > max_len ) ? tmp_buf : data );
 
137
        double min_samples;
 
138
        unsigned int num_samples;
 
139
        unsigned int n;
 
140
        int rc;
 
141
 
 
142
        /* Sanity checks */
 
143
        linker_assert ( ( min_entropy_per_sample() <=
 
144
                          ( 8 * sizeof ( noise_sample_t ) ) ),
 
145
                        min_entropy_per_sample_is_impossibly_high );
 
146
        linker_assert ( ( min_entropy_bits <= ( 8 * max_len ) ),
 
147
                        entropy_buffer_too_small );
 
148
 
 
149
        /* Round up minimum entropy to an integral number of bytes */
 
150
        min_entropy_bits = ( ( min_entropy_bits + 7 ) & ~7 );
 
151
 
 
152
        /* Calculate number of samples required to contain sufficient entropy */
 
153
        min_samples = ( ( min_entropy_bits * 1.0 ) / min_entropy_per_sample() );
 
154
 
 
155
        /* Round up to a whole number of samples.  We don't have the
 
156
         * ceil() function available, so do the rounding by hand.
 
157
         */
 
158
        num_samples = min_samples;
 
159
        if ( num_samples < min_samples )
 
160
                num_samples++;
 
161
        linker_assert ( ( num_samples >= min_samples ), rounding_error );
 
162
 
 
163
        /* Floating-point operations are not allowed in iPXE since we
 
164
         * never set up a suitable environment.  Abort the build
 
165
         * unless the calculated number of samples is a compile-time
 
166
         * constant.
 
167
         */
 
168
        linker_assert ( __builtin_constant_p ( num_samples ),
 
169
                        num_samples_not_constant );
 
170
 
 
171
        /* (Unnumbered).  The output length of the hash function shall
 
172
         * meet or exceed the security strength indicated by the
 
173
         * min_entropy parameter.
 
174
         */
 
175
        linker_assert ( ( ( 8 * ENTROPY_HASH_DF_OUTLEN_BYTES ) >=
 
176
                          min_entropy_bits ), hash_df_algorithm_too_weak );
 
177
 
 
178
        /* 1.  If ( min_length > max_length ), then return ( FAILURE, Null ) */
 
179
        linker_assert ( ( min_len <= max_len ), min_len_greater_than_max_len );
 
180
 
 
181
        /* 2.  n = 2 * min_entropy */
 
182
        n = ( 2 * min_entropy_bits );
 
183
 
 
184
        /* 3.  entropy_total = 0
 
185
         * 4.  tmp = a fixed n-bit value, such as 0^n
 
186
         * 5.  While ( entropy_total < min_entropy )
 
187
         *     5.1.  ( status, entropy_bitstring, assessed_entropy )
 
188
         *           = GetEntropy()
 
189
         *     5.2.  If status indicates an error, return ( status, Null )
 
190
         *     5.3.  nonce = MakeNextNonce()
 
191
         *     5.4.  tmp = tmp XOR df ( ( nonce || entropy_bitstring ), n )
 
192
         *     5.5.  entropy_total = entropy_total + assessed_entropy
 
193
         *
 
194
         * (The implementation of these steps is inside the function
 
195
         * get_entropy_input_tmp().)
 
196
         */
 
197
        linker_assert ( __builtin_constant_p ( tmp_len ),
 
198
                        tmp_len_not_constant );
 
199
        linker_assert ( ( n == ( 8 * tmp_len ) ), tmp_len_mismatch );
 
200
        if ( ( rc = get_entropy_input_tmp ( num_samples, tmp, tmp_len ) ) != 0 )
 
201
                return rc;
 
202
 
 
203
        /* 6.  If ( n < min_length ), then tmp = tmp || 0^(min_length-n)
 
204
         * 7.  If ( n > max_length ), then tmp = df ( tmp, max_length )
 
205
         * 8.  Return ( SUCCESS, tmp )
 
206
         */
 
207
        if ( tmp_len < min_len ) {
 
208
                /* (Data is already in-place.) */
 
209
                linker_assert ( ( data == tmp ), data_not_inplace );
 
210
                memset ( ( data + tmp_len ), 0, ( min_len - tmp_len ) );
 
211
                return min_len;
 
212
        } else if ( tmp_len > max_len ) {
 
213
                linker_assert ( ( tmp == tmp_buf ), data_inplace );
 
214
                hash_df ( &entropy_hash_df_algorithm, tmp, tmp_len,
 
215
                          data, max_len );
 
216
                return max_len;
 
217
        } else {
 
218
                /* (Data is already in-place.) */
 
219
                linker_assert ( ( data == tmp ), data_not_inplace );
 
220
                return tmp_len;
 
221
        }
 
222
}
 
223
 
 
224
#endif /* _IPXE_ENTROPY_H */