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 #ifndef WebCrypto_h 32 #define WebCrypto_h 33 34 #include "WebCommon.h" 35 #include "WebCryptoAlgorithm.h" 36 #include "WebCryptoKey.h" 37 #include "WebPrivatePtr.h" 38 #include "WebString.h" 39 #include "WebVector.h" 40 41 #if INSIDE_BLINK 42 namespace WTF { template <typename T> class PassRefPtr; } 43 #endif 44 45 namespace blink { 46 47 class CryptoResult; 48 class WebArrayBuffer; 49 class WebString; 50 51 enum WebCryptoErrorType { 52 WebCryptoErrorTypeType, 53 WebCryptoErrorTypeNotSupported, 54 WebCryptoErrorTypeSyntax, 55 WebCryptoErrorTypeInvalidState, 56 WebCryptoErrorTypeInvalidAccess, 57 WebCryptoErrorTypeUnknown, 58 WebCryptoErrorTypeData, 59 WebCryptoErrorTypeOperation, 60 }; 61 62 class WebCryptoResult { 63 public: WebCryptoResult(const WebCryptoResult & o)64 WebCryptoResult(const WebCryptoResult& o) 65 { 66 assign(o); 67 } 68 ~WebCryptoResult()69 ~WebCryptoResult() 70 { 71 reset(); 72 } 73 74 WebCryptoResult& operator=(const WebCryptoResult& o) 75 { 76 assign(o); 77 return *this; 78 } 79 80 // Note that WebString is NOT safe to pass across threads. 81 // 82 // Error details are surfaced in an exception, and MUST NEVER reveal any 83 // secret information such as bytes of the key or plain text. An 84 // appropriate error would be something like: 85 // "iv must be 16 bytes long". 86 BLINK_PLATFORM_EXPORT void completeWithError(WebCryptoErrorType, const WebString&); 87 88 // Note that WebArrayBuffer is NOT safe to create from another thread. 89 BLINK_PLATFORM_EXPORT void completeWithBuffer(const WebArrayBuffer&); 90 // Makes a copy of the input data given as a pointer and byte length. 91 BLINK_PLATFORM_EXPORT void completeWithBuffer(const void*, unsigned); 92 BLINK_PLATFORM_EXPORT void completeWithJson(const char* utf8Data, unsigned length); 93 BLINK_PLATFORM_EXPORT void completeWithBoolean(bool); 94 BLINK_PLATFORM_EXPORT void completeWithKey(const WebCryptoKey&); 95 BLINK_PLATFORM_EXPORT void completeWithKeyPair(const WebCryptoKey& publicKey, const WebCryptoKey& privateKey); 96 97 // Returns true if the underlying operation was cancelled. 98 // This method can be called from any thread. 99 BLINK_PLATFORM_EXPORT bool cancelled() const; 100 101 #if INSIDE_BLINK 102 BLINK_PLATFORM_EXPORT explicit WebCryptoResult(const WTF::PassRefPtr<CryptoResult>&); 103 #endif 104 105 private: 106 BLINK_PLATFORM_EXPORT void reset(); 107 BLINK_PLATFORM_EXPORT void assign(const WebCryptoResult&); 108 109 WebPrivatePtr<CryptoResult> m_impl; 110 }; 111 112 class WebCryptoDigestor { 113 public: ~WebCryptoDigestor()114 virtual ~WebCryptoDigestor() { } 115 116 // consume() will return |true| on the successful addition of data to the 117 // partially generated digest. It will return |false| when that fails. After 118 // a return of |false|, consume() should not be called again (nor should 119 // finish() be called). consume(const unsigned char * data,unsigned dataSize)120 virtual bool consume(const unsigned char* data, unsigned dataSize) { return false; } 121 122 // finish() will return |true| if the digest has been successfully computed 123 // and put into the result buffer, otherwise it will return |false|. In 124 // either case, neither finish() nor consume() should be called again after 125 // a call to finish(). resultData is valid until the WebCrytpoDigestor 126 // object is destroyed. finish(unsigned char * & resultData,unsigned & resultDataSize)127 virtual bool finish(unsigned char*& resultData, unsigned& resultDataSize) { return false; } 128 129 protected: WebCryptoDigestor()130 WebCryptoDigestor() { } 131 }; 132 133 class WebCrypto { 134 public: 135 // WebCrypto is the interface for starting one-shot cryptographic 136 // operations. 137 // 138 // ----------------------- 139 // Completing the request 140 // ----------------------- 141 // 142 // Implementations signal completion by calling one of the methods on 143 // "result". Only a single result/error should be set for the request. 144 // Different operations expect different result types based on the 145 // algorithm parameters; see the Web Crypto standard for details. 146 // 147 // The result can be set either synchronously while handling the request, 148 // or asynchronously after the method has returned. When completing 149 // asynchronously make a copy of the WebCryptoResult and call it from the 150 // same thread that started the request. 151 // 152 // If the request was cancelled it is not necessary for implementations to 153 // set the result. 154 // 155 // ----------------------- 156 // Threading 157 // ----------------------- 158 // 159 // The WebCrypto interface will be called from blink threads (main or 160 // web worker). All communication back to Blink must be on this same thread. 161 // 162 // Notably: 163 // 164 // * The WebCryptoResult can be copied between threads, however all 165 // methods other than the destructor must be called from the origin 166 // Blink thread. 167 // 168 // * WebCryptoKey and WebCryptoAlgorithm ARE threadsafe. They can be 169 // safely copied between threads and accessed. Copying is cheap because 170 // they are internally reference counted. 171 // 172 // * WebArrayBuffer is NOT threadsafe. It should only be created from the 173 // target Blink thread. This means threaded implementations may have to 174 // make a copy of the output buffer. 175 // 176 // ----------------------- 177 // Inputs 178 // ----------------------- 179 // 180 // * Data buffers are passed as (basePointer, byteLength) pairs. 181 // These buffers are only valid during the call itself. Asynchronous 182 // implementations wishing to access it after the function returns 183 // should make a copy. 184 // 185 // * All WebCryptoKeys are guaranteeed to be !isNull(). 186 // 187 // * All WebCryptoAlgorithms are guaranteed to be !isNull() 188 // 189 // * Look to the Web Crypto spec for an explanation of the parameter. The 190 // method names here have a 1:1 correspondence with those of 191 // crypto.subtle, with the exception of "verify" which is here called 192 // "verifySignature". 193 // 194 // ----------------------- 195 // Guarantees on input validity 196 // ----------------------- 197 // 198 // Implementations MUST carefully sanitize algorithm inputs before using 199 // them, as they come directly from the user. Few checks have been done on 200 // algorithm parameters prior to passing to the embedder. 201 // 202 // Only the following checks can be assumed as having already passed: 203 // 204 // * The key is extractable when calling into exportKey/wrapKey. 205 // * The key usages permit the operation being requested. 206 // * The key's algorithm matches that of the requested operation. 207 // encrypt(const WebCryptoAlgorithm &,const WebCryptoKey &,const unsigned char * data,unsigned dataSize,WebCryptoResult result)208 virtual void encrypt(const WebCryptoAlgorithm&, const WebCryptoKey&, const unsigned char* data, unsigned dataSize, WebCryptoResult result) { result.completeWithError(WebCryptoErrorTypeNotSupported, ""); } decrypt(const WebCryptoAlgorithm &,const WebCryptoKey &,const unsigned char * data,unsigned dataSize,WebCryptoResult result)209 virtual void decrypt(const WebCryptoAlgorithm&, const WebCryptoKey&, const unsigned char* data, unsigned dataSize, WebCryptoResult result) { result.completeWithError(WebCryptoErrorTypeNotSupported, ""); } sign(const WebCryptoAlgorithm &,const WebCryptoKey &,const unsigned char * data,unsigned dataSize,WebCryptoResult result)210 virtual void sign(const WebCryptoAlgorithm&, const WebCryptoKey&, const unsigned char* data, unsigned dataSize, WebCryptoResult result) { result.completeWithError(WebCryptoErrorTypeNotSupported, ""); } verifySignature(const WebCryptoAlgorithm &,const WebCryptoKey &,const unsigned char * signature,unsigned signatureSize,const unsigned char * data,unsigned dataSize,WebCryptoResult result)211 virtual void verifySignature(const WebCryptoAlgorithm&, const WebCryptoKey&, const unsigned char* signature, unsigned signatureSize, const unsigned char* data, unsigned dataSize, WebCryptoResult result) { result.completeWithError(WebCryptoErrorTypeNotSupported, ""); } digest(const WebCryptoAlgorithm &,const unsigned char * data,unsigned dataSize,WebCryptoResult result)212 virtual void digest(const WebCryptoAlgorithm&, const unsigned char* data, unsigned dataSize, WebCryptoResult result) { result.completeWithError(WebCryptoErrorTypeNotSupported, ""); } generateKey(const WebCryptoAlgorithm &,bool extractable,WebCryptoKeyUsageMask,WebCryptoResult result)213 virtual void generateKey(const WebCryptoAlgorithm&, bool extractable, WebCryptoKeyUsageMask, WebCryptoResult result) { result.completeWithError(WebCryptoErrorTypeNotSupported, ""); } importKey(WebCryptoKeyFormat,const unsigned char * keyData,unsigned keyDataSize,const WebCryptoAlgorithm &,bool extractable,WebCryptoKeyUsageMask,WebCryptoResult result)214 virtual void importKey(WebCryptoKeyFormat, const unsigned char* keyData, unsigned keyDataSize, const WebCryptoAlgorithm&, bool extractable, WebCryptoKeyUsageMask, WebCryptoResult result) { result.completeWithError(WebCryptoErrorTypeNotSupported, ""); } exportKey(WebCryptoKeyFormat,const WebCryptoKey &,WebCryptoResult result)215 virtual void exportKey(WebCryptoKeyFormat, const WebCryptoKey&, WebCryptoResult result) { result.completeWithError(WebCryptoErrorTypeNotSupported, ""); } wrapKey(WebCryptoKeyFormat,const WebCryptoKey & key,const WebCryptoKey & wrappingKey,const WebCryptoAlgorithm &,WebCryptoResult result)216 virtual void wrapKey(WebCryptoKeyFormat, const WebCryptoKey& key, const WebCryptoKey& wrappingKey, const WebCryptoAlgorithm&, WebCryptoResult result) { result.completeWithError(WebCryptoErrorTypeNotSupported, ""); } unwrapKey(WebCryptoKeyFormat,const unsigned char * wrappedKey,unsigned wrappedKeySize,const WebCryptoKey &,const WebCryptoAlgorithm & unwrapAlgorithm,const WebCryptoAlgorithm & unwrappedKeyAlgorithm,bool extractable,WebCryptoKeyUsageMask,WebCryptoResult result)217 virtual void unwrapKey(WebCryptoKeyFormat, const unsigned char* wrappedKey, unsigned wrappedKeySize, const WebCryptoKey&, const WebCryptoAlgorithm& unwrapAlgorithm, const WebCryptoAlgorithm& unwrappedKeyAlgorithm, bool extractable, WebCryptoKeyUsageMask, WebCryptoResult result) { result.completeWithError(WebCryptoErrorTypeNotSupported, ""); } 218 219 // This is the exception to the "Completing the request" guarantees 220 // outlined above. This is useful for Blink internal crypto and is not part 221 // of the WebCrypto standard. createDigestor must provide the result via 222 // the WebCryptoDigestor object synchronously. createDigestor may return 0 223 // if it fails to create a WebCryptoDigestor. If it succeeds, the 224 // WebCryptoDigestor returned by createDigestor must be freed by the 225 // caller. createDigestor(WebCryptoAlgorithmId algorithmId)226 virtual WebCryptoDigestor* createDigestor(WebCryptoAlgorithmId algorithmId) { return 0; } 227 228 // ----------------------- 229 // Structured clone 230 // ----------------------- 231 // 232 // deserializeKeyForClone() and serializeKeyForClone() are used for 233 // implementing structured cloning of WebCryptoKey. 234 // 235 // Blink is responsible for saving and restoring all of the attributes of 236 // WebCryptoKey EXCEPT for the actual key data: 237 // 238 // In other words, Blink takes care of serializing: 239 // * Key usages 240 // * Key extractability 241 // * Key algorithm 242 // * Key type (public, private, secret) 243 // 244 // The embedder is responsible for saving the key data itself. 245 // 246 // Visibility of the serialized key data: 247 // 248 // The serialized key data will NOT be visible to web pages. So if the 249 // serialized format were to include key bytes as plain text, this wouldn't 250 // make it available to web pages. 251 // 252 // Longevity of the key data: 253 // 254 // The serialized key data is intended to be long lived (years) and MUST 255 // be using a stable format. For instance a key might be persisted to 256 // IndexedDB and should be able to be deserialized correctly in the 257 // future. 258 // 259 // Error handling and asynchronous completion: 260 // 261 // Serialization/deserialization must complete synchronously, and will 262 // block the JavaScript thread. 263 // 264 // The only reasons to fail serialization/deserialization are: 265 // * Key serialization not yet implemented 266 // * The bytes to deserialize were corrupted 267 268 // Creates a new key given key data which was written using 269 // serializeKeyForClone(). Returns true on success. deserializeKeyForClone(const WebCryptoKeyAlgorithm &,WebCryptoKeyType,bool extractable,WebCryptoKeyUsageMask,const unsigned char * keyData,unsigned keyDataSize,WebCryptoKey &)270 virtual bool deserializeKeyForClone(const WebCryptoKeyAlgorithm&, WebCryptoKeyType, bool extractable, WebCryptoKeyUsageMask, const unsigned char* keyData, unsigned keyDataSize, WebCryptoKey&) { return false; } 271 272 // Writes the key data into the given WebVector. 273 // Returns true on success. serializeKeyForClone(const WebCryptoKey &,WebVector<unsigned char> &)274 virtual bool serializeKeyForClone(const WebCryptoKey&, WebVector<unsigned char>&) { return false; } 275 276 protected: ~WebCrypto()277 virtual ~WebCrypto() { } 278 }; 279 280 } // namespace blink 281 282 #endif 283