1// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "net/base/cert_database.h"
6
7#include <Security/Security.h>
8
9#include "base/logging.h"
10#include "base/synchronization/lock.h"
11#include "crypto/mac_security_services_lock.h"
12#include "net/base/net_errors.h"
13#include "net/base/x509_certificate.h"
14
15namespace net {
16
17CertDatabase::CertDatabase() {
18}
19
20int CertDatabase::CheckUserCert(X509Certificate* cert) {
21  if (!cert)
22    return ERR_CERT_INVALID;
23  if (cert->HasExpired())
24    return ERR_CERT_DATE_INVALID;
25
26  // Verify the Keychain already has the corresponding private key:
27  SecIdentityRef identity = NULL;
28  OSStatus err = SecIdentityCreateWithCertificate(NULL, cert->os_cert_handle(),
29                                                  &identity);
30  if (err == errSecItemNotFound) {
31    LOG(ERROR) << "CertDatabase couldn't find private key for user cert";
32    return ERR_NO_PRIVATE_KEY_FOR_CERT;
33  }
34  if (err != noErr || !identity) {
35    // TODO(snej): Map the error code more intelligently.
36    return ERR_CERT_INVALID;
37  }
38
39  CFRelease(identity);
40  return OK;
41}
42
43int CertDatabase::AddUserCert(X509Certificate* cert) {
44  OSStatus err;
45  {
46    base::AutoLock locked(crypto::GetMacSecurityServicesLock());
47    err = SecCertificateAddToKeychain(cert->os_cert_handle(), NULL);
48  }
49  switch (err) {
50    case noErr:
51      CertDatabase::NotifyObserversOfUserCertAdded(cert);
52      // Fall through.
53    case errSecDuplicateItem:
54      return OK;
55    default:
56      LOG(ERROR) << "CertDatabase failed to add cert to keychain: " << err;
57      // TODO(snej): Map the error code more intelligently.
58      return ERR_ADD_USER_CERT_FAILED;
59  }
60}
61
62}  // namespace net
63