|
56 | 56 | #define PTLS_HANDSHAKE_TYPE_KEY_UPDATE 24
|
57 | 57 | #define PTLS_HANDSHAKE_TYPE_MESSAGE_HASH 254
|
58 | 58 |
|
| 59 | +/* 4.4.2 */ |
| 60 | +#define PTLS_CERTIFICATE_TYPE_X509 0 |
| 61 | +#define PTLS_CERTIFICATE_TYPE_X509_BIT 1 << PTLS_CERTIFICATE_TYPE_X509 |
| 62 | +#define PTLS_CERTIFICATE_TYPE_RAW_PUBLIC_KEY 2 |
| 63 | +#define PTLS_CERTIFICATE_TYPE_RAW_PUBLIC_KEY_BIT 1 << PTLS_CERTIFICATE_TYPE_RAW_PUBLIC_KEY |
| 64 | + |
59 | 65 | #define PTLS_PSK_KE_MODE_PSK 0
|
60 | 66 | #define PTLS_PSK_KE_MODE_PSK_DHE 1
|
61 | 67 |
|
|
66 | 72 | #define PTLS_EXTENSION_TYPE_SUPPORTED_GROUPS 10
|
67 | 73 | #define PTLS_EXTENSION_TYPE_SIGNATURE_ALGORITHMS 13
|
68 | 74 | #define PTLS_EXTENSION_TYPE_ALPN 16
|
| 75 | +#define PTLS_EXTENSION_TYPE_CLIENT_CERTIFICATE_TYPE 19 |
| 76 | +#define PTLS_EXTENSION_TYPE_SERVER_CERTIFICATE_TYPE 20 |
69 | 77 | #define PTLS_EXTENSION_TYPE_PRE_SHARED_KEY 41
|
70 | 78 | #define PTLS_EXTENSION_TYPE_EARLY_DATA 42
|
71 | 79 | #define PTLS_EXTENSION_TYPE_SUPPORTED_VERSIONS 43
|
@@ -217,6 +225,11 @@ struct st_ptls_t {
|
217 | 225 | unsigned is_psk_handshake : 1;
|
218 | 226 | unsigned skip_early_data : 1; /* if early-data is not recognized by the server */
|
219 | 227 | unsigned send_change_cipher_spec : 1;
|
| 228 | + /* RFC 7250 */ |
| 229 | + uint8_t client_certificate_types; /* bit field as should have been all along */ |
| 230 | + uint8_t server_certificate_types; /* bit field as should have been all along */ |
| 231 | + uint8_t client_certificate_type; |
| 232 | + uint8_t server_certificate_type; |
220 | 233 | /**
|
221 | 234 | * exporter master secret (either 0rtt or 1rtt)
|
222 | 235 | */
|
@@ -1538,6 +1551,22 @@ static int send_client_hello(ptls_t *tls, struct st_ptls_message_emitter_t *emit
|
1538 | 1551 | }
|
1539 | 1552 | });
|
1540 | 1553 | });
|
| 1554 | + /* RFC 7250 RawPublicKey |
| 1555 | + * TODO make sure all every ptls_key_exchange_algorithm_t implements RawPublicKey |
| 1556 | + * as per https://tools.ietf.org/html/rfc7250#section-4.1 P 5 and 6 |
| 1557 | + * TODO allow accepting both RAW_PUBLIC_KEY and X509, and then extracting the public key from the certificate |
| 1558 | + * ptls_buffer_push(sendbuf, 2, PTLS_CERTIFICATE_TYPE_X509, PTLS_CERTIFICATE_TYPE_RAW_PUBLIC_KEY); |
| 1559 | + */ |
| 1560 | + if (tls->ctx->client_raw_public_key) { |
| 1561 | + buffer_push_extension(sendbuf, PTLS_EXTENSION_TYPE_CLIENT_CERTIFICATE_TYPE, { |
| 1562 | + ptls_buffer_push(sendbuf, 1, PTLS_CERTIFICATE_TYPE_RAW_PUBLIC_KEY); |
| 1563 | + }); |
| 1564 | + } |
| 1565 | + if (tls->ctx->server_raw_public_key) { |
| 1566 | + buffer_push_extension(sendbuf, PTLS_EXTENSION_TYPE_SERVER_CERTIFICATE_TYPE, { |
| 1567 | + ptls_buffer_push(sendbuf, 1, PTLS_CERTIFICATE_TYPE_RAW_PUBLIC_KEY); |
| 1568 | + }); |
| 1569 | + } |
1541 | 1570 | if (cookie != NULL && cookie->base != NULL) {
|
1542 | 1571 | buffer_push_extension(sendbuf, PTLS_EXTENSION_TYPE_COOKIE, {
|
1543 | 1572 | ptls_buffer_push_block(sendbuf, 2, { ptls_buffer_pushv(sendbuf, cookie->base, cookie->len); });
|
@@ -1730,12 +1759,43 @@ static int decode_server_hello(ptls_t *tls, struct st_ptls_server_hello_t *sh, c
|
1730 | 1759 | goto Exit;
|
1731 | 1760 | }
|
1732 | 1761 | break;
|
1733 |
| - default: |
| 1762 | + case PTLS_EXTENSION_TYPE_CLIENT_CERTIFICATE_TYPE: |
| 1763 | + case PTLS_EXTENSION_TYPE_SERVER_CERTIFICATE_TYPE: { |
| 1764 | + if (src == end) { |
| 1765 | + ret = PTLS_ALERT_DECODE_ERROR; |
| 1766 | + goto Exit; |
| 1767 | + } |
| 1768 | + uint8_t certificate_type = *src++; |
| 1769 | + if (certificate_type > PTLS_CERTIFICATE_TYPE_RAW_PUBLIC_KEY || |
| 1770 | + certificate_type == 1/* OpenSSH, forbidden by TLS 1.3 */) { |
| 1771 | + ret = PTLS_ALERT_UNSUPPORTED_CERTIFICATE; |
| 1772 | + goto Exit; |
| 1773 | + } |
| 1774 | + switch (exttype) { |
| 1775 | + case PTLS_EXTENSION_TYPE_CLIENT_CERTIFICATE_TYPE: |
| 1776 | + tls->client_certificate_type = certificate_type; |
| 1777 | + break; |
| 1778 | + case PTLS_EXTENSION_TYPE_SERVER_CERTIFICATE_TYPE: |
| 1779 | + tls->server_certificate_type = certificate_type; |
| 1780 | + break; |
| 1781 | + default: |
| 1782 | + break; |
| 1783 | + } |
| 1784 | + break; |
| 1785 | + } default: |
1734 | 1786 | src = end;
|
1735 | 1787 | break;
|
1736 | 1788 | }
|
1737 | 1789 | });
|
1738 | 1790 |
|
| 1791 | + if (((tls->client_certificate_type == PTLS_CERTIFICATE_TYPE_RAW_PUBLIC_KEY) != |
| 1792 | + tls->ctx->client_raw_public_key) || /* TODO handle this case by extracting public key from client certificate */ |
| 1793 | + ((tls->server_certificate_type == PTLS_CERTIFICATE_TYPE_RAW_PUBLIC_KEY) != |
| 1794 | + tls->ctx->server_raw_public_key)) { |
| 1795 | + ret = PTLS_ALERT_UNSUPPORTED_CERTIFICATE; |
| 1796 | + goto Exit; |
| 1797 | + } |
| 1798 | + |
1739 | 1799 | if (!is_supported_version(found_version)) {
|
1740 | 1800 | ret = PTLS_ALERT_ILLEGAL_PARAMETER;
|
1741 | 1801 | goto Exit;
|
@@ -2612,13 +2672,50 @@ static int decode_client_hello(ptls_t *tls, struct st_ptls_client_hello_t *ch, c
|
2612 | 2672 | case PTLS_EXTENSION_TYPE_STATUS_REQUEST:
|
2613 | 2673 | ch->status_request = 1;
|
2614 | 2674 | break;
|
2615 |
| - default: |
| 2675 | + case PTLS_EXTENSION_TYPE_CLIENT_CERTIFICATE_TYPE: |
| 2676 | + case PTLS_EXTENSION_TYPE_SERVER_CERTIFICATE_TYPE: { |
| 2677 | + if (src == end) { |
| 2678 | + ret = PTLS_ALERT_DECODE_ERROR; |
| 2679 | + goto Exit; |
| 2680 | + } |
| 2681 | + uint8_t length = *src++; |
| 2682 | + if (end - src != length) { |
| 2683 | + ret = PTLS_ALERT_DECODE_ERROR; |
| 2684 | + goto Exit; |
| 2685 | + } |
| 2686 | + for (;src != end; ++src) { |
| 2687 | + uint8_t certificate_type = *src; |
| 2688 | + if (certificate_type > PTLS_CERTIFICATE_TYPE_RAW_PUBLIC_KEY || |
| 2689 | + certificate_type == 1/* OpenSSH, forbidden by TLS 1.3 */) { |
| 2690 | + ret = PTLS_ALERT_UNSUPPORTED_CERTIFICATE; |
| 2691 | + goto Exit; |
| 2692 | + } |
| 2693 | + if (exttype == PTLS_EXTENSION_TYPE_CLIENT_CERTIFICATE_TYPE) { |
| 2694 | + tls->client_certificate_types |= (1 << certificate_type); |
| 2695 | + } else if (exttype == PTLS_EXTENSION_TYPE_SERVER_CERTIFICATE_TYPE) { |
| 2696 | + tls->server_certificate_types |= (1 << certificate_type); |
| 2697 | + } |
| 2698 | + } |
| 2699 | + break; |
| 2700 | + } default: |
2616 | 2701 | handle_unknown_extension(tls, properties, exttype, src, end, ch->unknown_extensions);
|
2617 | 2702 | break;
|
2618 | 2703 | }
|
2619 | 2704 | src = end;
|
2620 | 2705 | });
|
2621 | 2706 |
|
| 2707 | + if ((tls->client_certificate_types & PTLS_CERTIFICATE_TYPE_RAW_PUBLIC_KEY_BIT) && |
| 2708 | + !tls->ctx->client_raw_public_key ) { |
| 2709 | + ret = PTLS_ALERT_UNSUPPORTED_CERTIFICATE; |
| 2710 | + goto Exit; |
| 2711 | + } |
| 2712 | + /* TODO handle this case by extracting public key from certificate */ |
| 2713 | + if ((tls->server_certificate_types & PTLS_CERTIFICATE_TYPE_RAW_PUBLIC_KEY_BIT) && |
| 2714 | + !tls->ctx->server_raw_public_key) { |
| 2715 | + ret = PTLS_ALERT_UNSUPPORTED_CERTIFICATE; |
| 2716 | + goto Exit; |
| 2717 | + } |
| 2718 | + |
2622 | 2719 | /* check if client hello make sense */
|
2623 | 2720 | if (is_supported_version(ch->selected_version)) {
|
2624 | 2721 | if (!(ch->compression_methods.count == 1 && ch->compression_methods.ids[0] == 0)) {
|
@@ -3072,6 +3169,14 @@ static int server_handle_hello(ptls_t *tls, struct st_ptls_message_emitter_t *em
|
3072 | 3169 | buffer_push_extension(sendbuf, PTLS_EXTENSION_TYPE_PRE_SHARED_KEY,
|
3073 | 3170 | { ptls_buffer_push16(sendbuf, (uint16_t)psk_index); });
|
3074 | 3171 | }
|
| 3172 | + if (tls->ctx->server_raw_public_key) |
| 3173 | + buffer_push_extension(sendbuf, PTLS_EXTENSION_TYPE_SERVER_CERTIFICATE_TYPE, { |
| 3174 | + ptls_buffer_push(sendbuf, PTLS_CERTIFICATE_TYPE_RAW_PUBLIC_KEY); |
| 3175 | + }); |
| 3176 | + if (tls->ctx->client_raw_public_key) |
| 3177 | + buffer_push_extension(sendbuf, PTLS_EXTENSION_TYPE_CLIENT_CERTIFICATE_TYPE, { |
| 3178 | + ptls_buffer_push(sendbuf, PTLS_CERTIFICATE_TYPE_RAW_PUBLIC_KEY); |
| 3179 | + }); |
3075 | 3180 | });
|
3076 | 3181 | if ((ret = push_change_cipher_spec(tls, emitter->buf)) != 0)
|
3077 | 3182 | goto Exit;
|
|
0 commit comments