[git commit] tls: server: fix incorrect key_block assignments - now works against openssl s_client

Denys Vlasenko vda.linux at googlemail.com
Sun Feb 15 14:26:31 UTC 2026


commit: https://git.busybox.net/busybox/commit/?id=22b66febbd9c41be3841cb565ad14215b8ae74c7
branch: https://git.busybox.net/busybox/log/?h=master

function                                             old     new   delta
privRsaEncryptSignedElement                            -     236    +236
tls_handshake_as_server                             2033    2264    +231
.rodata                                           108079  108301    +222
initialize_aes_keys                                    -      77     +77
xwrite_encrypted                                     507     506      -1
tls_handshake                                       1519    1500     -19
derive_master_secret_and_keys                        154     123     -31
------------------------------------------------------------------------------
(add/remove: 2/0 grow/shrink: 2/3 up/down: 766/-51)           Total: 715 bytes

Totoal growth compared to code before TLS server code:

function                                             old     new   delta
tls_handshake_as_server                                -    2264   +2264
.rodata                                           107074  108301   +1227
psRsaCrypt                                             -     577    +577
load_rsa_priv_key                                      -     282    +282
ssl_server_main                                        -     279    +279
privRsaEncryptSignedElement                            -     236    +236
ssl_client_main                                      137     363    +226
psRsaDecryptPriv                                       -     171    +171
set_cipher_parameters                                  -     161    +161
derive_master_secret_and_keys                          -     123    +123
packed_usage                                       36034   36146    +112
sp_ecc_make_key_256                                    -     103    +103
send_finished                                          -      94     +94
get_change_cipher_spec                                 -      88     +88
initialize_aes_keys                                    -      77     +77
static.BLOCK_NAMES                                     -      70     +70
curve_P256_compute_premaster                           -      65     +65
der_binary_to_pstm                                     -      50     +50
curve_x25519_generate_keypair                          -      44     +44
get_finished                                           -      42     +42
get_outbuf_fill_handshake_record                       -      37     +37
client_hello_ciphers                                   -      32     +32
curve_P256_generate_keypair                            -      27     +27
sp_256_from_bin_8                                      -      26     +26
tls_xread_record                                     681     704     +23
curve_x25519_compute_premaster                         -      15     +15
applet_names                                        2870    2881     +11
applet_main                                         1652    1656      +4
xwrite_encrypted                                     507     506      -1
xwrite_and_update_handshake_hash                      76      59     -17
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
psRsaEncryptPub                                      395     199    -196
tls_handshake                                       2069    1500    -569
------------------------------------------------------------------------------
(add/remove: 23/0 grow/shrink: 6/7 up/down: 6466/-944)       Total: 5522 bytes

Signed-off-by: Denys Vlasenko <vda.linux at googlemail.com>
---
 include/libbb.h      |  23 +++---
 networking/tls.c     | 217 ++++++++++++++++++++++++++++++++-------------------
 networking/tls.h     |   2 +
 networking/tls_rsa.c |  84 ++++++++++++++++++++
 networking/tls_rsa.h |   6 ++
 5 files changed, 241 insertions(+), 91 deletions(-)

