[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