| 1 | /* Copyright (c) (2010-2012,2015-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_IMPL_H_ |
| 13 | #define _CORECRYPTO_CCMODE_IMPL_H_ |
| 14 | #include <corecrypto/cc.h> |
| 15 | |
| 16 | #define CCMODE_MAX_BLOCK_SIZE 16 |
| 17 | |
| 18 | /* ECB mode. */ |
| 19 | cc_aligned_struct(16) ccecb_ctx; |
| 20 | |
| 21 | /* Actual symmetric algorithm implementation should provide you one of these. */ |
| 22 | struct ccmode_ecb { |
| 23 | size_t size; /* first argument to ccecb_ctx_decl(). */ |
| 24 | size_t block_size; |
| 25 | int (*CC_SPTR(ccmode_ecb, init))(const struct ccmode_ecb *ecb, ccecb_ctx *ctx, size_t key_nbytes, const void *key); |
| 26 | int (*CC_SPTR(ccmode_ecb, ecb))(const ccecb_ctx *ctx, size_t nblocks, const void *in, void *out); |
| 27 | void (*CC_SPTR(ccmode_ecb, roundkey))(const ccecb_ctx *ctx, unsigned r, void *key); |
| 28 | cc_impl_t impl; |
| 29 | }; |
| 30 | |
| 31 | /*! |
| 32 | * @brief corecrypto symmetrical encryption and decryption modes |
| 33 | * |
| 34 | * corecrypto supports 6 stateless en(de)cryption modes and 2 stateful authenticated en(de)cryption modes |
| 35 | * stateless modes CBC, CFB, CFB8, CTR, OFB, XTS: They provide 3 interface functions that do not return errors codes |
| 36 | * 1- ccmod_xxx_init() |
| 37 | * 2- ccmod_xxx_decrypt() |
| 38 | * 3- ccmod_xxx_encrypt() |
| 39 | * |
| 40 | * stateful modes CCM and GCM: They provide 7 interface functions that return error codes if a function is called out of state |
| 41 | * 1- ccmod_xxx_init() |
| 42 | * 2- ccmod_xxx_setiv() |
| 43 | * 3- ccmod_xxx_aad() |
| 44 | * 4- ccmod_xxx_decrypt() |
| 45 | * 5- ccmod_xxx_encrypt() |
| 46 | * 6- ccmod_xxx_finalize() |
| 47 | * 7- ccmod_xxx_reset() |
| 48 | * |
| 49 | * the correct call sequences are: |
| 50 | * |
| 51 | * calls to 1, 2 and 6 arerequired |
| 52 | * 2 and 3 can be called as mant times as needed |
| 53 | * calls to 3, 4, 5 can be skipped |
| 54 | * |
| 55 | * 1, 2*n, 3*n, 4|5, 6 |
| 56 | * 1, 2*n, , 4|5, 6 |
| 57 | * 1, 2*n, , , 6 |
| 58 | * 1, 2*n, 3*n, , 6 |
| 59 | */ |
| 60 | |
| 61 | // 1- CBC mode, stateless |
| 62 | cc_aligned_struct(16) cccbc_ctx; |
| 63 | cc_aligned_struct(16) cccbc_iv; |
| 64 | |
| 65 | // This value was derived empirically. It may need to be updated to |
| 66 | // match changes in implementation. |
| 67 | #define CCCBC_MAX_CTX_SIZE 512 |
| 68 | |
| 69 | struct ccmode_cbc { |
| 70 | size_t size; /* first argument to cccbc_ctx_decl(). */ |
| 71 | size_t block_size; |
| 72 | int (*CC_SPTR(ccmode_cbc, init))(const struct ccmode_cbc *cbc, cccbc_ctx *ctx, size_t key_len, const void *key); |
| 73 | /* cbc encrypt or decrypt nblocks from in to out, iv will be used and updated. */ |
| 74 | int (*CC_SPTR(ccmode_cbc, cbc))(const cccbc_ctx *ctx, cccbc_iv *iv, size_t nblocks, const void *in, void *out); |
| 75 | const void *custom; |
| 76 | }; |
| 77 | |
| 78 | // 2- CFB mode, stateless |
| 79 | cc_aligned_struct(16) cccfb_ctx; |
| 80 | |
| 81 | struct ccmode_cfb { |
| 82 | size_t size; /* first argument to cccfb_ctx_decl(). */ |
| 83 | size_t block_size; |
| 84 | int (*CC_SPTR(ccmode_cfb, |
| 85 | init))(const struct ccmode_cfb *cfb, cccfb_ctx *ctx, size_t key_len, const void *key, const void *iv); |
| 86 | int (*CC_SPTR(ccmode_cfb, cfb))(cccfb_ctx *ctx, size_t nbytes, const void *in, void *out); |
| 87 | const void *custom; |
| 88 | }; |
| 89 | |
| 90 | // 3- CFB8 mode, stateless |
| 91 | cc_aligned_struct(16) cccfb8_ctx; |
| 92 | |
| 93 | struct ccmode_cfb8 { |
| 94 | size_t size; /* first argument to cccfb8_ctx_decl(). */ |
| 95 | size_t block_size; |
| 96 | int (*CC_SPTR(ccmode_cfb8, |
| 97 | init))(const struct ccmode_cfb8 *cfb8, cccfb8_ctx *ctx, size_t key_len, const void *key, const void *iv); |
| 98 | int (*CC_SPTR(ccmode_cfb8, cfb8))(cccfb8_ctx *ctx, size_t nbytes, const void *in, void *out); |
| 99 | const void *custom; |
| 100 | }; |
| 101 | |
| 102 | // 4- CTR mode, stateless |
| 103 | cc_aligned_struct(16) ccctr_ctx; |
| 104 | |
| 105 | struct ccmode_ctr { |
| 106 | size_t size; /* first argument to ccctr_ctx_decl(). */ |
| 107 | size_t block_size; /* for historical reasons, this is set to 1 */ |
| 108 | size_t ecb_block_size; /* the actual block size of the underlying cipher */ |
| 109 | int (*CC_SPTR(ccmode_ctr, |
| 110 | init))(const struct ccmode_ctr *mode, ccctr_ctx *ctx, size_t key_len, const void *key, const void *iv); |
| 111 | int (*CC_SPTR(ccmode_ctr, setctr))(const struct ccmode_ctr *mode, ccctr_ctx *ctx, const void *ctr); |
| 112 | int (*CC_SPTR(ccmode_ctr, ctr))(ccctr_ctx *ctx, size_t nbytes, const void *in, void *out); |
| 113 | const void *custom; |
| 114 | }; |
| 115 | |
| 116 | // 5- OFB mode, stateless |
| 117 | cc_aligned_struct(16) ccofb_ctx; |
| 118 | |
| 119 | struct ccmode_ofb { |
| 120 | size_t size; /* first argument to ccofb_ctx_decl(). */ |
| 121 | size_t block_size; |
| 122 | int (*CC_SPTR(ccmode_ofb, |
| 123 | init))(const struct ccmode_ofb *ofb, ccofb_ctx *ctx, size_t key_len, const void *key, const void *iv); |
| 124 | int (*CC_SPTR(ccmode_ofb, ofb))(ccofb_ctx *ctx, size_t nbytes, const void *in, void *out); |
| 125 | const void *custom; |
| 126 | }; |
| 127 | |
| 128 | // 6- XTS mode, stateless |
| 129 | cc_aligned_struct(16) ccxts_ctx; |
| 130 | cc_aligned_struct(16) ccxts_tweak; |
| 131 | |
| 132 | struct ccmode_xts { |
| 133 | size_t size; /* first argument to ccxts_ctx_decl(). Size of the ctx data structure */ |
| 134 | size_t tweak_size; /* first argument to ccxts_tweak_decl(). Size of the tweak structure, not the expected tweak size */ |
| 135 | size_t block_size; |
| 136 | |
| 137 | /* Create a xts key from a xts mode object. |
| 138 | key must point to at least 'size' bytes of free storage. |
| 139 | tweak_key must point to at least 'tweak_size' bytes of free storage. |
| 140 | key and tweak_key must differ. |
| 141 | Returns nonzero on failure. |
| 142 | */ |
| 143 | int (*CC_SPTR(ccmode_xts, init))(const struct ccmode_xts *xts, |
| 144 | ccxts_ctx *ctx, |
| 145 | size_t key_nbytes, |
| 146 | const void *data_key, |
| 147 | const void *tweak_key); |
| 148 | |
| 149 | void (*CC_SPTR(ccmode_xts, key_sched))(const struct ccmode_xts *xts, |
| 150 | ccxts_ctx *ctx, |
| 151 | size_t key_nbytes, |
| 152 | const void *data_key, |
| 153 | const void *tweak_key); |
| 154 | |
| 155 | /* Set the tweak (sector number), the block within the sector zero. */ |
| 156 | int (*CC_SPTR(ccmode_xts, set_tweak))(const ccxts_ctx *ctx, ccxts_tweak *tweak, const void *iv); |
| 157 | |
| 158 | /* Encrypt blocks for a sector, clients must call set_tweak before calling |
| 159 | this function. Return a pointer to the tweak buffer */ |
| 160 | void *(*CC_SPTR(ccmode_xts, xts))(const ccxts_ctx *ctx, ccxts_tweak *tweak, size_t nblocks, const void *in, void *out); |
| 161 | |
| 162 | const void *custom; |
| 163 | const void *custom1; |
| 164 | cc_impl_t impl; |
| 165 | }; |
| 166 | |
| 167 | // 7- GCM mode, statful |
| 168 | cc_aligned_struct(16) ccgcm_ctx; |
| 169 | #define CCMODE_GCM_DECRYPTOR 78647 |
| 170 | #define CCMODE_GCM_ENCRYPTOR 4073947 |
| 171 | |
| 172 | struct ccmode_gcm { |
| 173 | size_t size; /* first argument to ccgcm_ctx_decl(). */ |
| 174 | int encdec; // is it encrypt or decrypt object |
| 175 | size_t block_size; |
| 176 | int (*CC_SPTR(ccmode_gcm, init))(const struct ccmode_gcm *gcm, ccgcm_ctx *ctx, size_t key_nbytes, const void *key); |
| 177 | int (*CC_SPTR(ccmode_gcm, set_iv))(ccgcm_ctx *ctx, size_t iv_nbytes, const void *iv); |
| 178 | int (*CC_SPTR(ccmode_gcm, gmac))(ccgcm_ctx *ctx, size_t nbytes, const void *in); // could just be gcm with NULL out |
| 179 | int (*CC_SPTR(ccmode_gcm, gcm))(ccgcm_ctx *ctx, size_t nbytes, const void *in, void *out); |
| 180 | int (*CC_SPTR(ccmode_gcm, finalize))(ccgcm_ctx *key, size_t tag_nbytes, void *tag); |
| 181 | int (*CC_SPTR(ccmode_gcm, reset))(ccgcm_ctx *ctx); |
| 182 | const void *custom; |
| 183 | }; |
| 184 | |
| 185 | // 8- CCM mode, stateful |
| 186 | cc_aligned_struct(16) ccccm_ctx; |
| 187 | cc_aligned_struct(16) ccccm_nonce; |
| 188 | |
| 189 | struct ccmode_ccm { |
| 190 | size_t size; /* first argument to ccccm_ctx_decl(). */ |
| 191 | size_t nonce_size; /* first argument to ccccm_nonce_decl(). */ |
| 192 | size_t block_size; |
| 193 | int (*CC_SPTR(ccmode_ccm, init))(const struct ccmode_ccm *ccm, ccccm_ctx *ctx, size_t key_len, const void *key); |
| 194 | int (*CC_SPTR(ccmode_ccm, set_iv))(ccccm_ctx *ctx, |
| 195 | ccccm_nonce *nonce_ctx, |
| 196 | size_t nonce_len, |
| 197 | const void *nonce, |
| 198 | size_t mac_size, |
| 199 | size_t auth_len, |
| 200 | size_t data_len); |
| 201 | int (*CC_SPTR(ccmode_ccm, cbcmac))(ccccm_ctx *ctx, |
| 202 | ccccm_nonce *nonce_ctx, |
| 203 | size_t nbytes, |
| 204 | const void *in); // could just be ccm with NULL out |
| 205 | int (*CC_SPTR(ccmode_ccm, ccm))(ccccm_ctx *ctx, ccccm_nonce *nonce_ctx, size_t nbytes, const void *in, void *out); |
| 206 | int (*CC_SPTR(ccmode_ccm, finalize))(ccccm_ctx *key, ccccm_nonce *nonce_ctx, void *mac); |
| 207 | int (*CC_SPTR(ccmode_ccm, reset))(ccccm_ctx *key, ccccm_nonce *nonce_ctx); |
| 208 | const void *custom; |
| 209 | bool enc_mode; |
| 210 | }; |
| 211 | |
| 212 | /* We need to expose this (currently)to keep CommonCrypto happy. */ |
| 213 | struct _ccmode_ccm_nonce { |
| 214 | unsigned char A_i[16]; /* crypto block iv */ |
| 215 | unsigned char B_i[16]; /* mac block iv */ |
| 216 | unsigned char MAC[16]; /* crypted mac */ |
| 217 | unsigned char buf[16]; /* crypt buffer */ |
| 218 | |
| 219 | uint32_t mode; /* mode: IV -> AD -> DATA */ |
| 220 | uint32_t buflen; /* length of data in buf */ |
| 221 | uint32_t b_i_len; /* length of cbcmac data in B_i */ |
| 222 | |
| 223 | size_t nonce_size; |
| 224 | size_t mac_size; |
| 225 | }; |
| 226 | |
| 227 | /* OMAC mode. */ |
| 228 | cc_aligned_struct(16) ccomac_ctx; |
| 229 | |
| 230 | struct ccmode_omac { |
| 231 | size_t size; /* first argument to ccomac_ctx_decl(). */ |
| 232 | size_t block_size; |
| 233 | int (*CC_SPTR(ccmode_omac, |
| 234 | init))(const struct ccmode_omac *omac, ccomac_ctx *ctx, size_t tweak_len, size_t key_len, const void *key); |
| 235 | int (*CC_SPTR(ccmode_omac, omac))(ccomac_ctx *ctx, size_t nblocks, const void *tweak, const void *in, void *out); |
| 236 | const void *custom; |
| 237 | }; |
| 238 | |
| 239 | /* This provide an implementation of SIV |
| 240 | as specified in https://tools.ietf.org/html/rfc5297 |
| 241 | also in http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/siv/siv.pdf |
| 242 | Counter Mode where IV is based on CMAC |
| 243 | */ |
| 244 | |
| 245 | cc_aligned_struct(16) ccsiv_ctx; |
| 246 | |
| 247 | struct ccmode_siv { |
| 248 | size_t size; /* first argument to ccsiv_ctx_decl(). */ |
| 249 | size_t block_size; |
| 250 | int (*CC_SPTR(ccmode_siv, init))(const struct ccmode_siv *siv, ccsiv_ctx *ctx, |
| 251 | size_t key_len, const uint8_t *key); |
| 252 | int (*CC_SPTR(ccmode_siv, set_nonce))(ccsiv_ctx *ctx, size_t nbytes, const uint8_t *in); // could just be ccm with NULL out |
| 253 | int (*CC_SPTR(ccmode_siv, auth))(ccsiv_ctx *ctx, size_t nbytes, const uint8_t *in); // could just be ccm with NULL out |
| 254 | int (*CC_SPTR(ccmode_siv, crypt))(ccsiv_ctx *ctx, size_t nbytes, const uint8_t *in, uint8_t *out); |
| 255 | int (*CC_SPTR(ccmode_siv, reset))(ccsiv_ctx *ctx); |
| 256 | const struct ccmode_cbc *cbc; |
| 257 | const struct ccmode_ctr *ctr; |
| 258 | }; |
| 259 | |
| 260 | /* This provides an implementation of SIV using AES CTR mode with HMAC as the MAC, |
| 261 | allowing for a tagging mechanism with collision resistant tags. This is a modification of the |
| 262 | standard specified in https://tools.ietf.org/html/rfc5297 |
| 263 | also in http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/siv/siv.pdf |
| 264 | Counter Mode where IV is based on HMAC. |
| 265 | */ |
| 266 | |
| 267 | cc_aligned_struct(16) ccsiv_hmac_ctx; |
| 268 | |
| 269 | struct ccmode_siv_hmac { |
| 270 | size_t size; /* first argument to ccsiv_hmac_ctx_decl(). */ |
| 271 | size_t block_size; |
| 272 | |
| 273 | int (*CC_SPTR(ccmode_siv_hmac, init))(const struct ccmode_siv_hmac *sivhmac, |
| 274 | ccsiv_hmac_ctx *ctx, |
| 275 | size_t key_len, |
| 276 | const uint8_t *key, |
| 277 | const size_t tag_size); |
| 278 | int (*CC_SPTR(ccmode_siv_hmac, set_nonce))(ccsiv_hmac_ctx *ctx, size_t nbytes, const uint8_t *in); |
| 279 | int (*CC_SPTR(ccmode_siv_hmac, auth))(ccsiv_hmac_ctx *ctx, size_t nbytes, const uint8_t *in); |
| 280 | int (*CC_SPTR(ccmode_siv_hmac, crypt))(ccsiv_hmac_ctx *ctx, size_t nbytes, const uint8_t *in, uint8_t *out); |
| 281 | int (*CC_SPTR(ccmode_siv_hmac, reset))(ccsiv_hmac_ctx *ctx); |
| 282 | const struct ccdigest_info *hmac_digest; // Digest to be used in HMAC; |
| 283 | const struct ccmode_ctr *ctr; |
| 284 | }; |
| 285 | |
| 286 | #endif /* _CORECRYPTO_CCMODE_IMPL_H_ */ |
| 287 | |