]>
Commit | Line | Data |
---|---|---|
f427ee49 A |
1 | /* Copyright (c) (2019) 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 | */ | |
cb323159 A |
11 | // Created by Apple on 12/10/18. |
12 | // | |
13 | ||
14 | #ifndef ccmode_siv_hmac_h | |
15 | #define ccmode_siv_hmac_h | |
16 | ||
17 | #include <corecrypto/cc.h> | |
18 | #include <corecrypto/ccmode.h> | |
19 | #include <corecrypto/ccmode_impl.h> | |
20 | #include <corecrypto/ccdigest.h> | |
21 | #include <corecrypto/cchmac.h> | |
22 | #include <corecrypto/ccsha2.h> | |
23 | ||
24 | /* This provides an implementation of SIV using AES CTR mode with HMAC as the MAC, | |
25 | allowing for a tagging mechanism with collision resistant tags. This is a modification of the | |
26 | standard specified in https://tools.ietf.org/html/rfc5297 | |
27 | also in http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/siv/siv.pdf | |
28 | Counter Mode where IV is based on HMAC. | |
29 | */ | |
30 | ||
31 | cc_aligned_struct(16) ccsiv_hmac_ctx; | |
32 | ||
33 | struct ccmode_siv_hmac { | |
34 | size_t size; /* first argument to ccsiv_hmac_ctx_decl(). */ | |
35 | size_t block_size; | |
36 | ||
37 | int (*init)(const struct ccmode_siv_hmac *sivhmac, | |
38 | ccsiv_hmac_ctx *ctx, | |
39 | size_t key_len, | |
40 | const uint8_t *key, | |
41 | const size_t tag_size); | |
42 | int (*set_nonce)(ccsiv_hmac_ctx *ctx, size_t nbytes, const uint8_t *in); | |
43 | int (*auth)(ccsiv_hmac_ctx *ctx, size_t nbytes, const uint8_t *in); | |
44 | int (*crypt)(ccsiv_hmac_ctx *ctx, size_t nbytes, const uint8_t *in, uint8_t *out); | |
45 | int (*reset)(ccsiv_hmac_ctx *ctx); | |
46 | const struct ccdigest_info *hmac_digest; // Digest to be used in HMAC; | |
47 | const struct ccmode_ctr *ctr; | |
48 | }; | |
49 | ||
50 | #define ccsiv_hmac_ctx_decl(_size_, _name_) cc_ctx_decl(ccsiv_hmac_ctx, _size_, _name_) | |
51 | #define ccsiv_hmac_ctx_clear(_size_, _name_) cc_clear(_size_, _name_) | |
52 | ||
53 | /*! | |
54 | @function ccsiv_hmac_context_size | |
55 | @abstract Return size of context | |
56 | ||
57 | @param mode Descriptor for the mode | |
58 | */ | |
59 | CC_INLINE size_t ccsiv_hmac_context_size(const struct ccmode_siv_hmac *mode) | |
60 | { | |
61 | return mode->size; | |
62 | } | |
63 | ||
64 | /*! | |
65 | @function ccsiv_hmac_block_size | |
66 | @abstract Return size of context | |
67 | ||
68 | @param mode Descriptor for the mode | |
69 | */ | |
70 | CC_INLINE size_t ccsiv_hmac_block_size(const struct ccmode_siv_hmac *mode) | |
71 | { | |
72 | return mode->block_size; | |
73 | } | |
74 | ||
75 | /*! | |
76 | @function ccsiv_hmac_ciphertext_size | |
77 | @abstract Return size of Ciphertext (which is the ciphertext and corresponding tag) given the mode and plaintext length | |
78 | ||
79 | @param ctx Current siv_hmac context that has been previously initialized | |
80 | @param plaintext_size Size of the plaintext | |
81 | ||
82 | @discussion returns the length of the aead ciphertext that the context will generate which includes both the encrypted plaintext | |
83 | and tag. | |
84 | */ | |
85 | size_t ccsiv_hmac_ciphertext_size(ccsiv_hmac_ctx *ctx, size_t plaintext_size); | |
86 | ||
87 | /*! | |
88 | @function ccsiv_hmac_plaintext_size | |
89 | @abstract Return size of plaintext given a ciphertext length and mode. | |
90 | ||
91 | @param ctx Current siv_hmac context that has been previously initialized | |
f427ee49 | 92 | @param ciphertext_size Size of the ciphertext (which includes the tag) |
cb323159 | 93 | |
f427ee49 | 94 | @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). |
cb323159 A |
95 | */ |
96 | size_t ccsiv_hmac_plaintext_size(ccsiv_hmac_ctx *ctx, size_t ciphertext_size); | |
97 | ||
98 | /*! | |
99 | @function ccsiv_hmac_init | |
100 | @abstract Initialize a context for siv_hmac with an associated mode, given key and specifying output tag size. | |
101 | ||
102 | @param mode Descriptor for the mode | |
103 | @param ctx Alocated context to be intialized | |
104 | @param key_byte_len Length of the key: Supported key sizes are 32, 48, 64 bytes | |
105 | @param key key for siv_hmac | |
106 | @param tag_size The length of the output tag requested. Must be at least 20 bytes, and can be as larged as the | |
107 | associated digest's output | |
108 | ||
109 | @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 | |
110 | 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 | |
111 | 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, | |
112 | 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, | |
113 | and begin again. | |
114 | */ | |
115 | 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); | |
116 | ||
117 | /*! | |
118 | @function ccsiv_hmac_aad | |
119 | @abstract Add the next piece of associated data to the hmac_siv's computation of the tag. Note this call is optional and no | |
120 | associated data needs to be provided. Multiple pieces of associated data can be provided by multiple calls to this | |
121 | function. Each input is regarded as a seperate piece of associated data, and the mac is NOT simply computed on the | |
122 | concatenation of all of the associated data inputs. Therefore on decryption the same inputs must be prodivded and in | |
123 | the same order. | |
124 | ||
125 | @param mode Descriptor for the mode | |
126 | @param ctx Intialized ctx | |
127 | @param nbytes Length of the current associated data being added | |
128 | @param in Associated data to be authenticated. | |
129 | ||
130 | @discussion Adds the associated data given by in to the computation of the tag in the associated data. | |
131 | */ | |
132 | int ccsiv_hmac_aad(const struct ccmode_siv_hmac *mode, ccsiv_hmac_ctx *ctx, size_t nbytes, const uint8_t *in); | |
133 | ||
134 | /*! | |
135 | @function ccsiv_hmac_nonce | |
136 | @abstract Add the nonce to the hmac_siv's computation of the the tag. Changes the internal state of the context | |
137 | so that after the call only a crypt or reset call is permitted. | |
138 | @param mode Descriptor for the mode | |
139 | @param ctx Intialized ctx | |
140 | @param nbytes Length of the current nonce data being added | |
141 | @param in Nonce data to be authenticated. | |
142 | ||
143 | @discussion The nonce is a special form of authenticated data. If provided ( a call to hmac_nonce is optional) it allows | |
144 | randomization of the of ciphertext (preventing deterministic encryption). While the length of the nonce is not limimited, the | |
145 | amount of entropy that can be provided is limited by the number of bits in the block of the associated block-cipher in mode. | |
146 | */ | |
147 | int ccsiv_hmac_set_nonce(const struct ccmode_siv_hmac *mode, ccsiv_hmac_ctx *ctx, size_t nbytes, const uint8_t *in); | |
148 | ||
149 | /*! | |
150 | @function ccsiv_hmac_crypt | |
151 | @abstract Depending on whether mode has been setup to encrypt or decrypt, this function | |
152 | 1) Encrypts the plaintext given as input in, and provides the ciphertext (which is a concatenation of the tag | |
153 | followed by the encrypted plaintext) as output out. 2) Decrypts plaintext using the input ciphertext at in (which again is the | |
154 | tag, followed by encrypted plaintext), and then verifies that the computer tag and provided tags match. | |
155 | @param mode Descriptor for the mode | |
156 | @param ctx Intialized ctx | |
157 | @param nbytes Case 1) Length of the current plaintext | |
158 | Case 2) Length of the current ciphertext (tag length + plaintext length) | |
159 | @param in Case 1) Plaintext | |
160 | Case 2) Ciphertext | |
161 | @discussion This function is only called once. If one wishes to compute another (en)/(de)cryption, one resets the state with | |
162 | ccsiv_hmac_reset, and then begins the process again. There is no way to stream large plaintext/ciphertext inputs into the | |
163 | function. | |
f427ee49 A |
164 | @param out Case1) Tag+ Ciphertext (buffer should be already allocated and of length tag + plaintext length) |
165 | Case 2) Plaintext (buffer should be already allocated and of length ciphertext - tag length | |
166 | ||
cb323159 A |
167 | 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 |
168 | failure is returned, and any internally computed plaintexts and tags are zeroed out. | |
169 | Lastly the contexts internal state is reset, so that a new decryption/encryption can be commenced. | |
170 | */ | |
171 | int ccsiv_hmac_crypt(const struct ccmode_siv_hmac *mode, ccsiv_hmac_ctx *ctx, size_t nbytes, const uint8_t *in, uint8_t *out); | |
172 | ||
173 | /*! | |
174 | @function ccsiv_hmac_reset | |
175 | @abstract Resets the state of the siv_hamc ctx, maintaing the key, but preparing the | |
176 | ctx to preform a new Associated Data Authenticated (En)/(De)cryption. | |
177 | @param mode Descriptor for the mode | |
178 | @param ctx Intialized ctx | |
179 | */ | |
180 | int ccsiv_hmac_reset(const struct ccmode_siv_hmac *mode, ccsiv_hmac_ctx *ctx); | |
181 | ||
182 | /*! | |
183 | @function ccsiv_hmac_one_shot | |
184 | @abstract A simplified but more constrained way of performing an AEAD SIV HMAC (en)/(de)cryption. It is limited because only | |
185 | one piece of associated data may be provided. | |
186 | @param mode Descriptor for the mode | |
187 | @param key_len Length of the key: Supported key sizes are 32, 48, 64 bytes | |
188 | @param key key for siv_hmac | |
189 | @param tag_length The length of the tag to produce or accept as input. Must be at least 20 | |
190 | bytes, and can be as large as the hmac's digest's output | |
191 | @param nonce_nbytes Length of the current nonce data being added | |
192 | @param nonce Nonce data to be authenticated. | |
193 | @param adata_nbytes Length of the associated data. | |
194 | @param adata Associated data to be authenticated. | |
195 | @param in_nbytes Length of either the plaintext (for encryption) or ciphertext (for decryption) | |
f427ee49 A |
196 | @param in plaintext or ciphertext. Note that the ciphertext includes a tag of length tag_length prepended to it. |
197 | @param out Buffer to hold ciphertext/plaintext. (Note Ciphertext is of size plaintext length + tag_length and plaintext is of length ciphertext - tag_length.) | |
cb323159 A |
198 | */ |
199 | ||
200 | // One shot AEAD with only one input for adata, and a nonce. | |
201 | int ccsiv_hmac_one_shot(const struct ccmode_siv_hmac *mode, | |
202 | size_t key_len, | |
203 | const uint8_t *key, | |
204 | size_t tag_length, | |
205 | unsigned nonce_nbytes, | |
206 | const uint8_t *nonce, | |
207 | unsigned adata_nbytes, | |
208 | const uint8_t *adata, | |
209 | size_t in_nbytes, | |
210 | const uint8_t *in, | |
211 | uint8_t *out); | |
212 | ||
213 | #endif /* ccmode_siv_hmac_h */ |