Title: [204567] trunk/Source
Revision
204567
Author
[email protected]
Date
2016-08-17 12:58:00 -0700 (Wed, 17 Aug 2016)

Log Message

Move WKSignedPublicKeyAndChallengeString into WebCore and make it proper C++
https://bugs.webkit.org/show_bug.cgi?id=160945

Reviewed by Dan Bernstein.

Source/WebCore:

* platform/mac/SSLKeyGeneratorMac.mm:
(WebCore::getSubjectPublicKey):
(WebCore::signPublicKeyAndChallenge):
(WebCore::signedPublicKeyAndChallengeString):

Source/WTF:

* wtf/RetainPtr.h:
(WTF::RetainPtr::operator&):
Cast this to the right type.

* wtf/spi/cocoa/SecuritySPI.h:
Add new SPI.

Modified Paths

Diff

Modified: trunk/Source/WTF/ChangeLog (204566 => 204567)


--- trunk/Source/WTF/ChangeLog	2016-08-17 19:56:28 UTC (rev 204566)
+++ trunk/Source/WTF/ChangeLog	2016-08-17 19:58:00 UTC (rev 204567)
@@ -1,3 +1,17 @@
+2016-08-17  Anders Carlsson  <[email protected]>
+
+        Move WKSignedPublicKeyAndChallengeString into WebCore and make it proper C++
+        https://bugs.webkit.org/show_bug.cgi?id=160945
+
+        Reviewed by Dan Bernstein.
+
+        * wtf/RetainPtr.h:
+        (WTF::RetainPtr::operator&):
+        Cast this to the right type.
+
+        * wtf/spi/cocoa/SecuritySPI.h:
+        Add new SPI.
+
 2016-08-17  Antti Koivisto  <[email protected]>
 
         Remove CSS_IMAGE_SET feature define

Modified: trunk/Source/WTF/wtf/RetainPtr.h (204566 => 204567)


--- trunk/Source/WTF/wtf/RetainPtr.h	2016-08-17 19:56:28 UTC (rev 204566)
+++ trunk/Source/WTF/wtf/RetainPtr.h	2016-08-17 19:58:00 UTC (rev 204567)
@@ -96,7 +96,7 @@
         // Require that the pointer is null, to prevent leaks.
         ASSERT(!m_ptr);
 
-        return &m_ptr;
+        return (PtrType*)&m_ptr;
     }
 #endif
 

Modified: trunk/Source/WTF/wtf/spi/cocoa/SecuritySPI.h (204566 => 204567)


--- trunk/Source/WTF/wtf/spi/cocoa/SecuritySPI.h	2016-08-17 19:56:28 UTC (rev 204566)
+++ trunk/Source/WTF/wtf/spi/cocoa/SecuritySPI.h	2016-08-17 19:58:00 UTC (rev 204567)
@@ -23,8 +23,7 @@
  * THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#ifndef SecuritySPI_h
-#define SecuritySPI_h
+#pragma once
 
 #if USE(APPLE_INTERNAL_SDK)
 
@@ -32,6 +31,10 @@
 #include <Security/SecTask.h>
 #include <Security/SecTrustPriv.h>
 
+#if PLATFORM(MAC)
+#include <Security/keyTemplates.h>
+#endif
+
 #else
 
 #if (PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101100) || PLATFORM(IOS)
@@ -62,9 +65,13 @@
 EXTERN_C CFStringRef SecTaskCopySigningIdentifier(SecTaskRef, CFErrorRef *);
 #endif
 
+#if PLATFORM(MAC)
+#include <Security/SecAsn1Types.h>
+extern const SecAsn1Template kSecAsn1AlgorithmIDTemplate[];
+extern const SecAsn1Template kSecAsn1SubjectPublicKeyInfoTemplate[];
+#endif
+
 #if HAVE(SEC_TRUST_SERIALIZATION)
 EXTERN_C CF_RETURNS_RETAINED CFDataRef SecTrustSerialize(SecTrustRef, CFErrorRef *);
 EXTERN_C CF_RETURNS_RETAINED SecTrustRef SecTrustDeserialize(CFDataRef serializedTrust, CFErrorRef *);
 #endif
-
-#endif // SecuritySPI_h

Modified: trunk/Source/WebCore/ChangeLog (204566 => 204567)


