Changeset 164181 in webkit


Ignore:
Timestamp:
Feb 15, 2014 3:26:21 PM (10 years ago)
Author:
ap@apple.com
Message:

[Mac] All WebKit clients should encrypt WebCrypto keys automatically
https://bugs.webkit.org/show_bug.cgi?id=128852

Reviewed by Oliver Hunt.

Source/WebCore:

Install a persistent master key in Keychain on first use of WebCrypto key serialization.
The key is per application, protected with ACL.

  • English.lproj/Localizable.strings:
  • WebCore.exp.in:
  • crypto/SerializedCryptoKeyWrap.h:
  • crypto/mac/SerializedCryptoKeyWrapMac.mm:

(WebCore::masterKeyAccountNameForCurrentApplication):
(WebCore::getDefaultWebCryptoMasterKey):
(WebCore::createAndStoreMasterKey):
(WebCore::findMasterKey):

  • platform/LocalizedStrings.cpp:

(WebCore::webCryptoMasterKeyKeychainLabel):
(WebCore::webCryptoMasterKeyKeychainComment):

  • platform/LocalizedStrings.h:

Source/WebKit/mac:

  • WebCoreSupport/WebChromeClient.mm:

(WebChromeClient::wrapCryptoKey):
(WebChromeClient::unwrapCryptoKey):
Call the default implementation if key is not provided by a client.

Source/WebKit2:

  • UIProcess/WebPageProxy.cpp:

(WebKit::WebPageProxy::wrapCryptoKey):
(WebKit::WebPageProxy::unwrapCryptoKey):
Call the default implementation if key is not provided by a client.

