1/*
2 * Copyright (C) 2013 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 *    notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 *    notice, this list of conditions and the following disclaimer in the
11 *    documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23 * THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#include "config.h"
27#include "CommonCryptoUtilities.h"
28
29#if ENABLE(SUBTLE_CRYPTO)
30
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
48namespace WebCore {
49
50bool getCommonCryptoDigestAlgorithm(CryptoAlgorithmIdentifier hashFunction, CCDigestAlgorithm& algorithm)
51{
52    switch (hashFunction) {
53    case CryptoAlgorithmIdentifier::SHA_1:
54        algorithm = kCCDigestSHA1;
55        return true;
56    case CryptoAlgorithmIdentifier::SHA_224:
57        algorithm = kCCDigestSHA224;
58        return true;
59    case CryptoAlgorithmIdentifier::SHA_256:
60        algorithm = kCCDigestSHA256;
61        return true;
62    case CryptoAlgorithmIdentifier::SHA_384:
63        algorithm = kCCDigestSHA384;
64        return true;
65    case CryptoAlgorithmIdentifier::SHA_512:
66        algorithm = kCCDigestSHA512;
67        return true;
68    default:
69        return false;
70    }
71}
72
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
173} // namespace WebCore
174
175#endif // ENABLE(SUBTLE_CRYPTO)
176