1 /* 2 * Copyright 2019-2025 The OpenSSL Project Authors. All Rights Reserved. 3 * 4 * Licensed under the Apache License 2.0 (the "License"). You may not use 5 * this file except in compliance with the License. You can obtain a copy 6 * in the file LICENSE in the source distribution or at 7 * https://www.openssl.org/source/license.html 8 */ 9 10 /* 11 * AES low level APIs are deprecated for public use, but still ok for internal 12 * use where we're using them to implement the higher level EVP interface, as is 13 * the case here. 14 */ 15 #include "internal/deprecated.h" 16 17 #include <openssl/evp.h> 18 #include <internal/endian.h> 19 #include <prov/implementations.h> 20 #include "cipher_aes_gcm_siv.h" 21 22 static int aes_gcm_siv_ctr32(PROV_AES_GCM_SIV_CTX *ctx, const unsigned char *init_counter, 23 unsigned char *out, const unsigned char *in, size_t len); 24 25 static int aes_gcm_siv_initkey(void *vctx) 26 { 27 PROV_AES_GCM_SIV_CTX *ctx = (PROV_AES_GCM_SIV_CTX *)vctx; 28 uint8_t output[BLOCK_SIZE]; 29 uint32_t counter = 0x0; 30 size_t i; 31 union { 32 uint32_t counter; 33 uint8_t block[BLOCK_SIZE]; 34 } data; 35 int out_len; 36 EVP_CIPHER *ecb = NULL; 37 DECLARE_IS_ENDIAN; 38 39 switch (ctx->key_len) { 40 case 16: 41 ecb = EVP_CIPHER_fetch(ctx->libctx, "AES-128-ECB", NULL); 42 break; 43 case 24: 44 ecb = EVP_CIPHER_fetch(ctx->libctx, "AES-192-ECB", NULL); 45 break; 46 case 32: 47 ecb = EVP_CIPHER_fetch(ctx->libctx, "AES-256-ECB", NULL); 48 break; 49 default: 50 goto err; 51 } 52 53 if (ctx->ecb_ctx == NULL && (ctx->ecb_ctx = EVP_CIPHER_CTX_new()) == NULL) 54 goto err; 55 if (!EVP_EncryptInit_ex2(ctx->ecb_ctx, ecb, ctx->key_gen_key, NULL, NULL)) 56 goto err; 57 58 memset(&data, 0, sizeof(data)); 59 memcpy(&data.block[sizeof(data.counter)], ctx->nonce, NONCE_SIZE); 60 61 /* msg_auth_key is always 16 bytes in size, regardless of AES128/AES256 */ 62 /* counter is stored little-endian */ 63 for (i = 0; i < BLOCK_SIZE; i += 8) { 64 if (IS_LITTLE_ENDIAN) { 65 data.counter = counter; 66 } else { 67 data.counter = GSWAP4(counter); 68 } 69 /* Block size is 16 (128 bits), but only 8 bytes are used */ 70 out_len = BLOCK_SIZE; 71 if (!EVP_EncryptUpdate(ctx->ecb_ctx, output, &out_len, data.block, BLOCK_SIZE)) 72 goto err; 73 memcpy(&ctx->msg_auth_key[i], output, 8); 74 counter++; 75 } 76 77 /* msg_enc_key length is directly tied to key length AES128/AES256 */ 78 for (i = 0; i < ctx->key_len; i += 8) { 79 if (IS_LITTLE_ENDIAN) { 80 data.counter = counter; 81 } else { 82 data.counter = GSWAP4(counter); 83 } 84 /* Block size is 16 bytes (128 bits), but only 8 bytes are used */ 85 out_len = BLOCK_SIZE; 86 if (!EVP_EncryptUpdate(ctx->ecb_ctx, output, &out_len, data.block, BLOCK_SIZE)) 87 goto err; 88 memcpy(&ctx->msg_enc_key[i], output, 8); 89 counter++; 90 } 91 92 if (!EVP_EncryptInit_ex2(ctx->ecb_ctx, ecb, ctx->msg_enc_key, NULL, NULL)) 93 goto err; 94 95 /* Freshen up the state */ 96 ctx->used_enc = 0; 97 ctx->used_dec = 0; 98 EVP_CIPHER_free(ecb); 99 return 1; 100 err: 101 EVP_CIPHER_CTX_free(ctx->ecb_ctx); 102 EVP_CIPHER_free(ecb); 103 ctx->ecb_ctx = NULL; 104 return 0; 105 } 106 107 static int aes_gcm_siv_aad(PROV_AES_GCM_SIV_CTX *ctx, 108 const unsigned char *aad, size_t len) 109 { 110 size_t to_alloc; 111 uint8_t *ptr; 112 uint64_t len64; 113 114 /* length of 0 resets the AAD */ 115 if (len == 0) { 116 OPENSSL_free(ctx->aad); 117 ctx->aad = NULL; 118 ctx->aad_len = 0; 119 return 1; 120 } 121 to_alloc = UP16(ctx->aad_len + len); 122 /* need to check the size of the AAD per RFC8452 */ 123 len64 = to_alloc; 124 if (len64 > ((uint64_t)1 << 36)) 125 return 0; 126 ptr = OPENSSL_realloc(ctx->aad, to_alloc); 127 if (ptr == NULL) 128 return 0; 129 ctx->aad = ptr; 130 memcpy(&ctx->aad[ctx->aad_len], aad, len); 131 ctx->aad_len += len; 132 if (to_alloc > ctx->aad_len) 133 memset(&ctx->aad[ctx->aad_len], 0, to_alloc - ctx->aad_len); 134 return 1; 135 } 136 137 static int aes_gcm_siv_finish(PROV_AES_GCM_SIV_CTX *ctx) 138 { 139 int ret = 0; 140 141 if (ctx->enc) 142 return ctx->generated_tag; 143 ret = !CRYPTO_memcmp(ctx->tag, ctx->user_tag, sizeof(ctx->tag)); 144 ret &= ctx->have_user_tag; 145 return ret; 146 } 147 148 static int aes_gcm_siv_encrypt(PROV_AES_GCM_SIV_CTX *ctx, const unsigned char *in, 149 unsigned char *out, size_t len) 150 { 151 uint64_t len_blk[2]; 152 uint8_t S_s[TAG_SIZE]; 153 uint8_t counter_block[TAG_SIZE]; 154 uint8_t padding[BLOCK_SIZE]; 155 size_t i; 156 int64_t len64 = len; 157 int out_len; 158 int error = 0; 159 DECLARE_IS_ENDIAN; 160 161 ctx->generated_tag = 0; 162 if (!ctx->speed && ctx->used_enc) 163 return 0; 164 /* need to check the size of the input! */ 165 if (len64 > ((int64_t)1 << 36)) 166 return 0; 167 168 if (IS_LITTLE_ENDIAN) { 169 len_blk[0] = (uint64_t)ctx->aad_len * 8; 170 len_blk[1] = (uint64_t)len * 8; 171 } else { 172 len_blk[0] = GSWAP8((uint64_t)ctx->aad_len * 8); 173 len_blk[1] = GSWAP8((uint64_t)len * 8); 174 } 175 memset(S_s, 0, TAG_SIZE); 176 ossl_polyval_ghash_init(ctx->Htable, (const uint64_t*)ctx->msg_auth_key); 177 178 if (ctx->aad != NULL) { 179 /* AAD is allocated with padding, but need to adjust length */ 180 ossl_polyval_ghash_hash(ctx->Htable, S_s, ctx->aad, UP16(ctx->aad_len)); 181 } 182 if (DOWN16(len) > 0) 183 ossl_polyval_ghash_hash(ctx->Htable, S_s, (uint8_t *) in, DOWN16(len)); 184 if (!IS16(len)) { 185 /* deal with padding - probably easier to memset the padding first rather than calculate */ 186 memset(padding, 0, sizeof(padding)); 187 memcpy(padding, &in[DOWN16(len)], REMAINDER16(len)); 188 ossl_polyval_ghash_hash(ctx->Htable, S_s, padding, sizeof(padding)); 189 } 190 ossl_polyval_ghash_hash(ctx->Htable, S_s, (uint8_t *) len_blk, sizeof(len_blk)); 191 192 for (i = 0; i < NONCE_SIZE; i++) 193 S_s[i] ^= ctx->nonce[i]; 194 195 S_s[TAG_SIZE - 1] &= 0x7f; 196 out_len = sizeof(ctx->tag); 197 error |= !EVP_EncryptUpdate(ctx->ecb_ctx, ctx->tag, &out_len, S_s, sizeof(S_s)); 198 memcpy(counter_block, ctx->tag, TAG_SIZE); 199 counter_block[TAG_SIZE - 1] |= 0x80; 200 201 error |= !aes_gcm_siv_ctr32(ctx, counter_block, out, in, len); 202 203 ctx->generated_tag = !error; 204 /* Regardless of error */ 205 ctx->used_enc = 1; 206 return !error; 207 } 208 209 static int aes_gcm_siv_decrypt(PROV_AES_GCM_SIV_CTX *ctx, const unsigned char *in, 210 unsigned char *out, size_t len) 211 { 212 uint8_t counter_block[TAG_SIZE]; 213 uint64_t len_blk[2]; 214 uint8_t S_s[TAG_SIZE]; 215 size_t i; 216 uint64_t padding[2]; 217 int64_t len64 = len; 218 int out_len; 219 int error = 0; 220 DECLARE_IS_ENDIAN; 221 222 ctx->generated_tag = 0; 223 if (!ctx->speed && ctx->used_dec) 224 return 0; 225 /* need to check the size of the input! */ 226 if (len64 > ((int64_t)1 << 36)) 227 return 0; 228 229 memcpy(counter_block, ctx->user_tag, sizeof(counter_block)); 230 counter_block[TAG_SIZE - 1] |= 0x80; 231 232 error |= !aes_gcm_siv_ctr32(ctx, counter_block, out, in, len); 233 234 if (IS_LITTLE_ENDIAN) { 235 len_blk[0] = (uint64_t)ctx->aad_len * 8; 236 len_blk[1] = (uint64_t)len * 8; 237 } else { 238 len_blk[0] = GSWAP8((uint64_t)ctx->aad_len * 8); 239 len_blk[1] = GSWAP8((uint64_t)len * 8); 240 } 241 memset(S_s, 0, TAG_SIZE); 242 ossl_polyval_ghash_init(ctx->Htable, (const uint64_t*)ctx->msg_auth_key); 243 if (ctx->aad != NULL) { 244 /* AAD allocated with padding, but need to adjust length */ 245 ossl_polyval_ghash_hash(ctx->Htable, S_s, ctx->aad, UP16(ctx->aad_len)); 246 } 247 if (DOWN16(len) > 0) 248 ossl_polyval_ghash_hash(ctx->Htable, S_s, out, DOWN16(len)); 249 if (!IS16(len)) { 250 /* deal with padding - probably easier to "memset" the padding first rather than calculate */ 251 padding[0] = padding[1] = 0; 252 memcpy(padding, &out[DOWN16(len)], REMAINDER16(len)); 253 ossl_polyval_ghash_hash(ctx->Htable, S_s, (uint8_t *)padding, sizeof(padding)); 254 } 255 ossl_polyval_ghash_hash(ctx->Htable, S_s, (uint8_t *)len_blk, TAG_SIZE); 256 257 for (i = 0; i < NONCE_SIZE; i++) 258 S_s[i] ^= ctx->nonce[i]; 259 260 S_s[TAG_SIZE - 1] &= 0x7f; 261 262 /* 263 * In the ctx, user_tag is the one received/set by the user, 264 * and tag is generated from the input 265 */ 266 out_len = sizeof(ctx->tag); 267 error |= !EVP_EncryptUpdate(ctx->ecb_ctx, ctx->tag, &out_len, S_s, sizeof(S_s)); 268 ctx->generated_tag = !error; 269 /* Regardless of error */ 270 ctx->used_dec = 1; 271 return !error; 272 } 273 274 static int aes_gcm_siv_cipher(void *vctx, unsigned char *out, 275 const unsigned char *in, size_t len) 276 { 277 PROV_AES_GCM_SIV_CTX *ctx = (PROV_AES_GCM_SIV_CTX *)vctx; 278 279 /* EncryptFinal or DecryptFinal */ 280 if (in == NULL) 281 return aes_gcm_siv_finish(ctx); 282 283 /* Deal with associated data */ 284 if (out == NULL) 285 return aes_gcm_siv_aad(ctx, in, len); 286 287 if (ctx->enc) 288 return aes_gcm_siv_encrypt(ctx, in, out, len); 289 290 return aes_gcm_siv_decrypt(ctx, in, out, len); 291 } 292 293 static void aes_gcm_siv_clean_ctx(void *vctx) 294 { 295 PROV_AES_GCM_SIV_CTX *ctx = (PROV_AES_GCM_SIV_CTX *)vctx; 296 297 EVP_CIPHER_CTX_free(ctx->ecb_ctx); 298 ctx->ecb_ctx = NULL; 299 } 300 301 static int aes_gcm_siv_dup_ctx(void *vdst, void *vsrc) 302 { 303 PROV_AES_GCM_SIV_CTX *dst = (PROV_AES_GCM_SIV_CTX *)vdst; 304 PROV_AES_GCM_SIV_CTX *src = (PROV_AES_GCM_SIV_CTX *)vsrc; 305 306 dst->ecb_ctx = NULL; 307 if (src->ecb_ctx != NULL) { 308 if ((dst->ecb_ctx = EVP_CIPHER_CTX_new()) == NULL) 309 goto err; 310 if (!EVP_CIPHER_CTX_copy(dst->ecb_ctx, src->ecb_ctx)) 311 goto err; 312 } 313 return 1; 314 315 err: 316 EVP_CIPHER_CTX_free(dst->ecb_ctx); 317 dst->ecb_ctx = NULL; 318 return 0; 319 } 320 321 static const PROV_CIPHER_HW_AES_GCM_SIV aes_gcm_siv_hw = { 322 aes_gcm_siv_initkey, 323 aes_gcm_siv_cipher, 324 aes_gcm_siv_dup_ctx, 325 aes_gcm_siv_clean_ctx, 326 }; 327 328 const PROV_CIPHER_HW_AES_GCM_SIV *ossl_prov_cipher_hw_aes_gcm_siv(size_t keybits) 329 { 330 return &aes_gcm_siv_hw; 331 } 332 333 /* AES-GCM-SIV needs AES-CTR32, which is different than the AES-CTR implementation */ 334 static int aes_gcm_siv_ctr32(PROV_AES_GCM_SIV_CTX *ctx, const unsigned char *init_counter, 335 unsigned char *out, const unsigned char *in, size_t len) 336 { 337 uint8_t keystream[BLOCK_SIZE]; 338 int out_len; 339 size_t i; 340 size_t j; 341 size_t todo; 342 uint32_t counter; 343 int error = 0; 344 union { 345 uint32_t x32[BLOCK_SIZE / sizeof(uint32_t)]; 346 uint8_t x8[BLOCK_SIZE]; 347 } block; 348 DECLARE_IS_ENDIAN; 349 350 memcpy(&block, init_counter, sizeof(block)); 351 if (IS_BIG_ENDIAN) { 352 counter = GSWAP4(block.x32[0]); 353 } 354 355 for (i = 0; i < len; i += sizeof(block)) { 356 out_len = BLOCK_SIZE; 357 error |= !EVP_EncryptUpdate(ctx->ecb_ctx, keystream, &out_len, (uint8_t*)&block, sizeof(block)); 358 if (IS_LITTLE_ENDIAN) { 359 block.x32[0]++; 360 } else { 361 counter++; 362 block.x32[0] = GSWAP4(counter); 363 } 364 todo = len - i; 365 if (todo > sizeof(keystream)) 366 todo = sizeof(keystream); 367 /* Non optimal, but avoids alignment issues */ 368 for (j = 0; j < todo; j++) 369 out[i + j] = in[i + j] ^ keystream[j]; 370 } 371 return !error; 372 } 373