summaryrefslogtreecommitdiffstats
path: root/providers
diff options
context:
space:
mode:
authorShane Lontis <shane.lontis@oracle.com>2019-10-14 20:59:31 +1000
committerShane Lontis <shane.lontis@oracle.com>2020-01-10 11:58:27 +1000
commit11b44359862632e283feabf15dab85bb550ebace (patch)
tree23572f4121313e7bd83308405e0a4472baa9461d /providers
parent1e8879691ff86bda75b6e2e66c0f528684df5d47 (diff)
Add GCM support for EVP_CTRL_GCM_IV_GEN and EVP_CTRL_GCM_SET_IV_INV to providers
Reviewed-by: Matt Caswell <matt@openssl.org> (Merged from https://github.com/openssl/openssl/pull/10173)
Diffstat (limited to 'providers')
-rw-r--r--providers/implementations/ciphers/ciphercommon.c2
-rw-r--r--providers/implementations/ciphers/ciphercommon_gcm.c97
2 files changed, 68 insertions, 31 deletions
diff --git a/providers/implementations/ciphers/ciphercommon.c b/providers/implementations/ciphers/ciphercommon.c
index a6b890704e..967622cf64 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 803f810a30..a6928e1ba3 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 @@ err:
*padlen = plen;
return rv;
}
+