diff options
author | beck <> | 2020-01-26 03:55:22 +0000 |
---|---|---|
committer | beck <> | 2020-01-26 03:55:22 +0000 |
commit | 5b2b58a4eec035a63a1914d4fdbe93163cf57a88 (patch) | |
tree | 08dac32de7bda745ce57f491a7995709e61abe97 /src | |
parent | 1d09551b34092455ded15acaa7abfb96b5b6eed8 (diff) | |
download | openbsd-5b2b58a4eec035a63a1914d4fdbe93163cf57a88.tar.gz openbsd-5b2b58a4eec035a63a1914d4fdbe93163cf57a88.tar.bz2 openbsd-5b2b58a4eec035a63a1914d4fdbe93163cf57a88.zip |
Add server side support for requesting client certificates in tls 1.3
ok jsing@
Diffstat (limited to 'src')
-rw-r--r-- | src/lib/libssl/tls13_server.c | 177 |
1 files changed, 173 insertions, 4 deletions
diff --git a/src/lib/libssl/tls13_server.c b/src/lib/libssl/tls13_server.c index 64c9741d7d..e5e029c998 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.18 2020/01/26 03:38:24 beck Exp $ */ | 1 | /* $OpenBSD: tls13_server.c,v 1.19 2020/01/26 03:55:22 beck 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> |
@@ -314,13 +314,179 @@ tls13_client_end_of_early_data_recv(struct tls13_ctx *ctx, CBS *cbs) | |||
314 | int | 314 | int |
315 | tls13_client_certificate_recv(struct tls13_ctx *ctx, CBS *cbs) | 315 | tls13_client_certificate_recv(struct tls13_ctx *ctx, CBS *cbs) |
316 | { | 316 | { |
317 | return 0; | 317 | CBS cert_request_context, cert_list, cert_data, cert_exts; |
318 | struct stack_st_X509 *certs = NULL; | ||
319 | SSL *s = ctx->ssl; | ||
320 | X509 *cert = NULL; | ||
321 | EVP_PKEY *pkey; | ||
322 | const uint8_t *p; | ||
323 | int cert_idx; | ||
324 | int ret = 0; | ||
325 | |||
326 | if (!CBS_get_u8_length_prefixed(cbs, &cert_request_context)) | ||
327 | goto err; | ||
328 | if (CBS_len(&cert_request_context) != 0) | ||
329 | goto err; | ||
330 | if (!CBS_get_u24_length_prefixed(cbs, &cert_list)) | ||
331 | goto err; | ||
332 | |||
333 | if (CBS_len(&cert_list) == 0) | ||
334 | return 1; | ||
335 | |||
336 | if ((certs = sk_X509_new_null()) == NULL) | ||
337 | goto err; | ||
338 | while (CBS_len(&cert_list) > 0) { | ||
339 | if (!CBS_get_u24_length_prefixed(&cert_list, &cert_data)) | ||
340 | goto err; | ||
341 | if (!CBS_get_u16_length_prefixed(&cert_list, &cert_exts)) | ||
342 | goto err; | ||
343 | |||
344 | p = CBS_data(&cert_data); | ||
345 | if ((cert = d2i_X509(NULL, &p, CBS_len(&cert_data))) == NULL) | ||
346 | goto err; | ||
347 | if (p != CBS_data(&cert_data) + CBS_len(&cert_data)) | ||
348 | goto err; | ||
349 | |||
350 | if (!sk_X509_push(certs, cert)) | ||
351 | goto err; | ||
352 | |||
353 | cert = NULL; | ||
354 | } | ||
355 | |||
356 | /* | ||
357 | * At this stage we still have no proof of possession. As such, it would | ||
358 | * be preferable to keep the chain and verify once we have successfully | ||
359 | * processed the CertificateVerify message. | ||
360 | */ | ||
361 | if (ssl_verify_cert_chain(s, certs) <= 0 && | ||
362 | s->verify_mode != SSL_VERIFY_NONE) { | ||
363 | ctx->alert = ssl_verify_alarm_type(s->verify_result); | ||
364 | tls13_set_errorx(ctx, TLS13_ERR_VERIFY_FAILED, 0, | ||
365 | "failed to verify peer certificate", NULL); | ||
366 | goto err; | ||
367 | } | ||
368 | ERR_clear_error(); | ||
369 | |||
370 | cert = sk_X509_value(certs, 0); | ||
371 | X509_up_ref(cert); | ||
372 | |||
373 | if ((pkey = X509_get0_pubkey(cert)) == NULL) | ||
374 | goto err; | ||
375 | if (EVP_PKEY_missing_parameters(pkey)) | ||
376 | goto err; | ||
377 | if ((cert_idx = ssl_cert_type(cert, pkey)) < 0) | ||
378 | goto err; | ||
379 | |||
380 | ssl_sess_cert_free(SSI(s)->sess_cert); | ||
381 | if ((SSI(s)->sess_cert = ssl_sess_cert_new()) == NULL) | ||
382 | goto err; | ||
383 | |||
384 | SSI(s)->sess_cert->cert_chain = certs; | ||
385 | certs = NULL; | ||
386 | |||
387 | X509_up_ref(cert); | ||
388 | SSI(s)->sess_cert->peer_pkeys[cert_idx].x509 = cert; | ||
389 | SSI(s)->sess_cert->peer_key = &(SSI(s)->sess_cert->peer_pkeys[cert_idx]); | ||
390 | |||
391 | X509_free(s->session->peer); | ||
392 | |||
393 | X509_up_ref(cert); | ||
394 | s->session->peer = cert; | ||
395 | s->session->verify_result = s->verify_result; | ||
396 | |||
397 | ctx->handshake_stage.hs_type |= WITH_CCV; | ||
398 | ret = 1; | ||
399 | |||
400 | err: | ||
401 | sk_X509_pop_free(certs, X509_free); | ||
402 | X509_free(cert); | ||
403 | |||
404 | return ret; | ||
318 | } | 405 | } |
319 | 406 | ||
320 | int | 407 | int |
321 | tls13_client_certificate_verify_recv(struct tls13_ctx *ctx, CBS *cbs) | 408 | tls13_client_certificate_verify_recv(struct tls13_ctx *ctx, CBS *cbs) |
322 | { | 409 | { |
323 | return 0; | 410 | const struct ssl_sigalg *sigalg; |
411 | uint16_t signature_scheme; | ||
412 | uint8_t *sig_content = NULL; | ||
413 | size_t sig_content_len; | ||
414 | EVP_MD_CTX *mdctx = NULL; | ||
415 | EVP_PKEY_CTX *pctx; | ||
416 | EVP_PKEY *pkey; | ||
417 | X509 *cert; | ||
418 | CBS signature; | ||
419 | CBB cbb; | ||
420 | int ret = 0; | ||
421 | |||
422 | memset(&cbb, 0, sizeof(cbb)); | ||
423 | |||
424 | if (!CBS_get_u16(cbs, &signature_scheme)) | ||
425 | goto err; | ||
426 | if (!CBS_get_u16_length_prefixed(cbs, &signature)) | ||
427 | goto err; | ||
428 | |||
429 | if ((sigalg = ssl_sigalg(signature_scheme, tls13_sigalgs, | ||
430 | tls13_sigalgs_len)) == NULL) | ||
431 | goto err; | ||
432 | |||
433 | if (!CBB_init(&cbb, 0)) | ||
434 | goto err; | ||
435 | if (!CBB_add_bytes(&cbb, tls13_cert_verify_pad, | ||
436 | sizeof(tls13_cert_verify_pad))) | ||
437 | goto err; | ||
438 | if (!CBB_add_bytes(&cbb, tls13_cert_client_verify_context, | ||
439 | strlen(tls13_cert_client_verify_context))) | ||
440 | goto err; | ||
441 | if (!CBB_add_u8(&cbb, 0)) | ||
442 | goto err; | ||
443 | if (!CBB_add_bytes(&cbb, ctx->hs->transcript_hash, | ||
444 | ctx->hs->transcript_hash_len)) | ||
445 | goto err; | ||
446 | if (!CBB_finish(&cbb, &sig_content, &sig_content_len)) | ||
447 | goto err; | ||
448 | |||
449 | if ((cert = ctx->ssl->session->peer) == NULL) | ||
450 | goto err; | ||
451 | if ((pkey = X509_get0_pubkey(cert)) == NULL) | ||
452 | goto err; | ||
453 | if (!ssl_sigalg_pkey_ok(sigalg, pkey, 1)) | ||
454 | goto err; | ||
455 | |||
456 | if (CBS_len(&signature) > EVP_PKEY_size(pkey)) | ||
457 | goto err; | ||
458 | |||
459 | if ((mdctx = EVP_MD_CTX_new()) == NULL) | ||
460 | goto err; | ||
461 | if (!EVP_DigestVerifyInit(mdctx, &pctx, sigalg->md(), NULL, pkey)) | ||
462 | goto err; | ||
463 | if (sigalg->flags & SIGALG_FLAG_RSA_PSS) { | ||
464 | if (!EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PSS_PADDING)) | ||
465 | goto err; | ||
466 | if (!EVP_PKEY_CTX_set_rsa_pss_saltlen(pctx, -1)) | ||
467 | goto err; | ||
468 | } | ||
469 | if (!EVP_DigestVerifyUpdate(mdctx, sig_content, sig_content_len)) { | ||
470 | ctx->alert = TLS1_AD_DECRYPT_ERROR; | ||
471 | goto err; | ||
472 | } | ||
473 | if (EVP_DigestVerifyFinal(mdctx, CBS_data(&signature), | ||
474 | CBS_len(&signature)) <= 0) { | ||
475 | ctx->alert = TLS1_AD_DECRYPT_ERROR; | ||
476 | goto err; | ||
477 | } | ||
478 | |||
479 | ret = 1; | ||
480 | |||
481 | err: | ||
482 | if (!ret && ctx->alert == 0) { | ||
483 | ctx->alert = TLS1_AD_DECODE_ERROR; | ||
484 | } | ||
485 | CBB_cleanup(&cbb); | ||
486 | EVP_MD_CTX_free(mdctx); | ||
487 | free(sig_content); | ||
488 | |||
489 | return ret; | ||
324 | } | 490 | } |
325 | 491 | ||
326 | int | 492 | int |
@@ -439,7 +605,10 @@ tls13_server_hello_sent(struct tls13_ctx *ctx) | |||
439 | &secrets->server_handshake_traffic)) | 605 | &secrets->server_handshake_traffic)) |
440 | goto err; | 606 | goto err; |
441 | 607 | ||
442 | ctx->handshake_stage.hs_type |= NEGOTIATED | WITHOUT_CR; | 608 | ctx->handshake_stage.hs_type |= NEGOTIATED; |
609 | if (!(SSL_get_verify_mode(s) & SSL_VERIFY_PEER)) | ||
610 | ctx->handshake_stage.hs_type |= WITHOUT_CR; | ||
611 | |||
443 | ret = 1; | 612 | ret = 1; |
444 | 613 | ||
445 | err: | 614 | err: |