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