1 // Copyright 2017 The Fuchsia Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #pragma once 6 7 #include <stddef.h> 8 #include <stdint.h> 9 10 #include <crypto/bytes.h> 11 #include <crypto/secret.h> 12 #include <crypto/cipher.h> 13 #include <fbl/macros.h> 14 #include <zircon/types.h> 15 16 // |crypto::AEAD| is an authenticated encryption and decryption cipher. It differs from |Cipher| in 17 // that it incurs additional overhead to store its authentication tag, but can verify data integrity 18 // as a result. The ciphertext produced by an AEAD is the same length as its plaintext, excluding 19 // the IV and tag. A 64 bit nonce is used to seal plain texts, meaning a given key and IV can be 20 // used for at most 2^64 - 1 operations. 21 namespace crypto { 22 23 class AEAD final { 24 public: 25 // Algorithm enumerates the supported secret key ciphers. 26 enum Algorithm { 27 kUninitialized = 0, 28 kAES128_GCM, 29 kAES128_GCM_SIV, 30 }; 31 32 AEAD(); 33 ~AEAD(); 34 35 // Gets the number of bytes needed for the symmetric key used by the given |aead|. 36 static zx_status_t GetKeyLen(Algorithm aead, size_t* out); 37 38 // Gets the number of bytes needed for the initialization vector (IV) used by the given 39 // |aead|. 40 static zx_status_t GetIVLen(Algorithm aead, size_t* out); 41 42 // Gets the length of an authentication tag created by the given |aead|. 43 static zx_status_t GetTagLen(Algorithm aead, size_t* out); 44 45 // Sets up the AEAD to use the algorithm indicated by |aead| to encrypt data using the given 46 // |key| and |iv|. InitSeal(Algorithm aead,const Secret & key,const Bytes & iv)47 zx_status_t InitSeal(Algorithm aead, const Secret& key, const Bytes& iv) { 48 return Init(aead, key, iv, Cipher::kEncrypt); 49 } 50 51 // Sets up the AEAD to use the algorithm indicated by |aead| to decrypt data using the given 52 // |key| and |iv|. InitOpen(Algorithm aead,const Secret & key,const Bytes & iv)53 zx_status_t InitOpen(Algorithm aead, const Secret& key, const Bytes& iv) { 54 return Init(aead, key, iv, Cipher::kDecrypt); 55 } 56 57 // Encrypts data from |ptext| to |ctext|, based on the parameters set in |InitSeal|. Saves the 58 // |iv| used; |iv| will be resized and filled automatically. The AEAD tag is stored at the end 59 // of |ctext| This method will fail if called 2^64 or more times with the same key and IV. The 60 // second variant includes additional authenticated data in the tag calculation. Seal(const Bytes & ptext,uint64_t * out_nonce,Bytes * out_ctext)61 zx_status_t Seal(const Bytes& ptext, uint64_t* out_nonce, Bytes* out_ctext) { 62 return Seal(ptext, nullptr, 0, out_nonce, out_ctext); 63 } Seal(const Bytes & ptext,const Bytes & aad,uint64_t * out_nonce,Bytes * out_ctext)64 zx_status_t Seal(const Bytes& ptext, const Bytes& aad, uint64_t* out_nonce, Bytes* out_ctext) { 65 return Seal(ptext, aad.get(), aad.len(), out_nonce, out_ctext); 66 } 67 68 // Decrypts data from |ctext| to |ptext|, based on the parameters set in |InitOpen|. 69 // Decryption can only succeed if the |iv| matches those produced by |Seal| and the AEAD tag is 70 // included in |ctext|. The second variant includes additional authenticated data in the tag 71 // calculation. Open(uint64_t nonce,const Bytes & ctext,Bytes * out_ptext)72 zx_status_t Open(uint64_t nonce, const Bytes& ctext, Bytes* out_ptext) { 73 return Open(nonce, ctext, nullptr, 0, out_ptext); 74 } Open(uint64_t nonce,const Bytes & ctext,const Bytes & aad,Bytes * out_ptext)75 zx_status_t Open(uint64_t nonce, const Bytes& ctext, const Bytes& aad, Bytes* out_ptext) { 76 return Open(nonce, ctext, aad.get(), aad.len(), out_ptext); 77 } 78 79 // Clears all state from this instance. 80 void Reset(); 81 82 private: 83 DISALLOW_COPY_ASSIGN_AND_MOVE(AEAD); 84 85 // Sets up the aead to encrypt or decrypt data using the given |key| based on the 86 // given |direction|. 87 zx_status_t Init(Algorithm aead, const Secret& key, const Bytes& iv, 88 Cipher::Direction direction); 89 zx_status_t Seal(const Bytes& ptext, const uint8_t* aad, size_t aad_len, uint64_t* out_nonce, 90 Bytes* out_ctext); 91 zx_status_t Open(uint64_t nonce, const Bytes& ctext, const uint8_t* aad, size_t aad_len, 92 Bytes* out_ptext); 93 94 // Opaque crypto implementation context. 95 struct Context; 96 97 // Opaque pointer to the crypto implementation context. 98 fbl::unique_ptr<Context> ctx_; 99 // Indicates whether configured to encrypt or decrypt. 100 Cipher::Direction direction_; 101 // Buffer holding initial vector. The IV is expanded to be |uint64_t|-aligned. 102 fbl::unique_ptr<uint64_t[]> iv_; 103 // Original value of |iv_[0]|. |Seal| will fail if |iv_[0]| wraps around to this value. 104 uint64_t iv0_; 105 // Size of the actual IV. 106 size_t iv_len_; 107 // Length of authentication tag. 108 size_t tag_len_; 109 }; 110 } // namespace crypto 111