--- trunk/Source/WebCore/ChangeLog	2016-08-17 19:56:28 UTC (rev 204566)
+++ trunk/Source/WebCore/ChangeLog	2016-08-17 19:58:00 UTC (rev 204567)
@@ -1,3 +1,15 @@
+2016-08-17  Anders Carlsson  <[email protected]>
+
+        Move WKSignedPublicKeyAndChallengeString into WebCore and make it proper C++
+        https://bugs.webkit.org/show_bug.cgi?id=160945
+
+        Reviewed by Dan Bernstein.
+
+        * platform/mac/SSLKeyGeneratorMac.mm:
+        (WebCore::getSubjectPublicKey):
+        (WebCore::signPublicKeyAndChallenge):
+        (WebCore::signedPublicKeyAndChallengeString):
+
 2016-08-17  Antti Koivisto  <[email protected]>
 
         Remove CSS_IMAGE_SET feature define

Modified: trunk/Source/WebCore/platform/mac/SSLKeyGeneratorMac.mm (204566 => 204567)


--- trunk/Source/WebCore/platform/mac/SSLKeyGeneratorMac.mm	2016-08-17 19:56:28 UTC (rev 204566)
+++ trunk/Source/WebCore/platform/mac/SSLKeyGeneratorMac.mm	2016-08-17 19:58:00 UTC (rev 204567)
@@ -23,16 +23,194 @@
  * THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#include "config.h"
-#include "SSLKeyGenerator.h"
+#import "config.h"
+#import "SSLKeyGenerator.h"
 
