diff options
author | jsing <> | 2019-02-11 17:48:15 +0000 |
---|---|---|
committer | jsing <> | 2019-02-11 17:48:15 +0000 |
commit | 340ba8d1a0d10761e6beb200d6a90332c7a7d3ba (patch) | |
tree | ea2ea6e9de0d1e517cc0729929682b8ed2530317 | |
parent | bc7cd6de243436fe1c7d5d876b63335ee03c3250 (diff) | |
download | openbsd-340ba8d1a0d10761e6beb200d6a90332c7a7d3ba.tar.gz openbsd-340ba8d1a0d10761e6beb200d6a90332c7a7d3ba.tar.bz2 openbsd-340ba8d1a0d10761e6beb200d6a90332c7a7d3ba.zip |
Implement handling of Certificate and CertificateVerify messages.
This allows the TLS 1.3 client to process the certificates that the server
has sent and verify that the server has possession of the private key.
ok tb@
-rw-r--r-- | src/lib/libssl/tls13_client.c | 214 | ||||
-rw-r--r-- | src/lib/libssl/tls13_handshake.c | 31 |
2 files changed, 214 insertions, 31 deletions
diff --git a/src/lib/libssl/tls13_client.c b/src/lib/libssl/tls13_client.c index 6578438c78..d15ab65105 100644 --- a/src/lib/libssl/tls13_client.c +++ b/src/lib/libssl/tls13_client.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: tls13_client.c,v 1.5 2019/02/09 15:26:15 jsing Exp $ */ | 1 | /* $OpenBSD: tls13_client.c,v 1.6 2019/02/11 17:48:15 jsing Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2018, 2019 Joel Sing <jsing@openbsd.org> | 3 | * Copyright (c) 2018, 2019 Joel Sing <jsing@openbsd.org> |
4 | * | 4 | * |
@@ -343,3 +343,215 @@ tls13_server_encrypted_extensions_recv(struct tls13_ctx *ctx) | |||
343 | 343 | ||
344 | return 0; | 344 | return 0; |
345 | } | 345 | } |
346 | |||
347 | int | ||
348 | tls13_server_certificate_request_recv(struct tls13_ctx *ctx) | ||
349 | { | ||
350 | /* | ||
351 | * Thanks to poor state design in the RFC, this function can be called | ||
352 | * when we actually have a certificate message instead of a certificate | ||
353 | * request... in that case we call the certificate handler after | ||
354 | * switching state, to avoid advancing state. | ||
355 | */ | ||
356 | if (tls13_handshake_msg_type(ctx->hs_msg) == TLS13_MT_CERTIFICATE) { | ||
357 | ctx->handshake_stage.hs_type |= WITHOUT_CR; | ||
358 | return tls13_server_certificate_recv(ctx); | ||
359 | } | ||
360 | |||
361 | /* XXX - unimplemented. */ | ||
362 | |||
363 | return 0; | ||
364 | } | ||
365 | |||
366 | int | ||
367 | tls13_server_certificate_recv(struct tls13_ctx *ctx) | ||
368 | { | ||
369 | CBS cbs, cert_request_context, cert_list, cert_data, cert_exts; | ||
370 | struct stack_st_X509 *certs = NULL; | ||
371 | SSL *s = ctx->ssl; | ||
372 | X509 *cert = NULL; | ||
373 | EVP_PKEY *pkey; | ||
374 | const uint8_t *p; | ||
375 | int cert_idx; | ||
376 | int ret = 0; | ||
377 | |||
378 | if ((certs = sk_X509_new_null()) == NULL) | ||
379 | goto err; | ||
380 | |||
381 | if (!tls13_handshake_msg_content(ctx->hs_msg, &cbs)) | ||
382 | goto err; | ||
383 | |||
384 | if (!CBS_get_u8_length_prefixed(&cbs, &cert_request_context)) | ||
385 | goto err; | ||
386 | if (CBS_len(&cert_request_context) != 0) | ||
387 | goto err; | ||
388 | if (!CBS_get_u24_length_prefixed(&cbs, &cert_list)) | ||
389 | goto err; | ||
390 | if (CBS_len(&cbs) != 0) | ||
391 | goto err; | ||
392 | |||
393 | while (CBS_len(&cert_list) > 0) { | ||
394 | if (!CBS_get_u24_length_prefixed(&cert_list, &cert_data)) | ||
395 | goto err; | ||
396 | if (!CBS_get_u16_length_prefixed(&cert_list, &cert_exts)) | ||
397 | goto err; | ||
398 | |||
399 | p = CBS_data(&cert_data); | ||
400 | if ((cert = d2i_X509(NULL, &p, CBS_len(&cert_data))) == NULL) | ||
401 | goto err; | ||
402 | if (p != CBS_data(&cert_data) + CBS_len(&cert_data)) | ||
403 | goto err; | ||
404 | |||
405 | if (!sk_X509_push(certs, cert)) | ||
406 | goto err; | ||
407 | |||
408 | cert = NULL; | ||
409 | } | ||
410 | |||
411 | /* | ||
412 | * At this stage we still have no proof of possession. As such, it would | ||
413 | * be preferable to keep the chain and verify once we have successfully | ||
414 | * processed the CertificateVerify message. | ||
415 | */ | ||
416 | if (ssl_verify_cert_chain(s, certs) <= 0 && | ||
417 | s->verify_mode != SSL_VERIFY_NONE) { | ||
418 | /* XXX send alert */ | ||
419 | goto err; | ||
420 | } | ||
421 | ERR_clear_error(); | ||
422 | |||
423 | cert = sk_X509_value(certs, 0); | ||
424 | X509_up_ref(cert); | ||
425 | |||
426 | if ((pkey = X509_get0_pubkey(cert)) == NULL) | ||
427 | goto err; | ||
428 | if (EVP_PKEY_missing_parameters(pkey)) | ||
429 | goto err; | ||
430 | if ((cert_idx = ssl_cert_type(cert, pkey)) < 0) | ||
431 | goto err; | ||
432 | |||
433 | ssl_sess_cert_free(SSI(s)->sess_cert); | ||
434 | if ((SSI(s)->sess_cert = ssl_sess_cert_new()) == NULL) | ||
435 | goto err; | ||
436 | |||
437 | SSI(s)->sess_cert->cert_chain = certs; | ||
438 | certs = NULL; | ||
439 | |||
440 | X509_up_ref(cert); | ||
441 | SSI(s)->sess_cert->peer_pkeys[cert_idx].x509 = cert; | ||
442 | SSI(s)->sess_cert->peer_key = &(SSI(s)->sess_cert->peer_pkeys[cert_idx]); | ||
443 | |||
444 | X509_free(s->session->peer); | ||
445 | |||
446 | X509_up_ref(cert); | ||
447 | s->session->peer = cert; | ||
448 | s->session->verify_result = s->verify_result; | ||
449 | |||
450 | ret = 1; | ||
451 | |||
452 | err: | ||
453 | sk_X509_pop_free(certs, X509_free); | ||
454 | X509_free(cert); | ||
455 | |||
456 | return ret; | ||
457 | } | ||
458 | |||
459 | /* | ||
460 | * Certificate Verify padding - RFC 8446 section 4.4.3. | ||
461 | */ | ||
462 | static uint8_t cert_verify_pad[64] = { | ||
463 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, | ||
464 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, | ||
465 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, | ||
466 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, | ||
467 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, | ||
468 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, | ||
469 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, | ||
470 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, | ||
471 | }; | ||
472 | |||
473 | static uint8_t server_cert_verify_context[] = "TLS 1.3, server CertificateVerify"; | ||
474 | |||
475 | int | ||
476 | tls13_server_certificate_verify_recv(struct tls13_ctx *ctx) | ||
477 | { | ||
478 | const struct ssl_sigalg *sigalg; | ||
479 | uint16_t signature_scheme; | ||
480 | uint8_t *sig_content = NULL; | ||
481 | size_t sig_content_len; | ||
482 | EVP_MD_CTX *mdctx = NULL; | ||
483 | EVP_PKEY_CTX *pctx; | ||
484 | EVP_PKEY *pkey; | ||
485 | X509 *cert; | ||
486 | CBS cbs, signature; | ||
487 | CBB cbb; | ||
488 | int ret = 0; | ||
489 | |||
490 | memset(&cbb, 0, sizeof(cbb)); | ||
491 | |||
492 | if (!tls13_handshake_msg_content(ctx->hs_msg, &cbs)) | ||
493 | goto err; | ||
494 | |||
495 | if (!CBS_get_u16(&cbs, &signature_scheme)) | ||
496 | goto err; | ||
497 | if (!CBS_get_u16_length_prefixed(&cbs, &signature)) | ||
498 | goto err; | ||
499 | if (CBS_len(&cbs) != 0) | ||
500 | goto err; | ||
501 | |||
502 | if ((sigalg = ssl_sigalg(signature_scheme, tls13_sigalgs, | ||
503 | tls13_sigalgs_len)) == NULL) | ||
504 | goto err; | ||
505 | |||
506 | if (!CBB_init(&cbb, 0)) | ||
507 | goto err; | ||
508 | if (!CBB_add_bytes(&cbb, cert_verify_pad, sizeof(cert_verify_pad))) | ||
509 | goto err; | ||
510 | if (!CBB_add_bytes(&cbb, server_cert_verify_context, | ||
511 | strlen(server_cert_verify_context))) | ||
512 | goto err; | ||
513 | if (!CBB_add_u8(&cbb, 0)) | ||
514 | goto err; | ||
515 | if (!CBB_add_bytes(&cbb, ctx->hs->transcript_hash, | ||
516 | ctx->hs->transcript_hash_len)) | ||
517 | goto err; | ||
518 | if (!CBB_finish(&cbb, &sig_content, &sig_content_len)) | ||
519 | goto err; | ||
520 | |||
521 | if ((cert = ctx->ssl->session->peer) == NULL) | ||
522 | goto err; | ||
523 | if ((pkey = X509_get0_pubkey(cert)) == NULL) | ||
524 | goto err; | ||
525 | if (!ssl_sigalg_pkey_ok(sigalg, pkey)) | ||
526 | goto err; | ||
527 | |||
528 | if (CBS_len(&signature) > EVP_PKEY_size(pkey)) | ||
529 | goto err; | ||
530 | |||
531 | if ((mdctx = EVP_MD_CTX_new()) == NULL) | ||
532 | goto err; | ||
533 | if (!EVP_DigestVerifyInit(mdctx, &pctx, sigalg->md(), NULL, pkey)) | ||
534 | goto err; | ||
535 | if (sigalg->flags & SIGALG_FLAG_RSA_PSS) { | ||
536 | if (!EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PSS_PADDING)) | ||
537 | goto err; | ||
538 | if (!EVP_PKEY_CTX_set_rsa_pss_saltlen(pctx, -1)) | ||
539 | goto err; | ||
540 | } | ||
541 | if (!EVP_DigestVerifyUpdate(mdctx, sig_content, sig_content_len)) | ||
542 | goto err; | ||
543 | if (EVP_DigestVerifyFinal(mdctx, CBS_data(&signature), | ||
544 | CBS_len(&signature)) <= 0) { | ||
545 | /* XXX - send alert. */ | ||
546 | goto err; | ||
547 | } | ||
548 | |||
549 | ret = 1; | ||
550 | |||
551 | err: | ||
552 | CBB_cleanup(&cbb); | ||
553 | EVP_MD_CTX_free(mdctx); | ||
554 | free(sig_content); | ||
555 | |||
556 | return ret; | ||
557 | } | ||
diff --git a/src/lib/libssl/tls13_handshake.c b/src/lib/libssl/tls13_handshake.c index 8d5b0e3516..3ebf1e9d73 100644 --- a/src/lib/libssl/tls13_handshake.c +++ b/src/lib/libssl/tls13_handshake.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: tls13_handshake.c,v 1.25 2019/02/10 13:04:29 jsing Exp $ */ | 1 | /* $OpenBSD: tls13_handshake.c,v 1.26 2019/02/11 17:48:15 jsing Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2018-2019 Theo Buehler <tb@openbsd.org> | 3 | * Copyright (c) 2018-2019 Theo Buehler <tb@openbsd.org> |
4 | * Copyright (c) 2019 Joel Sing <jsing@openbsd.org> | 4 | * Copyright (c) 2019 Joel Sing <jsing@openbsd.org> |
@@ -491,35 +491,12 @@ tls13_server_encrypted_extensions_send(struct tls13_ctx *ctx) | |||
491 | } | 491 | } |
492 | 492 | ||
493 | int | 493 | int |
494 | tls13_server_certificate_recv(struct tls13_ctx *ctx) | ||
495 | { | ||
496 | return 0; | ||
497 | } | ||
498 | |||
499 | int | ||
500 | tls13_server_certificate_send(struct tls13_ctx *ctx) | 494 | tls13_server_certificate_send(struct tls13_ctx *ctx) |
501 | { | 495 | { |
502 | return 0; | 496 | return 0; |
503 | } | 497 | } |
504 | 498 | ||
505 | int | 499 | int |
506 | tls13_server_certificate_request_recv(struct tls13_ctx *ctx) | ||
507 | { | ||
508 | /* | ||
509 | * Thanks to poor state design in the RFC, this function can be called | ||
510 | * when we actually have a certificate message instead of a certificate | ||
511 | * request... in that case we call the certificate handler after | ||
512 | * switching state, to avoid advancing state. | ||
513 | */ | ||
514 | if (tls13_handshake_msg_type(ctx->hs_msg) == TLS13_MT_CERTIFICATE) { | ||
515 | ctx->handshake_stage.hs_type |= WITHOUT_CR; | ||
516 | return tls13_server_certificate_recv(ctx); | ||
517 | } | ||
518 | |||
519 | return 0; | ||
520 | } | ||
521 | |||
522 | int | ||
523 | tls13_server_certificate_request_send(struct tls13_ctx *ctx) | 500 | tls13_server_certificate_request_send(struct tls13_ctx *ctx) |
524 | { | 501 | { |
525 | return 0; | 502 | return 0; |
@@ -532,12 +509,6 @@ tls13_server_certificate_verify_send(struct tls13_ctx *ctx) | |||
532 | } | 509 | } |
533 | 510 | ||
534 | int | 511 | int |
535 | tls13_server_certificate_verify_recv(struct tls13_ctx *ctx) | ||
536 | { | ||
537 | return 0; | ||
538 | } | ||
539 | |||
540 | int | ||
541 | tls13_server_finished_recv(struct tls13_ctx *ctx) | 512 | tls13_server_finished_recv(struct tls13_ctx *ctx) |
542 | { | 513 | { |
543 | return 0; | 514 | return 0; |