mirror of https://github.com/ipxe/ipxe.git
[tls] Allow for NIST elliptic curve point formats
The elliptic curve point representation for the x25519 curve includes only the X value, since the curve is designed such that the Montgomery ladder does not need to ever know or calculate a Y value. There is no curve point format byte: the public key data is simply the X value. The pre-master secret is also simply the X value of the shared secret curve point. The point representation for the NIST curves includes both X and Y values, and a single curve point format byte that must indicate that the format is uncompressed. The pre-master secret for the NIST curves does not include both X and Y values: only the X value is used. Extend the definition of an elliptic curve to allow the point size to be specified separately from the key size, and extend the definition of a TLS named curve to include an optional curve point format byte and a pre-master secret length. Signed-off-by: Michael Brown <mcb30@ipxe.org>pull/1386/head
parent
df7ec31766
commit
c9291bc5c7
|
@ -42,4 +42,5 @@ struct asn1_algorithm x25519_algorithm __asn1_algorithm = {
|
||||||
struct tls_named_curve tls_x25519_named_curve __tls_named_curve ( 01 ) = {
|
struct tls_named_curve tls_x25519_named_curve __tls_named_curve ( 01 ) = {
|
||||||
.curve = &x25519_curve,
|
.curve = &x25519_curve,
|
||||||
.code = htons ( TLS_NAMED_CURVE_X25519 ),
|
.code = htons ( TLS_NAMED_CURVE_X25519 ),
|
||||||
|
.pre_master_secret_len = sizeof ( struct x25519_value ),
|
||||||
};
|
};
|
||||||
|
|
|
@ -839,6 +839,7 @@ static int x25519_curve_multiply ( const void *base, const void *scalar,
|
||||||
/** X25519 elliptic curve */
|
/** X25519 elliptic curve */
|
||||||
struct elliptic_curve x25519_curve = {
|
struct elliptic_curve x25519_curve = {
|
||||||
.name = "x25519",
|
.name = "x25519",
|
||||||
|
.pointsize = sizeof ( struct x25519_value ),
|
||||||
.keysize = sizeof ( struct x25519_value ),
|
.keysize = sizeof ( struct x25519_value ),
|
||||||
.multiply = x25519_curve_multiply,
|
.multiply = x25519_curve_multiply,
|
||||||
};
|
};
|
||||||
|
|
|
@ -184,7 +184,9 @@ struct pubkey_algorithm {
|
||||||
struct elliptic_curve {
|
struct elliptic_curve {
|
||||||
/** Curve name */
|
/** Curve name */
|
||||||
const char *name;
|
const char *name;
|
||||||
/** Key size */
|
/** Point (and public key) size */
|
||||||
|
size_t pointsize;
|
||||||
|
/** Scalar (and private key) size */
|
||||||
size_t keysize;
|
size_t keysize;
|
||||||
/** Multiply scalar by curve point
|
/** Multiply scalar by curve point
|
||||||
*
|
*
|
||||||
|
|
|
@ -218,12 +218,19 @@ struct tls_cipher_suite {
|
||||||
/** TLS named curved type */
|
/** TLS named curved type */
|
||||||
#define TLS_NAMED_CURVE_TYPE 3
|
#define TLS_NAMED_CURVE_TYPE 3
|
||||||
|
|
||||||
|
/** TLS uncompressed curve point format */
|
||||||
|
#define TLS_POINT_FORMAT_UNCOMPRESSED 4
|
||||||
|
|
||||||
/** A TLS named curve */
|
/** A TLS named curve */
|
||||||
struct tls_named_curve {
|
struct tls_named_curve {
|
||||||
/** Elliptic curve */
|
/** Elliptic curve */
|
||||||
struct elliptic_curve *curve;
|
struct elliptic_curve *curve;
|
||||||
/** Numeric code (in network-endian order) */
|
/** Numeric code (in network-endian order) */
|
||||||
uint16_t code;
|
uint16_t code;
|
||||||
|
/** Curve point format byte (if any) */
|
||||||
|
uint8_t format;
|
||||||
|
/** Pre-master secret length */
|
||||||
|
uint8_t pre_master_secret_len;
|
||||||
};
|
};
|
||||||
|
|
||||||
/** TLS named curve table */
|
/** TLS named curve table */
|
||||||
|
|
|
@ -1671,6 +1671,9 @@ static int tls_send_client_key_exchange_ecdhe ( struct tls_connection *tls ) {
|
||||||
uint8_t public[0];
|
uint8_t public[0];
|
||||||
} __attribute__ (( packed )) *ecdh;
|
} __attribute__ (( packed )) *ecdh;
|
||||||
size_t param_len;
|
size_t param_len;
|
||||||
|
size_t pointsize;
|
||||||
|
size_t keysize;
|
||||||
|
size_t offset;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
/* Parse ServerKeyExchange record */
|
/* Parse ServerKeyExchange record */
|
||||||
|
@ -1706,9 +1709,13 @@ static int tls_send_client_key_exchange_ecdhe ( struct tls_connection *tls ) {
|
||||||
tls->server.exchange_len );
|
tls->server.exchange_len );
|
||||||
return -ENOTSUP_CURVE;
|
return -ENOTSUP_CURVE;
|
||||||
}
|
}
|
||||||
|
DBGC ( tls, "TLS %p using named curve %s\n", tls, curve->curve->name );
|
||||||
|
pointsize = curve->curve->pointsize;
|
||||||
|
keysize = curve->curve->keysize;
|
||||||
|
offset = ( curve->format ? 1 : 0 );
|
||||||
|
|
||||||
/* Check key length */
|
/* Check key length */
|
||||||
if ( ecdh->public_len != curve->curve->keysize ) {
|
if ( ecdh->public_len != ( offset + pointsize ) ) {
|
||||||
DBGC ( tls, "TLS %p invalid %s key\n",
|
DBGC ( tls, "TLS %p invalid %s key\n",
|
||||||
tls, curve->curve->name );
|
tls, curve->curve->name );
|
||||||
DBGC_HDA ( tls, 0, tls->server.exchange,
|
DBGC_HDA ( tls, 0, tls->server.exchange,
|
||||||
|
@ -1716,15 +1723,23 @@ static int tls_send_client_key_exchange_ecdhe ( struct tls_connection *tls ) {
|
||||||
return -EINVAL_KEY_EXCHANGE;
|
return -EINVAL_KEY_EXCHANGE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Check curve point format byte (if present) */
|
||||||
|
if ( curve->format && ( ecdh->public[0] != curve->format ) ) {
|
||||||
|
DBGC ( tls, "TLS %p invalid %s curve point format\n",
|
||||||
|
tls, curve->curve->name );
|
||||||
|
DBGC_HDA ( tls, 0, tls->server.exchange,
|
||||||
|
tls->server.exchange_len );
|
||||||
|
return -EINVAL_KEY_EXCHANGE;
|
||||||
|
}
|
||||||
|
|
||||||
/* Construct pre-master secret and ClientKeyExchange record */
|
/* Construct pre-master secret and ClientKeyExchange record */
|
||||||
{
|
{
|
||||||
size_t len = curve->curve->keysize;
|
uint8_t private[keysize];
|
||||||
uint8_t private[len];
|
uint8_t pre_master_secret[pointsize];
|
||||||
uint8_t pre_master_secret[len];
|
|
||||||
struct {
|
struct {
|
||||||
uint32_t type_length;
|
uint32_t type_length;
|
||||||
uint8_t public_len;
|
uint8_t public_len;
|
||||||
uint8_t public[len];
|
uint8_t public[ecdh->public_len];
|
||||||
} __attribute__ (( packed )) key_xchg;
|
} __attribute__ (( packed )) key_xchg;
|
||||||
|
|
||||||
/* Generate ephemeral private key */
|
/* Generate ephemeral private key */
|
||||||
|
@ -1733,9 +1748,9 @@ static int tls_send_client_key_exchange_ecdhe ( struct tls_connection *tls ) {
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Calculate pre-master secret */
|
/* Exchange keys */
|
||||||
if ( ( rc = ecdhe_key ( curve->curve, ecdh->public,
|
if ( ( rc = ecdhe_key ( curve->curve, ( ecdh->public + offset ),
|
||||||
private, key_xchg.public,
|
private, ( key_xchg.public + offset ),
|
||||||
pre_master_secret ) ) != 0 ) {
|
pre_master_secret ) ) != 0 ) {
|
||||||
DBGC ( tls, "TLS %p could not exchange ECDHE key: %s\n",
|
DBGC ( tls, "TLS %p could not exchange ECDHE key: %s\n",
|
||||||
tls, strerror ( rc ) );
|
tls, strerror ( rc ) );
|
||||||
|
@ -1743,14 +1758,17 @@ static int tls_send_client_key_exchange_ecdhe ( struct tls_connection *tls ) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Generate master secret */
|
/* Generate master secret */
|
||||||
tls_generate_master_secret ( tls, pre_master_secret, len );
|
tls_generate_master_secret ( tls, pre_master_secret,
|
||||||
|
curve->pre_master_secret_len );
|
||||||
|
|
||||||
/* Generate Client Key Exchange record */
|
/* Generate Client Key Exchange record */
|
||||||
key_xchg.type_length =
|
key_xchg.type_length =
|
||||||
( cpu_to_le32 ( TLS_CLIENT_KEY_EXCHANGE ) |
|
( cpu_to_le32 ( TLS_CLIENT_KEY_EXCHANGE ) |
|
||||||
htonl ( sizeof ( key_xchg ) -
|
htonl ( sizeof ( key_xchg ) -
|
||||||
sizeof ( key_xchg.type_length ) ) );
|
sizeof ( key_xchg.type_length ) ) );
|
||||||
key_xchg.public_len = len;
|
key_xchg.public_len = sizeof ( key_xchg.public );
|
||||||
|
if ( curve->format )
|
||||||
|
key_xchg.public[0] = curve->format;
|
||||||
|
|
||||||
/* Transmit Client Key Exchange record */
|
/* Transmit Client Key Exchange record */
|
||||||
if ( ( rc = tls_send_handshake ( tls, &key_xchg,
|
if ( ( rc = tls_send_handshake ( tls, &key_xchg,
|
||||||
|
|
Loading…
Reference in New Issue