Skip to content

Commit f3e7f21

Browse files
authored
Merge pull request #2325 from nextcloud/chore/noid/replace-openssl
chore: Replace openSSL with native methods
2 parents fd7cfe6 + 50fb88c commit f3e7f21

12 files changed

Lines changed: 385 additions & 413 deletions

File tree

NextcloudTalk.xcodeproj/project.pbxproj

Lines changed: 107 additions & 25 deletions
Large diffs are not rendered by default.

NextcloudTalk/AppDelegate.m

Lines changed: 25 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@
2424
#import "NCNavigationController.h"
2525
#import "NCNotificationController.h"
2626
#import "NCPushNotification.h"
27-
#import "NCPushNotificationsUtils.h"
2827
#import "NCRoomsManager.h"
2928
#import "NCSettingsController.h"
3029
#import "NCUserInterfaceController.h"
@@ -344,16 +343,19 @@ - (void)application:(UIApplication *)application didReceiveRemoteNotification:(N
344343
{
345344
// Called when a background notification is delivered.
346345
NSString *message = [userInfo objectForKey:@"subject"];
346+
NSString *signature = [userInfo objectForKey:@"signature"];
347+
348+
if (!message || !signature) {
349+
return;
350+
}
351+
347352
for (TalkAccount *account in [[NCDatabaseManager sharedInstance] allAccounts]) {
348-
NSData *pushNotificationPrivateKey = [[NCKeyChainController sharedInstance] pushNotificationPrivateKeyForAccountId:account.accountId];
349-
if (message && pushNotificationPrivateKey) {
350-
NSString *decryptedMessage = [NCPushNotificationsUtils decryptPushNotification:message withDevicePrivateKey:pushNotificationPrivateKey];
351-
if (decryptedMessage) {
352-
NCPushNotification *pushNotification = [NCPushNotification pushNotificationFromDecryptedString:decryptedMessage withAccountId:account.accountId];
353-
[[NCNotificationController sharedInstance] processBackgroundPushNotification:pushNotification];
354-
355-
break;
356-
}
353+
NSString *decryptedMessage = [NCPushNotificationsUtils decryptPushNotificationWithMessageBase64:message withSignatureBase64:signature forAccount:account];
354+
if (decryptedMessage) {
355+
NCPushNotification *pushNotification = [NCPushNotification pushNotificationFromDecryptedString:decryptedMessage withAccountId:account.accountId];
356+
[[NCNotificationController sharedInstance] processBackgroundPushNotification:pushNotification];
357+
358+
break;
357359
}
358360
}
359361

@@ -382,25 +384,23 @@ - (void)pushRegistry:(PKPushRegistry *)registry didReceiveIncomingPushWithPayloa
382384
[NCUtils log:@"Received PushKit notification"];
383385

384386
NSString *message = [payload.dictionaryPayload objectForKey:@"subject"];
385-
for (TalkAccount *account in [[NCDatabaseManager sharedInstance] allAccounts]) {
386-
NSData *pushNotificationPrivateKey = [[NCKeyChainController sharedInstance] pushNotificationPrivateKeyForAccountId:account.accountId];
387+
NSString *signature = [payload.dictionaryPayload objectForKey:@"signature"];
387388

388-
if (!message || !pushNotificationPrivateKey) {
389-
continue;
390-
}
391-
392-
NSString *decryptedMessage = [NCPushNotificationsUtils decryptPushNotification:message withDevicePrivateKey:pushNotificationPrivateKey];
389+
if (message && signature) {
390+
for (TalkAccount *account in [[NCDatabaseManager sharedInstance] allAccounts]) {
391+
NSString *decryptedMessage = [NCPushNotificationsUtils decryptPushNotificationWithMessageBase64:message withSignatureBase64:signature forAccount:account];
393392

394-
if (!decryptedMessage) {
395-
continue;
396-
}
393+
if (!decryptedMessage) {
394+
continue;
395+
}
397396

398-
NCPushNotification *pushNotification = [NCPushNotification pushNotificationFromDecryptedString:decryptedMessage withAccountId:account.accountId];
397+
NCPushNotification *pushNotification = [NCPushNotification pushNotificationFromDecryptedString:decryptedMessage withAccountId:account.accountId];
399398

400-
if ( pushNotification && pushNotification.type == NCPushNotificationTypeCall) {
401-
[[NCNotificationController sharedInstance] showIncomingCallForPushNotification:pushNotification];
402-
completion();
403-
return;
399+
if (pushNotification && pushNotification.type == NCPushNotificationTypeCall) {
400+
[[NCNotificationController sharedInstance] showIncomingCallForPushNotification:pushNotification];
401+
completion();
402+
return;
403+
}
404404
}
405405
}
406406

NextcloudTalk/Database/TalkAccount.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ NS_ASSUME_NONNULL_BEGIN
2929
@property NSInteger lastPushSubscription;
3030
@property NSString *deviceIdentifier;
3131
@property NSString *deviceSignature;
32-
@property NSString *userPublicKey;
32+
@property NSString * _Nullable userPublicKey;
3333
@property NSInteger unreadBadgeNumber;
3434
@property BOOL unreadNotification;
3535
@property NSInteger lastContactSync;
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
//
2+
// SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
3+
// SPDX-License-Identifier: GPL-3.0-or-later
4+
//
5+
6+
@objcMembers
7+
public class NCPushNotificationKeyPair: NSObject {
8+
9+
public var privateKey: Data
10+
public var publicKey: Data
11+
12+
init(privateKey: Data, publicKey: Data) {
13+
self.privateKey = privateKey
14+
self.publicKey = publicKey
15+
}
16+
}

NextcloudTalk/Notifications/NCPushNotificationsUtils.h

Lines changed: 0 additions & 16 deletions
This file was deleted.

NextcloudTalk/Notifications/NCPushNotificationsUtils.m

Lines changed: 0 additions & 53 deletions
This file was deleted.
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
//
2+
// SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
3+
// SPDX-License-Identifier: GPL-3.0-or-later
4+
//
5+
6+
import SwiftyRSA
7+
8+
@objcMembers
9+
public class NCPushNotificationsUtils: NSObject {
10+
11+
public static func decryptPushNotification(withMessageBase64 messageBase64: String, withSignatureBase64 signatureBase64: String, forAccount account: TalkAccount) -> String? {
12+
do {
13+
guard let userPublicKeyPem = account.userPublicKey else { return nil }
14+
15+
let encryptedMessage = try EncryptedMessage(base64Encoded: messageBase64)
16+
let userPublicKey = try RsaPublicKey(pemEncoded: userPublicKeyPem)
17+
let signature = try Signature(base64Encoded: signatureBase64)
18+
19+
guard try encryptedMessage.verify(with: userPublicKey, signature: signature, digestType: .sha512) else {
20+
return nil
21+
}
22+
23+
guard let devicePrivateKeyData = NCKeyChainController.sharedInstance().pushNotificationPrivateKey(forAccountId: account.accountId),
24+
let devicePrivateKeyPem = String(data: devicePrivateKeyData, encoding: .utf8) else {
25+
return nil
26+
}
27+
28+
let devicePrivateKey = try RsaPrivateKey(pemEncoded: devicePrivateKeyPem)
29+
let clearMessage = try encryptedMessage.decrypted(with: devicePrivateKey, padding: .PKCS1)
30+
31+
return try clearMessage.string(encoding: .utf8)
32+
} catch {
33+
print("decryptPushNotificationError: \(error)")
34+
}
35+
36+
return nil
37+
}
38+
39+
public static func generatePushNotificationKeyPair() -> NCPushNotificationKeyPair? {
40+
do {
41+
let keyPair = try SwiftyRSA.generateRSAKeyPair(sizeInBits: 2048)
42+
43+
let privateKeyPem = try keyPair.privateKey.pemStringPkcs8()
44+
let publicKeyPem = try keyPair.publicKey.pemStringPkcs8()
45+
46+
return NCPushNotificationKeyPair(privateKey: privateKeyPem.data(using: .utf8)!, publicKey: publicKeyPem.data(using: .utf8)!)
47+
} catch {
48+
NCUtils.log("Error generating push keypair: \(error)")
49+
}
50+
51+
return nil
52+
}
53+
54+
}

NextcloudTalk/Security/CCCertificate.m

Lines changed: 17 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,10 @@
55

66
#import "CCCertificate.h"
77

8-
#import <openssl/x509.h>
9-
#import <openssl/bio.h>
10-
#import <openssl/err.h>
11-
#import <openssl/pem.h>
12-
138
#import "NCAppBranding.h"
149

10+
#import "NextcloudTalk-Swift.h"
11+
1512
@implementation CCCertificate
1613

1714
NSString *const appCertificates = @"Library/Application Support/Certificates";
@@ -79,45 +76,23 @@ - (BOOL)checkTrustedChallenge:(NSURLAuthenticationChallenge *)challenge
7976
- (void)saveCertificate:(SecTrustRef)trust withName:(NSString *)certName
8077
{
8178
SecCertificateRef currentServerCert = SecTrustGetLeafCertificate(trust);
82-
8379
CFDataRef data = SecCertificateCopyData(currentServerCert);
84-
X509 *x509cert = NULL;
85-
if (data) {
86-
BIO *mem = BIO_new_mem_buf((void *)CFDataGetBytePtr(data), (int)CFDataGetLength(data));
87-
x509cert = d2i_X509_bio(mem, NULL);
88-
BIO_free(mem);
89-
CFRelease(data);
90-
91-
if (!x509cert) {
92-
93-
NSLog(@"[LOG] OpenSSL couldn't parse X509 Certificate");
94-
95-
} else {
96-
97-
NSString *localCertificatesFolder = [self getDirectoryCerificates];
98-
99-
certName = [NSString stringWithFormat:@"%@/%@",localCertificatesFolder,certName];
100-
101-
if ([[NSFileManager defaultManager] fileExistsAtPath:certName]) {
102-
NSError *error;
103-
[[NSFileManager defaultManager] removeItemAtPath:certName error:&error];
104-
}
105-
106-
FILE *file;
107-
file = fopen([certName UTF8String], "w");
108-
if (file) {
109-
PEM_write_X509(file, x509cert);
110-
}
111-
fclose(file);
112-
}
113-
114-
} else {
115-
116-
NSLog(@"[LOG] Failed to retrieve DER data from Certificate Ref");
80+
81+
if (!data) {
82+
return;
11783
}
118-
119-
//Free
120-
X509_free(x509cert);
84+
85+
NSData *nsData = (__bridge NSData *)(data);
86+
NSString *base64Certificate = [nsData base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength | NSDataBase64EncodingEndLineWithLineFeed];
87+
88+
if (!base64Certificate) {
89+
return;
90+
}
91+
92+
NSString *localCertificatesFolder = [self getDirectoryCerificates];
93+
certName = [NSString stringWithFormat:@"%@/%@", localCertificatesFolder, certName];
94+
95+
[base64Certificate writeToFile:certName atomically:YES encoding:NSUTF8StringEncoding error:nil];
12196
}
12297

12398
- (void)presentViewControllerCertificateWithTitle:(NSString *)title viewController:(UIViewController *)viewController delegate:(id)delegate

NextcloudTalk/Settings/NCKeyChainController.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,9 @@ extern NSString * const kNCPushKitTokenKey;
2020
- (void)setToken:(NSString *)token forAccountId:(NSString *)accountId;
2121
- (NSString *)tokenForAccountId:(NSString *)accountId;
2222
- (void)setPushNotificationPublicKey:(NSData *)privateKey forAccountId:(NSString *)accountId;
23-
- (NSData *)pushNotificationPublicKeyForAccountId:(NSString *)accountId;
23+
- (NSData * _Nullable)pushNotificationPublicKeyForAccountId:(NSString *)accountId;
2424
- (void)setPushNotificationPrivateKey:(NSData *)privateKey forAccountId:(NSString *)accountId;
25-
- (NSData *)pushNotificationPrivateKeyForAccountId:(NSString *)accountId;
25+
- (NSData * _Nullable)pushNotificationPrivateKeyForAccountId:(NSString *)accountId;
2626
- (NSString *)pushTokenSHA512;
2727
- (void)logCombinedPushToken;
2828
- (NSString *)combinedPushToken;

NextcloudTalk/Settings/NCSettingsController.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,6 @@ typedef NS_ENUM(NSInteger, NCPreferredFileSorting) {
6666
- (void)connectDisconnectedExternalSignalingControllers;
6767
- (void)disconnectAllExternalSignalingControllers;
6868
- (void)subscribeForPushNotificationsForAccountId:(NSString *)accountId withCompletionBlock:(SubscribeForPushNotificationsCompletionBlock)block;
69-
- (NSInteger)chatMaxLengthConfigCapability;
7069
- (BOOL)canCreateGroupAndPublicRooms;
7170
- (BOOL)isGuestsAppEnabled;
7271
- (BOOL)isReferenceApiSupported;

0 commit comments

Comments
 (0)