diff --git a/include/libbb.h b/include/libbb.h
index 5f4ba6b0f..76d79da23 100644
--- a/include/libbb.h
+++ b/include/libbb.h
@@ -899,17 +899,18 @@ typedef struct tls_state {
 	/*uint64_t read_seq64_be;*/
 	uint64_t write_seq64_be;
 
-	/*uint8_t *server_write_MAC_key;*/
-	uint8_t *client_write_key;
-	uint8_t *server_write_key;
-	uint8_t *client_write_IV;
-	uint8_t *server_write_IV;
-	uint8_t client_write_MAC_key[TLS_MAX_MAC_SIZE];
-	uint8_t server_write_MAC_k__[TLS_MAX_MAC_SIZE];
-	uint8_t client_write_k__[TLS_MAX_KEY_SIZE];
-	uint8_t server_write_k__[TLS_MAX_KEY_SIZE];
-	uint8_t client_write_I_[TLS_MAX_IV_SIZE];
-	uint8_t server_write_I_[TLS_MAX_IV_SIZE];
+	uint8_t *our_write_MAC_key;
+	uint8_t *peer_write_MAC_key;
+	uint8_t *our_write_key;
+	uint8_t *peer_write_key;
+	uint8_t *our_write_IV;
+	uint8_t *peer_write_IV;
+	uint8_t key_block[TLS_MAX_MAC_SIZE];
+	uint8_t key_block2[TLS_MAX_MAC_SIZE];
+	uint8_t key_block3[TLS_MAX_KEY_SIZE];
+	uint8_t key_block4[TLS_MAX_KEY_SIZE];
+	uint8_t key_block5[TLS_MAX_IV_SIZE];
+	uint8_t key_block6[TLS_MAX_IV_SIZE];
 
 	struct tls_aes aes_encrypt;
 	struct tls_aes aes_decrypt;
diff --git a/networking/tls.c b/networking/tls.c
index cde92ad1e..c135f9e4d 100644
--- a/networking/tls.c
+++ b/networking/tls.c
@@ -318,6 +318,7 @@ enum {
 	ENCRYPTION_AESGCM      = 1 << 5, // else AES-SHA (or NULL-SHA if ALLOW_RSA_NULL_SHA256=1)
 };
 
+#if ENABLE_SSL_SERVER // || ENABLE_FEATURE_HTTPD_SSL
 /* Note: return value matches KEY_RSA (0) / KEY_ECDSA (1) enum values */
 static int is_cipher_ECDSA(const uint8_t *cipherid)
 {
@@ -330,6 +331,7 @@ static int is_cipher_ECDSA(const uint8_t *cipherid)
 		|| cipher_lo == 0x23 || cipher_lo == 0x2B
 	);
 }
+#endif
 
 /* Set cipher parameters based on selected cipher_id */
 static void set_cipher_parameters(tls_state_t *tls, const uint8_t *cipherid)
@@ -406,6 +408,7 @@ struct tls_handshake_data {
 	//uint8_t saved_client_hello[1];
 
 #if ENABLE_SSL_SERVER // || ENABLE_FEATURE_HTTPD_SSL
+	smallint reneg_info_requested;
 	/* Server certificate and key data */
 	char *keys[2];
 	char *certs[2];
@@ -428,18 +431,20 @@ static unsigned get24be(const uint8_t *p)
 	return 0x100*(0x100*p[0] + p[1]) + p[2];
 }
 
+#if ENABLE_SSL_SERVER // || ENABLE_FEATURE_HTTPD_SSL
 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) {
 		/* 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);
 	}
 	/* Subsequent packets: must match negotiated version exactly */
-#endif
 	return minor_ver == TLS_MIN;
 }
+#else
+#define is_minor_version_valid(tls, minor_ver) ((minor_ver) == TLS_MIN)
+#endif
 
 #if TLS_DEBUG
 /* Nondestructively see the current hash value */
