mirror of
https://github.com/ipxe/ipxe
synced 2026-07-02 20:10:19 +03:00
[crypto] Generalise notion of uncompressed elliptic curve points
With algorithm private data pointers now available, the general mechanism for key exchange using uncompressed elliptic curve points can be separated from the Weierstrass curve implementation. Generalise the mechanism for performing elliptic curve key exchange using uncompressed affine co-ordinates. Signed-off-by: Michael Brown <mcb30@ipxe.org>
This commit is contained in:
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
* Copyright (C) 2026 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_SECBOOT ( PERMITTED );
|
||||
|
||||
/** @file
|
||||
*
|
||||
* Elliptic curves
|
||||
*
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <ipxe/crypto.h>
|
||||
#include <ipxe/elliptic.h>
|
||||
|
||||
/**
|
||||
* Share public key
|
||||
*
|
||||
* @v exchange Key exchange algorithm
|
||||
* @v private Private key
|
||||
* @v public Public key to fill in
|
||||
*/
|
||||
void elliptic_share ( struct exchange_algorithm *exchange, const void *private,
|
||||
void *public ) {
|
||||
struct elliptic_curve *curve = exchange->priv;
|
||||
size_t len = exchange->sharedsize;
|
||||
elliptic_uncompressed_t ( len ) *result = public;
|
||||
int rc;
|
||||
|
||||
/* Sanity checks */
|
||||
assert ( curve->keysize == exchange->privsize );
|
||||
assert ( curve->pointsize == sizeof ( result->xy ) );
|
||||
assert ( sizeof ( *result ) == exchange->pubsize );
|
||||
|
||||
/* Calculate public key */
|
||||
result->format = ELLIPTIC_FORMAT_UNCOMPRESSED;
|
||||
rc = elliptic_multiply ( curve, curve->base, private, &result->xy );
|
||||
|
||||
/* Can never fail when using the curve's own base point */
|
||||
assert ( rc == 0 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Agree shared secret
|
||||
*
|
||||
* @v exchange Key exchange algorithm
|
||||
* @v private Private key
|
||||
* @v partner Partner public key
|
||||
* @v shared Shared secret to fill in
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
int elliptic_agree ( struct exchange_algorithm *exchange, const void *private,
|
||||
const void *partner, void *shared ) {
|
||||
struct elliptic_curve *curve = exchange->priv;
|
||||
size_t len = exchange->sharedsize;
|
||||
const elliptic_uncompressed_t ( len ) *base = partner;
|
||||
elliptic_uncompressed_t ( len ) result;
|
||||
int rc;
|
||||
|
||||
/* Sanity checks */
|
||||
assert ( curve->keysize == exchange->privsize );
|
||||
assert ( curve->pointsize == sizeof ( base->xy ) );
|
||||
assert ( curve->pointsize == sizeof ( result.xy ) );
|
||||
assert ( sizeof ( *base ) == exchange->pubsize );
|
||||
assert ( sizeof ( result.x ) == exchange->sharedsize );
|
||||
|
||||
/* Calculate shared secret */
|
||||
if ( ( rc = elliptic_multiply ( curve, &base->xy, private,
|
||||
result.xy ) ) != 0 )
|
||||
return rc;
|
||||
memcpy ( shared, &result.x, sizeof ( result.x ) );
|
||||
|
||||
/* Check for point at infinity */
|
||||
if ( elliptic_is_infinity ( curve, &result.xy ) )
|
||||
return -EPERM;
|
||||
|
||||
/* Check format byte */
|
||||
if ( base->format != ELLIPTIC_FORMAT_UNCOMPRESSED )
|
||||
return -EPERM;
|
||||
|
||||
return 0;
|
||||
}
|
||||
+4
-1
@@ -71,5 +71,8 @@ static const uint8_t p256_order[P256_LEN] = {
|
||||
};
|
||||
|
||||
/** P-256 elliptic curve */
|
||||
WEIERSTRASS_CURVE ( p256, p256_curve, p256_algorithm, P256_LEN,
|
||||
WEIERSTRASS_CURVE ( p256, p256_curve, P256_LEN,
|
||||
p256_prime, p256_a, p256_b, p256_base, p256_order );
|
||||
|
||||
/** P-256 key exchange */
|
||||
ELLIPTIC_EXCHANGE ( p256, p256_algorithm, P256_LEN, &p256_curve );
|
||||
|
||||
+4
-1
@@ -82,5 +82,8 @@ static const uint8_t p384_order[P384_LEN] = {
|
||||
};
|
||||
|
||||
/** P-384 elliptic curve */
|
||||
WEIERSTRASS_CURVE ( p384, p384_curve, p384_algorithm, P384_LEN,
|
||||
WEIERSTRASS_CURVE ( p384, p384_curve, P384_LEN,
|
||||
p384_prime, p384_a, p384_b, p384_base, p384_order );
|
||||
|
||||
/** P-384 key exchange */
|
||||
ELLIPTIC_EXCHANGE ( p384, p384_algorithm, P384_LEN, &p384_curve );
|
||||
|
||||
@@ -1038,63 +1038,3 @@ int weierstrass_add_once ( struct elliptic_curve *curve,
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Share public key
|
||||
*
|
||||
* @v exchange Key exchange algorithm
|
||||
* @v private Private key
|
||||
* @v public Public key to fill in
|
||||
*/
|
||||
void weierstrass_share ( struct exchange_algorithm *exchange,
|
||||
const void *private, void *public ) {
|
||||
struct elliptic_curve *curve = exchange->priv;
|
||||
struct weierstrass_curve *weierstrass = curve->priv;
|
||||
size_t len = weierstrass->len;
|
||||
weierstrass_uncompressed_t ( len ) *uncompressed = public;
|
||||
int rc;
|
||||
|
||||
/* Calculate public key */
|
||||
uncompressed->format = WEIERSTRASS_FORMAT;
|
||||
rc = weierstrass_multiply ( curve, weierstrass->base, private,
|
||||
&uncompressed->xy );
|
||||
|
||||
/* Can never fail when using the curve's own base point */
|
||||
assert ( rc == 0 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Agree shared secret
|
||||
*
|
||||
* @v exchange Key exchange algorithm
|
||||
* @v private Private key
|
||||
* @v partner Partner public key
|
||||
* @v shared Shared secret to fill in
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
int weierstrass_agree ( struct exchange_algorithm *exchange,
|
||||
const void *private, const void *partner,
|
||||
void *shared ) {
|
||||
struct elliptic_curve *curve = exchange->priv;
|
||||
struct weierstrass_curve *weierstrass = curve->priv;
|
||||
size_t len = weierstrass->len;
|
||||
const weierstrass_uncompressed_t ( len ) *uncompressed = partner;
|
||||
weierstrass_raw_t ( len ) point;
|
||||
int rc;
|
||||
|
||||
/* Calculate shared secret */
|
||||
if ( ( rc = weierstrass_multiply ( curve, &uncompressed->xy, private,
|
||||
&point.xy ) ) != 0 )
|
||||
return rc;
|
||||
memcpy ( shared, &point.x, sizeof ( point.x ) );
|
||||
|
||||
/* Check for point at infinity */
|
||||
if ( weierstrass_is_infinity ( curve, &point.xy ) )
|
||||
return -EPERM;
|
||||
|
||||
/* Check format byte */
|
||||
if ( uncompressed->format != WEIERSTRASS_FORMAT )
|
||||
return -EPERM;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
#ifndef _IPXE_ELLIPTIC_H
|
||||
#define _IPXE_ELLIPTIC_H
|
||||
|
||||
/** @file
|
||||
*
|
||||
* Elliptic curves
|
||||
*
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||
FILE_SECBOOT ( PERMITTED );
|
||||
|
||||
#include <stdint.h>
|
||||
#include <ipxe/crypto.h>
|
||||
|
||||
/** An uncompressed elliptic curve point */
|
||||
#define elliptic_uncompressed_t( len ) \
|
||||
struct { \
|
||||
uint8_t format; \
|
||||
union { \
|
||||
struct { \
|
||||
uint8_t x[ (len) ]; \
|
||||
uint8_t y[ (len) ]; \
|
||||
} __attribute__ (( packed )); \
|
||||
uint8_t xy[ (len) * 2 ]; \
|
||||
}; \
|
||||
} __attribute__ (( packed ))
|
||||
|
||||
/** Format byte for uncompressed curve point representation */
|
||||
#define ELLIPTIC_FORMAT_UNCOMPRESSED 0x04
|
||||
|
||||
extern void elliptic_share ( struct exchange_algorithm *exchange,
|
||||
const void *private, void *public );
|
||||
extern int elliptic_agree ( struct exchange_algorithm *exchange,
|
||||
const void *private, const void *partner,
|
||||
void *shared );
|
||||
|
||||
/** Define an uncompressed elliptic curve point key exchange algorithm */
|
||||
#define ELLIPTIC_EXCHANGE( _name, _exchange, _len, _curve ) \
|
||||
struct exchange_algorithm _exchange = { \
|
||||
.name = #_name, \
|
||||
.privsize = (_len), \
|
||||
.pubsize = sizeof ( elliptic_uncompressed_t (_len) ), \
|
||||
.sharedsize = (_len), \
|
||||
.share = elliptic_share, \
|
||||
.agree = elliptic_agree, \
|
||||
.priv = _curve, \
|
||||
}
|
||||
|
||||
#endif /* _IPXE_ELLIPTIC_H */
|
||||
@@ -447,7 +447,7 @@ FILE_SECBOOT ( PERMITTED );
|
||||
#define ERRFILE_usb_settings ( ERRFILE_OTHER | 0x00650000 )
|
||||
#define ERRFILE_weierstrass ( ERRFILE_OTHER | 0x00660000 )
|
||||
#define ERRFILE_efi_cacert ( ERRFILE_OTHER | 0x00670000 )
|
||||
#define ERRFILE_ecdhe ( ERRFILE_OTHER | 0x00680000 )
|
||||
#define ERRFILE_elliptic ( ERRFILE_OTHER | 0x00680000 )
|
||||
#define ERRFILE_ecdsa ( ERRFILE_OTHER | 0x00690000 )
|
||||
#define ERRFILE_crypto_null ( ERRFILE_OTHER | 0x006a0000 )
|
||||
#define ERRFILE_ffdhe ( ERRFILE_OTHER | 0x006b0000 )
|
||||
|
||||
@@ -12,6 +12,7 @@ FILE_SECBOOT ( PERMITTED );
|
||||
|
||||
#include <ipxe/bigint.h>
|
||||
#include <ipxe/crypto.h>
|
||||
#include <ipxe/elliptic.h>
|
||||
|
||||
/** Number of axes in Weierstrass curve point representation */
|
||||
#define WEIERSTRASS_AXES 2
|
||||
@@ -67,37 +68,6 @@ FILE_SECBOOT ( PERMITTED );
|
||||
bigint_t ( size * 3 ) all; \
|
||||
}
|
||||
|
||||
/**
|
||||
* Define a Weierstrass raw affine co-ordinate type
|
||||
*
|
||||
* @v len Length of scalar values
|
||||
* @ret type Raw affine co-ordinate type
|
||||
*/
|
||||
#define weierstrass_raw_t( len ) \
|
||||
union { \
|
||||
uint8_t axis[2][ len ]; \
|
||||
struct { \
|
||||
uint8_t x[ len ]; \
|
||||
uint8_t y[ len ]; \
|
||||
} __attribute__ (( packed )); \
|
||||
uint8_t xy[ len * 2 ]; \
|
||||
}
|
||||
|
||||
/**
|
||||
* Define a Weierstrass "uncompressed" affine co-ordinate type
|
||||
*
|
||||
* @v len Length of scalar values
|
||||
* @ret type Uncompressed affine co-ordinate type
|
||||
*/
|
||||
#define weierstrass_uncompressed_t( len ) \
|
||||
struct { \
|
||||
uint8_t format; \
|
||||
weierstrass_raw_t ( len ); \
|
||||
} __attribute__ (( packed ))
|
||||
|
||||
/** Format byte for Weierstrass curve point representation */
|
||||
#define WEIERSTRASS_FORMAT 0x04 /* "uncompressed" */
|
||||
|
||||
/** Indexes for stored multiples of the field prime */
|
||||
enum weierstrass_multiple {
|
||||
WEIERSTRASS_N = 0,
|
||||
@@ -169,8 +139,8 @@ extern int weierstrass_agree ( struct exchange_algorithm *exchange,
|
||||
void *shared );
|
||||
|
||||
/** Define a Weierstrass curve */
|
||||
#define WEIERSTRASS_CURVE( _name, _curve, _exchange, _len, _prime, \
|
||||
_a, _b, _base, _order ) \
|
||||
#define WEIERSTRASS_CURVE( _name, _curve, _len, _prime, _a, _b, _base, \
|
||||
_order ) \
|
||||
static bigint_t ( weierstrass_size(_len) ) \
|
||||
_name ## _cache[WEIERSTRASS_NUM_CACHED]; \
|
||||
static struct weierstrass_curve _name ## _weierstrass = { \
|
||||
@@ -193,7 +163,7 @@ extern int weierstrass_agree ( struct exchange_algorithm *exchange,
|
||||
}; \
|
||||
struct elliptic_curve _curve = { \
|
||||
.name = #_name, \
|
||||
.pointsize = sizeof ( weierstrass_raw_t(_len) ), \
|
||||
.pointsize = ( (_len) * WEIERSTRASS_AXES ), \
|
||||
.keysize = (_len), \
|
||||
.base = (_base), \
|
||||
.order = (_order), \
|
||||
@@ -201,15 +171,6 @@ extern int weierstrass_agree ( struct exchange_algorithm *exchange,
|
||||
.multiply = weierstrass_multiply, \
|
||||
.add = weierstrass_add_once, \
|
||||
.priv = &_name ## _weierstrass, \
|
||||
}; \
|
||||
struct exchange_algorithm _exchange = { \
|
||||
.name = #_name, \
|
||||
.privsize = (_len), \
|
||||
.pubsize = sizeof ( weierstrass_uncompressed_t(_len) ), \
|
||||
.sharedsize = (_len), \
|
||||
.share = weierstrass_share, \
|
||||
.agree = weierstrass_agree, \
|
||||
.priv = &_curve, \
|
||||
}
|
||||
|
||||
#endif /* _IPXE_WEIERSTRASS_H */
|
||||
|
||||
Reference in New Issue
Block a user