Swift Exception wrap Curve25519

pull/1/head
Michael Kirk 7 years ago
parent c686e766b1
commit c4f8975308

@ -83,9 +83,9 @@ NSErrorDomain const ContactDiscoveryServiceErrorDomain = @"SignalServiceKit.Cont
NSData *ephemeralToStatic; NSData *ephemeralToStatic;
@try { @try {
ephemeralToEphemeral = ephemeralToEphemeral =
[Curve25519 generateSharedSecretFromPublicKey:self.serverEphemeralPublic andKeyPair:self.keyPair]; [Curve25519 try_generateSharedSecretFromPublicKey:self.serverEphemeralPublic andKeyPair:self.keyPair];
ephemeralToStatic = ephemeralToStatic =
[Curve25519 generateSharedSecretFromPublicKey:self.serverStaticPublic andKeyPair:self.keyPair]; [Curve25519 try_generateSharedSecretFromPublicKey:self.serverStaticPublic andKeyPair:self.keyPair];
} @catch (NSException *exception) { } @catch (NSException *exception) {
OWSFailDebug(@"could not generate shared secrets: %@", exception); OWSFailDebug(@"could not generate shared secrets: %@", exception);
return NO; return NO;

@ -54,11 +54,7 @@ NS_ASSUME_NONNULL_BEGIN
- (nullable NSData *)encrypt:(NSData *)dataToEncrypt - (nullable NSData *)encrypt:(NSData *)dataToEncrypt
{ {
@try { @try {
// Exceptions can be thrown in a number of places in encryptUnsafe, e.g.: return [self try_encryptWithData:dataToEncrypt];
//
// * Curve25519's generateSharedSecretFromPublicKey.
// * [HKDFKit deriveKey].
return [self encryptUnsafe:dataToEncrypt];
} @catch (NSException *exception) { } @catch (NSException *exception) {
OWSFailDebug(@"exception: %@ of type: %@ with reason: %@, user info: %@.", OWSFailDebug(@"exception: %@ of type: %@ with reason: %@, user info: %@.",
exception.description, exception.description,
@ -69,10 +65,10 @@ NS_ASSUME_NONNULL_BEGIN
} }
} }
- (nullable NSData *)encryptUnsafe:(NSData *)dataToEncrypt - (nullable NSData *)try_encryptWithData:(NSData *)dataToEncrypt
{ {
NSData *sharedSecret = NSData *sharedSecret =
[Curve25519 generateSharedSecretFromPublicKey:self.theirPublicKey andKeyPair:self.ourKeyPair]; [Curve25519 try_generateSharedSecretFromPublicKey:self.theirPublicKey andKeyPair:self.ourKeyPair];
NSData *infoData = [@"TextSecure Provisioning Message" dataUsingEncoding:NSASCIIStringEncoding]; NSData *infoData = [@"TextSecure Provisioning Message" dataUsingEncoding:NSASCIIStringEncoding];
NSData *nullSalt = [[NSMutableData dataWithLength:32] copy]; NSData *nullSalt = [[NSMutableData dataWithLength:32] copy];

@ -479,7 +479,7 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
failure:(RetryableFailureHandler)failure failure:(RetryableFailureHandler)failure
{ {
[self.udManager [self.udManager
ensureSenderCertificateObjCWithSuccess:^(SMKSenderCertificate *senderCertificate) { trywrapped_ensureSenderCertificateWithSuccess:^(SMKSenderCertificate *senderCertificate) {
dispatch_async([OWSDispatch sendingQueue], ^{ dispatch_async([OWSDispatch sendingQueue], ^{
[self sendMessageToService:message senderCertificate:senderCertificate success:success failure:failure]; [self sendMessageToService:message senderCertificate:senderCertificate success:success failure:failure];
}); });

@ -65,7 +65,7 @@ private func string(forUnidentifiedAccessMode mode: UnidentifiedAccessMode) -> S
// We use completion handlers instead of a promise so that message sending // We use completion handlers instead of a promise so that message sending
// logic can access the strongly typed certificate data. // logic can access the strongly typed certificate data.
@objc @objc
func ensureSenderCertificateObjC(success:@escaping (SMKSenderCertificate) -> Void, func trywrapped_ensureSenderCertificate(success:@escaping (SMKSenderCertificate) -> Void,
failure:@escaping (Error) -> Void) failure:@escaping (Error) -> Void)
// MARK: Unrestricted Access // MARK: Unrestricted Access
@ -109,7 +109,9 @@ public class OWSUDManagerImpl: NSObject, OWSUDManager {
guard TSAccountManager.isRegistered() else { guard TSAccountManager.isRegistered() else {
return return
} }
self.ensureSenderCertificate().retainUntilComplete()
// Any error is silently ignored on startup.
self.trywrapped_ensureSenderCertificate().retainUntilComplete()
} }
NotificationCenter.default.addObserver(self, NotificationCenter.default.addObserver(self,
selector: #selector(registrationStateDidChange), selector: #selector(registrationStateDidChange),
@ -121,7 +123,8 @@ public class OWSUDManagerImpl: NSObject, OWSUDManager {
func registrationStateDidChange() { func registrationStateDidChange() {
AssertIsOnMainThread() AssertIsOnMainThread()
ensureSenderCertificate().retainUntilComplete() // Any error is silently ignored
trywrapped_ensureSenderCertificate().retainUntilComplete()
} }
// MARK: - // MARK: -
@ -263,12 +266,12 @@ public class OWSUDManagerImpl: NSObject, OWSUDManager {
#if DEBUG #if DEBUG
@objc @objc
public func hasSenderCertificate() -> Bool { public func trywrapped_hasSenderCertificate() -> Bool {
return senderCertificate() != nil return trywrapped_senderCertificate() != nil
} }
#endif #endif
private func senderCertificate() -> SMKSenderCertificate? { private func trywrapped_senderCertificate() -> SMKSenderCertificate? {
guard let certificateData = dbConnection.object(forKey: senderCertificateKey(), inCollection: kUDCollection) as? Data else { guard let certificateData = dbConnection.object(forKey: senderCertificateKey(), inCollection: kUDCollection) as? Data else {
return nil return nil
} }
@ -276,7 +279,7 @@ public class OWSUDManagerImpl: NSObject, OWSUDManager {
do { do {
let certificate = try SMKSenderCertificate.parse(data: certificateData) let certificate = try SMKSenderCertificate.parse(data: certificateData)
guard isValidCertificate(certificate) else { guard trywrapped_isValidCertificate(certificate) else {
Logger.warn("Current sender certificate is not valid.") Logger.warn("Current sender certificate is not valid.")
return nil return nil
} }
@ -297,10 +300,10 @@ public class OWSUDManagerImpl: NSObject, OWSUDManager {
} }
@objc @objc
public func ensureSenderCertificateObjC(success:@escaping (SMKSenderCertificate) -> Void, public func trywrapped_ensureSenderCertificate(success:@escaping (SMKSenderCertificate) -> Void,
failure:@escaping (Error) -> Void) { failure:@escaping (Error) -> Void) {
firstly { firstly {
ensureSenderCertificate() trywrapped_ensureSenderCertificate()
}.map { certificate in }.map { certificate in
success(certificate) success(certificate)
}.catch { error in }.catch { error in
@ -308,15 +311,15 @@ public class OWSUDManagerImpl: NSObject, OWSUDManager {
}.retainUntilComplete() }.retainUntilComplete()
} }
public func ensureSenderCertificate() -> Promise<SMKSenderCertificate> { public func trywrapped_ensureSenderCertificate() -> Promise<SMKSenderCertificate> {
// If there is a valid cached sender certificate, use that. // If there is a valid cached sender certificate, use that.
if let certificate = senderCertificate() { if let certificate = trywrapped_senderCertificate() {
return Promise.value(certificate) return Promise.value(certificate)
} }
// Try to obtain a new sender certificate. // Try to obtain a new sender certificate.
return firstly { return firstly {
requestSenderCertificate() trywrapped_requestSenderCertificate()
}.map { (certificateData: Data, certificate: SMKSenderCertificate) in }.map { (certificateData: Data, certificate: SMKSenderCertificate) in
// Cache the current sender certificate. // Cache the current sender certificate.
@ -326,13 +329,13 @@ public class OWSUDManagerImpl: NSObject, OWSUDManager {
} }
} }
private func requestSenderCertificate() -> Promise<(certificateData: Data, certificate: SMKSenderCertificate)> { private func trywrapped_requestSenderCertificate() -> Promise<(certificateData: Data, certificate: SMKSenderCertificate)> {
return firstly { return firstly {
SignalServiceRestClient().requestUDSenderCertificate() SignalServiceRestClient().requestUDSenderCertificate()
}.map { certificateData -> (certificateData: Data, certificate: SMKSenderCertificate) in }.map { certificateData -> (certificateData: Data, certificate: SMKSenderCertificate) in
let certificate = try SMKSenderCertificate.parse(data: certificateData) let certificate = try SMKSenderCertificate.parse(data: certificateData)
guard self.isValidCertificate(certificate) else { guard self.trywrapped_isValidCertificate(certificate) else {
throw OWSUDError.invalidData(description: "Invalid sender certificate returned by server") throw OWSUDError.invalidData(description: "Invalid sender certificate returned by server")
} }
@ -340,7 +343,7 @@ public class OWSUDManagerImpl: NSObject, OWSUDManager {
} }
} }
private func isValidCertificate(_ certificate: SMKSenderCertificate) -> Bool { private func trywrapped_isValidCertificate(_ certificate: SMKSenderCertificate) -> Bool {
// Ensure that the certificate will not expire in the next hour. // Ensure that the certificate will not expire in the next hour.
// We want a threshold long enough to ensure that any outgoing message // We want a threshold long enough to ensure that any outgoing message
// sends will complete before the expiration. // sends will complete before the expiration.
@ -348,7 +351,7 @@ public class OWSUDManagerImpl: NSObject, OWSUDManager {
let anHourFromNowMs = nowMs + kHourInMs let anHourFromNowMs = nowMs + kHourInMs
do { do {
try certificateValidator.validate(senderCertificate: certificate, validationTime: anHourFromNowMs) try certificateValidator.trywrapped_validate(senderCertificate: certificate, validationTime: anHourFromNowMs)
return true return true
} catch { } catch {
OWSLogger.error("Invalid certificate") OWSLogger.error("Invalid certificate")

@ -29,11 +29,19 @@ NSString *const OWSPrimaryStorageKeyPrekeyCurrentSignedPrekeyId = @"currentSigne
// Signed prekey ids must be > 0. // Signed prekey ids must be > 0.
int preKeyId = 1 + arc4random_uniform(INT32_MAX - 1); int preKeyId = 1 + arc4random_uniform(INT32_MAX - 1);
ECKeyPair *_Nullable identityKeyPair = [[OWSIdentityManager sharedManager] identityKeyPair]; ECKeyPair *_Nullable identityKeyPair = [[OWSIdentityManager sharedManager] identityKeyPair];
return [[SignedPreKeyRecord alloc] OWSAssert(identityKeyPair);
initWithId:preKeyId @try {
keyPair:keyPair return [[SignedPreKeyRecord alloc]
signature:[Ed25519 sign:keyPair.publicKey.prependKeyType withKeyPair:identityKeyPair] initWithId:preKeyId
generatedAt:[NSDate date]]; keyPair:keyPair
signature:[Ed25519 try_sign:keyPair.publicKey.prependKeyType withKeyPair:identityKeyPair]
generatedAt:[NSDate date]];
} @catch (NSException *exception) {
// try_sign only throws when the data to sign is empty or `keyPair`.
// Neither of which should happen.
OWSFail(@"exception: %@", exception);
return nil;
}
} }
- (SignedPreKeyRecord *)try_loadSignedPrekey:(int)signedPreKeyId - (SignedPreKeyRecord *)try_loadSignedPrekey:(int)signedPreKeyId

Loading…
Cancel
Save