@@ -711,7 +716,7 @@ static void xwrite_encrypted_and_hmac_signed(tls_state_t *tls, unsigned size, un
 
 	/* Calculate MAC signature */
 	hmac_blocks(tls, buf + size, /* result */
-		tls->client_write_MAC_key, TLS_MAC_SIZE(tls),
+		tls->our_write_MAC_key, TLS_MAC_SIZE(tls),
 		&tls->write_seq64_be, sizeof(tls->write_seq64_be),
 		xhdr, RECHDR_LEN,
 		buf, size,
@@ -883,7 +888,7 @@ static void xwrite_encrypted_aesgcm(tls_state_t *tls, unsigned size, unsigned ty
 	/* set aad[12], and clear aad[13..15] */
 	COUNTER(aad) = SWAP_LE32(size & 0xff);
 
-	memcpy(nonce, tls->client_write_IV, 4);
+	memcpy(nonce, tls->our_write_IV, 4);
 	t64 = tls->write_seq64_be;
 	move_to_unaligned64(nonce + 4, t64);
 	move_to_unaligned64(aad,       t64);
@@ -1046,7 +1051,7 @@ static void tls_aesgcm_decrypt(tls_state_t *tls, uint8_t *buf, int size)
 	///* set aad[12], and clear aad[13..15] */
 	//COUNTER(aad) = SWAP_LE32(size & 0xff);
 
-	memcpy(nonce,     tls->server_write_IV, 4);
+	memcpy(nonce,     tls->peer_write_IV, 4);
 	memcpy(nonce + 4, buf, 8);
 
 	cnt = 1;
@@ -1930,30 +1935,22 @@ static void derive_master_secret_and_keys(tls_state_t *tls, uint8_t *premaster,
 	memcpy(&tmp64[32], &tls->hsd->client_and_server_rand32[0] , 32);
 
 	prf_hmac_sha256(/*tls,*/
-		tls->client_write_MAC_key, 2 * (tls->MAC_size + tls->key_size + tls->IV_size),
-		// also fills:
-		// server_write_MAC_key[]
-		// client_write_key[]
-		// server_write_key[]
-		// client_write_IV[]
-		// server_write_IV[]
+		tls->key_block, 2 * (tls->MAC_size + tls->key_size + tls->IV_size),
 		tls->hsd->master_secret, sizeof(tls->hsd->master_secret),
 		"key expansion",
 		tmp64, 64
 	);
-	tls->client_write_key = tls->client_write_MAC_key + (2 * tls->MAC_size);
-	tls->server_write_key = tls->client_write_key + tls->key_size;
-	tls->client_write_IV = tls->server_write_key + tls->key_size;
-	tls->server_write_IV = tls->client_write_IV + tls->IV_size;
-	dump_hex("client_write_MAC_key:%s",
-		tls->client_write_MAC_key, tls->MAC_size
-	);
-	dump_hex("client_write_key:%s",
-		tls->client_write_key, tls->key_size
-	);
-	dump_hex("client_write_IV:%s",
-		tls->client_write_IV, tls->IV_size
-	);
+}
+
+static void initialize_aes_keys(tls_state_t *tls)
+{
+	uint8_t iv[AES_BLOCK_SIZE];
+	aes_setkey(&tls->aes_decrypt, tls->peer_write_key, tls->key_size);
+	aes_setkey(&tls->aes_encrypt, tls->our_write_key, tls->key_size);
+	if (1) { //if AESGCM
+		memset(iv, 0, AES_BLOCK_SIZE);
+		aes_encrypt_one_block(&tls->aes_encrypt, iv, tls->H);
+	}
 }
 
 static void send_client_key_exchange(tls_state_t *tls)
@@ -2038,14 +2035,21 @@ static void send_client_key_exchange(tls_state_t *tls)
 	xwrite_and_update_handshake_hash(tls, len);
 
 	derive_master_secret_and_keys(tls, premaster, premaster_size);
-
-	aes_setkey(&tls->aes_decrypt, tls->server_write_key, tls->key_size);
-	aes_setkey(&tls->aes_encrypt, tls->client_write_key, tls->key_size);
-	{
-		uint8_t iv[AES_BLOCK_SIZE];
-		memset(iv, 0, AES_BLOCK_SIZE);
-		aes_encrypt_one_block(&tls->aes_encrypt, iv, tls->H);
-	}
+	// The key_block is partitioned as follows:
+	tls->our_write_MAC_key  = tls->key_block;                          // client_write_MAC_key[]
+	tls->peer_write_MAC_key = tls->key_block          + tls->MAC_size; // server_write_MAC_key[]
+	tls->our_write_key      = tls->peer_write_MAC_key + tls->MAC_size; // client_write_key[]
+	tls->peer_write_key     = tls->our_write_key      + tls->key_size; // server_write_key[]
+	tls->our_write_IV       = tls->peer_write_key     + tls->key_size; // client_write_IV[]
+	tls->peer_write_IV      = tls->our_write_IV       + tls->IV_size;  // server_write_IV[]
+	dump_hex("client write_MAC_key:%s", tls->our_write_MAC_key, tls->MAC_size);
+	dump_hex("client write_key:%s",	tls->our_write_key, tls->key_size);
+	dump_hex("client write_IV:%s", tls->our_write_IV, tls->IV_size);
+	dump_hex("server write_MAC_key:%s", tls->peer_write_MAC_key, tls->MAC_size);
+	dump_hex("server write_key:%s",	tls->peer_write_key, tls->key_size);
+	dump_hex("server write_IV:%s", tls->peer_write_IV, tls->IV_size);
+
+	initialize_aes_keys(tls);
 }
 
 static const uint8_t rec_CHANGE_CIPHER_SPEC[] ALIGN1 = {
@@ -2118,8 +2122,8 @@ static void send_finished(tls_state_t *tls, const char *msg_to_encrypt)
 		handshake_hash, len
 	);
 	dump_hex("from secret: %s", tls->hsd->master_secret, sizeof(tls->hsd->master_secret));
-	dump_hex("from labelSeed: %s", "client finished", sizeof("client finished")-1);
-	dump_hex("%s", handshake_hash, sizeof(handshake_hash));
+	dump_hex("from labelSeed: %s", msg_to_encrypt, strlen(msg_to_encrypt));
+	dump_hex("handshake_hash: %s", handshake_hash, sizeof(handshake_hash));
 	dump_hex("=> digest: %s", record->prf_result, sizeof(record->prf_result));
 
 	dbg(">> FINISHED");
@@ -2440,7 +2444,7 @@ static void get_client_hello(tls_state_t *tls)
 	/* NB: the recv'd block is already hashed by tls_xread_handshake_block() */
 	hp = (void*)(tls->inbuf + RECHDR_LEN);
 	if (hp->type != HANDSHAKE_CLIENT_HELLO
-	 || hp->len24_hi  != 0
+	 || hp->len24_hi != 0
 	 || len != ((hp->len24_mid << 8) | hp->len24_lo) + 4
 	 || hp->proto_maj != TLS_MAJ
 	 || !is_minor_version_valid(tls, hp->proto_min)
@@ -2452,18 +2456,11 @@ static void get_client_hello(tls_state_t *tls)
 	/* Save client random */
 	memcpy(tls->hsd->client_and_server_rand32, hp->rand32, 32);
 
-	/* Parse cipher suites to select one we support */
-	p = (uint8_t*)(hp + 1);
-
 	/* 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");
-	}
+	p = (uint8_t*)(hp + 1) + hp->session_id_len;
+	len -= (sizeof(*hp) + hp->session_id_len);
 
-	/* Parse cipher suite list */
+	/* Parse cipher suites to select one we support */
 	if (len < 2) {
 		bb_simple_error_msg_and_die("malformed ClientHello");
 	}
@@ -2475,6 +2472,17 @@ static void get_client_hello(tls_state_t *tls)
 		bb_simple_error_msg_and_die("malformed ClientHello");
 	}
 
+	/* Check whether we have TLS_EMPTY_RENEGOTIATION_INFO_SCSV */
+	for (j = 0; j < cipher_list_len; j += 2) {
+		if (p[j] == TLS_EMPTY_RENEGOTIATION_INFO_SCSV >> 8
+		 && p[j + 1] == (uint8_t)TLS_EMPTY_RENEGOTIATION_INFO_SCSV
+		) {
+			dbg("got TLS_EMPTY_RENEGOTIATION_INFO_SCSV");
+			tls->hsd->reneg_info_requested = 1;
+			break;
+		}
+	}
+
 	/* Select cipher + cert pair from client's list, preferring our ciphers in order */
 	for (i = 0; i < NUM_CIPHERS*2; i += 2) {
 		const uint8_t *our_cipher = &supported_ciphers[i];
@@ -2533,15 +2541,15 @@ static void get_client_hello(tls_state_t *tls)
 		return; /* malformed extensions, ignore */
 	}
 
-	/* Look for supported_groups extension (type 0x000a) */
+	/* Process extensions */
 	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) {
+		p += 4;
+		extensions_len -= 4 + ext_len;
+		if (extensions_len < 0) {
 			dbg("Extension length overflow");
 			return; /* malformed */
 		}
@@ -2552,7 +2560,7 @@ static void get_client_hello(tls_state_t *tls)
 			dbg("Found supported_groups extension");
 			p += 2;
 			ext_len -= 2;
-			if (ext_len != curve_list_len)
+			if (ext_len != curve_list_len || (ext_len & 1))
 				return; /* malformed */
 			while (1) {
 				unsigned curve;
@@ -2560,19 +2568,22 @@ static void get_client_hello(tls_state_t *tls)
 				if (ext_len < 0)
 					break; /* oops, it didn't */
 				curve = (p[0] << 8) | p[1];
+				p += 2;
 				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 */
+			continue;
 		}
 
+		if (ext_type == 0xff01) {
+			dbg("got reneg_info extension ff01");
+			tls->hsd->reneg_info_requested = 1;
+		}
 		p += ext_len;
-		extensions_len -= ext_len;
 	}
 }
 
