blob: 5974f98bfbd6e56ce3c3c272b8f8fec06a5ef648 [file] [log] [blame]
/*
*
* Copyright (c) 2016-2017 Nest Labs, Inc.
* All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @file
* This file implements a Wrapper for C++ implementation of pincode encryption/decryption functionality.
* for pin encryption.
*
*/
#import "NLWeavePasscodeEncryptionSupport.h"
#include <Weave/Profiles/security/WeavePasscodes.h>
using namespace nl::Weave::Profiles::Security::Passcodes;
NSUInteger const NLWeavePasscode_Config1_TEST_ONLY = kPasscode_Config1_TEST_ONLY;
NSUInteger const NLWeavePasscode_Config2 = kPasscode_Config2;
UInt8 const NLWeavePasscodeEncKeyDiversifier[] = { 0x1A, 0x65, 0x5D, 0x96 };
UInt32 const NLWeavePasscodeEncKeyDiversifierSize = sizeof(NLWeavePasscodeEncKeyDiversifier);
UInt8 const NLWeavePasscodeFingerprintKeyDiversifier[] = { 0xD1, 0xA1, 0xD9, 0x6C };
UInt32 const NLWeavePasscodeFingerprintKeyDiversifierSize = sizeof(NLWeavePasscodeFingerprintKeyDiversifier);
UInt32 const NLWeavePasscodeEncryptionKeyLen = kPasscodeEncryptionKeyLen;
UInt32 const NLWeavePasscodeAuthenticationKeyLen = kPasscodeAuthenticationKeyLen;
UInt32 const NLWeavePasscodeFingerprintKeyLen = kPasscodeFingerprintKeyLen;
NSString * const NLPasscodeEncryptionSupportDomain = @"NLPasscodeEncryptionSupportDomain";
@implementation NLWeavePasscodeEncryptionSupport
#pragma mark Public Methods
+ (NSData *)encryptPasscode:(UInt8)config
keyId:(UInt32)keyId
nonce:(UInt32)nonce
passcode:(NSData *)passcode
encKey:(NSData *)encKey
authKey:(NSData *)authKey
fingerprintKey:(NSData *)fingerprintKey
error:(NSError **)errOut
{
if (config != NLWeavePasscode_Config1_TEST_ONLY) {
if (![NLWeavePasscodeEncryptionSupport validateKeySize:encKey authKey:authKey fingerprintKey:fingerprintKey error:errOut]) {
return nil;
}
}
NSMutableData * encPasscodeBuff = [[NSMutableData alloc] initWithLength:kPasscodeMaxEncryptedLen];
size_t encPasscodeLen = 0;
WEAVE_ERROR err = EncryptPasscode(config, keyId, nonce, (unsigned char *) [passcode bytes], [passcode length],
(unsigned char *) [encKey bytes], (unsigned char *) [authKey bytes], (unsigned char *) [fingerprintKey bytes],
(unsigned char *) [encPasscodeBuff mutableBytes], [encPasscodeBuff length], encPasscodeLen);
if (err != WEAVE_NO_ERROR) {
if (errOut) {
NSString * failureReason = [NSString stringWithFormat:NSLocalizedString(@"EncryptPasscode error: %d", @""), err];
NSDictionary * userInfo = @{ NSLocalizedFailureReasonErrorKey : failureReason };
*errOut = [NSError errorWithDomain:NLPasscodeEncryptionSupportDomain
code:NLPasscodeEncryptionSupportDomainEncryptionFailure
userInfo:userInfo];
}
return nil;
}
[encPasscodeBuff setLength:encPasscodeLen];
return encPasscodeBuff;
}
+ (nullable NSData *)decryptPasscode:(NSData *)encPasscode
config:(UInt8)config
encKey:(NSData *)encKey
authKey:(NSData *)authKey
fingerprintKey:(NSData *)fingerprintKey
error:(NSError **)errOut
{
NSMutableData * passcodeBuff = [[NSMutableData alloc] initWithLength:kPasscodePaddedLen];
size_t passcodeLen = 0;
if (config != NLWeavePasscode_Config1_TEST_ONLY) {
if (![NLWeavePasscodeEncryptionSupport validateKeySize:encKey authKey:authKey fingerprintKey:fingerprintKey error:errOut]) {
return nil;
}
}
WEAVE_ERROR err = DecryptPasscode((unsigned char *) [encPasscode bytes], [encPasscode length], (unsigned char *) [encKey bytes],
(unsigned char *) [authKey bytes], (unsigned char *) [fingerprintKey bytes], (unsigned char *) [passcodeBuff mutableBytes],
[passcodeBuff length], passcodeLen);
if (err != WEAVE_NO_ERROR) {
NSString * failureReason = [NSString stringWithFormat:NSLocalizedString(@"DecryptPasscode error: %d", @""), err];
NSDictionary * userInfo = @{ NSLocalizedFailureReasonErrorKey : failureReason };
*errOut = [NSError errorWithDomain:NLPasscodeEncryptionSupportDomain
code:NLPasscodeEncryptionSupportDomainDecryptionFailure
userInfo:userInfo];
return nil;
}
[passcodeBuff setLength:passcodeLen];
return passcodeBuff;
}
+ (BOOL)isSupportedPasscodeEncryptionConfig:(UInt8)config
{
return IsSupportedPasscodeEncryptionConfig(config);
}
+ (BOOL)getEncryptedPasscodeConfig:(NSData *)encPasscode config:(UInt8 *)configOut error:(NSError **)errOut
{
UInt8 config = 0;
WEAVE_ERROR err = GetEncryptedPasscodeConfig((unsigned char *) [encPasscode bytes], [encPasscode length], config);
if (err != WEAVE_NO_ERROR) {
NSString * failureReason =
[NSString stringWithFormat:NSLocalizedString(@"retrieving encrypted config error: %d", @""), err];
NSDictionary * userInfo = @{ NSLocalizedFailureReasonErrorKey : failureReason };
*errOut = [NSError errorWithDomain:NLPasscodeEncryptionSupportDomain
code:NLPasscodeEncryptionSupportDomainInvalidData
userInfo:userInfo];
return FALSE;
}
*configOut = config;
return TRUE;
}
+ (BOOL)getEncryptedPasscodeKeyId:(NSData *)encPasscode keyId:(UInt32 *)keyIdOut error:(NSError **)errOut
{
UInt32 keyId = 0;
WEAVE_ERROR err = GetEncryptedPasscodeKeyId((unsigned char *) [encPasscode bytes], [encPasscode length], (uint32_t &) keyId);
if (err != WEAVE_NO_ERROR) {
NSString * failureReason =
[NSString stringWithFormat:NSLocalizedString(@"retrieving encrypted config error: %d", @""), err];
NSDictionary * userInfo = @{ NSLocalizedFailureReasonErrorKey : failureReason };
*errOut = [NSError errorWithDomain:NLPasscodeEncryptionSupportDomain
code:NLPasscodeEncryptionSupportDomainInvalidData
userInfo:userInfo];
return FALSE;
}
*keyIdOut = keyId;
return TRUE;
}
+ (BOOL)getEncryptedPasscodeNonce:(NSData *)encPasscode nonce:(UInt32 *)nonceOut error:(NSError **)errOut
{
UInt32 nonce = 0;
WEAVE_ERROR err = GetEncryptedPasscodeNonce((unsigned char *) [encPasscode bytes], [encPasscode length], (uint32_t &) nonce);
if (err != WEAVE_NO_ERROR) {
NSString * failureReason =
[NSString stringWithFormat:NSLocalizedString(@"retrieving encrypted passcode nonce: %d", @""), err];
NSDictionary * userInfo = @{ NSLocalizedFailureReasonErrorKey : failureReason };
*errOut = [NSError errorWithDomain:NLPasscodeEncryptionSupportDomain
code:NLPasscodeEncryptionSupportDomainInvalidData
userInfo:userInfo];
return FALSE;
}
*nonceOut = nonce;
return TRUE;
}
+ (nullable NSData *)getEncryptedPasscodeFingerprint:(NSData *)encPasscode error:(NSError **)errOut
{
NSMutableData * fingerprint = [[NSMutableData alloc] initWithLength:kPasscodeFingerprintLen];
size_t fingerprintLen = 0;
WEAVE_ERROR err = GetEncryptedPasscodeFingerprint((unsigned char *) [encPasscode bytes], [encPasscode length],
(unsigned char *) [fingerprint mutableBytes], [fingerprint length], fingerprintLen);
if (err != WEAVE_NO_ERROR) {
NSString * failureReason = [NSString stringWithFormat:NSLocalizedString(@"get fingerprint error: %d", @""), err];
NSDictionary * userInfo = @{ NSLocalizedFailureReasonErrorKey : failureReason };
*errOut = [NSError errorWithDomain:NLPasscodeEncryptionSupportDomain
code:NLPasscodeEncryptionSupportDomainInvalidData
userInfo:userInfo];
return nil;
}
[fingerprint setLength:fingerprintLen];
return fingerprint;
}
#pragma mark Private Methods
+ (BOOL)validateKeySize:(NSData *)encKey authKey:(NSData *)authKey fingerprintKey:(NSData *)fingerprintKey error:(NSError **)errOut
{
if ([encKey length] != kPasscodeEncryptionKeyLen) {
if (errOut) {
*errOut = [NSError errorWithDomain:NLPasscodeEncryptionSupportDomain
code:NLPasscodeEncryptionSupportDomainInvalidEncKeySize
userInfo:nil];
}
return FALSE;
}
if ([authKey length] != kPasscodeAuthenticationKeyLen) {
if (errOut) {
*errOut = [NSError errorWithDomain:NLPasscodeEncryptionSupportDomain
code:NLPasscodeEncryptionSupportDomainInvalidAuthKeySize
userInfo:nil];
}
return FALSE;
}
if ([fingerprintKey length] != kPasscodeFingerprintKeyLen) {
if (errOut) {
*errOut = [NSError errorWithDomain:NLPasscodeEncryptionSupportDomain
code:NLPasscodeEncryptionSupportDomainInvalidFingerprintKeySize
userInfo:nil];
}
return FALSE;
}
return TRUE;
}
@end