/*
 *
 *    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 key derivation functionality
 *      for pin encryption.
 *
 */

#import "NLHKDF.h"

#include <Weave/Support/NLDLLUtil.h>
#include <Weave/Core/WeaveCore.h>
#include <Weave/Support/crypto/HMAC.h>
#include <Weave/Support/crypto/HashAlgos.h>
#include <Weave/Support/crypto/HKDF.h>

NSString * const NLHKDFErrorDomain = @"NLHKDFErrorDomain";

@implementation NLHKDF

+ (NSData *)deriveKey:(NSString *)alg
                 salt:(NSData *)salt
         keyMaterial1:(NSData *)keyMaterial1
         keyMaterial2:(NSData *)keyMaterial2
                 info:(NSData *)info
      requestedKeyLen:(NSUInteger)requestedKeyLen
                error:(NSError **)errOut
{

    if (![alg isEqualToString:@"HKDFSHA1"]) {
        if (errOut) {
            *errOut = [NSError errorWithDomain:NLHKDFErrorDomain code:NLHKDFErrorDomainAlgNotSupported userInfo:nil];
        }
        return nil;
    }

    NSMutableData * data = [[NSMutableData alloc] initWithLength:requestedKeyLen];

    WEAVE_ERROR err = nl::Weave::Crypto::HKDFSHA1::DeriveKey((salt != nil) ? (unsigned char *) [salt bytes] : NULL,
        (salt != nil) ? [salt length] : 0, (unsigned char *) [keyMaterial1 bytes], [keyMaterial1 length],
        (unsigned char *) [keyMaterial2 bytes], [keyMaterial2 length], (unsigned char *) [info bytes], [info length],
        (unsigned char *) [data mutableBytes], requestedKeyLen, requestedKeyLen);

    if (err != WEAVE_NO_ERROR) {
        if (err == WEAVE_ERROR_BUFFER_TOO_SMALL) {
            *errOut = [NSError errorWithDomain:NLHKDFErrorDomain code:NLHKDFErrorDomainKeyBuffSizeInsufficient userInfo:nil];
        } else if (err == WEAVE_ERROR_INVALID_ARGUMENT) {
            *errOut = [NSError errorWithDomain:NLHKDFErrorDomain code:NLHKDFErrorDomainKeyInvalidRequestedKeySize userInfo:nil];
        } else {
            NSString * failureReason = [NSString stringWithFormat:NSLocalizedString(@"DeriveKey error: %d", @""), err];
            NSDictionary * userInfo = @{ NSLocalizedFailureReasonErrorKey : failureReason };
            *errOut = [NSError errorWithDomain:NLHKDFErrorDomain code:NLHKDFErrorDomainDeriveKeyFailure userInfo:userInfo];
        }
        return nil;
    }

    return data;
}

@end