@@ -2591,8 +2602,12 @@ static void send_server_hello(tls_state_t *tls)
 		uint8_t ext_reneg_info[5];  /* ff 01 00 01 00 */
 	};
 	struct server_hello *record;
+	unsigned len = sizeof(*record);
+
+	if (!tls->hsd->reneg_info_requested)
+		len -= 7;
 
-	record = get_outbuf_fill_handshake_record(tls, HANDSHAKE_SERVER_HELLO, sizeof(*record));
+	record = get_outbuf_fill_handshake_record(tls, HANDSHAKE_SERVER_HELLO, len);
 
 	record->proto_maj = TLS_MAJ;
 	record->proto_min = TLS_MIN;
@@ -2611,19 +2626,21 @@ static void send_server_hello(tls_state_t *tls)
 	/* No compression */
 	//record->comprtype = 0;
 
-	/* Extensions */
-	//record->extensions_len_hi = 0;
-	record->extensions_len_lo = 5; /* length of renegotiation_info extension */
-
-	/* Renegotiation info extension (RFC 5746) */
-	record->ext_reneg_info[0] = 0xff;
-	record->ext_reneg_info[1] = 0x01; /* extension type */
-	//record->ext_reneg_info[2] = 0x00;
-	record->ext_reneg_info[3] = 0x01; /* extension data length: 1 byte */
-	//record->ext_reneg_info[4] = 0x00; /* renegotiation info length: 0 (no previous connection) */
+	if (tls->hsd->reneg_info_requested) {
+		/* Extensions */
+		//record->extensions_len_hi = 0;
+		record->extensions_len_lo = 5; /* length of renegotiation_info extension */
+
+		/* Renegotiation info extension (RFC 5746) */
+		record->ext_reneg_info[0] = 0xff;
+		record->ext_reneg_info[1] = 0x01; /* extension type */
+		//record->ext_reneg_info[2] = 0x00;
+		record->ext_reneg_info[3] = 0x01; /* extension data length: 1 byte */
+		//record->ext_reneg_info[4] = 0x00; /* renegotiation info length: 0 (no previous connection) */
+	}
 
 	dbg(">> SERVER_HELLO");
