| 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 |  | 
|---|