Compare commits

..

17 Commits
x25519 ... des

Author SHA1 Message Date
93a6e18086 [crypto] Add implementation of the DES cipher
The DES block cipher dates back to the 1970s.  It is no longer
relevant for use in TLS cipher suites, but it is still used by the
MS-CHAPv2 authentication protocol which remains unfortunately common
for 802.1x port authentication.

Add an implementation of the DES block cipher, complete with the
extremely comprehensive test vectors published by NBS (the precursor
to NIST) in the form of an utterly adorable typewritten and hand-drawn
paper document.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-02-07 23:13:48 +00:00
af4583b214 [test] Remove dummy initialisation vector for ECB-mode AES tests
A block cipher in ECB mode has no concept of an initialisation vector,
and any data provided to cipher_setiv() for an ECB cipher will be
ignored.  There is no requirement within our cipher algorithm
abstraction for a dummy initialisation vector to be provided.

Remove the entirely spurious dummy 16-byte initialisation vector from
the ECB test cases.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-02-07 21:16:47 +00:00
36a27b22b1 [crypto] Fix stray references to AES
The CBC_CIPHER() macro contains some accidentally hardcoded references
to an underlying AES cipher, instead of using the cipher specified in
the macro parameters.

Fix by using the macro parameter as required.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-02-02 17:09:06 +00:00
0cc0f47443 [tls] Tidy up error handling flow in tls_send_plaintext()
Coverity reported that tls_send_plaintext() failed to check the return
status from tls_generate_random(), which could potentially result in
uninitialised random data being used as the block initialisation
vector (instead of intentionally random data).

Add the missing return status check, and separate out the error
handling code paths (since on the successful exit code path there will
be no need to free either the plaintext or the ciphertext anyway).

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-01-31 13:49:35 +00:00
65d69d33da [efi] Fix hang during ExitBootServices()
When ExitBootServices() invokes efi_shutdown_hook(), there may be
nothing to generate an interrupt since the timer is disabled in the
first step of ExitBootServices().  Additionally, for VMs OVMF masks
everything from the PIC (except the timer) by default.  This means
that calling cpu_nap() may hang indefinitely.  This was seen in
practice in netfront_reset() when running in a VM on XenServer.

Fix this by skipping the halt if an EFI shutdown is in progress.

Signed-off-by: Ross Lagerwall <ross.lagerwall@citrix.com>
Modified-by: Michael Brown <mcb30@ipxe.org>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-01-31 13:23:56 +00:00
963ec1c4f3 [tls] Add ECDHE cipher suites
Add ECDHE variants of the existing cipher suites, and lower the
priority of the non-ECDHE variants.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-01-31 12:34:20 +00:00
8f6a9399b3 [tls] Make key exchange algorithms selectable via build configuration
Allow the choice of key exchange algorithms to be controlled via build
configuration options in config/crypto.h, as is already done for the
choices of public-key algorithms, cipher algorithms, and digest
algorithms.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-01-30 18:01:44 +00:00
a881a26061 [crypto] Add X25519 OID-identified algorithm and TLS named curve
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-01-30 18:01:44 +00:00
b234226dbc [tls] Add support for Ephemeral Elliptic Curve Diffie-Hellman key exchange
Add support for the Ephemeral Elliptic Curve Diffie-Hellman (ECDHE)
key exchange algorithm.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-01-30 16:16:31 +00:00
8e2469c861 [tls] Split out Diffie-Hellman parameter signature verification
DHE and ECDHE use essentially the same mechanism for verifying the
signature over the Diffie-Hellman parameters, though the format of the
parameters is different between the two methods.

Split out the verification of the parameter signature so that it may
be shared between the DHE and ECDHE key exchange algorithms.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-01-30 16:06:45 +00:00
989dbe0bc4 [tls] Generate key material after sending ClientKeyExchange
The construction of the key material for the pending cipher suites
from the TLS master secret must happen regardless of which key
exchange algorithm is in use, and the key material is not required to
send the ClientKeyExchange handshake (which is sent before changing
cipher suites).

Centralise the call to tls_generate_keys() after performing key
exchange via the selected algorithm.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-01-30 15:25:38 +00:00
6f70e8be83 [tls] Restructure construction of ClientHello message
Define an individual local structure for each extension and a single
structure for the list of extensions.  This makes it viable to add
extensions such as the Supported Elliptic Curves extension, which must
not be present if the list of curves is empty.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-01-30 13:38:15 +00:00
17135c83fb [crypto] Add an abstraction of an elliptic curve
Define an abstraction of an elliptic curve with a fixed generator and
one supported operation (scalar multiplication of a curve point).

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-01-30 13:26:36 +00:00
27398f1360 [crypto] Check for all-zeros result from X25519 key exchange
RFC7748 states that it is entirely optional for X25519 Diffie-Hellman
implementations to check whether or not the result is the all-zero
value (indicating that an attacker sent a malicious public key with a
small order).  RFC8422 states that implementations in TLS must abort
the handshake if the all-zero value is obtained.

Return an error if the all-zero value is obtained, so that the TLS
code will not require knowledge specific to the X25519 curve.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-01-30 13:21:01 +00:00
de8a0821c7 [bnxt] Add support for additional chip IDs
Add additional chip IDs that can be recognized as part of the thor
family.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-01-19 22:08:48 +00:00
2eea04c02c [crypto] Add X25519 key exchange algorithm
Add an implementation of the X25519 key exchange algorithm as defined
in RFC7748.

This implementation is inspired by and partially based upon the paper
"Implementing Curve25519/X25519: A Tutorial on Elliptic Curve
Cryptography" by Martin Kleppmann, available for download from
https://www.cl.cam.ac.uk/teaching/2122/Crypto/curve25519.pdf

The underlying modular addition, subtraction, and multiplication
operations are completely redesigned for substantially improved
efficiency compared to the TweetNaCl implementation studied in that
paper (approximately 5x-10x faster and with 70% less memory usage).

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-01-19 16:44:30 +00:00
908174ec7e [loong64] Replace broken big integer arithmetic implementations
The slightly incomprehensible LoongArch64 implementation for
bigint_subtract() is observed to produce incorrect results for some
input values.

Replace the suspicious LoongArch64 implementations of bigint_add(),
bigint_subtract(), bigint_rol() and bigint_ror(), and add a test case
for a subtraction that was producing an incorrect result with the
previous implementation.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-01-19 16:40:11 +00:00
36 changed files with 2948 additions and 379 deletions

View File

@ -46,8 +46,12 @@ static void efiarm_cpu_nap ( void ) {
* The EFI shell doesn't seem to bother sleeping the CPU; it
* just sits there idly burning power.
*
* If a shutdown is in progess, there may be nothing to
* generate an interrupt since the timer is disabled in the
* first step of ExitBootServices().
*/
__asm__ __volatile__ ( "wfi" );
if ( ! efi_shutdown_in_progress )
__asm__ __volatile__ ( "wfi" );
}
PROVIDE_NAP ( efiarm, cpu_nap, efiarm_cpu_nap );

View File

@ -53,34 +53,37 @@ bigint_add_raw ( const uint64_t *addend0, uint64_t *value0,
uint64_t *discard_value;
uint64_t discard_addend_i;
uint64_t discard_value_i;
uint64_t discard_carry;
uint64_t discard_temp;
unsigned int discard_size;
__asm__ __volatile__ ( "move $t0, $zero\n"
"1:\n\t"
"ld.d %3, %0, 0\n\t"
__asm__ __volatile__ ( "\n1:\n\t"
/* Load addend[i] and value[i] */
"ld.d %3, %0, 0\n\t"
"ld.d %4, %1, 0\n\t"
/* Add carry flag and addend */
"add.d %4, %4, %5\n\t"
"sltu %6, %4, %5\n\t"
"add.d %4, %4, %3\n\t"
"sltu %5, %4, %3\n\t"
"or %5, %5, %6\n\t"
/* Store value[i] */
"st.d %4, %1, 0\n\t"
/* Loop */
"addi.d %0, %0, 8\n\t"
"ld.d %4, %1, 0\n\t"
"add.d %4, %4, $t0\n\t"
"sltu $t0, %4, $t0\n\t"
"add.d %4, %4, %3\n\t"
"sltu $t1, %4, %3\n\t"
"or $t0, $t0, $t1\n\t"
"st.d %4, %1, 0\n\t"
"addi.d %1, %1, 8\n\t"
"addi.w %2, %2, -1\n\t"
"bnez %2, 1b"
"bnez %2, 1b\n\t"
: "=r" ( discard_addend ),
"=r" ( discard_value ),
"=r" ( discard_size ),
"=r" ( discard_addend_i ),
"=r" ( discard_value_i ),
"=r" ( discard_carry ),
"=r" ( discard_temp ),
"+m" ( *value )
: "0" ( addend0 ),
"1" ( value0 ),
"2" ( size )
: "t0", "t1" );
: "0" ( addend0 ), "1" ( value0 ),
"2" ( size ), "5" ( 0 ) );
}
/**
@ -93,35 +96,43 @@ bigint_add_raw ( const uint64_t *addend0, uint64_t *value0,
static inline __attribute__ (( always_inline )) void
bigint_subtract_raw ( const uint64_t *subtrahend0, uint64_t *value0,
unsigned int size ) {
bigint_t ( size ) __attribute__ (( may_alias )) *value =
( ( void * ) value0 );
uint64_t *discard_subtrahend;
uint64_t *discard_value;
uint64_t discard_subtrahend_i;
uint64_t discard_value_i;
uint64_t discard_carry;
uint64_t discard_temp;
unsigned int discard_size;
unsigned int flag = 0;
discard_subtrahend = (uint64_t*) subtrahend0;
discard_value = value0;
discard_size = size;
do {
discard_subtrahend_i = *discard_subtrahend;
discard_subtrahend++;
discard_value_i = *discard_value;
discard_value_i = discard_value_i - discard_subtrahend_i - flag;
if ( *discard_value < (discard_subtrahend_i + flag)) {
flag = 1;
} else {
flag = 0;
}
*discard_value = discard_value_i;
discard_value++;
discard_size -= 1;
} while (discard_size != 0);
__asm__ __volatile__ ( "\n1:\n\t"
/* Load subtrahend[i] and value[i] */
"ld.d %3, %0, 0\n\t"
"ld.d %4, %1, 0\n\t"
/* Subtract carry flag and subtrahend */
"sltu %6, %4, %5\n\t"
"sub.d %4, %4, %5\n\t"
"sltu %5, %4, %3\n\t"
"sub.d %4, %4, %3\n\t"
"or %5, %5, %6\n\t"
/* Store value[i] */
"st.d %4, %1, 0\n\t"
/* Loop */
"addi.d %0, %0, 8\n\t"
"addi.d %1, %1, 8\n\t"
"addi.w %2, %2, -1\n\t"
"bnez %2, 1b\n\t"
: "=r" ( discard_subtrahend ),
"=r" ( discard_value ),
"=r" ( discard_size ),
"=r" ( discard_subtrahend_i ),
"=r" ( discard_value_i ),
"=r" ( discard_carry ),
"=r" ( discard_temp ),
"+m" ( *value )
: "0" ( subtrahend0 ), "1" ( value0 ),
"2" ( size ), "5" ( 0 ) );
}
/**
@ -132,30 +143,37 @@ bigint_subtract_raw ( const uint64_t *subtrahend0, uint64_t *value0,
*/
static inline __attribute__ (( always_inline )) void
bigint_rol_raw ( uint64_t *value0, unsigned int size ) {
bigint_t ( size ) __attribute__ (( may_alias )) *value =
( ( void * ) value0 );
uint64_t *discard_value;
uint64_t discard_value_i;
uint64_t discard_carry;
uint64_t discard_temp;
unsigned int discard_size;
uint64_t current_value_i;
unsigned int flag = 0;
discard_value = value0;
discard_size = size;
do {
discard_value_i = *discard_value;
current_value_i = discard_value_i;
discard_value_i += discard_value_i + flag;
if (discard_value_i < current_value_i) {
flag = 1;
} else {
flag = 0;
}
*discard_value = discard_value_i;
discard_value++;
discard_size -= 1;
} while ( discard_size != 0 );
__asm__ __volatile__ ( "\n1:\n\t"
/* Load value[i] */
"ld.d %2, %0, 0\n\t"
/* Shift left */
"rotri.d %2, %2, 63\n\t"
"andi %4, %2, 1\n\t"
"xor %2, %2, %4\n\t"
"or %2, %2, %3\n\t"
"move %3, %4\n\t"
/* Store value[i] */
"st.d %2, %0, 0\n\t"
/* Loop */
"addi.d %0, %0, 8\n\t"
"addi.w %1, %1, -1\n\t"
"bnez %1, 1b\n\t"
: "=r" ( discard_value ),
"=r" ( discard_size ),
"=r" ( discard_value_i ),
"=r" ( discard_carry ),
"=r" ( discard_temp ),
"+m" ( *value )
: "0" ( value0 ), "1" ( size ), "3" ( 0 )
: "cc" );
}
/**
@ -166,27 +184,37 @@ bigint_rol_raw ( uint64_t *value0, unsigned int size ) {
*/
static inline __attribute__ (( always_inline )) void
bigint_ror_raw ( uint64_t *value0, unsigned int size ) {
bigint_t ( size ) __attribute__ (( may_alias )) *value =
( ( void * ) value0 );
uint64_t *discard_value;
uint64_t discard_value_i;
uint64_t discard_value_j;
uint64_t discard_carry;
uint64_t discard_temp;
unsigned int discard_size;
discard_value = value0;
discard_size = size;
discard_value_j = 0;
do {
discard_size -= 1;
discard_value_i = *(discard_value + discard_size);
discard_value_j = (discard_value_j << 63) | (discard_value_i >> 1);
*(discard_value + discard_size) = discard_value_j;
discard_value_j = discard_value_i;
} while ( discard_size > 0 );
__asm__ __volatile__ ( "\n1:\n\t"
/* Load value[i] */
"ld.d %2, %0, -8\n\t"
/* Shift right */
"andi %4, %2, 1\n\t"
"xor %2, %2, %4\n\t"
"or %2, %2, %3\n\t"
"move %3, %4\n\t"
"rotri.d %2, %2, 1\n\t"
/* Store value[i] */
"st.d %2, %0, -8\n\t"
/* Loop */
"addi.d %0, %0, -8\n\t"
"addi.w %1, %1, -1\n\t"
"bnez %1, 1b\n\t"
: "=r" ( discard_value ),
"=r" ( discard_size ),
"=r" ( discard_value_i ),
"=r" ( discard_carry ),
"=r" ( discard_temp ),
"+m" ( *value )
: "0" ( value0 + size ), "1" ( size ), "3" ( 0 )
: "cc" );
}
/**

View File

@ -46,8 +46,12 @@ static void efiloong64_cpu_nap ( void ) {
* The EFI shell doesn't seem to bother sleeping the CPU; it
* just sits there idly burning power.
*
* If a shutdown is in progess, there may be nothing to
* generate an interrupt since the timer is disabled in the
* first step of ExitBootServices().
*/
__asm__ __volatile__ ( "idle 0" );
if ( ! efi_shutdown_in_progress )
__asm__ __volatile__ ( "idle 0" );
}
PROVIDE_NAP ( efiloong64, cpu_nap, efiloong64_cpu_nap );

View File

@ -46,8 +46,12 @@ static void efix86_cpu_nap ( void ) {
* The EFI shell doesn't seem to bother sleeping the CPU; it
* just sits there idly burning power.
*
* If a shutdown is in progess, there may be nothing to
* generate an interrupt since the timer is disabled in the
* first step of ExitBootServices().
*/
__asm__ __volatile__ ( "hlt" );
if ( ! efi_shutdown_in_progress )
__asm__ __volatile__ ( "hlt" );
}
PROVIDE_NAP ( efix86, cpu_nap, efix86_cpu_nap );

View File

