diff options
| author | 2011-09-14 18:55:59 +0200 | |
|---|---|---|
| committer | 2012-03-19 01:43:29 +0100 | |
| commit | 8b1af4cf80eff619d3465925dce7fe572fc09224 (patch) | |
| tree | 1fc167114f574c2ff3470c97d6ce74938778f9db /src/lockdown.c | |
| parent | 294cf69b256419e407b1eac04634752412ee7756 (diff) | |
| download | libimobiledevice-8b1af4cf80eff619d3465925dce7fe572fc09224.tar.gz libimobiledevice-8b1af4cf80eff619d3465925dce7fe572fc09224.tar.bz2 | |
Add OpenSSL support
Diffstat (limited to 'src/lockdown.c')
| -rw-r--r-- | src/lockdown.c | 164 |
1 files changed, 154 insertions, 10 deletions
diff --git a/src/lockdown.c b/src/lockdown.c index 0f1e1b2..f22fb08 100644 --- a/src/lockdown.c +++ b/src/lockdown.c | |||
| @@ -20,14 +20,24 @@ | |||
| 20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | 20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| 21 | */ | 21 | */ |
| 22 | 22 | ||
| 23 | #ifdef HAVE_CONFIG_H | ||
| 24 | #include <config.h> | ||
| 25 | #endif | ||
| 26 | |||
| 23 | #include <string.h> | 27 | #include <string.h> |
| 24 | #include <stdlib.h> | 28 | #include <stdlib.h> |
| 25 | #define _GNU_SOURCE 1 | 29 | #define _GNU_SOURCE 1 |
| 26 | #define __USE_GNU 1 | 30 | #define __USE_GNU 1 |
| 27 | #include <stdio.h> | 31 | #include <stdio.h> |
| 28 | #include <ctype.h> | 32 | #include <ctype.h> |
| 33 | #ifdef HAVE_OPENSSL | ||
| 34 | #include <openssl/pem.h> | ||
| 35 | #include <openssl/x509.h> | ||
| 36 | #include <openssl/x509v3.h> | ||
| 37 | #else | ||
| 29 | #include <libtasn1.h> | 38 | #include <libtasn1.h> |
| 30 | #include <gnutls/x509.h> | 39 | #include <gnutls/x509.h> |
| 40 | #endif | ||
| 31 | #include <plist/plist.h> | 41 | #include <plist/plist.h> |
| 32 | 42 | ||
| 33 | #include "property_list_service.h" | 43 | #include "property_list_service.h" |
| @@ -40,6 +50,7 @@ | |||
| 40 | #define RESULT_SUCCESS 0 | 50 | #define RESULT_SUCCESS 0 |
| 41 | #define RESULT_FAILURE 1 | 51 | #define RESULT_FAILURE 1 |
| 42 | 52 | ||
| 53 | #ifndef HAVE_OPENSSL | ||
| 43 | const ASN1_ARRAY_TYPE pkcs1_asn1_tab[] = { | 54 | const ASN1_ARRAY_TYPE pkcs1_asn1_tab[] = { |
| 44 | {"PKCS1", 536872976, 0}, | 55 | {"PKCS1", 536872976, 0}, |
| 45 | {0, 1073741836, 0}, | 56 | {0, 1073741836, 0}, |
| @@ -48,6 +59,7 @@ const ASN1_ARRAY_TYPE pkcs1_asn1_tab[] = { | |||
| 48 | {"publicExponent", 3, 0}, | 59 | {"publicExponent", 3, 0}, |
| 49 | {0, 0, 0} | 60 | {0, 0, 0} |
| 50 | }; | 61 | }; |
| 62 | #endif | ||
| 51 | 63 | ||
| 52 | /** | 64 | /** |
| 53 | * Internally used function for checking the result from lockdown's answer | 65 | * Internally used function for checking the result from lockdown's answer |
| @@ -567,7 +579,7 @@ lockdownd_error_t lockdownd_get_device_uuid(lockdownd_client_t client, char **uu | |||
| 567 | * | 579 | * |
| 568 | * @return LOCKDOWN_E_SUCCESS on success | 580 | * @return LOCKDOWN_E_SUCCESS on success |
| 569 | */ | 581 | */ |
| 570 | lockdownd_error_t lockdownd_get_device_public_key(lockdownd_client_t client, gnutls_datum_t * public_key) | 582 | lockdownd_error_t lockdownd_get_device_public_key(lockdownd_client_t client, key_data_t * public_key) |
| 571 | { | 583 | { |
| 572 | lockdownd_error_t ret = LOCKDOWN_E_UNKNOWN_ERROR; | 584 | lockdownd_error_t ret = LOCKDOWN_E_UNKNOWN_ERROR; |
| 573 | plist_t value = NULL; | 585 | plist_t value = NULL; |
| @@ -783,13 +795,13 @@ static plist_t lockdownd_pair_record_to_plist(lockdownd_pair_record_t pair_recor | |||
| 783 | * | 795 | * |
| 784 | * @return LOCKDOWN_E_SUCCESS on success | 796 | * @return LOCKDOWN_E_SUCCESS on success |
| 785 | */ | 797 | */ |
| 786 | static lockdownd_error_t generate_pair_record_plist(gnutls_datum_t public_key, char *host_id, plist_t *pair_record_plist) | 798 | static lockdownd_error_t generate_pair_record_plist(key_data_t public_key, char *host_id, plist_t *pair_record_plist) |
| 787 | { | 799 | { |
| 788 | lockdownd_error_t ret = LOCKDOWN_E_UNKNOWN_ERROR; | 800 | lockdownd_error_t ret = LOCKDOWN_E_UNKNOWN_ERROR; |
| 789 | 801 | ||
| 790 | gnutls_datum_t device_cert = { NULL, 0 }; | 802 | key_data_t device_cert = { NULL, 0 }; |
| 791 | gnutls_datum_t host_cert = { NULL, 0 }; | 803 | key_data_t host_cert = { NULL, 0 }; |
| 792 | gnutls_datum_t root_cert = { NULL, 0 }; | 804 | key_data_t root_cert = { NULL, 0 }; |
| 793 | 805 | ||
| 794 | ret = lockdownd_gen_pair_cert(public_key, &device_cert, &host_cert, &root_cert); | 806 | ret = lockdownd_gen_pair_cert(public_key, &device_cert, &host_cert, &root_cert); |
| 795 | if (ret != LOCKDOWN_E_SUCCESS) { | 807 | if (ret != LOCKDOWN_E_SUCCESS) { |
| @@ -844,7 +856,7 @@ static lockdownd_error_t lockdownd_do_pair(lockdownd_client_t client, lockdownd_ | |||
| 844 | lockdownd_error_t ret = LOCKDOWN_E_UNKNOWN_ERROR; | 856 | lockdownd_error_t ret = LOCKDOWN_E_UNKNOWN_ERROR; |
| 845 | plist_t dict = NULL; | 857 | plist_t dict = NULL; |
| 846 | plist_t dict_record = NULL; | 858 | plist_t dict_record = NULL; |
| 847 | gnutls_datum_t public_key = { NULL, 0 }; | 859 | key_data_t public_key = { NULL, 0 }; |
| 848 | int pairing_mode = 0; /* 0 = libimobiledevice, 1 = external */ | 860 | int pairing_mode = 0; /* 0 = libimobiledevice, 1 = external */ |
| 849 | 861 | ||
| 850 | if (pair_record && pair_record->host_id) { | 862 | if (pair_record && pair_record->host_id) { |
| @@ -1096,14 +1108,145 @@ lockdownd_error_t lockdownd_goodbye(lockdownd_client_t client) | |||
| 1096 | * LOCKDOWN_E_INVALID_CONF if the internal configuration system failed, | 1108 | * LOCKDOWN_E_INVALID_CONF if the internal configuration system failed, |
| 1097 | * LOCKDOWN_E_SSL_ERROR if the certificates could not be generated | 1109 | * LOCKDOWN_E_SSL_ERROR if the certificates could not be generated |
| 1098 | */ | 1110 | */ |
| 1099 | lockdownd_error_t lockdownd_gen_pair_cert(gnutls_datum_t public_key, gnutls_datum_t * odevice_cert, | 1111 | lockdownd_error_t lockdownd_gen_pair_cert(key_data_t public_key, key_data_t * odevice_cert, |
| 1100 | gnutls_datum_t * ohost_cert, gnutls_datum_t * oroot_cert) | 1112 | key_data_t * ohost_cert, key_data_t * oroot_cert) |
| 1101 | { | 1113 | { |
| 1102 | if (!public_key.data || !odevice_cert || !ohost_cert || !oroot_cert) | 1114 | if (!public_key.data || !odevice_cert || !ohost_cert || !oroot_cert) |
| 1103 | return LOCKDOWN_E_INVALID_ARG; | 1115 | return LOCKDOWN_E_INVALID_ARG; |
| 1104 | lockdownd_error_t ret = LOCKDOWN_E_UNKNOWN_ERROR; | 1116 | lockdownd_error_t ret = LOCKDOWN_E_UNKNOWN_ERROR; |
| 1105 | userpref_error_t uret = USERPREF_E_UNKNOWN_ERROR; | 1117 | userpref_error_t uret = USERPREF_E_UNKNOWN_ERROR; |
| 1106 | 1118 | ||
| 1119 | #ifdef HAVE_OPENSSL | ||
| 1120 | BIO *membio = BIO_new_mem_buf(public_key.data, public_key.size); | ||
| 1121 | RSA *pubkey = NULL; | ||
| 1122 | if (!PEM_read_bio_RSAPublicKey(membio, &pubkey, NULL, NULL)) { | ||
| 1123 | debug_info("%s: Could not read public key", __func__); | ||
| 1124 | } | ||
| 1125 | BIO_free(membio); | ||
| 1126 | |||
| 1127 | /* now generate certificates */ | ||
| 1128 | key_data_t root_privkey, host_privkey; | ||
| 1129 | key_data_t root_cert, host_cert; | ||
| 1130 | X509* dev_cert; | ||
| 1131 | |||
| 1132 | root_cert.data = NULL; | ||
| 1133 | root_cert.size = 0; | ||
| 1134 | host_cert.data = NULL; | ||
| 1135 | host_cert.size = 0; | ||
| 1136 | |||
| 1137 | dev_cert = X509_new(); | ||
| 1138 | |||
| 1139 | root_privkey.data = NULL; | ||
| 1140 | root_privkey.size = 0; | ||
| 1141 | host_privkey.data = NULL; | ||
| 1142 | host_privkey.size = 0; | ||
| 1143 | |||
| 1144 | uret = userpref_get_keys_and_certs(&root_privkey, &root_cert, &host_privkey, &host_cert); | ||
| 1145 | if (USERPREF_E_SUCCESS == uret) { | ||
| 1146 | /* generate device certificate */ | ||
| 1147 | ASN1_INTEGER* sn = ASN1_INTEGER_new(); | ||
| 1148 | ASN1_INTEGER_set(sn, 0); | ||
| 1149 | X509_set_serialNumber(dev_cert, sn); | ||
| 1150 | ASN1_INTEGER_free(sn); | ||
| 1151 | X509_set_version(dev_cert, 2); | ||
| 1152 | |||
| 1153 | X509_EXTENSION* ext; | ||
| 1154 | if (!(ext = X509V3_EXT_conf_nid(NULL, NULL, NID_basic_constraints, (char*)"critical,CA:FALSE"))) { | ||
| 1155 | debug_info("ERROR: X509V3_EXT_conf_nid failed"); | ||
| 1156 | } | ||
| 1157 | X509_add_ext(dev_cert, ext, -1); | ||
| 1158 | |||
| 1159 | ASN1_TIME* asn1time = ASN1_TIME_new(); | ||
| 1160 | ASN1_TIME_set(asn1time, time(NULL)); | ||
| 1161 | X509_set_notBefore(dev_cert, asn1time); | ||
| 1162 | ASN1_TIME_set(asn1time, time(NULL) + (60 * 60 * 24 * 365 * 10)); | ||
| 1163 | X509_set_notAfter(dev_cert, asn1time); | ||
| 1164 | ASN1_TIME_free(asn1time); | ||
| 1165 | |||
| 1166 | BIO* membp; | ||
| 1167 | |||
| 1168 | X509* rootCert = NULL; | ||
| 1169 | membp = BIO_new_mem_buf(root_cert.data, root_cert.size); | ||
| 1170 | PEM_read_bio_X509(membp, &rootCert, NULL, NULL); | ||
| 1171 | BIO_free(membp); | ||
| 1172 | if (!rootCert) { | ||
| 1173 | debug_info("Could not read RootCertificate%*s"); | ||
| 1174 | } else { | ||
| 1175 | debug_info("RootCertificate loaded"); | ||
| 1176 | EVP_PKEY* pkey = EVP_PKEY_new(); | ||
| 1177 | EVP_PKEY_assign_RSA(pkey, pubkey); | ||
| 1178 | X509_set_pubkey(dev_cert, pkey); | ||
| 1179 | EVP_PKEY_free(pkey); | ||
| 1180 | X509_free(rootCert); | ||
| 1181 | } | ||
| 1182 | |||
| 1183 | EVP_PKEY* rootPriv = NULL; | ||
| 1184 | membp = BIO_new_mem_buf(root_privkey.data, root_privkey.size); | ||
| 1185 | PEM_read_bio_PrivateKey(membp, &rootPriv, NULL, NULL); | ||
| 1186 | BIO_free(membp); | ||
| 1187 | if (!rootPriv) { | ||
| 1188 | debug_info("Could not read RootPrivateKey"); | ||
| 1189 | } else { | ||
| 1190 | debug_info("RootPrivateKey loaded"); | ||
| 1191 | if (X509_sign(dev_cert, rootPriv, EVP_sha1())) { | ||
| 1192 | ret = LOCKDOWN_E_SUCCESS; | ||
| 1193 | } else { | ||
| 1194 | debug_info("signing failed"); | ||
| 1195 | } | ||
| 1196 | EVP_PKEY_free(rootPriv); | ||
| 1197 | } | ||
| 1198 | |||
| 1199 | if (LOCKDOWN_E_SUCCESS == ret) { | ||
| 1200 | /* if everything went well, export in PEM format */ | ||
| 1201 | key_data_t pem_root_cert = { NULL, 0 }; | ||
| 1202 | key_data_t pem_host_cert = { NULL, 0 }; | ||
| 1203 | |||
| 1204 | uret = userpref_get_certs_as_pem(&pem_root_cert, &pem_host_cert); | ||
| 1205 | if (USERPREF_E_SUCCESS == uret) { | ||
| 1206 | /* copy buffer for output */ | ||
| 1207 | membp = BIO_new(BIO_s_mem()); | ||
| 1208 | if (PEM_write_bio_X509(membp, dev_cert) > 0) { | ||
| 1209 | odevice_cert->size = BIO_get_mem_data(membp, &odevice_cert->data); | ||
| 1210 | } | ||
| 1211 | |||
| 1212 | ohost_cert->data = malloc(pem_host_cert.size); | ||
| 1213 | memcpy(ohost_cert->data, pem_host_cert.data, pem_host_cert.size); | ||
| 1214 | ohost_cert->size = pem_host_cert.size; | ||
| 1215 | |||
| 1216 | oroot_cert->data = malloc(pem_root_cert.size); | ||
| 1217 | memcpy(oroot_cert->data, pem_root_cert.data, pem_root_cert.size); | ||
| 1218 | oroot_cert->size = pem_root_cert.size; | ||
| 1219 | |||
| 1220 | free(pem_root_cert.data); | ||
| 1221 | free(pem_host_cert.data); | ||
| 1222 | } | ||
| 1223 | } | ||
| 1224 | } | ||
| 1225 | X509V3_EXT_cleanup(); | ||
| 1226 | X509_free(dev_cert); | ||
| 1227 | |||
| 1228 | switch(uret) { | ||
| 1229 | case USERPREF_E_INVALID_ARG: | ||
| 1230 | ret = LOCKDOWN_E_INVALID_ARG; | ||
| 1231 | break; | ||
| 1232 | case USERPREF_E_INVALID_CONF: | ||
| 1233 | ret = LOCKDOWN_E_INVALID_CONF; | ||
| 1234 | break; | ||
| 1235 | case USERPREF_E_SSL_ERROR: | ||
| 1236 | ret = LOCKDOWN_E_SSL_ERROR; | ||
| 1237 | default: | ||
| 1238 | break; | ||
| 1239 | } | ||
| 1240 | |||
| 1241 | if (root_cert.data) | ||
| 1242 | free(root_cert.data); | ||
| 1243 | if (host_cert.data) | ||
| 1244 | free(host_cert.data); | ||
| 1245 | if (root_privkey.data) | ||
| 1246 | free(root_privkey.data); | ||
| 1247 | if (host_privkey.data) | ||
| 1248 | free(host_privkey.data); | ||
| 1249 | #else | ||
| 1107 | gnutls_datum_t modulus = { NULL, 0 }; | 1250 | gnutls_datum_t modulus = { NULL, 0 }; |
| 1108 | gnutls_datum_t exponent = { NULL, 0 }; | 1251 | gnutls_datum_t exponent = { NULL, 0 }; |
| 1109 | 1252 | ||
| @@ -1200,8 +1343,8 @@ lockdownd_error_t lockdownd_gen_pair_cert(gnutls_datum_t public_key, gnutls_datu | |||
| 1200 | memcpy(oroot_cert->data, pem_root_cert.data, pem_root_cert.size); | 1343 | memcpy(oroot_cert->data, pem_root_cert.data, pem_root_cert.size); |
| 1201 | oroot_cert->size = pem_root_cert.size; | 1344 | oroot_cert->size = pem_root_cert.size; |
| 1202 | 1345 | ||
| 1203 | free(pem_root_cert.data); | 1346 | gnutls_free(pem_root_cert.data); |
| 1204 | free(pem_host_cert.data); | 1347 | gnutls_free(pem_host_cert.data); |
| 1205 | 1348 | ||
| 1206 | if (dev_pem.data) | 1349 | if (dev_pem.data) |
| 1207 | gnutls_free(dev_pem.data); | 1350 | gnutls_free(dev_pem.data); |
| @@ -1238,6 +1381,7 @@ lockdownd_error_t lockdownd_gen_pair_cert(gnutls_datum_t public_key, gnutls_datu | |||
| 1238 | gnutls_free(exponent.data); | 1381 | gnutls_free(exponent.data); |
| 1239 | 1382 | ||
| 1240 | gnutls_free(der_pub_key.data); | 1383 | gnutls_free(der_pub_key.data); |
| 1384 | #endif | ||
| 1241 | 1385 | ||
| 1242 | return ret; | 1386 | return ret; |
| 1243 | } | 1387 | } |
