aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2026-02-15 00:13:51 +0100
committerDenys Vlasenko <vda.linux@googlemail.com>2026-02-15 15:16:26 +0100
commit7773faa8781d91bb328d38fcef1c5fd393e03230 (patch)
tree2832c942e888139334c11cd69964b0388b0bc9c8
parent2ab2c258479ef140ea59481fb493b113219201b9 (diff)
downloadbusybox-w32-7773faa8781d91bb328d38fcef1c5fd393e03230.tar.gz
busybox-w32-7773faa8781d91bb328d38fcef1c5fd393e03230.tar.bz2
busybox-w32-7773faa8781d91bb328d38fcef1c5fd393e03230.zip
tls: make ECDHE_RSA work against our client (openssl s_client not yet)
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@googlemail.com>
-rw-r--r--networking/tls.c278
-rw-r--r--networking/tls.h16
-rw-r--r--networking/tls_fe.c47
-rw-r--r--networking/tls_sp_c32.c46
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 {
312 GOT_CERT_RSA_KEY_ALG = 1 << 1, 312 GOT_CERT_RSA_KEY_ALG = 1 << 1,
313 GOT_CERT_ECDSA_KEY_ALG = 1 << 2, // so far unused 313 GOT_CERT_ECDSA_KEY_ALG = 1 << 2, // so far unused
314 GOT_EC_KEY = 1 << 3, 314 GOT_EC_KEY = 1 << 3,
315 GOT_EC_CURVE_X25519 = 1 << 4, // else P256 315 /* Client: server sent x25519 key in SERVER_KEY_EXCHANGE (else P256)
316 * Server: we chose x25519 based on client's supported_groups (else P256) */
317 USE_EC_CURVE_X25519 = 1 << 4,
316 ENCRYPTION_AESGCM = 1 << 5, // else AES-SHA (or NULL-SHA if ALLOW_RSA_NULL_SHA256=1) 318 ENCRYPTION_AESGCM = 1 << 5, // else AES-SHA (or NULL-SHA if ALLOW_RSA_NULL_SHA256=1)
317}; 319};
318 320
@@ -412,8 +414,8 @@ struct tls_handshake_data {
412 int key_type_chosen; 414 int key_type_chosen;
413 psRsaKey_t rsa_priv_key; 415 psRsaKey_t rsa_priv_key;
414 416
415 ///* For ECDHE: server's ephemeral EC private key */ 417 /* For ECDHE: server's ephemeral EC private key */
416 //uint8_t ecc_priv_key32[32]; 418 uint8_t ecc_priv_key32[32];
417#endif 419#endif
418}; 420};
419enum { 421enum {
@@ -430,7 +432,6 @@ static int is_minor_version_valid(tls_state_t *tls, uint8_t minor_ver)
430{ 432{
431#if ENABLE_SSL_SERVER // || ENABLE_FEATURE_HTTPD_SSL 433#if ENABLE_SSL_SERVER // || ENABLE_FEATURE_HTTPD_SSL
432 if (tls->expecting_first_packet == 1) { 434 if (tls->expecting_first_packet == 1) {
433 tls->expecting_first_packet = 0;
434 /* First packet: accept TLS 1.0 (3.1) through TLS 1.3 (3.4) 435 /* First packet: accept TLS 1.0 (3.1) through TLS 1.3 (3.4)
435 * for compatibility with clients using other record versions */ 436 * for compatibility with clients using other record versions */
436 return (minor_ver > 0 && minor_ver <= 4); 437 return (minor_ver > 0 && minor_ver <= 4);
@@ -1836,7 +1837,7 @@ static void process_server_key(tls_state_t *tls, int len)
1836 switch (t32) { 1837 switch (t32) {
1837 case _0x03001d20: //curve_x25519 1838 case _0x03001d20: //curve_x25519
1838 dbg("got x25519 eccPubKey"); 1839 dbg("got x25519 eccPubKey");
1839 tls->flags |= GOT_EC_CURVE_X25519; 1840 tls->flags |= USE_EC_CURVE_X25519;
1840 memcpy(tls->hsd->ecc_pub_key32, keybuf, 32); 1841 memcpy(tls->hsd->ecc_pub_key32, keybuf, 32);
1841 break; 1842 break;
1842 case _0x03001741: //curve_secp256r1 (aka P256) 1843 case _0x03001741: //curve_secp256r1 (aka P256)
@@ -2001,7 +2002,7 @@ static void send_client_key_exchange(tls_state_t *tls)
2001 if (!(tls->flags & GOT_EC_KEY)) 2002 if (!(tls->flags & GOT_EC_KEY))
2002 bb_simple_error_msg_and_die("server did not provide EC key"); 2003 bb_simple_error_msg_and_die("server did not provide EC key");
2003 2004
2004 if (tls->flags & GOT_EC_CURVE_X25519) { 2005 if (tls->flags & USE_EC_CURVE_X25519) {
2005 /* ECDHE, curve x25519 */ 2006 /* ECDHE, curve x25519 */
2006 dbg("computing x25519_premaster"); 2007 dbg("computing x25519_premaster");
2007 curve_x25519_compute_pubkey_and_premaster( 2008 curve_x25519_compute_pubkey_and_premaster(
@@ -2431,7 +2432,8 @@ static void get_client_hello(tls_state_t *tls)
2431 unsigned i, j; 2432 unsigned i, j;
2432 struct client_hello *hp; 2433 struct client_hello *hp;
2433 uint8_t *p; 2434 uint8_t *p;
2434 unsigned cipher_list_len; 2435 int cipher_list_len;
2436 int extensions_len;
2435 int len; 2437 int len;
2436 2438
2437 len = tls_xread_handshake_block(tls, sizeof(*hp)); 2439 len = tls_xread_handshake_block(tls, sizeof(*hp));
@@ -2439,9 +2441,9 @@ static void get_client_hello(tls_state_t *tls)
2439 hp = (void*)(tls->inbuf + RECHDR_LEN); 2441 hp = (void*)(tls->inbuf + RECHDR_LEN);
2440 if (hp->type != HANDSHAKE_CLIENT_HELLO 2442 if (hp->type != HANDSHAKE_CLIENT_HELLO
2441 || hp->len24_hi != 0 2443 || hp->len24_hi != 0
2442 /* hp->len24_mid,lo checked later */ 2444 || len != ((hp->len24_mid << 8) | hp->len24_lo) + 4
2443 || hp->proto_maj != TLS_MAJ 2445 || hp->proto_maj != TLS_MAJ
2444///? || hp->proto_min != TLS_MIN 2446 || !is_minor_version_valid(tls, hp->proto_min)
2445 ) { 2447 ) {
2446 bad_record_die(tls, "'client hello'", len); 2448 bad_record_die(tls, "'client hello'", len);
2447 } 2449 }
@@ -2453,13 +2455,13 @@ static void get_client_hello(tls_state_t *tls)
2453 /* Parse cipher suites to select one we support */ 2455 /* Parse cipher suites to select one we support */
2454 p = (uint8_t*)(hp + 1); 2456 p = (uint8_t*)(hp + 1);
2455 2457
2456 /* Skip session ID */ 2458 /* Skip session ID and handshake header */
2457 len -= RECHDR_LEN + sizeof(*hp); 2459 len -= sizeof(*hp);
2458 if (len < hp->session_id_len) {
2459 bb_simple_error_msg_and_die("malformed ClientHello");
2460 }
2461 p += hp->session_id_len; 2460 p += hp->session_id_len;
2462 len -= hp->session_id_len; 2461 len -= hp->session_id_len;
2462 if (len < 0) {
2463 bb_simple_error_msg_and_die("malformed ClientHello");
2464 }
2463 2465
2464 /* Parse cipher suite list */ 2466 /* Parse cipher suite list */
2465 if (len < 2) { 2467 if (len < 2) {
@@ -2478,16 +2480,6 @@ static void get_client_hello(tls_state_t *tls)
2478 const uint8_t *our_cipher = &supported_ciphers[i]; 2480 const uint8_t *our_cipher = &supported_ciphers[i];
2479 int key_type; 2481 int key_type;
2480 2482
2481 /* Skip all ECDHE ciphers (0xC0xx) - we don't support server-side ephemeral
2482 * EC key generation yet. ECDHE_RSA uses RSA certificates (which we have)
2483 * but still requires generating ephemeral EC keys for the key exchange.
2484 * We only support plain RSA key exchange (0x00xx) on the server side.
2485 */
2486 if (our_cipher[0] == 0xC0) {
2487 //TODO: implement server-side ECDHE
2488 continue;
2489 }
2490
2491 /* Determine required key type for this cipher */ 2483 /* Determine required key type for this cipher */
2492 key_type = is_cipher_ECDSA(our_cipher); 2484 key_type = is_cipher_ECDSA(our_cipher);
2493 if (key_type == KEY_ECDSA) { 2485 if (key_type == KEY_ECDSA) {
@@ -2510,12 +2502,78 @@ static void get_client_hello(tls_state_t *tls)
2510 set_cipher_parameters(tls, our_cipher); 2502 set_cipher_parameters(tls, our_cipher);
2511 dbg("Selected cipher: %04x", tls->cipher_id); 2503 dbg("Selected cipher: %04x", tls->cipher_id);
2512 tls->hsd->key_type_chosen = key_type; 2504 tls->hsd->key_type_chosen = key_type;
2513 return; 2505 goto cipher_selected;
2514 } 2506 }
2515 } 2507 }
2516 /* try our next cipherid */ 2508 /* try our next cipherid */
2517 } 2509 }
2518 bb_simple_error_msg_and_die("no common cipher suites"); 2510 bb_simple_error_msg_and_die("no common cipher suites");
2511
2512 cipher_selected:
2513 /* Skip past cipher list */
2514 p += cipher_list_len;
2515 len -= cipher_list_len;
2516
2517 /* Skip compression methods */
2518 len -= 1 + p[0];
2519 p += 1 + p[0];
2520
2521 /* Parse extensions if present */
2522 if (len < 2) {
2523 dbg("No extensions");
2524 return; /* no extensions */
2525 }
2526 extensions_len = (p[0] << 8) | p[1];
2527 p += 2;
2528 len -= 2;
2529 dbg("Extensions total length: %u, remaining len: %d", extensions_len, len);
2530
2531 if (len < extensions_len) {
2532 dbg("Malformed extensions length (len %d < extensions_len %u)", len, extensions_len);
2533 return; /* malformed extensions, ignore */
2534 }
2535
2536 /* Look for supported_groups extension (type 0x000a) */
2537 while (extensions_len >= 4) {
2538 unsigned ext_type = (p[0] << 8) | p[1];
2539 int ext_len = (p[2] << 8) | p[3];
2540 dbg("Extension type: 0x%04x, len: %u", ext_type, ext_len);
2541 p += 4;
2542 extensions_len -= 4;
2543
2544 if (extensions_len < ext_len) {
2545 dbg("Extension length overflow");
2546 return; /* malformed */
2547 }
2548
2549 if (ext_type == 0x000a) { /* supported_groups */
2550 /* Parse named curve list */
2551 int curve_list_len = (p[0] << 8) | p[1];
2552 dbg("Found supported_groups extension");
2553 p += 2;
2554 ext_len -= 2;
2555 if (ext_len != curve_list_len)
2556 return; /* malformed */
2557 while (1) {
2558 unsigned curve;
2559 ext_len -= 2; /* skip (presumably existing) curve id */
2560 if (ext_len < 0)
2561 break; /* oops, it didn't */
2562 curve = (p[0] << 8) | p[1];
2563 if (curve == 0x001d) /* x25519 */
2564 tls->flags |= USE_EC_CURVE_X25519;
2565// if (curve == 0x0017) /* secp256r1 (P256) */
2566// /* We'll try P256 as fallback without checking client support */
2567 p += 2;
2568 }
2569 dbg("Client supports:%s",
2570 (tls->flags & USE_EC_CURVE_X25519) ? " x25519" : " P256(assumed)");
2571 return; /* found what we need */
2572 }
2573
2574 p += ext_len;
2575 extensions_len -= ext_len;
2576 }
2519} 2577}
2520 2578
2521static void send_server_hello(tls_state_t *tls) 2579static void send_server_hello(tls_state_t *tls)
@@ -2580,6 +2638,67 @@ static void send_server_certificate(tls_state_t *tls)
2580 xwrite_and_update_handshake_hash(tls, sz); 2638 xwrite_and_update_handshake_hash(tls, sz);
2581} 2639}
2582 2640
2641static void send_server_key_exchange(tls_state_t *tls)
2642{
2643 struct server_key_exchange {
2644 uint8_t type;
2645 uint8_t len24_hi, len24_mid, len24_lo;
2646 uint8_t curve_type; /* 3 = named curve */
2647 uint8_t curve_id_hi, curve_id_lo;
2648 uint8_t pubkey_len;
2649 uint8_t pubkey[1 + 2 * 32]; /* for P256: 04 + x(32) + y(32) */
2650 };
2651 struct server_key_exchange *record;
2652 int pubkey_len;
2653 int total_len;
2654
2655 record = tls_get_zeroed_outbuf(tls, sizeof(*record));
2656
2657 record->type = HANDSHAKE_SERVER_KEY_EXCHANGE;
2658 record->curve_type = 3; /* named curve */
2659
2660 /* Determine which curve to use based on client's supported_groups extension.
2661 * Prefer x25519 (faster) if client supports it, otherwise use P256.
2662 * If client didn't send supported_groups, default to P256 (most widely supported).
2663 */
2664 if (tls->flags & USE_EC_CURVE_X25519) { /* Use x25519 */
2665 //record->curve_id_hi = 0x00; /* already zero from tls_get_zeroed_outbuf() */
2666 record->curve_id_lo = 0x1d; /* x25519 */
2667
2668 /* Generate ephemeral keypair directly into output buffer */
2669 curve_x25519_generate_keypair(tls->hsd->ecc_priv_key32, record->pubkey);
2670
2671 pubkey_len = 32;
2672 dbg("Using x25519 for ECDHE");
2673 } else { /* Use P256 (default or if client advertised it) */
2674 //record->curve_id_hi = 0x00; /* already zero from tls_get_zeroed_outbuf() */
2675 record->curve_id_lo = 0x17; /* secp256r1 (P256) */
2676
2677 /* Generate ephemeral keypair directly into output buffer */
2678 record->pubkey[0] = 0x04; /* uncompressed point */
2679 curve_P256_generate_keypair(tls->hsd->ecc_priv_key32, record->pubkey + 1);
2680
2681 pubkey_len = 1 + 2 * 32;
2682 /* P256 is the default, no need to set USE_EC_CURVE_X25519 flag */
2683 dbg("Using P256 for ECDHE");
2684 }
2685
2686 record->pubkey_len = pubkey_len;
2687
2688 /* Calculate total length: curve_type(1) + curve_id(2) + pubkey_len(1) + pubkey */
2689 total_len = 4 + pubkey_len;
2690
2691 //record->len24_hi = 0; /* already zero from tls_get_zeroed_outbuf() */
2692 record->len24_mid = total_len >> 8;
2693 record->len24_lo = total_len & 0xff;
2694
2695 /* Total message length */
2696 total_len += 4; /* type + len24 */
2697
2698 dbg(">> SERVER_KEY_EXCHANGE");
2699 xwrite_and_update_handshake_hash(tls, total_len);
2700}
2701
2583static void send_server_hello_done(tls_state_t *tls) 2702static void send_server_hello_done(tls_state_t *tls)
2584{ 2703{
2585 struct server_hello_done { 2704 struct server_hello_done {
@@ -2600,15 +2719,14 @@ static void get_client_key_exchange(tls_state_t *tls)
2600 struct client_key_exchange { 2719 struct client_key_exchange {
2601 uint8_t type; 2720 uint8_t type;
2602 uint8_t len24_hi, len24_mid, len24_lo; 2721 uint8_t len24_hi, len24_mid, len24_lo;
2603 uint8_t enckey_len_hi, enckey_len_lo; /* RSA encrypted premaster length */ 2722 uint8_t key[1]; /* Variable length: encrypted premaster (RSA) or EC point (ECDHE) */
2604 /* followed by RSA encrypted premaster secret */
2605 }; 2723 };
2606 struct client_key_exchange *record; 2724 struct client_key_exchange *record;
2607 uint8_t premaster[RSA_PREMASTER_SIZE]; 2725 uint8_t premaster[RSA_PREMASTER_SIZE > EC_CURVE_KEYSIZE ? RSA_PREMASTER_SIZE : EC_CURVE_KEYSIZE];
2608 int len, enckey_len; 2726 int len, premaster_size;
2609 uint8_t *encrypted_premaster; 2727 uint8_t *key_data;
2610 2728
2611 len = tls_xread_handshake_block(tls, 64); 2729 len = tls_xread_handshake_block(tls, sizeof(*record));
2612 record = (void*)(tls->inbuf + RECHDR_LEN); 2730 record = (void*)(tls->inbuf + RECHDR_LEN);
2613 2731
2614 if (record->type != HANDSHAKE_CLIENT_KEY_EXCHANGE) { 2732 if (record->type != HANDSHAKE_CLIENT_KEY_EXCHANGE) {
@@ -2616,40 +2734,85 @@ static void get_client_key_exchange(tls_state_t *tls)
2616 } 2734 }
2617 dbg("<< CLIENT_KEY_EXCHANGE"); 2735 dbg("<< CLIENT_KEY_EXCHANGE");
2618 2736
2619 /* Get the length of the encrypted premaster secret */ 2737 key_data = record->key;
2620 enckey_len = (record->enckey_len_hi << 8) | record->enckey_len_lo;
2621 dbg("enckey_len:%d len:%d", enckey_len, len);
2622 2738
2623 if (enckey_len < 128 || enckey_len > 512) { 2739 if (!(tls->flags & NEED_EC_KEY)) {
2624 bb_simple_error_msg_and_die("bad encrypted premaster length"); 2740 /* RSA key exchange */
2625 } 2741 int enckey_len;
2626 2742
2627 encrypted_premaster = (uint8_t*)(record + 1); 2743 /* Get the length of the encrypted premaster secret */
2744 enckey_len = (key_data[0] << 8) | key_data[1];
2745 key_data += 2;
2746 dbg("enckey_len:%d len:%d", enckey_len, len);
2628 2747
2629 /* Decrypt the premaster secret using server's private RSA key */ 2748 if (enckey_len < 128 || enckey_len > 512) {
2630 { 2749 bb_simple_error_msg_and_die("bad encrypted premaster length");
2631 int32 ret; 2750 }
2632 uint32 premaster_len; 2751
2633 psRsaKey_t *key = &tls->hsd->rsa_priv_key; 2752 /* Decrypt the premaster secret using server's private RSA key */
2753 {
2754 int32 ret;
2755 uint32 plen;
2756 psRsaKey_t *key = &tls->hsd->rsa_priv_key;
2757
2758 plen = RSA_PREMASTER_SIZE;
2759 ret = psRsaDecryptPriv(NULL, key,
2760 key_data, enckey_len,
2761 premaster, plen, NULL);
2634 2762
2635 premaster_len = RSA_PREMASTER_SIZE; 2763 if (ret != RSA_PREMASTER_SIZE) {
2636 ret = psRsaDecryptPriv(NULL, key, 2764 bb_error_msg_and_die("RSA decrypt failed or wrong premaster size: %d", ret);
2637 encrypted_premaster, enckey_len, 2765 }
2638 premaster, premaster_len, NULL); 2766
2767 dbg("Decrypted premaster secret (%d bytes)", ret);
2639 2768
2640 if (ret != RSA_PREMASTER_SIZE) { 2769 /* Verify premaster format: should start with version 0x03 0x03 (TLS 1.2) */
2641 bb_error_msg_and_die("RSA decrypt failed or wrong premaster size: %d", ret); 2770 if (premaster[0] != 0x03 || premaster[1] != 0x03) {
2771 bb_simple_error_msg_and_die("bad premaster secret version");
2772 }
2642 } 2773 }
2774 premaster_size = RSA_PREMASTER_SIZE;
2775 } else {
2776 /* ECDHE key exchange */
2777 int pubkey_len;
2778 uint8_t *client_pubkey;
2779
2780 /* Get client's ephemeral public key length */
2781 pubkey_len = *key_data++;
2782 client_pubkey = key_data;
2643 2783
2644 dbg("Decrypted premaster secret (%d bytes)", ret); 2784 dbg("ECDHE: client pubkey_len:%d", pubkey_len);
2645 2785
2646 /* Verify premaster format: should start with version 0x03 0x03 (TLS 1.2) */ 2786 /* Compute shared secret using client's public key and our private key */
2647 if (premaster[0] != 0x03 || premaster[1] != 0x03) { 2787 if (tls->flags & USE_EC_CURVE_X25519) {
2648 bb_simple_error_msg_and_die("bad premaster secret version"); 2788 /* x25519 */
2789 if (pubkey_len != CURVE25519_KEYSIZE) {
2790 bb_simple_error_msg_and_die("bad x25519 public key length");
2791 }
2792 curve_x25519_compute_premaster(
2793 tls->hsd->ecc_priv_key32, client_pubkey,
2794 premaster
2795 );
2796 premaster_size = CURVE25519_KEYSIZE;
2797 } else {
2798 /* P256 */
2799 if (pubkey_len != 1 + 2 * P256_KEYSIZE) {
2800 bb_simple_error_msg_and_die("bad P256 public key length");
2801 }
2802 if (*client_pubkey++ != 0x04) {
2803 bb_simple_error_msg_and_die("compressed EC points not supported");
2804 }
2805 curve_P256_compute_premaster(
2806 tls->hsd->ecc_priv_key32, client_pubkey,
2807 premaster
2808 );
2809 premaster_size = P256_KEYSIZE;
2649 } 2810 }
2811
2812 dbg("Computed ECDHE premaster secret (%d bytes)", premaster_size);
2650 } 2813 }
2651 2814
2652 derive_master_secret_and_keys(tls, premaster, RSA_PREMASTER_SIZE); 2815 derive_master_secret_and_keys(tls, premaster, premaster_size);
2653 2816
2654 /* Server decrypts with client_write_key, encrypts with server_write_key */ 2817 /* Server decrypts with client_write_key, encrypts with server_write_key */
2655 aes_setkey(&tls->aes_decrypt, tls->client_write_key, tls->key_size); 2818 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,
2932 load_pem_key_cert_pairs(tls, pem_filename); 3095 load_pem_key_cert_pairs(tls, pem_filename);
2933 3096
2934 sha256_begin(&tls->hsd->handshake_hash_ctx); 3097 sha256_begin(&tls->hsd->handshake_hash_ctx);
2935 tls->expecting_first_packet = 1;
2936 3098
2937 /* Server handshake sequence (RSA mode): 3099 /* Server handshake sequence:
2938 * 1. Receive ClientHello 3100 * 1. Receive ClientHello
2939 * 2. Send ServerHello 3101 * 2. Send ServerHello
2940 * 3. Send Certificate 3102 * 3. Send Certificate
@@ -2947,9 +3109,13 @@ void FAST_FUNC tls_handshake_as_server(tls_state_t *tls,
2947 * 10. Send ChangeCipherSpec 3109 * 10. Send ChangeCipherSpec
2948 * 11. Send Finished (encrypted) 3110 * 11. Send Finished (encrypted)
2949 */ 3111 */
3112 tls->expecting_first_packet = 1;
2950 get_client_hello(tls); 3113 get_client_hello(tls);
3114 tls->expecting_first_packet = 0;
2951 send_server_hello(tls); 3115 send_server_hello(tls);
2952 send_server_certificate(tls); 3116 send_server_certificate(tls);
3117 if (tls->flags & NEED_EC_KEY)
3118 send_server_key_exchange(tls);
2953 send_server_hello_done(tls); 3119 send_server_hello_done(tls);
2954 3120
2955 get_client_key_exchange(tls); 3121 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;
108#define P256_KEYSIZE 32 108#define P256_KEYSIZE 32
109#define CURVE25519_KEYSIZE 32 109#define CURVE25519_KEYSIZE 32
110 110
111/* Separate keypair generation and premaster computation functions */
112void curve_x25519_generate_keypair(
113 uint8_t *privkey32, uint8_t *pubkey32) FAST_FUNC;
114void curve_x25519_compute_premaster(
115 const uint8_t *privkey32, const uint8_t *peerkey32,
116 uint8_t *premaster32) FAST_FUNC;
117
118#if ENABLE_SSL_SERVER
119void curve_P256_generate_keypair(
120 uint8_t *privkey32, uint8_t *pubkey2x32) FAST_FUNC;
121void curve_P256_compute_premaster(
122 const uint8_t *privkey32, const uint8_t *peerkey2x32,
123 uint8_t *premaster32) FAST_FUNC;
124#endif
125
126/* Combined operations (for client-side use) */
111void curve_x25519_compute_pubkey_and_premaster( 127void curve_x25519_compute_pubkey_and_premaster(
112 uint8_t *pubkey32, uint8_t *premaster32, 128 uint8_t *pubkey32, uint8_t *premaster32,
113 const uint8_t *peerkey32) FAST_FUNC; 129 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)
607 fe_normalize(result); 607 fe_normalize(result);
608} 608}
609 609
610/* interface to bbox's TLS code: */ 610/* interface to bbox's TLS code:
611 *
612 * Wire format for elliptic curve points differs between curves:
613 * - P256: point is (x,y) where each coordinate is a 256-bit (32-byte) big-endian integer.
614 * Wire format: 64 bytes total (plus 0x04 prefix byte for "uncompressed point").
615 * - x25519: point is a single 256-bit (32-byte) little-endian integer.
616 * Wire format: 32 bytes.
617 *
618 * The interface functions below accept and generate EC points in their respective
619 * wire formats. Internal calculations may use different representations, but all
620 * conversions are handled internally within these functions.
621 * (Note: x25519 implementation in this file uses wire format internally as well)
622 */
623
624/* Generate x25519 keypair: random private key + corresponding public key */
625void FAST_FUNC curve_x25519_generate_keypair(uint8_t *privkey32, uint8_t *pubkey32)
626{
627 /* Generate random private key, see RFC 7748 */
628 tls_get_random(privkey32, CURVE25519_KEYSIZE);
629 privkey32[0] &= 0xf8;
630 privkey32[CURVE25519_KEYSIZE-1] = ((privkey32[CURVE25519_KEYSIZE-1] & 0x7f) | 0x40);
631
632 /* Compute public key from private key */
633 curve25519(pubkey32, privkey32, NULL /* "use base point of x25519" */);
634}
635
636/* Compute shared secret (premaster) from our private key and peer's public key */
637void FAST_FUNC curve_x25519_compute_premaster(
638 const uint8_t *privkey32, const uint8_t *peerkey32,
639 uint8_t *premaster32)
640{
641 curve25519(premaster32, privkey32, peerkey32);
642}
611 643
644/* Combined operation: generate keypair and compute premaster in one call */
612void FAST_FUNC curve_x25519_compute_pubkey_and_premaster( 645void FAST_FUNC curve_x25519_compute_pubkey_and_premaster(
613 uint8_t *pubkey, uint8_t *premaster, 646 uint8_t *pubkey, uint8_t *premaster,
614 const uint8_t *peerkey32) 647 const uint8_t *peerkey32)
615{ 648{
616 uint8_t privkey[CURVE25519_KEYSIZE]; //[32] 649 uint8_t privkey[CURVE25519_KEYSIZE]; //[32]
617 650
618 /* Generate random private key, see RFC 7748 */ 651 curve_x25519_generate_keypair(privkey, pubkey);
619 tls_get_random(privkey, sizeof(privkey)); 652 curve_x25519_compute_premaster(privkey, peerkey32, premaster);
620 privkey[0] &= 0xf8;
621 privkey[CURVE25519_KEYSIZE-1] = ((privkey[CURVE25519_KEYSIZE-1] & 0x7f) | 0x40);
622
623 /* Compute public key */
624 curve25519(pubkey, privkey, NULL /* "use base point of x25519" */);
625
626 /* Compute premaster using peer's public key */
627 curve25519(premaster, privkey, peerkey32);
628} 653}
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)
1514 memset(point, 0, sizeof(point)); //paranoia 1514 memset(point, 0, sizeof(point)); //paranoia
1515} 1515}
1516 1516
1517/* interface to bbox's TLS code:
1518 *
1519 * Wire format for elliptic curve points differs between curves:
1520 * - P256: point is (x,y) where each coordinate is a 256-bit (32-byte) big-endian integer.
1521 * Wire format: 64 bytes total (plus 0x04 prefix byte for "uncompressed point").
1522 * - x25519: point is a single 256-bit (32-byte) little-endian integer.
1523 * Wire format: 32 bytes.
1524 *
1525 * The interface functions below accept and generate EC points in their respective
1526 * wire formats. Internal calculations may use different representations, but all
1527 * conversions are handled internally within these functions.
1528 */
1529
1530#if ENABLE_SSL_SERVER
1531/* Generate P256 keypair: random private key + corresponding public key */
1532void FAST_FUNC curve_P256_generate_keypair(uint8_t *privkey32, uint8_t *pubkey2x32)
1533{
1534 sp_digit privkey_sp[8];
1535
1536 /* Generate keypair using internal representation */
1537 sp_ecc_make_key_256(privkey_sp, pubkey2x32);
1538
1539 /* Convert private key to binary format for storage */
1540 sp_256_to_bin_8(privkey_sp, privkey32);
1541
1542 memset(privkey_sp, 0, sizeof(privkey_sp)); //paranoia
1543}
1544
1545/* Compute shared secret (premaster) from our private key and peer's public key */
1546void FAST_FUNC curve_P256_compute_premaster(
1547 const uint8_t *privkey32, const uint8_t *peerkey2x32,
1548 uint8_t *premaster32)
1549{
1550 sp_digit privkey_sp[8];
1551
1552 /* Convert binary private key to internal representation */
1553 sp_256_from_bin_8(privkey_sp, privkey32);
1554
1555 /* Compute shared secret */
1556 sp_ecc_secret_gen_256(privkey_sp, peerkey2x32, premaster32);
1557
1558 memset(privkey_sp, 0, sizeof(privkey_sp)); //paranoia
1559}
1560#endif
1561
1562/* Combined operation: generate keypair and compute premaster in one call */
1517void FAST_FUNC curve_P256_compute_pubkey_and_premaster( 1563void FAST_FUNC curve_P256_compute_pubkey_and_premaster(
1518 uint8_t *pubkey2x32, uint8_t *premaster32, 1564 uint8_t *pubkey2x32, uint8_t *premaster32,
1519 const uint8_t *peerkey2x32) 1565 const uint8_t *peerkey2x32)