@ -83,6 +83,11 @@ REQUIRE_OBJECT ( oid_sha512_224 );
REQUIRE_OBJECT ( oid_sha512_256 );
#endif
/* X25519 */
#if defined ( CRYPTO_CURVE_X25519 )
REQUIRE_OBJECT ( oid_x25519 );
#endif
/* RSA and MD5 */
#if defined ( CRYPTO_PUBKEY_RSA ) && defined ( CRYPTO_DIGEST_MD5 )
REQUIRE_OBJECT ( rsa_md5 );
@ -114,25 +119,79 @@ REQUIRE_OBJECT ( rsa_sha512 );
#endif
/* RSA, AES-CBC, and SHA-1 */
#if defined ( CRYPTO_PUBKEY_RSA ) && defined ( CRYPTO_CIPHER_AES_CBC ) && \
defined ( CRYPTO_DIGEST_SHA1 )
#if defined ( CRYPTO_EXCHANGE_PUBKEY ) && defined ( CRYPTO_PUBKEY_RSA ) && \
defined ( CRYPTO_CIPHER_AES_CBC ) && defined ( CRYPTO_DIGEST_SHA1 )
REQUIRE_OBJECT ( rsa_aes_cbc_sha1 );
#endif
/* RSA, AES-CBC, and SHA-256 */
#if defined ( CRYPTO_PUBKEY_RSA ) && defined ( CRYPTO_CIPHER_AES_CBC ) && \
defined ( CRYPTO_DIGEST_SHA256 )
#if defined ( CRYPTO_EXCHANGE_PUBKEY ) && defined ( CRYPTO_PUBKEY_RSA ) && \
defined ( CRYPTO_CIPHER_AES_CBC ) && defined ( CRYPTO_DIGEST_SHA256 )
REQUIRE_OBJECT ( rsa_aes_cbc_sha256 );
#endif
/* RSA, AES-GCM, and SHA-256 */
#if defined ( CRYPTO_PUBKEY_RSA ) && defined ( CRYPTO_CIPHER_AES_GCM ) && \
defined ( CRYPTO_DIGEST_SHA256 )
#if defined ( CRYPTO_EXCHANGE_PUBKEY ) && defined ( CRYPTO_PUBKEY_RSA ) && \
defined ( CRYPTO_CIPHER_AES_GCM ) && defined ( CRYPTO_DIGEST_SHA256 )
REQUIRE_OBJECT ( rsa_aes_gcm_sha256 );
#endif
/* RSA, AES-GCM, and SHA-384 */
#if defined ( CRYPTO_PUBKEY_RSA ) && defined ( CRYPTO_CIPHER_AES_GCM ) && \
defined ( CRYPTO_DIGEST_SHA384 )
#if defined ( CRYPTO_EXCHANGE_PUBKEY ) && defined ( CRYPTO_PUBKEY_RSA ) && \
defined ( CRYPTO_CIPHER_AES_GCM ) && defined ( CRYPTO_DIGEST_SHA384 )
REQUIRE_OBJECT ( rsa_aes_gcm_sha384 );
#endif
/* DHE, RSA, AES-CBC, and SHA-1 */
#if defined ( CRYPTO_EXCHANGE_DHE ) && defined ( CRYPTO_PUBKEY_RSA ) && \
defined ( CRYPTO_CIPHER_AES_CBC ) && defined ( CRYPTO_DIGEST_SHA1 )
REQUIRE_OBJECT ( dhe_rsa_aes_cbc_sha1 );
#endif
/* DHE, RSA, AES-CBC, and SHA-256 */
#if defined ( CRYPTO_EXCHANGE_DHE ) && defined ( CRYPTO_PUBKEY_RSA ) && \
defined ( CRYPTO_CIPHER_AES_CBC ) && defined ( CRYPTO_DIGEST_SHA256 )
REQUIRE_OBJECT ( dhe_rsa_aes_cbc_sha256 );
#endif
/* DHE, RSA, AES-GCM, and SHA-256 */
#if defined ( CRYPTO_EXCHANGE_DHE ) && defined ( CRYPTO_PUBKEY_RSA ) && \
defined ( CRYPTO_CIPHER_AES_GCM ) && defined ( CRYPTO_DIGEST_SHA256 )
REQUIRE_OBJECT ( dhe_rsa_aes_gcm_sha256 );
#endif
/* DHE, RSA, AES-GCM, and SHA-384 */
#if defined ( CRYPTO_EXCHANGE_DHE ) && defined ( CRYPTO_PUBKEY_RSA ) && \
defined ( CRYPTO_CIPHER_AES_GCM ) && defined ( CRYPTO_DIGEST_SHA384 )
REQUIRE_OBJECT ( dhe_rsa_aes_gcm_sha384 );
#endif
/* ECDHE, RSA, AES-CBC, and SHA-1 */
#if defined ( CRYPTO_EXCHANGE_ECDHE ) && defined ( CRYPTO_PUBKEY_RSA ) && \
defined ( CRYPTO_CIPHER_AES_CBC ) && defined ( CRYPTO_DIGEST_SHA1 )
REQUIRE_OBJECT ( ecdhe_rsa_aes_cbc_sha1 );
#endif
/* ECDHE, RSA, AES-CBC, and SHA-256 */
#if defined ( CRYPTO_EXCHANGE_ECDHE ) && defined ( CRYPTO_PUBKEY_RSA ) && \
defined ( CRYPTO_CIPHER_AES_CBC ) && defined ( CRYPTO_DIGEST_SHA256 )
REQUIRE_OBJECT ( ecdhe_rsa_aes_cbc_sha256 );
#endif
/* ECDHE, RSA, AES-CBC, and SHA-384 */
#if defined ( CRYPTO_EXCHANGE_ECDHE ) && defined ( CRYPTO_PUBKEY_RSA ) && \
defined ( CRYPTO_CIPHER_AES_CBC ) && defined ( CRYPTO_DIGEST_SHA384 )
REQUIRE_OBJECT ( ecdhe_rsa_aes_cbc_sha384 );
#endif
/* ECDHE, RSA, AES-GCM, and SHA-256 */
#if defined ( CRYPTO_EXCHANGE_ECDHE ) && defined ( CRYPTO_PUBKEY_RSA ) && \
defined ( CRYPTO_CIPHER_AES_GCM ) && defined ( CRYPTO_DIGEST_SHA256 )
REQUIRE_OBJECT ( ecdhe_rsa_aes_gcm_sha256 );
#endif
/* ECDHE, RSA, AES-GCM, and SHA-384 */
#if defined ( CRYPTO_EXCHANGE_ECDHE ) && defined ( CRYPTO_PUBKEY_RSA ) && \
defined ( CRYPTO_CIPHER_AES_GCM ) && defined ( CRYPTO_DIGEST_SHA384 )
REQUIRE_OBJECT ( ecdhe_rsa_aes_gcm_sha384 );
#endif

View File

@ -12,6 +12,15 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
/** Minimum TLS version */
#define TLS_VERSION_MIN TLS_VERSION_TLS_1_1
/** Public-key exchange algorithm */
#define CRYPTO_EXCHANGE_PUBKEY
/** DHE key exchange algorithm */
#define CRYPTO_EXCHANGE_DHE
/** ECDHE key exchange algorithm */
#define CRYPTO_EXCHANGE_ECDHE
/** RSA public-key algorithm */
#define CRYPTO_PUBKEY_RSA
@ -48,6 +57,9 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
/** SHA-512/256 digest algorithm */
//#define CRYPTO_DIGEST_SHA512_256
/** X25519 elliptic curve */
#define CRYPTO_CURVE_X25519
/** Margin of error (in seconds) allowed in signed timestamps
*
* We default to allowing a reasonable margin of error: 12 hours to

695
src/crypto/des.c Normal file
View File

@ -0,0 +1,695 @@
/*
* Copyright (C) 2024 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
*
* DES algorithm
*
* DES was not designed to be implemented in software, and therefore
* contains a large number of bit permutation operations that are
* essentially free in hardware (requiring only wires, no gates) but
* expensive in software.
*
* Since DES is no longer used as a practical block cipher for large
* volumes of data, we optimise for code size, and do not attempt to
* obtain fast throughput.
*
* The algorithm is specified in NIST SP 800-67, downloadable from
* https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-67r2.pdf
*/
#include <stdint.h>
#include <string.h>
#include <errno.h>
#include <byteswap.h>
#include <ipxe/rotate.h>
#include <ipxe/crypto.h>
#include <ipxe/ecb.h>
#include <ipxe/cbc.h>
#include <ipxe/init.h>
#include <ipxe/des.h>
/**
* DES shift schedule
*
* The DES shift schedule (ordered from round 16 down to round 1) is
* {1,2,2,2,2,2,2,1,2,2,2,2,2,2,1,1}. In binary, this may be
* represented as {1,10,10,10,10,10,10,1,10,10,10,10,10,10,1,1} and
* concatenated (without padding) to produce a single binary integer
* 1101010101010110101010101011 (equal to 0x0d556aab in hexadecimal).
*
* This integer may then be consumed LSB-first, where a 1 bit
* indicates a shift and the generation of a round key, and a 0 bit
* indicates a shift without the generation of a round key.
*/
#define DES_SCHEDULE 0x0d556aab
/**
* Define an element pair in a DES S-box
*
* @v x Upper element of element pair
* @v y Lower element of element pair
*
* DES S-box elements are 4-bit values. We encode two values per
* byte, ordering the elements so that the six-bit input value may be
* used directly as a lookup index.
*
* Specifically, if the input value is {r1,c3,c2,c1,c0,r0}, where
* {r1,r0} is the table row index and {c3,c2,c1,c0} is the table
* column index (as used in the DES specification), then:
*
* - {r1,c3,c2,c1,c0} is the byte index into the table
*
* - (4*r0) is the required bit shift to extract the 4-bit value
*/
#define SBYTE( x, y ) ( ( (y) << 4 ) | (x) )
/**
* Define a row pair in a DES S-box
*
* @v x0..xf Upper row of row pair
* @v y0..yf Lower row of row pair
*/
#define SBOX( x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, xa, xb, xc, xd, xe, xf, \
y0, y1, y2, y3, y4, y5, y6, y7, y8, y9, ya, yb, yc, yd, ye, yf ) \
SBYTE ( x0, y0 ), SBYTE ( x1, y1 ), SBYTE ( x2, y2 ), SBYTE ( x3, y3 ),\
SBYTE ( x4, y4 ), SBYTE ( x5, y5 ), SBYTE ( x6, y6 ), SBYTE ( x7, y7 ),\
SBYTE ( x8, y8 ), SBYTE ( x9, y9 ), SBYTE ( xa, ya ), SBYTE ( xb, yb ),\
SBYTE ( xc, yc ), SBYTE ( xd, yd ), SBYTE ( xe, ye ), SBYTE ( xf, yf )
/** DES S-boxes S1..S8 */
static const uint8_t des_s[8][32] = { {
/* S1 */
SBOX ( 14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7,
0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8 ),
SBOX ( 4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0,
15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13 )
}, {
/* S2 */
SBOX ( 15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10,
3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5 ),
SBOX ( 0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15,
13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9 )
}, {
/* S3 */
SBOX ( 10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8,
13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1 ),
SBOX ( 13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7,
1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12 )
}, {
/* S4 */
SBOX ( 7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15,
13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9 ),
SBOX ( 10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4,
3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14 )
}, {
/* S5 */
SBOX ( 2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9,
14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6 ),
SBOX ( 4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14,
11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3 )
}, {
/* S6 */
SBOX ( 12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11,
10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8 ),
SBOX ( 9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6,
4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13 )
}, {
/* S7 */
SBOX ( 4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1,
13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6 ),
SBOX ( 1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2,
6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12 )
}, {
/* S8 */
SBOX ( 13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7,
1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2 ),
SBOX ( 7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8,
2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11 )
} };
/**
* Define a bit index within permuted choice 2 (PC2)
*
* @v bit Bit index
*
* Permuted choice 2 (PC2) is used to select bits from a concatenated
* pair of 28-bit registers ("C" and "D") as part of the key schedule.
* We store these as 32-bit registers and so must add 4 to indexes
* above 28.
*/
#define DES_PC2( x ) ( (x) + ( ( (x) > 28 ) ? 4 : 0 ) )
/**
* Define six bits of permuted choice 2 (PC2)
*
* @v r1:r0 Bits corresponding to S-box row index
* @v c3:c0 Bits corresponding to S-box column index
*
* There are 8 steps within a DES round (one step per S-box). Each
* step requires six bits of the round key, corresponding to the S-box
* input value {r1,c3,c2,c1,c0,r0}, where {r1,r0} is the table row
* index and {c3,c2,c1,c0} is the table column index.
*
* As an optimisation, we store the least significant of the 6 bits in
* the sign bit of a signed 8-bit value, and the remaining 5 bits in
* the least significant 5 bits of the 8-bit value. See the comments
* in des_sbox() for further details.
*/
#define DES_PC2R( r1, c3, c2, c1, c0, r0 ) \
DES_PC2 ( r0 ), /* LSB stored in sign bit */ \
DES_PC2 ( r0 ), /* Unused bit */ \
DES_PC2 ( r0 ), /* Unused bit */ \
DES_PC2 ( r1 ), /* Remaining 5 bits */ \
DES_PC2 ( c3 ), /* ... */ \
DES_PC2 ( c2 ), /* ... */ \
DES_PC2 ( c1 ), /* ... */ \
DES_PC2 ( c0 ) /* ... */
/**
* A DES systematic permutation generator
*
* Many of the permutations used in DES comprise systematic bit
* patterns. We generate these permutations at runtime to save on
* code size.
*/
struct des_generator {
/** Permutation */
uint8_t *permutation;
/** Seed value */
uint32_t seed;
};
/**
* Define a DES permutation generator
*
* @v PERMUTATION Permutation
* @v OFFSET Fixed input bit offset (0 or 1)
* @v INV<n> Input bit index bit <n> should be inverted
* @v BIT<n> Source bit for input bit index bit <n>
* @ret generator Permutation generator
*/
#define DES_GENERATOR( PERMUTATION, OFFSET, INV5, BIT5, INV4, BIT4, \
INV3, BIT3, INV2, BIT2, INV1, BIT1, INV0, BIT0 ) \
{ \
.permutation = (PERMUTATION), \
.seed = ( ( (INV0) << 31 ) | ( (BIT0) << 28 ) | \
( (INV1) << 27 ) | ( (BIT1) << 24 ) | \
( (INV2) << 23 ) | ( (BIT2) << 20 ) | \
( (INV3) << 19 ) | ( (BIT3) << 16 ) | \
( (INV4) << 15 ) | ( (BIT4) << 12 ) | \
( (INV5) << 11 ) | ( (BIT5) << 8 ) | \
( ( uint32_t ) sizeof (PERMUTATION) - 1 ) | \
(OFFSET) ), \
}
/** DES permuted choice 1 (PC1) "C" register */
static uint8_t des_pc1c[29];
/** DES permuted choice 1 (PC1) "D" register */
static uint8_t des_pc1d[33];
/** DES permuted choice 2 (PC2) */
static const uint8_t des_pc2[65] = {
DES_PC2R ( 14, 17, 11, 24, 1, 5 ),
DES_PC2R ( 3, 28, 15, 6, 21, 10 ),
DES_PC2R ( 23, 19, 12, 4, 26, 8 ),
DES_PC2R ( 16, 7, 27, 20, 13, 2 ),
DES_PC2R ( 41, 52, 31, 37, 47, 55 ),
DES_PC2R ( 30, 40, 51, 45, 33, 48 ),
DES_PC2R ( 44, 49, 39, 56, 34, 53 ),
DES_PC2R ( 46, 42, 50, 36, 29, 32 ),
0 /* terminator */
};
/** DES initial permutation (IP) */
static uint8_t des_ip[65];
/** DES data permutation (P) */
static const uint8_t des_p[33] = {
16, 7, 20, 21, 29, 12, 28, 17, 1, 15, 23, 26, 5, 18, 31, 10,
2, 8, 24, 14, 32, 27, 3, 9, 19, 13, 30, 6, 22, 11, 4, 25,
0 /* terminator */
};
/** DES final / inverse initial permutation (FP / IP^-1) */
static uint8_t des_fp[65];
/** DES permutation generators */
static struct des_generator des_generators[] = {
/* The DES initial permutation transforms the bit index
* {x5,x4,x3,x2,x1,x0}+1 into {~x2,~x1,~x0,x4,x3,~x5}+1
*/
DES_GENERATOR ( des_ip, 1, 1, 2, 1, 1, 1, 0, 0, 4, 0, 3, 1, 5 ),
/* The DES final permutation transforms the bit index
* {x5,x4,x3,x2,x1,x0}+1 into {~x0,x2,x1,~x5,~x4,~x3}+1
*
* There is an asymmetry in the DES block diagram for the last
* of the 16 rounds, which is functionally equivalent to
* performing 16 identical rounds and then swapping the left
* and right halves before applying the final permutation. We
* may therefore account for this asymmetry by inverting the
* MSB in each bit index, to point to the corresponding bit in
* the other half.
*
* This is equivalent to using a permutation that transforms
* {x5,x4,x3,x2,x1,x0}+1 into {x0,x2,x1,~x5,~x4,~x3}+1
*/
DES_GENERATOR ( des_fp, 1, 0, 0, 0, 2, 0, 1, 1, 5, 1, 4, 1, 3 ),
/* The "C" half of DES permuted choice 1 (PC1) transforms the
* bit index {x5,x4,x3,x2,x1,x0}+1 into {~x2,~x1,~x0,x5,x4,x3}+1
*/
DES_GENERATOR ( des_pc1c, 1, 1, 2, 1, 1, 1, 0, 0, 5, 0, 4, 0, 3 ),
/* The "D" half of DES permuted choice 1 (PC1) transforms the
* bit index {x5,x4,x3,x2,x1,x0}+1 into {~x2,~x1,~x0,~x5,~x4,~x3}+0
*
* Due to the idosyncratic design choice of using 28-bit
* registers in the DES key expansion schedule, the final four
* permutation values appear at indices [28:31] instead of
* [24:27]. This is adjusted for in @c des_setkey().
*/
DES_GENERATOR ( des_pc1d, 0, 1, 2, 1, 1, 1, 0, 1, 5, 1, 4, 1, 3 ),
};
/**
* Generate DES permutation
*
* @v generator Generator
*/
static __attribute__ (( noinline )) void
des_generate ( struct des_generator *generator ) {
uint8_t *permutation = generator->permutation;
uint32_t seed = generator->seed;
unsigned int index = 0;
uint8_t accum;
uint8_t bit;
/* Generate permutations
*
* This loop is optimised for code size on a
* register-constrained architecture such as i386.
*/
do {
/* Rotate seed to access MSB's bit descriptor */
seed = ror32 ( seed, 8 );
/* Initialise accumulator with six flag bits */
accum = 0xfc;
/* Accumulate bits until all six flag bits are cleared */
do {
/* Extract specified bit from index. Use a
* rotation instead of a shift, since this
* will allow the mask to be elided.
*/
bit = ror8 ( index, ( seed & 0x07 ) );
seed = ror32 ( seed, 3 );
/* Toggle bit if applicable */
bit ^= seed;
seed = ror32 ( seed, 1 );
/* Add bit to accumulator and clear one flag bit */
accum <<= 1;
accum |= ( bit & 0x01 );
} while ( accum & 0x80 );
/* Add constant offset if applicable */
accum += ( seed & 0x01 );
/* Store permutation */
permutation[index] = accum;
/* Loop until reaching length (which is always even) */
} while ( ++index < ( seed & 0xfe ) );
DBGC2 ( permutation, "DES generated permutation %p:\n", permutation );
DBGC2_HDA ( permutation, 0, permutation,
( ( seed & 0xfe ) + 1 /* zero terminator */ ) );
}
/**
* Initialise permutations
*/
static void des_init ( void ) {
unsigned int i;
/* Generate all generated permutations */
for ( i = 0 ; i < ( sizeof ( des_generators ) /
sizeof ( des_generators[0] ) ) ; i++ ) {
des_generate ( &des_generators[i] );
}
}
/** Initialisation function */
struct init_fn des_init_fn __init_fn ( INIT_NORMAL ) = {
.initialise = des_init,
};
/**
* Perform bit permutation
*
* @v permutation Bit permutation (zero-terminated)
* @v in Input value
* @v out Output value
*/
static void des_permute ( const uint8_t *permutation, const uint8_t *in,
uint8_t *out ) {
uint8_t mask = 0x80;
uint8_t accum = 0;
unsigned int bit;
/* Extract individual input bits to construct output value */
while ( ( bit = *(permutation++) ) ) {
bit--;
if ( in[ bit / 8 ] & ( 0x80 >> ( bit % 8 ) ) )
accum |= mask;
*out = accum;
mask = ror8 ( mask, 1 );
if ( mask == 0x80 ) {
out++;
accum = 0;
}
}
}
/**
* Perform DES S-box substitution
*
* @v in 32-bit input value (native endian)
* @v rkey 48-bit round key
* @ret out 32-bit output value (native endian)
*/
static uint32_t des_sbox ( uint32_t in, const union des_round_key *rkey ) {
uint32_t out = 0;
uint32_t lookup;
int32_t key;
uint8_t sub;
unsigned int i;
/* Perform input expansion, key addition, and S-box substitution */
for ( i = 0 ; i < 8 ; i++ ) {
/* Rotate input and output */
out = rol32 ( out, 4 );
in = rol32 ( in, 4 );
/* Extract step key from relevant 6 bits of round key
*
* The least significant of the 6 bits (corresponding
* to bit r0 in the S-box lookup index) is stored in
* the sign bit of the step key byte. It will
* therefore be propagated via sign extension to the
* MSB of the 32-bit step key.
*
* The remaining 5 of the 6 bits (corresponding to
* bits {r1,c3,c2,c1,c0} in the S-box lookup index)
* are stored in the least significant 5 bits of the
* step key byte and will end up in the least
* significant 5 bits of the 32-bit step key.
*/
key = rkey->step[i];
/* Add step key to input to produce S-box lookup index
*
* We do not ever perform an explicit expansion of the
* input value from 32 to 48 bits. Instead, we rotate
* the 32-bit input value by 4 bits on each step, and
* extract the relevant 6 bits.
*
* The least significant of the 6 bits (corresponding
* to bit r0 in the S-box lookup index) is currently
* in the MSB of the 32-bit (rotated) input value.
*
* The remaining 5 of the 6 bits (corresponding to
* bits {r1,c3,c2,c1,c0} in the S-box lookup index)
* are currently in the least significant 5 bits of
* the 32-bit (rotated) input value.
*
* This aligns with the placement of the bits in the
* step key (see above), and we can therefore perform
* a single XOR to add the 6-bit step key to the
* relevant 6 bits of the input value.
*/
lookup = ( in ^ key );
/* Look up S[i][in ^ key] from S-box
*
* We have bits {r1,c3,c2,c1,c0} in the least
* significant 5 bits of the lookup index, and so can
* use the masked lookup index directly as a byte
* index into the relevant S-box to extract the byte
* containing both {r1,c3,c2,c1,c0,'0'} and
* {r1,c3,c2,c1,c0,'1'}.
*
* We then use the MSB of the 32-bit lookup index to
* extract the relevant nibble for the full lookup
* index {r1,c3,c2,c1,c0,r0}.
*/
sub = des_s[i][ lookup & 0x1f ];
sub >>= ( ( lookup >> 29 ) & 4 );
sub &= 0x0f;
/* Substitute S[i][input ^ key] into output */
out |= sub;
}
return out;
}
/**
* Perform a single DES round
*
* @v block DES block
* @v rkey 48-bit round key
*/
static void des_round ( union des_block *block,
const union des_round_key *rkey ) {
union des_dword sbox;
uint32_t left;
uint32_t right;
/* Extract left and right halves L[n-1] and R[n-1] */
left = block->left.dword;
right = block->right.dword;
DBGC2 ( block, "DES L=%08x R=%08x K=%08x%08x", be32_to_cpu ( left ),
be32_to_cpu ( right ), be32_to_cpu ( rkey->dword[0] ),
be32_to_cpu ( rkey->dword[1] ) );
/* L[n] = R[n-1] */
block->left.dword = right;
/* Calculate Feistel function f(R[n-1], K[n]) */
sbox.dword = cpu_to_be32 ( des_sbox ( be32_to_cpu ( right ), rkey ) );
des_permute ( des_p, sbox.byte, block->right.byte );
/* R[n] = L[n-1] + f(R[n-1], K[n]) */
block->right.dword ^= left;
DBGC2 ( block, " => L=%08x R=%08x\n",
be32_to_cpu ( block->left.dword ),
be32_to_cpu ( block->right.dword ) );
}
/**
* Perform all DES rounds
*
* @v in Input DES block
* @v out Output DES block
* @v rkey Starting 48-bit round key
* @v offset Byte offset between round keys
*/
static void des_rounds ( const union des_block *in, union des_block *out,
const union des_round_key *rkey,
ssize_t offset ) {
union des_block tmp;
unsigned int i;
/* Apply initial permutation */
des_permute ( des_ip, in->byte, tmp.byte );
/* Perform all DES rounds, consuming keys in the specified order */
for ( i = 0 ; i < DES_ROUNDS ; i++ ) {
des_round ( &tmp, rkey );
rkey = ( ( ( void * ) rkey ) + offset );
}
/* Apply final permutation */
DBGC ( &tmp, "DES %scrypted %08x%08x => ",
( ( offset > 0 ) ? "en" : "de" ), be32_to_cpu ( in->dword[0] ),
be32_to_cpu ( in->dword[1] ) );
des_permute ( des_fp, tmp.byte, out->byte );
DBGC ( &tmp, "%08x%08x\n", be32_to_cpu ( out->dword[0] ),
be32_to_cpu ( out->dword[1] ) );
}
/**
* Rotate 28-bit word
*
* @v dword 28-bit dword value
* @ret dword Rotated 28-bit dword value
*/
static uint32_t des_rol28 ( uint32_t dword ) {
int32_t sdword;
/* Convert to native-endian */
sdword = be32_to_cpu ( dword );
/* Signed shift right by 4 places to copy bit 31 to bits 27:31 */
sdword >>= 4;
/* Rotate left */
sdword = rol32 ( sdword, 1 );
/* Shift left by 4 places to restore bit positions */
sdword <<= 4;
/* Convert back to big-endian */
dword = cpu_to_be32 ( sdword );
return dword;
}
/**
* Set key
*
* @v ctx Context
* @v key Key
* @v keylen Key length
* @ret rc Return status code
*/
static int des_setkey ( void *ctx, const void *key, size_t keylen ) {
struct des_context *des = ctx;
union des_round_key *rkey = des->rkey;
union des_block reg;
uint32_t schedule;
/* Validate key length */
if ( keylen != DES_BLOCKSIZE )
return -EINVAL;
DBGC ( des, "DES %p new key:\n", des );
DBGC_HDA ( des, 0, key, keylen );
/* Apply permuted choice 1 */
des_permute ( des_pc1c, key, reg.c.byte );
des_permute ( des_pc1d, key, reg.d.byte );
reg.d.byte[3] <<= 4; /* see comment for @c des_pc1d */
DBGC2 ( des, "DES %p C[ 0]=%07x D[ 0]=%07x\n",
des, ( be32_to_cpu ( reg.c.dword ) >> 4 ),
( be32_to_cpu ( reg.d.dword ) >> 4 ) );
/* Generate round keys */
for ( schedule = DES_SCHEDULE ; schedule ; schedule >>= 1 ) {
/* Shift 28-bit words */
reg.c.dword = des_rol28 ( reg.c.dword );
reg.d.dword = des_rol28 ( reg.d.dword );
/* Skip rounds according to shift schedule */
if ( ! ( schedule & 1 ) )
continue;
/* Apply permuted choice 2 */
des_permute ( des_pc2, reg.byte, rkey->byte );
DBGC2 ( des, "DES %p C[%2zd]=%07x D[%2zd]=%07x K[%2zd]="
"%08x%08x\n", des, ( ( rkey - des->rkey ) + 1 ),
( be32_to_cpu ( reg.c.dword ) >> 4 ),
( ( rkey - des->rkey ) + 1 ),
( be32_to_cpu ( reg.d.dword ) >> 4 ),
( ( rkey - des->rkey ) + 1 ),
be32_to_cpu ( rkey->dword[0] ),
be32_to_cpu ( rkey->dword[1] ) );
/* Move to next key */
rkey++;
}
/* Sanity check */
assert ( rkey == &des->rkey[DES_ROUNDS] );
return 0;
}
/**
* Encrypt data
*
* @v ctx Context
* @v src Data to encrypt
* @v dst Buffer for encrypted data
* @v len Length of data
*/
static void des_encrypt ( void *ctx, const void *src, void *dst, size_t len ) {
struct des_context *des = ctx;
/* Sanity check */
assert ( len == DES_BLOCKSIZE );
/* Cipher using keys in forward direction */
des_rounds ( src, dst, &des->rkey[0], sizeof ( des->rkey[0] ) );
}
/**
* Decrypt data
*
* @v ctx Context
* @v src Data to decrypt
* @v dst Buffer for decrypted data
* @v len Length of data
*/
static void des_decrypt ( void *ctx, const void *src, void *dst, size_t len ) {
struct des_context *des = ctx;
/* Sanity check */
assert ( len == DES_BLOCKSIZE );
/* Cipher using keys in reverse direction */
des_rounds ( src, dst, &des->rkey[ DES_ROUNDS - 1 ],
-sizeof ( des->rkey[0] ) );
}
/** Basic DES algorithm */
struct cipher_algorithm des_algorithm = {
.name = "des",
.ctxsize = sizeof ( struct des_context ),
.blocksize = DES_BLOCKSIZE,
.alignsize = 0,
.authsize = 0,
.setkey = des_setkey,
.setiv = cipher_null_setiv,
.encrypt = des_encrypt,
.decrypt = des_decrypt,
.auth = cipher_null_auth,
};
/* DES in Electronic Codebook mode */
ECB_CIPHER ( des_ecb, des_ecb_algorithm,
des_algorithm, struct des_context, DES_BLOCKSIZE );
/* DES in Cipher Block Chaining mode */
CBC_CIPHER ( des_cbc, des_cbc_algorithm,
des_algorithm, struct des_context, DES_BLOCKSIZE );

