1/*
2 * Copyright (C) 2013 Google 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 are
6 * met:
7 *
8 *     * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 *     * Redistributions in binary form must reproduce the above
11 * copyright notice, this list of conditions and the following disclaimer
12 * in the documentation and/or other materials provided with the
13 * distribution.
14 *     * Neither the name of Google Inc. nor the names of its
15 * contributors may be used to endorse or promote products derived from
16 * this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31#include "config.h"
32#include "public/platform/WebCryptoAlgorithm.h"
33
34#include "public/platform/WebCryptoAlgorithmParams.h"
35#include "wtf/Assertions.h"
36#include "wtf/OwnPtr.h"
37#include "wtf/StdLibExtras.h"
38#include "wtf/ThreadSafeRefCounted.h"
39
40namespace blink {
41
42namespace {
43
44// A mapping from the algorithm ID to information about the algorithm.
45const WebCryptoAlgorithmInfo algorithmIdToInfo[] = {
46    { // Index 0
47        "AES-CBC", {
48            WebCryptoAlgorithmParamsTypeAesCbcParams, // Encrypt
49            WebCryptoAlgorithmParamsTypeAesCbcParams, // Decrypt
50            WebCryptoAlgorithmInfo::Undefined, // Sign
51            WebCryptoAlgorithmInfo::Undefined, // Verify
52            WebCryptoAlgorithmInfo::Undefined, // Digest
53            WebCryptoAlgorithmParamsTypeAesKeyGenParams, // GenerateKey
54            WebCryptoAlgorithmParamsTypeNone, // ImportKey
55            WebCryptoAlgorithmInfo::Undefined, // DeriveKey
56            WebCryptoAlgorithmInfo::Undefined, // DeriveBits
57            WebCryptoAlgorithmParamsTypeAesCbcParams, // WrapKey
58            WebCryptoAlgorithmParamsTypeAesCbcParams // UnwrapKey
59        }
60    }, { // Index 1
61        "HMAC", {
62            WebCryptoAlgorithmInfo::Undefined, // Encrypt
63            WebCryptoAlgorithmInfo::Undefined, // Decrypt
64            WebCryptoAlgorithmParamsTypeNone, // Sign
65            WebCryptoAlgorithmParamsTypeNone, // Verify
66            WebCryptoAlgorithmInfo::Undefined, // Digest
67            WebCryptoAlgorithmParamsTypeHmacKeyGenParams, // GenerateKey
68            WebCryptoAlgorithmParamsTypeHmacImportParams, // ImportKey
69            WebCryptoAlgorithmInfo::Undefined, // DeriveKey
70            WebCryptoAlgorithmInfo::Undefined, // DeriveBits
71            WebCryptoAlgorithmInfo::Undefined, // WrapKey
72            WebCryptoAlgorithmInfo::Undefined // UnwrapKey
73        }
74    }, { // Index 2
75        "RSASSA-PKCS1-v1_5", {
76            WebCryptoAlgorithmInfo::Undefined, // Encrypt
77            WebCryptoAlgorithmInfo::Undefined, // Decrypt
78            WebCryptoAlgorithmParamsTypeNone, // Sign
79            WebCryptoAlgorithmParamsTypeNone, // Verify
80            WebCryptoAlgorithmInfo::Undefined, // Digest
81            WebCryptoAlgorithmParamsTypeRsaHashedKeyGenParams, // GenerateKey
82            WebCryptoAlgorithmParamsTypeRsaHashedImportParams, // ImportKey
83            WebCryptoAlgorithmInfo::Undefined, // DeriveKey
84            WebCryptoAlgorithmInfo::Undefined, // DeriveBits
85            WebCryptoAlgorithmInfo::Undefined, // WrapKey
86            WebCryptoAlgorithmInfo::Undefined // UnwrapKey
87        }
88    }, { // Index 3
89        "SHA-1", {
90            WebCryptoAlgorithmInfo::Undefined, // Encrypt
91            WebCryptoAlgorithmInfo::Undefined, // Decrypt
92            WebCryptoAlgorithmInfo::Undefined, // Sign
93            WebCryptoAlgorithmInfo::Undefined, // Verify
94            WebCryptoAlgorithmParamsTypeNone, // Digest
95            WebCryptoAlgorithmInfo::Undefined, // GenerateKey
96            WebCryptoAlgorithmInfo::Undefined, // ImportKey
97            WebCryptoAlgorithmInfo::Undefined, // DeriveKey
98            WebCryptoAlgorithmInfo::Undefined, // DeriveBits
99            WebCryptoAlgorithmInfo::Undefined, // WrapKey
100            WebCryptoAlgorithmInfo::Undefined // UnwrapKey
101        }
102    }, { // Index 4
103        "SHA-256", {
104            WebCryptoAlgorithmInfo::Undefined, // Encrypt
105            WebCryptoAlgorithmInfo::Undefined, // Decrypt
106            WebCryptoAlgorithmInfo::Undefined, // Sign
107            WebCryptoAlgorithmInfo::Undefined, // Verify
108            WebCryptoAlgorithmParamsTypeNone, // Digest
109            WebCryptoAlgorithmInfo::Undefined, // GenerateKey
110            WebCryptoAlgorithmInfo::Undefined, // ImportKey
111            WebCryptoAlgorithmInfo::Undefined, // DeriveKey
112            WebCryptoAlgorithmInfo::Undefined, // DeriveBits
113            WebCryptoAlgorithmInfo::Undefined, // WrapKey
114            WebCryptoAlgorithmInfo::Undefined // UnwrapKey
115        }
116    }, { // Index 5
117        "SHA-384", {
118            WebCryptoAlgorithmInfo::Undefined, // Encrypt
119            WebCryptoAlgorithmInfo::Undefined, // Decrypt
120            WebCryptoAlgorithmInfo::Undefined, // Sign
121            WebCryptoAlgorithmInfo::Undefined, // Verify
122            WebCryptoAlgorithmParamsTypeNone, // Digest
123            WebCryptoAlgorithmInfo::Undefined, // GenerateKey
124            WebCryptoAlgorithmInfo::Undefined, // ImportKey
125            WebCryptoAlgorithmInfo::Undefined, // DeriveKey
126            WebCryptoAlgorithmInfo::Undefined, // DeriveBits
127            WebCryptoAlgorithmInfo::Undefined, // WrapKey
128            WebCryptoAlgorithmInfo::Undefined // UnwrapKey
129        }
130    }, { // Index 6
131        "SHA-512", {
132            WebCryptoAlgorithmInfo::Undefined, // Encrypt
133            WebCryptoAlgorithmInfo::Undefined, // Decrypt
134            WebCryptoAlgorithmInfo::Undefined, // Sign
135            WebCryptoAlgorithmInfo::Undefined, // Verify
136            WebCryptoAlgorithmParamsTypeNone, // Digest
137            WebCryptoAlgorithmInfo::Undefined, // GenerateKey
138            WebCryptoAlgorithmInfo::Undefined, // ImportKey
139            WebCryptoAlgorithmInfo::Undefined, // DeriveKey
140            WebCryptoAlgorithmInfo::Undefined, // DeriveBits
141            WebCryptoAlgorithmInfo::Undefined, // WrapKey
142            WebCryptoAlgorithmInfo::Undefined // UnwrapKey
143        }
144    }, { // Index 7
145        "AES-GCM", {
146            WebCryptoAlgorithmParamsTypeAesGcmParams, // Encrypt
147            WebCryptoAlgorithmParamsTypeAesGcmParams, // Decrypt
148            WebCryptoAlgorithmInfo::Undefined, // Sign
149            WebCryptoAlgorithmInfo::Undefined, // Verify
150            WebCryptoAlgorithmInfo::Undefined, // Digest
151            WebCryptoAlgorithmParamsTypeAesKeyGenParams, // GenerateKey
152            WebCryptoAlgorithmParamsTypeNone, // ImportKey
153            WebCryptoAlgorithmInfo::Undefined, // DeriveKey
154            WebCryptoAlgorithmInfo::Undefined, // DeriveBits
155            WebCryptoAlgorithmParamsTypeAesGcmParams, // WrapKey
156            WebCryptoAlgorithmParamsTypeAesGcmParams // UnwrapKey
157        }
158    }, { // Index 8
159        "RSA-OAEP", {
160            WebCryptoAlgorithmParamsTypeRsaOaepParams, // Encrypt
161            WebCryptoAlgorithmParamsTypeRsaOaepParams, // Decrypt
162            WebCryptoAlgorithmInfo::Undefined, // Sign
163            WebCryptoAlgorithmInfo::Undefined, // Verify
164            WebCryptoAlgorithmInfo::Undefined, // Digest
165            WebCryptoAlgorithmParamsTypeRsaHashedKeyGenParams, // GenerateKey
166            WebCryptoAlgorithmParamsTypeRsaHashedImportParams, // ImportKey
167            WebCryptoAlgorithmInfo::Undefined, // DeriveKey
168            WebCryptoAlgorithmInfo::Undefined, // DeriveBits
169            WebCryptoAlgorithmParamsTypeRsaOaepParams, // WrapKey
170            WebCryptoAlgorithmParamsTypeRsaOaepParams // UnwrapKey
171        }
172    }, { // Index 9
173        "AES-CTR", {
174            WebCryptoAlgorithmParamsTypeAesCtrParams, // Encrypt
175            WebCryptoAlgorithmParamsTypeAesCtrParams, // Decrypt
176            WebCryptoAlgorithmInfo::Undefined, // Sign
177            WebCryptoAlgorithmInfo::Undefined, // Verify
178            WebCryptoAlgorithmInfo::Undefined, // Digest
179            WebCryptoAlgorithmParamsTypeAesKeyGenParams, // GenerateKey
180            WebCryptoAlgorithmParamsTypeNone, // ImportKey
181            WebCryptoAlgorithmInfo::Undefined, // DeriveKey
182            WebCryptoAlgorithmInfo::Undefined, // DeriveBits
183            WebCryptoAlgorithmParamsTypeAesCtrParams, // WrapKey
184            WebCryptoAlgorithmParamsTypeAesCtrParams // UnwrapKey
185        }
186    }, { // Index 10
187        "AES-KW", {
188            WebCryptoAlgorithmInfo::Undefined, // Encrypt
189            WebCryptoAlgorithmInfo::Undefined, // Decrypt
190            WebCryptoAlgorithmInfo::Undefined, // Sign
191            WebCryptoAlgorithmInfo::Undefined, // Verify
192            WebCryptoAlgorithmInfo::Undefined, // Digest
193            WebCryptoAlgorithmParamsTypeAesKeyGenParams, // GenerateKey
194            WebCryptoAlgorithmParamsTypeNone, // ImportKey
195            WebCryptoAlgorithmInfo::Undefined, // DeriveKey
196            WebCryptoAlgorithmInfo::Undefined, // DeriveBits
197            WebCryptoAlgorithmParamsTypeNone, // WrapKey
198            WebCryptoAlgorithmParamsTypeNone // UnwrapKey
199        }
200    },
201};
202
203// Initializing the algorithmIdToInfo table above depends on knowing the enum
204// values for algorithm IDs. If those ever change, the table will need to be
205// updated.
206COMPILE_ASSERT(WebCryptoAlgorithmIdAesCbc == 0, AesCbc_idDoesntMatch);
207COMPILE_ASSERT(WebCryptoAlgorithmIdHmac == 1, Hmac_idDoesntMatch);
208COMPILE_ASSERT(WebCryptoAlgorithmIdRsaSsaPkcs1v1_5 == 2, RsaSsaPkcs1v1_5_idDoesntMatch);
209COMPILE_ASSERT(WebCryptoAlgorithmIdSha1 == 3, Sha1_idDoesntMatch);
210COMPILE_ASSERT(WebCryptoAlgorithmIdSha256 == 4, Sha256_idDoesntMatch);
211COMPILE_ASSERT(WebCryptoAlgorithmIdSha384 == 5, Sha384_idDoesntMatch);
212COMPILE_ASSERT(WebCryptoAlgorithmIdSha512 == 6, Sha512_idDoesntMatch);
213COMPILE_ASSERT(WebCryptoAlgorithmIdAesGcm == 7, AesGcm_idDoesntMatch);
214COMPILE_ASSERT(WebCryptoAlgorithmIdRsaOaep == 8, RsaOaep_idDoesntMatch);
215COMPILE_ASSERT(WebCryptoAlgorithmIdAesCtr == 9, AesCtr_idDoesntMatch);
216COMPILE_ASSERT(WebCryptoAlgorithmIdAesKw == 10, AesKw_idDoesntMatch);
217COMPILE_ASSERT(WebCryptoAlgorithmIdLast == 10, Last_idDoesntMatch);
218COMPILE_ASSERT(10 == WebCryptoOperationLast, UpdateParamsMapping);
219
220} // namespace
221
222class WebCryptoAlgorithmPrivate : public ThreadSafeRefCounted<WebCryptoAlgorithmPrivate> {
223public:
224    WebCryptoAlgorithmPrivate(WebCryptoAlgorithmId id, PassOwnPtr<WebCryptoAlgorithmParams> params)
225        : id(id)
226        , params(params)
227    {
228    }
229
230    WebCryptoAlgorithmId id;
231    OwnPtr<WebCryptoAlgorithmParams> params;
232};
233
234WebCryptoAlgorithm::WebCryptoAlgorithm(WebCryptoAlgorithmId id, PassOwnPtr<WebCryptoAlgorithmParams> params)
235    : m_private(adoptRef(new WebCryptoAlgorithmPrivate(id, params)))
236{
237}
238
239WebCryptoAlgorithm WebCryptoAlgorithm::createNull()
240{
241    return WebCryptoAlgorithm();
242}
243
244WebCryptoAlgorithm WebCryptoAlgorithm::adoptParamsAndCreate(WebCryptoAlgorithmId id, WebCryptoAlgorithmParams* params)
245{
246    return WebCryptoAlgorithm(id, adoptPtr(params));
247}
248
249const WebCryptoAlgorithmInfo* WebCryptoAlgorithm::lookupAlgorithmInfo(WebCryptoAlgorithmId id)
250{
251    if (id < 0 || id >= WTF_ARRAY_LENGTH(algorithmIdToInfo))
252        return 0;
253    return &algorithmIdToInfo[id];
254}
255
256bool WebCryptoAlgorithm::isNull() const
257{
258    return m_private.isNull();
259}
260
261WebCryptoAlgorithmId WebCryptoAlgorithm::id() const
262{
263    ASSERT(!isNull());
264    return m_private->id;
265}
266
267WebCryptoAlgorithmParamsType WebCryptoAlgorithm::paramsType() const
268{
269    ASSERT(!isNull());
270    if (!m_private->params)
271        return WebCryptoAlgorithmParamsTypeNone;
272    return m_private->params->type();
273}
274
275const WebCryptoAesCbcParams* WebCryptoAlgorithm::aesCbcParams() const
276{
277    ASSERT(!isNull());
278    if (paramsType() == WebCryptoAlgorithmParamsTypeAesCbcParams)
279        return static_cast<WebCryptoAesCbcParams*>(m_private->params.get());
280    return 0;
281}
282
283const WebCryptoAesCtrParams* WebCryptoAlgorithm::aesCtrParams() const
284{
285    ASSERT(!isNull());
286    if (paramsType() == WebCryptoAlgorithmParamsTypeAesCtrParams)
287        return static_cast<WebCryptoAesCtrParams*>(m_private->params.get());
288    return 0;
289}
290
291const WebCryptoAesKeyGenParams* WebCryptoAlgorithm::aesKeyGenParams() const
292{
293    ASSERT(!isNull());
294    if (paramsType() == WebCryptoAlgorithmParamsTypeAesKeyGenParams)
295        return static_cast<WebCryptoAesKeyGenParams*>(m_private->params.get());
296    return 0;
297}
298
299const WebCryptoHmacImportParams* WebCryptoAlgorithm::hmacImportParams() const
300{
301    ASSERT(!isNull());
302    if (paramsType() == WebCryptoAlgorithmParamsTypeHmacImportParams)
303        return static_cast<WebCryptoHmacImportParams*>(m_private->params.get());
304    return 0;
305}
306
307const WebCryptoHmacKeyGenParams* WebCryptoAlgorithm::hmacKeyGenParams() const
308{
309    ASSERT(!isNull());
310    if (paramsType() == WebCryptoAlgorithmParamsTypeHmacKeyGenParams)
311        return static_cast<WebCryptoHmacKeyGenParams*>(m_private->params.get());
312    return 0;
313}
314
315const WebCryptoAesGcmParams* WebCryptoAlgorithm::aesGcmParams() const
316{
317    ASSERT(!isNull());
318    if (paramsType() == WebCryptoAlgorithmParamsTypeAesGcmParams)
319        return static_cast<WebCryptoAesGcmParams*>(m_private->params.get());
320    return 0;
321}
322
323const WebCryptoRsaOaepParams* WebCryptoAlgorithm::rsaOaepParams() const
324{
325    ASSERT(!isNull());
326    if (paramsType() == WebCryptoAlgorithmParamsTypeRsaOaepParams)
327        return static_cast<WebCryptoRsaOaepParams*>(m_private->params.get());
328    return 0;
329}
330
331const WebCryptoRsaHashedImportParams* WebCryptoAlgorithm::rsaHashedImportParams() const
332{
333    ASSERT(!isNull());
334    if (paramsType() == WebCryptoAlgorithmParamsTypeRsaHashedImportParams)
335        return static_cast<WebCryptoRsaHashedImportParams*>(m_private->params.get());
336    return 0;
337}
338
339const WebCryptoRsaHashedKeyGenParams* WebCryptoAlgorithm::rsaHashedKeyGenParams() const
340{
341    ASSERT(!isNull());
342    if (paramsType() == WebCryptoAlgorithmParamsTypeRsaHashedKeyGenParams)
343        return static_cast<WebCryptoRsaHashedKeyGenParams*>(m_private->params.get());
344    return 0;
345}
346
347bool WebCryptoAlgorithm::isHash(WebCryptoAlgorithmId id)
348{
349    switch (id) {
350    case WebCryptoAlgorithmIdSha1:
351    case WebCryptoAlgorithmIdSha256:
352    case WebCryptoAlgorithmIdSha384:
353    case WebCryptoAlgorithmIdSha512:
354        return true;
355    case WebCryptoAlgorithmIdAesCbc:
356    case WebCryptoAlgorithmIdHmac:
357    case WebCryptoAlgorithmIdRsaSsaPkcs1v1_5:
358    case WebCryptoAlgorithmIdAesGcm:
359    case WebCryptoAlgorithmIdRsaOaep:
360    case WebCryptoAlgorithmIdAesCtr:
361    case WebCryptoAlgorithmIdAesKw:
362        break;
363    }
364    return false;
365}
366
367void WebCryptoAlgorithm::assign(const WebCryptoAlgorithm& other)
368{
369    m_private = other.m_private;
370}
371
372void WebCryptoAlgorithm::reset()
373{
374    m_private.reset();
375}
376
377} // namespace blink
378