| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "bin/secure_socket.h" | 5 #include "bin/secure_socket.h" |
| 6 | 6 |
| 7 #include <errno.h> | 7 #include <errno.h> |
| 8 #include <fcntl.h> | 8 #include <fcntl.h> |
| 9 #include <sys/stat.h> | 9 #include <sys/stat.h> |
| 10 #include <stdio.h> | 10 #include <stdio.h> |
| (...skipping 490 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 501 DISALLOW_COPY_AND_ASSIGN(ScopedSSLStackType); | 501 DISALLOW_COPY_AND_ASSIGN(ScopedSSLStackType); |
| 502 }; | 502 }; |
| 503 | 503 |
| 504 typedef ScopedSSLType<PKCS12, PKCS12_free> ScopedPKCS12; | 504 typedef ScopedSSLType<PKCS12, PKCS12_free> ScopedPKCS12; |
| 505 typedef ScopedSSLType<X509, X509_free> ScopedX509; | 505 typedef ScopedSSLType<X509, X509_free> ScopedX509; |
| 506 | 506 |
| 507 typedef ScopedSSLStackType<STACK_OF(X509), X509, X509_free> ScopedX509Stack; | 507 typedef ScopedSSLStackType<STACK_OF(X509), X509, X509_free> ScopedX509Stack; |
| 508 typedef ScopedSSLStackType<STACK_OF(X509_NAME), X509_NAME, X509_NAME_free> | 508 typedef ScopedSSLStackType<STACK_OF(X509_NAME), X509_NAME, X509_NAME_free> |
| 509 ScopedX509NAMEStack; | 509 ScopedX509NAMEStack; |
| 510 | 510 |
| 511 |
| 512 // We try reading data as PKCS12 only if reading as PEM was unsuccessful and |
| 513 // if there is no indication that the data is malformed PEM. We assume the data |
| 514 // is malformed PEM if it contains the start line, i.e. a line with ----- BEGIN. |
| 515 static bool TryPKCS12(bool pem_success) { |
| 516 uint32_t last_error = ERR_peek_last_error(); |
| 517 return !pem_success && |
| 518 (ERR_GET_LIB(last_error) == ERR_LIB_PEM) && |
| 519 (ERR_GET_REASON(last_error) == PEM_R_NO_START_LINE); |
| 520 } |
| 521 |
| 522 |
| 511 static EVP_PKEY* GetPrivateKeyPKCS12(BIO* bio, const char* password) { | 523 static EVP_PKEY* GetPrivateKeyPKCS12(BIO* bio, const char* password) { |
| 512 ScopedPKCS12 p12(d2i_PKCS12_bio(bio, NULL)); | 524 ScopedPKCS12 p12(d2i_PKCS12_bio(bio, NULL)); |
| 513 if (p12.get() == NULL) { | 525 if (p12.get() == NULL) { |
| 514 return NULL; | 526 return NULL; |
| 515 } | 527 } |
| 516 | 528 |
| 517 EVP_PKEY* key = NULL; | 529 EVP_PKEY* key = NULL; |
| 518 X509 *cert = NULL; | 530 X509 *cert = NULL; |
| 519 STACK_OF(X509) *ca_certs = NULL; | 531 STACK_OF(X509) *ca_certs = NULL; |
| 520 int status = PKCS12_parse(p12.get(), password, &key, &cert, &ca_certs); | 532 int status = PKCS12_parse(p12.get(), password, &key, &cert, &ca_certs); |
| 521 if (status == 0) { | 533 if (status == 0) { |
| 522 return NULL; | 534 return NULL; |
| 523 } | 535 } |
| 524 | 536 |
| 525 // We only care about the private key. | 537 // We only care about the private key. |
| 526 ScopedX509 delete_cert(cert); | 538 ScopedX509 delete_cert(cert); |
| 527 ScopedX509Stack delete_ca_certs(ca_certs); | 539 ScopedX509Stack delete_ca_certs(ca_certs); |
| 528 return key; | 540 return key; |
| 529 } | 541 } |
| 530 | 542 |
| 531 | 543 |
| 532 static EVP_PKEY* GetPrivateKey(BIO* bio, const char* password) { | 544 static EVP_PKEY* GetPrivateKey(BIO* bio, const char* password) { |
| 533 EVP_PKEY *key = PEM_read_bio_PrivateKey( | 545 EVP_PKEY *key = PEM_read_bio_PrivateKey( |
| 534 bio, NULL, PasswordCallback, const_cast<char*>(password)); | 546 bio, NULL, PasswordCallback, const_cast<char*>(password)); |
| 535 | 547 if (TryPKCS12(key != NULL)) { |
| 536 // If the data doesn't contain the PEM start line, try reading as PKCS12. | |
| 537 uint32_t err = ERR_peek_last_error(); | |
| 538 if ((key == NULL) && | |
| 539 (ERR_GET_LIB(err) == ERR_LIB_PEM) && | |
| 540 (ERR_GET_REASON(err) == PEM_R_NO_START_LINE)) { | |
| 541 // Reset the bio, and clear the error from trying to read as PEM. | 548 // Reset the bio, and clear the error from trying to read as PEM. |
| 542 ERR_clear_error(); | 549 ERR_clear_error(); |
| 543 BIO_reset(bio); | 550 BIO_reset(bio); |
| 544 | 551 |
| 545 // Try to decode as PKCS12 | 552 // Try to decode as PKCS12 |
| 546 key = GetPrivateKeyPKCS12(bio, password); | 553 key = GetPrivateKeyPKCS12(bio, password); |
| 547 } | 554 } |
| 548 return key; | 555 return key; |
| 549 } | 556 } |
| 550 | 557 |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 634 int status = 0; | 641 int status = 0; |
| 635 X509* cert = NULL; | 642 X509* cert = NULL; |
| 636 while ((cert = PEM_read_bio_X509(bio, NULL, NULL, NULL)) != NULL) { | 643 while ((cert = PEM_read_bio_X509(bio, NULL, NULL, NULL)) != NULL) { |
| 637 status = X509_STORE_add_cert(store, cert); | 644 status = X509_STORE_add_cert(store, cert); |
| 638 if (status == 0) { | 645 if (status == 0) { |
| 639 X509_free(cert); | 646 X509_free(cert); |
| 640 return status; | 647 return status; |
| 641 } | 648 } |
| 642 } | 649 } |
| 643 | 650 |
| 651 // If bio does not contain PEM data, the first call to PEM_read_bio_X509 will |
| 652 // return NULL, and the while-loop will exit while status is still 0. |
| 644 uint32_t err = ERR_peek_last_error(); | 653 uint32_t err = ERR_peek_last_error(); |
| 645 if ((ERR_GET_LIB(err) != ERR_LIB_PEM) || | 654 if ((ERR_GET_LIB(err) != ERR_LIB_PEM) || |
| 646 (ERR_GET_REASON(err) != PEM_R_NO_START_LINE)) { | 655 (ERR_GET_REASON(err) != PEM_R_NO_START_LINE)) { |
| 647 // Some real error happened. | 656 // If bio contains data that is trying to be PEM but is malformed, then |
| 657 // this case will be triggered. |
| 648 status = 0; | 658 status = 0; |
| 649 } | 659 } |
| 650 | 660 |
| 651 return status; | 661 return status; |
| 652 } | 662 } |
| 653 | 663 |
| 654 | 664 |
| 655 static int SetTrustedCertificatesBytes(SSL_CTX* context, BIO* bio) { | 665 static int SetTrustedCertificatesBytes(SSL_CTX* context, BIO* bio) { |
| 656 int status = SetTrustedCertificatesBytesPEM(context, bio); | 666 int status = SetTrustedCertificatesBytesPEM(context, bio); |
| 657 uint32_t err = ERR_peek_last_error(); | 667 if (TryPKCS12(status != 0)) { |
| 658 if ((status == 0) && | |
| 659 (ERR_GET_LIB(err) == ERR_LIB_PEM) && | |
| 660 (ERR_GET_REASON(err) == PEM_R_NO_START_LINE)) { | |
| 661 ERR_clear_error(); | 668 ERR_clear_error(); |
| 662 BIO_reset(bio); | 669 BIO_reset(bio); |
| 663 status = SetTrustedCertificatesBytesPKCS12(context, bio); | 670 status = SetTrustedCertificatesBytesPKCS12(context, bio); |
| 664 } else if (status != 0) { | 671 } else if (status != 0) { |
| 665 // The PEM file was successfully parsed. | 672 // The PEM file was successfully parsed. |
| 666 ERR_clear_error(); | 673 ERR_clear_error(); |
| 667 } | 674 } |
| 668 return status; | 675 return status; |
| 669 } | 676 } |
| 670 | 677 |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 773 status = SSL_CTX_add0_chain_cert(context, ca); | 780 status = SSL_CTX_add0_chain_cert(context, ca); |
| 774 if (status == 0) { | 781 if (status == 0) { |
| 775 X509_free(ca); | 782 X509_free(ca); |
| 776 return status; | 783 return status; |
| 777 } | 784 } |
| 778 // Note that we must not free `ca` if it was successfully added to the | 785 // Note that we must not free `ca` if it was successfully added to the |
| 779 // chain. We must free the main certificate x509, though since its reference | 786 // chain. We must free the main certificate x509, though since its reference |
| 780 // count is increased by SSL_CTX_use_certificate. | 787 // count is increased by SSL_CTX_use_certificate. |
| 781 } | 788 } |
| 782 | 789 |
| 790 // If bio does not contain PEM data, the first call to PEM_read_bio_X509 will |
| 791 // return NULL, and the while-loop will exit while status is still 0. |
| 783 uint32_t err = ERR_peek_last_error(); | 792 uint32_t err = ERR_peek_last_error(); |
| 784 if ((ERR_GET_LIB(err) != ERR_LIB_PEM) || | 793 if ((ERR_GET_LIB(err) != ERR_LIB_PEM) || |
| 785 (ERR_GET_REASON(err) != PEM_R_NO_START_LINE)) { | 794 (ERR_GET_REASON(err) != PEM_R_NO_START_LINE)) { |
| 786 // Some real error happened. | 795 // If bio contains data that is trying to be PEM but is malformed, then |
| 796 // this case will be triggered. |
| 787 status = 0; | 797 status = 0; |
| 788 } | 798 } |
| 789 | 799 |
| 790 return status; | 800 return status; |
| 791 } | 801 } |
| 792 | 802 |
| 793 | 803 |
| 794 static int UseChainBytes(SSL_CTX* context, BIO* bio) { | 804 static int UseChainBytes(SSL_CTX* context, BIO* bio) { |
| 795 int status = UseChainBytesPEM(context, bio); | 805 int status = UseChainBytesPEM(context, bio); |
| 796 uint32_t err = ERR_peek_last_error(); | 806 if (TryPKCS12(status != 0)) { |
| 797 if ((status == 0) && | |
| 798 (ERR_GET_LIB(err) == ERR_LIB_PEM) && | |
| 799 (ERR_GET_REASON(err) == PEM_R_NO_START_LINE)) { | |
| 800 ERR_clear_error(); | 807 ERR_clear_error(); |
| 801 BIO_reset(bio); | 808 BIO_reset(bio); |
| 802 status = UseChainBytesPKCS12(context, bio); | 809 status = UseChainBytesPKCS12(context, bio); |
| 803 } else if (status != 0) { | 810 } else if (status != 0) { |
| 804 // The PEM file was successfully parsed. | 811 // The PEM file was successfully read. |
| 805 ERR_clear_error(); | 812 ERR_clear_error(); |
| 806 } | 813 } |
| 807 return status; | 814 return status; |
| 808 } | 815 } |
| 809 | 816 |
| 810 | 817 |
| 811 void FUNCTION_NAME(SecurityContext_UseCertificateChainBytes)( | 818 void FUNCTION_NAME(SecurityContext_UseCertificateChainBytes)( |
| 812 Dart_NativeArguments args) { | 819 Dart_NativeArguments args) { |
| 813 SSL_CTX* context = GetSecurityContext(args); | 820 SSL_CTX* context = GetSecurityContext(args); |
| 814 int status; | 821 int status; |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 905 } | 912 } |
| 906 | 913 |
| 907 // Duplicate the name to put it on the stack. | 914 // Duplicate the name to put it on the stack. |
| 908 x509_name = X509_NAME_dup(x509_name); | 915 x509_name = X509_NAME_dup(x509_name); |
| 909 if (x509_name == NULL) { | 916 if (x509_name == NULL) { |
| 910 return NULL; | 917 return NULL; |
| 911 } | 918 } |
| 912 sk_X509_NAME_push(result.get(), x509_name); | 919 sk_X509_NAME_push(result.get(), x509_name); |
| 913 } | 920 } |
| 914 | 921 |
| 922 if (sk_X509_NAME_num(result.get()) == 0) { |
| 923 // The data was not PEM. |
| 924 return NULL; |
| 925 } |
| 926 |
| 915 uint32_t err = ERR_peek_last_error(); | 927 uint32_t err = ERR_peek_last_error(); |
| 916 if ((ERR_GET_LIB(err) != ERR_LIB_PEM) || | 928 if ((ERR_GET_LIB(err) != ERR_LIB_PEM) || |
| 917 (ERR_GET_REASON(err) != PEM_R_NO_START_LINE)) { | 929 (ERR_GET_REASON(err) != PEM_R_NO_START_LINE)) { |
| 918 // Some real error happened. | 930 // The data was trying to be PEM, but was malformed. |
| 919 return NULL; | 931 return NULL; |
| 920 } | 932 } |
| 921 | 933 |
| 922 return result.release(); | 934 return result.release(); |
| 923 } | 935 } |
| 924 | 936 |
| 925 | 937 |
| 926 static STACK_OF(X509_NAME)* GetCertificateNames(BIO* bio) { | 938 static STACK_OF(X509_NAME)* GetCertificateNames(BIO* bio) { |
| 927 STACK_OF(X509_NAME)* result = GetCertificateNamesPEM(bio); | 939 STACK_OF(X509_NAME)* result = GetCertificateNamesPEM(bio); |
| 928 uint32_t err = ERR_peek_last_error(); | 940 if (TryPKCS12(result != NULL)) { |
| 929 if ((result == NULL) && | |
| 930 (ERR_GET_LIB(err) == ERR_LIB_PEM) && | |
| 931 (ERR_GET_REASON(err) == PEM_R_NO_START_LINE)) { | |
| 932 ERR_clear_error(); | 941 ERR_clear_error(); |
| 933 BIO_reset(bio); | 942 BIO_reset(bio); |
| 934 result = GetCertificateNamesPKCS12(bio); | 943 result = GetCertificateNamesPKCS12(bio); |
| 935 } else if (result != NULL) { | 944 } else if (result != NULL) { |
| 936 // The PEM file was successfully parsed. | 945 // The PEM file was successfully parsed. |
| 937 ERR_clear_error(); | 946 ERR_clear_error(); |
| 938 } | 947 } |
| 939 return result; | 948 return result; |
| 940 } | 949 } |
| 941 | 950 |
| (...skipping 633 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1575 } else { | 1584 } else { |
| 1576 if (SSL_LOG_DATA) Log::Print( | 1585 if (SSL_LOG_DATA) Log::Print( |
| 1577 "WriteEncrypted BIO_read wrote %d bytes\n", bytes_processed); | 1586 "WriteEncrypted BIO_read wrote %d bytes\n", bytes_processed); |
| 1578 } | 1587 } |
| 1579 } | 1588 } |
| 1580 return bytes_processed; | 1589 return bytes_processed; |
| 1581 } | 1590 } |
| 1582 | 1591 |
| 1583 } // namespace bin | 1592 } // namespace bin |
| 1584 } // namespace dart | 1593 } // namespace dart |
| OLD | NEW |