View File

@ -0,0 +1,61 @@
/*
* Copyright (C) 2015 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/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 ( 15 ) = {
.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 ( 16 ) = {
.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,
};

View File

@ -0,0 +1,60 @@
/*
* Copyright (C) 2015 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_CBC_SHA256 cipher suite */
struct tls_cipher_suite
tls_dhe_rsa_with_aes_128_cbc_sha256 __tls_cipher_suite ( 13 ) = {
.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 ( 14 ) = {
.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,
};

View File

@ -0,0 +1,45 @@
/*
* 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 ( 11 ) = {
.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,
};

View File

@ -0,0 +1,45 @@
/*
* 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 ( 12 ) = {
.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,
};

View File

@ -0,0 +1,61 @@
/*
* Copyright (C) 2024 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/sha1.h>
#include <ipxe/sha256.h>
#include <ipxe/tls.h>
/** TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA cipher suite */
struct tls_cipher_suite
tls_ecdhe_rsa_with_aes_128_cbc_sha __tls_cipher_suite ( 05 ) = {
.code = htons ( TLS_ECDHE_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_ecdhe_exchange_algorithm,
.pubkey = &rsa_algorithm,
.cipher = &aes_cbc_algorithm,
.digest = &sha1_algorithm,
.handshake = &sha256_algorithm,
};
/** TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA cipher suite */
struct tls_cipher_suite
tls_ecdhe_rsa_with_aes_256_cbc_sha __tls_cipher_suite ( 06 ) = {
.code = htons ( TLS_ECDHE_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_ecdhe_exchange_algorithm,
.pubkey = &rsa_algorithm,
.cipher = &aes_cbc_algorithm,
.digest = &sha1_algorithm,
.handshake = &sha256_algorithm,
};

View File

@ -0,0 +1,45 @@
/*
* Copyright (C) 2024 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_ECDHE_RSA_WITH_AES_128_CBC_SHA256 cipher suite */
struct tls_cipher_suite
tls_ecdhe_rsa_with_aes_128_cbc_sha256 __tls_cipher_suite ( 03 ) = {
.code = htons ( TLS_ECDHE_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_ecdhe_exchange_algorithm,
.pubkey = &rsa_algorithm,
.cipher = &aes_cbc_algorithm,
.digest = &sha256_algorithm,
.handshake = &sha256_algorithm,
};

View File

@ -0,0 +1,45 @@
/*
* Copyright (C) 2024 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_ECDHE_RSA_WITH_AES_256_CBC_SHA384 cipher suite */
struct tls_cipher_suite
tls_ecdhe_rsa_with_aes_256_cbc_sha384 __tls_cipher_suite ( 04 ) = {
.code = htons ( TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 ),
.key_len = ( 256 / 8 ),
.fixed_iv_len = 0,
.record_iv_len = AES_BLOCKSIZE,
.mac_len = SHA384_DIGEST_SIZE,
.exchange = &tls_ecdhe_exchange_algorithm,
.pubkey = &rsa_algorithm,
.cipher = &aes_cbc_algorithm,
.digest = &sha384_algorithm,
.handshake = &sha384_algorithm,
};

View File

@ -0,0 +1,45 @@
/*
* Copyright (C) 2024 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_ECDHE_RSA_WITH_AES_128_GCM_SHA256 cipher suite */
struct tls_cipher_suite
tls_ecdhe_rsa_with_aes_128_gcm_sha256 __tls_cipher_suite ( 01 ) = {
.code = htons ( TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 ),
.key_len = ( 128 / 8 ),
.fixed_iv_len = 4,
.record_iv_len = 8,
.mac_len = 0,
.exchange = &tls_ecdhe_exchange_algorithm,
.pubkey = &rsa_algorithm,
.cipher = &aes_gcm_algorithm,
.digest = &sha256_algorithm,
.handshake = &sha256_algorithm,
};

View File

@ -0,0 +1,45 @@
/*
* Copyright (C) 2024 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_ECDHE_RSA_WITH_AES_256_GCM_SHA384 cipher suite */
struct tls_cipher_suite
tls_ecdhe_rsa_with_aes_256_gcm_sha384 __tls_cipher_suite ( 02 ) = {
.code = htons ( TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 ),
.key_len = ( 256 / 8 ),
.fixed_iv_len = 4,
.record_iv_len = 8,
.mac_len = 0,
.exchange = &tls_ecdhe_exchange_algorithm,
.pubkey = &rsa_algorithm,
.cipher = &aes_gcm_algorithm,
.digest = &sha384_algorithm,
.handshake = &sha384_algorithm,
};

View File

@ -0,0 +1,45 @@
/*
* Copyright (C) 2024 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/x25519.h>
#include <ipxe/asn1.h>
#include <ipxe/tls.h>
/** "x25519" object identifier */
static uint8_t oid_x25519[] = { ASN1_OID_X25519 };
/** "x25519" OID-identified algorithm */
struct asn1_algorithm x25519_algorithm __asn1_algorithm = {
.name = "x25519",
.curve = &x25519_curve,
.oid = ASN1_CURSOR ( oid_x25519 ),
};
/** X25519 named curve */
struct tls_named_curve tls_x25519_named_curve __tls_named_curve ( 01 ) = {
.curve = &x25519_curve,
.code = htons ( TLS_NAMED_CURVE_X25519 ),
};

View File

@ -30,39 +30,9 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#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 ( 15 ) = {
tls_rsa_with_aes_128_cbc_sha __tls_cipher_suite ( 25 ) = {
.code = htons ( TLS_RSA_WITH_AES_128_CBC_SHA ),
.key_len = ( 128 / 8 ),
.fixed_iv_len = 0,
@ -77,7 +47,7 @@ tls_rsa_with_aes_128_cbc_sha __tls_cipher_suite ( 15 ) = {
/** TLS_RSA_WITH_AES_256_CBC_SHA cipher suite */
struct tls_cipher_suite
tls_rsa_with_aes_256_cbc_sha __tls_cipher_suite ( 16 ) = {
tls_rsa_with_aes_256_cbc_sha __tls_cipher_suite ( 26 ) = {
.code = htons ( TLS_RSA_WITH_AES_256_CBC_SHA ),
.key_len = ( 256 / 8 ),
.fixed_iv_len = 0,

View File

@ -29,39 +29,9 @@ 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 ( 13 ) = {
tls_rsa_with_aes_128_cbc_sha256 __tls_cipher_suite ( 23 ) = {
.code = htons ( TLS_RSA_WITH_AES_128_CBC_SHA256 ),
.key_len = ( 128 / 8 ),
.fixed_iv_len = 0,
@ -76,7 +46,7 @@ tls_rsa_with_aes_128_cbc_sha256 __tls_cipher_suite ( 13 ) = {
/** TLS_RSA_WITH_AES_256_CBC_SHA256 cipher suite */
struct tls_cipher_suite
tls_rsa_with_aes_256_cbc_sha256 __tls_cipher_suite ( 14 ) = {
tls_rsa_with_aes_256_cbc_sha256 __tls_cipher_suite ( 24 ) = {
.code = htons ( TLS_RSA_WITH_AES_256_CBC_SHA256 ),
.key_len = ( 256 / 8 ),
.fixed_iv_len = 0,

View File

@ -29,24 +29,9 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#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 ) = {
tls_rsa_with_aes_128_gcm_sha256 __tls_cipher_suite ( 21 ) = {
.code = htons ( TLS_RSA_WITH_AES_128_GCM_SHA256 ),
.key_len = ( 128 / 8 ),
.fixed_iv_len = 4,

View File

@ -29,24 +29,9 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#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 ) = {
tls_rsa_with_aes_256_gcm_sha384 __tls_cipher_suite ( 22 ) = {
.code = htons ( TLS_RSA_WITH_AES_256_GCM_SHA384 ),
.key_len = ( 256 / 8 ),
.fixed_iv_len = 4,

View File

@ -59,7 +59,9 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <stdint.h>
#include <string.h>
#include <assert.h>
#include <errno.h>
#include <ipxe/init.h>
#include <ipxe/crypto.h>
#include <ipxe/x25519.h>
/** X25519 reduction constant
@ -299,6 +301,11 @@ static const uint8_t x25519_121665_raw[] = { 0x01, 0xdb, 0x41 };
/** Constant 121665 (used in the Montgomery ladder) */
static union x25519_oct258 x25519_121665;
/** Constant g=9 (the group generator) */
static struct x25519_value x25519_generator = {
.raw = { 9, }
};
/**
* Initialise constants
*
@ -781,10 +788,11 @@ static void x25519_reverse ( struct x25519_value *value ) {
* @v base Base point
* @v scalar Scalar multiple
* @v result Point to hold result (may overlap base point)
* @ret rc Return status code
*/
void x25519_key ( const struct x25519_value *base,
const struct x25519_value *scalar,
struct x25519_value *result ) {
int x25519_key ( const struct x25519_value *base,
const struct x25519_value *scalar,
struct x25519_value *result ) {
struct x25519_value *tmp = result;
union x25519_quad257 point;
@ -805,4 +813,32 @@ void x25519_key ( const struct x25519_value *base,
/* Reverse result */
bigint_done ( &point.value, result->raw, sizeof ( result->raw ) );
x25519_reverse ( result );
/* Fail if result was all zeros (as required by RFC8422) */
return ( bigint_is_zero ( &point.value ) ? -EPERM : 0 );
}
/**
* Multiply scalar by curve point
*
* @v base Base point (or NULL to use generator)
* @v scalar Scalar multiple
* @v result Result point to fill in
* @ret rc Return status code
*/
static int x25519_curve_multiply ( const void *base, const void *scalar,
void *result ) {
/* Use base point if applicable */
if ( ! base )
base = &x25519_generator;
return x25519_key ( base, scalar, result );
}
/** X25519 elliptic curve */
struct elliptic_curve x25519_curve = {
.name = "x25519",
.keysize = sizeof ( struct x25519_value ),
.multiply = x25519_curve_multiply,
};

View File

@ -722,7 +722,9 @@ static int bnxt_hwrm_ver_get ( struct bnxt *bp )
( resp->dev_caps_cfg & SHORT_CMD_REQUIRED ) )
FLAG_SET ( bp->flags, BNXT_FLAG_HWRM_SHORT_CMD_SUPP );
bp->hwrm_max_ext_req_len = resp->max_ext_req_len;
if ( bp->chip_num == CHIP_NUM_57500 )
if ( ( bp->chip_num == CHIP_NUM_57508 ) ||
( bp->chip_num == CHIP_NUM_57504 ) ||
( bp->chip_num == CHIP_NUM_57502 ) )
bp->thor = 1;
dbg_fw_ver ( resp, bp->hwrm_cmd_timeout );
return STATUS_SUCCESS;

View File

@ -868,4 +868,6 @@ struct bnxt {
FUNC_VF_CFG_REQ_ENABLES_ASYNC_EVENT_CR | \
FUNC_VF_CFG_REQ_ENABLES_DFLT_MAC_ADDR)
#define CHIP_NUM_57500 0x1750
#define CHIP_NUM_57508 0x1750
#define CHIP_NUM_57504 0x1751
#define CHIP_NUM_57502 0x1752

View File

@ -187,6 +187,11 @@ struct asn1_builder_header {
ASN1_OID_SINGLE ( 3 ), ASN1_OID_SINGLE ( 2 ), \
ASN1_OID_SINGLE ( 26 )
/** ASN.1 OID for id-x25519 (1.3.101.110) */
#define ASN1_OID_X25519 \
ASN1_OID_INITIAL ( 1, 3 ), ASN1_OID_SINGLE ( 101 ), \
ASN1_OID_SINGLE ( 110 )
/** ASN.1 OID for id-sha256 (2.16.840.1.101.3.4.2.1) */
#define ASN1_OID_SHA256 \
ASN1_OID_INITIAL ( 2, 16 ), ASN1_OID_DOUBLE ( 840 ), \
@ -312,6 +317,8 @@ struct asn1_algorithm {
struct pubkey_algorithm *pubkey;
/** Digest algorithm (if applicable) */
struct digest_algorithm *digest;
/** Elliptic curve (if applicable) */
struct elliptic_curve *curve;
};
/** ASN.1 OID-identified algorithms */

View File

@ -77,19 +77,19 @@ static void _cbc_name ## _setiv ( void *ctx, const void *iv, \
size_t ivlen ) { \
struct _cbc_name ## _context * _cbc_name ## _ctx = ctx; \
cbc_setiv ( &_cbc_name ## _ctx->raw_ctx, iv, ivlen, \
&_raw_cipher, &aes_cbc_ctx->cbc_ctx ); \
&_raw_cipher, &_cbc_name ## _ctx->cbc_ctx ); \
} \
static void _cbc_name ## _encrypt ( void *ctx, const void *src, \
void *dst, size_t len ) { \
struct _cbc_name ## _context * _cbc_name ## _ctx = ctx; \
cbc_encrypt ( &_cbc_name ## _ctx->raw_ctx, src, dst, len, \
&_raw_cipher, &aes_cbc_ctx->cbc_ctx ); \
&_raw_cipher, &_cbc_name ## _ctx->cbc_ctx ); \
} \
static void _cbc_name ## _decrypt ( void *ctx, const void *src, \
void *dst, size_t len ) { \
struct _cbc_name ## _context * _cbc_name ## _ctx = ctx; \
cbc_decrypt ( &_cbc_name ## _ctx->raw_ctx, src, dst, len, \
&_raw_cipher, &aes_cbc_ctx->cbc_ctx ); \
&_raw_cipher, &_cbc_name ## _ctx->cbc_ctx ); \
} \
struct cipher_algorithm _cbc_cipher = { \
.name = #_cbc_name, \

View File

@ -195,6 +195,23 @@ struct pubkey_algorithm {
const void *public_key, size_t public_key_len );
};
/** An elliptic curve */
struct elliptic_curve {
/** Curve name */
const char *name;
/** Key size */
size_t keysize;
/** Multiply scalar by curve point
*
* @v base Base point (or NULL to use generator)
* @v scalar Scalar multiple
* @v result Result point to fill in
* @ret rc Return status code
*/
int ( * multiply ) ( const void *base, const void *scalar,
void *result );
};
static inline void digest_init ( struct digest_algorithm *digest,
void *ctx ) {
digest->init ( ctx );
@ -302,6 +319,12 @@ static inline int pubkey_match ( struct pubkey_algorithm *pubkey,
public_key_len );
}
static inline int elliptic_multiply ( struct elliptic_curve *curve,
const void *base, const void *scalar,
void *result ) {
return curve->multiply ( base, scalar, result );
}
extern void digest_null_init ( void *ctx );
extern void digest_null_update ( void *ctx, const void *src, size_t len );
extern void digest_null_final ( void *ctx, void *out );

91
src/include/ipxe/des.h Normal file
View File

@ -0,0 +1,91 @@
#ifndef _IPXE_DES_H
#define _IPXE_DES_H
/** @file
*
* DES algorithm
*
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <ipxe/crypto.h>
/** A DES 32-bit dword value
*
* DES views data as 64-bit big-endian values, typically handled as a
* most-significant "left" half and a least-significant "right" half.
*/
union des_dword {
/** Raw bytes */
uint8_t byte[4];
/** 32-bit big-endian dword */
uint32_t dword;
};
/** A DES 64-bit block */
union des_block {
/** Raw bytes */
uint8_t byte[8];
/** 32-bit big-endian dwords */
uint32_t dword[2];
/** Named left and right halves */
struct {
/** Left (most significant) half */
union des_dword left;
/** Right (least significant) half */
union des_dword right;
};
/** Named "C" and "D" halves */
struct {
/** "C" (most significant) half */
union des_dword c;
/** "D" (least significant) half */
union des_dword d;
};
};
/** DES blocksize */
#define DES_BLOCKSIZE sizeof ( union des_block )
/** A DES round key
*
* A DES round key is a 48-bit value, consumed as 8 groups of 6 bits.
* We store these as 8 separate bytes, for simplicity of consumption.
*/
union des_round_key {
/** Raw bytes */
uint8_t byte[8];
/** 32-bit big-endian dwords */
uint32_t dword[2];
/** 6-bit step key byte
*
* There are 8 steps within a DES round (one step per S-box).
* Each step requires six bits of the round key.
*
* As an optimisation, we store the least significant of the 6
* bits in the sign bit of a signed 8-bit value, and the
* remaining 5 bits in the least significant 5 bits of the
* 8-bit value. See the comments in des_sbox() for further
* details.
*/
int8_t step[8];
};
/** Number of DES rounds */
#define DES_ROUNDS 16
/** DES context */
struct des_context {
/** Round keys */
union des_round_key rkey[DES_ROUNDS];
};
/** DES context size */
#define DES_CTX_SIZE sizeof ( struct des_context )
extern struct cipher_algorithm des_algorithm;
extern struct cipher_algorithm des_ecb_algorithm;
extern struct cipher_algorithm des_cbc_algorithm;
#endif /* _IPXE_DES_H */

View File

@ -407,6 +407,8 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#define ERRFILE_efi_rng ( ERRFILE_OTHER | 0x005c0000 )
#define ERRFILE_efi_shim ( ERRFILE_OTHER | 0x005d0000 )
#define ERRFILE_efi_settings ( ERRFILE_OTHER | 0x005e0000 )
#define ERRFILE_x25519 ( ERRFILE_OTHER | 0x005f0000 )
#define ERRFILE_des ( ERRFILE_OTHER | 0x00600000 )
/** @} */

View File

@ -96,6 +96,12 @@ struct tls_header {
#define TLS_RSA_WITH_AES_256_GCM_SHA384 0x009d
#define TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 0x009e
#define TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 0x009f
#define TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA 0xc013
#define TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA 0xc014
#define TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 0xc027
#define TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 0xc028
#define TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 0xc02f
#define TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 0xc030
/* TLS hash algorithm identifiers */
#define TLS_MD5_ALGORITHM 1
@ -119,6 +125,10 @@ struct tls_header {
#define TLS_MAX_FRAGMENT_LENGTH_2048 3
#define TLS_MAX_FRAGMENT_LENGTH_4096 4
/* TLS named curve extension */
#define TLS_NAMED_CURVE 10
#define TLS_NAMED_CURVE_X25519 29
/* TLS signature algorithms extension */
#define TLS_SIGNATURE_ALGORITHMS 13
@ -205,6 +215,25 @@ struct tls_cipher_suite {
#define __tls_cipher_suite( pref ) \
__table_entry ( TLS_CIPHER_SUITES, pref )
/** TLS named curved type */
#define TLS_NAMED_CURVE_TYPE 3
/** A TLS named curve */
struct tls_named_curve {
/** Elliptic curve */
struct elliptic_curve *curve;
/** Numeric code (in network-endian order) */
uint16_t code;
};
/** TLS named curve table */
#define TLS_NAMED_CURVES \
__table ( struct tls_named_curve, "tls_named_curves" )
/** Declare a TLS named curve */
#define __tls_named_curve( pref ) \
__table_entry ( TLS_NAMED_CURVES, pref )
/** A TLS cipher specification */
struct tls_cipherspec {
/** Cipher suite */
@ -425,6 +454,7 @@ struct tls_connection {
extern struct tls_key_exchange_algorithm tls_pubkey_exchange_algorithm;
extern struct tls_key_exchange_algorithm tls_dhe_exchange_algorithm;
extern struct tls_key_exchange_algorithm tls_ecdhe_exchange_algorithm;
extern int add_tls ( struct interface *xfer, const char *name,
struct x509_root *root, struct private_key *key );

View File

@ -11,6 +11,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <stdint.h>
#include <ipxe/bigint.h>
#include <ipxe/crypto.h>
/** X25519 unsigned big integer size
*
@ -84,8 +85,10 @@ extern void x25519_multiply ( const union x25519_oct258 *multiplicand,
extern void x25519_invert ( const union x25519_oct258 *invertend,
union x25519_quad257 *result );
extern void x25519_reduce ( union x25519_quad257 *value );
extern void x25519_key ( const struct x25519_value *base,
const struct x25519_value *scalar,
struct x25519_value *result );
extern int x25519_key ( const struct x25519_value *base,
const struct x25519_value *scalar,
struct x25519_value *result );
extern struct elliptic_curve x25519_curve;
#endif /* _IPXE_X25519_H */

View File

@ -158,6 +158,10 @@ FILE_LICENCE ( GPL2_OR_LATER );
#define EINFO_ENOTSUP_VERSION \
__einfo_uniqify ( EINFO_ENOTSUP, 0x04, \
"Unsupported protocol version" )
#define ENOTSUP_CURVE __einfo_error ( EINFO_ENOTSUP_CURVE )
#define EINFO_ENOTSUP_CURVE \
__einfo_uniqify ( EINFO_ENOTSUP, 0x05, \
"Unsupported elliptic curve" )
#define EPERM_ALERT __einfo_error ( EINFO_EPERM_ALERT )
#define EINFO_EPERM_ALERT \
__einfo_uniqify ( EINFO_EPERM, 0x01, \
@ -1042,6 +1046,35 @@ tls_signature_hash_digest ( struct tls_signature_hash_id code ) {
return NULL;
}
/******************************************************************************
*
* Ephemeral Elliptic Curve Diffie-Hellman key exchange
*
******************************************************************************
*/
/** Number of supported named curves */
#define TLS_NUM_NAMED_CURVES table_num_entries ( TLS_NAMED_CURVES )
/**
* Identify named curve
*
* @v named_curve Named curve specification
* @ret curve Named curve, or NULL
*/
static struct tls_named_curve *
tls_find_named_curve ( unsigned int named_curve ) {
struct tls_named_curve *curve;
/* Identify named curve */
for_each_table_entry ( curve, TLS_NAMED_CURVES ) {
if ( curve->code == named_curve )
return curve;
}
return NULL;
}
/******************************************************************************
*
* Record handling
@ -1121,6 +1154,67 @@ static int tls_client_hello ( struct tls_connection *tls,
size_t len ) ) {
struct tls_session *session = tls->session;
size_t name_len = strlen ( session->name );
struct {
uint16_t type;
uint16_t len;
struct {
uint16_t len;
struct {
uint8_t type;
uint16_t len;
uint8_t name[name_len];
} __attribute__ (( packed )) list[1];
} __attribute__ (( packed )) data;
} __attribute__ (( packed )) *server_name_ext;
struct {
uint16_t type;
uint16_t len;
struct {
uint8_t max;
} __attribute__ (( packed )) data;
} __attribute__ (( packed )) *max_fragment_length_ext;
struct {
uint16_t type;
uint16_t len;
struct {
uint16_t len;
struct tls_signature_hash_id
code[TLS_NUM_SIG_HASH_ALGORITHMS];
} __attribute__ (( packed )) data;
} __attribute__ (( packed )) *signature_algorithms_ext;
struct {
uint16_t type;
uint16_t len;
struct {
uint8_t len;
uint8_t data[ tls->secure_renegotiation ?
sizeof ( tls->verify.client ) :0 ];
} __attribute__ (( packed )) data;
} __attribute__ (( packed )) *renegotiation_info_ext;
struct {
uint16_t type;
uint16_t len;
struct {
uint8_t data[session->ticket_len];
} __attribute__ (( packed )) data;
} __attribute__ (( packed )) *session_ticket_ext;
struct {
uint16_t type;
uint16_t len;
struct {
uint16_t len;
uint16_t code[TLS_NUM_NAMED_CURVES];
} __attribute__ (( packed )) data;
} __attribute__ (( packed )) *named_curve_ext;
struct {
typeof ( *server_name_ext ) server_name;
typeof ( *max_fragment_length_ext ) max_fragment_length;
typeof ( *signature_algorithms_ext ) signature_algorithms;
typeof ( *renegotiation_info_ext ) renegotiation_info;
typeof ( *session_ticket_ext ) session_ticket;
typeof ( *named_curve_ext )
named_curve[TLS_NUM_NAMED_CURVES ? 1 : 0];
} __attribute__ (( packed )) *extensions;
struct {
uint32_t type_length;
uint16_t version;
@ -1132,45 +1226,11 @@ static int tls_client_hello ( struct tls_connection *tls,
uint8_t compression_methods_len;
uint8_t compression_methods[1];
uint16_t extensions_len;
struct {
uint16_t server_name_type;
uint16_t server_name_len;
struct {
uint16_t len;
struct {
uint8_t type;
uint16_t len;
uint8_t name[name_len];
} __attribute__ (( packed )) list[1];
} __attribute__ (( packed )) server_name;
uint16_t max_fragment_length_type;
uint16_t max_fragment_length_len;
struct {
uint8_t max;
} __attribute__ (( packed )) max_fragment_length;
uint16_t signature_algorithms_type;
uint16_t signature_algorithms_len;
struct {
uint16_t len;
struct tls_signature_hash_id
code[TLS_NUM_SIG_HASH_ALGORITHMS];
} __attribute__ (( packed )) signature_algorithms;
uint16_t renegotiation_info_type;
uint16_t renegotiation_info_len;
struct {
uint8_t len;
uint8_t data[ tls->secure_renegotiation ?
sizeof ( tls->verify.client ) :0];
} __attribute__ (( packed )) renegotiation_info;
uint16_t session_ticket_type;
uint16_t session_ticket_len;
struct {
uint8_t data[session->ticket_len];
} __attribute__ (( packed )) session_ticket;
} __attribute__ (( packed )) extensions;
typeof ( *extensions ) extensions;
} __attribute__ (( packed )) hello;
struct tls_cipher_suite *suite;
struct tls_signature_hash_algorithm *sighash;
struct tls_named_curve *curve;
unsigned int i;
/* Construct record */
@ -1188,43 +1248,66 @@ static int tls_client_hello ( struct tls_connection *tls,
hello.cipher_suites[i++] = suite->code;
hello.compression_methods_len = sizeof ( hello.compression_methods );
hello.extensions_len = htons ( sizeof ( hello.extensions ) );
hello.extensions.server_name_type = htons ( TLS_SERVER_NAME );
hello.extensions.server_name_len
= htons ( sizeof ( hello.extensions.server_name ) );
hello.extensions.server_name.len
= htons ( sizeof ( hello.extensions.server_name.list ) );
hello.extensions.server_name.list[0].type = TLS_SERVER_NAME_HOST_NAME;
hello.extensions.server_name.list[0].len
= htons ( sizeof ( hello.extensions.server_name.list[0].name ));
memcpy ( hello.extensions.server_name.list[0].name, session->name,
sizeof ( hello.extensions.server_name.list[0].name ) );
hello.extensions.max_fragment_length_type
= htons ( TLS_MAX_FRAGMENT_LENGTH );
hello.extensions.max_fragment_length_len
= htons ( sizeof ( hello.extensions.max_fragment_length ) );
hello.extensions.max_fragment_length.max
= TLS_MAX_FRAGMENT_LENGTH_4096;
hello.extensions.signature_algorithms_type
= htons ( TLS_SIGNATURE_ALGORITHMS );
hello.extensions.signature_algorithms_len
= htons ( sizeof ( hello.extensions.signature_algorithms ) );
hello.extensions.signature_algorithms.len
= htons ( sizeof ( hello.extensions.signature_algorithms.code));
extensions = &hello.extensions;
/* Construct server name extension */
server_name_ext = &extensions->server_name;
server_name_ext->type = htons ( TLS_SERVER_NAME );
server_name_ext->len = htons ( sizeof ( server_name_ext->data ) );
server_name_ext->data.len
= htons ( sizeof ( server_name_ext->data.list ) );
server_name_ext->data.list[0].type = TLS_SERVER_NAME_HOST_NAME;
server_name_ext->data.list[0].len
= htons ( sizeof ( server_name_ext->data.list[0].name ) );
memcpy ( server_name_ext->data.list[0].name, session->name,
sizeof ( server_name_ext->data.list[0].name ) );
/* Construct maximum fragment length extension */
max_fragment_length_ext = &extensions->max_fragment_length;
max_fragment_length_ext->type = htons ( TLS_MAX_FRAGMENT_LENGTH );
max_fragment_length_ext->len
= htons ( sizeof ( max_fragment_length_ext->data ) );
max_fragment_length_ext->data.max = TLS_MAX_FRAGMENT_LENGTH_4096;
/* Construct supported signature algorithms extension */
signature_algorithms_ext = &extensions->signature_algorithms;
signature_algorithms_ext->type = htons ( TLS_SIGNATURE_ALGORITHMS );
signature_algorithms_ext->len
= htons ( sizeof ( signature_algorithms_ext->data ) );
signature_algorithms_ext->data.len
= htons ( sizeof ( signature_algorithms_ext->data.code ) );
i = 0 ; for_each_table_entry ( sighash, TLS_SIG_HASH_ALGORITHMS )
hello.extensions.signature_algorithms.code[i++] = sighash->code;
hello.extensions.renegotiation_info_type
= htons ( TLS_RENEGOTIATION_INFO );
hello.extensions.renegotiation_info_len
= htons ( sizeof ( hello.extensions.renegotiation_info ) );
hello.extensions.renegotiation_info.len
= sizeof ( hello.extensions.renegotiation_info.data );
memcpy ( hello.extensions.renegotiation_info.data, tls->verify.client,
sizeof ( hello.extensions.renegotiation_info.data ) );
hello.extensions.session_ticket_type = htons ( TLS_SESSION_TICKET );
hello.extensions.session_ticket_len
= htons ( sizeof ( hello.extensions.session_ticket ) );
memcpy ( hello.extensions.session_ticket.data, session->ticket,
sizeof ( hello.extensions.session_ticket.data ) );
signature_algorithms_ext->data.code[i++] = sighash->code;
/* Construct renegotiation information extension */
renegotiation_info_ext = &extensions->renegotiation_info;
renegotiation_info_ext->type = htons ( TLS_RENEGOTIATION_INFO );
renegotiation_info_ext->len
= htons ( sizeof ( renegotiation_info_ext->data ) );
renegotiation_info_ext->data.len
= sizeof ( renegotiation_info_ext->data.data );
memcpy ( renegotiation_info_ext->data.data, tls->verify.client,
sizeof ( renegotiation_info_ext->data.data ) );
/* Construct session ticket extension */
session_ticket_ext = &extensions->session_ticket;
session_ticket_ext->type = htons ( TLS_SESSION_TICKET );
session_ticket_ext->len
= htons ( sizeof ( session_ticket_ext->data ) );
memcpy ( session_ticket_ext->data.data, session->ticket,
sizeof ( session_ticket_ext->data.data ) );
/* Construct named curves extension, if applicable */
if ( sizeof ( extensions->named_curve ) ) {
named_curve_ext = &extensions->named_curve[0];
named_curve_ext->type = htons ( TLS_NAMED_CURVE );
named_curve_ext->len
= htons ( sizeof ( named_curve_ext->data ) );
named_curve_ext->data.len
= htons ( sizeof ( named_curve_ext->data.code ) );
i = 0 ; for_each_table_entry ( curve, TLS_NAMED_CURVES )
named_curve_ext->data.code[i++] = curve->code;
}
return action ( tls, &hello, sizeof ( hello ) );
}
@ -1336,13 +1419,6 @@ static int tls_send_client_key_exchange_pubkey ( struct tls_connection *tls ) {
tls_generate_master_secret ( tls, &pre_master_secret,
sizeof ( pre_master_secret ) );
/* Generate keys */
if ( ( rc = tls_generate_keys ( tls ) ) != 0 ) {
DBGC ( tls, "TLS %p could not generate keys: %s\n",
tls, strerror ( rc ) );
return rc;
}
/* Encrypt pre-master secret using server's public key */
memset ( &key_xchg, 0, sizeof ( key_xchg ) );
len = pubkey_encrypt ( pubkey, cipherspec->pubkey_ctx,
@ -1374,21 +1450,18 @@ struct tls_key_exchange_algorithm tls_pubkey_exchange_algorithm = {
};
/**
* Transmit Client Key Exchange record using DHE key exchange
* Verify Diffie-Hellman parameter signature
*
* @v tls TLS connection
* @v param_len Diffie-Hellman parameter length
* @ret rc Return status code
*/
static int tls_send_client_key_exchange_dhe ( struct tls_connection *tls ) {
static int tls_verify_dh_params ( struct tls_connection *tls,
size_t param_len ) {
struct tls_cipherspec *cipherspec = &tls->tx_cipherspec_pending;
struct pubkey_algorithm *pubkey;
struct digest_algorithm *digest;
int use_sig_hash = tls_version ( tls, TLS_VERSION_TLS_1_2 );
uint8_t private[ sizeof ( tls->client_random.random ) ];
const struct {
uint16_t len;
uint8_t data[0];
} __attribute__ (( packed )) *dh_val[3];
const struct {
struct tls_signature_hash_id sig_hash[use_sig_hash];
uint16_t signature_len;
@ -1396,7 +1469,91 @@ static int tls_send_client_key_exchange_dhe ( struct tls_connection *tls ) {
} __attribute__ (( packed )) *sig;
const void *data;
size_t remaining;
int rc;
/* Signature follows parameters */
assert ( param_len <= tls->server_key_len );
data = ( tls->server_key + param_len );
remaining = ( tls->server_key_len - param_len );
/* Parse signature from ServerKeyExchange */
sig = data;
if ( ( sizeof ( *sig ) > remaining ) ||
( ntohs ( sig->signature_len ) > ( remaining -
sizeof ( *sig ) ) ) ) {
DBGC ( tls, "TLS %p received underlength ServerKeyExchange\n",
tls );
DBGC_HDA ( tls, 0, tls->server_key, tls->server_key_len );
return -EINVAL_KEY_EXCHANGE;
}
/* Identify signature and hash algorithm */
if ( use_sig_hash ) {
pubkey = tls_signature_hash_pubkey ( sig->sig_hash[0] );
digest = tls_signature_hash_digest ( sig->sig_hash[0] );
if ( ( ! pubkey ) || ( ! digest ) ) {
DBGC ( tls, "TLS %p ServerKeyExchange unsupported "
"signature and hash algorithm\n", tls );
return -ENOTSUP_SIG_HASH;
}
if ( pubkey != cipherspec->suite->pubkey ) {
DBGC ( tls, "TLS %p ServerKeyExchange incorrect "
"signature algorithm %s (expected %s)\n", tls,
pubkey->name, cipherspec->suite->pubkey->name );
return -EPERM_KEY_EXCHANGE;
}
} else {
pubkey = cipherspec->suite->pubkey;
digest = &md5_sha1_algorithm;
}
/* Verify signature */
{
const void *signature = sig->signature;
size_t signature_len = ntohs ( sig->signature_len );
uint8_t ctx[digest->ctxsize];
uint8_t hash[digest->digestsize];
/* Calculate digest */
digest_init ( digest, ctx );
digest_update ( digest, ctx, &tls->client_random,
sizeof ( tls->client_random ) );
digest_update ( digest, ctx, tls->server_random,
sizeof ( tls->server_random ) );
digest_update ( digest, ctx, tls->server_key, param_len );
digest_final ( digest, ctx, hash );
/* Verify signature */
if ( ( rc = pubkey_verify ( pubkey, cipherspec->pubkey_ctx,
digest, hash, signature,
signature_len ) ) != 0 ) {
DBGC ( tls, "TLS %p ServerKeyExchange failed "
"verification\n", tls );
DBGC_HDA ( tls, 0, tls->server_key,
tls->server_key_len );
return -EPERM_KEY_EXCHANGE;
}
}
return 0;
}
/**
* Transmit Client Key Exchange record using DHE key exchange
*
* @v tls TLS connection
* @ret rc Return status code
*/
static int tls_send_client_key_exchange_dhe ( struct tls_connection *tls ) {
uint8_t private[ sizeof ( tls->client_random.random ) ];
const struct {
uint16_t len;
uint8_t data[0];
} __attribute__ (( packed )) *dh_val[3];
const void *data;
size_t remaining;
size_t frag_len;
size_t param_len;
unsigned int i;
int rc;
@ -1419,68 +1576,11 @@ static int tls_send_client_key_exchange_dhe ( struct tls_connection *tls ) {
data += frag_len;
remaining -= frag_len;
}
sig = data;
if ( ( sizeof ( *sig ) > remaining ) ||
( ntohs ( sig->signature_len ) > ( remaining -
sizeof ( *sig ) ) ) ) {
DBGC ( tls, "TLS %p received underlength ServerKeyExchange\n",
tls );
DBGC_HDA ( tls, 0, tls->server_key, tls->server_key_len );
rc = -EINVAL_KEY_EXCHANGE;
goto err_header;
}
param_len = ( tls->server_key_len - remaining );
/* Identify signature and hash algorithm */
if ( use_sig_hash ) {
pubkey = tls_signature_hash_pubkey ( sig->sig_hash[0] );
digest = tls_signature_hash_digest ( sig->sig_hash[0] );
if ( ( ! pubkey ) || ( ! digest ) ) {
DBGC ( tls, "TLS %p ServerKeyExchange unsupported "
"signature and hash algorithm\n", tls );
rc = -ENOTSUP_SIG_HASH;
goto err_sig_hash;
}
if ( pubkey != cipherspec->suite->pubkey ) {
DBGC ( tls, "TLS %p ServerKeyExchange incorrect "
"signature algorithm %s (expected %s)\n", tls,
pubkey->name, cipherspec->suite->pubkey->name );
rc = -EPERM_KEY_EXCHANGE;
goto err_sig_hash;
}
} else {
pubkey = cipherspec->suite->pubkey;
digest = &md5_sha1_algorithm;
}
/* Verify signature */
{
const void *signature = sig->signature;
size_t signature_len = ntohs ( sig->signature_len );
uint8_t ctx[digest->ctxsize];
uint8_t hash[digest->digestsize];
/* Calculate digest */
digest_init ( digest, ctx );
digest_update ( digest, ctx, &tls->client_random,
sizeof ( tls->client_random ) );
digest_update ( digest, ctx, tls->server_random,
sizeof ( tls->server_random ) );
digest_update ( digest, ctx, tls->server_key,
( tls->server_key_len - remaining ) );
digest_final ( digest, ctx, hash );
/* Verify signature */
if ( ( rc = pubkey_verify ( pubkey, cipherspec->pubkey_ctx,
digest, hash, signature,
signature_len ) ) != 0 ) {
DBGC ( tls, "TLS %p ServerKeyExchange failed "
"verification\n", tls );
DBGC_HDA ( tls, 0, tls->server_key,
tls->server_key_len );
rc = -EPERM_KEY_EXCHANGE;
goto err_verify;
}
}
/* Verify parameter signature */
if ( ( rc = tls_verify_dh_params ( tls, param_len ) ) != 0 )
goto err_verify;
/* Generate Diffie-Hellman private key */
if ( ( rc = tls_generate_random ( tls, private,
@ -1540,13 +1640,6 @@ static int tls_send_client_key_exchange_dhe ( struct tls_connection *tls ) {
/* Generate master secret */
tls_generate_master_secret ( tls, pre_master_secret, len );
/* Generate keys */
if ( ( rc = tls_generate_keys ( tls ) ) != 0 ) {
DBGC ( tls, "TLS %p could not generate keys: %s\n",
tls, strerror ( rc ) );
goto err_generate_keys;
}
/* Transmit Client Key Exchange record */
if ( ( rc = tls_send_handshake ( tls, key_xchg,
sizeof ( *key_xchg ) ) ) !=0){
@ -1554,14 +1647,12 @@ static int tls_send_client_key_exchange_dhe ( struct tls_connection *tls ) {
}
err_send_handshake:
err_generate_keys:
err_dhe_key:
free ( dynamic );
}
err_alloc:
err_random:
err_verify:
err_sig_hash:
err_header:
return rc;
}
@ -1572,6 +1663,119 @@ struct tls_key_exchange_algorithm tls_dhe_exchange_algorithm = {
.exchange = tls_send_client_key_exchange_dhe,
};
/**
* Transmit Client Key Exchange record using ECDHE key exchange
*
* @v tls TLS connection
* @ret rc Return status code
*/
static int tls_send_client_key_exchange_ecdhe ( struct tls_connection *tls ) {
struct tls_named_curve *curve;
const struct {
uint8_t curve_type;
uint16_t named_curve;
uint8_t public_len;
uint8_t public[0];
} __attribute__ (( packed )) *ecdh;
size_t param_len;
int rc;
/* Parse ServerKeyExchange record */
ecdh = tls->server_key;
if ( ( sizeof ( *ecdh ) > tls->server_key_len ) ||
( ecdh->public_len > ( tls->server_key_len - sizeof ( *ecdh ) ))){
DBGC ( tls, "TLS %p received underlength ServerKeyExchange\n",
tls );
DBGC_HDA ( tls, 0, tls->server_key, tls->server_key_len );
return -EINVAL_KEY_EXCHANGE;
}
param_len = ( sizeof ( *ecdh ) + ecdh->public_len );
/* Verify parameter signature */
if ( ( rc = tls_verify_dh_params ( tls, param_len ) ) != 0 )
return rc;
/* Identify named curve */
if ( ecdh->curve_type != TLS_NAMED_CURVE_TYPE ) {
DBGC ( tls, "TLS %p unsupported curve type %d\n",
tls, ecdh->curve_type );
DBGC_HDA ( tls, 0, tls->server_key, tls->server_key_len );
return -ENOTSUP_CURVE;
}
curve = tls_find_named_curve ( ecdh->named_curve );
if ( ! curve ) {
DBGC ( tls, "TLS %p unsupported named curve %d\n",
tls, ntohs ( ecdh->named_curve ) );
DBGC_HDA ( tls, 0, tls->server_key, tls->server_key_len );
return -ENOTSUP_CURVE;
}
/* Check key length */
if ( ecdh->public_len != curve->curve->keysize ) {
DBGC ( tls, "TLS %p invalid %s key\n",
tls, curve->curve->name );
DBGC_HDA ( tls, 0, tls->server_key, tls->server_key_len );
return -EINVAL_KEY_EXCHANGE;
}
/* Construct pre-master secret and ClientKeyExchange record */
{
size_t len = curve->curve->keysize;
uint8_t private[len];
uint8_t pre_master_secret[len];
struct {
uint32_t type_length;
uint8_t public_len;
uint8_t public[len];
} __attribute__ (( packed )) key_xchg;
/* Generate ephemeral private key */
if ( ( rc = tls_generate_random ( tls, private,
sizeof ( private ) ) ) != 0){
return rc;
}
/* Calculate pre-master secret */
if ( ( rc = elliptic_multiply ( curve->curve,
ecdh->public, private,
pre_master_secret ) ) != 0 ) {
DBGC ( tls, "TLS %p could not exchange ECDHE key: %s\n",
tls, strerror ( rc ) );
return rc;
}
/* Generate master secret */
tls_generate_master_secret ( tls, pre_master_secret, len );
/* Generate Client Key Exchange record */
key_xchg.type_length =
( cpu_to_le32 ( TLS_CLIENT_KEY_EXCHANGE ) |
htonl ( sizeof ( key_xchg ) -
sizeof ( key_xchg.type_length ) ) );
key_xchg.public_len = len;
if ( ( rc = elliptic_multiply ( curve->curve, NULL, private,
key_xchg.public ) ) != 0 ) {
DBGC ( tls, "TLS %p could not generate ECDHE key: %s\n",
tls, strerror ( rc ) );
return rc;
}
/* Transmit Client Key Exchange record */
if ( ( rc = tls_send_handshake ( tls, &key_xchg,
sizeof ( key_xchg ) ) ) !=0){
return rc;
}
}
return 0;
}
/** Ephemeral Elliptic Curve Diffie-Hellman key exchange algorithm */
struct tls_key_exchange_algorithm tls_ecdhe_exchange_algorithm = {
.name = "ecdhe",
.exchange = tls_send_client_key_exchange_ecdhe,
};
/**
* Transmit Client Key Exchange record
*
@ -1581,9 +1785,23 @@ struct tls_key_exchange_algorithm tls_dhe_exchange_algorithm = {
static int tls_send_client_key_exchange ( struct tls_connection *tls ) {
struct tls_cipherspec *cipherspec = &tls->tx_cipherspec_pending;
struct tls_cipher_suite *suite = cipherspec->suite;
int rc;
/* Transmit Client Key Exchange record via key exchange algorithm */
return suite->exchange->exchange ( tls );
if ( ( rc = suite->exchange->exchange ( tls ) ) != 0 ) {
DBGC ( tls, "TLS %p could not exchange keys: %s\n",
tls, strerror ( rc ) );
return rc;
}
/* Generate keys from master secret */
if ( ( rc = tls_generate_keys ( tls ) ) != 0 ) {
DBGC ( tls, "TLS %p could not generate keys: %s\n",
tls, strerror ( rc ) );
return rc;
}
return 0;
}
/**
@ -2727,9 +2945,9 @@ static int tls_send_plaintext ( struct tls_connection *tls, unsigned int type,
} __attribute__ (( packed )) iv;
struct tls_auth_header authhdr;
struct tls_header *tlshdr;
void *plaintext = NULL;
size_t plaintext_len = len;
struct io_buffer *ciphertext = NULL;
void *plaintext;
size_t plaintext_len;
struct io_buffer *ciphertext;
size_t ciphertext_len;
size_t padding_len;
uint8_t mac[digest->digestsize];
@ -2738,7 +2956,10 @@ static int tls_send_plaintext ( struct tls_connection *tls, unsigned int type,
/* Construct initialisation vector */
memcpy ( iv.fixed, cipherspec->fixed_iv, sizeof ( iv.fixed ) );
tls_generate_random ( tls, iv.record, sizeof ( iv.record ) );
if ( ( rc = tls_generate_random ( tls, iv.record,
sizeof ( iv.record ) ) ) != 0 ) {
goto err_random;
}
/* Construct authentication data */
authhdr.seq = cpu_to_be64 ( tls->tx_seq );
@ -2747,7 +2968,7 @@ static int tls_send_plaintext ( struct tls_connection *tls, unsigned int type,
authhdr.header.length = htons ( len );
/* Calculate padding length */
plaintext_len += suite->mac_len;
plaintext_len = ( len + suite->mac_len );
if ( is_block_cipher ( cipher ) ) {
padding_len = ( ( ( cipher->blocksize - 1 ) &
-( plaintext_len + 1 ) ) + 1 );
@ -2762,7 +2983,7 @@ static int tls_send_plaintext ( struct tls_connection *tls, unsigned int type,
DBGC ( tls, "TLS %p could not allocate %zd bytes for "
"plaintext\n", tls, plaintext_len );
rc = -ENOMEM_TX_PLAINTEXT;
goto done;
goto err_plaintext;
}
/* Assemble plaintext */
@ -2796,7 +3017,7 @@ static int tls_send_plaintext ( struct tls_connection *tls, unsigned int type,
DBGC ( tls, "TLS %p could not allocate %zd bytes for "
"ciphertext\n", tls, ciphertext_len );
rc = -ENOMEM_TX_CIPHERTEXT;
goto done;
goto err_ciphertext;
}
/* Assemble ciphertext */
@ -2821,15 +3042,22 @@ static int tls_send_plaintext ( struct tls_connection *tls, unsigned int type,
iob_disown ( ciphertext ) ) ) != 0 ) {
DBGC ( tls, "TLS %p could not deliver ciphertext: %s\n",
tls, strerror ( rc ) );
goto done;
goto err_deliver;
}
/* Update TX state machine to next record */
tls->tx_seq += 1;
done:
free ( plaintext );
assert ( plaintext == NULL );
assert ( ciphertext == NULL );
return 0;
err_deliver:
free_iob ( ciphertext );
err_ciphertext:
free ( plaintext );
err_plaintext:
err_random:
return rc;
}

View File

@ -63,11 +63,6 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
0x2c, 0x07, 0x3b, 0x61, 0x08, 0xd7, 0x2d, 0x98, 0x10, \
0xa3, 0x09, 0x14, 0xdf, 0xf4 )
/** Dummy initialisation vector used for NIST ECB-mode test vectors */
#define AES_IV_NIST_DUMMY \
IV ( 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 )
/** Initialisation vector used for NIST CBC-mode test vectors */
#define AES_IV_NIST_CBC \
IV ( 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, \
@ -86,7 +81,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
/** AES-128-ECB (same test as AES-128-Core) */
CIPHER_TEST ( aes_128_ecb, &aes_ecb_algorithm,
AES_KEY_NIST_128, AES_IV_NIST_DUMMY, ADDITIONAL(), AES_PLAINTEXT_NIST,
AES_KEY_NIST_128, IV(), ADDITIONAL(), AES_PLAINTEXT_NIST,
CIPHERTEXT ( 0x3a, 0xd7, 0x7b, 0xb4, 0x0d, 0x7a, 0x36, 0x60,
0xa8, 0x9e, 0xca, 0xf3, 0x24, 0x66, 0xef, 0x97,
0xf5, 0xd3, 0xd5, 0x85, 0x03, 0xb9, 0x69, 0x9d,
@ -110,7 +105,7 @@ CIPHER_TEST ( aes_128_cbc, &aes_cbc_algorithm,
/** AES-192-ECB (same test as AES-192-Core) */
CIPHER_TEST ( aes_192_ecb, &aes_ecb_algorithm,
AES_KEY_NIST_192, AES_IV_NIST_DUMMY, ADDITIONAL(), AES_PLAINTEXT_NIST,
AES_KEY_NIST_192, IV(), ADDITIONAL(), AES_PLAINTEXT_NIST,
CIPHERTEXT ( 0xbd, 0x33, 0x4f, 0x1d, 0x6e, 0x45, 0xf2, 0x5f,
0xf7, 0x12, 0xa2, 0x14, 0x57, 0x1f, 0xa5, 0xcc,
0x97, 0x41, 0x04, 0x84, 0x6d, 0x0a, 0xd3, 0xad,
@ -134,7 +129,7 @@ CIPHER_TEST ( aes_192_cbc, &aes_cbc_algorithm,
/** AES-256-ECB (same test as AES-256-Core) */
CIPHER_TEST ( aes_256_ecb, &aes_ecb_algorithm,
AES_KEY_NIST_256, AES_IV_NIST_DUMMY, ADDITIONAL(), AES_PLAINTEXT_NIST,
AES_KEY_NIST_256, IV(), ADDITIONAL(), AES_PLAINTEXT_NIST,
CIPHERTEXT ( 0xf3, 0xee, 0xd1, 0xbd, 0xb5, 0xd2, 0xa0, 0x3c,
0x06, 0x4b, 0x5a, 0x7e, 0x3d, 0xb1, 0x81, 0xf8,
0x59, 0x1c, 0xcb, 0x10, 0xd4, 0x10, 0xed, 0x26,

View File

@ -714,6 +714,15 @@ static void bigint_test_exec ( void ) {
bigint_subtract_ok ( BIGINT ( 0xbb, 0x77, 0x32, 0x5a ),
BIGINT ( 0x5a, 0xd5, 0xfe, 0x28 ),
BIGINT ( 0x9f, 0x5e, 0xcb, 0xce ) );
bigint_subtract_ok ( BIGINT ( 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff ),
BIGINT ( 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x2a ),
BIGINT ( 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x2b ) );
bigint_subtract_ok ( BIGINT ( 0x7b, 0xaa, 0x16, 0xcf, 0x15, 0x87,
0xe0, 0x4f, 0x2c, 0xa3, 0xec, 0x2f,
0x46, 0xfb, 0x83, 0xc6, 0xe0, 0xee,

898
src/tests/des_test.c Normal file
View File

@ -0,0 +1,898 @@
/*
* Copyright (C) 2024 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
*
* DES tests
*
* These test vectors are originally provided by NBS (the precursor of
* NIST) in SP 500-20, downloadable as a scan of the typewritten
* original from:
*
* https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nbsspecialpublication500-20e1980.pdf
*/
/* Forcibly enable assertions */
#undef NDEBUG
#include <assert.h>
#include <ipxe/des.h>
#include <ipxe/test.h>
#include "cipher_test.h"
/** Define a DES 64-bit test value */
#define DES_VALUE(value) { \
( ( ( ( uint64_t ) (value) ) >> 56 ) & 0xff ), \
( ( ( ( uint64_t ) (value) ) >> 48 ) & 0xff ), \
( ( ( ( uint64_t ) (value) ) >> 40 ) & 0xff ), \
( ( ( ( uint64_t ) (value) ) >> 32 ) & 0xff ), \
( ( ( ( uint64_t ) (value) ) >> 24 ) & 0xff ), \
( ( ( ( uint64_t ) (value) ) >> 16 ) & 0xff ), \
( ( ( ( uint64_t ) (value) ) >> 8 ) & 0xff ), \
( ( ( ( uint64_t ) (value) ) >> 0 ) & 0xff ) \
}
/** Define a DES test */
#define DES_TEST( name, key, plaintext, ciphertext ) \
CIPHER_TEST ( name, &des_ecb_algorithm, DES_VALUE ( key ), \
IV(), ADDITIONAL(), DES_VALUE ( plaintext ), \
DES_VALUE ( ciphertext ), AUTH() )
/* Sample round outputs (page 9) */
DES_TEST ( des_round_sample,
0x10316e028c8f3b4a, 0x0000000000000000, 0x82dcbafbdeab6602 );
/* Test 1: Initial permutation and expansion tests
*
* "Set Key=0 and encrypt the 64-bit data vectors e[i]: i=1,...,64"
*
* Appendix B, page 28 ("IP and E test")
*/
DES_TEST ( des_test1_1,
0x0101010101010101, 0x8000000000000000, 0x95f8a5e5dd31d900 );
DES_TEST ( des_test1_2,
0x0101010101010101, 0x4000000000000000, 0xdd7f121ca5015619 );
DES_TEST ( des_test1_3,
0x0101010101010101, 0x2000000000000000, 0x2e8653104f3834ea );
DES_TEST ( des_test1_4,
0x0101010101010101, 0x1000000000000000, 0x4bd388ff6cd81d4f );
DES_TEST ( des_test1_5,
0x0101010101010101, 0x0800000000000000, 0x20b9e767b2fb1456 );
DES_TEST ( des_test1_6,
0x0101010101010101, 0x0400000000000000, 0x55579380d77138ef );
DES_TEST ( des_test1_7,
0x0101010101010101, 0x0200000000000000, 0x6cc5defaaf04512f );
DES_TEST ( des_test1_8,
0x0101010101010101, 0x0100000000000000, 0x0d9f279ba5d87260 );
DES_TEST ( des_test1_9,
0x0101010101010101, 0x0080000000000000, 0xd9031b0271bd5a0a );
DES_TEST ( des_test1_10,
0x0101010101010101, 0x0040000000000000, 0x424250b37c3dd951 );
DES_TEST ( des_test1_11,
0x0101010101010101, 0x0020000000000000, 0xb8061b7ecd9a21e5 );
DES_TEST ( des_test1_12,
0x0101010101010101, 0x0010000000000000, 0xf15d0f286b65bd28 );
DES_TEST ( des_test1_13,
0x0101010101010101, 0x0008000000000000, 0xadd0cc8d6e5deba1 );
DES_TEST ( des_test1_14,
0x0101010101010101, 0x0004000000000000, 0xe6d5f82752ad63d1 );
DES_TEST ( des_test1_15,
0x0101010101010101, 0x0002000000000000, 0xecbfe3bd3f591a5e );
DES_TEST ( des_test1_16,
0x0101010101010101, 0x0001000000000000, 0xf356834379d165cd );
DES_TEST ( des_test1_17,
0x0101010101010101, 0x0000800000000000, 0x2b9f982f20037fa9 );
DES_TEST ( des_test1_18,
0x0101010101010101, 0x0000400000000000, 0x889de068a16f0be6 );
DES_TEST ( des_test1_19,
0x0101010101010101, 0x0000200000000000, 0xe19e275d846a1298 );
DES_TEST ( des_test1_20,
0x0101010101010101, 0x0000100000000000, 0x329a8ed523d71aec );
DES_TEST ( des_test1_21,
0x0101010101010101, 0x0000080000000000, 0xe7fce22557d23c97 );
DES_TEST ( des_test1_22,
0x0101010101010101, 0x0000040000000000, 0x12a9f5817ff2d65d );
DES_TEST ( des_test1_23,
0x0101010101010101, 0x0000020000000000, 0xa484c3ad38dc9c19 );
DES_TEST ( des_test1_24,
0x0101010101010101, 0x0000010000000000, 0xfbe00a8a1ef8ad72 );
DES_TEST ( des_test1_25,
0x0101010101010101, 0x0000008000000000, 0x750d079407521363 );
DES_TEST ( des_test1_26,
0x0101010101010101, 0x0000004000000000, 0x64feed9c724c2faf );
DES_TEST ( des_test1_27,
0x0101010101010101, 0x0000002000000000, 0xf02b263b328e2b60 );
DES_TEST ( des_test1_28,
0x0101010101010101, 0x0000001000000000, 0x9d64555a9a10b852 );
DES_TEST ( des_test1_29,
0x0101010101010101, 0x0000000800000000, 0xd106ff0bed5255d7 );
DES_TEST ( des_test1_30,
0x0101010101010101, 0x0000000400000000, 0xe1652c6b138c64a5 );
DES_TEST ( des_test1_31,
0x0101010101010101, 0x0000000200000000, 0xe428581186ec8f46 );
DES_TEST ( des_test1_32,
0x0101010101010101, 0x0000000100000000, 0xaeb5f5ede22d1a36 );
DES_TEST ( des_test1_33,
0x0101010101010101, 0x0000000080000000, 0xe943d7568aec0c5c );
DES_TEST ( des_test1_34,
0x0101010101010101, 0x0000000040000000, 0xdf98c8276f54b04b );
DES_TEST ( des_test1_35,
0x0101010101010101, 0x0000000020000000, 0xb160e4680f6c696f );
DES_TEST ( des_test1_36,
0x0101010101010101, 0x0000000010000000, 0xfa0752b07d9c4ab8 );
DES_TEST ( des_test1_37,
0x0101010101010101, 0x0000000008000000, 0xca3a2b036dbc8502 );
DES_TEST ( des_test1_38,
0x0101010101010101, 0x0000000004000000, 0x5e0905517bb59bcf );
DES_TEST ( des_test1_39,
0x0101010101010101, 0x0000000002000000, 0x814eeb3b91d90726 );
DES_TEST ( des_test1_40,
0x0101010101010101, 0x0000000001000000, 0x4d49db1532919c9f );
DES_TEST ( des_test1_41,
0x0101010101010101, 0x0000000000800000, 0x25eb5fc3f8cf0621 );
DES_TEST ( des_test1_42,
0x0101010101010101, 0x0000000000400000, 0xab6a20c0620d1c6f );
DES_TEST ( des_test1_43,
0x0101010101010101, 0x0000000000200000, 0x79e90dbc98f92cca );
DES_TEST ( des_test1_44,
0x0101010101010101, 0x0000000000100000, 0x866ecedd8072bb0e );
DES_TEST ( des_test1_45,
0x0101010101010101, 0x0000000000080000, 0x8b54536f2f3e64a8 );
DES_TEST ( des_test1_46,
0x0101010101010101, 0x0000000000040000, 0xea51d3975595b86b );
DES_TEST ( des_test1_47,
0x0101010101010101, 0x0000000000020000, 0xcaffc6ac4542de31 );
DES_TEST ( des_test1_48,
0x0101010101010101, 0x0000000000010000, 0x8dd45a2ddf90796c );
DES_TEST ( des_test1_49,
0x0101010101010101, 0x0000000000008000, 0x1029d55e880ec2d0 );
DES_TEST ( des_test1_50,
0x0101010101010101, 0x0000000000004000, 0x5d86cb23639dbea9 );
DES_TEST ( des_test1_51,
0x0101010101010101, 0x0000000000002000, 0x1d1ca853ae7c0c5f );
DES_TEST ( des_test1_52,
0x0101010101010101, 0x0000000000001000, 0xce332329248f3228 );
DES_TEST ( des_test1_53,
0x0101010101010101, 0x0000000000000800, 0x8405d1abe24fb942 );
DES_TEST ( des_test1_54,
0x0101010101010101, 0x0000000000000400, 0xe643d78090ca4207 );
DES_TEST ( des_test1_55,
0x0101010101010101, 0x0000000000000200, 0x48221b9937748a23 );
DES_TEST ( des_test1_56,
0x0101010101010101, 0x0000000000000100, 0xdd7c0bbd61fafd54 );
DES_TEST ( des_test1_57,
0x0101010101010101, 0x0000000000000080, 0x2fbc291a570db5c4 );
DES_TEST ( des_test1_58,
0x0101010101010101, 0x0000000000000040, 0xe07c30d7e4e26e12 );
DES_TEST ( des_test1_59,
0x0101010101010101, 0x0000000000000020, 0x0953e2258e8e90a1 );
DES_TEST ( des_test1_60,
0x0101010101010101, 0x0000000000000010, 0x5b711bc4ceebf2ee );
DES_TEST ( des_test1_61,
0x0101010101010101, 0x0000000000000008, 0xcc083f1e6d9e85f6 );
DES_TEST ( des_test1_62,
0x0101010101010101, 0x0000000000000004, 0xd2fd8867d50d2dfe );
DES_TEST ( des_test1_63,
0x0101010101010101, 0x0000000000000002, 0x06e7ea22ce92708f );
DES_TEST ( des_test1_64,
0x0101010101010101, 0x0000000000000001, 0x166b40b44aba4bd6 );
/* Test 2: Inverse permutation and expansion tests
*
* "Set Key=0 and encrypt the results c[i] obtained in Test 1"
*
* Appendix B, page 28 ("IP and E test")
*/
DES_TEST ( des_test2_1,
0x0101010101010101, 0x95f8a5e5dd31d900, 0x8000000000000000 );
DES_TEST ( des_test2_2,
0x0101010101010101, 0xdd7f121ca5015619, 0x4000000000000000 );
DES_TEST ( des_test2_3,
0x0101010101010101, 0x2e8653104f3834ea, 0x2000000000000000 );
DES_TEST ( des_test2_4,
0x0101010101010101, 0x4bd388ff6cd81d4f, 0x1000000000000000 );
DES_TEST ( des_test2_5,
0x0101010101010101, 0x20b9e767b2fb1456, 0x0800000000000000 );
DES_TEST ( des_test2_6,
0x0101010101010101, 0x55579380d77138ef, 0x0400000000000000 );
DES_TEST ( des_test2_7,
0x0101010101010101, 0x6cc5defaaf04512f, 0x0200000000000000 );
DES_TEST ( des_test2_8,
0x0101010101010101, 0x0d9f279ba5d87260, 0x0100000000000000 );
DES_TEST ( des_test2_9,
0x0101010101010101, 0xd9031b0271bd5a0a, 0x0080000000000000 );
DES_TEST ( des_test2_10,
0x0101010101010101, 0x424250b37c3dd951, 0x0040000000000000 );
DES_TEST ( des_test2_11,
0x0101010101010101, 0xb8061b7ecd9a21e5, 0x0020000000000000 );
DES_TEST ( des_test2_12,
0x0101010101010101, 0xf15d0f286b65bd28, 0x0010000000000000 );
DES_TEST ( des_test2_13,
0x0101010101010101, 0xadd0cc8d6e5deba1, 0x0008000000000000 );
DES_TEST ( des_test2_14,
0x0101010101010101, 0xe6d5f82752ad63d1, 0x0004000000000000 );
DES_TEST ( des_test2_15,
0x0101010101010101, 0xecbfe3bd3f591a5e, 0x0002000000000000 );
DES_TEST ( des_test2_16,
0x0101010101010101, 0xf356834379d165cd, 0x0001000000000000 );
DES_TEST ( des_test2_17,
0x0101010101010101, 0x2b9f982f20037fa9, 0x0000800000000000 );
DES_TEST ( des_test2_18,
0x0101010101010101, 0x889de068a16f0be6, 0x0000400000000000 );
DES_TEST ( des_test2_19,
0x0101010101010101, 0xe19e275d846a1298, 0x0000200000000000 );
DES_TEST ( des_test2_20,
0x0101010101010101, 0x329a8ed523d71aec, 0x0000100000000000 );
DES_TEST ( des_test2_21,
0x0101010101010101, 0xe7fce22557d23c97, 0x0000080000000000 );
DES_TEST ( des_test2_22,
0x0101010101010101, 0x12a9f5817ff2d65d, 0x0000040000000000 );
DES_TEST ( des_test2_23,
0x0101010101010101, 0xa484c3ad38dc9c19, 0x0000020000000000 );
DES_TEST ( des_test2_24,
0x0101010101010101, 0xfbe00a8a1ef8ad72, 0x0000010000000000 );
DES_TEST ( des_test2_25,
0x0101010101010101, 0x750d079407521363, 0x0000008000000000 );
DES_TEST ( des_test2_26,
0x0101010101010101, 0x64feed9c724c2faf, 0x0000004000000000 );
DES_TEST ( des_test2_27,
0x0101010101010101, 0xf02b263b328e2b60, 0x0000002000000000 );
DES_TEST ( des_test2_28,
0x0101010101010101, 0x9d64555a9a10b852, 0x0000001000000000 );
DES_TEST ( des_test2_29,
0x0101010101010101, 0xd106ff0bed5255d7, 0x0000000800000000 );
DES_TEST ( des_test2_30,
0x0101010101010101, 0xe1652c6b138c64a5, 0x0000000400000000 );
DES_TEST ( des_test2_31,
0x0101010101010101, 0xe428581186ec8f46, 0x0000000200000000 );
DES_TEST ( des_test2_32,
0x0101010101010101, 0xaeb5f5ede22d1a36, 0x0000000100000000 );
DES_TEST ( des_test2_33,
0x0101010101010101, 0xe943d7568aec0c5c, 0x0000000080000000 );
DES_TEST ( des_test2_34,
0x0101010101010101, 0xdf98c8276f54b04b, 0x0000000040000000 );
DES_TEST ( des_test2_35,
0x0101010101010101, 0xb160e4680f6c696f, 0x0000000020000000 );
DES_TEST ( des_test2_36,
0x0101010101010101, 0xfa0752b07d9c4ab8, 0x0000000010000000 );
DES_TEST ( des_test2_37,
0x0101010101010101, 0xca3a2b036dbc8502, 0x0000000008000000 );
DES_TEST ( des_test2_38,
0x0101010101010101, 0x5e0905517bb59bcf, 0x0000000004000000 );
DES_TEST ( des_test2_39,
0x0101010101010101, 0x814eeb3b91d90726, 0x0000000002000000 );
DES_TEST ( des_test2_40,
0x0101010101010101, 0x4d49db1532919c9f, 0x0000000001000000 );
DES_TEST ( des_test2_41,
0x0101010101010101, 0x25eb5fc3f8cf0621, 0x0000000000800000 );
DES_TEST ( des_test2_42,
0x0101010101010101, 0xab6a20c0620d1c6f, 0x0000000000400000 );
DES_TEST ( des_test2_43,
0x0101010101010101, 0x79e90dbc98f92cca, 0x0000000000200000 );
DES_TEST ( des_test2_44,
0x0101010101010101, 0x866ecedd8072bb0e, 0x0000000000100000 );
DES_TEST ( des_test2_45,
0x0101010101010101, 0x8b54536f2f3e64a8, 0x0000000000080000 );
DES_TEST ( des_test2_46,
0x0101010101010101, 0xea51d3975595b86b, 0x0000000000040000 );
DES_TEST ( des_test2_47,
0x0101010101010101, 0xcaffc6ac4542de31, 0x0000000000020000 );
DES_TEST ( des_test2_48,
0x0101010101010101, 0x8dd45a2ddf90796c, 0x0000000000010000 );
DES_TEST ( des_test2_49,
0x0101010101010101, 0x1029d55e880ec2d0, 0x0000000000008000 );
DES_TEST ( des_test2_50,
0x0101010101010101, 0x5d86cb23639dbea9, 0x0000000000004000 );
DES_TEST ( des_test2_51,
0x0101010101010101, 0x1d1ca853ae7c0c5f, 0x0000000000002000 );
DES_TEST ( des_test2_52,
0x0101010101010101, 0xce332329248f3228, 0x0000000000001000 );
DES_TEST ( des_test2_53,
0x0101010101010101, 0x8405d1abe24fb942, 0x0000000000000800 );
DES_TEST ( des_test2_54,
0x0101010101010101, 0xe643d78090ca4207, 0x0000000000000400 );
DES_TEST ( des_test2_55,
0x0101010101010101, 0x48221b9937748a23, 0x0000000000000200 );
DES_TEST ( des_test2_56,
0x0101010101010101, 0xdd7c0bbd61fafd54, 0x0000000000000100 );
DES_TEST ( des_test2_57,
0x0101010101010101, 0x2fbc291a570db5c4, 0x0000000000000080 );
DES_TEST ( des_test2_58,
0x0101010101010101, 0xe07c30d7e4e26e12, 0x0000000000000040 );
DES_TEST ( des_test2_59,
0x0101010101010101, 0x0953e2258e8e90a1, 0x0000000000000020 );
DES_TEST ( des_test2_60,
0x0101010101010101, 0x5b711bc4ceebf2ee, 0x0000000000000010 );
DES_TEST ( des_test2_61,
0x0101010101010101, 0xcc083f1e6d9e85f6, 0x0000000000000008 );
DES_TEST ( des_test2_62,
0x0101010101010101, 0xd2fd8867d50d2dfe, 0x0000000000000004 );
DES_TEST ( des_test2_63,
0x0101010101010101, 0x06e7ea22ce92708f, 0x0000000000000002 );
DES_TEST ( des_test2_64,
0x0101010101010101, 0x166b40b44aba4bd6, 0x0000000000000001 );
/* Test 3: Data permutation tests
*
* "Set the plaintext to zero and process the 32 keys in PTEST"
*
* Appendix B, page 32 ("PTEST")
*/
DES_TEST ( des_test3_1,
0x1046913489980131, 0x0000000000000000, 0x88d55e54f54c97b4 );
DES_TEST ( des_test3_2,
0x1007103489988020, 0x0000000000000000, 0x0c0cc00c83ea48fd );
DES_TEST ( des_test3_3,
0x10071034c8980120, 0x0000000000000000, 0x83bc8ef3a6570183 );
DES_TEST ( des_test3_4,
0x1046103489988020, 0x0000000000000000, 0xdf725dcad94ea2e9 );
DES_TEST ( des_test3_5,
0x1086911519190101, 0x0000000000000000, 0xe652b53b550be8b0 );
DES_TEST ( des_test3_6,
0x1086911519580101, 0x0000000000000000, 0xaf527120c485cbb0 );
DES_TEST ( des_test3_7,
0x5107b01519580101, 0x0000000000000000, 0x0f04ce393db926d5 );
DES_TEST ( des_test3_8,
0x1007b01519190101, 0x0000000000000000, 0xc9f00ffc74079067 );
DES_TEST ( des_test3_9,
0x3107915498080101, 0x0000000000000000, 0x7cfd82a593252b4e );
DES_TEST ( des_test3_10,
0x3107919498080101, 0x0000000000000000, 0xcb49a2f9e91363e3 );
DES_TEST ( des_test3_11,
0x10079115b9080140, 0x0000000000000000, 0x00b588be70d23f56 );
DES_TEST ( des_test3_12,
0x3107911598080140, 0x0000000000000000, 0x406a9a6ab43399ae );
DES_TEST ( des_test3_13,
0x1007d01589980101, 0x0000000000000000, 0x6cb773611dca9ada );
DES_TEST ( des_test3_14,
0x9107911589980101, 0x0000000000000000, 0x67fd21c17dbb5d70 );
DES_TEST ( des_test3_15,
0x9107d01589190101, 0x0000000000000000, 0x9592cb4110430787 );
DES_TEST ( des_test3_16,
0x1007d01598980120, 0x0000000000000000, 0xa6b7ff68a318ddd3 );
DES_TEST ( des_test3_17,
0x1007940498190101, 0x0000000000000000, 0x4d102196c914ca16 );
DES_TEST ( des_test3_18,
0x0107910491190401, 0x0000000000000000, 0x2dfa9f4573594965 );
DES_TEST ( des_test3_19,
0x0107910491190101, 0x0000000000000000, 0xb46604816c0e0774 );
DES_TEST ( des_test3_20,
0x0107940491190401, 0x0000000000000000, 0x6e7e6221a4f34e87 );
DES_TEST ( des_test3_21,
0x19079210981a0101, 0x0000000000000000, 0xaa85e74643233199 );
DES_TEST ( des_test3_22,
0x1007911998190801, 0x0000000000000000, 0x2e5a19db4d1962d6 );
DES_TEST ( des_test3_23,
0x10079119981a0801, 0x0000000000000000, 0x23a866a809d30894 );
DES_TEST ( des_test3_24,
0x1007921098190101, 0x0000000000000000, 0xd812d961f017d320 );
DES_TEST ( des_test3_25,
0x100791159819010b, 0x0000000000000000, 0x055605816e58608f );
DES_TEST ( des_test3_26,
0x1004801598190101, 0x0000000000000000, 0xabd88e8b1b7716f1 );
DES_TEST ( des_test3_27,
0x1004801598190102, 0x0000000000000000, 0x537ac95be69da1e1 );
DES_TEST ( des_test3_28,
0x1004801598190108, 0x0000000000000000, 0xaed0f6ae3c25cdd8 );
DES_TEST ( des_test3_29,
0x1002911498100104, 0x0000000000000000, 0xb3e35a5ee53e7b8d );
DES_TEST ( des_test3_30,
0x1002911598190104, 0x0000000000000000, 0x61c79c71921a2ef8 );
DES_TEST ( des_test3_31,
0x1002911598100201, 0x0000000000000000, 0xe2f5728f0995013c );
DES_TEST ( des_test3_32,
0x1002911698100101, 0x0000000000000000, 0x1aeac39a61f0a464 );
/* Test 4: Key permutation tests
*
* "Set Data=0 and use the keys e[i]: i=1,...,64 ignoring i=8,16,...,64"
*
* Test 4 part 1 is the forward direction as described above. Test 4
* part 2 ("set data=c[i] from part 1 ... then decipher") is carried
* out for us automatically, since CIPHER_TEST() performs both
* encryption and decryption tests.
*
* Appendix B, page 30 ("PC1 and PC2 test")
*/
DES_TEST ( des_test4_1,
0x8001010101010101, 0x0000000000000000, 0x95a8d72813daa94d );
DES_TEST ( des_test4_2,
0x4001010101010101, 0x0000000000000000, 0x0eec1487dd8c26d5 );
DES_TEST ( des_test4_3,
0x2001010101010101, 0x0000000000000000, 0x7ad16ffb79c45926 );
DES_TEST ( des_test4_4,
0x1001010101010101, 0x0000000000000000, 0xd3746294ca6a6cf3 );
DES_TEST ( des_test4_5,
0x0801010101010101, 0x0000000000000000, 0x809f5f873c1fd761 );
DES_TEST ( des_test4_6,
0x0401010101010101, 0x0000000000000000, 0xc02faffec989d1fc );
DES_TEST ( des_test4_7,
0x0201010101010101, 0x0000000000000000, 0x4615aa1d33e72f10 );
DES_TEST ( des_test4_8,
0x0180010101010101, 0x0000000000000000, 0x2055123350c00858 );
DES_TEST ( des_test4_9,
0x0140010101010101, 0x0000000000000000, 0xdf3b99d6577397c8 );
DES_TEST ( des_test4_10,
0x0120010101010101, 0x0000000000000000, 0x31fe17369b5288c9 );
DES_TEST ( des_test4_11,
0x0110010101010101, 0x0000000000000000, 0xdfdd3cc64dae1642 );
DES_TEST ( des_test4_12,
0x0108010101010101, 0x0000000000000000, 0x178c83ce2b399d94 );
DES_TEST ( des_test4_13,
0x0104010101010101, 0x0000000000000000, 0x50f636324a9b7f80 );
DES_TEST ( des_test4_14,
0x0102010101010101, 0x0000000000000000, 0xa8468ee3bc18f06d );
DES_TEST ( des_test4_15,
0x0101800101010101, 0x0000000000000000, 0xa2dc9e92fd3cde92 );
DES_TEST ( des_test4_16,
0x0101400101010101, 0x0000000000000000, 0xcac09f797d031287 );
DES_TEST ( des_test4_17,
0x0101200101010101, 0x0000000000000000, 0x90ba680b22aeb525 );
DES_TEST ( des_test4_18,
0x0101100101010101, 0x0000000000000000, 0xce7a24f350e280b6 );
DES_TEST ( des_test4_19,
0x0101080101010101, 0x0000000000000000, 0x882bff0aa01a0b87 );
DES_TEST ( des_test4_20,
0x0101040101010101, 0x0000000000000000, 0x25610288924511c2 );
DES_TEST ( des_test4_21,
0x0101020101010101, 0x0000000000000000, 0xc71516c29c75d170 );
DES_TEST ( des_test4_22,
0x0101018001010101, 0x0000000000000000, 0x5199c29a52c9f059 );
DES_TEST ( des_test4_23,
0x0101014001010101, 0x0000000000000000, 0xc22f0a294a71f29f );
DES_TEST ( des_test4_24,
0x0101012001010101, 0x0000000000000000, 0xee371483714c02ea );
DES_TEST ( des_test4_25,
0x0101011001010101, 0x0000000000000000, 0xa81fbd448f9e522f );
DES_TEST ( des_test4_26,
0x0101010801010101, 0x0000000000000000, 0x4f644c92e192dfed );
DES_TEST ( des_test4_27,
0x0101010401010101, 0x0000000000000000, 0x1afa9a66a6df92ae );
DES_TEST ( des_test4_28,
0x0101010201010101, 0x0000000000000000, 0xb3c1cc715cb879d8 );
DES_TEST ( des_test4_29,
0x0101010180010101, 0x0000000000000000, 0x19d032e64ab0bd8b );
DES_TEST ( des_test4_30,
0x0101010140010101, 0x0000000000000000, 0x3cfaa7a7dc8720dc );
DES_TEST ( des_test4_31,
0x0101010120010101, 0x0000000000000000, 0xb7265f7f447ac6f3 );
DES_TEST ( des_test4_32,
0x0101010110010101, 0x0000000000000000, 0x9db73b3c0d163f54 );
DES_TEST ( des_test4_33,
0x0101010108010101, 0x0000000000000000, 0x8181b65babf4a975 );
DES_TEST ( des_test4_34,
0x0101010104010101, 0x0000000000000000, 0x93c9b64042eaa240 );
DES_TEST ( des_test4_35,
0x0101010102010101, 0x0000000000000000, 0x5570530829705592 );
DES_TEST ( des_test4_36,
0x0101010101800101, 0x0000000000000000, 0x8638809e878787a0 );
DES_TEST ( des_test4_37,
0x0101010101400101, 0x0000000000000000, 0x41b9a79af79ac208 );
DES_TEST ( des_test4_38,
0x0101010101200101, 0x0000000000000000, 0x7a9be42f2009a892 );
DES_TEST ( des_test4_39,
0x0101010101100101, 0x0000000000000000, 0x29038d56ba6d2745 );
DES_TEST ( des_test4_40,
0x0101010101080101, 0x0000000000000000, 0x5495c6abf1e5df51 );
DES_TEST ( des_test4_41,
0x0101010101040101, 0x0000000000000000, 0xae13dbd561488933 );
DES_TEST ( des_test4_42,
0x0101010101020101, 0x0000000000000000, 0x024d1ffa8904e389 );
DES_TEST ( des_test4_43,
0x0101010101018001, 0x0000000000000000, 0xd1399712f99bf02e );
DES_TEST ( des_test4_44,
0x0101010101014001, 0x0000000000000000, 0x14c1d7c1cffec79e );
DES_TEST ( des_test4_45,
0x0101010101012001, 0x0000000000000000, 0x1de5279dae3bed6f );
DES_TEST ( des_test4_46,
0x0101010101011001, 0x0000000000000000, 0xe941a33f85501303 );
DES_TEST ( des_test4_47,
0x0101010101010801, 0x0000000000000000, 0xda99dbbc9a03f379 );
DES_TEST ( des_test4_48,
0x0101010101010401, 0x0000000000000000, 0xb7fc92f91d8e92e9 );
DES_TEST ( des_test4_49,
0x0101010101010201, 0x0000000000000000, 0xae8e5caa3ca04e85 );
DES_TEST ( des_test4_50,
0x0101010101010180, 0x0000000000000000, 0x9cc62df43b6eed74 );
DES_TEST ( des_test4_51,
0x0101010101010140, 0x0000000000000000, 0xd863dbb5c59a91a0 );
DES_TEST ( des_test4_52,
0x0101010101010120, 0x0000000000000000, 0xa1ab2190545b91d7 );
DES_TEST ( des_test4_53,
0x0101010101010110, 0x0000000000000000, 0x0875041e64c570f7 );
DES_TEST ( des_test4_54,
0x0101010101010108, 0x0000000000000000, 0x5a594528bebef1cc );
DES_TEST ( des_test4_55,
0x0101010101010104, 0x0000000000000000, 0xfcdb3291de21f0c0 );
DES_TEST ( des_test4_56,
0x0101010101010102, 0x0000000000000000, 0x869efd7f9f265a09 );
/* Test 5: S-box tests
*
* "Set Data and Key equal to the inputs defined in the Substitution
* Table test"
*
* Appendix B, page 33 ("19 key data pairs which exercise every S-box entry")
*/
DES_TEST ( des_test5_1,
0x7ca110454a1a6e57, 0x01a1d6d039776742, 0x690f5b0d9a26939b );
DES_TEST ( des_test5_2,
0x0131d9619dc1376e, 0x5cd54ca83def57da, 0x7a389d10354bd271 );
DES_TEST ( des_test5_3,
0x07a1133e4a0b2686, 0x0248d43806f67172, 0x868ebb51cab4599a );
DES_TEST ( des_test5_4,
0x3849674c2602319e, 0x51454b582ddf440a, 0x7178876e01f19b2a );
DES_TEST ( des_test5_5,
0x04b915ba43feb5b6, 0x42fd443059577fa2, 0xaf37fb421f8c4095 );
DES_TEST ( des_test5_6,
0x0113b970fd34f2ce, 0x059b5e0851cf143a, 0x86a560f10ec6d85b );
DES_TEST ( des_test5_7,
0x0170f175468fb5e6, 0x0756d8e0774761d2, 0x0cd3da020021dc09 );
DES_TEST ( des_test5_8,
0x43297fad38e373fe, 0x762514b829bf486a, 0xea676b2cb7db2b7a );
DES_TEST ( des_test5_9,
0x07a7137045da2a16, 0x3bdd119049372802, 0xdfd64a815caf1a0f );
DES_TEST ( des_test5_10,
0x04689104c2fd3b2f, 0x26955f6835af609a, 0x5c513c9c4886c088 );
DES_TEST ( des_test5_11,
0x37d06bb516cb7546, 0x164d5e404f275232, 0x0a2aeeae3ff4ab77 );
DES_TEST ( des_test5_12,
0x1f08260d1ac2465e, 0x6b056e18759f5cca, 0xef1bf03e5dfa575a );
DES_TEST ( des_test5_13,
0x584023641aba6176, 0x004bd6ef09176062, 0x88bf0db6d70dee56 );
DES_TEST ( des_test5_14,
0x025816164629b007, 0x480d39006ee762f2, 0xa1f9915541020b56 );
DES_TEST ( des_test5_15,
0x49793ebc79b3258f, 0x437540c8698f3cfa, 0x6fbf1cafcffd0556 );
DES_TEST ( des_test5_16,
0x4fb05e1515ab73a7, 0x072d43a077075292, 0x2f22e49bab7ca1ac );
DES_TEST ( des_test5_17,
0x49e95d6d4ca229bf, 0x02fe55778117f12a, 0x5a6b612cc26cce4a );
DES_TEST ( des_test5_18,
0x018310dc409b26d6, 0x1d9d5c5018f728c2, 0x5f4c038ed12b2e41 );
DES_TEST ( des_test5_19,
0x1c587f1c13924fef, 0x305532286d6f295a, 0x63fac0d034d9f793 );
/* Unofficial tests
*
* The official tests are all exactly one block in length. Add some
* multi-block tests (generated in Python).
*/
CIPHER_TEST ( des_unofficial_ecb, &des_ecb_algorithm,
KEY ( 0x6e, 0x6f, 0x70, 0x61, 0x72, 0x69, 0x74, 0x79 ),
IV(), ADDITIONAL(),
PLAINTEXT ( 0x53, 0x6f, 0x20, 0x63, 0x75, 0x74, 0x65, 0x20,
0x74, 0x6f, 0x20, 0x73, 0x65, 0x65, 0x20, 0x61,
0x20, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69,
0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x77,
0x72, 0x69, 0x74, 0x74, 0x65, 0x6e, 0x20, 0x6f,
0x6e, 0x20, 0x61, 0x6e, 0x20, 0x61, 0x63, 0x74,
0x75, 0x61, 0x6c, 0x20, 0x74, 0x79, 0x70, 0x65,
0x77, 0x72, 0x69, 0x74, 0x65, 0x72, 0x21, 0x21 ),
CIPHERTEXT ( 0x1a, 0x02, 0x17, 0xcb, 0x93, 0xa3, 0xd2, 0xf2,
0xf9, 0x45, 0x71, 0x1c, 0x33, 0xb1, 0x5c, 0xa4,
0x8b, 0x6b, 0x11, 0x7a, 0x7c, 0x86, 0x7c, 0x7f,
0x9f, 0x56, 0x61, 0x46, 0x7f, 0xa6, 0xae, 0xf1,
0x49, 0xf7, 0x53, 0xe0, 0xbc, 0x15, 0x6a, 0x30,
0xe7, 0xf8, 0xf3, 0x29, 0x11, 0xd8, 0x7d, 0x04,
0x62, 0x5a, 0xaa, 0xa1, 0x89, 0x61, 0x4c, 0xf6,
0x5a, 0x47, 0x3b, 0xc6, 0x04, 0x15, 0xce, 0xf6 ),
AUTH() );
CIPHER_TEST ( des_unofficial_cbc, &des_cbc_algorithm,
KEY ( 0x6e, 0x6f, 0x70, 0x61, 0x72, 0x69, 0x74, 0x79 ),
IV ( 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 ),
ADDITIONAL(),
PLAINTEXT ( 0x53, 0x6f, 0x20, 0x63, 0x75, 0x74, 0x65, 0x20,
0x74, 0x6f, 0x20, 0x73, 0x65, 0x65, 0x20, 0x61,
0x20, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69,
0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x77,
0x72, 0x69, 0x74, 0x74, 0x65, 0x6e, 0x20, 0x6f,
0x6e, 0x20, 0x61, 0x6e, 0x20, 0x61, 0x63, 0x74,
0x75, 0x61, 0x6c, 0x20, 0x74, 0x79, 0x70, 0x65,
0x77, 0x72, 0x69, 0x74, 0x65, 0x72, 0x21, 0x21 ),
CIPHERTEXT ( 0x4c, 0x5f, 0x62, 0xfc, 0xf4, 0x93, 0x09, 0xb5,
0x1d, 0x52, 0x25, 0xec, 0xc7, 0x42, 0x3c, 0x29,
0x33, 0x67, 0xf5, 0xe9, 0xd6, 0x3c, 0x27, 0x5b,
0x49, 0x69, 0xc5, 0xa9, 0x08, 0xa3, 0x14, 0x66,
0x3c, 0x95, 0x33, 0x30, 0xcf, 0x3c, 0x7c, 0xaf,
0xa3, 0xe4, 0xf8, 0x2e, 0xc3, 0x55, 0x57, 0x81,
0x33, 0xd9, 0x90, 0xe2, 0x99, 0xdc, 0x32, 0x10,
0x13, 0x21, 0xb6, 0xc1, 0x6b, 0x0f, 0x22, 0xa9 ),
AUTH() );
/**
* Perform DES self-test
*
*/
static void des_test_exec ( void ) {
/* Sample round outputs (page 9) */
cipher_ok ( &des_round_sample );
/* Test 1: Initial permutation and expansion tests */
cipher_ok ( &des_test1_1 );
cipher_ok ( &des_test1_2 );
cipher_ok ( &des_test1_3 );
cipher_ok ( &des_test1_4 );
cipher_ok ( &des_test1_5 );
cipher_ok ( &des_test1_6 );
cipher_ok ( &des_test1_7 );
cipher_ok ( &des_test1_8 );
cipher_ok ( &des_test1_9 );
cipher_ok ( &des_test1_10 );
cipher_ok ( &des_test1_11 );
cipher_ok ( &des_test1_12 );
cipher_ok ( &des_test1_13 );
cipher_ok ( &des_test1_14 );
cipher_ok ( &des_test1_15 );
cipher_ok ( &des_test1_16 );
cipher_ok ( &des_test1_17 );
cipher_ok ( &des_test1_18 );
cipher_ok ( &des_test1_19 );
cipher_ok ( &des_test1_20 );
cipher_ok ( &des_test1_21 );
cipher_ok ( &des_test1_22 );
cipher_ok ( &des_test1_23 );
cipher_ok ( &des_test1_24 );
cipher_ok ( &des_test1_25 );
cipher_ok ( &des_test1_26 );
cipher_ok ( &des_test1_27 );
cipher_ok ( &des_test1_28 );
cipher_ok ( &des_test1_29 );
cipher_ok ( &des_test1_30 );
cipher_ok ( &des_test1_31 );
cipher_ok ( &des_test1_32 );
cipher_ok ( &des_test1_33 );
cipher_ok ( &des_test1_34 );
cipher_ok ( &des_test1_35 );
cipher_ok ( &des_test1_36 );
cipher_ok ( &des_test1_37 );
cipher_ok ( &des_test1_38 );
cipher_ok ( &des_test1_39 );
cipher_ok ( &des_test1_40 );
cipher_ok ( &des_test1_41 );
cipher_ok ( &des_test1_42 );
cipher_ok ( &des_test1_43 );
cipher_ok ( &des_test1_44 );
cipher_ok ( &des_test1_45 );
cipher_ok ( &des_test1_46 );
cipher_ok ( &des_test1_47 );
cipher_ok ( &des_test1_48 );
cipher_ok ( &des_test1_49 );
cipher_ok ( &des_test1_50 );
cipher_ok ( &des_test1_51 );
cipher_ok ( &des_test1_52 );
cipher_ok ( &des_test1_53 );
cipher_ok ( &des_test1_54 );
cipher_ok ( &des_test1_55 );
cipher_ok ( &des_test1_56 );
cipher_ok ( &des_test1_57 );
cipher_ok ( &des_test1_58 );
cipher_ok ( &des_test1_59 );
cipher_ok ( &des_test1_60 );
cipher_ok ( &des_test1_61 );
cipher_ok ( &des_test1_62 );
cipher_ok ( &des_test1_63 );
cipher_ok ( &des_test1_64 );
/* Test 2: Inverse permutation and expansion tests */
cipher_ok ( &des_test2_1 );
cipher_ok ( &des_test2_2 );
cipher_ok ( &des_test2_3 );
cipher_ok ( &des_test2_4 );
cipher_ok ( &des_test2_5 );
cipher_ok ( &des_test2_6 );
cipher_ok ( &des_test2_7 );
cipher_ok ( &des_test2_8 );
cipher_ok ( &des_test2_9 );
cipher_ok ( &des_test2_10 );
cipher_ok ( &des_test2_11 );
cipher_ok ( &des_test2_12 );
cipher_ok ( &des_test2_13 );
cipher_ok ( &des_test2_14 );
cipher_ok ( &des_test2_15 );
cipher_ok ( &des_test2_16 );
cipher_ok ( &des_test2_17 );
cipher_ok ( &des_test2_18 );
cipher_ok ( &des_test2_19 );
cipher_ok ( &des_test2_20 );
cipher_ok ( &des_test2_21 );
cipher_ok ( &des_test2_22 );
cipher_ok ( &des_test2_23 );
cipher_ok ( &des_test2_24 );
cipher_ok ( &des_test2_25 );
cipher_ok ( &des_test2_26 );
cipher_ok ( &des_test2_27 );
cipher_ok ( &des_test2_28 );
cipher_ok ( &des_test2_29 );
cipher_ok ( &des_test2_30 );
cipher_ok ( &des_test2_31 );
cipher_ok ( &des_test2_32 );
cipher_ok ( &des_test2_33 );
cipher_ok ( &des_test2_34 );
cipher_ok ( &des_test2_35 );
cipher_ok ( &des_test2_36 );
cipher_ok ( &des_test2_37 );
cipher_ok ( &des_test2_38 );
cipher_ok ( &des_test2_39 );
cipher_ok ( &des_test2_40 );
cipher_ok ( &des_test2_41 );
cipher_ok ( &des_test2_42 );
cipher_ok ( &des_test2_43 );
cipher_ok ( &des_test2_44 );
cipher_ok ( &des_test2_45 );
cipher_ok ( &des_test2_46 );
cipher_ok ( &des_test2_47 );
cipher_ok ( &des_test2_48 );
cipher_ok ( &des_test2_49 );
cipher_ok ( &des_test2_50 );
cipher_ok ( &des_test2_51 );
cipher_ok ( &des_test2_52 );
cipher_ok ( &des_test2_53 );
cipher_ok ( &des_test2_54 );
cipher_ok ( &des_test2_55 );
cipher_ok ( &des_test2_56 );
cipher_ok ( &des_test2_57 );
cipher_ok ( &des_test2_58 );
cipher_ok ( &des_test2_59 );
cipher_ok ( &des_test2_60 );
cipher_ok ( &des_test2_61 );
cipher_ok ( &des_test2_62 );
cipher_ok ( &des_test2_63 );
cipher_ok ( &des_test2_64 );
/* Test 3: Data permutation tests */
cipher_ok ( &des_test3_1 );
cipher_ok ( &des_test3_2 );
cipher_ok ( &des_test3_3 );
cipher_ok ( &des_test3_4 );
cipher_ok ( &des_test3_5 );
cipher_ok ( &des_test3_6 );
cipher_ok ( &des_test3_7 );
cipher_ok ( &des_test3_8 );
cipher_ok ( &des_test3_9 );
cipher_ok ( &des_test3_10 );
cipher_ok ( &des_test3_11 );
cipher_ok ( &des_test3_12 );
cipher_ok ( &des_test3_13 );
cipher_ok ( &des_test3_14 );
cipher_ok ( &des_test3_15 );
cipher_ok ( &des_test3_16 );
cipher_ok ( &des_test3_17 );
cipher_ok ( &des_test3_18 );
cipher_ok ( &des_test3_19 );
cipher_ok ( &des_test3_20 );
cipher_ok ( &des_test3_21 );
cipher_ok ( &des_test3_22 );
cipher_ok ( &des_test3_23 );
cipher_ok ( &des_test3_24 );
cipher_ok ( &des_test3_25 );
cipher_ok ( &des_test3_26 );
cipher_ok ( &des_test3_27 );
cipher_ok ( &des_test3_28 );
cipher_ok ( &des_test3_29 );
cipher_ok ( &des_test3_30 );
cipher_ok ( &des_test3_31 );
cipher_ok ( &des_test3_32 );
/* Test 4: Key permutation tests */
cipher_ok ( &des_test4_1 );
cipher_ok ( &des_test4_2 );
cipher_ok ( &des_test4_3 );
cipher_ok ( &des_test4_4 );
cipher_ok ( &des_test4_5 );
cipher_ok ( &des_test4_6 );
cipher_ok ( &des_test4_7 );
cipher_ok ( &des_test4_8 );
cipher_ok ( &des_test4_9 );
cipher_ok ( &des_test4_10 );
cipher_ok ( &des_test4_11 );
cipher_ok ( &des_test4_12 );
cipher_ok ( &des_test4_13 );
cipher_ok ( &des_test4_14 );
cipher_ok ( &des_test4_15 );
cipher_ok ( &des_test4_16 );
cipher_ok ( &des_test4_17 );
cipher_ok ( &des_test4_18 );
cipher_ok ( &des_test4_19 );
cipher_ok ( &des_test4_20 );
cipher_ok ( &des_test4_21 );
cipher_ok ( &des_test4_22 );
cipher_ok ( &des_test4_23 );
cipher_ok ( &des_test4_24 );
cipher_ok ( &des_test4_25 );
cipher_ok ( &des_test4_26 );
cipher_ok ( &des_test4_27 );
cipher_ok ( &des_test4_28 );
cipher_ok ( &des_test4_29 );
cipher_ok ( &des_test4_30 );
cipher_ok ( &des_test4_31 );
cipher_ok ( &des_test4_32 );
cipher_ok ( &des_test4_33 );
cipher_ok ( &des_test4_34 );
cipher_ok ( &des_test4_35 );
cipher_ok ( &des_test4_36 );
cipher_ok ( &des_test4_37 );
cipher_ok ( &des_test4_38 );
cipher_ok ( &des_test4_39 );
cipher_ok ( &des_test4_40 );
cipher_ok ( &des_test4_41 );
cipher_ok ( &des_test4_42 );
cipher_ok ( &des_test4_43 );
cipher_ok ( &des_test4_44 );
cipher_ok ( &des_test4_45 );
cipher_ok ( &des_test4_46 );
cipher_ok ( &des_test4_47 );
cipher_ok ( &des_test4_48 );
cipher_ok ( &des_test4_49 );
cipher_ok ( &des_test4_50 );
cipher_ok ( &des_test4_51 );
cipher_ok ( &des_test4_52 );
cipher_ok ( &des_test4_53 );
cipher_ok ( &des_test4_54 );
cipher_ok ( &des_test4_55 );
cipher_ok ( &des_test4_56 );
/* Test 5: S-box tests */
cipher_ok ( &des_test5_1 );
cipher_ok ( &des_test5_2 );
cipher_ok ( &des_test5_3 );
cipher_ok ( &des_test5_4 );
cipher_ok ( &des_test5_5 );
cipher_ok ( &des_test5_6 );
cipher_ok ( &des_test5_7 );
cipher_ok ( &des_test5_8 );
cipher_ok ( &des_test5_9 );
cipher_ok ( &des_test5_10 );
cipher_ok ( &des_test5_11 );
cipher_ok ( &des_test5_12 );
cipher_ok ( &des_test5_13 );
cipher_ok ( &des_test5_14 );
cipher_ok ( &des_test5_15 );
cipher_ok ( &des_test5_16 );
cipher_ok ( &des_test5_17 );
cipher_ok ( &des_test5_18 );
cipher_ok ( &des_test5_19 );
/* Multi-block tests */
cipher_ok ( &des_unofficial_ecb );
cipher_ok ( &des_unofficial_cbc );
/* Speed tests */
DBG ( "DES-ECB encryption required %ld cycles per byte\n",
cipher_cost_encrypt ( &des_ecb_algorithm, 8 ) );
DBG ( "DES-ECB decryption required %ld cycles per byte\n",
cipher_cost_decrypt ( &des_ecb_algorithm, 8 ) );
DBG ( "DES-CBC encryption required %ld cycles per byte\n",
cipher_cost_encrypt ( &des_cbc_algorithm, 8 ) );
DBG ( "DES-CBC decryption required %ld cycles per byte\n",
cipher_cost_decrypt ( &des_cbc_algorithm, 8 ) );
}
/** DES self-test */
struct self_test des_test __self_test = {
.name = "des",
.exec = des_test_exec,
};

View File

@ -27,7 +27,8 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
*
* X25519 key exchange test
*
* Full key exchange test vectors are taken from RFC 7748.
* Full key exchange test vectors are taken from RFC7748.
*
*/
/* Forcibly enable assertions */
@ -135,6 +136,8 @@ struct x25519_key_test {
struct x25519_value expected;
/** Number of iterations */
unsigned int count;
/** Key exchange is expected to fail (i.e. produce all-zeroes) */
int fail;
};
/**
@ -142,14 +145,16 @@ struct x25519_key_test {
*
* @v name Test name
* @v COUNT Number of iterations
* @v FAIL Expected failure status
* @v BASE Base point
* @v SCALAR Scalar multiple
* @v EXPECTED Expected result
* @ret test X25519 key exchange test
*/
#define X25519_KEY_TEST( name, COUNT, BASE, SCALAR, EXPECTED ) \
#define X25519_KEY_TEST( name, COUNT, FAIL, BASE, SCALAR, EXPECTED ) \
static struct x25519_key_test name = { \
.count = COUNT, \
.fail = FAIL, \
.base = { .raw = BASE }, \
.scalar = { .raw = SCALAR }, \
.expected = { .raw = EXPECTED }, \
@ -258,6 +263,7 @@ static void x25519_key_okx ( struct x25519_key_test *test,
struct x25519_value scalar;
struct x25519_value actual;
unsigned int i;
int rc;
/* Construct input values */
memcpy ( &base, &test->base, sizeof ( test->base ) );
@ -271,7 +277,12 @@ static void x25519_key_okx ( struct x25519_key_test *test,
/* Calculate key */
for ( i = 0 ; i < test->count ; i++ ) {
x25519_key ( &base, &scalar, &actual );
rc = x25519_key ( &base, &scalar, &actual );
if ( test->fail ) {
okx ( rc != 0, file, line );
} else {
okx ( rc == 0, file, line );
}
memcpy ( &base, &scalar, sizeof ( base ) );
memcpy ( &scalar, &actual, sizeof ( scalar ) );
}
@ -460,7 +471,7 @@ X25519_INVERT_TEST ( invert_5,
* Scalar: 0xa546e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449ac4
* Result: 0xc3da55379de9c6908e94ea4df28d084f32eccf03491c71f754b4075577a28552
*/
X25519_KEY_TEST ( rfc7748_1, 1,
X25519_KEY_TEST ( rfc7748_1, 1, 0,
BASE ( 0xe6, 0xdb, 0x68, 0x67, 0x58, 0x30, 0x30, 0xdb, 0x35, 0x94,
0xc1, 0xa4, 0x24, 0xb1, 0x5f, 0x7c, 0x72, 0x66, 0x24, 0xec,
0x26, 0xb3, 0x35, 0x3b, 0x10, 0xa9, 0x03, 0xa6, 0xd0, 0xab,
@ -478,7 +489,7 @@ X25519_KEY_TEST ( rfc7748_1, 1,
* Scalar: 0x4b66e9d4d1b4673c5ad22691957d6af5c11b6421e0ea01d42ca4169e7918ba0d
* Result: 0x95cbde9476e8907d7aade45cb4b873f88b595a68799fa152e6f8f7647aac7957
*/
X25519_KEY_TEST ( rfc7748_2, 1,
X25519_KEY_TEST ( rfc7748_2, 1, 0,
BASE ( 0xe5, 0x21, 0x0f, 0x12, 0x78, 0x68, 0x11, 0xd3, 0xf4, 0xb7,
0x95, 0x9d, 0x05, 0x38, 0xae, 0x2c, 0x31, 0xdb, 0xe7, 0x10,
0x6f, 0xc0, 0x3c, 0x3e, 0xfc, 0x4c, 0xd5, 0x49, 0xc7, 0x15,
@ -496,7 +507,7 @@ X25519_KEY_TEST ( rfc7748_2, 1,
* Scalar: 0x0900000000000000000000000000000000000000000000000000000000000000
* Result: 0x422c8e7a6227d7bca1350b3e2bb7279f7897b87bb6854b783c60e80311ae3079
*/
X25519_KEY_TEST ( rfc7748_3, 1,
X25519_KEY_TEST ( rfc7748_3, 1, 0,
BASE ( 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@ -515,12 +526,12 @@ X25519_KEY_TEST ( rfc7748_3, 1,
* Result: 0xb1a5a73158904c020866c13939dd7e1aa26852ee1d2609c92e5a8f1debe2150a
* (after 100 iterations)
*
* RFC 7748 gives test vectors for 1000 and 1000000 iterations with
* RFC7748 gives test vectors for 1000 and 1000000 iterations with
* these starting values. This test case stops after 100 iterations
* to avoid a pointlessly slow test cycle in the common case of
* running tests under Valgrind.
*/
X25519_KEY_TEST ( rfc7748_4_100, 100,
X25519_KEY_TEST ( rfc7748_4_100, 100, 0,
BASE ( 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@ -534,6 +545,24 @@ X25519_KEY_TEST ( rfc7748_4_100, 100,
0x1d, 0x26, 0x09, 0xc9, 0x2e, 0x5a, 0x8f, 0x1d, 0xeb, 0xe2,
0x15, 0x0a ) );
/* Base: 2^255 - 19 + 1 (deliberately malicious public key)
* Scalar: 0x000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f
* Result: Failure (all zeros)
*/
X25519_KEY_TEST ( malicious, 1, 1,
BASE ( 0xee, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0x7f ),
SCALAR ( 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, 0x02, 0x03,
0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d,
0x0e, 0x0f ),
EXPECTED ( 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00 ) );
/**
* Perform X25519 self-tests
*
@ -561,6 +590,7 @@ static void x25519_test_exec ( void ) {
x25519_key_ok ( &rfc7748_2 );
x25519_key_ok ( &rfc7748_3 );
x25519_key_ok ( &rfc7748_4_100 );
x25519_key_ok ( &malicious );
}
/** X25519 self-test */