// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "crypto/apple_keychain.h"

#import <Foundation/Foundation.h>

#include "base/mac/foundation_util.h"
#include "base/mac/scoped_cftyperef.h"
#include "base/memory/scoped_nsobject.h"

namespace {

enum KeychainAction {
  kKeychainActionCreate,
  kKeychainActionUpdate
};

// Creates a dictionary that can be used to query the keystore.
// Ownership follows the Create rule.
CFDictionaryRef CreateGenericPasswordQuery(UInt32 serviceNameLength,
                                           const char* serviceName,
                                           UInt32 accountNameLength,
                                           const char* accountName) {
  CFMutableDictionaryRef query =
      CFDictionaryCreateMutable(NULL,
                                5,
                                &kCFTypeDictionaryKeyCallBacks,
                                &kCFTypeDictionaryValueCallBacks);
  // Type of element is generic password.
  CFDictionarySetValue(query, kSecClass, kSecClassGenericPassword);

  // Set the service name.
  scoped_nsobject<NSString> service_name_ns(
      [[NSString alloc] initWithBytes:serviceName
                               length:serviceNameLength
                             encoding:NSUTF8StringEncoding]);
  CFDictionarySetValue(query, kSecAttrService,
                       base::mac::NSToCFCast(service_name_ns));

  // Set the account name.
  scoped_nsobject<NSString> account_name_ns(
      [[NSString alloc] initWithBytes:accountName
                               length:accountNameLength
                             encoding:NSUTF8StringEncoding]);
  CFDictionarySetValue(query, kSecAttrAccount,
                       base::mac::NSToCFCast(account_name_ns));

  // Use the proper search constants, return only the data of the first match.
  CFDictionarySetValue(query, kSecMatchLimit, kSecMatchLimitOne);
  CFDictionarySetValue(query, kSecReturnData, kCFBooleanTrue);
  return query;
}

// Creates a dictionary conatining the data to save into the keychain.
// Ownership follows the Create rule.
CFDictionaryRef CreateKeychainData(UInt32 serviceNameLength,
                                   const char* serviceName,
                                   UInt32 accountNameLength,
                                   const char* accountName,
                                   UInt32 passwordLength,
                                   const void* passwordData,
                                   KeychainAction action) {
  CFMutableDictionaryRef keychain_data =
      CFDictionaryCreateMutable(NULL,
                                0,
                                &kCFTypeDictionaryKeyCallBacks,
                                &kCFTypeDictionaryValueCallBacks);

  // Set the password.
  NSData* password = [NSData dataWithBytes:passwordData length:passwordLength];
  CFDictionarySetValue(keychain_data, kSecValueData,
                       base::mac::NSToCFCast(password));

  // If this is not a creation, no structural information is needed.
  if (action != kKeychainActionCreate)
    return keychain_data;

  // Set the type of the data.
  CFDictionarySetValue(keychain_data, kSecClass, kSecClassGenericPassword);

  // Only allow access when the device has been unlocked.
  CFDictionarySetValue(keychain_data,
                       kSecAttrAccessible,
                       kSecAttrAccessibleWhenUnlocked);

  // Set the service name.
  scoped_nsobject<NSString> service_name_ns(
      [[NSString alloc] initWithBytes:serviceName
                               length:serviceNameLength
                             encoding:NSUTF8StringEncoding]);
  CFDictionarySetValue(keychain_data, kSecAttrService,
                       base::mac::NSToCFCast(service_name_ns));

  // Set the account name.
  scoped_nsobject<NSString> account_name_ns(
      [[NSString alloc] initWithBytes:accountName
                               length:accountNameLength
                             encoding:NSUTF8StringEncoding]);
  CFDictionarySetValue(keychain_data, kSecAttrAccount,
                       base::mac::NSToCFCast(account_name_ns));

  return keychain_data;
}

}  // namespace

namespace crypto {

AppleKeychain::AppleKeychain() {}

AppleKeychain::~AppleKeychain() {}

OSStatus AppleKeychain::ItemFreeContent(SecKeychainAttributeList* attrList,
                                        void* data) const {
  free(data);
  return noErr;
}

OSStatus AppleKeychain::AddGenericPassword(SecKeychainRef keychain,
                                           UInt32 serviceNameLength,
                                           const char* serviceName,
                                           UInt32 accountNameLength,
                                           const char* accountName,
                                           UInt32 passwordLength,
                                           const void* passwordData,
                                           SecKeychainItemRef* itemRef) const {
  base::mac::ScopedCFTypeRef<CFDictionaryRef> query(
      CreateGenericPasswordQuery(serviceNameLength,
                                 serviceName,
                                 accountNameLength,
                                 accountName));
  // Check that there is not already a password.
  OSStatus status = SecItemCopyMatching(query, NULL);
  if (status == errSecItemNotFound) {
    // A new entry must be created.
    base::mac::ScopedCFTypeRef<CFDictionaryRef> keychain_data(
        CreateKeychainData(serviceNameLength,
                           serviceName,
                           accountNameLength,
                           accountName,
                           passwordLength,
                           passwordData,
                           kKeychainActionCreate));
    status = SecItemAdd(keychain_data, NULL);
  } else if (status == noErr) {
    // The entry must be updated.
    base::mac::ScopedCFTypeRef<CFDictionaryRef> keychain_data(
        CreateKeychainData(serviceNameLength,
                           serviceName,
                           accountNameLength,
                           accountName,
                           passwordLength,
                           passwordData,
                           kKeychainActionUpdate));
    status = SecItemUpdate(query, keychain_data);
  }

  return status;
}

OSStatus AppleKeychain::FindGenericPassword(CFTypeRef keychainOrArray,
                                            UInt32 serviceNameLength,
                                            const char* serviceName,
                                            UInt32 accountNameLength,
                                            const char* accountName,
                                            UInt32* passwordLength,
                                            void** passwordData,
                                            SecKeychainItemRef* itemRef) const {
  DCHECK((passwordData && passwordLength) ||
         (!passwordData && !passwordLength));
  base::mac::ScopedCFTypeRef<CFDictionaryRef> query(
      CreateGenericPasswordQuery(serviceNameLength,
                                 serviceName,
                                 accountNameLength,
                                 accountName));

  // Get the keychain item containing the password.
  CFTypeRef resultRef = NULL;
  OSStatus status = SecItemCopyMatching(query, &resultRef);
  base::mac::ScopedCFTypeRef<CFTypeRef> result(resultRef);

  if (status != noErr) {
    if (passwordData) {
      *passwordData = NULL;
      *passwordLength = 0;
    }
    return status;
  }

  if (passwordData) {
    CFDataRef data = base::mac::CFCast<CFDataRef>(result);
    NSUInteger length = CFDataGetLength(data);
    *passwordData = malloc(length * sizeof(UInt8));
    CFDataGetBytes(data, CFRangeMake(0, length), (UInt8*)*passwordData);
    *passwordLength = length;
  }
  return status;
}

}  // namespace crypto
