[iOS] Support pasting item-provider-backed data on the pasteboard as attachment elements
[WebKit-https.git] / Source / WebCore / loader / ResourceCryptographicDigest.cpp
1 /*
2  * Copyright (C) 2017 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 "ResourceCryptographicDigest.h"
28
29 #include "ParsingUtilities.h"
30 #include <pal/crypto/CryptoDigest.h>
31 #include <wtf/text/Base64.h>
32
33 namespace WebCore {
34
35 template<typename CharacterType>
36 static bool parseHashAlgorithmAdvancingPosition(const CharacterType*& position, const CharacterType* end, ResourceCryptographicDigest::Algorithm& algorithm)
37 {
38     // FIXME: This would be much cleaner with a lookup table of pairs of label / algorithm enum values, but I can't
39     // figure out how to keep the labels compiletime strings for skipExactlyIgnoringASCIICase.
40
41     if (skipExactlyIgnoringASCIICase(position, end, "sha256")) {
42         algorithm = ResourceCryptographicDigest::Algorithm::SHA256;
43         return true;
44     }
45     if (skipExactlyIgnoringASCIICase(position, end, "sha384")) {
46         algorithm = ResourceCryptographicDigest::Algorithm::SHA384;
47         return true;
48     }
49     if (skipExactlyIgnoringASCIICase(position, end, "sha512")) {
50         algorithm = ResourceCryptographicDigest::Algorithm::SHA512;
51         return true;
52     }
53
54     return false;
55 }
56
57 template<typename CharacterType>
58 static Optional<ResourceCryptographicDigest> parseCryptographicDigestImpl(const CharacterType*& position, const CharacterType* end)
59 {
60     if (position == end)
61         return WTF::nullopt;
62
63     ResourceCryptographicDigest::Algorithm algorithm;
64     if (!parseHashAlgorithmAdvancingPosition(position, end, algorithm))
65         return WTF::nullopt;
66
67     if (!skipExactly<CharacterType>(position, end, '-'))
68         return WTF::nullopt;
69
70     const CharacterType* beginHashValue = position;
71     skipWhile<CharacterType, isBase64OrBase64URLCharacter>(position, end);
72     skipExactly<CharacterType>(position, end, '=');
73     skipExactly<CharacterType>(position, end, '=');
74
75     if (position == beginHashValue)
76         return WTF::nullopt;
77
78     Vector<uint8_t> digest;
79     StringView hashValue(beginHashValue, position - beginHashValue);
80     if (!base64Decode(hashValue, digest, Base64ValidatePadding)) {
81         if (!base64URLDecode(hashValue, digest))
82             return WTF::nullopt;
83     }
84
85     return ResourceCryptographicDigest { algorithm, WTFMove(digest) };
86 }
87
88 Optional<ResourceCryptographicDigest> parseCryptographicDigest(const UChar*& begin, const UChar* end)
89 {
90     return parseCryptographicDigestImpl(begin, end);
91 }
92
93 Optional<ResourceCryptographicDigest> parseCryptographicDigest(const LChar*& begin, const LChar* end)
94 {
95     return parseCryptographicDigestImpl(begin, end);
96 }
97
98 template<typename CharacterType>
99 static Optional<EncodedResourceCryptographicDigest> parseEncodedCryptographicDigestImpl(const CharacterType*& position, const CharacterType* end)
100 {
101     if (position == end)
102         return WTF::nullopt;
103
104     EncodedResourceCryptographicDigest::Algorithm algorithm;
105     if (!parseHashAlgorithmAdvancingPosition(position, end, algorithm))
106         return WTF::nullopt;
107
108     if (!skipExactly<CharacterType>(position, end, '-'))
109         return WTF::nullopt;
110
111     const CharacterType* beginHashValue = position;
112     skipWhile<CharacterType, isBase64OrBase64URLCharacter>(position, end);
113     skipExactly<CharacterType>(position, end, '=');
114     skipExactly<CharacterType>(position, end, '=');
115
116     if (position == beginHashValue)
117         return WTF::nullopt;
118
119     return EncodedResourceCryptographicDigest { algorithm, String(beginHashValue, position - beginHashValue) };
120 }
121
122 Optional<EncodedResourceCryptographicDigest> parseEncodedCryptographicDigest(const UChar*& begin, const UChar* end)
123 {
124     return parseEncodedCryptographicDigestImpl(begin, end);
125 }
126
127 Optional<EncodedResourceCryptographicDigest> parseEncodedCryptographicDigest(const LChar*& begin, const LChar* end)
128 {
129     return parseEncodedCryptographicDigestImpl(begin, end);
130 }
131
132 Optional<ResourceCryptographicDigest> decodeEncodedResourceCryptographicDigest(const EncodedResourceCryptographicDigest& encodedDigest)
133 {
134     Vector<uint8_t> digest;
135     if (!base64Decode(encodedDigest.digest, digest, Base64ValidatePadding)) {
136         if (!base64URLDecode(encodedDigest.digest, digest))
137             return WTF::nullopt;
138     }
139
140     return ResourceCryptographicDigest { encodedDigest.algorithm, WTFMove(digest) };
141 }
142
143 static PAL::CryptoDigest::Algorithm toCryptoDigestAlgorithm(ResourceCryptographicDigest::Algorithm algorithm)
144 {
145     switch (algorithm) {
146     case ResourceCryptographicDigest::Algorithm::SHA256:
147         return PAL::CryptoDigest::Algorithm::SHA_256;
148     case ResourceCryptographicDigest::Algorithm::SHA384:
149         return PAL::CryptoDigest::Algorithm::SHA_384;
150     case ResourceCryptographicDigest::Algorithm::SHA512:
151         return PAL::CryptoDigest::Algorithm::SHA_512;
152     }
153     ASSERT_NOT_REACHED();
154     return PAL::CryptoDigest::Algorithm::SHA_512;
155 }
156
157 ResourceCryptographicDigest cryptographicDigestForBytes(ResourceCryptographicDigest::Algorithm algorithm, const void* bytes, size_t length)
158 {
159     auto cryptoDigest = PAL::CryptoDigest::create(toCryptoDigestAlgorithm(algorithm));
160     cryptoDigest->addBytes(bytes, length);
161     return { algorithm, cryptoDigest->computeHash() };
162 }
163
164 }