// Copyright 2014 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 "net/ssl/openssl_platform_key.h"

#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/rsa.h>

#include <Security/cssm.h>
#include <Security/SecBase.h>
#include <Security/SecCertificate.h>
#include <Security/SecIdentity.h>
#include <Security/SecKey.h>

#include "base/lazy_instance.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/mac/mac_logging.h"
#include "base/mac/scoped_cftyperef.h"
#include "base/memory/scoped_policy.h"
#include "base/memory/scoped_ptr.h"
#include "base/synchronization/lock.h"
#include "crypto/mac_security_services_lock.h"
#include "net/base/net_errors.h"
#include "net/cert/x509_certificate.h"
#include "net/ssl/openssl_ssl_util.h"

namespace net {

namespace {

class ScopedCSSM_CC_HANDLE {
 public:
  ScopedCSSM_CC_HANDLE() : handle_(0) {
  }

  ~ScopedCSSM_CC_HANDLE() {
    reset();
  }

  CSSM_CC_HANDLE get() const {
    return handle_;
  }

  void reset() {
    if (handle_)
      CSSM_DeleteContext(handle_);
    handle_ = 0;
  }

  CSSM_CC_HANDLE* InitializeInto() {
    reset();
    return &handle_;
  }
 private:
  CSSM_CC_HANDLE handle_;

  DISALLOW_COPY_AND_ASSIGN(ScopedCSSM_CC_HANDLE);
};

// Looks up the private key for |certificate| in KeyChain and returns
// a SecKeyRef or NULL on failure. The caller takes ownership of the
// result.
SecKeyRef FetchSecKeyRefForCertificate(const X509Certificate* certificate) {
  OSStatus status;
  base::ScopedCFTypeRef<SecIdentityRef> identity;
  {
    base::AutoLock lock(crypto::GetMacSecurityServicesLock());
    status = SecIdentityCreateWithCertificate(
        NULL, certificate->os_cert_handle(), identity.InitializeInto());
  }
  if (status != noErr) {
    OSSTATUS_LOG(WARNING, status);
    return NULL;
  }

  base::ScopedCFTypeRef<SecKeyRef> private_key;
  status = SecIdentityCopyPrivateKey(identity, private_key.InitializeInto());
  if (status != noErr) {
    OSSTATUS_LOG(WARNING, status);
    return NULL;
  }

  return private_key.release();
}

extern const RSA_METHOD mac_rsa_method;
extern const ECDSA_METHOD mac_ecdsa_method;

// KeyExData contains the data that is contained in the EX_DATA of the
// RSA and ECDSA objects that are created to wrap Mac system keys.
struct KeyExData {
  KeyExData(SecKeyRef key, const CSSM_KEY* cssm_key)
      : key(key, base::scoped_policy::RETAIN), cssm_key(cssm_key) {}

  base::ScopedCFTypeRef<SecKeyRef> key;
  const CSSM_KEY* cssm_key;
};

// ExDataDup is called when one of the RSA or EC_KEY objects is
// duplicated. This is not supported and should never happen.
int ExDataDup(CRYPTO_EX_DATA* to,
              const CRYPTO_EX_DATA* from,
              void** from_d,
              int idx,
              long argl,
              void* argp) {
  CHECK_EQ((void*)NULL, *from_d);
  return 0;
}

// ExDataFree is called when one of the RSA or EC_KEY objects is freed.
void ExDataFree(void* parent,
                void* ptr,
                CRYPTO_EX_DATA* ex_data,
                int idx,
                long argl, void* argp) {
  KeyExData* data = reinterpret_cast<KeyExData*>(ptr);
  delete data;
}

// BoringSSLEngine is a BoringSSL ENGINE that implements RSA and ECDSA
// by forwarding the requested operations to Apple's CSSM
// implementation.
class BoringSSLEngine {
 public:
  BoringSSLEngine()
      : rsa_index_(RSA_get_ex_new_index(0 /* argl */,
                                        NULL /* argp */,
                                        NULL /* new_func */,
                                        ExDataDup,
                                        ExDataFree)),
        ec_key_index_(EC_KEY_get_ex_new_index(0 /* argl */,
                                              NULL /* argp */,
                                              NULL /* new_func */,
                                              ExDataDup,
                                              ExDataFree)),
        engine_(ENGINE_new()) {
    ENGINE_set_RSA_method(
        engine_, &mac_rsa_method, sizeof(mac_rsa_method));
    ENGINE_set_ECDSA_method(
        engine_, &mac_ecdsa_method, sizeof(mac_ecdsa_method));
  }

