Skip to content

Commit

Permalink
Use synchronizable keys for Darwin credentials issuer (#8044)
Browse files Browse the repository at this point in the history
  • Loading branch information
pan-apple authored and pull[bot] committed Aug 6, 2021
1 parent 4bc8e81 commit e39590e
Show file tree
Hide file tree
Showing 2 changed files with 87 additions and 35 deletions.
10 changes: 7 additions & 3 deletions src/darwin/Framework/CHIP/CHIPOperationalCredentialsDelegate.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,12 @@ class CHIPOperationalCredentialsDelegate : public chip::Controller::OperationalC

private:
CHIP_ERROR GenerateKeys();
CHIP_ERROR StoreKeysInKeyChain(NSData * keypairData);
CHIP_ERROR LoadKeysFromKeyChain();
CHIP_ERROR LoadDeprecatedKeysFromKeyChain();
CHIP_ERROR DeleteKeys();

CHIP_ERROR ConvertToP256Keypair(SecKeyRef privateKey);
CHIP_ERROR ConvertToP256Keypair(NSData * keypairData);

CHIP_ERROR SetIssuerID(CHIPPersistentStorageDelegateBridge * storage);

Expand All @@ -57,8 +59,10 @@ class CHIPOperationalCredentialsDelegate : public chip::Controller::OperationalC
uint32_t mIssuerId = 1234;

const uint32_t kCertificateValiditySecs = 365 * 24 * 60 * 60;
const NSString * kCHIPCAKeyLabel = @"chip.nodeopcerts.CA:0";
const NSData * kCHIPCAKeyTag = [@"com.zigbee.chip.commissioner.ca.issuer.id" dataUsingEncoding:NSUTF8StringEncoding];
const NSString * kCHIPCADeprecatedKeyLabel = @"chip.nodeopcerts.CA:0";
const NSData * kCHIPCADeprecatedKeyTag = [@"com.zigbee.chip.commissioner.ca.issuer.id" dataUsingEncoding:NSUTF8StringEncoding];
const NSString * kCHIPCAKeyLabel = @"matter.nodeopcerts.CA:0";
const NSData * kCHIPCAKeyTag = [@"com.zigbee.matter.commissioner.ca.issuer.id" dataUsingEncoding:NSUTF8StringEncoding];

id mKeyType = (id) kSecAttrKeyTypeECSECPrimeRandom;
id mKeySize = @256;
Expand Down
112 changes: 80 additions & 32 deletions src/darwin/Framework/CHIP/CHIPOperationalCredentialsDelegate.mm
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,13 @@ static BOOL isRunningTests(void)
mStorage = storage;

CHIP_ERROR err = LoadKeysFromKeyChain();

// TODO - Remove use of deprecated storage for Darwin keys
if (err != CHIP_NO_ERROR) {
// Try loading the deprecated keys.
err = LoadDeprecatedKeysFromKeyChain();
}

if (err != CHIP_NO_ERROR) {
// Generate keys if keys could not be loaded
err = GenerateKeys();
Expand Down Expand Up @@ -78,14 +85,8 @@ static BOOL isRunningTests(void)
return CHIP_NO_ERROR;
}

CHIP_ERROR CHIPOperationalCredentialsDelegate::ConvertToP256Keypair(SecKeyRef keypair)
CHIP_ERROR CHIPOperationalCredentialsDelegate::ConvertToP256Keypair(NSData * keypairData)
{
NSData * keypairData = (__bridge_transfer NSData *) SecKeyCopyExternalRepresentation(keypair, nil);
if (keypairData == nil) {
NSLog(@"Failed in getting keypair data");
return CHIP_ERROR_INTERNAL;
}

chip::Crypto::P256SerializedKeypair serialized;
if ([keypairData length] != serialized.Capacity()) {
NSLog(@"Keypair length %zu does not match expected length %zu", [keypairData length], serialized.Capacity());
Expand All @@ -100,15 +101,38 @@ static BOOL isRunningTests(void)
}

CHIP_ERROR CHIPOperationalCredentialsDelegate::LoadKeysFromKeyChain()
{
const NSDictionary * query = @{
(id) kSecClass : (id) kSecClassGenericPassword,
(id) kSecAttrService : kCHIPCAKeyLabel,
(id) kSecAttrSynchronizable : @YES,
(id) kSecReturnData : @YES,
};

CFDataRef keyDataRef;
OSStatus status = SecItemCopyMatching((CFDictionaryRef) query, (CFTypeRef *) &keyDataRef);
if (status == errSecItemNotFound || keyDataRef == nil) {
CHIP_LOG_ERROR("Did not find an existing key in the keychain");
return CHIP_ERROR_KEY_NOT_FOUND;
}

CHIP_LOG_ERROR("Found an existing keypair in the keychain");
NSData * keyData = CFBridgingRelease(keyDataRef);

NSData * privateKey = [[NSData alloc] initWithBase64EncodedData:keyData options:0];
return ConvertToP256Keypair(privateKey);
}

CHIP_ERROR CHIPOperationalCredentialsDelegate::LoadDeprecatedKeysFromKeyChain()
{
SecKeyRef privateKey;

const NSDictionary * query = @ {
(id) kSecClass : (id) kSecClassKey,
(id) kSecAttrKeyType : mKeyType,
(id) kSecAttrKeySizeInBits : mKeySize,
(id) kSecAttrLabel : kCHIPCAKeyLabel,
(id) kSecAttrApplicationTag : kCHIPCAKeyTag,
(id) kSecAttrLabel : kCHIPCADeprecatedKeyLabel,
(id) kSecAttrApplicationTag : kCHIPCADeprecatedKeyTag,
(id) kSecReturnRef : (id) kCFBooleanTrue
};

Expand All @@ -118,8 +142,40 @@ static BOOL isRunningTests(void)
return CHIP_ERROR_KEY_NOT_FOUND;
}

CHIP_LOG_ERROR("Found an existing keypair in the keychain");
return ConvertToP256Keypair(privateKey);
NSData * keypairData = (__bridge_transfer NSData *) SecKeyCopyExternalRepresentation(privateKey, nil);
if (keypairData == nil) {
NSLog(@"Failed in getting keypair data");
return CHIP_ERROR_INTERNAL;
}

// Store the key in the new format, so that henceforth the deprecated key storage won't be needed
CHIP_ERROR errorCode = StoreKeysInKeyChain(keypairData);
if (errorCode != CHIP_NO_ERROR) {
return errorCode;
}

CHIP_LOG_ERROR("Found an existing keypair in deprecated format in the keychain");
return ConvertToP256Keypair(keypairData);
}

CHIP_ERROR CHIPOperationalCredentialsDelegate::StoreKeysInKeyChain(NSData * keypairData)
{
const NSDictionary * addParams = @{
(id) kSecClass : (id) kSecClassGenericPassword,
(id) kSecAttrService : kCHIPCAKeyLabel,
(id) kSecAttrSynchronizable : @YES,
(id) kSecValueData : [keypairData base64EncodedDataWithOptions:0],
};

OSStatus status = SecItemAdd((__bridge CFDictionaryRef) addParams, NULL);
// TODO: Enable SecItemAdd for Darwin unit tests
if (status != errSecSuccess && !isRunningTests()) {
NSLog(@"Failed in storing key : %d", status);
return CHIP_ERROR_INTERNAL;
}

NSLog(@"Stored the keys");
return CHIP_NO_ERROR;
}

CHIP_ERROR CHIPOperationalCredentialsDelegate::GenerateKeys()
Expand All @@ -143,37 +199,29 @@ static BOOL isRunningTests(void)
return CHIP_ERROR_INTERNAL;
}

