diff options
| author | Simon Rettberg | 2023-04-04 15:12:41 +0200 |
|---|---|---|
| committer | Simon Rettberg | 2023-04-04 15:12:41 +0200 |
| commit | 5ba496dce11d10198a0eae0c8440dccb256fbf32 (patch) | |
| tree | 549903f1dab893870335a6e4767a4530444d2e83 /src/crypto | |
| parent | [vesafb] Map Unicode characters to CP437 if possible (diff) | |
| parent | [tls] Handle fragmented handshake records (diff) | |
| download | ipxe-5ba496dce11d10198a0eae0c8440dccb256fbf32.tar.gz ipxe-5ba496dce11d10198a0eae0c8440dccb256fbf32.tar.xz ipxe-5ba496dce11d10198a0eae0c8440dccb256fbf32.zip | |
Merge branch 'master' into openslx
Diffstat (limited to 'src/crypto')
| -rw-r--r-- | src/crypto/aes.c | 20 | ||||
| -rw-r--r-- | src/crypto/arc4.c | 11 | ||||
| -rw-r--r-- | src/crypto/crypto_null.c | 70 | ||||
| -rw-r--r-- | src/crypto/entropy.c | 442 | ||||
| -rw-r--r-- | src/crypto/gcm.c | 535 | ||||
| -rw-r--r-- | src/crypto/mishmash/rsa_aes_cbc_sha1.c | 45 | ||||
| -rw-r--r-- | src/crypto/mishmash/rsa_aes_cbc_sha256.c | 44 | ||||
| -rw-r--r-- | src/crypto/mishmash/rsa_aes_gcm_sha256.c | 60 | ||||
| -rw-r--r-- | src/crypto/mishmash/rsa_aes_gcm_sha384.c | 60 | ||||
| -rw-r--r-- | src/crypto/null_entropy.c | 40 |
10 files changed, 1016 insertions, 311 deletions
diff --git a/src/crypto/aes.c b/src/crypto/aes.c index b9e206bfb..5200e7760 100644 --- a/src/crypto/aes.c +++ b/src/crypto/aes.c @@ -38,6 +38,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #include <ipxe/crypto.h> #include <ipxe/ecb.h> #include <ipxe/cbc.h> +#include <ipxe/gcm.h> #include <ipxe/aes.h> /** AES strides @@ -778,25 +779,18 @@ static int aes_setkey ( void *ctx, const void *key, size_t keylen ) { return 0; } -/** - * Set initialisation vector - * - * @v ctx Context - * @v iv Initialisation vector - */ -static void aes_setiv ( void *ctx __unused, const void *iv __unused ) { - /* Nothing to do */ -} - /** Basic AES algorithm */ struct cipher_algorithm aes_algorithm = { .name = "aes", .ctxsize = sizeof ( struct aes_context ), .blocksize = AES_BLOCKSIZE, + .alignsize = 0, + .authsize = 0, .setkey = aes_setkey, - .setiv = aes_setiv, + .setiv = cipher_null_setiv, .encrypt = aes_encrypt, .decrypt = aes_decrypt, + .auth = cipher_null_auth, }; /* AES in Electronic Codebook mode */ @@ -806,3 +800,7 @@ ECB_CIPHER ( aes_ecb, aes_ecb_algorithm, /* AES in Cipher Block Chaining mode */ CBC_CIPHER ( aes_cbc, aes_cbc_algorithm, aes_algorithm, struct aes_context, AES_BLOCKSIZE ); + +/* AES in Galois/Counter mode */ +GCM_CIPHER ( aes_gcm, aes_gcm_algorithm, + aes_algorithm, struct aes_context, AES_BLOCKSIZE ); diff --git a/src/crypto/arc4.c b/src/crypto/arc4.c index 91a732019..3b6adec19 100644 --- a/src/crypto/arc4.c +++ b/src/crypto/arc4.c @@ -96,12 +96,6 @@ static void arc4_xor ( void *ctxv, const void *srcv, void *dstv, ctx->j = j; } -static void arc4_setiv ( void *ctx __unused, const void *iv __unused ) -{ - /* ARC4 does not use a fixed-length IV */ -} - - /** * Perform ARC4 encryption or decryption, skipping initial keystream bytes * @@ -125,8 +119,11 @@ struct cipher_algorithm arc4_algorithm = { .name = "ARC4", .ctxsize = ARC4_CTX_SIZE, .blocksize = 1, + .alignsize = 1, + .authsize = 0, .setkey = arc4_setkey, - .setiv = arc4_setiv, + .setiv = cipher_null_setiv, .encrypt = arc4_xor, .decrypt = arc4_xor, + .auth = cipher_null_auth, }; diff --git a/src/crypto/crypto_null.c b/src/crypto/crypto_null.c index 15a1c538b..0ad463c3e 100644 --- a/src/crypto/crypto_null.c +++ b/src/crypto/crypto_null.c @@ -32,16 +32,16 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #include <string.h> #include <ipxe/crypto.h> -static void digest_null_init ( void *ctx __unused ) { +void digest_null_init ( void *ctx __unused ) { /* Do nothing */ } -static void digest_null_update ( void *ctx __unused, const void *src __unused, - size_t len __unused ) { +void digest_null_update ( void *ctx __unused, const void *src __unused, + size_t len __unused ) { /* Do nothing */ } -static void digest_null_final ( void *ctx __unused, void *out __unused ) { +void digest_null_final ( void *ctx __unused, void *out __unused ) { /* Do nothing */ } @@ -55,76 +55,80 @@ struct digest_algorithm digest_null = { .final = digest_null_final, }; -static int cipher_null_setkey ( void *ctx __unused, const void *key __unused, - size_t keylen __unused ) { +int cipher_null_setkey ( void *ctx __unused, const void *key __unused, + size_t keylen __unused ) { /* Do nothing */ return 0; } -static void cipher_null_setiv ( void *ctx __unused, - const void *iv __unused ) { +void cipher_null_setiv ( void *ctx __unused, const void *iv __unused, + size_t ivlen __unused ) { /* Do nothing */ } -static void cipher_null_encrypt ( void *ctx __unused, const void *src, - void *dst, size_t len ) { +void cipher_null_encrypt ( void *ctx __unused, const void *src, void *dst, + size_t len ) { memcpy ( dst, src, len ); } -static void cipher_null_decrypt ( void *ctx __unused, const void *src, - void *dst, size_t len ) { +void cipher_null_decrypt ( void *ctx __unused, const void *src, void *dst, + size_t len ) { memcpy ( dst, src, len ); } +void cipher_null_auth ( void *ctx __unused, void *auth __unused ) { + /* Do nothing */ +} + struct cipher_algorithm cipher_null = { .name = "null", .ctxsize = 0, .blocksize = 1, + .alignsize = 1, + .authsize = 0, .setkey = cipher_null_setkey, .setiv = cipher_null_setiv, .encrypt = cipher_null_encrypt, .decrypt = cipher_null_decrypt, + .auth = cipher_null_auth, }; -static int pubkey_null_init ( void *ctx __unused, const void *key __unused, - size_t key_len __unused ) { +int pubkey_null_init ( void *ctx __unused, const void *key __unused, + size_t key_len __unused ) { return 0; } -static size_t pubkey_null_max_len ( void *ctx __unused ) { +size_t pubkey_null_max_len ( void *ctx __unused ) { return 0; } -static int pubkey_null_encrypt ( void *ctx __unused, - const void *plaintext __unused, - size_t plaintext_len __unused, - void *ciphertext __unused ) { +int pubkey_null_encrypt ( void *ctx __unused, const void *plaintext __unused, + size_t plaintext_len __unused, + void *ciphertext __unused ) { return 0; } -static int pubkey_null_decrypt ( void *ctx __unused, - const void *ciphertext __unused, - size_t ciphertext_len __unused, - void *plaintext __unused ) { +int pubkey_null_decrypt ( void *ctx __unused, const void *ciphertext __unused, + size_t ciphertext_len __unused, + void *plaintext __unused ) { return 0; } -static int pubkey_null_sign ( void *ctx __unused, - struct digest_algorithm *digest __unused, - const void *value __unused, - void *signature __unused ) { +int pubkey_null_sign ( void *ctx __unused, + struct digest_algorithm *digest __unused, + const void *value __unused, void *signature __unused ) { return 0; } -static int pubkey_null_verify ( void *ctx __unused, - struct digest_algorithm *digest __unused, - const void *value __unused, - const void *signature __unused , - size_t signature_len __unused ) { +int pubkey_null_verify ( void *ctx __unused, + struct digest_algorithm *digest __unused, + const void *value __unused, + const void *signature __unused , + size_t signature_len __unused ) { return 0; } -static void pubkey_null_final ( void *ctx __unused ) { +void pubkey_null_final ( void *ctx __unused ) { /* Do nothing */ } diff --git a/src/crypto/entropy.c b/src/crypto/entropy.c index ced6fd921..419007159 100644 --- a/src/crypto/entropy.c +++ b/src/crypto/entropy.c @@ -51,59 +51,33 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); __einfo_uniqify ( EINFO_EPIPE, 0x02, "Adaptive proportion test failed" ) /** - * Calculate cutoff value for the repetition count test + * Initialise repetition count test * - * @ret cutoff Cutoff value - * - * This is the cutoff value for the Repetition Count Test defined in - * ANS X9.82 Part 2 (October 2011 Draft) Section 8.5.2.1.2. + * @v source Entropy source */ -static inline __attribute__ (( always_inline )) unsigned int -repetition_count_cutoff ( void ) { - double max_repetitions; - unsigned int cutoff; - - /* The cutoff formula for the repetition test is: - * - * C = ( 1 + ( -log2(W) / H_min ) ) - * - * where W is set at 2^(-30) (in ANS X9.82 Part 2 (October - * 2011 Draft) Section 8.5.2.1.3.1). - */ - max_repetitions = ( 1 + ( MIN_ENTROPY ( 30 ) / - min_entropy_per_sample() ) ); - - /* Round up to a whole number of repetitions. We don't have - * the ceil() function available, so do the rounding by hand. - */ - cutoff = max_repetitions; - if ( cutoff < max_repetitions ) - cutoff++; - linker_assert ( ( cutoff >= max_repetitions ), rounding_error ); - - /* Floating-point operations are not allowed in iPXE since we - * never set up a suitable environment. Abort the build - * unless the calculated number of repetitions is a - * compile-time constant. - */ - linker_assert ( __builtin_constant_p ( cutoff ), - repetition_count_cutoff_not_constant ); +static void repetition_count_test_init ( struct entropy_source *source ) { + struct entropy_repetition_count_test *test = + &source->repetition_count_test; - return cutoff; + /* Sanity checks */ + assert ( test->repetition_count == 0 ); + assert ( test->cutoff > 0 ); } /** * Perform repetition count test * + * @v source Entropy source * @v sample Noise sample * @ret rc Return status code * * This is the Repetition Count Test defined in ANS X9.82 Part 2 * (October 2011 Draft) Section 8.5.2.1.2. */ -static int repetition_count_test ( noise_sample_t sample ) { - static noise_sample_t most_recent_sample; - static unsigned int repetition_count = 0; +static int repetition_count_test ( struct entropy_source *source, + noise_sample_t sample ) { + struct entropy_repetition_count_test *test = + &source->repetition_count_test; /* A = the most recently seen sample value * B = the number of times that value A has been seen in a row @@ -116,158 +90,71 @@ static int repetition_count_test ( noise_sample_t sample ) { * the initial value of most_recent_sample is treated as being * undefined.) */ - if ( ( sample == most_recent_sample ) && ( repetition_count > 0 ) ) { + if ( ( sample == test->most_recent_sample ) && + ( test->repetition_count > 0 ) ) { /* a) If the new sample = A, then B is incremented by one. */ - repetition_count++; + test->repetition_count++; /* i. If B >= C, then an error condition is raised * due to a failure of the test */ - if ( repetition_count >= repetition_count_cutoff() ) + if ( test->repetition_count >= test->cutoff ) { + DBGC ( source, "ENTROPY %s excessively repeated " + "value %d (%d/%d)\n", source->name, sample, + test->repetition_count, test->cutoff ); return -EPIPE_REPETITION_COUNT_TEST; + } } else { /* b) Else: * i. A = new sample */ - most_recent_sample = sample; + test->most_recent_sample = sample; /* ii. B = 1 */ - repetition_count = 1; + test->repetition_count = 1; } return 0; } /** - * Window size for the adaptive proportion test + * Initialise adaptive proportion test * - * ANS X9.82 Part 2 (October 2011 Draft) Section 8.5.2.1.3.1.1 allows - * five possible window sizes: 16, 64, 256, 4096 and 65536. - * - * We expect to generate relatively few (<256) entropy samples during - * a typical iPXE run; the use of a large window size would mean that - * the test would never complete a single cycle. We use a window size - * of 64, which is the smallest window size that permits values of - * H_min down to one bit per sample. + * @v source Entropy source */ -#define ADAPTIVE_PROPORTION_WINDOW_SIZE 64 +static void adaptive_proportion_test_init ( struct entropy_source *source ) { + struct entropy_adaptive_proportion_test *test = + &source->adaptive_proportion_test; -/** - * Combine adaptive proportion test window size and min-entropy - * - * @v n N (window size) - * @v h H (min-entropy) - * @ret n_h (N,H) combined value - */ -#define APC_N_H( n, h ) ( ( (n) << 8 ) | (h) ) + /* Sanity checks */ + assert ( test->sample_count == 0 ); + assert ( test->repetition_count == 0 ); + assert ( test->cutoff > 0 ); -/** - * Define a row of the adaptive proportion cutoff table - * - * @v h H (min-entropy) - * @v c16 Cutoff for N=16 - * @v c64 Cutoff for N=64 - * @v c256 Cutoff for N=256 - * @v c4096 Cutoff for N=4096 - * @v c65536 Cutoff for N=65536 - */ -#define APC_TABLE_ROW( h, c16, c64, c256, c4096, c65536) \ - case APC_N_H ( 16, h ) : return c16; \ - case APC_N_H ( 64, h ) : return c64; \ - case APC_N_H ( 256, h ) : return c256; \ - case APC_N_H ( 4096, h ) : return c4096; \ - case APC_N_H ( 65536, h ) : return c65536; - -/** Value used to represent "N/A" in adaptive proportion cutoff table */ -#define APC_NA 0 - -/** - * Look up value in adaptive proportion test cutoff table - * - * @v n N (window size) - * @v h H (min-entropy) - * @ret cutoff Cutoff - * - * This is the table of cutoff values defined in ANS X9.82 Part 2 - * (October 2011 Draft) Section 8.5.2.1.3.1.2. - */ -static inline __attribute__ (( always_inline )) unsigned int -adaptive_proportion_cutoff_lookup ( unsigned int n, unsigned int h ) { - switch ( APC_N_H ( n, h ) ) { - APC_TABLE_ROW ( 1, APC_NA, 51, 168, 2240, 33537 ); - APC_TABLE_ROW ( 2, APC_NA, 35, 100, 1193, 17053 ); - APC_TABLE_ROW ( 3, 10, 24, 61, 643, 8705 ); - APC_TABLE_ROW ( 4, 8, 16, 38, 354, 4473 ); - APC_TABLE_ROW ( 5, 6, 12, 25, 200, 2321 ); - APC_TABLE_ROW ( 6, 5, 9, 17, 117, 1220 ); - APC_TABLE_ROW ( 7, 4, 7, 15, 71, 653 ); - APC_TABLE_ROW ( 8, 4, 5, 9, 45, 358 ); - APC_TABLE_ROW ( 9, 3, 4, 7, 30, 202 ); - APC_TABLE_ROW ( 10, 3, 4, 5, 21, 118 ); - APC_TABLE_ROW ( 11, 2, 3, 4, 15, 71 ); - APC_TABLE_ROW ( 12, 2, 3, 4, 11, 45 ); - APC_TABLE_ROW ( 13, 2, 2, 3, 9, 30 ); - APC_TABLE_ROW ( 14, 2, 2, 3, 7, 21 ); - APC_TABLE_ROW ( 15, 1, 2, 2, 6, 15 ); - APC_TABLE_ROW ( 16, 1, 2, 2, 5, 11 ); - APC_TABLE_ROW ( 17, 1, 1, 2, 4, 9 ); - APC_TABLE_ROW ( 18, 1, 1, 2, 4, 7 ); - APC_TABLE_ROW ( 19, 1, 1, 1, 3, 6 ); - APC_TABLE_ROW ( 20, 1, 1, 1, 3, 5 ); - default: - return APC_NA; - } -} - -/** - * Calculate cutoff value for the adaptive proportion test - * - * @ret cutoff Cutoff value - * - * This is the cutoff value for the Adaptive Proportion Test defined - * in ANS X9.82 Part 2 (October 2011 Draft) Section 8.5.2.1.3.1.2. - */ -static inline __attribute__ (( always_inline )) unsigned int -adaptive_proportion_cutoff ( void ) { - unsigned int h; - unsigned int n; - unsigned int cutoff; - - /* Look up cutoff value in cutoff table */ - n = ADAPTIVE_PROPORTION_WINDOW_SIZE; - h = ( min_entropy_per_sample() / MIN_ENTROPY_SCALE ); - cutoff = adaptive_proportion_cutoff_lookup ( n, h ); - - /* Fail unless cutoff value is a build-time constant */ - linker_assert ( __builtin_constant_p ( cutoff ), - adaptive_proportion_cutoff_not_constant ); - - /* Fail if cutoff value is N/A */ - linker_assert ( ( cutoff != APC_NA ), - adaptive_proportion_cutoff_not_applicable ); - - return cutoff; + /* Ensure that a new test run starts immediately */ + test->sample_count = ADAPTIVE_PROPORTION_WINDOW_SIZE; } /** * Perform adaptive proportion test * + * @v source Entropy source * @v sample Noise sample * @ret rc Return status code * * This is the Adaptive Proportion Test for the Most Common Value * defined in ANS X9.82 Part 2 (October 2011 Draft) Section 8.5.2.1.3. */ -static int adaptive_proportion_test ( noise_sample_t sample ) { - static noise_sample_t current_counted_sample; - static unsigned int sample_count = ADAPTIVE_PROPORTION_WINDOW_SIZE; - static unsigned int repetition_count; +static int adaptive_proportion_test ( struct entropy_source *source, + noise_sample_t sample ) { + struct entropy_adaptive_proportion_test *test = + &source->adaptive_proportion_test; /* A = the sample value currently being counted - * B = the number of samples examined in this run of the test so far + * S = the number of samples examined in this run of the test so far * N = the total number of samples that must be observed in * one run of the test, also known as the "window size" of * the test @@ -284,37 +171,41 @@ static int adaptive_proportion_test ( noise_sample_t sample ) { */ /* 2. If S = N, then a new run of the test begins: */ - if ( sample_count == ADAPTIVE_PROPORTION_WINDOW_SIZE ) { + if ( test->sample_count == ADAPTIVE_PROPORTION_WINDOW_SIZE ) { /* a. A = the current sample */ - current_counted_sample = sample; + test->current_counted_sample = sample; /* b. S = 0 */ - sample_count = 0; + test->sample_count = 0; /* c. B = 0 */ - repetition_count = 0; + test->repetition_count = 0; } else { /* Else: (the test is already running) * a. S = S + 1 */ - sample_count++; + test->sample_count++; /* b. If A = the current sample, then: */ - if ( sample == current_counted_sample ) { + if ( sample == test->current_counted_sample ) { /* i. B = B + 1 */ - repetition_count++; + test->repetition_count++; /* ii. If S (sic) > C then raise an error * condition, because the test has * detected a failure */ - if ( repetition_count > adaptive_proportion_cutoff() ) + if ( test->repetition_count > test->cutoff ) { + DBGC ( source, "ENTROPY %s excessively " + "repeated value %d (%d/%d)\n", + source->name, sample, + test->repetition_count, test->cutoff ); return -EPIPE_ADAPTIVE_PROPORTION_TEST; - + } } } @@ -324,62 +215,180 @@ static int adaptive_proportion_test ( noise_sample_t sample ) { /** * Get entropy sample * + * @v source Entropy source * @ret entropy Entropy sample * @ret rc Return status code * * This is the GetEntropy function defined in ANS X9.82 Part 2 * (October 2011 Draft) Section 6.5.1. */ -static int get_entropy ( entropy_sample_t *entropy ) { - static int rc = 0; +static int get_entropy ( struct entropy_source *source, + entropy_sample_t *entropy ) { noise_sample_t noise; + int rc; /* Any failure is permanent */ - if ( rc != 0 ) - return rc; + if ( ( rc = source->rc ) != 0 ) + goto err_broken; /* Get noise sample */ - if ( ( rc = get_noise ( &noise ) ) != 0 ) - return rc; + if ( ( rc = get_noise ( source, &noise ) ) != 0 ) + goto err_get_noise; /* Perform Repetition Count Test and Adaptive Proportion Test * as mandated by ANS X9.82 Part 2 (October 2011 Draft) * Section 8.5.2.1.1. */ - if ( ( rc = repetition_count_test ( noise ) ) != 0 ) - return rc; - if ( ( rc = adaptive_proportion_test ( noise ) ) != 0 ) - return rc; + if ( ( rc = repetition_count_test ( source, noise ) ) != 0 ) + goto err_repetition_count_test; + if ( ( rc = adaptive_proportion_test ( source, noise ) ) != 0 ) + goto err_adaptive_proportion_test; /* We do not use any optional conditioning component */ *entropy = noise; return 0; + + err_adaptive_proportion_test: + err_repetition_count_test: + err_get_noise: + source->rc = rc; + err_broken: + return rc; } /** - * Calculate number of samples required for startup tests + * Initialise startup test * - * @ret num_samples Number of samples required + * @v source Entropy source + */ +static void startup_test_init ( struct entropy_source *source ) { + struct entropy_startup_test *test = &source->startup_test; + + /* Sanity check */ + assert ( test->tested == 0 ); + assert ( test->count > 0 ); +} + +/** + * Perform startup test * - * ANS X9.82 Part 2 (October 2011 Draft) Section 8.5.2.1.5 requires - * that at least one full cycle of the continuous tests must be - * performed at start-up. + * @v source Entropy source + * @ret rc Return status code */ -static inline __attribute__ (( always_inline )) unsigned int -startup_test_count ( void ) { - unsigned int num_samples; +static int startup_test ( struct entropy_source *source ) { + struct entropy_startup_test *test = &source->startup_test; + entropy_sample_t sample; + int rc; - /* At least max(N,C) samples shall be generated by the noise - * source for start-up testing. - */ - num_samples = repetition_count_cutoff(); - if ( num_samples < adaptive_proportion_cutoff() ) - num_samples = adaptive_proportion_cutoff(); - linker_assert ( __builtin_constant_p ( num_samples ), - startup_test_count_not_constant ); + /* Perform mandatory number of startup tests */ + for ( ; test->tested < test->count ; test->tested++ ) { + if ( ( rc = get_entropy ( source, &sample ) ) != 0 ) { + DBGC ( source, "ENTROPY %s failed: %s\n", + source->name, strerror ( rc ) ); + return rc; + } + } - return num_samples; + return 0; +} + +/** + * Enable entropy gathering + * + * @v source Entropy source + * @ret rc Return status code + */ +int entropy_enable ( struct entropy_source *source ) { + int rc; + + /* Refuse to enable a previously failed source */ + if ( ( rc = source->rc ) != 0 ) + return rc; + + /* Enable entropy source */ + if ( ( rc = source->enable() ) != 0 ) { + DBGC ( source, "ENTROPY %s could not enable: %s\n", + source->name, strerror ( rc ) ); + source->rc = rc; + return rc; + } + + /* Sanity check */ + assert ( source->min_entropy_per_sample > 0 ); + + /* Initialise test state if this source has not previously been used */ + if ( source->startup_test.tested == 0 ) { + repetition_count_test_init ( source ); + adaptive_proportion_test_init ( source ); + startup_test_init ( source ); + } + + DBGC ( source, "ENTROPY %s enabled\n", source->name ); + return 0; +} + +/** + * Enable and test entropy source + * + * @v source Entropy source + * @ret rc Return status code + */ +static int entropy_enable_and_test ( struct entropy_source *source ) { + int rc; + + /* Enable source */ + if ( ( rc = entropy_enable ( source ) ) != 0 ) + goto err_enable; + + /* Test source */ + if ( ( rc = startup_test ( source ) ) != 0 ) + goto err_test; + + DBGC ( source, "ENTROPY %s passed %d startup tests\n", + source->name, source->startup_test.count ); + return 0; + + err_test: + entropy_disable ( source ); + err_enable: + assert ( source->rc == rc ); + return rc; +} + +/** + * Enable first working entropy source + * + * @v source Entropy source to fill in + * @ret rc Return status code + */ +static int entropy_enable_working ( struct entropy_source **source ) { + int rc; + + /* Find the first working source */ + rc = -ENOENT; + for_each_table_entry ( *source, ENTROPY_SOURCES ) { + if ( ( rc = entropy_enable_and_test ( *source ) ) == 0 ) + return 0; + } + + DBGC ( *source, "ENTROPY has no working sources: %s\n", + strerror ( rc ) ); + return rc; +} + +/** + * Disable entropy gathering + * + * @v source Entropy source + */ +void entropy_disable ( struct entropy_source *source ) { + + /* Disable entropy gathering, if applicable */ + if ( source->disable ) + source->disable(); + + DBGC ( source, "ENTROPY %s disabled\n", source->name ); } /** @@ -402,7 +411,7 @@ static uint32_t make_next_nonce ( void ) { /** * Obtain entropy input temporary buffer * - * @v num_samples Number of entropy samples + * @v min_entropy Min-entropy required * @v tmp Temporary buffer * @v tmp_len Length of temporary buffer * @ret rc Return status code @@ -412,47 +421,41 @@ static uint32_t make_next_nonce ( void ) { * and condensing each entropy source output after each GetEntropy * call) as defined in ANS X9.82 Part 4 (April 2011 Draft) Section * 13.3.4.2. - * - * To minimise code size, the number of samples required is calculated - * at compilation time. */ -int get_entropy_input_tmp ( unsigned int num_samples, uint8_t *tmp, +int get_entropy_input_tmp ( min_entropy_t min_entropy, uint8_t *tmp, size_t tmp_len ) { - static unsigned int startup_tested = 0; + struct entropy_source *source; struct { uint32_t nonce; entropy_sample_t sample; } __attribute__ (( packed )) data;; uint8_t df_buf[tmp_len]; + min_entropy_t entropy_total; + unsigned int num_samples; unsigned int i; int rc; /* Enable entropy gathering */ - if ( ( rc = entropy_enable() ) != 0 ) - return rc; + if ( ( rc = entropy_enable_working ( &source ) ) != 0 ) + goto err_enable_working; - /* Perform mandatory startup tests, if not yet performed */ - for ( ; startup_tested < startup_test_count() ; startup_tested++ ) { - if ( ( rc = get_entropy ( &data.sample ) ) != 0 ) - goto err_get_entropy; - } + /* Sanity checks */ + assert ( source->startup_test.count > 0 ); + assert ( source->startup_test.tested >= source->startup_test.count ); - /* 3. entropy_total = 0 - * - * (Nothing to do; the number of entropy samples required has - * already been precalculated.) - */ + /* 3. entropy_total = 0 */ + entropy_total = MIN_ENTROPY ( 0 ); /* 4. tmp = a fixed n-bit value, such as 0^n */ memset ( tmp, 0, tmp_len ); /* 5. While ( entropy_total < min_entropy ) */ - while ( num_samples-- ) { + for ( num_samples = 0 ; entropy_total < min_entropy ; num_samples++ ) { /* 5.1. ( status, entropy_bitstring, assessed_entropy ) * = GetEntropy() * 5.2. If status indicates an error, return ( status, Null ) */ - if ( ( rc = get_entropy ( &data.sample ) ) != 0 ) + if ( ( rc = get_entropy ( source, &data.sample ) ) != 0 ) goto err_get_entropy; /* 5.3. nonce = MakeNextNonce() */ @@ -466,19 +469,26 @@ int get_entropy_input_tmp ( unsigned int num_samples, uint8_t *tmp, for ( i = 0 ; i < tmp_len ; i++ ) tmp[i] ^= df_buf[i]; - /* 5.5. entropy_total = entropy_total + assessed_entropy - * - * (Nothing to do; the number of entropy samples - * required has already been precalculated.) - */ + /* 5.5. entropy_total = entropy_total + assessed_entropy */ + entropy_total += source->min_entropy_per_sample; } /* Disable entropy gathering */ - entropy_disable(); + entropy_disable ( source ); + DBGC ( source, "ENTROPY %s gathered %d bits in %d samples\n", + source->name, ( min_entropy / MIN_ENTROPY_SCALE ), num_samples ); return 0; err_get_entropy: - entropy_disable(); + entropy_disable ( source ); + assert ( source->rc == rc ); + err_enable_working: return rc; } + +/* Drag in objects via entropy_enable */ +REQUIRING_SYMBOL ( entropy_enable ); + +/* Drag in entropy configuration */ +REQUIRE_OBJECT ( config_entropy ); diff --git a/src/crypto/gcm.c b/src/crypto/gcm.c new file mode 100644 index 000000000..9d8bae824 --- /dev/null +++ b/src/crypto/gcm.c @@ -0,0 +1,535 @@ +/* + * Copyright (C) 2022 Michael Brown <mbrown@fensystems.co.uk>. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + * + * You can also choose to distribute this program under the terms of + * the Unmodified Binary Distribution Licence (as given in the file + * COPYING.UBDL), provided that you have satisfied its requirements. + */ + +FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); + +/** @file + * + * Galois/Counter Mode (GCM) + * + * The GCM algorithm is specified in + * + * https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38d.pdf + * https://csrc.nist.rip/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/gcm-spec.pdf + * + */ + +#include <stdint.h> +#include <string.h> +#include <byteswap.h> +#include <ipxe/crypto.h> +#include <ipxe/gcm.h> + +/** + * Perform encryption + * + * This value is chosen to allow for ANDing with a fragment length. + */ +#define GCM_FL_ENCRYPT 0x00ff + +/** + * Calculate hash over an initialisation vector value + * + * The hash calculation for a non 96-bit initialisation vector is + * identical to the calculation used for additional data, except that + * the non-additional data length counter is used. + */ +#define GCM_FL_IV 0x0100 + +/** + * GCM field polynomial + * + * GCM treats 128-bit blocks as polynomials in GF(2^128) with the + * field polynomial f(x) = 1 + x + x^2 + x^7 + x^128. + * + * In a somewhat bloody-minded interpretation of "big-endian", the + * constant term (with degree zero) is arbitrarily placed in the + * leftmost bit of the big-endian binary representation (i.e. the most + * significant bit of byte 0), thereby failing to correspond to the + * bit ordering in any CPU architecture in existence. This + * necessitates some wholly gratuitous byte reversals when + * constructing the multiplication tables, since all CPUs will treat + * bit 0 as being the least significant bit within a byte. + * + * The field polynomial maps to the 128-bit constant + * 0xe1000000000000000000000000000000 (with the x^128 term outside the + * 128-bit range), and can therefore be treated as a single-byte + * value. + */ +#define GCM_POLY 0xe1 + +/** + * Hash key for which multiplication tables are cached + * + * GCM operates much more efficiently with a cached multiplication + * table, which costs 4kB per hash key. Since this exceeds the + * available stack space, we place a single 4kB cache in .bss and + * recalculate the cached values as required. In the common case of a + * single HTTPS connection being used to download a (relatively) large + * file, the same key will be used repeatedly for almost all GCM + * operations, and so the overhead of recalculation is negligible. + */ +static const union gcm_block *gcm_cached_key; + +/** + * Cached multiplication table (M0) for Shoup's method + * + * Each entry within this table represents the result of multiplying + * the cached hash key by an arbitrary 8-bit polynomial. + */ +static union gcm_block gcm_cached_mult[256]; + +/** + * Cached reduction table (R) for Shoup's method + * + * Each entry within this table represents the result of multiplying + * the fixed polynomial x^128 by an arbitrary 8-bit polynomial. Only + * the leftmost 16 bits are stored, since all other bits within the + * result will always be zero. + */ +static uint16_t gcm_cached_reduce[256]; + +/** + * Reverse bits in a byte + * + * @v byte Byte + * @ret etyb Bit-reversed byte + */ +static inline __attribute__ (( always_inline )) uint8_t +gcm_reverse ( const uint8_t byte ) { + uint8_t etyb = etyb; + uint8_t mask; + + for ( mask = 1 ; mask ; mask <<= 1 ) { + etyb <<= 1; + if ( byte & mask ) + etyb |= 1; + } + return etyb; +} + +/** + * Update GCM counter + * + * @v ctr Counter + * @v delta Amount to add to counter + */ +static inline __attribute__ (( always_inline )) void +gcm_count ( union gcm_block *ctr, uint32_t delta ) { + uint32_t *value = &ctr->ctr.value; + + /* Update counter modulo 2^32 */ + *value = cpu_to_be32 ( be32_to_cpu ( *value ) + delta ); +} + +/** + * XOR partial data block + * + * @v src1 Source buffer 1 + * @v src2 Source buffer 2 + * @v dst Destination buffer + * @v len Length + */ +static inline void gcm_xor ( const void *src1, const void *src2, void *dst, + size_t len ) { + uint8_t *dst_bytes = dst; + const uint8_t *src1_bytes = src1; + const uint8_t *src2_bytes = src2; + + /* XOR one byte at a time */ + while ( len-- ) + *(dst_bytes++) = ( *(src1_bytes++) ^ *(src2_bytes++) ); +} + +/** + * XOR whole data block in situ + * + * @v src Source block + * @v dst Destination block + */ +static inline void gcm_xor_block ( const union gcm_block *src, + union gcm_block *dst ) { + + /* XOR whole dwords */ + dst->dword[0] ^= src->dword[0]; + dst->dword[1] ^= src->dword[1]; + dst->dword[2] ^= src->dword[2]; + dst->dword[3] ^= src->dword[3]; +} + +/** + * Multiply polynomial by (x) + * + * @v mult Multiplicand + * @v res Result + */ +static void gcm_multiply_x ( const union gcm_block *mult, + union gcm_block *res ) { + unsigned int i; + uint8_t byte; + uint8_t carry; + + /* Multiply by (x) by shifting all bits rightward */ + for ( i = 0, carry = 0 ; i < sizeof ( res->byte ) ; i++ ) { + byte = mult->byte[i]; + res->byte[i] = ( ( carry << 7 ) | ( byte >> 1 ) ); + carry = ( byte & 0x01 ); + } + + /* If result overflows, reduce modulo the field polynomial */ + if ( carry ) + res->byte[0] ^= GCM_POLY; +} + +/** + * Construct cached tables + * + * @v key Hash key + * @v context Context + */ +static void gcm_cache ( const union gcm_block *key ) { + union gcm_block *mult; + uint16_t reduce; + unsigned int this; + unsigned int other; + unsigned int i; + + /* Calculate M0[1..255] and R[1..255] + * + * The R[] values are independent of the key, but the overhead + * of recalculating them here is negligible and saves on + * overall code size since the calculations are related. + */ + for ( i = 1 ; i < 256 ; i++ ) { + + /* Reverse bit order to compensate for poor life choices */ + this = gcm_reverse ( i ); + + /* Construct entries */ + mult = &gcm_cached_mult[this]; + if ( this & 0x80 ) { + + /* Odd number: entry[i] = entry[i - 1] + poly */ + other = ( this & 0x7f ); /* bit-reversed (i - 1) */ + gcm_xor ( key, &gcm_cached_mult[other], mult, + sizeof ( *mult ) ); + reduce = gcm_cached_reduce[other]; + reduce ^= be16_to_cpu ( GCM_POLY << 8 ); + gcm_cached_reduce[this] = reduce; + + } else { + + /* Even number: entry[i] = entry[i/2] * (x) */ + other = ( this << 1 ); /* bit-reversed (i / 2) */ + gcm_multiply_x ( &gcm_cached_mult[other], mult ); + reduce = be16_to_cpu ( gcm_cached_reduce[other] ); + reduce >>= 1; + gcm_cached_reduce[this] = cpu_to_be16 ( reduce ); + } + } + + /* Record cached key */ + gcm_cached_key = key; +} + +/** + * Multiply polynomial by (x^8) in situ + * + * @v poly Multiplicand and result + */ +static void gcm_multiply_x_8 ( union gcm_block *poly ) { + uint8_t *byte; + uint8_t msb; + + /* Reduction table must already have been calculated */ + assert ( gcm_cached_key != NULL ); + + /* Record most significant byte */ + byte = &poly->byte[ sizeof ( poly->byte ) - 1 ]; + msb = *byte; + + /* Multiply least significant bytes by shifting */ + for ( ; byte > &poly->byte[0] ; byte-- ) + *byte = *( byte - 1 ); + *byte = 0; + + /* Multiply most significant byte via reduction table */ + poly->word[0] ^= gcm_cached_reduce[msb]; +} + +/** + * Multiply polynomial by hash key in situ + * + * @v key Hash key + * @v poly Multiplicand and result + */ +static void gcm_multiply_key ( const union gcm_block *key, + union gcm_block *poly ) { + union gcm_block res; + uint8_t *byte; + + /* Construct tables, if necessary */ + if ( gcm_cached_key != key ) + gcm_cache ( key ); + + /* Multiply using Shoup's algorithm */ + byte = &poly->byte[ sizeof ( poly->byte ) - 1 ]; + memcpy ( &res, &gcm_cached_mult[ *byte ], sizeof ( res ) ); + for ( byte-- ; byte >= &poly->byte[0] ; byte-- ) { + gcm_multiply_x_8 ( &res ); + gcm_xor_block ( &gcm_cached_mult[ *byte ], &res ); + } + + /* Overwrite result */ + memcpy ( poly, &res, sizeof ( *poly ) ); +} + +/** + * Encrypt/decrypt/authenticate data + * + * @v context Context + * @v src Input data + * @v dst Output data, or NULL to process additional data + * @v len Length of data + * @v flags Operation flags + */ +static void gcm_process ( struct gcm_context *context, const void *src, + void *dst, size_t len, unsigned int flags ) { + union gcm_block tmp; + uint64_t *total; + size_t frag_len; + unsigned int block; + + /* Calculate block number (for debugging) */ + block = ( ( ( context->len.len.add + 8 * sizeof ( tmp ) - 1 ) / + ( 8 * sizeof ( tmp ) ) ) + + ( ( context->len.len.data + 8 * sizeof ( tmp ) - 1 ) / + ( 8 * sizeof ( tmp ) ) ) + 1 ); + + /* Update total length (in bits) */ + total = ( ( dst || ( flags & GCM_FL_IV ) ) ? + &context->len.len.data : &context->len.len.add ); + *total += ( len * 8 ); + + /* Process data */ + for ( ; len ; src += frag_len, len -= frag_len, block++ ) { + + /* Calculate fragment length */ + frag_len = len; + if ( frag_len > sizeof ( tmp ) ) + frag_len = sizeof ( tmp ); + + /* Update hash with input data */ + gcm_xor ( src, &context->hash, &context->hash, frag_len ); + + /* Encrypt/decrypt block, if applicable */ + if ( dst ) { + + /* Increment counter */ + gcm_count ( &context->ctr, 1 ); + + /* Encrypt counter */ + DBGC2 ( context, "GCM %p Y[%d]:\n", context, block ); + DBGC2_HDA ( context, 0, &context->ctr, + sizeof ( context->ctr ) ); + cipher_encrypt ( context->raw_cipher, &context->raw_ctx, + &context->ctr, &tmp, sizeof ( tmp ) ); + DBGC2 ( context, "GCM %p E(K,Y[%d]):\n", + context, block ); + DBGC2_HDA ( context, 0, &tmp, sizeof ( tmp ) ); + + /* Encrypt/decrypt data */ + gcm_xor ( src, &tmp, dst, frag_len ); + dst += frag_len; + + /* Update hash with encrypted data, if applicable */ + gcm_xor ( &tmp, &context->hash, &context->hash, + ( frag_len & flags ) ); + } + + /* Update hash */ + gcm_multiply_key ( &context->key, &context->hash ); + DBGC2 ( context, "GCM %p X[%d]:\n", context, block ); + DBGC2_HDA ( context, 0, &context->hash, + sizeof ( context->hash ) ); + } +} + +/** + * Construct hash + * + * @v context Context + * @v hash Hash to fill in + */ +static void gcm_hash ( struct gcm_context *context, union gcm_block *hash ) { + + /* Construct big-endian lengths block */ + hash->len.add = cpu_to_be64 ( context->len.len.add ); + hash->len.data = cpu_to_be64 ( context->len.len.data ); + DBGC2 ( context, "GCM %p len(A)||len(C):\n", context ); + DBGC2_HDA ( context, 0, hash, sizeof ( *hash ) ); + + /* Update hash */ + gcm_xor_block ( &context->hash, hash ); + gcm_multiply_key ( &context->key, hash ); + DBGC2 ( context, "GCM %p GHASH(H,A,C):\n", context ); + DBGC2_HDA ( context, 0, hash, sizeof ( *hash ) ); +} + +/** + * Construct tag + * + * @v context Context + * @v tag Tag + */ +void gcm_tag ( struct gcm_context *context, union gcm_block *tag ) { + union gcm_block tmp; + uint32_t offset; + + /* Construct hash */ + gcm_hash ( context, tag ); + + /* Construct encrypted initial counter value */ + memcpy ( &tmp, &context->ctr, sizeof ( tmp ) ); + offset = ( ( -context->len.len.data ) / ( 8 * sizeof ( tmp ) ) ); + gcm_count ( &tmp, offset ); + cipher_encrypt ( context->raw_cipher, &context->raw_ctx, &tmp, + &tmp, sizeof ( tmp ) ); + DBGC2 ( context, "GCM %p E(K,Y[0]):\n", context ); + DBGC2_HDA ( context, 0, &tmp, sizeof ( tmp ) ); + + /* Construct tag */ + gcm_xor_block ( &tmp, tag ); + DBGC2 ( context, "GCM %p T:\n", context ); + DBGC2_HDA ( context, 0, tag, sizeof ( *tag ) ); +} + +/** + * Set key + * + * @v context Context + * @v key Key + * @v keylen Key length + * @v raw_cipher Underlying cipher + * @ret rc Return status code + */ +int gcm_setkey ( struct gcm_context *context, const void *key, size_t keylen, + struct cipher_algorithm *raw_cipher ) { + int rc; + + /* Initialise GCM context */ + memset ( context, 0, sizeof ( *context ) ); + context->raw_cipher = raw_cipher; + + /* Set underlying block cipher key */ + if ( ( rc = cipher_setkey ( raw_cipher, context->raw_ctx, key, + keylen ) ) != 0 ) + return rc; + + /* Construct GCM hash key */ + cipher_encrypt ( raw_cipher, context->raw_ctx, &context->ctr, + &context->key, sizeof ( context->key ) ); + DBGC2 ( context, "GCM %p H:\n", context ); + DBGC2_HDA ( context, 0, &context->key, sizeof ( context->key ) ); + + /* Reset counter */ + context->ctr.ctr.value = cpu_to_be32 ( 1 ); + + /* Construct cached tables */ + gcm_cache ( &context->key ); + + return 0; +} + +/** + * Set initialisation vector + * + * @v ctx Context + * @v iv Initialisation vector + * @v ivlen Initialisation vector length + */ +void gcm_setiv ( struct gcm_context *context, const void *iv, size_t ivlen ) { + union gcm_block *check = ( ( void * ) context ); + + /* Sanity checks */ + linker_assert ( &context->hash == check, gcm_bad_layout ); + linker_assert ( &context->len == check + 1, gcm_bad_layout ); + linker_assert ( &context->ctr == check + 2, gcm_bad_layout ); + linker_assert ( &context->key == check + 3, gcm_bad_layout ); + + /* Reset non-key state */ + memset ( context, 0, offsetof ( typeof ( *context ), key ) ); + + /* Reset counter */ + context->ctr.ctr.value = cpu_to_be32 ( 1 ); + + /* Process initialisation vector */ + if ( ivlen == sizeof ( context->ctr.ctr.iv ) ) { + + /* Initialisation vector is exactly 96 bits, use it as-is */ + memcpy ( context->ctr.ctr.iv, iv, ivlen ); + + } else { + + /* Calculate hash over initialisation vector */ + gcm_process ( context, iv, NULL, ivlen, GCM_FL_IV ); + gcm_hash ( context, &context->ctr ); + assert ( context->len.len.add == 0 ); + + /* Reset non-key, non-counter state */ + memset ( context, 0, offsetof ( typeof ( *context ), ctr ) ); + } + + DBGC2 ( context, "GCM %p Y[0]:\n", context ); + DBGC2_HDA ( context, 0, &context->ctr, sizeof ( context->ctr ) ); +} + +/** + * Encrypt data + * + * @v context Context + * @v src Data to encrypt + * @v dst Buffer for encrypted data, or NULL for additional data + * @v len Length of data + */ +void gcm_encrypt ( struct gcm_context *context, const void *src, void *dst, + size_t len ) { + + /* Process data */ + gcm_process ( context, src, dst, len, GCM_FL_ENCRYPT ); +} + +/** + * Decrypt data + * + * @v context Context + * @v src Data to decrypt + * @v dst Buffer for decrypted data, or NULL for additional data + * @v len Length of data + */ +void gcm_decrypt ( struct gcm_context *context, const void *src, void *dst, + size_t len ) { + + /* Process data */ + gcm_process ( context, src, dst, len, 0 ); +} diff --git a/src/crypto/mishmash/rsa_aes_cbc_sha1.c b/src/crypto/mishmash/rsa_aes_cbc_sha1.c index 04b4ce2a7..9f8193de0 100644 --- a/src/crypto/mishmash/rsa_aes_cbc_sha1.c +++ b/src/crypto/mishmash/rsa_aes_cbc_sha1.c @@ -27,24 +27,65 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #include <ipxe/rsa.h> #include <ipxe/aes.h> #include <ipxe/sha1.h> +#include <ipxe/sha256.h> #include <ipxe/tls.h> +/** TLS_DHE_RSA_WITH_AES_128_CBC_SHA cipher suite */ +struct tls_cipher_suite +tls_dhe_rsa_with_aes_128_cbc_sha __tls_cipher_suite ( 05 ) = { + .code = htons ( TLS_DHE_RSA_WITH_AES_128_CBC_SHA ), + .key_len = ( 128 / 8 ), + .fixed_iv_len = 0, + .record_iv_len = AES_BLOCKSIZE, + .mac_len = SHA1_DIGEST_SIZE, + .exchange = &tls_dhe_exchange_algorithm, + .pubkey = &rsa_algorithm, + .cipher = &aes_cbc_algorithm, + .digest = &sha1_algorithm, + .handshake = &sha256_algorithm, +}; + +/** TLS_DHE_RSA_WITH_AES_256_CBC_SHA cipher suite */ +struct tls_cipher_suite +tls_dhe_rsa_with_aes_256_cbc_sha __tls_cipher_suite ( 06 ) = { + .code = htons ( TLS_DHE_RSA_WITH_AES_256_CBC_SHA ), + .key_len = ( 256 / 8 ), + .fixed_iv_len = 0, + .record_iv_len = AES_BLOCKSIZE, + .mac_len = SHA1_DIGEST_SIZE, + .exchange = &tls_dhe_exchange_algorithm, + .pubkey = &rsa_algorithm, + .cipher = &aes_cbc_algorithm, + .digest = &sha1_algorithm, + .handshake = &sha256_algorithm, +}; + /** TLS_RSA_WITH_AES_128_CBC_SHA cipher suite */ -struct tls_cipher_suite tls_rsa_with_aes_128_cbc_sha __tls_cipher_suite (03) = { +struct tls_cipher_suite +tls_rsa_with_aes_128_cbc_sha __tls_cipher_suite ( 15 ) = { .code = htons ( TLS_RSA_WITH_AES_128_CBC_SHA ), .key_len = ( 128 / 8 ), + .fixed_iv_len = 0, + .record_iv_len = AES_BLOCKSIZE, + .mac_len = SHA1_DIGEST_SIZE, .exchange = &tls_pubkey_exchange_algorithm, .pubkey = &rsa_algorithm, .cipher = &aes_cbc_algorithm, .digest = &sha1_algorithm, + .handshake = &sha256_algorithm, }; /** TLS_RSA_WITH_AES_256_CBC_SHA cipher suite */ -struct tls_cipher_suite tls_rsa_with_aes_256_cbc_sha __tls_cipher_suite (04) = { +struct tls_cipher_suite +tls_rsa_with_aes_256_cbc_sha __tls_cipher_suite ( 16 ) = { .code = htons ( TLS_RSA_WITH_AES_256_CBC_SHA ), .key_len = ( 256 / 8 ), + .fixed_iv_len = 0, + .record_iv_len = AES_BLOCKSIZE, + .mac_len = SHA1_DIGEST_SIZE, .exchange = &tls_pubkey_exchange_algorithm, .pubkey = &rsa_algorithm, .cipher = &aes_cbc_algorithm, .digest = &sha1_algorithm, + .handshake = &sha256_algorithm, }; diff --git a/src/crypto/mishmash/rsa_aes_cbc_sha256.c b/src/crypto/mishmash/rsa_aes_cbc_sha256.c index 1021f76f4..d0dc84964 100644 --- a/src/crypto/mishmash/rsa_aes_cbc_sha256.c +++ b/src/crypto/mishmash/rsa_aes_cbc_sha256.c @@ -29,22 +29,62 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #include <ipxe/sha256.h> #include <ipxe/tls.h> +/** TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 cipher suite */ +struct tls_cipher_suite +tls_dhe_rsa_with_aes_128_cbc_sha256 __tls_cipher_suite ( 03 ) = { + .code = htons ( TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 ), + .key_len = ( 128 / 8 ), + .fixed_iv_len = 0, + .record_iv_len = AES_BLOCKSIZE, + .mac_len = SHA256_DIGEST_SIZE, + .exchange = &tls_dhe_exchange_algorithm, + .pubkey = &rsa_algorithm, + .cipher = &aes_cbc_algorithm, + .digest = &sha256_algorithm, + .handshake = &sha256_algorithm, +}; + +/** TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 cipher suite */ +struct tls_cipher_suite +tls_dhe_rsa_with_aes_256_cbc_sha256 __tls_cipher_suite ( 04 ) = { + .code = htons ( TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 ), + .key_len = ( 256 / 8 ), + .fixed_iv_len = 0, + .record_iv_len = AES_BLOCKSIZE, + .mac_len = SHA256_DIGEST_SIZE, + .exchange = &tls_dhe_exchange_algorithm, + .pubkey = &rsa_algorithm, + .cipher = &aes_cbc_algorithm, + .digest = &sha256_algorithm, + .handshake = &sha256_algorithm, +}; + /** TLS_RSA_WITH_AES_128_CBC_SHA256 cipher suite */ -struct tls_cipher_suite tls_rsa_with_aes_128_cbc_sha256 __tls_cipher_suite(01)={ +struct tls_cipher_suite +tls_rsa_with_aes_128_cbc_sha256 __tls_cipher_suite ( 13 ) = { .code = htons ( TLS_RSA_WITH_AES_128_CBC_SHA256 ), .key_len = ( 128 / 8 ), + .fixed_iv_len = 0, + .record_iv_len = AES_BLOCKSIZE, + .mac_len = SHA256_DIGEST_SIZE, .exchange = &tls_pubkey_exchange_algorithm, .pubkey = &rsa_algorithm, .cipher = &aes_cbc_algorithm, .digest = &sha256_algorithm, + .handshake = &sha256_algorithm, }; /** TLS_RSA_WITH_AES_256_CBC_SHA256 cipher suite */ -struct tls_cipher_suite tls_rsa_with_aes_256_cbc_sha256 __tls_cipher_suite(02)={ +struct tls_cipher_suite +tls_rsa_with_aes_256_cbc_sha256 __tls_cipher_suite ( 14 ) = { .code = htons ( TLS_RSA_WITH_AES_256_CBC_SHA256 ), .key_len = ( 256 / 8 ), + .fixed_iv_len = 0, + .record_iv_len = AES_BLOCKSIZE, + .mac_len = SHA256_DIGEST_SIZE, .exchange = &tls_pubkey_exchange_algorithm, .pubkey = &rsa_algorithm, .cipher = &aes_cbc_algorithm, .digest = &sha256_algorithm, + .handshake = &sha256_algorithm, }; diff --git a/src/crypto/mishmash/rsa_aes_gcm_sha256.c b/src/crypto/mishmash/rsa_aes_gcm_sha256.c new file mode 100644 index 000000000..cf9c4c279 --- /dev/null +++ b/src/crypto/mishmash/rsa_aes_gcm_sha256.c @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2022 Michael Brown <mbrown@fensystems.co.uk>. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + * + * You can also choose to distribute this program under the terms of + * the Unmodified Binary Distribution Licence (as given in the file + * COPYING.UBDL), provided that you have satisfied its requirements. + */ + +FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); + +#include <byteswap.h> +#include <ipxe/rsa.h> +#include <ipxe/aes.h> +#include <ipxe/sha256.h> +#include <ipxe/tls.h> + +/** TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 cipher suite */ +struct tls_cipher_suite +tls_dhe_rsa_with_aes_128_gcm_sha256 __tls_cipher_suite ( 01 ) = { + .code = htons ( TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 ), + .key_len = ( 128 / 8 ), + .fixed_iv_len = 4, + .record_iv_len = 8, + .mac_len = 0, + .exchange = &tls_dhe_exchange_algorithm, + .pubkey = &rsa_algorithm, + .cipher = &aes_gcm_algorithm, + .digest = &sha256_algorithm, + .handshake = &sha256_algorithm, +}; + +/** TLS_RSA_WITH_AES_128_GCM_SHA256 cipher suite */ +struct tls_cipher_suite +tls_rsa_with_aes_128_gcm_sha256 __tls_cipher_suite ( 11 ) = { + .code = htons ( TLS_RSA_WITH_AES_128_GCM_SHA256 ), + .key_len = ( 128 / 8 ), + .fixed_iv_len = 4, + .record_iv_len = 8, + .mac_len = 0, + .exchange = &tls_pubkey_exchange_algorithm, + .pubkey = &rsa_algorithm, + .cipher = &aes_gcm_algorithm, + .digest = &sha256_algorithm, + .handshake = &sha256_algorithm, +}; diff --git a/src/crypto/mishmash/rsa_aes_gcm_sha384.c b/src/crypto/mishmash/rsa_aes_gcm_sha384.c new file mode 100644 index 000000000..10a977f7f --- /dev/null +++ b/src/crypto/mishmash/rsa_aes_gcm_sha384.c @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2022 Michael Brown <mbrown@fensystems.co.uk>. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + * + * You can also choose to distribute this program under the terms of + * the Unmodified Binary Distribution Licence (as given in the file + * COPYING.UBDL), provided that you have satisfied its requirements. + */ + +FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); + +#include <byteswap.h> +#include <ipxe/rsa.h> +#include <ipxe/aes.h> +#include <ipxe/sha512.h> +#include <ipxe/tls.h> + +/** TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 cipher suite */ +struct tls_cipher_suite +tls_dhe_rsa_with_aes_256_gcm_sha384 __tls_cipher_suite ( 02 ) = { + .code = htons ( TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 ), + .key_len = ( 256 / 8 ), + .fixed_iv_len = 4, + .record_iv_len = 8, + .mac_len = 0, + .exchange = &tls_dhe_exchange_algorithm, + .pubkey = &rsa_algorithm, + .cipher = &aes_gcm_algorithm, + .digest = &sha384_algorithm, + .handshake = &sha384_algorithm, +}; + +/** TLS_RSA_WITH_AES_256_GCM_SHA384 cipher suite */ +struct tls_cipher_suite +tls_rsa_with_aes_256_gcm_sha384 __tls_cipher_suite ( 12 ) = { + .code = htons ( TLS_RSA_WITH_AES_256_GCM_SHA384 ), + .key_len = ( 256 / 8 ), + .fixed_iv_len = 4, + .record_iv_len = 8, + .mac_len = 0, + .exchange = &tls_pubkey_exchange_algorithm, + .pubkey = &rsa_algorithm, + .cipher = &aes_gcm_algorithm, + .digest = &sha384_algorithm, + .handshake = &sha384_algorithm, +}; diff --git a/src/crypto/null_entropy.c b/src/crypto/null_entropy.c deleted file mode 100644 index d1e1a6f73..000000000 --- a/src/crypto/null_entropy.c +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - * You can also choose to distribute this program under the terms of - * the Unmodified Binary Distribution Licence (as given in the file - * COPYING.UBDL), provided that you have satisfied its requirements. - */ - -FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); - -/** @file - * - * Nonexistent entropy source - * - * - * This source provides no entropy and must NOT be used in a - * security-sensitive environment. - */ - -#include <ipxe/entropy.h> - -PROVIDE_ENTROPY_INLINE ( null, min_entropy_per_sample ); -PROVIDE_ENTROPY_INLINE ( null, entropy_enable ); -PROVIDE_ENTROPY_INLINE ( null, entropy_disable ); -PROVIDE_ENTROPY_INLINE ( null, get_noise ); |