Location:
trunk/Source
Files:
11 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r164180 r164181  
     12014-02-15  Alexey Proskuryakov  <ap@apple.com>
     2
     3        [Mac] All WebKit clients should encrypt WebCrypto keys automatically
     4        https://bugs.webkit.org/show_bug.cgi?id=128852
     5
     6        Reviewed by Oliver Hunt.
     7
     8        Install a persistent master key in Keychain on first use of WebCrypto key serialization.
     9        The key is per application, protected with ACL.
     10
     11        * English.lproj/Localizable.strings:
     12        * WebCore.exp.in:
     13        * crypto/SerializedCryptoKeyWrap.h:
     14        * crypto/mac/SerializedCryptoKeyWrapMac.mm:
     15        (WebCore::masterKeyAccountNameForCurrentApplication):
     16        (WebCore::getDefaultWebCryptoMasterKey):
     17        (WebCore::createAndStoreMasterKey):
     18        (WebCore::findMasterKey):
     19        * platform/LocalizedStrings.cpp:
     20        (WebCore::webCryptoMasterKeyKeychainLabel):
     21        (WebCore::webCryptoMasterKeyKeychainComment):
     22        * platform/LocalizedStrings.h:
     23
    1242014-02-15  Ryosuke Niwa  <rniwa@webkit.org>
    225
  • trunk/Source/WebCore/English.lproj/Localizable.strings

    r163255 r164181  
    4141"%@ Web Content" = "%@ Web Content";
    4242
     43/* Name of application's single WebCrypto master key in Keychain */
     44"%@ WebCrypto Master Key" = "%@ WebCrypto Master Key";
     45
    4346/* Label to describe the number of files selected in a file upload control that allows multiple files */
    4447"%d files" = "%d files";
     
    596599"Use Standard Ligatures (Undo action name)" = "Use Standard Ligatures";
    597600
     601/* Description of WebCrypto master keys in Keychain */
     602"Used to encrypt WebCrypto keys in persistent storage, such as IndexedDB" = "Used to encrypt WebCrypto keys in persistent storage, such as IndexedDB";
     603
    598604/* Web Inspector window title */
    599605"Web Inspector — %@" = "Web Inspector — %@";
  • trunk/Source/WebCore/WebCore.exp.in

    r164131 r164181  
    26262626__ZN7WebCore23wrapSerializedCryptoKeyERKN3WTF6VectorIhLm0ENS0_15CrashOnOverflowEEES5_RS3_
    26272627__ZN7WebCore25unwrapSerializedCryptoKeyERKN3WTF6VectorIhLm0ENS0_15CrashOnOverflowEEES5_RS3_
     2628__ZN7WebCore28getDefaultWebCryptoMasterKeyERN3WTF6VectorIhLm0ENS0_15CrashOnOverflowEEE
    26282629#endif
    26292630
  • trunk/Source/WebCore/crypto/SerializedCryptoKeyWrap.h

    r163976 r164181  
    3434namespace WebCore {
    3535
     36bool getDefaultWebCryptoMasterKey(Vector<uint8_t>&);
     37
    3638bool wrapSerializedCryptoKey(const Vector<uint8_t>& masterKey, const Vector<uint8_t>& key, Vector<uint8_t>& result);
    3739bool unwrapSerializedCryptoKey(const Vector<uint8_t>& masterKey, const Vector<uint8_t>& wrappedKey, Vector<uint8_t>& key);
  • trunk/Source/WebCore/crypto/mac/SerializedCryptoKeyWrapMac.mm

    r163976 r164181  
    3030
    3131#include "CommonCryptoUtilities.h"
     32#include "LocalizedStrings.h"
    3233#include <CommonCrypto/CommonSymmetricKeywrap.h>
     34#include <wtf/text/Base64.h>
    3335#include <wtf/text/CString.h>
    3436#include <wtf/CryptographicUtilities.h>
     37#include <wtf/RetainPtr.h>
    3538
    3639namespace WebCore {
     
    4346const NSString* tagKey = @"tag";
    4447
     48const size_t masterKeySizeInBytes = 16;
     49
    4550inline Vector<uint8_t> vectorFromNSData(NSData* data)
    4651{
     
    4954    return result;
    5055}
     56
     57#if PLATFORM(IOS)
     58
     59bool getDefaultWebCryptoMasterKey(Vector<uint8_t>& masterKey)
     60{
     61    // FIXME: Implement.
     62    masterKey.resize(masterKeySizeInBytes);
     63    memset(masterKey.data(), 0, masterKey.size());
     64    return true;
     65}
     66
     67#else
     68
     69static NSString* masterKeyAccountNameForCurrentApplication()
     70{
     71    return [NSString stringWithFormat:@"com.apple.WebKit.WebCrypto.master+%@", [[NSRunningApplication currentApplication] bundleIdentifier]];
     72}
     73
     74static bool createAndStoreMasterKey(Vector<uint8_t>& masterKeyData)
     75{
     76    masterKeyData.resize(masterKeySizeInBytes);
     77    CCRandomCopyBytes(kCCRandomDefault, masterKeyData.data(), masterKeyData.size());
     78
     79    NSString *localizedItemName = webCryptoMasterKeyKeychainLabel([[NSRunningApplication currentApplication] localizedName]);
     80
     81    SecAccessRef accessRef;
     82    OSStatus status = SecAccessCreate((CFStringRef)localizedItemName, nullptr, &accessRef);
     83    if (status) {
     84        WTFLogAlways("Cannot create a security access object for storing WebCrypto master key, error %d", (int)status);
     85        return nullptr;
     86    }
     87    RetainPtr<SecAccessRef> access = adoptCF(accessRef);
     88
     89    RetainPtr<CFArrayRef> acls = adoptCF(SecAccessCopyMatchingACLList(accessRef, kSecACLAuthorizationExportClear));
     90    SecACLRef acl = (SecACLRef)CFArrayGetValueAtIndex(acls.get(), 0);
     91
     92    SecTrustedApplicationRef trustedAppRef;
     93    status = SecTrustedApplicationCreateFromPath(0, &trustedAppRef);
     94    if (status) {
     95        WTFLogAlways("Cannot create a trusted application object for storing WebCrypto master key, error %d", (int)status);
     96        return nullptr;
     97    }
     98    RetainPtr<SecTrustedApplicationRef> trustedApp = adoptCF(trustedAppRef);
     99
     100    status = SecACLSetContents(acl, (CFArrayRef)@[ (id)trustedApp.get() ], (CFStringRef)localizedItemName, kSecKeychainPromptRequirePassphase);
     101    if (status) {
     102        WTFLogAlways("Cannot set ACL for WebCrypto master key, error %d", (int)status);
     103        return nullptr;
     104    }
     105
     106    Vector<char> base64EncodedMasterKeyData;
     107    base64Encode(masterKeyData, base64EncodedMasterKeyData);
     108
     109    // Cannot use kSecClassKey because of <rdar://problem/16068207>.
     110    NSDictionary *attributes = @{
     111        (id)kSecClass : (id)kSecClassGenericPassword,
     112        (id)kSecAttrSynchronizable : @NO,
     113        (id)kSecAttrIsPermanent : @YES,
     114        (id)kSecAttrAccess : (id)access.get(),
     115        (id)kSecAttrComment : webCryptoMasterKeyKeychainComment(),
     116        (id)kSecAttrLabel : localizedItemName,
     117        (id)kSecAttrAccount : masterKeyAccountNameForCurrentApplication(),
     118        (id)kSecValueData : [NSData dataWithBytes:base64EncodedMasterKeyData.data() length:base64EncodedMasterKeyData.size()],
     119    };
     120
     121    status = SecItemAdd((CFDictionaryRef)attributes, nullptr);
     122    if (status) {
     123        WTFLogAlways("Cannot store WebCrypto master key, error %d", (int)status);
     124        return nullptr;
     125    }
     126    return true;
     127}
     128
     129static bool findMasterKey(Vector<uint8_t>& masterKeyData)
     130{
     131    NSDictionary *query = @{
     132        (id)kSecClass : (id)kSecClassGenericPassword,
     133        (id)kSecAttrAccount : masterKeyAccountNameForCurrentApplication(),
     134        (id)kSecReturnData : @YES,
     135    };
     136
     137    CFDataRef keyDataRef;
     138    OSStatus status = SecItemCopyMatching((CFDictionaryRef)query, (CFTypeRef*)&keyDataRef);
     139    if (status) {
     140        if (status != errSecItemNotFound && status != errSecUserCanceled)
     141            WTFLogAlways("Could not find WebCrypto master key in Keychain, error %d", (int)status);
     142        return false;
     143    }
     144    RetainPtr<CFDataRef> keyData = adoptCF(keyDataRef);
     145
     146    Vector<uint8_t> base64EncodedMasterKeyData = vectorFromNSData((NSData *)keyData.get());
     147    return base64Decode((const char*)base64EncodedMasterKeyData.data(), base64EncodedMasterKeyData.size(), masterKeyData);
     148}
     149
     150bool getDefaultWebCryptoMasterKey(Vector<uint8_t>& masterKey)
     151{
     152    if (!findMasterKey(masterKey) && !createAndStoreMasterKey(masterKey))
     153        return false;
     154    RELEASE_ASSERT(masterKey.size() == masterKeySizeInBytes);
     155    return true;
     156}
     157
     158#endif
    51159
    52160bool wrapSerializedCryptoKey(const Vector<uint8_t>& masterKey, const Vector<uint8_t>& key, Vector<uint8_t>& result)
  • trunk/Source/WebCore/platform/LocalizedStrings.cpp

    r163657 r164181  
    11191119}
    11201120
     1121#if ENABLE(SUBTLE_CRYPTO)
     1122String webCryptoMasterKeyKeychainLabel(const String& localizedApplicationName)
     1123{
     1124    return formatLocalizedString(WEB_UI_STRING("%@ WebCrypto Master Key", "Name of application's single WebCrypto master key in Keychain"), localizedApplicationName.createCFString().get());
     1125}
     1126
     1127String webCryptoMasterKeyKeychainComment()
     1128{
     1129    return WEB_UI_STRING("Used to encrypt WebCrypto keys in persistent storage, such as IndexedDB", "Description of WebCrypto master keys in Keychain");
     1130}
     1131#endif
     1132
    11211133} // namespace WebCore
  • trunk/Source/WebCore/platform/LocalizedStrings.h

    r163657 r164181  
    264264    String useBlockedPlugInContextMenuTitle();
    265265
     266#if ENABLE(SUBTLE_CRYPTO)
     267    String webCryptoMasterKeyKeychainLabel(const String& localizedApplicationName);
     268    String webCryptoMasterKeyKeychainComment();
     269#endif
     270
    266271#define WEB_UI_STRING(string, description) WebCore::localizedString(string)
    267272#define WEB_UI_STRING_KEY(string, key, description) WebCore::localizedString(key)
  • trunk/Source/WebKit/mac/ChangeLog

    r164152 r164181  
     12014-02-15  Alexey Proskuryakov  <ap@apple.com>
     2
     3        [Mac] All WebKit clients should encrypt WebCrypto keys automatically
     4        https://bugs.webkit.org/show_bug.cgi?id=128852
     5
     6        Reviewed by Oliver Hunt.
     7
     8        * WebCoreSupport/WebChromeClient.mm:
     9        (WebChromeClient::wrapCryptoKey):
     10        (WebChromeClient::unwrapCryptoKey):
     11        Call the default implementation if key is not provided by a client.
     12
    1132014-02-14  Anders Carlsson  <andersca@apple.com>
    214
  • trunk/Source/WebKit/mac/WebCoreSupport/WebChromeClient.mm

    r164042 r164181  
    10031003bool WebChromeClient::wrapCryptoKey(const Vector<uint8_t>& key, Vector<uint8_t>& wrappedKey) const
    10041004{
     1005    Vector<uint8_t> masterKey;
    10051006    SEL selector = @selector(webCryptoMasterKeyForWebView:);
    1006     if (![[m_webView UIDelegate] respondsToSelector:selector])
     1007    if ([[m_webView UIDelegate] respondsToSelector:selector]) {
     1008        NSData *keyData = CallUIDelegate(m_webView, selector);
     1009        masterKey.append((uint8_t*)[keyData bytes], [keyData length]);
     1010    } else if (!getDefaultWebCryptoMasterKey(masterKey))
    10071011        return false;
    10081012
    1009     NSData* keyData = CallUIDelegate(m_webView, selector);
    1010 
     1013    return wrapSerializedCryptoKey(masterKey, key, wrappedKey);
     1014}
     1015
     1016bool WebChromeClient::unwrapCryptoKey(const Vector<uint8_t>& wrappedKey, Vector<uint8_t>& key) const
     1017{
    10111018    Vector<uint8_t> masterKey;
    1012     masterKey.append((uint8_t*)[keyData bytes], [keyData length]);
    1013     return wrapSerializedCryptoKey(masterKey, key, wrappedKey);
    1014 }
    1015 
    1016 bool WebChromeClient::unwrapCryptoKey(const Vector<uint8_t>& wrappedKey, Vector<uint8_t>& key) const
    1017 {
    10181019    SEL selector = @selector(webCryptoMasterKeyForWebView:);
    1019     if (![[m_webView UIDelegate] respondsToSelector:selector])
     1020    if ([[m_webView UIDelegate] respondsToSelector:selector]) {
     1021        NSData *keyData = CallUIDelegate(m_webView, selector);
     1022        masterKey.append((uint8_t*)[keyData bytes], [keyData length]);
     1023    } else if (!getDefaultWebCryptoMasterKey(masterKey))
    10201024        return false;
    10211025
    1022     NSData *keyData = CallUIDelegate(m_webView, selector);
    1023 
    1024     Vector<uint8_t> masterKey;
    1025     masterKey.append((uint8_t*)[keyData bytes], [keyData length]);
    10261026    return unwrapSerializedCryptoKey(masterKey, wrappedKey, key);
    10271027}
  • trunk/Source/WebKit2/ChangeLog

    r164179 r164181  
     12014-02-15  Alexey Proskuryakov  <ap@apple.com>
     2
     3        [Mac] All WebKit clients should encrypt WebCrypto keys automatically
     4        https://bugs.webkit.org/show_bug.cgi?id=128852
     5
     6        Reviewed by Oliver Hunt.
     7
     8        * UIProcess/WebPageProxy.cpp:
     9        (WebKit::WebPageProxy::wrapCryptoKey):
     10        (WebKit::WebPageProxy::unwrapCryptoKey):
     11        Call the default implementation if key is not provided by a client.
     12
    1132014-02-15  Raphael Kubo da Costa  <raphael.kubo.da.costa@intel.com>
    214
  • trunk/Source/WebKit2/UIProcess/WebPageProxy.cpp

    r164172 r164181  
    44844484void WebPageProxy::wrapCryptoKey(const Vector<uint8_t>& key, bool& succeeded, Vector<uint8_t>& wrappedKey)
    44854485{
     4486    Vector<uint8_t> masterKey;
    44864487    RefPtr<API::Data> keyData = m_process->context().client().copyWebCryptoMasterKey(&m_process->context());
    4487     if (!keyData) {
     4488    if (keyData)
     4489        masterKey = keyData->dataReference().vector();
     4490    else if (!getDefaultWebCryptoMasterKey(masterKey)) {
    44884491        succeeded = false;
    44894492        return;
    44904493    }
    44914494
    4492     Vector<uint8_t> masterKey = keyData->dataReference().vector();
    44934495    succeeded = wrapSerializedCryptoKey(masterKey, key, wrappedKey);
    44944496}
     
    44964498void WebPageProxy::unwrapCryptoKey(const Vector<uint8_t>& wrappedKey, bool& succeeded, Vector<uint8_t>& key)
    44974499{
     4500    Vector<uint8_t> masterKey;
    44984501    RefPtr<API::Data> keyData = m_process->context().client().copyWebCryptoMasterKey(&m_process->context());
    4499     if (!keyData) {
     4502    if (keyData)
     4503        masterKey = keyData->dataReference().vector();
     4504    else if (!getDefaultWebCryptoMasterKey(masterKey)) {
    45004505        succeeded = false;
    45014506        return;
    45024507    }
    45034508
    4504     Vector<uint8_t> masterKey = keyData->dataReference().vector();
    45054509    succeeded = unwrapSerializedCryptoKey(masterKey, wrappedKey, key);
    45064510}
Note: See TracChangeset for help on using the changeset viewer.