summaryrefslogtreecommitdiffstats
path: root/src/userpref.c
diff options
context:
space:
mode:
authorGravatar Nikias Bassen2011-09-14 18:55:59 +0200
committerGravatar Martin Szulecki2012-03-19 01:43:29 +0100
commit8b1af4cf80eff619d3465925dce7fe572fc09224 (patch)
tree1fc167114f574c2ff3470c97d6ce74938778f9db /src/userpref.c
parent294cf69b256419e407b1eac04634752412ee7756 (diff)
downloadlibimobiledevice-8b1af4cf80eff619d3465925dce7fe572fc09224.tar.gz
libimobiledevice-8b1af4cf80eff619d3465925dce7fe572fc09224.tar.bz2
Add OpenSSL support
Diffstat (limited to 'src/userpref.c')
-rw-r--r--src/userpref.c233
1 files changed, 199 insertions, 34 deletions
diff --git a/src/userpref.c b/src/userpref.c
index f4e9fe6..409eb27 100644
--- a/src/userpref.c
+++ b/src/userpref.c
@@ -19,13 +19,23 @@
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */ 20 */
21 21
22#ifdef HAVE_CONFIG_H
23#include <config.h>
24#endif
22#include <stdio.h> 25#include <stdio.h>
23#include <stdint.h> 26#include <stdint.h>
24#include <stdlib.h> 27#include <stdlib.h>
25#include <string.h> 28#include <string.h>
29#ifdef HAVE_OPENSSL
30#include <openssl/pem.h>
31#include <openssl/rsa.h>
32#include <openssl/x509.h>
33#include <openssl/x509v3.h>
34#else
26#include <gnutls/gnutls.h> 35#include <gnutls/gnutls.h>
27#include <gnutls/x509.h> 36#include <gnutls/x509.h>
28#include <gcrypt.h> 37#include <gcrypt.h>
38#endif
29 39
30#include <dirent.h> 40#include <dirent.h>
31#include <libgen.h> 41#include <libgen.h>
@@ -526,7 +536,7 @@ userpref_error_t userpref_get_paired_uuids(char ***list, unsigned int *count)
526 * @return 1 on success and 0 if no public key is given or if it has already 536 * @return 1 on success and 0 if no public key is given or if it has already
527 * been marked as connected previously. 537 * been marked as connected previously.
528 */ 538 */
529userpref_error_t userpref_set_device_public_key(const char *uuid, gnutls_datum_t public_key) 539userpref_error_t userpref_set_device_public_key(const char *uuid, key_data_t public_key)
530{ 540{
531 if (NULL == public_key.data) 541 if (NULL == public_key.data)
532 return USERPREF_E_INVALID_ARG; 542 return USERPREF_E_INVALID_ARG;
@@ -583,14 +593,14 @@ userpref_error_t userpref_remove_device_public_key(const char *uuid)
583} 593}
584 594
585/** 595/**
586 * Private function which reads the given file into a gnutls structure. 596 * Private function which reads the given file into a key_data_t structure.
587 * 597 *
588 * @param file The filename of the file to read 598 * @param file The filename of the file to read
589 * @param data The pointer at which to store the data. 599 * @param data The pointer at which to store the data.
590 * 600 *
591 * @return 1 if the file contents where read successfully and 0 otherwise. 601 * @return 1 if the file contents where read successfully and 0 otherwise.
592 */ 602 */
593static int userpref_get_file_contents(const char *file, gnutls_datum_t * data) 603static int userpref_get_file_contents(const char *file, key_data_t * data)
594{ 604{
595 int success; 605 int success;
596 unsigned long int size = 0; 606 unsigned long int size = 0;
@@ -637,7 +647,7 @@ static int userpref_get_file_contents(const char *file, gnutls_datum_t * data)
637 647
638 free(filepath); 648 free(filepath);
639 649
640 /* Add it to the gnutls_datnum_t structure */ 650 /* Add it to the key_data_t structure */
641 if (success) { 651 if (success) {
642 data->data = (uint8_t*) content; 652 data->data = (uint8_t*) content;
643 data->size = size; 653 data->size = size;
@@ -655,6 +665,121 @@ static userpref_error_t userpref_gen_keys_and_cert(void)
655{ 665{
656 userpref_error_t ret = USERPREF_E_SSL_ERROR; 666 userpref_error_t ret = USERPREF_E_SSL_ERROR;
657 667
668 key_data_t root_key_pem = { NULL, 0 };
669 key_data_t root_cert_pem = { NULL, 0 };
670 key_data_t host_key_pem = { NULL, 0 };
671 key_data_t host_cert_pem = { NULL, 0 };
672
673#ifdef HAVE_OPENSSL
674 RSA* root_keypair = RSA_generate_key(2048, 65537, NULL, NULL);
675 RSA* host_keypair = RSA_generate_key(2048, 65537, NULL, NULL);
676
677 EVP_PKEY* root_pkey = EVP_PKEY_new();
678 EVP_PKEY_assign_RSA(root_pkey, root_keypair);
679
680 EVP_PKEY* host_pkey = EVP_PKEY_new();
681 EVP_PKEY_assign_RSA(host_pkey, host_keypair);
682
683 /* generate root certificate */
684 X509* root_cert = X509_new();
685 {
686 /* set serial number */
687 ASN1_INTEGER* sn = ASN1_INTEGER_new();
688 ASN1_INTEGER_set(sn, 0);
689 X509_set_serialNumber(root_cert, sn);
690 ASN1_INTEGER_free(sn);
691
692 /* set version */
693 X509_set_version(root_cert, 2);
694
695 /* set x509v3 basic constraints */
696 X509_EXTENSION* ext;
697 if (!(ext = X509V3_EXT_conf_nid(NULL, NULL, NID_basic_constraints, (char*)"critical,CA:TRUE"))) {
698 debug_info("ERROR: X509V3_EXT_conf_nid failed");
699 }
700 X509_add_ext(root_cert, ext, -1);
701
702 /* set key validity */
703 ASN1_TIME* asn1time = ASN1_TIME_new();
704 ASN1_TIME_set(asn1time, time(NULL));
705 X509_set_notBefore(root_cert, asn1time);
706 ASN1_TIME_set(asn1time, time(NULL) + (60 * 60 * 24 * 365 * 10));
707 X509_set_notAfter(root_cert, asn1time);
708 ASN1_TIME_free(asn1time);
709
710 /* use root public key for root cert */
711 X509_set_pubkey(root_cert, root_pkey);
712 /* sign root cert with root private key */
713 X509_sign(root_cert, root_pkey, EVP_sha1());
714 }
715
716 /* create host certificate */
717 X509* host_cert = X509_new();
718 {
719 /* set serial number */
720 ASN1_INTEGER* sn = ASN1_INTEGER_new();
721 ASN1_INTEGER_set(sn, 0);
722 X509_set_serialNumber(host_cert, sn);
723 ASN1_INTEGER_free(sn);
724
725 /* set version */
726 X509_set_version(host_cert, 2);
727
728 /* set x509v3 basic constraints */
729 X509_EXTENSION* ext;
730 if (!(ext = X509V3_EXT_conf_nid(NULL, NULL, NID_basic_constraints, (char*)"critical,CA:FALSE"))) {
731 debug_info("ERROR: X509V3_EXT_conf_nid failed");
732 }
733 X509_add_ext(host_cert, ext, -1);
734
735 /* set x509v3 key usage */
736 if (!(ext = X509V3_EXT_conf_nid(NULL, NULL, NID_key_usage, (char*)"digitalSignature,keyEncipherment"))) {
737 debug_info("ERROR: X509V3_EXT_conf_nid failed");
738 }
739 X509_add_ext(host_cert, ext, -1);
740
741 /* set key validity */
742 ASN1_TIME* asn1time = ASN1_TIME_new();
743 ASN1_TIME_set(asn1time, time(NULL));
744 X509_set_notBefore(host_cert, asn1time);
745 ASN1_TIME_set(asn1time, time(NULL) + (60 * 60 * 24 * 365 * 10));
746 X509_set_notAfter(host_cert, asn1time);
747 ASN1_TIME_free(asn1time);
748
749 /* use host public key for host cert */
750 X509_set_pubkey(host_cert, host_pkey);
751
752 /* sign host cert with root private key */
753 X509_sign(host_cert, root_pkey, EVP_sha1());
754 }
755
756 if (root_cert && root_pkey && host_cert && host_pkey) {
757 BIO* membp;
758
759 membp = BIO_new(BIO_s_mem());
760 if (PEM_write_bio_X509(membp, root_cert) > 0) {
761 root_cert_pem.size = BIO_get_mem_data(membp, &root_cert_pem.data);
762 }
763 membp = BIO_new(BIO_s_mem());
764 if (PEM_write_bio_PrivateKey(membp, root_pkey, NULL, NULL, 0, 0, NULL) > 0) {
765 root_key_pem.size = BIO_get_mem_data(membp, &root_key_pem.data);
766 }
767 membp = BIO_new(BIO_s_mem());
768 if (PEM_write_bio_X509(membp, host_cert) > 0) {
769 host_cert_pem.size = BIO_get_mem_data(membp, &host_cert_pem.data);
770 }
771 membp = BIO_new(BIO_s_mem());
772 if (PEM_write_bio_PrivateKey(membp, host_pkey, NULL, NULL, 0, 0, NULL) > 0) {
773 host_key_pem.size = BIO_get_mem_data(membp, &host_key_pem.data);
774 }
775 }
776
777 EVP_PKEY_free(root_pkey);
778 EVP_PKEY_free(host_pkey);
779
780 X509_free(host_cert);
781 X509_free(root_cert);
782#else
658 gnutls_x509_privkey_t root_privkey; 783 gnutls_x509_privkey_t root_privkey;
659 gnutls_x509_crt_t root_cert; 784 gnutls_x509_crt_t root_cert;
660 gnutls_x509_privkey_t host_privkey; 785 gnutls_x509_privkey_t host_privkey;
@@ -697,8 +822,6 @@ static userpref_error_t userpref_gen_keys_and_cert(void)
697 /* export to PEM format */ 822 /* export to PEM format */
698 size_t root_key_export_size = 0; 823 size_t root_key_export_size = 0;
699 size_t host_key_export_size = 0; 824 size_t host_key_export_size = 0;
700 gnutls_datum_t root_key_pem = { NULL, 0 };
701 gnutls_datum_t host_key_pem = { NULL, 0 };
702 825
703 gnutls_x509_privkey_export(root_privkey, GNUTLS_X509_FMT_PEM, NULL, &root_key_export_size); 826 gnutls_x509_privkey_export(root_privkey, GNUTLS_X509_FMT_PEM, NULL, &root_key_export_size);
704 gnutls_x509_privkey_export(host_privkey, GNUTLS_X509_FMT_PEM, NULL, &host_key_export_size); 827 gnutls_x509_privkey_export(host_privkey, GNUTLS_X509_FMT_PEM, NULL, &host_key_export_size);
@@ -713,8 +836,6 @@ static userpref_error_t userpref_gen_keys_and_cert(void)
713 836
714 size_t root_cert_export_size = 0; 837 size_t root_cert_export_size = 0;
715 size_t host_cert_export_size = 0; 838 size_t host_cert_export_size = 0;
716 gnutls_datum_t root_cert_pem = { NULL, 0 };
717 gnutls_datum_t host_cert_pem = { NULL, 0 };
718 839
719 gnutls_x509_crt_export(root_cert, GNUTLS_X509_FMT_PEM, NULL, &root_cert_export_size); 840 gnutls_x509_crt_export(root_cert, GNUTLS_X509_FMT_PEM, NULL, &root_cert_export_size);
720 gnutls_x509_crt_export(host_cert, GNUTLS_X509_FMT_PEM, NULL, &host_cert_export_size); 841 gnutls_x509_crt_export(host_cert, GNUTLS_X509_FMT_PEM, NULL, &host_cert_export_size);
@@ -727,6 +848,10 @@ static userpref_error_t userpref_gen_keys_and_cert(void)
727 gnutls_x509_crt_export(host_cert, GNUTLS_X509_FMT_PEM, host_cert_pem.data, &host_cert_export_size); 848 gnutls_x509_crt_export(host_cert, GNUTLS_X509_FMT_PEM, host_cert_pem.data, &host_cert_export_size);
728 host_cert_pem.size = host_cert_export_size; 849 host_cert_pem.size = host_cert_export_size;
729 850
851 //restore gnutls env
852 gnutls_global_deinit();
853 gnutls_global_init();
854#endif
730 if (NULL != root_cert_pem.data && 0 != root_cert_pem.size && 855 if (NULL != root_cert_pem.data && 0 != root_cert_pem.size &&
731 NULL != host_cert_pem.data && 0 != host_cert_pem.size) 856 NULL != host_cert_pem.data && 0 != host_cert_pem.size)
732 ret = USERPREF_E_SUCCESS; 857 ret = USERPREF_E_SUCCESS;
@@ -734,14 +859,14 @@ static userpref_error_t userpref_gen_keys_and_cert(void)
734 /* store values in config file */ 859 /* store values in config file */
735 userpref_set_keys_and_certs( &root_key_pem, &root_cert_pem, &host_key_pem, &host_cert_pem); 860 userpref_set_keys_and_certs( &root_key_pem, &root_cert_pem, &host_key_pem, &host_cert_pem);
736 861
737 gnutls_free(root_key_pem.data); 862 if (root_key_pem.data)
738 gnutls_free(root_cert_pem.data); 863 free(root_key_pem.data);
739 gnutls_free(host_key_pem.data); 864 if (root_cert_pem.data)
740 gnutls_free(host_cert_pem.data); 865 free(root_cert_pem.data);
741 866 if (host_key_pem.data)
742 //restore gnutls env 867 free(host_key_pem.data);
743 gnutls_global_deinit(); 868 if (host_cert_pem.data)
744 gnutls_global_init(); 869 free(host_cert_pem.data);
745 870
746 return ret; 871 return ret;
747} 872}
@@ -754,18 +879,33 @@ static userpref_error_t userpref_gen_keys_and_cert(void)
754 * 879 *
755 * @return 1 if the key was successfully imported. 880 * @return 1 if the key was successfully imported.
756 */ 881 */
882#ifdef HAVE_OPENSSL
883static userpref_error_t userpref_import_key(const char* key_name, key_data_t* key)
884#else
757static userpref_error_t userpref_import_key(const char* key_name, gnutls_x509_privkey_t key) 885static userpref_error_t userpref_import_key(const char* key_name, gnutls_x509_privkey_t key)
886#endif
758{ 887{
888#ifdef HAVE_OPENSSL
889 if (!key)
890 return USERPREF_E_SUCCESS;
891#endif
759 userpref_error_t ret = USERPREF_E_INVALID_CONF; 892 userpref_error_t ret = USERPREF_E_INVALID_CONF;
760 gnutls_datum_t pem_key = { NULL, 0 }; 893 key_data_t pem_key = { NULL, 0 };
761
762 if (userpref_get_file_contents(key_name, &pem_key)) { 894 if (userpref_get_file_contents(key_name, &pem_key)) {
763 if (GNUTLS_E_SUCCESS == gnutls_x509_privkey_import(key, &pem_key, GNUTLS_X509_FMT_PEM)) 895#ifdef HAVE_OPENSSL
764 ret = USERPREF_E_SUCCESS; 896 key->data = (unsigned char*)malloc(pem_key.size);
765 else 897 memcpy(key->data, pem_key.data, pem_key.size);
766 ret = USERPREF_E_SSL_ERROR; 898 key->size = pem_key.size;
899 ret = USERPREF_E_SUCCESS;
900#else
901 if (GNUTLS_E_SUCCESS == gnutls_x509_privkey_import(key, &pem_key, GNUTLS_X509_FMT_PEM))
902 ret = USERPREF_E_SUCCESS;
903 else
904 ret = USERPREF_E_SSL_ERROR;
905#endif
767 } 906 }
768 gnutls_free(pem_key.data); 907 if (pem_key.data)
908 free(pem_key.data);
769 return ret; 909 return ret;
770} 910}
771 911
@@ -777,18 +917,34 @@ static userpref_error_t userpref_import_key(const char* key_name, gnutls_x509_pr
777 * 917 *
778 * @return IDEVICE_E_SUCCESS if the certificate was successfully imported. 918 * @return IDEVICE_E_SUCCESS if the certificate was successfully imported.
779 */ 919 */
920#ifdef HAVE_OPENSSL
921static userpref_error_t userpref_import_crt(const char* crt_name, key_data_t* cert)
922#else
780static userpref_error_t userpref_import_crt(const char* crt_name, gnutls_x509_crt_t cert) 923static userpref_error_t userpref_import_crt(const char* crt_name, gnutls_x509_crt_t cert)
924#endif
781{ 925{
926#ifdef HAVE_OPENSSL
927 if (!cert)
928 return USERPREF_E_SUCCESS;
929#endif
782 userpref_error_t ret = USERPREF_E_INVALID_CONF; 930 userpref_error_t ret = USERPREF_E_INVALID_CONF;
783 gnutls_datum_t pem_cert = { NULL, 0 }; 931 key_data_t pem_cert = { NULL, 0 };
784 932
785 if (userpref_get_file_contents(crt_name, &pem_cert)) { 933 if (userpref_get_file_contents(crt_name, &pem_cert)) {
786 if (GNUTLS_E_SUCCESS == gnutls_x509_crt_import(cert, &pem_cert, GNUTLS_X509_FMT_PEM)) 934#ifdef HAVE_OPENSSL
787 ret = USERPREF_E_SUCCESS; 935 cert->data = (unsigned char*)malloc(pem_cert.size);
788 else 936 memcpy(cert->data, pem_cert.data, pem_cert.size);
789 ret = USERPREF_E_SSL_ERROR; 937 cert->size = pem_cert.size;
938 ret = USERPREF_E_SUCCESS;
939#else
940 if (GNUTLS_E_SUCCESS == gnutls_x509_crt_import(cert, &pem_cert, GNUTLS_X509_FMT_PEM))
941 ret = USERPREF_E_SUCCESS;
942 else
943 ret = USERPREF_E_SSL_ERROR;
944#endif
790 } 945 }
791 gnutls_free(pem_cert.data); 946 if (pem_cert.data)
947 free(pem_cert.data);
792 return ret; 948 return ret;
793} 949}
794 950
@@ -805,7 +961,11 @@ static userpref_error_t userpref_import_crt(const char* crt_name, gnutls_x509_cr
805 * 961 *
806 * @return 1 if the keys and certificates were successfully retrieved, 0 otherwise 962 * @return 1 if the keys and certificates were successfully retrieved, 0 otherwise
807 */ 963 */
964#ifdef HAVE_OPENSSL
965userpref_error_t userpref_get_keys_and_certs(key_data_t* root_privkey, key_data_t* root_crt, key_data_t* host_privkey, key_data_t* host_crt)
966#else
808userpref_error_t userpref_get_keys_and_certs(gnutls_x509_privkey_t root_privkey, gnutls_x509_crt_t root_crt, gnutls_x509_privkey_t host_privkey, gnutls_x509_crt_t host_crt) 967userpref_error_t userpref_get_keys_and_certs(gnutls_x509_privkey_t root_privkey, gnutls_x509_crt_t root_crt, gnutls_x509_privkey_t host_privkey, gnutls_x509_crt_t host_crt)
968#endif
809{ 969{
810 userpref_error_t ret = USERPREF_E_SUCCESS; 970 userpref_error_t ret = USERPREF_E_SUCCESS;
811 971
@@ -821,7 +981,6 @@ userpref_error_t userpref_get_keys_and_certs(gnutls_x509_privkey_t root_privkey,
821 if (ret == USERPREF_E_SUCCESS) 981 if (ret == USERPREF_E_SUCCESS)
822 ret = userpref_import_crt(LIBIMOBILEDEVICE_HOST_CERTIF, host_crt); 982 ret = userpref_import_crt(LIBIMOBILEDEVICE_HOST_CERTIF, host_crt);
823 983
824
825 if (USERPREF_E_SUCCESS != ret) { 984 if (USERPREF_E_SUCCESS != ret) {
826 //we had problem reading or importing root cert 985 //we had problem reading or importing root cert
827 //try with a new ones. 986 //try with a new ones.
@@ -851,7 +1010,7 @@ userpref_error_t userpref_get_keys_and_certs(gnutls_x509_privkey_t root_privkey,
851 * 1010 *
852 * @return 1 if the certificates were successfully retrieved, 0 otherwise 1011 * @return 1 if the certificates were successfully retrieved, 0 otherwise
853 */ 1012 */
854userpref_error_t userpref_get_certs_as_pem(gnutls_datum_t *pem_root_cert, gnutls_datum_t *pem_host_cert) 1013userpref_error_t userpref_get_certs_as_pem(key_data_t *pem_root_cert, key_data_t *pem_host_cert)
855{ 1014{
856 if (!pem_root_cert || !pem_host_cert) 1015 if (!pem_root_cert || !pem_host_cert)
857 return USERPREF_E_INVALID_ARG; 1016 return USERPREF_E_INVALID_ARG;
@@ -859,8 +1018,14 @@ userpref_error_t userpref_get_certs_as_pem(gnutls_datum_t *pem_root_cert, gnutls
859 if (userpref_get_file_contents(LIBIMOBILEDEVICE_ROOT_CERTIF, pem_root_cert) && userpref_get_file_contents(LIBIMOBILEDEVICE_HOST_CERTIF, pem_host_cert)) 1018 if (userpref_get_file_contents(LIBIMOBILEDEVICE_ROOT_CERTIF, pem_root_cert) && userpref_get_file_contents(LIBIMOBILEDEVICE_HOST_CERTIF, pem_host_cert))
860 return USERPREF_E_SUCCESS; 1019 return USERPREF_E_SUCCESS;
861 else { 1020 else {
862 gnutls_free(pem_root_cert->data); 1021 if (pem_root_cert->data) {
863 gnutls_free(pem_host_cert->data); 1022 free(pem_root_cert->data);
1023 pem_root_cert->size = 0;
1024 }
1025 if (pem_host_cert->data) {
1026 free(pem_host_cert->data);
1027 pem_host_cert->size = 0;
1028 }
864 } 1029 }
865 return USERPREF_E_INVALID_CONF; 1030 return USERPREF_E_INVALID_CONF;
866} 1031}
@@ -877,7 +1042,7 @@ userpref_error_t userpref_get_certs_as_pem(gnutls_datum_t *pem_root_cert, gnutls
877 * 1042 *
878 * @return 1 on success and 0 otherwise. 1043 * @return 1 on success and 0 otherwise.
879 */ 1044 */
880userpref_error_t userpref_set_keys_and_certs(gnutls_datum_t * root_key, gnutls_datum_t * root_cert, gnutls_datum_t * host_key, gnutls_datum_t * host_cert) 1045userpref_error_t userpref_set_keys_and_certs(key_data_t * root_key, key_data_t * root_cert, key_data_t * host_key, key_data_t * host_cert)
881{ 1046{
882 FILE *pFile; 1047 FILE *pFile;
883 char *pem; 1048 char *pem;