15f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
25f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// found in the LICENSE file.
45f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
55f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "net/ssl/openssl_platform_key.h"
65f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
75f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include <openssl/err.h>
85f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include <openssl/evp.h>
95f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include <openssl/rsa.h>
105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include <Security/cssm.h>
125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include <Security/SecBase.h>
135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include <Security/SecCertificate.h>
145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include <Security/SecIdentity.h>
155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include <Security/SecKey.h>
165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "base/lazy_instance.h"
185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "base/location.h"
195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "base/logging.h"
205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "base/mac/mac_logging.h"
215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "base/mac/scoped_cftyperef.h"
225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "base/memory/scoped_policy.h"
235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "base/memory/scoped_ptr.h"
245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "base/synchronization/lock.h"
255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "crypto/mac_security_services_lock.h"
265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "net/base/net_errors.h"
275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "net/cert/x509_certificate.h"
285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "net/ssl/openssl_ssl_util.h"
295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)namespace net {
315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)namespace {
335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class ScopedCSSM_CC_HANDLE {
355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) public:
365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ScopedCSSM_CC_HANDLE() : handle_(0) {
375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ~ScopedCSSM_CC_HANDLE() {
405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    reset();
415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  CSSM_CC_HANDLE get() const {
445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return handle_;
455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  void reset() {
485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if (handle_)
495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      CSSM_DeleteContext(handle_);
505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    handle_ = 0;
515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  CSSM_CC_HANDLE* InitializeInto() {
545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    reset();
555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return &handle_;
565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) private:
585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  CSSM_CC_HANDLE handle_;
595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(ScopedCSSM_CC_HANDLE);
615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)};
625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Looks up the private key for |certificate| in KeyChain and returns
645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// a SecKeyRef or NULL on failure. The caller takes ownership of the
655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// result.
665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)SecKeyRef FetchSecKeyRefForCertificate(const X509Certificate* certificate) {
675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  OSStatus status;
685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  base::ScopedCFTypeRef<SecIdentityRef> identity;
695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  {
705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    base::AutoLock lock(crypto::GetMacSecurityServicesLock());
715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    status = SecIdentityCreateWithCertificate(
725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        NULL, certificate->os_cert_handle(), identity.InitializeInto());
735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (status != noErr) {
755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    OSSTATUS_LOG(WARNING, status);
765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return NULL;
775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  base::ScopedCFTypeRef<SecKeyRef> private_key;
805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  status = SecIdentityCopyPrivateKey(identity, private_key.InitializeInto());
815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (status != noErr) {
825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    OSSTATUS_LOG(WARNING, status);
835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return NULL;
845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return private_key.release();
875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)extern const RSA_METHOD mac_rsa_method;
905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)extern const ECDSA_METHOD mac_ecdsa_method;
915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// KeyExData contains the data that is contained in the EX_DATA of the
935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// RSA and ECDSA objects that are created to wrap Mac system keys.
945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)struct KeyExData {
955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  KeyExData(SecKeyRef key, const CSSM_KEY* cssm_key)
965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      : key(key, base::scoped_policy::RETAIN), cssm_key(cssm_key) {}
975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  base::ScopedCFTypeRef<SecKeyRef> key;
995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  const CSSM_KEY* cssm_key;
1005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)};
1015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// ExDataDup is called when one of the RSA or EC_KEY objects is
1035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// duplicated. This is not supported and should never happen.
1045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)int ExDataDup(CRYPTO_EX_DATA* to,
1055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)              const CRYPTO_EX_DATA* from,
1065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)              void** from_d,
1075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)              int idx,
1085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)              long argl,
1095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)              void* argp) {
1101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  CHECK_EQ((void*)NULL, *from_d);
1115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return 0;
1125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
1135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// ExDataFree is called when one of the RSA or EC_KEY objects is freed.
1155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void ExDataFree(void* parent,
1165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                void* ptr,
1175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                CRYPTO_EX_DATA* ex_data,
1185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                int idx,
1195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                long argl, void* argp) {
1205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  KeyExData* data = reinterpret_cast<KeyExData*>(ptr);
1215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  delete data;
1225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
1235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// BoringSSLEngine is a BoringSSL ENGINE that implements RSA and ECDSA
1255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// by forwarding the requested operations to Apple's CSSM
1265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// implementation.
1275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class BoringSSLEngine {
1285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) public:
1295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  BoringSSLEngine()
1305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      : rsa_index_(RSA_get_ex_new_index(0 /* argl */,
1315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                        NULL /* argp */,
1325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                        NULL /* new_func */,
1335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                        ExDataDup,
1345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                        ExDataFree)),
1355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        ec_key_index_(EC_KEY_get_ex_new_index(0 /* argl */,
1365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                              NULL /* argp */,
1375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                              NULL /* new_func */,
1385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                              ExDataDup,
1395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                              ExDataFree)),
1405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        engine_(ENGINE_new()) {
1415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    ENGINE_set_RSA_method(
1425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        engine_, &mac_rsa_method, sizeof(mac_rsa_method));
1435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    ENGINE_set_ECDSA_method(
1445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        engine_, &mac_ecdsa_method, sizeof(mac_ecdsa_method));
1455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
1465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  int rsa_ex_index() const { return rsa_index_; }
1485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  int ec_key_ex_index() const { return ec_key_index_; }
1495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  const ENGINE* engine() const { return engine_; }
1515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) private:
1535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  const int rsa_index_;
1545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  const int ec_key_index_;
1555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ENGINE* const engine_;
1565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)};
1575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)base::LazyInstance<BoringSSLEngine>::Leaky global_boringssl_engine =
1595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    LAZY_INSTANCE_INITIALIZER;
1605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Helper function for making a signature.
1625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// MakeCSSMSignature uses the key information in |ex_data| to sign the
1645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// |in_len| bytes pointed by |in|. It writes up to |max_out| bytes
1655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// into the buffer pointed to by |out|, setting |*out_len| to the
1665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// number of bytes written. It returns 1 on success and 0 on failure.
1675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)int MakeCSSMSignature(const KeyExData* ex_data,
1685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                      size_t* out_len,
1695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                      uint8_t* out,
1705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                      size_t max_out,
1715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                      const uint8_t* in,
1725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                      size_t in_len) {
1735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  CSSM_CSP_HANDLE csp_handle;
1745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  OSStatus status = SecKeyGetCSPHandle(ex_data->key.get(), &csp_handle);
1755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (status != noErr) {
1765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    OSSTATUS_LOG(WARNING, status);
1775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    OPENSSL_PUT_ERROR(RSA, sign_raw, ERR_R_INTERNAL_ERROR);
1785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return 0;
1795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
1805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  const CSSM_ACCESS_CREDENTIALS* cssm_creds = NULL;
1825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  status = SecKeyGetCredentials(ex_data->key.get(), CSSM_ACL_AUTHORIZATION_SIGN,
1835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                kSecCredentialTypeDefault, &cssm_creds);
1845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (status != noErr) {
1855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    OSSTATUS_LOG(WARNING, status);
1865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    OpenSSLPutNetError(FROM_HERE, ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED);
1875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return 0;
1885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
1895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ScopedCSSM_CC_HANDLE cssm_signature;
1915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (CSSM_CSP_CreateSignatureContext(
1925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          csp_handle, ex_data->cssm_key->KeyHeader.AlgorithmId, cssm_creds,
1935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          ex_data->cssm_key, cssm_signature.InitializeInto()) != CSSM_OK) {
1945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    OpenSSLPutNetError(FROM_HERE, ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED);
1955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return 0;
1965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
1975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (ex_data->cssm_key->KeyHeader.AlgorithmId == CSSM_ALGID_RSA) {
1995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    // Set RSA blinding.
2005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    CSSM_CONTEXT_ATTRIBUTE blinding_attr;
2015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    blinding_attr.AttributeType   = CSSM_ATTRIBUTE_RSA_BLINDING;
2025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    blinding_attr.AttributeLength = sizeof(uint32);
2035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    blinding_attr.Attribute.Uint32 = 1;
2045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if (CSSM_UpdateContextAttributes(
2055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            cssm_signature.get(), 1, &blinding_attr) != CSSM_OK) {
2065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      OpenSSLPutNetError(FROM_HERE, ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED);
2075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      return 0;
2085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    }
2095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
2105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  CSSM_DATA hash_data;
2125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  hash_data.Length = in_len;
2135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  hash_data.Data = const_cast<uint8*>(in);
2145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  CSSM_DATA signature_data;
2165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  signature_data.Length = max_out;
2175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  signature_data.Data = out;
2185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (CSSM_SignData(cssm_signature.get(), &hash_data, 1,
2205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    CSSM_ALGID_NONE, &signature_data) != CSSM_OK) {
2215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    OpenSSLPutNetError(FROM_HERE, ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED);
2225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return 0;
2235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
2245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  *out_len = signature_data.Length;
2265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return 1;
2275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
2285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Custom RSA_METHOD that uses the platform APIs for signing.
2305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)const KeyExData* RsaGetExData(const RSA* rsa) {
2325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return reinterpret_cast<const KeyExData*>(
2335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      RSA_get_ex_data(rsa, global_boringssl_engine.Get().rsa_ex_index()));
2345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
2355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)size_t RsaMethodSize(const RSA *rsa) {
2375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  const KeyExData *ex_data = RsaGetExData(rsa);
2385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return (ex_data->cssm_key->KeyHeader.LogicalKeySizeInBits + 7) / 8;
2395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
2405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)int RsaMethodEncrypt(RSA* rsa,
2425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                     size_t* out_len,
2435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                     uint8_t* out,
2445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                     size_t max_out,
2455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                     const uint8_t* in,
2465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                     size_t in_len,
2475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                     int padding) {
2485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  NOTIMPLEMENTED();
2495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  OPENSSL_PUT_ERROR(RSA, encrypt, RSA_R_UNKNOWN_ALGORITHM_TYPE);
2505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return 0;
2515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
2525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)int RsaMethodSignRaw(RSA* rsa,
2545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                     size_t* out_len,
2555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                     uint8_t* out,
2565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                     size_t max_out,
2575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                     const uint8_t* in,
2585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                     size_t in_len,
2595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                     int padding) {
2605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Only support PKCS#1 padding.
2615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  DCHECK_EQ(RSA_PKCS1_PADDING, padding);
2625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (padding != RSA_PKCS1_PADDING) {
2635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    OPENSSL_PUT_ERROR(RSA, sign_raw, RSA_R_UNKNOWN_PADDING_TYPE);
2645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return 0;
2655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
2665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  const KeyExData *ex_data = RsaGetExData(rsa);
2685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (!ex_data) {
2695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    OPENSSL_PUT_ERROR(RSA, sign_raw, ERR_R_INTERNAL_ERROR);
2705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return 0;
2715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
2725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  DCHECK_EQ(CSSM_ALGID_RSA, ex_data->cssm_key->KeyHeader.AlgorithmId);
2735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return MakeCSSMSignature(ex_data, out_len, out, max_out, in, in_len);
2755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
2765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)int RsaMethodDecrypt(RSA* rsa,
2785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                     size_t* out_len,
2795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                     uint8_t* out,
2805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                     size_t max_out,
2815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                     const uint8_t* in,
2825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                     size_t in_len,
2835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                     int padding) {
2845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  NOTIMPLEMENTED();
2855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  OPENSSL_PUT_ERROR(RSA, decrypt, RSA_R_UNKNOWN_ALGORITHM_TYPE);
2865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return 0;
2875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
2885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)int RsaMethodVerifyRaw(RSA* rsa,
2905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                       size_t* out_len,
2915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                       uint8_t* out,
2925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                       size_t max_out,
2935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                       const uint8_t* in,
2945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                       size_t in_len,
2955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                       int padding) {
2965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  NOTIMPLEMENTED();
2975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  OPENSSL_PUT_ERROR(RSA, verify_raw, RSA_R_UNKNOWN_ALGORITHM_TYPE);
2985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return 0;
2995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
3005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
3015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)const RSA_METHOD mac_rsa_method = {
3025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    {
3035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)     0 /* references */,
3045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)     1 /* is_static */
3055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    } /* common */,
3065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    NULL /* app_data */,
3075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
3085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    NULL /* init */,
3095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    NULL /* finish */,
3105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    RsaMethodSize,
3115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    NULL /* sign */,
3125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    NULL /* verify */,
3135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    RsaMethodEncrypt,
3145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    RsaMethodSignRaw,
3155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    RsaMethodDecrypt,
3165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    RsaMethodVerifyRaw,
31703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    NULL /* private_transform */,
3185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    NULL /* mod_exp */,
3195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    NULL /* bn_mod_exp */,
3205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    RSA_FLAG_OPAQUE,
3215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    NULL /* keygen */,
3225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)};
3235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
3245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)crypto::ScopedEVP_PKEY CreateRSAWrapper(SecKeyRef key,
3255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                        const CSSM_KEY* cssm_key) {
3265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  crypto::ScopedRSA rsa(
3275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      RSA_new_method(global_boringssl_engine.Get().engine()));
3285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (!rsa)
3295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return crypto::ScopedEVP_PKEY();
3305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
3315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  RSA_set_ex_data(
3325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      rsa.get(), global_boringssl_engine.Get().rsa_ex_index(),
3335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      new KeyExData(key, cssm_key));
3345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
3355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  crypto::ScopedEVP_PKEY pkey(EVP_PKEY_new());
3365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (!pkey)
3375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return crypto::ScopedEVP_PKEY();
3385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
3395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (!EVP_PKEY_set1_RSA(pkey.get(), rsa.get()))
3405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return crypto::ScopedEVP_PKEY();
3415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
3425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return pkey.Pass();
3435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
3445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
3455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Custom ECDSA_METHOD that uses the platform APIs.
3465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Note that for now, only signing through ECDSA_sign() is really supported.
3475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// all other method pointers are either stubs returning errors, or no-ops.
3485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
3495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)const KeyExData* EcKeyGetExData(const EC_KEY* ec_key) {
3505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return reinterpret_cast<const KeyExData*>(EC_KEY_get_ex_data(
3515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      ec_key, global_boringssl_engine.Get().ec_key_ex_index()));
3525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
3535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
3545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)size_t EcdsaMethodGroupOrderSize(const EC_KEY* ec_key) {
3555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  const KeyExData* ex_data = EcKeyGetExData(ec_key);
3565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // LogicalKeySizeInBits is the size of an EC public key. But an
3575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // ECDSA signature length depends on the size of the base point's
3585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // order. For P-256, P-384, and P-521, these two sizes are the same.
3595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return (ex_data->cssm_key->KeyHeader.LogicalKeySizeInBits + 7) / 8;
3605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
3615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
3625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)int EcdsaMethodSign(const uint8_t* digest,
3635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    size_t digest_len,
3645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    uint8_t* sig,
3655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    unsigned int* sig_len,
3665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    EC_KEY* ec_key) {
3675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  const KeyExData *ex_data = EcKeyGetExData(ec_key);
3685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (!ex_data) {
3695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    OPENSSL_PUT_ERROR(RSA, sign_raw, ERR_R_INTERNAL_ERROR);
3705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return 0;
3715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
3725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  DCHECK_EQ(CSSM_ALGID_ECDSA, ex_data->cssm_key->KeyHeader.AlgorithmId);
3735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
3745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // TODO(davidben): Fix BoringSSL to make sig_len a size_t*.
3755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  size_t out_len;
3765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  int ret = MakeCSSMSignature(
3775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      ex_data, &out_len, sig, ECDSA_size(ec_key), digest, digest_len);
3785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (!ret)
3795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return 0;
3805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  *sig_len = out_len;
3815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return 1;
3825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
3835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
3845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)int EcdsaMethodVerify(const uint8_t* digest,
3855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                      size_t digest_len,
3865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                      const uint8_t* sig,
3875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                      size_t sig_len,
3885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                      EC_KEY* eckey) {
3895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  NOTIMPLEMENTED();
3905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  OPENSSL_PUT_ERROR(ECDSA, ECDSA_do_verify, ECDSA_R_NOT_IMPLEMENTED);
3915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return 0;
3925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
3935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
3945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)const ECDSA_METHOD mac_ecdsa_method = {
3955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    {
3965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)     0 /* references */,
3975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)     1 /* is_static */
3985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    } /* common */,
3995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    NULL /* app_data */,
4005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
4015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    NULL /* init */,
4025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    NULL /* finish */,
4035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    EcdsaMethodGroupOrderSize,
4045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    EcdsaMethodSign,
4055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    EcdsaMethodVerify,
4065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    ECDSA_FLAG_OPAQUE,
4075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)};
4085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
4095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)crypto::ScopedEVP_PKEY CreateECDSAWrapper(SecKeyRef key,
4105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                          const CSSM_KEY* cssm_key) {
4115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  crypto::ScopedEC_KEY ec_key(
4125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      EC_KEY_new_method(global_boringssl_engine.Get().engine()));
4135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (!ec_key)
4145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return crypto::ScopedEVP_PKEY();
4155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
4165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  EC_KEY_set_ex_data(
4175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      ec_key.get(), global_boringssl_engine.Get().ec_key_ex_index(),
4185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      new KeyExData(key, cssm_key));
4195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
4205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  crypto::ScopedEVP_PKEY pkey(EVP_PKEY_new());
4215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (!pkey)
4225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return crypto::ScopedEVP_PKEY();
4235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
4245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (!EVP_PKEY_set1_EC_KEY(pkey.get(), ec_key.get()))
4255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return crypto::ScopedEVP_PKEY();
4265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
4275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return pkey.Pass();
4285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
4295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
4305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)crypto::ScopedEVP_PKEY CreatePkeyWrapper(SecKeyRef key) {
4315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  const CSSM_KEY* cssm_key;
4325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  OSStatus status = SecKeyGetCSSMKey(key, &cssm_key);
4335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (status != noErr)
4345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return crypto::ScopedEVP_PKEY();
4355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
4365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  switch (cssm_key->KeyHeader.AlgorithmId) {
4375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    case CSSM_ALGID_RSA:
4385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      return CreateRSAWrapper(key, cssm_key);
4395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    case CSSM_ALGID_ECDSA:
4405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      return CreateECDSAWrapper(key, cssm_key);
4415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    default:
4425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      // TODO(davidben): Filter out anything other than ECDSA and RSA
4435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      // elsewhere. We don't support other key types.
4445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      NOTREACHED();
4455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      LOG(ERROR) << "Unknown key type";
4465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      return crypto::ScopedEVP_PKEY();
4475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
4485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
4495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
4505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}  // namespace
4515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
4525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)crypto::ScopedEVP_PKEY FetchClientCertPrivateKey(
4535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    const X509Certificate* certificate) {
4545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Look up the private key.
4555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  base::ScopedCFTypeRef<SecKeyRef> private_key(
4565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      FetchSecKeyRefForCertificate(certificate));
4575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (!private_key)
4585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return crypto::ScopedEVP_PKEY();
4595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
4605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Create an EVP_PKEY wrapper.
4615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return CreatePkeyWrapper(private_key.get());
4625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
4635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
4645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}  // namespace net
465