-	xwrite_and_update_handshake_hash(tls, sizeof(*record));
+	xwrite_and_update_handshake_hash(tls, len);
 }
 
 static void send_server_certificate(tls_state_t *tls)
@@ -2647,12 +2664,18 @@ static void send_server_key_exchange(tls_state_t *tls)
 		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) */
+		/* Followed by signature: hash_alg(1) + sign_alg(1) + sig_len(2) + signature */
 	};
 	struct server_key_exchange *record;
+	uint8_t *p;
 	int pubkey_len;
+	int params_len;
 	int total_len;
+	uint8_t hash[32]; /* SHA256 hash */
+	sha256_ctx_t sha256_ctx;
+	int32 sig_len;
 
-	record = tls_get_zeroed_outbuf(tls, sizeof(*record));
+	record = tls_get_zeroed_outbuf(tls, sizeof(*record) + 4 + 512); /* extra space for signature */
 
 	record->type = HANDSHAKE_SERVER_KEY_EXCHANGE;
 	record->curve_type = 3; /* named curve */
@@ -2685,14 +2708,43 @@ static void send_server_key_exchange(tls_state_t *tls)
 
 	record->pubkey_len = pubkey_len;
 
-	/* Calculate total length: curve_type(1) + curve_id(2) + pubkey_len(1) + pubkey */
-	total_len = 4 + pubkey_len;
+	/* ServerECDHParams length: curve_type(1) + curve_id(2) + pubkey_len(1) + pubkey */
+	params_len = 4 + pubkey_len;
+
+	/* Sign the parameters with our RSA private key:
+	 * Signature is over SHA256(client_random + server_random + ServerECDHParams)
+	 */
+	sha256_begin(&sha256_ctx);
+	sha256_hash(&sha256_ctx, tls->hsd->client_and_server_rand32, 2 * 32);
+	sha256_hash(&sha256_ctx, &record->curve_type, params_len);
+	sha256_end(&sha256_ctx, hash);
+
+	/* Pointer to where signature data goes (after ServerECDHParams) */
+	p = record->pubkey + pubkey_len;
+
+	/* SignatureAndHashAlgorithm: hash=SHA256(4), signature=RSA(1) */
+	*p++ = 4; /* SHA256 */
+	*p++ = 1; /* RSA */
+
+	/* Sign the hash */
+	sig_len = privRsaEncryptSignedElement(NULL, &tls->hsd->rsa_priv_key,
+		hash, 32, p + 2, 512, NULL);
+	if (sig_len < 0) {
+		bb_error_msg_and_die("RSA signature failed");
+	}
+
+	/* Signature length (2 bytes, big-endian) */
+	p[0] = sig_len >> 8;
+	p[1] = sig_len & 0xff;
+
+	/* Total handshake message length: params + hash_alg(1) + sign_alg(1) + sig_len(2) + signature */
+	total_len = params_len + 2 + 2 + sig_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 wire length */
 	total_len += 4; /* type + len24 */
 
 	dbg(">> SERVER_KEY_EXCHANGE");
