| 1 | /* Copyright (c) (2019-2022) Apple Inc. All rights reserved. |
| 2 | * |
| 3 | * corecrypto is licensed under Apple Inc.’s Internal Use License Agreement (which |
| 4 | * is contained in the License.txt file distributed with corecrypto) and only to |
| 5 | * people who accept that license. IMPORTANT: Any license rights granted to you by |
| 6 | * Apple Inc. (if any) are limited to internal use within your organization only on |
| 7 | * devices and computers you own or control, for the sole purpose of verifying the |
| 8 | * security characteristics and correct functioning of the Apple Software. You may |
| 9 | * not, directly or indirectly, redistribute the Apple Software or any portions thereof. |
| 10 | */ |
| 11 | |
| 12 | #ifndef _CORECRYPTO_CCMODE_SIV_HMAC_H |
| 13 | #define _CORECRYPTO_CCMODE_SIV_HMAC_H |
| 14 | |
| 15 | #include <corecrypto/cc.h> |
| 16 | #include <corecrypto/ccmode.h> |
| 17 | #include <corecrypto/ccmode_impl.h> |
| 18 | #include <corecrypto/ccdigest.h> |
| 19 | #include <corecrypto/cchmac.h> |
| 20 | #include <corecrypto/ccsha2.h> |
| 21 | |
| 22 | #define ccsiv_hmac_ctx_decl(_size_, _name_) cc_ctx_decl_vla(ccsiv_hmac_ctx, _size_, _name_) |
| 23 | #define ccsiv_hmac_ctx_clear(_size_, _name_) cc_clear(_size_, _name_) |
| 24 | |
| 25 | /*! |
| 26 | @function ccsiv_hmac_context_size |
| 27 | @abstract Return size of context |
| 28 | |
| 29 | @param mode Descriptor for the mode |
| 30 | */ |
| 31 | size_t ccsiv_hmac_context_size(const struct ccmode_siv_hmac *mode); |
| 32 | |
| 33 | /*! |
| 34 | @function ccsiv_hmac_block_size |
| 35 | @abstract Return size of context |
| 36 | |
| 37 | @param mode Descriptor for the mode |
| 38 | */ |
| 39 | size_t ccsiv_hmac_block_size(const struct ccmode_siv_hmac *mode); |
| 40 | |
| 41 | /*! |
| 42 | @function ccsiv_hmac_ciphertext_size |
| 43 | @abstract Return size of Ciphertext (which is the ciphertext and corresponding tag) given the mode and plaintext length |
| 44 | |
| 45 | @param ctx Current siv_hmac context that has been previously initialized |
| 46 | @param plaintext_size Size of the plaintext |
| 47 | |
| 48 | @discussion returns the length of the aead ciphertext that the context will generate which includes both the encrypted plaintext |
| 49 | and tag. |
| 50 | */ |
| 51 | size_t ccsiv_hmac_ciphertext_size(ccsiv_hmac_ctx *ctx, size_t plaintext_size); |
| 52 | |
| 53 | /*! |
| 54 | @function ccsiv_hmac_plaintext_size |
| 55 | @abstract Return size of plaintext given a ciphertext length and mode. |
| 56 | |
| 57 | @param ctx Current siv_hmac context that has been previously initialized |
| 58 | @param ciphertext_size Size of the ciphertext (which includes the tag) |
| 59 | |
| 60 | @discussion returns the length of the plaintext which results from the decryption of a ciphertext of the corresponding size (here ciphertext size includes the tag). |
| 61 | */ |
| 62 | size_t ccsiv_hmac_plaintext_size(ccsiv_hmac_ctx *ctx, size_t ciphertext_size); |
| 63 | |
| 64 | /*! |
| 65 | @function ccsiv_hmac_init |
| 66 | @abstract Initialize a context for siv_hmac with an associated mode, given key and specifying output tag size. |
| 67 | |
| 68 | @param mode Descriptor for the mode |
| 69 | @param ctx Alocated context to be intialized |
| 70 | @param key_byte_len Length of the key: Supported key sizes are 32, 48, 64 bytes |
| 71 | @param key key for siv_hmac |
| 72 | @param tag_size The length of the output tag requested. Must be at least 20 bytes, and can be as large as the |
| 73 | associated digest's output |
| 74 | |
| 75 | @discussion In order to compute HMAC_SIV_Enc_k(a1,...,am, n, x) where ai is the ith piece of associated data, n is a nonce and x |
| 76 | is a plaintext, we first initialize the context with this call, and then use it to call ccsiv_hmac_aad for each ai, followed by |
| 77 | ccsiv_hmac_set_nonce for nonce n, and finally a call to ccsiv_hmac_crypt for the plaintext x. Note the order of the calls to aad, |
| 78 | nonce and then crypt is critical. If a second encryption is needed then a call to ccsiv_hmac_reset can be used to reset state, |
| 79 | and begin again. |
| 80 | */ |
| 81 | int ccsiv_hmac_init(const struct ccmode_siv_hmac *mode, ccsiv_hmac_ctx *ctx, size_t key_byte_len, const uint8_t *key, size_t tag_size); |
| 82 | |
| 83 | /*! |
| 84 | @function ccsiv_hmac_aad |
| 85 | @abstract Add the next piece of associated data to the hmac_siv's computation of the tag. Note this call is optional and no |
| 86 | associated data needs to be provided. Multiple pieces of associated data can be provided by multiple calls to this |
| 87 | function. Each input is regarded as a separate piece of associated data, and the mac is NOT simply computed on the |
| 88 | concatenation of all of the associated data inputs. Therefore on decryption the same inputs must be provided in |
| 89 | the same order. |
| 90 | |
| 91 | @param mode Descriptor for the mode |
| 92 | @param ctx Intialized ctx |
| 93 | @param nbytes Length of the current associated data being added |
| 94 | @param in Associated data to be authenticated. |
| 95 | |
| 96 | @discussion Adds the associated data given by in to the computation of the tag in the associated data. |
| 97 | */ |
| 98 | int ccsiv_hmac_aad(const struct ccmode_siv_hmac *mode, ccsiv_hmac_ctx *ctx, size_t nbytes, const uint8_t *in); |
| 99 | |
| 100 | /*! |
| 101 | @function ccsiv_hmac_nonce |
| 102 | @abstract Add the nonce to the hmac_siv's computation of the the tag. Changes the internal state of the context |
| 103 | so that after the call only a crypt or reset call is permitted. |
| 104 | @param mode Descriptor for the mode |
| 105 | @param ctx Intialized ctx |
| 106 | @param nbytes Length of the current nonce data being added |
| 107 | @param in Nonce data to be authenticated. |
| 108 | |
| 109 | @discussion The nonce is a special form of authenticated data. If provided ( a call to hmac_nonce is optional) it allows |
| 110 | randomization of the ciphertext (preventing deterministic encryption). While the length of the nonce is not limited, the |
| 111 | amount of entropy that can be provided is limited by the number of bits in the block of the associated block-cipher in mode. |
| 112 | */ |
| 113 | int ccsiv_hmac_set_nonce(const struct ccmode_siv_hmac *mode, ccsiv_hmac_ctx *ctx, size_t nbytes, const uint8_t *in); |
| 114 | |
| 115 | /*! |
| 116 | @function ccsiv_hmac_crypt |
| 117 | @abstract Depending on whether mode has been setup to encrypt or decrypt, this function |
| 118 | 1) Encrypts the plaintext given as input in, and provides the ciphertext (which is a concatenation of the tag |
| 119 | followed by the encrypted plaintext) as output out. 2) Decrypts plaintext using the input ciphertext at in (which again is the |
| 120 | tag, followed by encrypted plaintext), and then verifies that the computer tag and provided tags match. |
| 121 | @param mode Descriptor for the mode |
| 122 | @param ctx Intialized ctx |
| 123 | @param nbytes Case 1) Length of the current plaintext |
| 124 | Case 2) Length of the current ciphertext (tag length + plaintext length) |
| 125 | @param in Case 1) Plaintext |
| 126 | Case 2) Ciphertext |
| 127 | @discussion This function is only called once. If one wishes to compute another (en)/(de)cryption, one resets the state with |
| 128 | ccsiv_hmac_reset, and then begins the process again. There is no way to stream large plaintext/ciphertext inputs into the |
| 129 | function. |
| 130 | @param out Case1) Tag+ Ciphertext (buffer should be already allocated and of length tag + plaintext length) |
| 131 | Case 2) Plaintext (buffer should be already allocated and of length ciphertext - tag length |
| 132 | |
| 133 | In the case of a decryption, if there is a failure in verifying the computed tag against the provided tag (embedded int he ciphertext), then a decryption/verification |
| 134 | failure is returned, and any internally computed plaintexts and tags are zeroed out. |
| 135 | Lastly the contexts internal state is reset, so that a new decryption/encryption can be commenced. |
| 136 | */ |
| 137 | int ccsiv_hmac_crypt(const struct ccmode_siv_hmac *mode, ccsiv_hmac_ctx *ctx, size_t nbytes, const uint8_t *in, uint8_t *out); |
| 138 | |
| 139 | /*! |
| 140 | @function ccsiv_hmac_reset |
| 141 | @abstract Resets the state of the siv_hamc ctx, maintaining the key, but preparing the |
| 142 | ctx to preform a new Associated Data Authenticated (En)/(De)cryption. |
| 143 | @param mode Descriptor for the mode |
| 144 | @param ctx Intialized ctx |
| 145 | */ |
| 146 | int ccsiv_hmac_reset(const struct ccmode_siv_hmac *mode, ccsiv_hmac_ctx *ctx); |
| 147 | |
| 148 | /*! |
| 149 | @function ccsiv_hmac_one_shot |
| 150 | @abstract A simplified but more constrained way of performing an AEAD SIV HMAC (en)/(de)cryption. It is limited because only |
| 151 | one piece of associated data may be provided. |
| 152 | @param mode Descriptor for the mode |
| 153 | @param key_len Length of the key: Supported key sizes are 32, 48, 64 bytes |
| 154 | @param key key for siv_hmac |
| 155 | @param tag_length The length of the tag to produce or accept as input. Must be at least 20 |
| 156 | bytes, and can be as large as the hmac's digest's output |
| 157 | @param nonce_nbytes Length of the current nonce data being added |
| 158 | @param nonce Nonce data to be authenticated. |
| 159 | @param adata_nbytes Length of the associated data. |
| 160 | @param adata Associated data to be authenticated. |
| 161 | @param in_nbytes Length of either the plaintext (for encryption) or ciphertext (for decryption) |
| 162 | @param in plaintext or ciphertext. Note that the ciphertext includes a tag of length tag_length prepended to it. |
| 163 | @param out Buffer to hold ciphertext/plaintext. (Note Ciphertext is of size plaintext length + tag_length and plaintext is of length ciphertext - tag_length.) |
| 164 | */ |
| 165 | |
| 166 | // One shot AEAD with only one input for adata, and a nonce. |
| 167 | int ccsiv_hmac_one_shot(const struct ccmode_siv_hmac *mode, |
| 168 | size_t key_len, |
| 169 | const uint8_t *key, |
| 170 | size_t tag_length, |
| 171 | unsigned nonce_nbytes, |
| 172 | const uint8_t *nonce, |
| 173 | unsigned adata_nbytes, |
| 174 | const uint8_t *adata, |
| 175 | size_t in_nbytes, |
| 176 | const uint8_t *in, |
| 177 | uint8_t *out); |
| 178 | |
| 179 | #endif /* _CORECRYPTO_CCMODE_SIV_HMAC_H */ |
| 180 | |