  int rsa_ex_index() const { return rsa_index_; }
  int ec_key_ex_index() const { return ec_key_index_; }

  const ENGINE* engine() const { return engine_; }

 private:
  const int rsa_index_;
  const int ec_key_index_;
  ENGINE* const engine_;
};

base::LazyInstance<BoringSSLEngine>::Leaky global_boringssl_engine =
    LAZY_INSTANCE_INITIALIZER;

// Helper function for making a signature.

// MakeCSSMSignature uses the key information in |ex_data| to sign the
// |in_len| bytes pointed by |in|. It writes up to |max_out| bytes
// into the buffer pointed to by |out|, setting |*out_len| to the
// number of bytes written. It returns 1 on success and 0 on failure.
int MakeCSSMSignature(const KeyExData* ex_data,
                      size_t* out_len,
                      uint8_t* out,
                      size_t max_out,
                      const uint8_t* in,
                      size_t in_len) {
  CSSM_CSP_HANDLE csp_handle;
  OSStatus status = SecKeyGetCSPHandle(ex_data->key.get(), &csp_handle);
  if (status != noErr) {
    OSSTATUS_LOG(WARNING, status);
    OPENSSL_PUT_ERROR(RSA, sign_raw, ERR_R_INTERNAL_ERROR);
    return 0;
  }

  const CSSM_ACCESS_CREDENTIALS* cssm_creds = NULL;
  status = SecKeyGetCredentials(ex_data->key.get(), CSSM_ACL_AUTHORIZATION_SIGN,
                                kSecCredentialTypeDefault, &cssm_creds);
  if (status != noErr) {
    OSSTATUS_LOG(WARNING, status);
    OpenSSLPutNetError(FROM_HERE, ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED);
    return 0;
  }

  ScopedCSSM_CC_HANDLE cssm_signature;
  if (CSSM_CSP_CreateSignatureContext(
          csp_handle, ex_data->cssm_key->KeyHeader.AlgorithmId, cssm_creds,
          ex_data->cssm_key, cssm_signature.InitializeInto()) != CSSM_OK) {
    OpenSSLPutNetError(FROM_HERE, ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED);
    return 0;
  }

  if (ex_data->cssm_key->KeyHeader.AlgorithmId == CSSM_ALGID_RSA) {
    // Set RSA blinding.
    CSSM_CONTEXT_ATTRIBUTE blinding_attr;
    blinding_attr.AttributeType   = CSSM_ATTRIBUTE_RSA_BLINDING;
    blinding_attr.AttributeLength = sizeof(uint32);
    blinding_attr.Attribute.Uint32 = 1;
    if (CSSM_UpdateContextAttributes(
            cssm_signature.get(), 1, &blinding_attr) != CSSM_OK) {
      OpenSSLPutNetError(FROM_HERE, ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED);
      return 0;
    }
  }

  CSSM_DATA hash_data;
  hash_data.Length = in_len;
  hash_data.Data = const_cast<uint8*>(in);

  CSSM_DATA signature_data;
  signature_data.Length = max_out;
  signature_data.Data = out;

  if (CSSM_SignData(cssm_signature.get(), &hash_data, 1,
                    CSSM_ALGID_NONE, &signature_data) != CSSM_OK) {
    OpenSSLPutNetError(FROM_HERE, ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED);
    return 0;
  }

  *out_len = signature_data.Length;
  return 1;
}

// Custom RSA_METHOD that uses the platform APIs for signing.

const KeyExData* RsaGetExData(const RSA* rsa) {
  return reinterpret_cast<const KeyExData*>(
      RSA_get_ex_data(rsa, global_boringssl_engine.Get().rsa_ex_index()));
}

size_t RsaMethodSize(const RSA *rsa) {
  const KeyExData *ex_data = RsaGetExData(rsa);
  return (ex_data->cssm_key->KeyHeader.LogicalKeySizeInBits + 7) / 8;
}

int RsaMethodEncrypt(RSA* rsa,
                     size_t* out_len,
                     uint8_t* out,
                     size_t max_out,
                     const uint8_t* in,
                     size_t in_len,
                     int padding) {
  NOTIMPLEMENTED();
  OPENSSL_PUT_ERROR(RSA, encrypt, RSA_R_UNKNOWN_ALGORITHM_TYPE);
  return 0;
}

int RsaMethodSignRaw(RSA* rsa,
                     size_t* out_len,
                     uint8_t* out,
                     size_t max_out,
                     const uint8_t* in,
                     size_t in_len,
                     int padding) {
  // Only support PKCS#1 padding.
  DCHECK_EQ(RSA_PKCS1_PADDING, padding);
  if (padding != RSA_PKCS1_PADDING) {
    OPENSSL_PUT_ERROR(RSA, sign_raw, RSA_R_UNKNOWN_PADDING_TYPE);
    return 0;
  }

  const KeyExData *ex_data = RsaGetExData(rsa);
  if (!ex_data) {
    OPENSSL_PUT_ERROR(RSA, sign_raw, ERR_R_INTERNAL_ERROR);
    return 0;
  }
  DCHECK_EQ(CSSM_ALGID_RSA, ex_data->cssm_key->KeyHeader.AlgorithmId);

  return MakeCSSMSignature(ex_data, out_len, out, max_out, in, in_len);
}

int RsaMethodDecrypt(RSA* rsa,
                     size_t* out_len,
                     uint8_t* out,
                     size_t max_out,
                     const uint8_t* in,
                     size_t in_len,
                     int padding) {
  NOTIMPLEMENTED();
  OPENSSL_PUT_ERROR(RSA, decrypt, RSA_R_UNKNOWN_ALGORITHM_TYPE);
  return 0;
}

int RsaMethodVerifyRaw(RSA* rsa,
                       size_t* out_len,
                       uint8_t* out,
                       size_t max_out,
                       const uint8_t* in,
                       size_t in_len,
                       int padding) {
  NOTIMPLEMENTED();
  OPENSSL_PUT_ERROR(RSA, verify_raw, RSA_R_UNKNOWN_ALGORITHM_TYPE);
  return 0;
}

const RSA_METHOD mac_rsa_method = {
    {
     0 /* references */,
     1 /* is_static */
    } /* common */,
    NULL /* app_data */,

    NULL /* init */,
    NULL /* finish */,
    RsaMethodSize,
    NULL /* sign */,
    NULL /* verify */,
    RsaMethodEncrypt,
    RsaMethodSignRaw,
    RsaMethodDecrypt,
    RsaMethodVerifyRaw,
    NULL /* private_transform */,
    NULL /* mod_exp */,
    NULL /* bn_mod_exp */,
    RSA_FLAG_OPAQUE,
    NULL /* keygen */,
};

crypto::ScopedEVP_PKEY CreateRSAWrapper(SecKeyRef key,
                                        const CSSM_KEY* cssm_key) {
  crypto::ScopedRSA rsa(
      RSA_new_method(global_boringssl_engine.Get().engine()));
  if (!rsa)
    return crypto::ScopedEVP_PKEY();

  RSA_set_ex_data(
      rsa.get(), global_boringssl_engine.Get().rsa_ex_index(),
      new KeyExData(key, cssm_key));

  crypto::ScopedEVP_PKEY pkey(EVP_PKEY_new());
  if (!pkey)
    return crypto::ScopedEVP_PKEY();

  if (!EVP_PKEY_set1_RSA(pkey.get(), rsa.get()))
    return crypto::ScopedEVP_PKEY();

  return pkey.Pass();
}

// Custom ECDSA_METHOD that uses the platform APIs.
// Note that for now, only signing through ECDSA_sign() is really supported.
// all other method pointers are either stubs returning errors, or no-ops.

const KeyExData* EcKeyGetExData(const EC_KEY* ec_key) {
  return reinterpret_cast<const KeyExData*>(EC_KEY_get_ex_data(
      ec_key, global_boringssl_engine.Get().ec_key_ex_index()));
}

size_t EcdsaMethodGroupOrderSize(const EC_KEY* ec_key) {
  const KeyExData* ex_data = EcKeyGetExData(ec_key);
  // LogicalKeySizeInBits is the size of an EC public key. But an
  // ECDSA signature length depends on the size of the base point's
  // order. For P-256, P-384, and P-521, these two sizes are the same.
  return (ex_data->cssm_key->KeyHeader.LogicalKeySizeInBits + 7) / 8;
}

int EcdsaMethodSign(const uint8_t* digest,
                    size_t digest_len,
                    uint8_t* sig,
                    unsigned int* sig_len,
                    EC_KEY* ec_key) {
  const KeyExData *ex_data = EcKeyGetExData(ec_key);
  if (!ex_data) {
    OPENSSL_PUT_ERROR(RSA, sign_raw, ERR_R_INTERNAL_ERROR);
    return 0;
  }
  DCHECK_EQ(CSSM_ALGID_ECDSA, ex_data->cssm_key->KeyHeader.AlgorithmId);

  // TODO(davidben): Fix BoringSSL to make sig_len a size_t*.
  size_t out_len;
  int ret = MakeCSSMSignature(
      ex_data, &out_len, sig, ECDSA_size(ec_key), digest, digest_len);
  if (!ret)
    return 0;
  *sig_len = out_len;
  return 1;
}

int EcdsaMethodVerify(const uint8_t* digest,
                      size_t digest_len,
                      const uint8_t* sig,
                      size_t sig_len,
                      EC_KEY* eckey) {
  NOTIMPLEMENTED();
  OPENSSL_PUT_ERROR(ECDSA, ECDSA_do_verify, ECDSA_R_NOT_IMPLEMENTED);
  return 0;
}

const ECDSA_METHOD mac_ecdsa_method = {
    {
     0 /* references */,
     1 /* is_static */
    } /* common */,
    NULL /* app_data */,

    NULL /* init */,
    NULL /* finish */,
    EcdsaMethodGroupOrderSize,
    EcdsaMethodSign,
    EcdsaMethodVerify,
    ECDSA_FLAG_OPAQUE,
};

crypto::ScopedEVP_PKEY CreateECDSAWrapper(SecKeyRef key,
                                          const CSSM_KEY* cssm_key) {
  crypto::ScopedEC_KEY ec_key(
      EC_KEY_new_method(global_boringssl_engine.Get().engine()));
  if (!ec_key)
    return crypto::ScopedEVP_PKEY();

  EC_KEY_set_ex_data(
      ec_key.get(), global_boringssl_engine.Get().ec_key_ex_index(),
      new KeyExData(key, cssm_key));

  crypto::ScopedEVP_PKEY pkey(EVP_PKEY_new());
  if (!pkey)
    return crypto::ScopedEVP_PKEY();

  if (!EVP_PKEY_set1_EC_KEY(pkey.get(), ec_key.get()))
    return crypto::ScopedEVP_PKEY();

  return pkey.Pass();
}

crypto::ScopedEVP_PKEY CreatePkeyWrapper(SecKeyRef key) {
  const CSSM_KEY* cssm_key;
  OSStatus status = SecKeyGetCSSMKey(key, &cssm_key);
  if (status != noErr)
    return crypto::ScopedEVP_PKEY();

  switch (cssm_key->KeyHeader.AlgorithmId) {
    case CSSM_ALGID_RSA:
      return CreateRSAWrapper(key, cssm_key);
    case CSSM_ALGID_ECDSA:
      return CreateECDSAWrapper(key, cssm_key);
    default:
      // TODO(davidben): Filter out anything other than ECDSA and RSA
      // elsewhere. We don't support other key types.
      NOTREACHED();
      LOG(ERROR) << "Unknown key type";
      return crypto::ScopedEVP_PKEY();
  }
}

}  // namespace

crypto::ScopedEVP_PKEY FetchClientCertPrivateKey(
    const X509Certificate* certificate) {
  // Look up the private key.
  base::ScopedCFTypeRef<SecKeyRef> private_key(
      FetchSecKeyRefForCertificate(certificate));
  if (!private_key)
    return crypto::ScopedEVP_PKEY();

  // Create an EVP_PKEY wrapper.
  return CreatePkeyWrapper(private_key.get());
}

}  // namespace net
