X509* SDMMD__decode_certificate(CFDataRef cert) { X509* result = NULL; if (cert) { BIO *newBIO = SDMMD__create_bio_from_data(cert); if (newBIO == 0) { printf("_decode_certificate: Could not create BIO from CFData.\n"); } else { result = PEM_read_bio_X509(newBIO, 0x0, 0x0, 0x0); if (result == NULL) { printf("_decode_certificate: PEM_read_bio_X509 failed.\n"); } BIO_free(newBIO); } } return result; }
CFMutableDictionaryRef SDMMD__CreatePairingMaterial(CFDataRef devicePubkey) { CFMutableDictionaryRef record = NULL; RSA *rsaBIOData = NULL; BIO *deviceBIO = SDMMD__create_bio_from_data(devicePubkey); if (deviceBIO) { PEM_read_bio_RSAPublicKey(deviceBIO, &rsaBIOData, NULL, NULL); BIO_free(deviceBIO); } else { printf("Could not decode device public key\\n"); } RSA *rootKeyPair = RSA_generate_key(2048, 65537, NULL, NULL); if (!rootKeyPair) { printf("Could not allocate root key pair\n"); } RSA *hostKeyPair = RSA_generate_key(2048, 65537, NULL, NULL); if (!hostKeyPair) { printf("Could not allocate host key pair\n"); } sdmmd_return_t result = kAMDSuccess; EVP_PKEY *rootEVP = EVP_PKEY_new(); if (!rootEVP) { printf("Could not allocate root EVP key\\n"); } else { result = EVP_PKEY_assign(rootEVP, EVP_CTRL_RAND_KEY, PtrCast(rootKeyPair, char *)); if (!result) { printf("Could not assign root key pair\n"); } } EVP_PKEY *hostEVP = EVP_PKEY_new(); if (!hostEVP) { printf("Could not allocate host EVP key\\n"); } else { result = EVP_PKEY_assign(hostEVP, EVP_CTRL_RAND_KEY, PtrCast(hostKeyPair, char *)); if (!result) { printf("Could not assign host key pair\n"); } } EVP_PKEY *deviceEVP = EVP_PKEY_new(); if (!deviceEVP) { printf("Could not allocate device EVP key\\n"); } else { result = EVP_PKEY_assign(deviceEVP, EVP_CTRL_RAND_KEY, PtrCast(rsaBIOData, char *)); if (!result) { printf("Could not assign device key pair\n"); } } X509 *rootX509 = X509_new(); if (!rootX509) { printf("Could not create root X509\\n"); } else { X509_set_pubkey(rootX509, rootEVP); X509_set_version(rootX509, 2); ASN1_INTEGER *rootSerial = X509_get_serialNumber(rootX509); ASN1_INTEGER_set(rootSerial, 0); ASN1_TIME *rootAsn1time = ASN1_TIME_new(); ASN1_TIME_set(rootAsn1time, 0); X509_set_notBefore(rootX509, rootAsn1time); ASN1_TIME_set(rootAsn1time, 0x12cc0300); // 60 sec * 60 minutes * 24 hours * 365 days * 10 years X509_set_notAfter(rootX509, rootAsn1time); ASN1_TIME_free(rootAsn1time); SDMMD__add_ext(rootX509, NID_basic_constraints, "critical,CA:TRUE"); SDMMD__add_ext(rootX509, NID_subject_key_identifier, "hash"); result = X509_sign(rootX509, rootEVP, EVP_sha1()); if (!result) { printf("Could not sign root cert\\n"); } } X509 *hostX509 = X509_new(); if (!hostX509) { printf("Could not create host X509\\n"); } else { X509_set_pubkey(hostX509, hostEVP); X509_set_version(hostX509, 2); ASN1_INTEGER *hostSerial = X509_get_serialNumber(hostX509); ASN1_INTEGER_set(hostSerial, 0); ASN1_TIME *hostAsn1time = ASN1_TIME_new(); ASN1_TIME_set(hostAsn1time, 0); X509_set_notBefore(hostX509, hostAsn1time); ASN1_TIME_set(hostAsn1time, 0x12cc0300); // 60 sec * 60 minutes * 24 hours * 365 days * 10 years X509_set_notAfter(hostX509, hostAsn1time); ASN1_TIME_free(hostAsn1time); SDMMD__add_ext(hostX509, NID_basic_constraints, "critical,CA:FALSE"); SDMMD__add_ext(hostX509, NID_subject_key_identifier, "hash"); SDMMD__add_ext(hostX509, NID_key_usage, "critical,digitalSignature,keyEncipherment"); result = X509_sign(hostX509, rootEVP, EVP_sha1()); if (!result) { printf("Could not sign host cert\\n"); } } X509 *deviceX509 = X509_new(); if (!deviceX509) { printf("Could not create device X509\\n"); } else { X509_set_pubkey(deviceX509, deviceEVP); X509_set_version(deviceX509, 2); ASN1_INTEGER *deviceSerial = X509_get_serialNumber(deviceX509); ASN1_INTEGER_set(deviceSerial, 0); ASN1_TIME *deviceAsn1time = ASN1_TIME_new(); ASN1_TIME_set(deviceAsn1time, 0); X509_set_notBefore(deviceX509, deviceAsn1time); ASN1_TIME_set(deviceAsn1time, 0x12cc0300); // 60 sec * 60 minutes * 24 hours * 365 days * 10 years X509_set_notAfter(deviceX509, deviceAsn1time); ASN1_TIME_free(deviceAsn1time); SDMMD__add_ext(deviceX509, NID_basic_constraints, "critical,CA:FALSE"); SDMMD__add_ext(deviceX509, NID_subject_key_identifier, "hash"); SDMMD__add_ext(deviceX509, NID_key_usage, "critical,digitalSignature,keyEncipherment"); result = X509_sign(deviceX509, rootEVP, EVP_sha1()); if (!result) { printf("Could not sign device cert\\n"); } } CFDataRef rootCert = SDMMD_CreateDataFromX509Certificate(rootX509); CFDataRef hostCert = SDMMD_CreateDataFromX509Certificate(hostX509); CFDataRef deviceCert = SDMMD_CreateDataFromX509Certificate(deviceX509); CFDataRef rootPrivKey = SDMMD_CreateDataFromPrivateKey(rootEVP); CFDataRef hostPrivKey = SDMMD_CreateDataFromPrivateKey(hostEVP); CFStringRef hostId = SDMMD_CreateUUID(); record = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); if (record) { CFDictionarySetValue(record, CFSTR("RootCertificate"), rootCert); CFDictionarySetValue(record, CFSTR("HostCertificate"), hostCert); CFDictionarySetValue(record, CFSTR("DeviceCertificate"), deviceCert); CFDictionarySetValue(record, CFSTR("RootPrivateKey"), rootPrivKey); CFDictionarySetValue(record, CFSTR("HostPrivateKey"), hostPrivKey); CFDictionarySetValue(record, CFSTR("HostID"), hostId); } CFSafeRelease(rootCert); CFSafeRelease(hostCert); CFSafeRelease(deviceCert); CFSafeRelease(rootPrivKey); CFSafeRelease(hostPrivKey); CFSafeRelease(hostId); Safe(EVP_PKEY_free, rootEVP); Safe(EVP_PKEY_free, hostEVP); Safe(EVP_PKEY_free, deviceEVP); Safe(X509_free, rootX509); Safe(X509_free, hostX509); Safe(X509_free, deviceX509); return record; }
SSL* SDMMD_lockssl_handshake(SDMMD_lockdown_conn *lockdown_conn, CFTypeRef hostCert, CFTypeRef deviceCert, CFTypeRef hostPrivKey, uint32_t num) { SSL *ssl = NULL; SSL_CTX *sslCTX = NULL; sdmmd_return_t result = 0x0; BIO_METHOD *bioMethod = BIO_s_socket(); BIO *bioSocket = BIO_new(bioMethod); if (bioSocket) { BIO_set_fd(bioSocket, lockdown_conn->connection, 0); X509 *cert = SDMMD__decode_certificate(hostCert); if (cert == 0) { printf("_create_ssl_context: Could not certificate.\n"); } RSA *rsa = NULL; BIO *dataBIO = SDMMD__create_bio_from_data(hostPrivKey); if (dataBIO == 0) { printf("_create_ssl_context: Could not decode host private key.\n"); if (cert) { X509_free(cert); result = 0x0; } } else { PEM_read_bio_RSAPrivateKey(dataBIO, &rsa, 0x0, 0x0); BIO_free(dataBIO); if (rsa) { if (hostCert) { sslCTX = SSL_CTX_new(SSLv3_method()); if (sslCTX) { result = SSL_CTX_use_certificate(sslCTX, cert); if (result == 0) printf("_create_ssl_context: Could not set certificate.\n"); result = SSL_CTX_use_RSAPrivateKey(sslCTX, rsa); if (result == 0) printf("_create_ssl_context: Could not set private key.\n"); } else { printf("_create_ssl_context: Could not create SSLv3 context.\n"); } } RSA_free(rsa); if (cert) X509_free(cert); if (sslCTX) { ssl = SSL_new(sslCTX); if (ssl) { if (num) { SSL_set_connect_state(ssl); } else { SSL_set_accept_state(ssl); } SSL_set_verify(ssl, 0x3, SDMMD__ssl_verify_callback); SSL_set_verify_depth(ssl, 0x0); SSL_set_bio(ssl, bioSocket, bioSocket); SSL_set_ex_data(ssl, SDMMobileDevice->peer_certificate_data_index, (void*)deviceCert); result = SSL_do_handshake(ssl); if (result == 1) { SSL_CTX_free(sslCTX); } else { uint32_t err = SSL_get_error(ssl, result); if (err) { char *reason = SDMMD_ssl_strerror(ssl, err); printf("lockssl_handshake: SSL handshake fatal lower level error %d: %s.\n", err, reason); } else { char *reason = SDMMD_ssl_strerror(ssl, 0x0); printf("lockssl_handshake: SSL handshake controlled failure %d: %s.\n", err, reason); } SSL_free(ssl); } } else { printf("_create_ssl: Could not create SSL thing.\n"); } } } else { printf("_create_ssl_context: Could not decode private key.\n"); if (cert) { X509_free(cert); result = 0x0; } } } } else { printf("lockssl_handshake: Could not create SSL bio.\n"); } return ssl; }