-#include "URL.h"
-#include "LocalizedStrings.h"
-#include "WebCoreSystemInterface.h"
-#include <wtf/RetainPtr.h>
+#import "LocalizedStrings.h"
+#import "URL.h"
+#import <Security/SecAsn1Coder.h>
+#import <Security/SecAsn1Templates.h>
+#import <Security/SecEncodeTransform.h>
+#import <wtf/RetainPtr.h>
+#import <wtf/Scope.h>
+#import <wtf/spi/cocoa/SecuritySPI.h>
+#import <wtf/text/Base64.h>
 
 namespace WebCore {
 
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
+
+struct PublicKeyAndChallenge {
+    CSSM_X509_SUBJECT_PUBLIC_KEY_INFO subjectPublicKeyInfo;
+    CSSM_DATA challenge;
+};
+
+struct SignedPublicKeyAndChallenge {
+    PublicKeyAndChallenge publicKeyAndChallenge;
+    CSSM_X509_ALGORITHM_IDENTIFIER algorithmIdentifier;
+    CSSM_DATA signature;
+};
+
+static const SecAsn1Template publicKeyAndChallengeTemplate[] {
+    { SEC_ASN1_SEQUENCE, 0, nullptr, sizeof(PublicKeyAndChallenge) },
+    { SEC_ASN1_INLINE, offsetof(PublicKeyAndChallenge, subjectPublicKeyInfo), kSecAsn1SubjectPublicKeyInfoTemplate, 0},
+    { SEC_ASN1_INLINE, offsetof(PublicKeyAndChallenge, challenge), kSecAsn1IA5StringTemplate, 0 },
+    { 0, 0, 0, 0}
+};
+
+static const SecAsn1Template signedPublicKeyAndChallengeTemplate[] {
+    { SEC_ASN1_SEQUENCE, 0, nullptr, sizeof(SignedPublicKeyAndChallenge) },
+    { SEC_ASN1_INLINE, offsetof(SignedPublicKeyAndChallenge, publicKeyAndChallenge), publicKeyAndChallengeTemplate, 0 },
+    { SEC_ASN1_INLINE, offsetof(SignedPublicKeyAndChallenge, algorithmIdentifier), kSecAsn1AlgorithmIDTemplate, 0 },
+    { SEC_ASN1_BIT_STRING, offsetof(SignedPublicKeyAndChallenge, signature), 0, 0 },
+    { 0, 0, 0, 0 }
+};
+
+static bool getSubjectPublicKey(CSSM_CSP_HANDLE cspHandle, SecKeyRef publicKey, CSSM_KEY_PTR subjectPublicKey)
+{
+    const CSSM_KEY* cssmPublicKey;
+    if (SecKeyGetCSSMKey(publicKey, &cssmPublicKey) != noErr)
+        return false;
+
+    CSSM_ACCESS_CREDENTIALS credentials { };
+    CSSM_CC_HANDLE ccHandle;
+    if (CSSM_CSP_CreateSymmetricContext(cspHandle, CSSM_ALGID_NONE, CSSM_ALGMODE_NONE, &credentials, nullptr, nullptr, CSSM_PADDING_NONE, 0, &ccHandle) != noErr)
+        return false;
+
+    auto deleteContext = makeScopeExit([&] {
+        CSSM_DeleteContext(ccHandle);
+    });
+
+    CSSM_CONTEXT_ATTRIBUTE publicKeyFormatAttribute;
+    publicKeyFormatAttribute.AttributeType = CSSM_ATTRIBUTE_PUBLIC_KEY_FORMAT;
+    publicKeyFormatAttribute.AttributeLength = sizeof(uint32);
+    publicKeyFormatAttribute.Attribute.Data = ""
+
+    if (CSSM_UpdateContextAttributes(ccHandle, 1, &publicKeyFormatAttribute) != noErr)
+        return false;
+
+    if (CSSM_WrapKey(ccHandle, &credentials, cssmPublicKey, nullptr, subjectPublicKey) != noErr)
+        return false;
+
+    return true;
+}
+
+static bool signPublicKeyAndChallenge(CSSM_CSP_HANDLE cspHandle, const CSSM_DATA* plainText, SecKeyRef privateKey, CSSM_ALGORITHMS algorithmID, CSSM_DATA& signature)
+{
+    ASSERT(!signature.Data);
+    ASSERT(!signature.Length);
+
+    const CSSM_KEY* cssmPrivateKey;
+    if (SecKeyGetCSSMKey(privateKey, &cssmPrivateKey) != noErr)
+        return false;
+
+    const CSSM_ACCESS_CREDENTIALS* credentials;
+    if (SecKeyGetCredentials(privateKey, CSSM_ACL_AUTHORIZATION_SIGN, kSecCredentialTypeDefault, &credentials) != noErr)
+        return false;
+
+    CSSM_CC_HANDLE ccHandle;
+    if (CSSM_CSP_CreateSignatureContext(cspHandle, algorithmID, credentials, cssmPrivateKey, &ccHandle) != noErr)
+        return false;
+    auto deleteContext = makeScopeExit([&] {
+        CSSM_DeleteContext(ccHandle);
+    });
+
+    if (CSSM_SignData(ccHandle, plainText, 1, CSSM_ALGID_NONE, &signature) != noErr)
+        return false;
+
+    return true;
+}
+
+static String signedPublicKeyAndChallengeString(unsigned keySize, const CString& challenge, const String& keyDescription)
+{
+    SignedPublicKeyAndChallenge signedPublicKeyAndChallenge { };
+
+    RetainPtr<SecAccessRef> access;
+    if (SecAccessCreate(keyDescription.createCFString().get(), nullptr, &access) != noErr)
+        return String();
+
+    RetainPtr<CFArrayRef> acls;
+    if (SecAccessCopySelectedACLList(access.get(), CSSM_ACL_AUTHORIZATION_DECRYPT, &acls) != noErr)
+        return String();
+
+    SecACLRef acl = (SecACLRef)(CFArrayGetValueAtIndex(acls.get(), 0));
+
+    // Passing nullptr to SecTrustedApplicationCreateFromPath tells that function to assume the application bundle.
+    RetainPtr<SecTrustedApplicationRef> trustedApp;
+    if (SecTrustedApplicationCreateFromPath(nullptr, &trustedApp) != noErr)
+        return String();
+
+    const CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR defaultSelector = {
+        CSSM_ACL_KEYCHAIN_PROMPT_CURRENT_VERSION, 0
+    };
+    if (SecACLSetSimpleContents(acl, (__bridge CFArrayRef)@[ (__bridge id)trustedApp.get() ], keyDescription.createCFString().get(), &defaultSelector) != noErr)
+        return String();
+
+    RetainPtr<SecKeyRef> publicKey;
+    RetainPtr<SecKeyRef> privateKey;
+    if (SecKeyCreatePair(nullptr, CSSM_ALGID_RSA, keySize, 0, CSSM_KEYUSE_ANY, CSSM_KEYATTR_PERMANENT | CSSM_KEYATTR_EXTRACTABLE | CSSM_KEYATTR_RETURN_REF, CSSM_KEYUSE_ANY, CSSM_KEYATTR_SENSITIVE | CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_PERMANENT | CSSM_KEYATTR_EXTRACTABLE, access.get(), &publicKey, &privateKey) != noErr)
+        return String();
+
+    CSSM_CSP_HANDLE cspHandle;
+    if (SecKeyGetCSPHandle(privateKey.get(), &cspHandle) != noErr)
+        return String();
+    
+    CSSM_KEY subjectPublicKey { };
+    if (!getSubjectPublicKey(cspHandle, publicKey.get(), &subjectPublicKey))
+        return String();
+    auto freeSubjectPublicKey = makeScopeExit([&] {
+        CSSM_FreeKey(cspHandle, nullptr, &subjectPublicKey, CSSM_FALSE);
+    });
+
+    SecAsn1CoderRef coder = nullptr;
+    if (SecAsn1CoderCreate(&coder) != noErr)
+        return String();
+    auto releaseCoder = makeScopeExit([&] {
+        SecAsn1CoderRelease(coder);
+    });
+
+    if (SecAsn1DecodeData(coder, &subjectPublicKey.KeyData, kSecAsn1SubjectPublicKeyInfoTemplate, &signedPublicKeyAndChallenge.publicKeyAndChallenge.subjectPublicKeyInfo) != noErr)
+        return String();
+
+    ASSERT(challenge.data());
+
+    signedPublicKeyAndChallenge.publicKeyAndChallenge.challenge.Length = challenge.length();
+    signedPublicKeyAndChallenge.publicKeyAndChallenge.challenge.Data = ""
+
+    CSSM_DATA encodedPublicKeyAndChallenge { 0, nullptr };
+    if (SecAsn1EncodeItem(coder, &signedPublicKeyAndChallenge.publicKeyAndChallenge, publicKeyAndChallengeTemplate, &encodedPublicKeyAndChallenge) != noErr)
+        return String();
+
+    CSSM_DATA signature { };
+    if (!signPublicKeyAndChallenge(cspHandle, &encodedPublicKeyAndChallenge, privateKey.get(), CSSM_ALGID_MD5WithRSA, signature))
+        return String();
+    auto freeSignatureData = makeScopeExit([&] {
+        CSSM_API_MEMORY_FUNCS memoryFunctions;
+        if (CSSM_GetAPIMemoryFunctions(cspHandle, &memoryFunctions) != noErr)
+            return;
+
+        memoryFunctions.free_func(signature.Data, memoryFunctions.AllocRef);
+    });
+
+    uint8 encodeNull[2] { SEC_ASN1_NULL, 0 };
+    signedPublicKeyAndChallenge.algorithmIdentifier.algorithm = CSSMOID_MD5WithRSA;
+    signedPublicKeyAndChallenge.algorithmIdentifier.parameters.Data = "" *)encodeNull;
+    signedPublicKeyAndChallenge.algorithmIdentifier.parameters.Length = 2;
+    signedPublicKeyAndChallenge.signature = signature;
+
+    // We want the signature length to be in bits.
+    signedPublicKeyAndChallenge.signature.Length *= 8;
+
+    CSSM_DATA encodedSignedPublicKeyAndChallenge { 0, nullptr };
+    if (SecAsn1EncodeItem(coder, &signedPublicKeyAndChallenge, signedPublicKeyAndChallengeTemplate, &encodedSignedPublicKeyAndChallenge) != noErr)
+        return String();
+
+    return base64Encode(encodedSignedPublicKeyAndChallenge.Data, encodedSignedPublicKeyAndChallenge.Length);
+}
+
+#pragma clang diagnostic pop
+
 void getSupportedKeySizes(Vector<String>& supportedKeySizes)
 {
     ASSERT(supportedKeySizes.isEmpty());
@@ -60,7 +238,9 @@
         return String();
     }
 
-    return adoptCF(wkSignedPublicKeyAndChallengeString(keySize, challengeString.createCFString().get(), keygenKeychainItemName(url.host()).createCFString().get())).get();
+    auto challenge = challengeString.containsOnlyASCII() ? challengeString.ascii() : "";
+
+    return signedPublicKeyAndChallengeString(keySize, challenge, keygenKeychainItemName(url.host()));
 }
 
 }
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to