Changeset 160029 in webkit


Ignore:
Timestamp:
Dec 3, 2013, 12:18:14 PM (11 years ago)
Author:
ap@apple.com
Message:

Support exporting private WebCrypto RSA keys
https://bugs.webkit.org/show_bug.cgi?id=124483

Reviewed by Anders Carlsson.

Source/WebCore:

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

It might be better to have our own bignum implementation in WTF, but we currently
don't, and the need for this computation is Common Crypto specific anyway.

  • crypto/CommonCryptoUtilities.h:
  • crypto/CommonCryptoUtilities.cpp:

(WebCore::CCBigNum::CCBigNum):
(WebCore::CCBigNum::~CCBigNum):
(WebCore::CCBigNum::operator=):
(WebCore::CCBigNum::data):
(WebCore::CCBigNum::operator-):
(WebCore::CCBigNum::operator%):
(WebCore::CCBigNum::inverse):
Added a minimal wrapper around CommonCrypto BigNum.

  • crypto/mac/CryptoKeyRSAMac.cpp:

(WebCore::getPrivateKeyComponents): Compute missing parts using CCBigNum.
(WebCore::CryptoKeyRSA::exportData): Implemented private key case.

LayoutTests:

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

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r160027 r160029  
     12013-12-03  Alexey Proskuryakov  <ap@apple.com>
     2
     3        Support exporting private WebCrypto RSA keys
     4        https://bugs.webkit.org/show_bug.cgi?id=124483
     5
     6        Reviewed by Anders Carlsson.
     7
     8        * crypto/subtle/rsa-export-private-key-expected.txt: Added.
     9        * crypto/subtle/rsa-export-private-key.html: Added.
     10
    1112013-12-03  Alexey Proskuryakov  <ap@apple.com>
    212
  • trunk/Source/WebCore/ChangeLog

    r160024 r160029  
     12013-12-03  Alexey Proskuryakov  <ap@apple.com>
     2
     3        Support exporting private WebCrypto RSA keys
     4        https://bugs.webkit.org/show_bug.cgi?id=124483
     5
     6        Reviewed by Anders Carlsson.
     7
     8        Test: crypto/subtle/rsa-export-private-key.html
     9
     10        It might be better to have our own bignum implementation in WTF, but we currently
     11        don't, and the need for this computation is Common Crypto specific anyway.
     12
     13        * crypto/CommonCryptoUtilities.h:
     14        * crypto/CommonCryptoUtilities.cpp:
     15        (WebCore::CCBigNum::CCBigNum):
     16        (WebCore::CCBigNum::~CCBigNum):
     17        (WebCore::CCBigNum::operator=):
     18        (WebCore::CCBigNum::data):
     19        (WebCore::CCBigNum::operator-):
     20        (WebCore::CCBigNum::operator%):
     21        (WebCore::CCBigNum::inverse):
     22        Added a minimal wrapper around CommonCrypto BigNum.
     23
     24        * crypto/mac/CryptoKeyRSAMac.cpp:
     25        (WebCore::getPrivateKeyComponents): Compute missing parts using CCBigNum.
     26        (WebCore::CryptoKeyRSA::exportData): Implemented private key case.
     27
    1282013-12-03  Ryosuke Niwa  <rniwa@webkit.org>
    229
  • trunk/Source/WebCore/crypto/CommonCryptoUtilities.cpp

    r159944 r160029  
    2929#if ENABLE(SUBTLE_CRYPTO)
    3030
     31#if defined(__has_include)
     32#if __has_include(<CommonCrypto/CommonBigNum.h>)
     33#include <CommonCrypto/CommonBigNum.h>
     34#endif
     35#endif
     36
     37typedef CCCryptorStatus CCStatus;
     38extern "C" CCBigNumRef CCBigNumFromData(CCStatus *status, const void *s, size_t len);
     39extern "C" size_t CCBigNumToData(CCStatus *status, const CCBigNumRef bn, void *to);
     40extern "C" uint32_t CCBigNumByteCount(const CCBigNumRef bn);
     41extern "C" CCBigNumRef CCCreateBigNum(CCStatus *status);
     42extern "C" void CCBigNumFree(CCBigNumRef bn);
     43extern "C" CCBigNumRef CCBigNumCopy(CCStatus *status, const CCBigNumRef bn);
     44extern "C" CCStatus CCBigNumSubI(CCBigNumRef result, const CCBigNumRef a, const uint32_t b);
     45extern "C" CCStatus CCBigNumMod(CCBigNumRef result, CCBigNumRef dividend, CCBigNumRef modulus);
     46extern "C" CCStatus CCBigNumInverseMod(CCBigNumRef result, const CCBigNumRef a, const CCBigNumRef modulus);
     47
    3148namespace WebCore {
    3249
     
    5471}
    5572
     73CCBigNum::CCBigNum(CCBigNumRef number)
     74    : m_number(number)
     75{
     76}
     77
     78CCBigNum::CCBigNum(const uint8_t* data, size_t size)
     79{
     80    CCStatus status = kCCSuccess;
     81    m_number = CCBigNumFromData(&status, data, size);
     82    RELEASE_ASSERT(!status);
     83}
     84
     85CCBigNum::~CCBigNum()
     86{
     87    CCBigNumFree(m_number);
     88}
     89
     90CCBigNum::CCBigNum(const CCBigNum& other)
     91{
     92    CCStatus status = kCCSuccess;
     93    m_number = CCBigNumCopy(&status, other.m_number);
     94    RELEASE_ASSERT(!status);
     95}
     96
     97CCBigNum::CCBigNum(CCBigNum&& other)
     98{
     99    m_number = other.m_number;
     100    other.m_number = nullptr;
     101}
     102
     103CCBigNum& CCBigNum::operator=(const CCBigNum& other)
     104{
     105    if (this == &other)
     106        return *this;
     107
     108    CCBigNumFree(m_number);
     109
     110    CCStatus status = kCCSuccess;
     111    m_number = CCBigNumCopy(&status, other.m_number);
     112    RELEASE_ASSERT(!status);
     113    return *this;
     114}
     115
     116CCBigNum& CCBigNum::operator=(CCBigNum&& other)
     117{
     118    if (this == &other)
     119        return *this;
     120
     121    m_number = other.m_number;
     122    other.m_number = nullptr;
     123
     124    return *this;
     125}
     126
     127Vector<uint8_t> CCBigNum::data() const
     128{
     129    Vector<uint8_t> result(CCBigNumByteCount(m_number));
     130    CCStatus status = kCCSuccess;
     131    CCBigNumToData(&status, m_number, result.data());
     132    RELEASE_ASSERT(!status);
     133
     134    return result;
     135}
     136
     137CCBigNum CCBigNum::operator-(uint32_t b) const
     138{
     139    CCStatus status = kCCSuccess;
     140    CCBigNumRef result = CCCreateBigNum(&status);
     141    RELEASE_ASSERT(!status);
     142
     143    status = CCBigNumSubI(result, m_number, b);
     144    RELEASE_ASSERT(!status);
     145
     146    return result;
     147}
     148
     149CCBigNum CCBigNum::operator%(const CCBigNum& modulus) const
     150{
     151    CCStatus status = kCCSuccess;
     152    CCBigNumRef result = CCCreateBigNum(&status);
     153    RELEASE_ASSERT(!status);
     154
     155    status = CCBigNumMod(result, m_number, modulus.m_number);
     156    RELEASE_ASSERT(!status);
     157
     158    return result;
     159}
     160
     161CCBigNum CCBigNum::inverse(const CCBigNum& modulus) const
     162{
     163    CCStatus status = kCCSuccess;
     164    CCBigNumRef result = CCCreateBigNum(&status);
     165    RELEASE_ASSERT(!status);
     166
     167    status = CCBigNumInverseMod(result, m_number, modulus.m_number);
     168    RELEASE_ASSERT(!status);
     169
     170    return result;
     171}
     172
    56173} // namespace WebCore
    57174
  • trunk/Source/WebCore/crypto/CommonCryptoUtilities.h

    r159951 r160029  
    3030
    3131#include "CryptoAlgorithmIdentifier.h"
    32 
    3332#include <CommonCrypto/CommonCryptor.h>
     33#include <wtf/Vector.h>
    3434
    3535#if defined(__has_include)
     
    7272#endif
    7373
     74typedef struct _CCBigNumRef *CCBigNumRef;
     75
    7476typedef struct __CCRandom *CCRandomRef;
    7577extern const CCRandomRef kCCRandomDefault;
     
    9092namespace WebCore {
    9193
     94class CCBigNum {
     95public:
     96    CCBigNum(const uint8_t*, size_t);
     97    ~CCBigNum();
     98
     99    CCBigNum(const CCBigNum&);
     100    CCBigNum(CCBigNum&&);
     101    CCBigNum& operator=(const CCBigNum&);
     102    CCBigNum& operator=(CCBigNum&&);
     103
     104    Vector<uint8_t> data() const;
     105
     106    CCBigNum operator-(uint32_t) const;
     107    CCBigNum operator%(const CCBigNum&) const;
     108    CCBigNum inverse(const CCBigNum& modulus) const;
     109
     110private:
     111    CCBigNum(CCBigNumRef);
     112
     113    CCBigNumRef m_number;
     114};
     115
    92116bool getCommonCryptoDigestAlgorithm(CryptoAlgorithmIdentifier, CCDigestAlgorithm&);
    93117
  • trunk/Source/WebCore/crypto/mac/CryptoKeyRSAMac.cpp

    r159951 r160029  
    6060}
    6161
     62static CCCryptorStatus getPrivateKeyComponents(CCRSACryptorRef rsaKey, Vector<uint8_t>& privateExponent, CryptoKeyDataRSAComponents::PrimeInfo& firstPrimeInfo, CryptoKeyDataRSAComponents::PrimeInfo& secondPrimeInfo)
     63{
     64    ASSERT(CCRSAGetKeyType(rsaKey) == ccRSAKeyPrivate);
     65
     66    Vector<uint8_t> unusedModulus(16384);
     67    size_t modulusLength = unusedModulus.size();
     68    privateExponent.resize(16384);
     69    size_t exponentLength = privateExponent.size();
     70    firstPrimeInfo.primeFactor.resize(16384);
     71    size_t pLength = firstPrimeInfo.primeFactor.size();
     72    secondPrimeInfo.primeFactor.resize(16384);
     73    size_t qLength = secondPrimeInfo.primeFactor.size();
     74
     75    CCCryptorStatus status = CCRSAGetKeyComponents(rsaKey, unusedModulus.data(), &modulusLength, privateExponent.data(), &exponentLength, firstPrimeInfo.primeFactor.data(), &pLength, secondPrimeInfo.primeFactor.data(), &qLength);
     76    if (status)
     77        return status;
     78
     79    privateExponent.shrink(exponentLength);
     80    firstPrimeInfo.primeFactor.shrink(pLength);
     81    secondPrimeInfo.primeFactor.shrink(qLength);
     82
     83    CCBigNum d(privateExponent.data(), privateExponent.size());
     84    CCBigNum p(firstPrimeInfo.primeFactor.data(), firstPrimeInfo.primeFactor.size());
     85    CCBigNum q(secondPrimeInfo.primeFactor.data(), secondPrimeInfo.primeFactor.size());
     86
     87    CCBigNum dp = d % (p - 1);
     88    CCBigNum dq = d % (q - 1);
     89    CCBigNum qi = q.inverse(p);
     90
     91    firstPrimeInfo.factorCRTExponent = dp.data();
     92    secondPrimeInfo.factorCRTExponent = dq.data();
     93    secondPrimeInfo.factorCRTCoefficient = qi.data();
     94
     95    return status;
     96}
     97
    6298CryptoKeyRSA::CryptoKeyRSA(CryptoAlgorithmIdentifier identifier, CryptoKeyType type, PlatformRSAKey platformKey, bool extractable, CryptoKeyUsage usage)
    6399    : CryptoKey(identifier, type, extractable, usage)
     
    166202        return CryptoKeyDataRSAComponents::createPublic(modulus, publicExponent);
    167203    }
    168     case ccRSAKeyPrivate:
    169         // Not supported yet.
     204    case ccRSAKeyPrivate: {
     205        Vector<uint8_t> modulus;
     206        Vector<uint8_t> publicExponent;
     207        CCCryptorStatus status = getPublicKeyComponents(m_platformKey, modulus, publicExponent);
     208        if (status) {
     209            WTFLogAlways("Couldn't get RSA key components, status %d", status);
     210            return nullptr;
     211        }
     212        Vector<uint8_t> privateExponent;
     213        CryptoKeyDataRSAComponents::PrimeInfo firstPrimeInfo;
     214        CryptoKeyDataRSAComponents::PrimeInfo secondPrimeInfo;
     215        Vector<CryptoKeyDataRSAComponents::PrimeInfo> otherPrimeInfos; // Always empty, CommonCrypto only supports two primes (cf. <rdar://problem/15444074>).
     216        status = getPrivateKeyComponents(m_platformKey, privateExponent, firstPrimeInfo, secondPrimeInfo);
     217        if (status) {
     218            WTFLogAlways("Couldn't get RSA key components, status %d", status);
     219            return nullptr;
     220        }
     221        return CryptoKeyDataRSAComponents::createPrivateWithAdditionalData(modulus, publicExponent, privateExponent, firstPrimeInfo, secondPrimeInfo, otherPrimeInfos);
     222    }
    170223    default:
    171224        return nullptr;
Note: See TracChangeset for help on using the changeset viewer.