[git commit] tls: make ECDHE_RSA work against our client (openssl s_client not yet)
Denys Vlasenko
vda.linux at googlemail.com
Sun Feb 15 14:16:26 UTC 2026
commit: https://git.busybox.net/busybox/commit/?id=7773faa8781d91bb328d38fcef1c5fd393e03230
branch: https://git.busybox.net/busybox/log/?h=master
function old new delta
tls_handshake_as_server 1601 2033 +432
sp_ecc_make_key_256 - 103 +103
curve_P256_compute_premaster - 65 +65
.rodata 108023 108079 +56
curve_x25519_generate_keypair - 44 +44
tls_get_zeroed_outbuf - 28 +28
curve_P256_generate_keypair - 27 +27
sp_256_from_bin_8 - 26 +26
curve_x25519_compute_premaster - 15 +15
tls_xread_record 708 704 -4
tls_handshake 1530 1519 -11
get_outbuf_fill_handshake_record 51 37 -14
sp_256_point_from_bin2x32 70 43 -27
curve_x25519_compute_pubkey_and_premaster 71 39 -32
curve_P256_compute_pubkey_and_premaster 167 65 -102
------------------------------------------------------------------------------
(add/remove: 7/0 grow/shrink: 2/6 up/down: 796/-190) Total: 606 bytes
Signed-off-by: Denys Vlasenko <vda.linux at googlemail.com>
---
networking/tls.c | 278 ++++++++++++++++++++++++++++++++++++++----------
networking/tls.h | 16 +++
networking/tls_fe.c | 47 ++++++--
networking/tls_sp_c32.c | 46 ++++++++
4 files changed, 320 insertions(+), 67 deletions(-)
diff --git a/networking/tls.c b/networking/tls.c
index 2f0afe00a..cde92ad1e 100644
--- a/networking/tls.c
+++ b/networking/tls.c
@@ -312,7 +312,9 @@ enum {
GOT_CERT_RSA_KEY_ALG = 1 << 1,
GOT_CERT_ECDSA_KEY_ALG = 1 << 2, // so far unused
GOT_EC_KEY = 1 << 3,
- GOT_EC_CURVE_X25519 = 1 << 4, // else P256
+ /* Client: server sent x25519 key in SERVER_KEY_EXCHANGE (else P256)
+ * Server: we chose x25519 based on client's supported_groups (else P256) */
+ USE_EC_CURVE_X25519 = 1 << 4,
ENCRYPTION_AESGCM = 1 << 5, // else AES-SHA (or NULL-SHA if ALLOW_RSA_NULL_SHA256=1)
};
@@ -412,8 +414,8 @@ struct tls_handshake_data {
int key_type_chosen;
psRsaKey_t rsa_priv_key;
- ///* For ECDHE: server's ephemeral EC private key */
- //uint8_t ecc_priv_key32[32];
+ /* For ECDHE: server's ephemeral EC private key */
+ uint8_t ecc_priv_key32[32];
#endif
};
enum {
@@ -430,7 +432,6 @@ static int is_minor_version_valid(tls_state_t *tls, uint8_t minor_ver)
{
#if ENABLE_SSL_SERVER // || ENABLE_FEATURE_HTTPD_SSL
if (tls->expecting_first_packet == 1) {
- tls->expecting_first_packet = 0;
/* First packet: accept TLS 1.0 (3.1) through TLS 1.3 (3.4)
* for compatibility with clients using other record versions */
return (minor_ver > 0 && minor_ver <= 4);
@@ -1836,7 +1837,7 @@ static void process_server_key(tls_state_t *tls, int len)
switch (t32) {
case _0x03001d20: //curve_x25519
dbg("got x25519 eccPubKey");
- tls->flags |= GOT_EC_CURVE_X25519;
+ tls->flags |= USE_EC_CURVE_X25519;
memcpy(tls->hsd->ecc_pub_key32, keybuf, 32);
break;
case _0x03001741: //curve_secp256r1 (aka P256)
@@ -2001,7 +2002,7 @@ static void send_client_key_exchange(tls_state_t *tls)
if (!(tls->flags & GOT_EC_KEY))
bb_simple_error_msg_and_die("server did not provide EC key");
- if (tls->flags & GOT_EC_CURVE_X25519) {
+ if (tls->flags & USE_EC_CURVE_X25519) {
/* ECDHE, curve x25519 */
dbg("computing x25519_premaster");
curve_x25519_compute_pubkey_and_premaster(
@@ -2431,7 +2432,8 @@ static void get_client_hello(tls_state_t *tls)
unsigned i, j;
struct client_hello *hp;
uint8_t *p;
- unsigned cipher_list_len;
+ int cipher_list_len;
+ int extensions_len;
int len;
len = tls_xread_handshake_block(tls, sizeof(*hp));
@@ -2439,9 +2441,9 @@ static void get_client_hello(tls_state_t *tls)
hp = (void*)(tls->inbuf + RECHDR_LEN);
if (hp->type != HANDSHAKE_CLIENT_HELLO
|| hp->len24_hi != 0
- /* hp->len24_mid,lo checked later */
+ || len != ((hp->len24_mid << 8) | hp->len24_lo) + 4
|| hp->proto_maj != TLS_MAJ
-///? || hp->proto_min != TLS_MIN
+ || !is_minor_version_valid(tls, hp->proto_min)
) {
bad_record_die(tls, "'client hello'", len);
}
@@ -2453,13 +2455,13 @@ static void get_client_hello(tls_state_t *tls)
/* Parse cipher suites to select one we support */
p = (uint8_t*)(hp + 1);
- /* Skip session ID */
- len -= RECHDR_LEN + sizeof(*hp);
- if (len < hp->session_id_len) {
- bb_simple_error_msg_and_die("malformed ClientHello");
- }
+ /* Skip session ID and handshake header */
+ len -= sizeof(*hp);
p += hp->session_id_len;
len -= hp->session_id_len;
+ if (len < 0) {
+ bb_simple_error_msg_and_die("malformed ClientHello");
+ }
/* Parse cipher suite list */
if (len < 2) {
@@ -2478,16 +2480,6 @@ static void get_client_hello(tls_state_t *tls)
const uint8_t *our_cipher = &supported_ciphers[i];
int key_type;
- /* Skip all ECDHE ciphers (0xC0xx) - we don't support server-side ephemeral
- * EC key generation yet. ECDHE_RSA uses RSA certificates (which we have)
- * but still requires generating ephemeral EC keys for the key exchange.
- * We only support plain RSA key exchange (0x00xx) on the server side.
- */
- if (our_cipher[0] == 0xC0) {
- //TODO: implement server-side ECDHE
- continue;
- }
-
/* Determine required key type for this cipher */
key_type = is_cipher_ECDSA(our_cipher);
if (key_type == KEY_ECDSA) {
@@ -2510,12 +2502,78 @@ static void get_client_hello(tls_state_t *tls)
set_cipher_parameters(tls, our_cipher);
dbg("Selected cipher: %04x", tls->cipher_id);
tls->hsd->key_type_chosen = key_type;
- return;
+ goto cipher_selected;
}
}
/* try our next cipherid */
}
bb_simple_error_msg_and_die("no common cipher suites");
+
+ cipher_selected:
+ /* Skip past cipher list */
+ p += cipher_list_len;
+ len -= cipher_list_len;
+
+ /* Skip compression methods */
+ len -= 1 + p[0];
+ p += 1 + p[0];
+
+ /* Parse extensions if present */
+ if (len < 2) {
+ dbg("No extensions");
+ return; /* no extensions */
+ }
+ extensions_len = (p[0] << 8) | p[1];
+ p += 2;
+ len -= 2;
+ dbg("Extensions total length: %u, remaining len: %d", extensions_len, len);
+
+ if (len < extensions_len) {
+ dbg("Malformed extensions length (len %d < extensions_len %u)", len, extensions_len);
+ return; /* malformed extensions, ignore */
+ }
+
+ /* Look for supported_groups extension (type 0x000a) */
+ while (extensions_len >= 4) {
+ unsigned ext_type = (p[0] << 8) | p[1];
+ int ext_len = (p[2] << 8) | p[3];
+ dbg("Extension type: 0x%04x, len: %u", ext_type, ext_len);
+ p += 4;
+ extensions_len -= 4;
+
+ if (extensions_len < ext_len) {
+ dbg("Extension length overflow");
+ return; /* malformed */
+ }
+
+ if (ext_type == 0x000a) { /* supported_groups */
+ /* Parse named curve list */
+ int curve_list_len = (p[0] << 8) | p[1];
+ dbg("Found supported_groups extension");
+ p += 2;
+ ext_len -= 2;
+ if (ext_len != curve_list_len)
+ return; /* malformed */
+ while (1) {
+ unsigned curve;
+ ext_len -= 2; /* skip (presumably existing) curve id */
+ if (ext_len < 0)
+ break; /* oops, it didn't */
+ curve = (p[0] << 8) | p[1];
+ if (curve == 0x001d) /* x25519 */
+ tls->flags |= USE_EC_CURVE_X25519;
+// if (curve == 0x0017) /* secp256r1 (P256) */
+// /* We'll try P256 as fallback without checking client support */
+ p += 2;
+ }
+ dbg("Client supports:%s",
+ (tls->flags & USE_EC_CURVE_X25519) ? " x25519" : " P256(assumed)");
+ return; /* found what we need */
+ }
+
+ p += ext_len;
+ extensions_len -= ext_len;
+ }
}
static void send_server_hello(tls_state_t *tls)
@@ -2580,6 +2638,67 @@ static void send_server_certificate(tls_state_t *tls)
xwrite_and_update_handshake_hash(tls, sz);
}
+static void send_server_key_exchange(tls_state_t *tls)
+{
+ struct server_key_exchange {
+ uint8_t type;
+ uint8_t len24_hi, len24_mid, len24_lo;
+ uint8_t curve_type; /* 3 = named curve */
+ uint8_t curve_id_hi, curve_id_lo;
+ uint8_t pubkey_len;
+ uint8_t pubkey[1 + 2 * 32]; /* for P256: 04 + x(32) + y(32) */
+ };
+ struct server_key_exchange *record;
+ int pubkey_len;
+ int total_len;
+
+ record = tls_get_zeroed_outbuf(tls, sizeof(*record));
+
+ record->type = HANDSHAKE_SERVER_KEY_EXCHANGE;
+ record->curve_type = 3; /* named curve */
+
+ /* Determine which curve to use based on client's supported_groups extension.
+ * Prefer x25519 (faster) if client supports it, otherwise use P256.
+ * If client didn't send supported_groups, default to P256 (most widely supported).
+ */
+ if (tls->flags & USE_EC_CURVE_X25519) { /* Use x25519 */
+ //record->curve_id_hi = 0x00; /* already zero from tls_get_zeroed_outbuf() */
+ record->curve_id_lo = 0x1d; /* x25519 */
+
+ /* Generate ephemeral keypair directly into output buffer */
+ curve_x25519_generate_keypair(tls->hsd->ecc_priv_key32, record->pubkey);
+
+ pubkey_len = 32;
+ dbg("Using x25519 for ECDHE");
+ } else { /* Use P256 (default or if client advertised it) */
+ //record->curve_id_hi = 0x00; /* already zero from tls_get_zeroed_outbuf() */
+ record->curve_id_lo = 0x17; /* secp256r1 (P256) */
+
+ /* Generate ephemeral keypair directly into output buffer */
+ record->pubkey[0] = 0x04; /* uncompressed point */
+ curve_P256_generate_keypair(tls->hsd->ecc_priv_key32, record->pubkey + 1);
+
+ pubkey_len = 1 + 2 * 32;
+ /* P256 is the default, no need to set USE_EC_CURVE_X25519 flag */
+ dbg("Using P256 for ECDHE");
+ }
+
+ record->pubkey_len = pubkey_len;
+
+ /* Calculate total length: curve_type(1) + curve_id(2) + pubkey_len(1) + pubkey */
+ total_len = 4 + pubkey_len;
+
+ //record->len24_hi = 0; /* already zero from tls_get_zeroed_outbuf() */
+ record->len24_mid = total_len >> 8;
+ record->len24_lo = total_len & 0xff;
+
+ /* Total message length */
+ total_len += 4; /* type + len24 */
+
+ dbg(">> SERVER_KEY_EXCHANGE");
+ xwrite_and_update_handshake_hash(tls, total_len);
+}
+
static void send_server_hello_done(tls_state_t *tls)
{
struct server_hello_done {
@@ -2600,15 +2719,14 @@ static void get_client_key_exchange(tls_state_t *tls)
struct client_key_exchange {
uint8_t type;
uint8_t len24_hi, len24_mid, len24_lo;
- uint8_t enckey_len_hi, enckey_len_lo; /* RSA encrypted premaster length */
- /* followed by RSA encrypted premaster secret */
+ uint8_t key[1]; /* Variable length: encrypted premaster (RSA) or EC point (ECDHE) */
};
struct client_key_exchange *record;
- uint8_t premaster[RSA_PREMASTER_SIZE];
- int len, enckey_len;
- uint8_t *encrypted_premaster;
+ uint8_t premaster[RSA_PREMASTER_SIZE > EC_CURVE_KEYSIZE ? RSA_PREMASTER_SIZE : EC_CURVE_KEYSIZE];
+ int len, premaster_size;
+ uint8_t *key_data;
- len = tls_xread_handshake_block(tls, 64);
+ len = tls_xread_handshake_block(tls, sizeof(*record));
record = (void*)(tls->inbuf + RECHDR_LEN);
if (record->type != HANDSHAKE_CLIENT_KEY_EXCHANGE) {
@@ -2616,40 +2734,85 @@ static void get_client_key_exchange(tls_state_t *tls)
}
dbg("<< CLIENT_KEY_EXCHANGE");
- /* Get the length of the encrypted premaster secret */
- enckey_len = (record->enckey_len_hi << 8) | record->enckey_len_lo;
- dbg("enckey_len:%d len:%d", enckey_len, len);
+ key_data = record->key;
- if (enckey_len < 128 || enckey_len > 512) {
- bb_simple_error_msg_and_die("bad encrypted premaster length");
- }
+ if (!(tls->flags & NEED_EC_KEY)) {
+ /* RSA key exchange */
+ int enckey_len;
- encrypted_premaster = (uint8_t*)(record + 1);
+ /* Get the length of the encrypted premaster secret */
+ enckey_len = (key_data[0] << 8) | key_data[1];
+ key_data += 2;
+ dbg("enckey_len:%d len:%d", enckey_len, len);
- /* Decrypt the premaster secret using server's private RSA key */
- {
- int32 ret;
- uint32 premaster_len;
- psRsaKey_t *key = &tls->hsd->rsa_priv_key;
+ if (enckey_len < 128 || enckey_len > 512) {
+ bb_simple_error_msg_and_die("bad encrypted premaster length");
+ }
+
+ /* Decrypt the premaster secret using server's private RSA key */
+ {
+ int32 ret;
+ uint32 plen;
+ psRsaKey_t *key = &tls->hsd->rsa_priv_key;
+
+ plen = RSA_PREMASTER_SIZE;
+ ret = psRsaDecryptPriv(NULL, key,
+ key_data, enckey_len,
+ premaster, plen, NULL);
- premaster_len = RSA_PREMASTER_SIZE;
- ret = psRsaDecryptPriv(NULL, key,
- encrypted_premaster, enckey_len,
- premaster, premaster_len, NULL);
+ if (ret != RSA_PREMASTER_SIZE) {
+ bb_error_msg_and_die("RSA decrypt failed or wrong premaster size: %d", ret);
+ }
+
+ dbg("Decrypted premaster secret (%d bytes)", ret);
- if (ret != RSA_PREMASTER_SIZE) {
- bb_error_msg_and_die("RSA decrypt failed or wrong premaster size: %d", ret);
+ /* Verify premaster format: should start with version 0x03 0x03 (TLS 1.2) */
+ if (premaster[0] != 0x03 || premaster[1] != 0x03) {
+ bb_simple_error_msg_and_die("bad premaster secret version");
+ }
}
+ premaster_size = RSA_PREMASTER_SIZE;
+ } else {
+ /* ECDHE key exchange */
+ int pubkey_len;
+ uint8_t *client_pubkey;
+
+ /* Get client's ephemeral public key length */
+ pubkey_len = *key_data++;
+ client_pubkey = key_data;
- dbg("Decrypted premaster secret (%d bytes)", ret);
+ dbg("ECDHE: client pubkey_len:%d", pubkey_len);
- /* Verify premaster format: should start with version 0x03 0x03 (TLS 1.2) */
- if (premaster[0] != 0x03 || premaster[1] != 0x03) {
- bb_simple_error_msg_and_die("bad premaster secret version");
+ /* Compute shared secret using client's public key and our private key */
+ if (tls->flags & USE_EC_CURVE_X25519) {
+ /* x25519 */
+ if (pubkey_len != CURVE25519_KEYSIZE) {
+ bb_simple_error_msg_and_die("bad x25519 public key length");
+ }
+ curve_x25519_compute_premaster(
+ tls->hsd->ecc_priv_key32, client_pubkey,
+ premaster
+ );
+ premaster_size = CURVE25519_KEYSIZE;
+ } else {
+ /* P256 */
+ if (pubkey_len != 1 + 2 * P256_KEYSIZE) {
+ bb_simple_error_msg_and_die("bad P256 public key length");
+ }
+ if (*client_pubkey++ != 0x04) {
+ bb_simple_error_msg_and_die("compressed EC points not supported");
+ }
+ curve_P256_compute_premaster(
+ tls->hsd->ecc_priv_key32, client_pubkey,
+ premaster
+ );
+ premaster_size = P256_KEYSIZE;
}
+
+ dbg("Computed ECDHE premaster secret (%d bytes)", premaster_size);
}
- derive_master_secret_and_keys(tls, premaster, RSA_PREMASTER_SIZE);
+ derive_master_secret_and_keys(tls, premaster, premaster_size);
/* Server decrypts with client_write_key, encrypts with server_write_key */
aes_setkey(&tls->aes_decrypt, tls->client_write_key, tls->key_size);
@@ -2932,9 +3095,8 @@ void FAST_FUNC tls_handshake_as_server(tls_state_t *tls,
load_pem_key_cert_pairs(tls, pem_filename);
sha256_begin(&tls->hsd->handshake_hash_ctx);
- tls->expecting_first_packet = 1;
- /* Server handshake sequence (RSA mode):
+ /* Server handshake sequence:
* 1. Receive ClientHello
* 2. Send ServerHello
* 3. Send Certificate
@@ -2947,9 +3109,13 @@ void FAST_FUNC tls_handshake_as_server(tls_state_t *tls,
* 10. Send ChangeCipherSpec
* 11. Send Finished (encrypted)
*/
+ tls->expecting_first_packet = 1;
get_client_hello(tls);
+ tls->expecting_first_packet = 0;
send_server_hello(tls);
send_server_certificate(tls);
+ if (tls->flags & NEED_EC_KEY)
+ send_server_key_exchange(tls);
send_server_hello_done(tls);
get_client_key_exchange(tls);
diff --git a/networking/tls.h b/networking/tls.h
index 167f8baf1..e59a77824 100644
--- a/networking/tls.h
+++ b/networking/tls.h
@@ -108,6 +108,22 @@ void tls_get_random(void *buf, unsigned len) FAST_FUNC;
#define P256_KEYSIZE 32
#define CURVE25519_KEYSIZE 32
+/* Separate keypair generation and premaster computation functions */
+void curve_x25519_generate_keypair(
+ uint8_t *privkey32, uint8_t *pubkey32) FAST_FUNC;
+void curve_x25519_compute_premaster(
+ const uint8_t *privkey32, const uint8_t *peerkey32,
+ uint8_t *premaster32) FAST_FUNC;
+
+#if ENABLE_SSL_SERVER
+void curve_P256_generate_keypair(
+ uint8_t *privkey32, uint8_t *pubkey2x32) FAST_FUNC;
+void curve_P256_compute_premaster(
+ const uint8_t *privkey32, const uint8_t *peerkey2x32,
+ uint8_t *premaster32) FAST_FUNC;
+#endif
+
+/* Combined operations (for client-side use) */
void curve_x25519_compute_pubkey_and_premaster(
uint8_t *pubkey32, uint8_t *premaster32,
const uint8_t *peerkey32) FAST_FUNC;
diff --git a/networking/tls_fe.c b/networking/tls_fe.c
index e5580fbcf..479d0aaee 100644
--- a/networking/tls_fe.c
+++ b/networking/tls_fe.c
@@ -607,22 +607,47 @@ static void curve25519(byte *result, const byte *e, const byte *q)
fe_normalize(result);
}
-/* interface to bbox's TLS code: */
+/* interface to bbox's TLS code:
+ *
+ * Wire format for elliptic curve points differs between curves:
+ * - P256: point is (x,y) where each coordinate is a 256-bit (32-byte) big-endian integer.
+ * Wire format: 64 bytes total (plus 0x04 prefix byte for "uncompressed point").
+ * - x25519: point is a single 256-bit (32-byte) little-endian integer.
+ * Wire format: 32 bytes.
+ *
+ * The interface functions below accept and generate EC points in their respective
+ * wire formats. Internal calculations may use different representations, but all
+ * conversions are handled internally within these functions.
+ * (Note: x25519 implementation in this file uses wire format internally as well)
+ */
+
+/* Generate x25519 keypair: random private key + corresponding public key */
+void FAST_FUNC curve_x25519_generate_keypair(uint8_t *privkey32, uint8_t *pubkey32)
+{
+ /* Generate random private key, see RFC 7748 */
+ tls_get_random(privkey32, CURVE25519_KEYSIZE);
+ privkey32[0] &= 0xf8;
+ privkey32[CURVE25519_KEYSIZE-1] = ((privkey32[CURVE25519_KEYSIZE-1] & 0x7f) | 0x40);
+
+ /* Compute public key from private key */
+ curve25519(pubkey32, privkey32, NULL /* "use base point of x25519" */);
+}
+
+/* Compute shared secret (premaster) from our private key and peer's public key */
+void FAST_FUNC curve_x25519_compute_premaster(
+ const uint8_t *privkey32, const uint8_t *peerkey32,
+ uint8_t *premaster32)
+{
+ curve25519(premaster32, privkey32, peerkey32);
+}
+/* Combined operation: generate keypair and compute premaster in one call */
void FAST_FUNC curve_x25519_compute_pubkey_and_premaster(
uint8_t *pubkey, uint8_t *premaster,
const uint8_t *peerkey32)
{
uint8_t privkey[CURVE25519_KEYSIZE]; //[32]
- /* Generate random private key, see RFC 7748 */
- tls_get_random(privkey, sizeof(privkey));
- privkey[0] &= 0xf8;
- privkey[CURVE25519_KEYSIZE-1] = ((privkey[CURVE25519_KEYSIZE-1] & 0x7f) | 0x40);
-
- /* Compute public key */
- curve25519(pubkey, privkey, NULL /* "use base point of x25519" */);
-
- /* Compute premaster using peer's public key */
- curve25519(premaster, privkey, peerkey32);
+ curve_x25519_generate_keypair(privkey, pubkey);
+ curve_x25519_compute_premaster(privkey, peerkey32, premaster);
}
diff --git a/networking/tls_sp_c32.c b/networking/tls_sp_c32.c
index e493c436a..90ab61a56 100644
--- a/networking/tls_sp_c32.c
+++ b/networking/tls_sp_c32.c
@@ -1514,6 +1514,52 @@ static void sp_ecc_make_key_256(sp_digit privkey[8], uint8_t *pubkey)
memset(point, 0, sizeof(point)); //paranoia
}
+/* interface to bbox's TLS code:
+ *
+ * Wire format for elliptic curve points differs between curves:
+ * - P256: point is (x,y) where each coordinate is a 256-bit (32-byte) big-endian integer.
+ * Wire format: 64 bytes total (plus 0x04 prefix byte for "uncompressed point").
+ * - x25519: point is a single 256-bit (32-byte) little-endian integer.
+ * Wire format: 32 bytes.
+ *
+ * The interface functions below accept and generate EC points in their respective
+ * wire formats. Internal calculations may use different representations, but all
+ * conversions are handled internally within these functions.
+ */
+
+#if ENABLE_SSL_SERVER
+/* Generate P256 keypair: random private key + corresponding public key */
+void FAST_FUNC curve_P256_generate_keypair(uint8_t *privkey32, uint8_t *pubkey2x32)
+{
+ sp_digit privkey_sp[8];
+
+ /* Generate keypair using internal representation */
+ sp_ecc_make_key_256(privkey_sp, pubkey2x32);
+
+ /* Convert private key to binary format for storage */
+ sp_256_to_bin_8(privkey_sp, privkey32);
+
+ memset(privkey_sp, 0, sizeof(privkey_sp)); //paranoia
+}
+
+/* Compute shared secret (premaster) from our private key and peer's public key */
+void FAST_FUNC curve_P256_compute_premaster(
+ const uint8_t *privkey32, const uint8_t *peerkey2x32,
+ uint8_t *premaster32)
+{
+ sp_digit privkey_sp[8];
+
+ /* Convert binary private key to internal representation */
+ sp_256_from_bin_8(privkey_sp, privkey32);
+
+ /* Compute shared secret */
+ sp_ecc_secret_gen_256(privkey_sp, peerkey2x32, premaster32);
+
+ memset(privkey_sp, 0, sizeof(privkey_sp)); //paranoia
+}
+#endif
+
+/* Combined operation: generate keypair and compute premaster in one call */
void FAST_FUNC curve_P256_compute_pubkey_and_premaster(
uint8_t *pubkey2x32, uint8_t *premaster32,
const uint8_t *peerkey2x32)
More information about the busybox-cvs
mailing list