blob: fccf3d2734407e0d5d1e86c765fff058b446ce95 [file] [log] [blame]
#import "CHIPToolKeypair.h"
#import <Matter/Matter.h>
#include <credentials/CHIPCert.h>
#include <crypto/CHIPCryptoPAL.h>
#include <lib/asn1/ASN1.h>
#include <stddef.h>
#define CHIPPlugin_CAKeyTag "com.apple.matter.commissioner.ca.issuer.id"
#define Public_KeySize "256"
static NSString * const kCHIPToolKeychainLabel = @"Chip Tool Keypair";
static NSString * const kOperationalCredentialsIssuerKeypairStorage = @"ChipToolOpCredsCAKey";
static NSString * const kOperationalCredentialsIPK = @"ChipToolOpCredsIPK";
@interface CHIPToolKeypair ()
@property (nonatomic) chip::Crypto::P256Keypair mKeyPair;
@property (nonatomic) chip::Crypto::P256Keypair mIssuer;
@property (nonatomic) NSData * ipk;
@property (atomic) uint32_t mNow;
@property (nonatomic, readonly) SecKeyRef mPublicKey;
@end
@implementation CHIPToolKeypair
- (instancetype)init
{
if (self = [super init]) {
_mNow = 0;
}
return self;
}
- (BOOL)initialize
{
return _mKeyPair.Initialize(chip::Crypto::ECPKeyTarget::ECDSA) == CHIP_NO_ERROR;
}
- (NSData *)signMessageECDSA_RAW:(NSData *)message
{
chip::Crypto::P256ECDSASignature signature;
NSData * out_signature;
CHIP_ERROR signing_error = _mKeyPair.ECDSA_sign_msg((const uint8_t *) [message bytes], (size_t)[message length], signature);
if (signing_error != CHIP_NO_ERROR)
return nil;
out_signature = [NSData dataWithBytes:signature.Bytes() length:signature.Length()];
return out_signature;
}
- (SecKeyRef)publicKey
{
if (_mPublicKey == nil) {
chip::Crypto::P256PublicKey publicKey = _mKeyPair.Pubkey();
NSData * publicKeyNSData = [NSData dataWithBytes:publicKey.Bytes() length:publicKey.Length()];
NSDictionary * attributes = @{
(__bridge NSString *) kSecAttrKeyClass : (__bridge NSString *) kSecAttrKeyClassPublic,
(NSString *) kSecAttrKeyType : (NSString *) kSecAttrKeyTypeECSECPrimeRandom,
(NSString *) kSecAttrKeySizeInBits : @Public_KeySize,
(NSString *) kSecAttrLabel : kCHIPToolKeychainLabel,
(NSString *) kSecAttrApplicationTag : @CHIPPlugin_CAKeyTag,
};
_mPublicKey = SecKeyCreateWithData((__bridge CFDataRef) publicKeyNSData, (__bridge CFDictionaryRef) attributes, nullptr);
}
return _mPublicKey;
}
- (CHIP_ERROR)Deserialize:(chip::Crypto::P256SerializedKeypair &)input
{
return _mKeyPair.Deserialize(input);
}
- (CHIP_ERROR)Serialize:(chip::Crypto::P256SerializedKeypair &)output
{
return _mKeyPair.Serialize(output);
}
- (NSData *)getIPK
{
return _ipk;
}
- (CHIP_ERROR)createOrLoadKeys:(CHIPToolPersistentStorageDelegate *)storage
{
chip::ASN1::ASN1UniversalTime effectiveTime;
chip::Crypto::P256SerializedKeypair serializedKey;
NSData * value;
CHIP_ERROR err = CHIP_NO_ERROR;
// Initializing the default start validity to start of 2021. The default validity duration is 10 years.
CHIP_ZERO_AT(effectiveTime);
effectiveTime.Year = 2021;
effectiveTime.Month = 1;
effectiveTime.Day = 1;
ReturnErrorOnFailure(chip::Credentials::ASN1ToChipEpochTime(effectiveTime, _mNow));
value = [storage storageDataForKey:kOperationalCredentialsIssuerKeypairStorage];
err = [self initSerializedKeyFromValue:value serializedKey:serializedKey];
if (err != CHIP_NO_ERROR) {
// Storage doesn't have an existing keypair. Let's create one and add it to the storage.
if (![self initialize]) {
return CHIP_ERROR_INTERNAL;
}
ReturnErrorOnFailure([self Serialize:serializedKey]);
NSData * valueData = [NSData dataWithBytes:serializedKey.Bytes() length:serializedKey.Length()];
[storage setStorageData:valueData forKey:kOperationalCredentialsIssuerKeypairStorage];
} else {
ReturnErrorOnFailure([self Deserialize:serializedKey]);
}
NSData * ipk = [storage storageDataForKey:kOperationalCredentialsIPK];
if (ipk == nil) {
err = CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND;
}
if (err != CHIP_NO_ERROR) {
uint8_t tempIPK[chip::Crypto::CHIP_CRYPTO_SYMMETRIC_KEY_LENGTH_BYTES];
ReturnLogErrorOnFailure(chip::Crypto::DRBG_get_bytes(tempIPK, sizeof(tempIPK)));
_ipk = [NSData dataWithBytes:tempIPK length:sizeof(tempIPK)];
[storage setStorageData:_ipk forKey:kOperationalCredentialsIPK];
} else {
_ipk = ipk;
}
return CHIP_NO_ERROR;
}
- (CHIP_ERROR)initSerializedKeyFromValue:(NSData *)value serializedKey:(chip::Crypto::P256SerializedKeypair &)serializedKey
{
if (value == nil) {
return CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND;
}
if (serializedKey.Capacity() < [value length]) {
return CHIP_ERROR_BUFFER_TOO_SMALL;
}
memcpy(serializedKey.Bytes(), [value bytes], [value length]);
serializedKey.SetLength([value length]);
return CHIP_NO_ERROR;
}
- (void)dealloc
{
if (_mPublicKey) {
CFRelease(_mPublicKey);
}
}
@end