summaryrefslogtreecommitdiffstats
path: root/src/lockdown.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/lockdown.c
parent294cf69b256419e407b1eac04634752412ee7756 (diff)
downloadlibimobiledevice-8b1af4cf80eff619d3465925dce7fe572fc09224.tar.gz
libimobiledevice-8b1af4cf80eff619d3465925dce7fe572fc09224.tar.bz2
Add OpenSSL support
Diffstat (limited to 'src/lockdown.c')
-rw-r--r--src/lockdown.c164
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
43const ASN1_ARRAY_TYPE pkcs1_asn1_tab[] = { 54const 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 */
570lockdownd_error_t lockdownd_get_device_public_key(lockdownd_client_t client, gnutls_datum_t * public_key) 582lockdownd_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 */
786static lockdownd_error_t generate_pair_record_plist(gnutls_datum_t public_key, char *host_id, plist_t *pair_record_plist) 798static 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 */
1099lockdownd_error_t lockdownd_gen_pair_cert(gnutls_datum_t public_key, gnutls_datum_t * odevice_cert, 1111lockdownd_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}