blob: ce44fe6b6fe76600ae4162b546c4e647686533c9 [file] [log] [blame]
// Copyright 2017 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Module Overview: Starboard Cryptography module
//
// Hardware-accelerated cryptography. Platforms should **only** implement this
// when there are **hardware-accelerated** cryptography facilities. Applications
// must fall back to platform-independent CPU-based algorithms if the cipher
// algorithm isn't supported in hardware.
//
// # Tips for Porters
//
// You should implement cipher algorithms in this descending order of priority
// to maximize usage for SSL.
//
// 1. GCM - The preferred block cipher mode for OpenSSL, mainly due to speed.
// 2. CTR - This can be used internally with GCM, as long as the CTR
// implementation only uses the last 4 bytes of the IV for the
// counter. (i.e. 96-bit IV, 32-bit counter)
// 3. ECB - This can be used (with a null IV) with any of the other cipher
// block modes to accelerate the core AES algorithm if none of the
// streaming modes can be accelerated.
// 4. CBC - GCM is always preferred if the server and client both support
// it. If not, they will generally negotiate down to AES-CBC. If this
// happens, and CBC is supported by SbCryptography, then it will be
// accelerated appropriately. But, most servers should support GCM,
// so it is not likely to come up much, which is why it is the lowest
// priority.
//
// Further reading on block cipher modes:
//
// https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation
//
// https://crbug.com/442572
//
// https://crypto.stackexchange.com/questions/10775/practical-disadvantages-of-gcm-mode-encryption
//
#ifndef STARBOARD_CRYPTOGRAPHY_H_
#define STARBOARD_CRYPTOGRAPHY_H_
#include "starboard/configuration.h"
#include "starboard/export.h"
#include "starboard/types.h"
#ifdef __cplusplus
extern "C" {
#endif
// String literal for the AES symmetric block cipher.
// https://en.wikipedia.org/wiki/Advanced_Encryption_Standard
#define kSbCryptographyAlgorithmAes "aes"
// The direction of a cryptographic transformation.
typedef enum SbCryptographyDirection {
// Cryptographic transformations that encode/encrypt data into a
// target format.
kSbCryptographyDirectionEncode,
// Cryptographic transformations that decode/decrypt data into
// its original form.
kSbCryptographyDirectionDecode,
} SbCryptographyDirection;
// The method of chaining encrypted blocks in a sequence.
// https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation
typedef enum SbCryptographyBlockCipherMode {
// Cipher Block Chaining mode.
kSbCryptographyBlockCipherModeCbc,
// Cipher Feedback mode.
kSbCryptographyBlockCipherModeCfb,
// Counter mode: A nonce is combined with an increasing counter.
kSbCryptographyBlockCipherModeCtr,
// Electronic Code Book mode: No chaining.
kSbCryptographyBlockCipherModeEcb,
// Output Feedback mode.
kSbCryptographyBlockCipherModeOfb,
// Galois/Counter Mode.
kSbCryptographyBlockCipherModeGcm,
} SbCryptographyBlockCipherMode;
// Private structure representing a cryptographic transformer
// configuration and state.
typedef struct SbCryptographyTransformerPrivate
SbCryptographyTransformerPrivate;
// A handle to a cryptographic transformer.
typedef SbCryptographyTransformerPrivate* SbCryptographyTransformer;
// Well-defined value for an invalid transformer.
#define kSbCryptographyInvalidTransformer ((SbCryptographyTransformer)NULL)
// Returns whether the given transformer handle is valid.
static SB_C_INLINE bool SbCryptographyIsTransformerValid(
SbCryptographyTransformer transformer) {
return transformer != kSbCryptographyInvalidTransformer;
}
// Creates an SbCryptographyTransformer with the given initialization
// data. It can then be used to transform a series of data blocks.
// Returns kSbCryptographyInvalidTransformer if the algorithm isn't
// supported, or if the parameters are not compatible with the
// algorithm.
//
// An SbCryptographyTransformer contains all state to start decrypting
// a sequence of cipher blocks according to the cipher block mode. It
// is not thread-safe, but implementations must allow different
// SbCryptographyTransformer instances to operate on different threads.
//
// All parameters must not be assumed to live longer than the call to
// this function. They must be copied by the implementation to be
// retained.
//
// This function determines success mainly based on whether the combination of
// |algorithm|, |direction|, |block_size_bits|, and |mode| is supported and
// whether all the sizes passed in are sufficient for the selected
// parameters. In particular, this function cannot verify that the key and IV
// used were correct for the ciphertext, were it to be used in the decode
// direction. The caller must make that verification.
//
// For example, to decrypt AES-128-CTR:
// SbCryptographyCreateTransformer(kSbCryptographyAlgorithmAes, 128,
// kSbCryptographyDirectionDecode,
// kSbCryptographyBlockCipherModeCtr,
// ...);
//
// |algorithm|: A string that represents the cipher algorithm.
// |block_size_bits|: The block size variant of the algorithm to use, in bits.
// |direction|: The direction in which to transform the data.
// |mode|: The block cipher mode to use.
// |initialization_vector|: The Initialization Vector (IV) to use. May be NULL
// for block cipher modes that don't use it, or don't set it at init time.
// |initialization_vector_size|: The size, in bytes, of the IV.
// |key|: The key to use for this transformation.
// |key_size|: The size, in bytes, of the key.
SB_EXPORT SbCryptographyTransformer
SbCryptographyCreateTransformer(const char* algorithm,
int block_size_bits,
SbCryptographyDirection direction,
SbCryptographyBlockCipherMode mode,
const void* initialization_vector,
int initialization_vector_size,
const void* key,
int key_size);
// Destroys the given |transformer| instance.
SB_EXPORT void SbCryptographyDestroyTransformer(
SbCryptographyTransformer transformer);
// Transforms one or more |block_size_bits|-sized blocks of |in_data|, with the
// given |transformer|, placing the result in |out_data|. Returns the number of
// bytes that were written to |out_data|, unless there was an error, in which
// case it will return a negative number.
//
// |transformer|: A transformer initialized with an algorithm, IV, cipherkey,
// and so on.
// |in_data|: The data to be transformed.
// |in_data_size|: The size of the data to be transformed, in bytes. Must be a
// multiple of the transformer's |block-size_bits|, or an error will be
// returned.
// |out_data|: A buffer where the transformed data should be placed. Must have
// at least capacity for |in_data_size| bytes. May point to the same memory as
// |in_data|.
SB_EXPORT int SbCryptographyTransform(
SbCryptographyTransformer transformer,
const void* in_data,
int in_data_size,
void* out_data);
// Sets the initialization vector (IV) for a transformer, replacing the
// internally-set IV. The block cipher mode algorithm will update the IV
// appropriately after every block, so this is not necessary unless the stream
// is discontiguous in some way. This happens with AES-GCM in TLS.
SB_EXPORT void SbCryptographySetInitializationVector(
SbCryptographyTransformer transformer,
const void* initialization_vector,
int initialization_vector_size);
// Sets additional authenticated data (AAD) for a transformer, for chaining
// modes that support it (GCM). Returns whether the data was successfully
// set. This can fail if the chaining mode doesn't support AAD, if the
// parameters are invalid, or if the internal state is invalid for setting AAD.
SB_EXPORT bool SbCryptographySetAuthenticatedData(
SbCryptographyTransformer transformer,
const void* data,
int data_size);
// Calculates the authenticator tag for a transformer and places up to
// |out_tag_size| bytes of it in |out_tag|. Returns whether it was able to get
// the tag, which mainly has to do with whether it is compatible with the
// current block cipher mode.
SB_EXPORT bool SbCryptographyGetTag(
SbCryptographyTransformer transformer,
void* out_tag,
int out_tag_size);
#ifdef __cplusplus
} // extern "C"
#endif
#endif // STARBOARD_CRYPTOGRAPHY_H_