diff --git a/crypto/evp/evp_enc.c b/crypto/evp/evp_enc.c index c650addbd1a4e..35feec17f6ffa 100644 --- a/crypto/evp/evp_enc.c +++ b/crypto/evp/evp_enc.c @@ -1135,10 +1135,22 @@ int EVP_CIPHER_CTX_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr) return 0; params[0] = OSSL_PARAM_construct_size_t(OSSL_CIPHER_PARAM_IVLEN, &sz); break; - case EVP_CTRL_GCM_SET_IV_FIXED: - params[0] = - OSSL_PARAM_construct_octet_string(OSSL_CIPHER_PARAM_AEAD_TLS1_IV_FIXED, - ptr, sz); + case EVP_CTRL_AEAD_SET_IV_FIXED: + params[0] = OSSL_PARAM_construct_octet_string( + OSSL_CIPHER_PARAM_AEAD_TLS1_IV_FIXED, ptr, sz); + break; + case EVP_CTRL_GCM_IV_GEN: + set_params = 0; + if (arg < 0) + sz = 0; /* special case that uses the iv length */ + params[0] = OSSL_PARAM_construct_octet_string( + OSSL_CIPHER_PARAM_AEAD_TLS1_GET_IV_GEN, ptr, sz); + break; + case EVP_CTRL_GCM_SET_IV_INV: + if (arg < 0) + return 0; + params[0] = OSSL_PARAM_construct_octet_string( + OSSL_CIPHER_PARAM_AEAD_TLS1_SET_IV_INV, ptr, sz); break; case EVP_CTRL_GET_RC5_ROUNDS: set_params = 0; /* Fall thru */ diff --git a/doc/man7/provider-cipher.pod b/doc/man7/provider-cipher.pod index 7ad239bcb63ff..80bba1f9781c6 100644 --- a/doc/man7/provider-cipher.pod +++ b/doc/man7/provider-cipher.pod @@ -349,6 +349,18 @@ by AES SIV ciphers which disallow multiple operations by default. Setting "speed" to 1 allows another encrypt or decrypt operation to be performed. This is used for performance testing. +=item "tlsivgen" (B) + +Gets the invocation field generated for encryption. +Can only be called after "tlsivfixed" is set. +This is only used for GCM mode. + +=item "tlsivinv" (B) + +Sets the invocation field used for decryption. +Can only be called after "tlsivfixed" is set. +This is only used for GCM mode. + =item "tls1multi_enc" (B) Triggers a multiblock tls1 encrypt operation for a tls1 aware cipher that supports diff --git a/include/openssl/core_names.h b/include/openssl/core_names.h index 446af5fa8e682..db9cb9ab2d449 100644 --- a/include/openssl/core_names.h +++ b/include/openssl/core_names.h @@ -51,27 +51,29 @@ extern "C" { #define OSSL_ALG_PARAM_PROPERTIES "properties"/* utf8_string */ /* cipher parameters */ -#define OSSL_CIPHER_PARAM_PADDING "padding" /* uint */ -#define OSSL_CIPHER_PARAM_MODE "mode" /* uint */ -#define OSSL_CIPHER_PARAM_BLOCK_SIZE "blocksize" /* size_t */ -#define OSSL_CIPHER_PARAM_FLAGS "flags" /* ulong */ -#define OSSL_CIPHER_PARAM_KEYLEN "keylen" /* size_t */ -#define OSSL_CIPHER_PARAM_IVLEN "ivlen" /* size_t */ -#define OSSL_CIPHER_PARAM_IV "iv" /* octet_string OR octet_ptr */ -#define OSSL_CIPHER_PARAM_NUM "num" /* uint */ -#define OSSL_CIPHER_PARAM_ROUNDS "rounds" /* uint */ -#define OSSL_CIPHER_PARAM_AEAD_TAG "tag" /* octet_string */ -#define OSSL_CIPHER_PARAM_AEAD_TLS1_AAD "tlsaad" /* octet_string */ -#define OSSL_CIPHER_PARAM_AEAD_TLS1_AAD_PAD "tlsaadpad" /* size_t */ -#define OSSL_CIPHER_PARAM_AEAD_TLS1_IV_FIXED "tlsivfixed" /* octet_string */ -#define OSSL_CIPHER_PARAM_AEAD_IVLEN OSSL_CIPHER_PARAM_IVLEN -#define OSSL_CIPHER_PARAM_AEAD_TAGLEN "taglen" /* size_t */ -#define OSSL_CIPHER_PARAM_AEAD_MAC_KEY "mackey" /* octet_string */ -#define OSSL_CIPHER_PARAM_RANDOM_KEY "randkey" /* octet_string */ -#define OSSL_CIPHER_PARAM_RC2_KEYBITS "keybits" /* size_t */ -#define OSSL_CIPHER_PARAM_SPEED "speed" /* uint */ +#define OSSL_CIPHER_PARAM_PADDING "padding" /* uint */ +#define OSSL_CIPHER_PARAM_MODE "mode" /* uint */ +#define OSSL_CIPHER_PARAM_BLOCK_SIZE "blocksize" /* size_t */ +#define OSSL_CIPHER_PARAM_FLAGS "flags" /* ulong */ +#define OSSL_CIPHER_PARAM_KEYLEN "keylen" /* size_t */ +#define OSSL_CIPHER_PARAM_IVLEN "ivlen" /* size_t */ +#define OSSL_CIPHER_PARAM_IV "iv" /* octet_string OR octet_ptr */ +#define OSSL_CIPHER_PARAM_NUM "num" /* uint */ +#define OSSL_CIPHER_PARAM_ROUNDS "rounds" /* uint */ +#define OSSL_CIPHER_PARAM_AEAD_TAG "tag" /* octet_string */ +#define OSSL_CIPHER_PARAM_AEAD_TLS1_AAD "tlsaad" /* octet_string */ +#define OSSL_CIPHER_PARAM_AEAD_TLS1_AAD_PAD "tlsaadpad" /* size_t */ +#define OSSL_CIPHER_PARAM_AEAD_TLS1_IV_FIXED "tlsivfixed" /* octet_string */ +#define OSSL_CIPHER_PARAM_AEAD_TLS1_GET_IV_GEN "tlsivgen" /* octet_string */ +#define OSSL_CIPHER_PARAM_AEAD_TLS1_SET_IV_INV "tlsivinv" /* octet_string */ +#define OSSL_CIPHER_PARAM_AEAD_IVLEN OSSL_CIPHER_PARAM_IVLEN +#define OSSL_CIPHER_PARAM_AEAD_TAGLEN "taglen" /* size_t */ +#define OSSL_CIPHER_PARAM_AEAD_MAC_KEY "mackey" /* octet_string */ +#define OSSL_CIPHER_PARAM_RANDOM_KEY "randkey" /* octet_string */ +#define OSSL_CIPHER_PARAM_RC2_KEYBITS "keybits" /* size_t */ +#define OSSL_CIPHER_PARAM_SPEED "speed" /* uint */ /* For passing the AlgorithmIdentifier parameter in DER form */ -#define OSSL_CIPHER_PARAM_ALG_ID "alg_id_param" /* octet_string */ +#define OSSL_CIPHER_PARAM_ALG_ID "alg_id_param" /* octet_string */ #define OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_MAX_SEND_FRAGMENT \ "tls1multi_maxsndfrag" /* uint */ diff --git a/providers/implementations/ciphers/ciphercommon.c b/providers/implementations/ciphers/ciphercommon.c index a6b890704e1ea..967622cf64e19 100644 --- a/providers/implementations/ciphers/ciphercommon.c +++ b/providers/implementations/ciphers/ciphercommon.c @@ -109,6 +109,7 @@ static const OSSL_PARAM cipher_aead_known_gettable_ctx_params[] = { OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_IV, NULL, 0), OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_AEAD_TAG, NULL, 0), OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_AEAD_TLS1_AAD_PAD, NULL), + OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_AEAD_TLS1_GET_IV_GEN, NULL, 0), OSSL_PARAM_END }; const OSSL_PARAM *cipher_aead_gettable_ctx_params(void) @@ -121,6 +122,7 @@ static const OSSL_PARAM cipher_aead_known_settable_ctx_params[] = { OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_AEAD_TAG, NULL, 0), OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_AEAD_TLS1_AAD, NULL, 0), OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_AEAD_TLS1_IV_FIXED, NULL, 0), + OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_AEAD_TLS1_SET_IV_INV, NULL, 0), OSSL_PARAM_END }; const OSSL_PARAM *cipher_aead_settable_ctx_params(void) diff --git a/providers/implementations/ciphers/ciphercommon_gcm.c b/providers/implementations/ciphers/ciphercommon_gcm.c index 803f810a30088..a6928e1ba36f7 100644 --- a/providers/implementations/ciphers/ciphercommon_gcm.c +++ b/providers/implementations/ciphers/ciphercommon_gcm.c @@ -77,6 +77,54 @@ int gcm_dinit(void *vctx, const unsigned char *key, size_t keylen, return gcm_init(vctx, key, keylen, iv, ivlen, 0); } +/* increment counter (64-bit int) by 1 */ +static void ctr64_inc(unsigned char *counter) +{ + int n = 8; + unsigned char c; + + do { + --n; + c = counter[n]; + ++c; + counter[n] = c; + if (c > 0) + return; + } while (n > 0); +} + +static int getivgen(PROV_GCM_CTX *ctx, unsigned char *out, size_t olen) +{ + if (!ctx->iv_gen + || !ctx->key_set + || !ctx->hw->setiv(ctx, ctx->iv, ctx->ivlen)) + return 0; + if (olen == 0 || olen > ctx->ivlen) + olen = ctx->ivlen; + memcpy(out, ctx->iv + ctx->ivlen - olen, olen); + /* + * Invocation field will be at least 8 bytes in size and so no need + * to check wrap around or increment more than last 8 bytes. + */ + ctr64_inc(ctx->iv + ctx->ivlen - 8); + ctx->iv_state = IV_STATE_COPIED; + return 1; +} + +static int setivinv(PROV_GCM_CTX *ctx, unsigned char *in, size_t inl) +{ + if (!ctx->iv_gen + || !ctx->key_set + || ctx->enc) + return 0; + + memcpy(ctx->iv + ctx->ivlen - inl, in, inl); + if (!ctx->hw->setiv(ctx, ctx->iv, ctx->ivlen)) + return 0; + ctx->iv_state = IV_STATE_COPIED; + return 1; +} + int gcm_get_ctx_params(void *vctx, OSSL_PARAM params[]) { PROV_GCM_CTX *ctx = (PROV_GCM_CTX *)vctx; @@ -138,7 +186,13 @@ int gcm_get_ctx_params(void *vctx, OSSL_PARAM params[]) return 0; } } - + p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_AEAD_TLS1_GET_IV_GEN); + if (p != NULL) { + if (p->data == NULL + || p->data_type != OSSL_PARAM_OCTET_STRING + || !getivgen(ctx, p->data, p->data_size)) + return 0; + } return 1; } @@ -201,6 +255,14 @@ int gcm_set_ctx_params(void *vctx, const OSSL_PARAM params[]) return 0; } } + p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_AEAD_TLS1_SET_IV_INV); + if (p != NULL) { + if (p->data == NULL + || p->data_type != OSSL_PARAM_OCTET_STRING + || !setivinv(ctx, p->data, p->data_size)) + return 0; + } + return 1; } @@ -397,22 +459,6 @@ static int gcm_tls_iv_set_fixed(PROV_GCM_CTX *ctx, unsigned char *iv, return 1; } -/* increment counter (64-bit int) by 1 */ -static void ctr64_inc(unsigned char *counter) -{ - int n = 8; - unsigned char c; - - do { - --n; - c = counter[n]; - ++c; - counter[n] = c; - if (c > 0) - return; - } while (n > 0); -} - /* * Handle TLS GCM packet format. This consists of the last portion of the IV * followed by the payload and finally the tag. On encrypt generate IV, @@ -445,29 +491,17 @@ static int gcm_tls_cipher(PROV_GCM_CTX *ctx, unsigned char *out, size_t *padlen, goto err; } - if (ctx->iv_gen == 0) - goto err; /* * Set IV from start of buffer or generate IV and write to start of * buffer. */ if (ctx->enc) { - if (!ctx->hw->setiv(ctx, ctx->iv, ctx->ivlen)) + if (!getivgen(ctx, out, arg)) goto err; - if (arg > ctx->ivlen) - arg = ctx->ivlen; - memcpy(out, ctx->iv + ctx->ivlen - arg, arg); - /* - * Invocation field will be at least 8 bytes in size and so no need - * to check wrap around or increment more than last 8 bytes. - */ - ctr64_inc(ctx->iv + ctx->ivlen - 8); } else { - memcpy(ctx->iv + ctx->ivlen - arg, out, arg); - if (!ctx->hw->setiv(ctx, ctx->iv, ctx->ivlen)) + if (!setivinv(ctx, out, arg)) goto err; } - ctx->iv_state = IV_STATE_COPIED; /* Fix buffer and length to point to payload */ in += EVP_GCM_TLS_EXPLICIT_IV_LEN; @@ -493,3 +527,4 @@ static int gcm_tls_cipher(PROV_GCM_CTX *ctx, unsigned char *out, size_t *padlen, *padlen = plen; return rv; } +