Changeset 159403 in webkit


Ignore:
Timestamp:
Nov 18, 2013 12:42:41 AM (10 years ago)
Author:
ap@apple.com
Message:

Support exporting public RSASSA-PKCS1-v1_5 keys
https://bugs.webkit.org/show_bug.cgi?id=124475

Reviewed by Sam Weinig.

Source/WebCore:

Test: crypto/subtle/rsa-export-key.html

  • bindings/js/JSCryptoKeySerializationJWK.h:
  • bindings/js/JSCryptoKeySerializationJWK.cpp:

(WebCore::JSCryptoKeySerializationJWK::buildJSONForRSAComponents):
(WebCore::JSCryptoKeySerializationJWK::addJWKAlgorithmToJSON):
(WebCore::JSCryptoKeySerializationJWK::serialize):
Added said support (this part works with private keys too).

  • crypto/keys/CryptoKeyRSA.h:
  • crypto/mac/CryptoKeyRSAMac.cpp:

(WebCore::CryptoKeyRSA::getPublicKeyComponents): Moved the logic for getting a
public key from private one here for reuse in keySizeInBits().
(WebCore::CryptoKeyRSA::isRestrictedToHash):
(WebCore::CryptoKeyRSA::keySizeInBits):
(WebCore::CryptoKeyRSA::exportData):
Exposed information necessary for JWK serialization.

LayoutTests:

  • crypto/subtle/rsa-export-key-expected.txt: Added.
  • crypto/subtle/rsa-export-key.html: Added.
