diff options
Diffstat (limited to 'networking/tls.c')
-rw-r--r-- | networking/tls.c | 101 |
1 files changed, 66 insertions, 35 deletions
diff --git a/networking/tls.c b/networking/tls.c index 8492997ac..cacd2e9ff 100644 --- a/networking/tls.c +++ b/networking/tls.c | |||
@@ -18,6 +18,7 @@ | |||
18 | //kbuild:lib-$(CONFIG_TLS) += tls_aesgcm.o | 18 | //kbuild:lib-$(CONFIG_TLS) += tls_aesgcm.o |
19 | //kbuild:lib-$(CONFIG_TLS) += tls_rsa.o | 19 | //kbuild:lib-$(CONFIG_TLS) += tls_rsa.o |
20 | //kbuild:lib-$(CONFIG_TLS) += tls_fe.o | 20 | //kbuild:lib-$(CONFIG_TLS) += tls_fe.o |
21 | //kbuild:lib-$(CONFIG_TLS) += tls_sp_c32.o | ||
21 | 22 | ||
22 | #include "tls.h" | 23 | #include "tls.h" |
23 | 24 | ||
@@ -265,8 +266,9 @@ enum { | |||
265 | GOT_CERT_RSA_KEY_ALG = 1 << 1, | 266 | GOT_CERT_RSA_KEY_ALG = 1 << 1, |
266 | GOT_CERT_ECDSA_KEY_ALG = 1 << 2, // so far unused | 267 | GOT_CERT_ECDSA_KEY_ALG = 1 << 2, // so far unused |
267 | GOT_EC_KEY = 1 << 3, | 268 | GOT_EC_KEY = 1 << 3, |
268 | ENCRYPTION_AESGCM = 1 << 4, // else AES-SHA (or NULL-SHA if ALLOW_RSA_NULL_SHA256=1) | 269 | GOT_EC_CURVE_X25519 = 1 << 4, // else P256 |
269 | ENCRYPT_ON_WRITE = 1 << 5, | 270 | ENCRYPTION_AESGCM = 1 << 5, // else AES-SHA (or NULL-SHA if ALLOW_RSA_NULL_SHA256=1) |
271 | ENCRYPT_ON_WRITE = 1 << 6, | ||
270 | }; | 272 | }; |
271 | 273 | ||
272 | struct record_hdr { | 274 | struct record_hdr { |
@@ -285,7 +287,11 @@ struct tls_handshake_data { | |||
285 | //TODO: store just the DER key here, parse/use/delete it when sending client key | 287 | //TODO: store just the DER key here, parse/use/delete it when sending client key |
286 | //this way it will stay key type agnostic here. | 288 | //this way it will stay key type agnostic here. |
287 | psRsaKey_t server_rsa_pub_key; | 289 | psRsaKey_t server_rsa_pub_key; |
288 | uint8_t ecc_pub_key32[32]; | 290 | |
291 | /* peer's elliptic curve key data */ | ||
292 | /* for x25519, it contains one point in first 32 bytes */ | ||
293 | /* for P256, it contains x,y point pair, each 32 bytes long */ | ||
294 | uint8_t ecc_pub_key32[2 * 32]; | ||
289 | 295 | ||
290 | /* HANDSHAKE HASH: */ | 296 | /* HANDSHAKE HASH: */ |
291 | //unsigned saved_client_hello_size; | 297 | //unsigned saved_client_hello_size; |
@@ -1526,20 +1532,13 @@ static void send_client_hello_and_alloc_hsd(tls_state_t *tls, const char *sni) | |||
1526 | }; | 1532 | }; |
1527 | static const uint8_t supported_groups[] = { | 1533 | static const uint8_t supported_groups[] = { |
1528 | 0x00,0x0a, //extension_type: "supported_groups" | 1534 | 0x00,0x0a, //extension_type: "supported_groups" |
1529 | 0x00,0x04, //ext len | 1535 | 0x00,0x06, //ext len |
1530 | 0x00,0x02, //list len | 1536 | 0x00,0x04, //list len |
1531 | 0x00,0x1d, //curve_x25519 (RFC 7748) | 1537 | 0x00,0x17, //curve_secp256r1 |
1532 | //0x00,0x1e, //curve_x448 (RFC 7748) | ||
1533 | //0x00,0x17, //curve_secp256r1 | ||
1534 | //0x00,0x18, //curve_secp384r1 | 1538 | //0x00,0x18, //curve_secp384r1 |
1535 | //0x00,0x19, //curve_secp521r1 | 1539 | //0x00,0x19, //curve_secp521r1 |
1536 | //TODO: implement secp256r1 (at least): dl.fedoraproject.org immediately aborts | 1540 | 0x00,0x1d, //curve_x25519 (RFC 7748) |
1537 | //if only x25519/x448 are advertised, seems to support only secpNNNr1 curves: | 1541 | //0x00,0x1e, //curve_x448 (RFC 7748) |
1538 | // openssl s_client -connect dl.fedoraproject.org:443 -debug -tls1_2 -cipher ECDHE-RSA-AES128-GCM-SHA256 | ||
1539 | //Peer signing digest: SHA512 | ||
1540 | //Peer signature type: RSA | ||
1541 | //Server Temp Key: ECDH, P-256, 256 bits | ||
1542 | //TLSv1.2, Cipher is ECDHE-RSA-AES128-GCM-SHA256 | ||
1543 | }; | 1542 | }; |
1544 | //static const uint8_t signature_algorithms[] = { | 1543 | //static const uint8_t signature_algorithms[] = { |
1545 | // 000d | 1544 | // 000d |
@@ -1877,12 +1876,32 @@ static void process_server_key(tls_state_t *tls, int len) | |||
1877 | if (len < (1+2+1+32)) tls_error_die(tls); | 1876 | if (len < (1+2+1+32)) tls_error_die(tls); |
1878 | keybuf += 4; | 1877 | keybuf += 4; |
1879 | 1878 | ||
1880 | /* So far we only support curve_x25519 */ | 1879 | #if BB_BIG_ENDIAN |
1880 | # define _0x03001741 0x03001741 | ||
1881 | # define _0x03001d20 0x03001d20 | ||
1882 | #else | ||
1883 | # define _0x03001741 0x41170003 | ||
1884 | # define _0x03001d20 0x201d0003 | ||
1885 | #endif | ||
1881 | move_from_unaligned32(t32, keybuf); | 1886 | move_from_unaligned32(t32, keybuf); |
1882 | if (t32 != htonl(0x03001d20)) | 1887 | keybuf += 4; |
1883 | bb_simple_error_msg_and_die("elliptic curve is not x25519"); | 1888 | switch (t32) { |
1889 | case _0x03001d20: //curve_x25519 | ||
1890 | tls->flags |= GOT_EC_CURVE_X25519; | ||
1891 | memcpy(tls->hsd->ecc_pub_key32, keybuf, 32); | ||
1892 | break; | ||
1893 | case _0x03001741: //curve_secp256r1 | ||
1894 | /* P256 point can be transmitted odd- or even-compressed | ||
1895 | * (first byte is 3 or 2) or uncompressed (4). | ||
1896 | */ | ||
1897 | if (*keybuf++ != 4) | ||
1898 | bb_simple_error_msg_and_die("compressed EC points not supported"); | ||
1899 | memcpy(tls->hsd->ecc_pub_key32, keybuf, 2 * 32); | ||
1900 | break; | ||
1901 | default: | ||
1902 | bb_error_msg_and_die("elliptic curve is not x25519 or P256: 0x%08x", t32); | ||
1903 | } | ||
1884 | 1904 | ||
1885 | memcpy(tls->hsd->ecc_pub_key32, keybuf + 4, 32); | ||
1886 | tls->flags |= GOT_EC_KEY; | 1905 | tls->flags |= GOT_EC_KEY; |
1887 | dbg("got eccPubKey\n"); | 1906 | dbg("got eccPubKey\n"); |
1888 | } | 1907 | } |
@@ -1918,9 +1937,7 @@ static void send_client_key_exchange(tls_state_t *tls) | |||
1918 | }; | 1937 | }; |
1919 | //FIXME: better size estimate | 1938 | //FIXME: better size estimate |
1920 | struct client_key_exchange *record = tls_get_zeroed_outbuf(tls, sizeof(*record)); | 1939 | struct client_key_exchange *record = tls_get_zeroed_outbuf(tls, sizeof(*record)); |
1921 | uint8_t rsa_premaster[RSA_PREMASTER_SIZE]; | 1940 | uint8_t premaster[RSA_PREMASTER_SIZE > EC_CURVE_KEYSIZE ? RSA_PREMASTER_SIZE : EC_CURVE_KEYSIZE]; |
1922 | uint8_t x25519_premaster[CURVE25519_KEYSIZE]; | ||
1923 | uint8_t *premaster; | ||
1924 | int premaster_size; | 1941 | int premaster_size; |
1925 | int len; | 1942 | int len; |
1926 | 1943 | ||
@@ -1929,19 +1946,19 @@ static void send_client_key_exchange(tls_state_t *tls) | |||
1929 | if (!(tls->flags & GOT_CERT_RSA_KEY_ALG)) | 1946 | if (!(tls->flags & GOT_CERT_RSA_KEY_ALG)) |
1930 | bb_simple_error_msg("server cert is not RSA"); | 1947 | bb_simple_error_msg("server cert is not RSA"); |
1931 | 1948 | ||
1932 | tls_get_random(rsa_premaster, sizeof(rsa_premaster)); | 1949 | tls_get_random(premaster, RSA_PREMASTER_SIZE); |
1933 | if (TLS_DEBUG_FIXED_SECRETS) | 1950 | if (TLS_DEBUG_FIXED_SECRETS) |
1934 | memset(rsa_premaster, 0x44, sizeof(rsa_premaster)); | 1951 | memset(premaster, 0x44, RSA_PREMASTER_SIZE); |
1935 | // RFC 5246 | 1952 | // RFC 5246 |
1936 | // "Note: The version number in the PreMasterSecret is the version | 1953 | // "Note: The version number in the PreMasterSecret is the version |
1937 | // offered by the client in the ClientHello.client_version, not the | 1954 | // offered by the client in the ClientHello.client_version, not the |
1938 | // version negotiated for the connection." | 1955 | // version negotiated for the connection." |
1939 | rsa_premaster[0] = TLS_MAJ; | 1956 | premaster[0] = TLS_MAJ; |
1940 | rsa_premaster[1] = TLS_MIN; | 1957 | premaster[1] = TLS_MIN; |
1941 | dump_hex("premaster:%s\n", rsa_premaster, sizeof(rsa_premaster)); | 1958 | dump_hex("premaster:%s\n", premaster, sizeof(premaster)); |
1942 | len = psRsaEncryptPub(/*pool:*/ NULL, | 1959 | len = psRsaEncryptPub(/*pool:*/ NULL, |
1943 | /* psRsaKey_t* */ &tls->hsd->server_rsa_pub_key, | 1960 | /* psRsaKey_t* */ &tls->hsd->server_rsa_pub_key, |
1944 | rsa_premaster, /*inlen:*/ sizeof(rsa_premaster), | 1961 | premaster, /*inlen:*/ RSA_PREMASTER_SIZE, |
1945 | record->key + 2, sizeof(record->key) - 2, | 1962 | record->key + 2, sizeof(record->key) - 2, |
1946 | data_param_ignored | 1963 | data_param_ignored |
1947 | ); | 1964 | ); |
@@ -1949,10 +1966,10 @@ static void send_client_key_exchange(tls_state_t *tls) | |||
1949 | record->key[0] = len >> 8; | 1966 | record->key[0] = len >> 8; |
1950 | record->key[1] = len & 0xff; | 1967 | record->key[1] = len & 0xff; |
1951 | len += 2; | 1968 | len += 2; |
1952 | premaster = rsa_premaster; | 1969 | premaster_size = RSA_PREMASTER_SIZE; |
1953 | premaster_size = sizeof(rsa_premaster); | 1970 | } else /* ECDHE */ |
1954 | } else { | 1971 | if (tls->flags & GOT_EC_CURVE_X25519) { |
1955 | /* ECDHE */ | 1972 | /* ECDHE, curve x25519 */ |
1956 | static const uint8_t basepoint9[CURVE25519_KEYSIZE] ALIGN8 = {9}; | 1973 | static const uint8_t basepoint9[CURVE25519_KEYSIZE] ALIGN8 = {9}; |
1957 | uint8_t privkey[CURVE25519_KEYSIZE]; //[32] | 1974 | uint8_t privkey[CURVE25519_KEYSIZE]; //[32] |
1958 | 1975 | ||
@@ -1969,13 +1986,27 @@ static void send_client_key_exchange(tls_state_t *tls) | |||
1969 | 1986 | ||
1970 | /* Compute premaster using peer's public key */ | 1987 | /* Compute premaster using peer's public key */ |
1971 | dbg("computing x25519_premaster\n"); | 1988 | dbg("computing x25519_premaster\n"); |
1972 | curve25519(x25519_premaster, privkey, tls->hsd->ecc_pub_key32); | 1989 | curve25519(premaster, privkey, tls->hsd->ecc_pub_key32); |
1973 | 1990 | ||
1974 | len = CURVE25519_KEYSIZE; | 1991 | len = CURVE25519_KEYSIZE; |
1975 | record->key[0] = len; | 1992 | record->key[0] = len; |
1976 | len++; | 1993 | len++; |
1977 | premaster = x25519_premaster; | 1994 | premaster_size = CURVE25519_KEYSIZE; |
1978 | premaster_size = sizeof(x25519_premaster); | 1995 | } else { |
1996 | /* ECDHE, curve P256 */ | ||
1997 | if (!(tls->flags & GOT_EC_KEY)) | ||
1998 | bb_simple_error_msg_and_die("server did not provide EC key"); | ||
1999 | |||
2000 | dbg("computing P256_premaster\n"); | ||
2001 | curve_P256_compute_pubkey_and_premaster( | ||
2002 | record->key + 2, premaster, | ||
2003 | /*point:*/ tls->hsd->ecc_pub_key32 | ||
2004 | ); | ||
2005 | premaster_size = P256_KEYSIZE; | ||
2006 | len = 1 + P256_KEYSIZE * 2; | ||
2007 | record->key[0] = len; | ||
2008 | record->key[1] = 4; | ||
2009 | len++; | ||
1979 | } | 2010 | } |
1980 | 2011 | ||
1981 | record->type = HANDSHAKE_CLIENT_KEY_EXCHANGE; | 2012 | record->type = HANDSHAKE_CLIENT_KEY_EXCHANGE; |