Skip to content

Commit

Permalink
fix(AWSIoT): Fixing crash in AWSIoTMQTTClient (#5185)
Browse files Browse the repository at this point in the history
---------
Co-authored-by: Di Wu <[email protected]>
  • Loading branch information
ruisebas authored Feb 7, 2024
1 parent 3dd9eb2 commit e209fa3
Show file tree
Hide file tree
Showing 13 changed files with 561 additions and 253 deletions.
5 changes: 5 additions & 0 deletions AWSIoT/AWSIoTDataManager.m
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,11 @@ - (instancetype)init {
return nil;
}

- (void)dealloc
{
[self.timer invalidate];
}

- (instancetype)initWithName:(NSString *)name
debug:(BOOL)enableDebugging
versioned:(BOOL)enableVersioning
Expand Down
101 changes: 56 additions & 45 deletions AWSIoT/AWSIoTManager.m
Original file line number Diff line number Diff line change
Expand Up @@ -206,19 +206,29 @@ - (void)createKeysAndCertificateFromCsr:(NSDictionary<NSString *, NSString*> *)c

SecKeyRef publicKeyRef = [AWSIoTKeychain getPublicKeyRef:publicTag];
SecKeyRef privateKeyRef = [AWSIoTKeychain getPrivateKeyRef:privateTag];
SecIdentityRef identityRef = [AWSIoTKeychain getIdentityRef:newPrivateTag certificateLabel:newCertTag];

if ([AWSIoTKeychain deleteAsymmetricKeysWithPublicTag:publicTag privateTag:privateTag] &&
[AWSIoTKeychain addPrivateKeyRef:privateKeyRef tag:newPrivateTag] &&
[AWSIoTKeychain addPublicKeyRef:publicKeyRef tag:newPublicTag] &&
[AWSIoTKeychain addCertificateToKeychain:certificatePem tag:newCertTag] &&
[AWSIoTKeychain getIdentityRef:newPrivateTag certificateLabel:newCertTag] != nil) {
identityRef != nil) {
AWSIoTCreateCertificateResponse* resp = [[AWSIoTCreateCertificateResponse alloc] init];
resp.certificateId = certificateId;
resp.certificatePem = certificatePem;
resp.certificateArn = certificateArn;

validatedResponse = resp;
}
if (identityRef) {
CFRelease(identityRef);
}
if (privateKeyRef) {
CFRelease(privateKeyRef);
}
if (publicKeyRef) {
CFRelease(publicKeyRef);
}
}
}

Expand All @@ -229,13 +239,11 @@ - (void)createKeysAndCertificateFromCsr:(NSDictionary<NSString *, NSString*> *)c
}