Location:
trunk
Files:
2 added
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r159402 r159403  
     12013-11-17  Alexey Proskuryakov  <ap@apple.com>
     2
     3        Support exporting public RSASSA-PKCS1-v1_5 keys
     4        https://bugs.webkit.org/show_bug.cgi?id=124475
     5
     6        Reviewed by Sam Weinig.
     7
     8        * crypto/subtle/rsa-export-key-expected.txt: Added.
     9        * crypto/subtle/rsa-export-key.html: Added.
     10
    1112013-11-18  Zan Dobersek  <zdobersek@igalia.com>
    212
  • trunk/Source/WebCore/ChangeLog

    r159393 r159403  
     12013-11-17  Alexey Proskuryakov  <ap@apple.com>
     2
     3        Support exporting public RSASSA-PKCS1-v1_5 keys
     4        https://bugs.webkit.org/show_bug.cgi?id=124475
     5
     6        Reviewed by Sam Weinig.
     7
     8        Test: crypto/subtle/rsa-export-key.html
     9
     10        * bindings/js/JSCryptoKeySerializationJWK.h:
     11        * bindings/js/JSCryptoKeySerializationJWK.cpp:
     12        (WebCore::JSCryptoKeySerializationJWK::buildJSONForRSAComponents):
     13        (WebCore::JSCryptoKeySerializationJWK::addJWKAlgorithmToJSON):
     14        (WebCore::JSCryptoKeySerializationJWK::serialize):
     15        Added said support (this part works with private keys too).
     16
     17        * crypto/keys/CryptoKeyRSA.h:
     18        * crypto/mac/CryptoKeyRSAMac.cpp:
     19        (WebCore::CryptoKeyRSA::getPublicKeyComponents): Moved the logic for getting a
     20        public key from private one here for reuse in keySizeInBits().
     21        (WebCore::CryptoKeyRSA::isRestrictedToHash):
     22        (WebCore::CryptoKeyRSA::keySizeInBits):
     23        (WebCore::CryptoKeyRSA::exportData):
     24        Exposed information necessary for JWK serialization.
     25
    1262013-11-17  Alexey Proskuryakov  <ap@apple.com>
    227
  • trunk/Source/WebCore/bindings/js/JSCryptoKeySerializationJWK.cpp

    r159393 r159403  
    3838#include "CryptoKeyDataRSAComponents.h"
    3939#include "CryptoKeyHMAC.h"
     40#include "CryptoKeyRSA.h"
    4041#include "ExceptionCode.h"
    4142#include "JSDOMBinding.h"
     
    434435}
    435436
     437void JSCryptoKeySerializationJWK::buildJSONForRSAComponents(JSC::ExecState* exec, const CryptoKeyDataRSAComponents& data, JSC::JSObject* result)
     438{
     439    addToJSON(exec, result, "kty", "RSA");
     440    addToJSON(exec, result, "n", base64URLEncode(data.modulus()));
     441    addToJSON(exec, result, "e", base64URLEncode(data.exponent()));
     442
     443    if (data.type() == CryptoKeyDataRSAComponents::Type::Public)
     444        return;
     445
     446    addToJSON(exec, result, "d", base64URLEncode(data.privateExponent()));
     447
     448    if (!data.hasAdditionalPrivateKeyParameters())
     449        return;
     450
     451    addToJSON(exec, result, "p", base64URLEncode(data.firstPrimeInfo().primeFactor));
     452    addToJSON(exec, result, "q", base64URLEncode(data.secondPrimeInfo().primeFactor));
     453    addToJSON(exec, result, "dp", base64URLEncode(data.firstPrimeInfo().factorCRTExponent));
     454    addToJSON(exec, result, "dq", base64URLEncode(data.secondPrimeInfo().factorCRTExponent));
     455    addToJSON(exec, result, "qi", base64URLEncode(data.secondPrimeInfo().factorCRTCoefficient));
     456
     457    if (data.otherPrimeInfos().isEmpty())
     458        return;
     459
     460    JSArray* oth = constructEmptyArray(exec, 0, exec->lexicalGlobalObject(), data.otherPrimeInfos().size());
     461    for (size_t i = 0, size = data.otherPrimeInfos().size(); i < size; ++i) {
     462        JSObject* jsPrimeInfo = constructEmptyObject(exec);
     463        addToJSON(exec, jsPrimeInfo, "r", base64URLEncode(data.otherPrimeInfos()[i].primeFactor));
     464        addToJSON(exec, jsPrimeInfo, "d", base64URLEncode(data.otherPrimeInfos()[i].factorCRTExponent));
     465        addToJSON(exec, jsPrimeInfo, "t", base64URLEncode(data.otherPrimeInfos()[i].factorCRTCoefficient));
     466        oth->putDirectIndex(exec, i, jsPrimeInfo);
     467    }
     468    result->putDirect(exec->vm(), Identifier(exec, "oth"), oth);
     469}
     470
    436471void JSCryptoKeySerializationJWK::addToJSON(ExecState* exec, JSObject* json, const char* key, const String& value)
    437472{
     
    483518        }
    484519        break;
     520    case CryptoAlgorithmIdentifier::RSASSA_PKCS1_v1_5: {
     521        const CryptoKeyRSA& rsaKey = toCryptoKeyRSA(key);
     522        CryptoAlgorithmIdentifier hash;
     523        if (!rsaKey.isRestrictedToHash(hash))
     524            break;
     525        if (rsaKey.keySizeInBits() < 2048)
     526            break;
     527        switch (hash) {
     528        case CryptoAlgorithmIdentifier::SHA_256:
     529            jwkAlgorithm = "RS256";
     530            break;
     531        case CryptoAlgorithmIdentifier::SHA_384:
     532            jwkAlgorithm = "RS384";
     533            break;
     534        case CryptoAlgorithmIdentifier::SHA_512:
     535            jwkAlgorithm = "RS512";
     536            break;
     537        default:
     538            break;
     539        }
     540        break;
     541    }
    485542    default:
    486543        break;
     
    535592    if (isCryptoKeyDataOctetSequence(*keyData))
    536593        buildJSONForOctetSequence(exec, toCryptoKeyDataOctetSequence(*keyData).octetSequence(), result);
     594    else if (isCryptoKeyDataRSAComponents(*keyData))
     595        buildJSONForRSAComponents(exec, toCryptoKeyDataRSAComponents(*keyData), result);
    537596    else {
    538597        throwTypeError(exec, "Key doesn't support exportKey");
    539598        return String();
    540599    }
    541     ASSERT(!exec->hadException());
     600    if (exec->hadException())
     601        return String();
    542602
    543603    return JSONStringify(exec, result, 4);
  • trunk/Source/WebCore/bindings/js/JSCryptoKeySerializationJWK.h

    r159390 r159403  
    4343class CryptoAlgorithmParameters;
    4444class CryptoKey;
     45class CryptoKeyDataRSAComponents;
    4546
    4647class JSCryptoKeySerializationJWK FINAL : public CryptoKeySerialization {
     
    6768
    6869    static void buildJSONForOctetSequence(JSC::ExecState*, const Vector<uint8_t>&, JSC::JSObject* result);
     70    static void buildJSONForRSAComponents(JSC::ExecState*, const CryptoKeyDataRSAComponents&, JSC::JSObject* result);
    6971    static void addJWKAlgorithmToJSON(JSC::ExecState*, JSC::JSObject*, const CryptoKey& key);
    7072    static void addJWKUseToJSON(JSC::ExecState*, JSC::JSObject*, CryptoKeyUsage);
  • trunk/Source/WebCore/crypto/keys/CryptoKeyRSA.h

    r159390 r159403  
    5252
    5353    void restrictToHash(CryptoAlgorithmIdentifier);
     54    bool isRestrictedToHash(CryptoAlgorithmIdentifier&) const;
     55
     56    size_t keySizeInBits() const;
    5457
    5558    static void generatePair(CryptoAlgorithmIdentifier, unsigned modulusLength, const Vector<uint8_t>& publicExponent, bool extractable, CryptoKeyUsage, std::unique_ptr<PromiseWrapper>);
    56 
    57     virtual CryptoKeyClass keyClass() const OVERRIDE { return CryptoKeyClass::RSA; }
    5859
    5960    PlatformRSAKey platformKey() const { return m_platformKey; }
     
    6162private:
    6263    CryptoKeyRSA(CryptoAlgorithmIdentifier, CryptoKeyType, PlatformRSAKey, bool extractable, CryptoKeyUsage);
     64
     65    virtual CryptoKeyClass keyClass() const OVERRIDE { return CryptoKeyClass::RSA; }
    6366
    6467    virtual void buildAlgorithmDescription(CryptoAlgorithmDescriptionBuilder&) const OVERRIDE;
  • trunk/Source/WebCore/crypto/mac/CryptoKeyRSAMac.cpp

    r159390 r159403  
    6161static CCCryptorStatus getPublicKeyComponents(CCRSACryptorRef rsaKey, Vector<uint8_t>& modulus, Vector<uint8_t>& publicExponent)
    6262{
    63     ASSERT(CCRSAGetKeyType(rsaKey) == ccRSAKeyPublic);
     63    ASSERT(CCRSAGetKeyType(rsaKey) == ccRSAKeyPublic || CCRSAGetKeyType(rsaKey) == ccRSAKeyPrivate);
     64    bool keyIsPublic = CCRSAGetKeyType(rsaKey) == ccRSAKeyPublic;
     65    CCRSACryptorRef publicKey = keyIsPublic ? rsaKey : CCRSACryptorGetPublicKeyFromPrivateKey(rsaKey);
    6466
    6567    modulus.resize(16384);
     
    6769    publicExponent.resize(16384);
    6870    size_t exponentLength = publicExponent.size();
    69     CCCryptorStatus status = CCRSAGetKeyComponents(rsaKey, modulus.data(), &modulusLength, publicExponent.data(), &exponentLength, 0, 0, 0, 0);
     71    CCCryptorStatus status = CCRSAGetKeyComponents(publicKey, modulus.data(), &modulusLength, publicExponent.data(), &exponentLength, 0, 0, 0, 0);
     72    if (!keyIsPublic) {
     73        // CCRSACryptorGetPublicKeyFromPrivateKey has "Get" in the name, but its result needs to be released (see <rdar://problem/15449697>).
     74        CCRSACryptorRelease(publicKey);
     75    }
    7076    if (status)
    7177        return status;
     
    123129}
    124130
    125 void CryptoKeyRSA::buildAlgorithmDescription(CryptoAlgorithmDescriptionBuilder& builder) const
    126 {
    127     CryptoKey::buildAlgorithmDescription(builder);
    128 
    129     ASSERT(CCRSAGetKeyType(m_platformKey) == ccRSAKeyPublic || CCRSAGetKeyType(m_platformKey) == ccRSAKeyPrivate);
    130     bool platformKeyIsPublic = CCRSAGetKeyType(m_platformKey) == ccRSAKeyPublic;
    131     CCRSACryptorRef publicKey = platformKeyIsPublic ? m_platformKey : CCRSACryptorGetPublicKeyFromPrivateKey(m_platformKey);
    132 
     131bool CryptoKeyRSA::isRestrictedToHash(CryptoAlgorithmIdentifier& identifier) const
     132{
     133    if (!m_restrictedToSpecificHash)
     134        return false;
     135
     136    identifier = m_hash;
     137    return true;
     138}
     139
     140size_t CryptoKeyRSA::keySizeInBits() const
     141{
    133142    Vector<uint8_t> modulus;
    134143    Vector<uint8_t> publicExponent;
    135     CCCryptorStatus status = getPublicKeyComponents(publicKey, modulus, publicExponent);
    136     if (!platformKeyIsPublic) {
    137         // CCRSACryptorGetPublicKeyFromPrivateKey has "Get" in the name, but its result needs to be released (see <rdar://problem/15449697>).
    138         CCRSACryptorRelease(publicKey);
    139     }
     144    CCCryptorStatus status = getPublicKeyComponents(m_platformKey, modulus, publicExponent);
     145    if (status) {
     146        WTFLogAlways("Couldn't get RSA key components, status %d", status);
     147        return 0;
     148    }
     149
     150    return modulus.size() * 8;
     151}
     152
     153void CryptoKeyRSA::buildAlgorithmDescription(CryptoAlgorithmDescriptionBuilder& builder) const
     154{
     155    CryptoKey::buildAlgorithmDescription(builder);
     156
     157    Vector<uint8_t> modulus;
     158    Vector<uint8_t> publicExponent;
     159    CCCryptorStatus status = getPublicKeyComponents(m_platformKey, modulus, publicExponent);
    140160    if (status) {
    141161        WTFLogAlways("Couldn't get RSA key components, status %d", status);
     
    155175std::unique_ptr<CryptoKeyData> CryptoKeyRSA::exportData() const
    156176{
    157     // Not implemented yet.
    158177    ASSERT(extractable());
    159     return nullptr;
     178
     179    switch (CCRSAGetKeyType(m_platformKey)) {
     180    case ccRSAKeyPublic: {
     181        Vector<uint8_t> modulus;
     182        Vector<uint8_t> publicExponent;
     183        CCCryptorStatus status = getPublicKeyComponents(m_platformKey, modulus, publicExponent);
     184        if (status) {
     185            WTFLogAlways("Couldn't get RSA key components, status %d", status);
     186            return nullptr;
     187        }
     188        return CryptoKeyDataRSAComponents::createPublic(modulus, publicExponent);
     189    }
     190    case ccRSAKeyPrivate:
     191        // Not supported yet.
     192    default:
     193        return nullptr;
     194    }
    160195}
    161196
Note: See TracChangeset for help on using the changeset viewer.