diff options
author | jsing <> | 2020-05-29 18:00:10 +0000 |
---|---|---|
committer | jsing <> | 2020-05-29 18:00:10 +0000 |
commit | 0ef5f8585d34b9d2de88692d29e28b65e20c9562 (patch) | |
tree | e48fe26edb46ce97cad12ada94c4e75d004a357d | |
parent | ed3918023e9cb56cd8b5aee0647135d4088a65b0 (diff) | |
download | openbsd-0ef5f8585d34b9d2de88692d29e28b65e20c9562.tar.gz openbsd-0ef5f8585d34b9d2de88692d29e28b65e20c9562.tar.bz2 openbsd-0ef5f8585d34b9d2de88692d29e28b65e20c9562.zip |
Improve server certificate selection for TLSv1.3.
This allows an EC certificate to be selected and used, if the client
sigalgs would allow it.
With feedback from tb@
ok inoguchi@ tb@
-rw-r--r-- | src/lib/libssl/ssl_locl.h | 18 | ||||
-rw-r--r-- | src/lib/libssl/tls13_server.c | 99 |
2 files changed, 94 insertions, 23 deletions
diff --git a/src/lib/libssl/ssl_locl.h b/src/lib/libssl/ssl_locl.h index 046c4bba52..e7e3e56154 100644 --- a/src/lib/libssl/ssl_locl.h +++ b/src/lib/libssl/ssl_locl.h | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: ssl_locl.h,v 1.276 2020/05/29 17:39:42 jsing Exp $ */ | 1 | /* $OpenBSD: ssl_locl.h,v 1.277 2020/05/29 18:00:10 jsing Exp $ */ |
2 | /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) | 2 | /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) |
3 | * All rights reserved. | 3 | * All rights reserved. |
4 | * | 4 | * |
@@ -435,6 +435,12 @@ typedef struct ssl_handshake_st { | |||
435 | uint8_t *sigalgs; | 435 | uint8_t *sigalgs; |
436 | } SSL_HANDSHAKE; | 436 | } SSL_HANDSHAKE; |
437 | 437 | ||
438 | typedef struct cert_pkey_st { | ||
439 | X509 *x509; | ||
440 | EVP_PKEY *privatekey; | ||
441 | STACK_OF(X509) *chain; | ||
442 | } CERT_PKEY; | ||
443 | |||
438 | typedef struct ssl_handshake_tls13_st { | 444 | typedef struct ssl_handshake_tls13_st { |
439 | uint16_t min_version; | 445 | uint16_t min_version; |
440 | uint16_t max_version; | 446 | uint16_t max_version; |
@@ -443,6 +449,10 @@ typedef struct ssl_handshake_tls13_st { | |||
443 | int use_legacy; | 449 | int use_legacy; |
444 | int hrr; | 450 | int hrr; |
445 | 451 | ||
452 | /* Certificate and sigalg selected for use (static pointers). */ | ||
453 | const CERT_PKEY *cpk; | ||
454 | const struct ssl_sigalg *sigalg; | ||
455 | |||
446 | /* Version proposed by peer server. */ | 456 | /* Version proposed by peer server. */ |
447 | uint16_t server_version; | 457 | uint16_t server_version; |
448 | 458 | ||
@@ -985,12 +995,6 @@ typedef struct dtls1_state_internal_st { | |||
985 | } DTLS1_STATE_INTERNAL; | 995 | } DTLS1_STATE_INTERNAL; |
986 | #define D1I(s) (s->d1->internal) | 996 | #define D1I(s) (s->d1->internal) |
987 | 997 | ||
988 | typedef struct cert_pkey_st { | ||
989 | X509 *x509; | ||
990 | EVP_PKEY *privatekey; | ||
991 | STACK_OF(X509) *chain; | ||
992 | } CERT_PKEY; | ||
993 | |||
994 | typedef struct cert_st { | 998 | typedef struct cert_st { |
995 | /* Current active set */ | 999 | /* Current active set */ |
996 | CERT_PKEY *key; /* ALWAYS points to an element of the pkeys array | 1000 | CERT_PKEY *key; /* ALWAYS points to an element of the pkeys array |
diff --git a/src/lib/libssl/tls13_server.c b/src/lib/libssl/tls13_server.c index 181ba583a0..e9fecdee26 100644 --- a/src/lib/libssl/tls13_server.c +++ b/src/lib/libssl/tls13_server.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: tls13_server.c,v 1.54 2020/05/29 17:47:30 jsing Exp $ */ | 1 | /* $OpenBSD: tls13_server.c,v 1.55 2020/05/29 18:00:10 jsing Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2019, 2020 Joel Sing <jsing@openbsd.org> | 3 | * Copyright (c) 2019, 2020 Joel Sing <jsing@openbsd.org> |
4 | * Copyright (c) 2020 Bob Beck <beck@openbsd.org> | 4 | * Copyright (c) 2020 Bob Beck <beck@openbsd.org> |
@@ -16,6 +16,8 @@ | |||
16 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | 16 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
17 | */ | 17 | */ |
18 | 18 | ||
19 | #include <openssl/x509v3.h> | ||
20 | |||
19 | #include "ssl_locl.h" | 21 | #include "ssl_locl.h" |
20 | #include "ssl_tlsext.h" | 22 | #include "ssl_tlsext.h" |
21 | 23 | ||
@@ -448,19 +450,85 @@ tls13_server_certificate_request_send(struct tls13_ctx *ctx, CBB *cbb) | |||
448 | return 0; | 450 | return 0; |
449 | } | 451 | } |
450 | 452 | ||
453 | static int | ||
454 | tls13_server_check_certificate(struct tls13_ctx *ctx, CERT_PKEY *cpk, | ||
455 | int *ok, const struct ssl_sigalg **out_sigalg) | ||
456 | { | ||
457 | const struct ssl_sigalg *sigalg; | ||
458 | SSL *s = ctx->ssl; | ||
459 | |||
460 | *ok = 0; | ||
461 | *out_sigalg = NULL; | ||
462 | |||
463 | if (cpk->x509 == NULL || cpk->privatekey == NULL) | ||
464 | goto done; | ||
465 | |||
466 | if (!X509_check_purpose(cpk->x509, -1, 0)) | ||
467 | return 0; | ||
468 | |||
469 | /* | ||
470 | * The digitalSignature bit MUST be set if the Key Usage extension is | ||
471 | * present as per RFC 8446 section 4.4.2.2. | ||
472 | */ | ||
473 | if ((cpk->x509->ex_flags & EXFLAG_KUSAGE) && | ||
474 | !(cpk->x509->ex_kusage & X509v3_KU_DIGITAL_SIGNATURE)) | ||
475 | goto done; | ||
476 | |||
477 | if ((sigalg = ssl_sigalg_select(s, cpk->privatekey)) == NULL) | ||
478 | goto done; | ||
479 | |||
480 | *ok = 1; | ||
481 | *out_sigalg = sigalg; | ||
482 | |||
483 | done: | ||
484 | return 1; | ||
485 | } | ||
486 | |||
487 | static int | ||
488 | tls13_server_select_certificate(struct tls13_ctx *ctx, CERT_PKEY **out_cpk, | ||
489 | const struct ssl_sigalg **out_sigalg) | ||
490 | { | ||
491 | SSL *s = ctx->ssl; | ||
492 | const struct ssl_sigalg *sigalg; | ||
493 | CERT_PKEY *cpk; | ||
494 | int cert_ok; | ||
495 | |||
496 | *out_cpk = NULL; | ||
497 | *out_sigalg = NULL; | ||
498 | |||
499 | cpk = &s->cert->pkeys[SSL_PKEY_ECC]; | ||
500 | if (!tls13_server_check_certificate(ctx, cpk, &cert_ok, &sigalg)) | ||
501 | return 0; | ||
502 | if (cert_ok) | ||
503 | goto done; | ||
504 | |||
505 | cpk = &s->cert->pkeys[SSL_PKEY_RSA]; | ||
506 | if (!tls13_server_check_certificate(ctx, cpk, &cert_ok, &sigalg)) | ||
507 | return 0; | ||
508 | if (cert_ok) | ||
509 | goto done; | ||
510 | |||
511 | return 0; | ||
512 | |||
513 | done: | ||
514 | *out_cpk = cpk; | ||
515 | *out_sigalg = sigalg; | ||
516 | |||
517 | return 1; | ||
518 | } | ||
519 | |||
451 | int | 520 | int |
452 | tls13_server_certificate_send(struct tls13_ctx *ctx, CBB *cbb) | 521 | tls13_server_certificate_send(struct tls13_ctx *ctx, CBB *cbb) |
453 | { | 522 | { |
454 | SSL *s = ctx->ssl; | 523 | SSL *s = ctx->ssl; |
455 | CBB cert_request_context, cert_list; | 524 | CBB cert_request_context, cert_list; |
525 | const struct ssl_sigalg *sigalg; | ||
456 | STACK_OF(X509) *chain; | 526 | STACK_OF(X509) *chain; |
457 | CERT_PKEY *cpk; | 527 | CERT_PKEY *cpk; |
458 | X509 *cert; | 528 | X509 *cert; |
459 | int i, ret = 0; | 529 | int i, ret = 0; |
460 | 530 | ||
461 | /* XXX - Need to revisit certificate selection. */ | 531 | if (!tls13_server_select_certificate(ctx, &cpk, &sigalg)) { |
462 | cpk = &s->cert->pkeys[SSL_PKEY_RSA]; | ||
463 | if (cpk->x509 == NULL) { | ||
464 | /* A server must always provide a certificate. */ | 532 | /* A server must always provide a certificate. */ |
465 | ctx->alert = TLS13_ALERT_HANDSHAKE_FAILURE; | 533 | ctx->alert = TLS13_ALERT_HANDSHAKE_FAILURE; |
466 | tls13_set_errorx(ctx, TLS13_ERR_NO_CERTIFICATE, 0, | 534 | tls13_set_errorx(ctx, TLS13_ERR_NO_CERTIFICATE, 0, |
@@ -468,6 +536,9 @@ tls13_server_certificate_send(struct tls13_ctx *ctx, CBB *cbb) | |||
468 | goto err; | 536 | goto err; |
469 | } | 537 | } |
470 | 538 | ||
539 | ctx->hs->cpk = cpk; | ||
540 | ctx->hs->sigalg = sigalg; | ||
541 | |||
471 | if ((chain = cpk->chain) == NULL) | 542 | if ((chain = cpk->chain) == NULL) |
472 | chain = s->ctx->extra_certs; | 543 | chain = s->ctx->extra_certs; |
473 | 544 | ||
@@ -502,27 +573,23 @@ tls13_server_certificate_send(struct tls13_ctx *ctx, CBB *cbb) | |||
502 | int | 573 | int |
503 | tls13_server_certificate_verify_send(struct tls13_ctx *ctx, CBB *cbb) | 574 | tls13_server_certificate_verify_send(struct tls13_ctx *ctx, CBB *cbb) |
504 | { | 575 | { |
505 | SSL *s = ctx->ssl; | 576 | const struct ssl_sigalg *sigalg; |
506 | const struct ssl_sigalg *sigalg = NULL; | ||
507 | uint8_t *sig = NULL, *sig_content = NULL; | 577 | uint8_t *sig = NULL, *sig_content = NULL; |
508 | size_t sig_len, sig_content_len; | 578 | size_t sig_len, sig_content_len; |
509 | EVP_MD_CTX *mdctx = NULL; | 579 | EVP_MD_CTX *mdctx = NULL; |
510 | EVP_PKEY_CTX *pctx; | 580 | EVP_PKEY_CTX *pctx; |
511 | EVP_PKEY *pkey; | 581 | EVP_PKEY *pkey; |
512 | CERT_PKEY *cpk; | 582 | const CERT_PKEY *cpk; |
513 | CBB sig_cbb; | 583 | CBB sig_cbb; |
514 | int ret = 0; | 584 | int ret = 0; |
515 | 585 | ||
516 | memset(&sig_cbb, 0, sizeof(sig_cbb)); | 586 | memset(&sig_cbb, 0, sizeof(sig_cbb)); |
517 | 587 | ||
518 | /* XXX - Need to revisit certificate selection. */ | 588 | if ((cpk = ctx->hs->cpk) == NULL) |
519 | cpk = &s->cert->pkeys[SSL_PKEY_RSA]; | 589 | goto err; |
520 | pkey = cpk->privatekey; | 590 | if ((sigalg = ctx->hs->sigalg) == NULL) |
521 | |||
522 | if ((sigalg = ssl_sigalg_select(s, pkey)) == NULL) { | ||
523 | /* XXX - SSL_R_SIGNATURE_ALGORITHMS_ERROR */ | ||
524 | goto err; | 591 | goto err; |
525 | } | 592 | pkey = cpk->privatekey; |
526 | 593 | ||
527 | if (!CBB_init(&sig_cbb, 0)) | 594 | if (!CBB_init(&sig_cbb, 0)) |
528 | goto err; | 595 | goto err; |
@@ -829,9 +896,9 @@ tls13_client_certificate_verify_recv(struct tls13_ctx *ctx, CBS *cbs) | |||
829 | ret = 1; | 896 | ret = 1; |
830 | 897 | ||
831 | err: | 898 | err: |
832 | if (!ret && ctx->alert == 0) { | 899 | if (!ret && ctx->alert == 0) |
833 | ctx->alert = TLS13_ALERT_DECODE_ERROR; | 900 | ctx->alert = TLS13_ALERT_DECODE_ERROR; |
834 | } | 901 | |
835 | CBB_cleanup(&cbb); | 902 | CBB_cleanup(&cbb); |
836 | EVP_MD_CTX_free(mdctx); | 903 | EVP_MD_CTX_free(mdctx); |
837 | free(sig_content); | 904 | free(sig_content); |