@@ -2813,16 +2865,21 @@ static void get_client_key_exchange(tls_state_t *tls)
 	}
 
 	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);
-	aes_setkey(&tls->aes_encrypt, tls->server_write_key, tls->key_size);
-	{
-		uint8_t iv[AES_BLOCK_SIZE];
-		memset(iv, 0, AES_BLOCK_SIZE);
-		aes_encrypt_one_block(&tls->aes_encrypt, iv, tls->H);
-	}
-	dbg("Derived key block");
+	// The key_block[] is partitioned as follows:
+	tls->peer_write_MAC_key = tls->key_block;                         // client_write_MAC_key[]
+	tls->our_write_MAC_key  = tls->key_block         + tls->MAC_size; // server_write_MAC_key[]
+	tls->peer_write_key     = tls->our_write_MAC_key + tls->MAC_size; // client_write_key[]
+	tls->our_write_key      = tls->peer_write_key    + tls->key_size; // server_write_key[]
+	tls->peer_write_IV      = tls->our_write_key     + tls->key_size; // client_write_IV[]
+	tls->our_write_IV       = tls->peer_write_IV     + tls->IV_size;  // server_write_IV[]
+	dump_hex("server write_MAC_key:%s", tls->our_write_MAC_key, tls->MAC_size);
+	dump_hex("server write_key:%s",	tls->our_write_key, tls->key_size);
+	dump_hex("server write_IV:%s", tls->our_write_IV, tls->IV_size);
+	dump_hex("client write_MAC_key:%s", tls->peer_write_MAC_key, tls->MAC_size);
+	dump_hex("client write_key:%s",	tls->peer_write_key, tls->key_size);
+	dump_hex("client write_IV:%s", tls->peer_write_IV, tls->IV_size);
+
+	initialize_aes_keys(tls);
 }
 
 /* Load RSA private key from DER file (supports PKCS#8 or PKCS#1)
diff --git a/networking/tls.h b/networking/tls.h
index e59a77824..e4c7090c8 100644
--- a/networking/tls.h
+++ b/networking/tls.h
@@ -48,6 +48,7 @@
 #define PS_PLATFORM_FAIL        -7      /* Failure as a result of system call error */
 #define PS_MEM_FAIL             -8      /* Failure to allocate requested memory */
 #define PS_LIMIT_FAIL           -9      /* Failure on sanity/limit tests */