+ (BOOL)importIdentityFromPKCS12Data:(NSData *)pkcs12Data passPhrase:(NSString *)passPhrase certificateId:(NSString *)certificateId {
SecKeyRef privateKey = NULL;
SecKeyRef publicKey = NULL;
SecCertificateRef certRef = NULL;

[AWSIoTManager readPk12:pkcs12Data passPhrase:passPhrase certRef:&certRef privateKeyRef:&privateKey publicKeyRef:&publicKey];
__block SecKeyRef privateKey = NULL;
__block SecKeyRef publicKey = NULL;
__block SecCertificateRef certRef = NULL;

if (!certRef || !privateKey || !publicKey) {
void (^cleanup)(void) = ^void {
if (certRef) {
CFRelease(certRef);
}
Expand All @@ -245,6 +253,12 @@ + (BOOL)importIdentityFromPKCS12Data:(NSData *)pkcs12Data passPhrase:(NSString *
if (publicKey) {
CFRelease(publicKey);
}
};

[AWSIoTManager readPk12:pkcs12Data passPhrase:passPhrase certRef:&certRef privateKeyRef:&privateKey publicKeyRef:&publicKey];

if (!certRef || !privateKey || !publicKey) {
cleanup();
AWSDDLogError(@"Unable to extract PKCS12 data. Ensure the passPhrase is correct.");
return NO;
}
Expand All @@ -254,27 +268,26 @@ + (BOOL)importIdentityFromPKCS12Data:(NSData *)pkcs12Data passPhrase:(NSString *
NSString *certTag = [AWSIoTManager certTagWithCertificateId:certificateId];

if (![AWSIoTKeychain addPrivateKeyRef:privateKey tag:privateTag]) {
if (publicKey) {
CFRelease(publicKey);
}
cleanup();
AWSDDLogError(@"Unable to add private key");
return NO;
}

if (![AWSIoTKeychain addPublicKeyRef:publicKey tag:publicTag]) {
[AWSIoTKeychain deleteAsymmetricKeysWithPublicTag:publicTag privateTag:privateTag];

cleanup();
AWSDDLogError(@"Unable to add public key");
return NO;
}

if (![AWSIoTKeychain addCertificateRef:certRef tag:certTag]) {
[AWSIoTKeychain deleteAsymmetricKeysWithPublicTag:publicTag privateTag:privateTag];

cleanup();
AWSDDLogError(@"Unable to add certificate");
return NO;
}

cleanup();
return YES;
}

Expand All @@ -283,40 +296,38 @@ + (BOOL)importIdentityFromPKCS12Data:(NSData *)pkcs12Data passPhrase:(NSString *
//
+ (BOOL)readPk12:(NSData *)pk12Data passPhrase:(NSString *)passPhrase certRef:(SecCertificateRef *)certRef privateKeyRef:(SecKeyRef *)privateKeyRef publicKeyRef:(SecKeyRef *)publicKeyRef
{
SecPolicyRef policy = NULL;
SecTrustRef trust = NULL;

__block SecPolicyRef policy = NULL;
__block SecTrustRef trust = NULL;
__block CFArrayRef secImportItems = NULL;

// cleanup stuff in a block so we don't need to do this over and over again.
static BOOL (^cleanup)(void);
static BOOL (^errorCleanup)(void);
static dispatch_once_t once;
dispatch_once(&once, ^{
cleanup = ^BOOL {
if(policy) {
CFRelease(policy);
}

if(trust) {
CFRelease(trust);
}

return YES;
};

errorCleanup = ^BOOL {
*privateKeyRef = NULL;
*publicKeyRef = NULL;
*certRef = NULL;

cleanup();

return NO;
};
});

BOOL (^cleanup)(void) = ^BOOL {
if (secImportItems) {
CFRelease(secImportItems);
}

if (policy) {
CFRelease(policy);
}

if (trust) {
CFRelease(trust);
}

return YES;
};

BOOL (^errorCleanup)(void) = ^BOOL {
*privateKeyRef = NULL;
*publicKeyRef = NULL;
*certRef = NULL;

cleanup();

return NO;
};

CFDictionaryRef secImportOptions = (__bridge CFDictionaryRef) @{(__bridge id) kSecImportExportPassphrase : passPhrase};
CFArrayRef secImportItems = NULL;

OSStatus status = SecPKCS12Import((__bridge CFDataRef) pk12Data, (CFDictionaryRef) secImportOptions, &secImportItems);

if (status == errSecSuccess && CFArrayGetCount(secImportItems) > 0)
Expand Down Expand Up @@ -369,7 +380,7 @@ + (BOOL)readPk12:(NSData *)pk12Data passPhrase:(NSString *)passPhrase certRef:(S
AWSDDLogError(@"Unable to copy public key");
return errorCleanup();
}

return cleanup();
}
AWSDDLogError(@"Unable to import from PKCS12 data");
Expand Down
11 changes: 8 additions & 3 deletions AWSIoT/Internal/AWSIoTCSR.m
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,12 @@ - (NSData*)generateCSRForCertificate:(NSString*)certificateId {
NSString *privateTag = [AWSIoTKeychain.privateKeyTag stringByAppendingString:certificateId];

_publicKeyBits = [AWSIoTKeychain getPublicKeyBits:publicTag];
SecKeyRef privateKeyRef = [AWSIoTKeychain getPrivateKeyRef:privateTag];
if (!_publicKeyBits) {
return nil;
}

if (!_publicKeyBits || !privateKeyRef) {
SecKeyRef privateKeyRef = [AWSIoTKeychain getPrivateKeyRef:privateTag];
if (!privateKeyRef) {
return nil;
}

Expand Down Expand Up @@ -113,7 +116,9 @@ - (NSData*)generateCSRForCertificate:(NSString*)certificateId {
[scr appendData:signdata];

[self addByte:seqTag intoData:scr];


CFRelease(privateKeyRef);

return [scr copy];
}

Expand Down
20 changes: 10 additions & 10 deletions AWSIoT/Internal/AWSIoTKeychain.m
Original file line number Diff line number Diff line change
Expand Up @@ -137,13 +137,13 @@ + (BOOL)isValidCertificate:(NSString*)privateKeyTag certificateLabel:(NSString*)
if (identityRef) {
SecCertificateRef cert = NULL;
OSStatus status = SecIdentityCopyCertificate(identityRef, &cert);
CFRelease(identityRef);
if (status == noErr) {
return YES;
} else {
AWSDDLogError(@"SecIdentityCopyCertificate failed [%d]", (int)status);
}
}

return NO;
}

Expand Down Expand Up @@ -205,7 +205,10 @@ + (BOOL)addCertificate:(NSData*)cert withTag:(NSString*)tag {
AWSDDLogError(@"Error create Sec Certificate from data");
return NO;
}
return [AWSIoTKeychain addCertificateRef:certRef tag:tag];

BOOL result = [AWSIoTKeychain addCertificateRef:certRef tag:tag];
CFRelease(certRef);
return result;
}

+ (BOOL)addCertificateRef:(SecCertificateRef)certRef {
Expand Down Expand Up @@ -305,7 +308,7 @@ + (NSData *)getPublicKeyBits:(NSString*)tag {
publicKeyRef = NULL;
}

return (__bridge NSData *)publicKeyRef;
return (__bridge_transfer NSData *)publicKeyRef;
}

+ (SecKeyRef)getPrivateKeyRef:(NSString*)tag {
Expand Down Expand Up @@ -347,7 +350,7 @@ + (NSData *)getPrivateKeyBits:(NSString*)tag {
privateKeyBits = NULL;
}

return (__bridge NSData *)privateKeyBits;
return (__bridge_transfer NSData *)privateKeyBits;
}

+ (SecIdentityRef)getIdentityRef:(NSString*)privateKeyTag certificateLabel:(NSString *)certificateLabel {
Expand All @@ -374,8 +377,7 @@ + (SecIdentityRef)getIdentityRef:(NSString*)privateKeyTag certificateLabel:(NSSt
+ (BOOL)addPublicKeyRef:(SecKeyRef)pubkeyRef tag:(NSString*)tag {

OSStatus sanityCheck = noErr;
CFTypeRef persistPeer = NULL;


NSMutableDictionary * publicKeyAttr = [[NSMutableDictionary alloc] init];

[publicKeyAttr setObject:(id)kSecClassKey forKey:(id)kSecClass];
Expand All @@ -386,7 +388,7 @@ + (BOOL)addPublicKeyRef:(SecKeyRef)pubkeyRef tag:(NSString*)tag {
[publicKeyAttr setObject:[NSNumber numberWithBool:YES] forKey:(id)kSecReturnPersistentRef];
[publicKeyAttr setObject:(__bridge id)[AWSIoTKeychain accessibilityType] forKey:(id)kSecAttrAccessible];

sanityCheck = SecItemAdd((CFDictionaryRef) publicKeyAttr, (CFTypeRef *)&persistPeer);
sanityCheck = SecItemAdd((CFDictionaryRef) publicKeyAttr, nil);
if ((sanityCheck != noErr) && (sanityCheck != errSecDuplicateItem)){
AWSDDLogError(@"addPublicKeyRef error: %d",(int)sanityCheck);
return NO;
Expand Down Expand Up @@ -422,8 +424,6 @@ + (BOOL)addPublicKey:(NSData*)pubkey tag:(NSString*)tag {
+ (BOOL)addPrivateKeyRef:(SecKeyRef)privkeyRef tag:(NSString*)tag {

OSStatus sanityCheck = noErr;
CFTypeRef persistPeer = NULL;

NSMutableDictionary * privateKeyAttr = [[NSMutableDictionary alloc] init];

[privateKeyAttr setObject:(id)kSecClassKey forKey:(id)kSecClass];
Expand All @@ -434,7 +434,7 @@ + (BOOL)addPrivateKeyRef:(SecKeyRef)privkeyRef tag:(NSString*)tag {
[privateKeyAttr setObject:[NSNumber numberWithBool:YES] forKey:(id)kSecReturnPersistentRef];
[privateKeyAttr setObject:(__bridge id)[AWSIoTKeychain accessibilityType] forKey:(id)kSecAttrAccessible];

sanityCheck = SecItemAdd((CFDictionaryRef) privateKeyAttr, (CFTypeRef *)&persistPeer);
sanityCheck = SecItemAdd((CFDictionaryRef) privateKeyAttr, nil);
if ((sanityCheck != noErr) && (sanityCheck != errSecDuplicateItem)){
AWSDDLogError(@"addPrivateKeyRef error: %d",(int)sanityCheck);
return NO;
Expand Down
Loading

0 comments on commit e209fa3

Please sign in to comment.