const NSDictionary * addParams = @ {
(id) kSecClass : (id) kSecClassKey,
(id) kSecAttrKeyType : mKeyType,
(id) kSecAttrKeySizeInBits : mKeySize,
(id) kSecAttrLabel : kCHIPCAKeyLabel,
(id) kSecAttrApplicationTag : kCHIPCAKeyTag,
(id) kSecValueRef : (__bridge id) privateKey,
};

status = SecItemAdd((__bridge CFDictionaryRef) addParams, NULL);
// TODO: Enable SecItemAdd for Darwin unit tests
if (status != errSecSuccess && !isRunningTests()) {
NSLog(@"Failed in storing key : %d", status);
NSData * keypairData = (__bridge_transfer NSData *) SecKeyCopyExternalRepresentation(privateKey, nil);
if (keypairData == nil) {
NSLog(@"Failed in getting keypair data");
return CHIP_ERROR_INTERNAL;
}

NSLog(@"Stored the keys");
return ConvertToP256Keypair(privateKey);
CHIP_ERROR errorCode = StoreKeysInKeyChain(keypairData);
if (errorCode != CHIP_NO_ERROR) {
return errorCode;
}

return ConvertToP256Keypair(keypairData);
}

CHIP_ERROR CHIPOperationalCredentialsDelegate::DeleteKeys()
{
CHIP_LOG_ERROR("Deleting current CA keys");
OSStatus status = noErr;

const NSDictionary * deleteParams = @ {
(id) kSecClass : (id) kSecClassKey,
(id) kSecAttrKeyType : mKeyType,
(id) kSecAttrKeySizeInBits : mKeySize,
(id) kSecAttrLabel : kCHIPCAKeyLabel,
(id) kSecAttrApplicationTag : kCHIPCAKeyTag,
const NSDictionary * deleteParams = @{
(id) kSecClass : (id) kSecClassGenericPassword,
(id) kSecAttrService : kCHIPCAKeyLabel,
(id) kSecAttrSynchronizable : @YES,
};

status = SecItemDelete((__bridge CFDictionaryRef) deleteParams);
Expand Down

0 comments on commit e39590e

Please sign in to comment.