+#define PS_UNSUPPORTED_FAIL     -10     /* Unsupported algorithm or operation */
 
 #define PS_TRUE         1
 #define PS_FALSE        0
@@ -89,6 +90,7 @@ void tls_get_random(void *buf, unsigned len) FAST_FUNC;
 
 #define matrixCryptoGetPrngData(buf, len, userPtr) (tls_get_random(buf, len), PS_SUCCESS)
 
+#define psMalloc(pool, size) xmalloc(size)
 #define psFree(p, pool)    free(p)
 #define psTraceCrypto(msg) bb_simple_error_msg_and_die(msg)
 
diff --git a/networking/tls_rsa.c b/networking/tls_rsa.c
index cb1ff11b2..4dcbd3a4d 100644
--- a/networking/tls_rsa.c
+++ b/networking/tls_rsa.c
@@ -212,6 +212,88 @@ int32 FAST_FUNC psRsaEncryptPub(psPool_t *pool, psRsaKey_t *key,
 	return size;
 }
 
+#if ENABLE_SSL_SERVER // || ENABLE_FEATURE_HTTPD_SSL
+
+#define psRsaEncryptPriv(pool, key, in, inlen, out, outlen, data) \
+        psRsaEncryptPriv(      key, in, inlen, out, outlen)
+static //bbox
+int32 psRsaEncryptPriv(psPool_t *pool, psRsaKey_t *key,
+					 unsigned char *in, uint32 inlen,
+					 unsigned char *out, uint32 outlen, void *data)
+{
+	int32	err;
+	uint32	size;
+
+	size = key->size;
+	if (outlen < size) {
+		psTraceCrypto("Error on bad outlen parameter to psRsaEncryptPriv\n");
+		return PS_ARG_FAIL;
+	}
+	if ((err = pkcs1Pad(in, inlen, out, size, PUBKEY_TYPE, data)) < PS_SUCCESS){
+		psTraceCrypto("Error padding psRsaEncryptPriv. Likely data too long\n");
+		return err;
+	}
+	if ((err = psRsaCrypt(pool, out, size, out, (uint32*)&outlen, key,
+			PRIVKEY_TYPE, data)) < PS_SUCCESS) {
+		psTraceCrypto("Error performing psRsaEncryptPriv\n");
+		return err;
+	}
+	if (outlen != size) {
+		psTraceCrypto("Encrypted size error in psRsaEncryptPriv\n");
+		return PS_FAILURE;
+	}
+	return size;
+}
+
+#define ASN_OVERHEAD_LEN_RSA_SHA2	19
+//#define ASN_OVERHEAD_LEN_RSA_SHA1	15
+
+/* ASN.1 DigestInfo wrappers for hash algorithms */
+static const unsigned char asn256dsWrap[] = {0x30, 0x31, 0x30, 0x0D, 0x06, 0x09, 0x60,
+	0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20};
+//#ifdef USE_SHA384
+//static const unsigned char asn384dsWrap[] = {0x30, 0x41, 0x30, 0x0D, 0x06, 0x09, 0x60,
+//	0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, 0x00, 0x04, 0x30};
+//#endif
+//static const unsigned char asn1dsWrap[] = {0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2B,
+//	0x0E, 0x03, 0x02, 0x1A, 0x05, 0x00, 0x04, 0x14};
+
+int32 FAST_FUNC privRsaEncryptSignedElement(psPool_t *pool, psRsaKey_t *key, //bbox: was psPubKey_t
+		unsigned char *in, uint32 inlen, unsigned char *out, uint32 outlen,
+		void *data)
+{
+	unsigned char	*c;
+	uint32			inlenWithAsn;
+	int32			rc;
+
+	if (inlen == 32) { //SHA256_HASH_SIZE
+		inlenWithAsn = inlen + ASN_OVERHEAD_LEN_RSA_SHA2;
+		c = psMalloc(pool, inlenWithAsn);
+		memcpy(c, asn256dsWrap, ASN_OVERHEAD_LEN_RSA_SHA2);
+		memcpy(c + ASN_OVERHEAD_LEN_RSA_SHA2, in, inlen);
+//	} else if (inlen == SHA1_HASH_SIZE) {
+//		inlenWithAsn = inlen + ASN_OVERHEAD_LEN_RSA_SHA1;
+//		c = psMalloc(pool, inlenWithAsn);
+//		memcpy(c, asn1dsWrap, ASN_OVERHEAD_LEN_RSA_SHA1);
+//		memcpy(c + ASN_OVERHEAD_LEN_RSA_SHA1, in, inlen);
+//#ifdef USE_SHA384
+//	} else if (inlen == SHA384_HASH_SIZE) {
+//		inlenWithAsn = inlen + ASN_OVERHEAD_LEN_RSA_SHA2;
+//		c = psMalloc(pool, inlenWithAsn);
+//		memcpy(c, asn384dsWrap, ASN_OVERHEAD_LEN_RSA_SHA2);
+//		memcpy(c + ASN_OVERHEAD_LEN_RSA_SHA2, in, inlen);
+//#endif
+	} else {
+		return PS_UNSUPPORTED_FAIL;
+	}
+
+	rc = psRsaEncryptPriv(pool, key, c, inlenWithAsn, //bbox: was (psRsaKey_t*)key->key
+		out, outlen, data);
+
+	psFree(c, pool);
+	return rc;
+}
+
 /* Remove PKCS#1 padding (Type 2) from decrypted data
  * Format: 00 || 02 || PS || 00 || M
  * Returns length of unpadded message, or negative on error
@@ -300,3 +382,5 @@ int32 FAST_FUNC psRsaDecryptPriv(psPool_t *pool, psRsaKey_t *key,
 	memset(in, 0x0, inlen);
 	return err;
 }
+
+#endif /* server */
diff --git a/networking/tls_rsa.h b/networking/tls_rsa.h
index b63a64d92..a8db73b9c 100644
--- a/networking/tls_rsa.h
+++ b/networking/tls_rsa.h
@@ -36,3 +36,9 @@ int32 psRsaEncryptPub(psPool_t *pool, psRsaKey_t *key,
 int32 psRsaDecryptPriv(psPool_t *pool, psRsaKey_t *key,
                                                 unsigned char *in, uint32 inlen,
                                                 unsigned char *out, uint32 outlen, void *data) FAST_FUNC;
+
+#define privRsaEncryptSignedElement(pool, key, in, inlen, out, outlen, data) \
+        privRsaEncryptSignedElement(      key, in, inlen, out, outlen)
+int32 privRsaEncryptSignedElement(psPool_t *pool, psRsaKey_t *key,
+                                                unsigned char *in, uint32 inlen,
+                                                unsigned char *out, uint32 outlen, void *data) FAST_FUNC;


More information about the busybox-cvs mailing list