summaryrefslogtreecommitdiff
path: root/sys/opencrypto
diff options
context:
space:
mode:
authorJohn Baldwin <jhb@FreeBSD.org>2020-11-06 00:10:58 +0000
committerJohn Baldwin <jhb@FreeBSD.org>2020-11-06 00:10:58 +0000
commitb19d4c075f39f2f8be36a51282691baf91ef3cb0 (patch)
tree557b79f9317d3c59b2830b36cb507599c10f20b7 /sys/opencrypto
parentc54004c6a949c0b938634105ce7e33b5f92be3c9 (diff)
downloadsrc-test-b19d4c075f39f2f8be36a51282691baf91ef3cb0.tar.gz
src-test-b19d4c075f39f2f8be36a51282691baf91ef3cb0.zip
Split logic to create new sessions into a separate function.
This simplifies cryptof_ioctl as it now a wrapper around functions that contain the bulk of the per-ioctl logic. Reviewed by: markj Sponsored by: Chelsio Communications Differential Revision: https://reviews.freebsd.org/D27068
Notes
Notes: svn path=/head/; revision=367409
Diffstat (limited to 'sys/opencrypto')
-rw-r--r--sys/opencrypto/cryptodev.c603
1 files changed, 300 insertions, 303 deletions
diff --git a/sys/opencrypto/cryptodev.c b/sys/opencrypto/cryptodev.c
index 86da8450230aa..fa353fb05ed67 100644
--- a/sys/opencrypto/cryptodev.c
+++ b/sys/opencrypto/cryptodev.c
@@ -415,26 +415,318 @@ checkforsoftware(int *cridp)
return 0;
}
+static int
+cryptodev_create_session(struct fcrypt *fcr, struct session2_op *sop)
+{
+ struct crypto_session_params csp;
+ struct csession *cse;
+ struct enc_xform *txform;
+ struct auth_hash *thash;
+ void *key = NULL;
+ void *mackey = NULL;
+ crypto_session_t cses;
+ int crid, error;
+
+ switch (sop->cipher) {
+ case 0:
+ txform = NULL;
+ break;
+ case CRYPTO_AES_CBC:
+ txform = &enc_xform_rijndael128;
+ break;
+ case CRYPTO_AES_XTS:
+ txform = &enc_xform_aes_xts;
+ break;
+ case CRYPTO_NULL_CBC:
+ txform = &enc_xform_null;
+ break;
+ case CRYPTO_CAMELLIA_CBC:
+ txform = &enc_xform_camellia;
+ break;
+ case CRYPTO_AES_ICM:
+ txform = &enc_xform_aes_icm;
+ break;
+ case CRYPTO_AES_NIST_GCM_16:
+ txform = &enc_xform_aes_nist_gcm;
+ break;
+ case CRYPTO_CHACHA20:
+ txform = &enc_xform_chacha20;
+ break;
+ case CRYPTO_AES_CCM_16:
+ txform = &enc_xform_ccm;
+ break;
+ default:
+ CRYPTDEB("invalid cipher");
+ SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
+ return (EINVAL);
+ }
+
+ switch (sop->mac) {
+ case 0:
+ thash = NULL;
+ break;
+ case CRYPTO_POLY1305:
+ thash = &auth_hash_poly1305;
+ break;
+ case CRYPTO_SHA1_HMAC:
+ thash = &auth_hash_hmac_sha1;
+ break;
+ case CRYPTO_SHA2_224_HMAC:
+ thash = &auth_hash_hmac_sha2_224;
+ break;
+ case CRYPTO_SHA2_256_HMAC:
+ thash = &auth_hash_hmac_sha2_256;
+ break;
+ case CRYPTO_SHA2_384_HMAC:
+ thash = &auth_hash_hmac_sha2_384;
+ break;
+ case CRYPTO_SHA2_512_HMAC:
+ thash = &auth_hash_hmac_sha2_512;
+ break;
+ case CRYPTO_RIPEMD160_HMAC:
+ thash = &auth_hash_hmac_ripemd_160;
+ break;
+#ifdef COMPAT_FREEBSD12
+ case CRYPTO_AES_128_NIST_GMAC:
+ case CRYPTO_AES_192_NIST_GMAC:
+ case CRYPTO_AES_256_NIST_GMAC:
+ /* Should always be paired with GCM. */
+ if (sop->cipher != CRYPTO_AES_NIST_GCM_16) {
+ CRYPTDEB("GMAC without GCM");
+ SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
+ return (EINVAL);
+ }
+ break;
+#endif
+ case CRYPTO_AES_NIST_GMAC:
+ switch (sop->mackeylen * 8) {
+ case 128:
+ thash = &auth_hash_nist_gmac_aes_128;
+ break;
+ case 192:
+ thash = &auth_hash_nist_gmac_aes_192;
+ break;
+ case 256:
+ thash = &auth_hash_nist_gmac_aes_256;
+ break;
+ default:
+ CRYPTDEB("invalid GMAC key length");
+ SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
+ return (EINVAL);
+ }
+ break;
+ case CRYPTO_AES_CCM_CBC_MAC:
+ switch (sop->mackeylen) {
+ case 16:
+ thash = &auth_hash_ccm_cbc_mac_128;
+ break;
+ case 24:
+ thash = &auth_hash_ccm_cbc_mac_192;
+ break;
+ case 32:
+ thash = &auth_hash_ccm_cbc_mac_256;
+ break;
+ default:
+ CRYPTDEB("Invalid CBC MAC key size %d", sop->keylen);
+ SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
+ return (EINVAL);
+ }
+ break;
+ case CRYPTO_SHA1:
+ thash = &auth_hash_sha1;
+ break;
+ case CRYPTO_SHA2_224:
+ thash = &auth_hash_sha2_224;
+ break;
+ case CRYPTO_SHA2_256:
+ thash = &auth_hash_sha2_256;
+ break;
+ case CRYPTO_SHA2_384:
+ thash = &auth_hash_sha2_384;
+ break;
+ case CRYPTO_SHA2_512:
+ thash = &auth_hash_sha2_512;
+ break;
+
+ case CRYPTO_NULL_HMAC:
+ thash = &auth_hash_null;
+ break;
+
+ case CRYPTO_BLAKE2B:
+ thash = &auth_hash_blake2b;
+ break;
+ case CRYPTO_BLAKE2S:
+ thash = &auth_hash_blake2s;
+ break;
+
+ default:
+ CRYPTDEB("invalid mac");
+ SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
+ return (EINVAL);
+ }
+
+ if (txform == NULL && thash == NULL) {
+ SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
+ return (EINVAL);
+ }
+
+ memset(&csp, 0, sizeof(csp));
+ if (use_outputbuffers)
+ csp.csp_flags |= CSP_F_SEPARATE_OUTPUT;
+
+ if (sop->cipher == CRYPTO_AES_NIST_GCM_16) {
+ switch (sop->mac) {
+#ifdef COMPAT_FREEBSD12
+ case CRYPTO_AES_128_NIST_GMAC:
+ case CRYPTO_AES_192_NIST_GMAC:
+ case CRYPTO_AES_256_NIST_GMAC:
+ if (sop->keylen != sop->mackeylen) {
+ SDT_PROBE1(opencrypto, dev, ioctl, error,
+ __LINE__);
+ return (EINVAL);
+ }
+ break;
+#endif
+ case 0:
+ break;
+ default:
+ SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
+ return (EINVAL);
+ }
+ csp.csp_mode = CSP_MODE_AEAD;
+ } else if (sop->cipher == CRYPTO_AES_CCM_16) {
+ switch (sop->mac) {
+#ifdef COMPAT_FREEBSD12
+ case CRYPTO_AES_CCM_CBC_MAC:
+ if (sop->keylen != sop->mackeylen) {
+ SDT_PROBE1(opencrypto, dev, ioctl, error,
+ __LINE__);
+ return (EINVAL);
+ }
+ thash = NULL;
+ break;
+#endif
+ case 0:
+ break;
+ default:
+ SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
+ return (EINVAL);
+ }
+ csp.csp_mode = CSP_MODE_AEAD;
+ } else if (txform != NULL && thash != NULL)
+ csp.csp_mode = CSP_MODE_ETA;
+ else if (txform != NULL)
+ csp.csp_mode = CSP_MODE_CIPHER;
+ else
+ csp.csp_mode = CSP_MODE_DIGEST;
+
+ switch (csp.csp_mode) {
+ case CSP_MODE_AEAD:
+ case CSP_MODE_ETA:
+ if (use_separate_aad)
+ csp.csp_flags |= CSP_F_SEPARATE_AAD;
+ break;
+ }
+
+ if (txform != NULL) {
+ csp.csp_cipher_alg = txform->type;
+ csp.csp_cipher_klen = sop->keylen;
+ if (sop->keylen > txform->maxkey ||
+ sop->keylen < txform->minkey) {
+ CRYPTDEB("invalid cipher parameters");
+ error = EINVAL;
+ SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
+ goto bail;
+ }
+
+ key = malloc(csp.csp_cipher_klen, M_XDATA, M_WAITOK);
+ error = copyin(sop->key, key, csp.csp_cipher_klen);
+ if (error) {
+ CRYPTDEB("invalid key");
+ SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
+ goto bail;
+ }
+ csp.csp_cipher_key = key;
+ csp.csp_ivlen = txform->ivsize;
+ }
+
+ if (thash != NULL) {
+ csp.csp_auth_alg = thash->type;
+ csp.csp_auth_klen = sop->mackeylen;
+ if (sop->mackeylen > thash->keysize || sop->mackeylen < 0) {
+ CRYPTDEB("invalid mac key length");
+ error = EINVAL;
+ SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
+ goto bail;
+ }
+
+ if (csp.csp_auth_klen != 0) {
+ mackey = malloc(csp.csp_auth_klen, M_XDATA, M_WAITOK);
+ error = copyin(sop->mackey, mackey, csp.csp_auth_klen);
+ if (error) {
+ CRYPTDEB("invalid mac key");
+ SDT_PROBE1(opencrypto, dev, ioctl, error,
+ __LINE__);
+ goto bail;
+ }
+ csp.csp_auth_key = mackey;
+ }
+
+ if (csp.csp_auth_alg == CRYPTO_AES_NIST_GMAC)
+ csp.csp_ivlen = AES_GCM_IV_LEN;
+ if (csp.csp_auth_alg == CRYPTO_AES_CCM_CBC_MAC)
+ csp.csp_ivlen = AES_CCM_IV_LEN;
+ }
+
+ crid = sop->crid;
+ error = checkforsoftware(&crid);
+ if (error) {
+ CRYPTDEB("checkforsoftware");
+ SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
+ goto bail;
+ }
+ error = crypto_newsession(&cses, &csp, crid);
+ if (error) {
+ CRYPTDEB("crypto_newsession");
+ SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
+ goto bail;
+ }
+
+ cse = csecreate(fcr, cses, &csp, txform, key, thash, mackey);
+
+ if (cse == NULL) {
+ crypto_freesession(cses);
+ error = EINVAL;
+ SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
+ CRYPTDEB("csecreate");
+ goto bail;
+ }
+ sop->ses = cse->ses;
+
+ /* return hardware/driver id */
+ sop->crid = crypto_ses2hid(cse->cses);
+bail:
+ if (error) {
+ free(key, M_XDATA);
+ free(mackey, M_XDATA);
+ }
+ return (error);
+}
+
/* ARGSUSED */
static int
cryptof_ioctl(struct file *fp, u_long cmd, void *data,
struct ucred *active_cred, struct thread *td)
{
static struct timeval keywarn, featwarn;
- struct crypto_session_params csp;
struct fcrypt *fcr = fp->f_data;
struct csession *cse;
struct session2_op *sop;
struct crypt_op *cop;
struct crypt_aead *caead;
- struct enc_xform *txform = NULL;
- struct auth_hash *thash = NULL;
- void *key = NULL;
- void *mackey = NULL;
struct crypt_kop *kop;
- crypto_session_t cses;
uint32_t ses;
- int error = 0, crid;
+ int error = 0;
union {
struct session2_op sopc;
#ifdef COMPAT_FREEBSD32
@@ -502,302 +794,7 @@ cryptof_ioctl(struct file *fp, u_long cmd, void *data,
} else
sop = (struct session2_op *)data;
- switch (sop->cipher) {
- case 0:
- break;
- case CRYPTO_AES_CBC:
- txform = &enc_xform_rijndael128;
- break;
- case CRYPTO_AES_XTS:
- txform = &enc_xform_aes_xts;
- break;
- case CRYPTO_NULL_CBC:
- txform = &enc_xform_null;
- break;
- case CRYPTO_CAMELLIA_CBC:
- txform = &enc_xform_camellia;
- break;
- case CRYPTO_AES_ICM:
- txform = &enc_xform_aes_icm;
- break;
- case CRYPTO_AES_NIST_GCM_16:
- txform = &enc_xform_aes_nist_gcm;
- break;
- case CRYPTO_CHACHA20:
- txform = &enc_xform_chacha20;
- break;
- case CRYPTO_AES_CCM_16:
- txform = &enc_xform_ccm;
- break;
-
- default:
- CRYPTDEB("invalid cipher");
- SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
- return (EINVAL);
- }
-
- switch (sop->mac) {
- case 0:
- break;
- case CRYPTO_POLY1305:
- thash = &auth_hash_poly1305;
- break;
- case CRYPTO_SHA1_HMAC:
- thash = &auth_hash_hmac_sha1;
- break;
- case CRYPTO_SHA2_224_HMAC:
- thash = &auth_hash_hmac_sha2_224;
- break;
- case CRYPTO_SHA2_256_HMAC:
- thash = &auth_hash_hmac_sha2_256;
- break;
- case CRYPTO_SHA2_384_HMAC:
- thash = &auth_hash_hmac_sha2_384;
- break;
- case CRYPTO_SHA2_512_HMAC:
- thash = &auth_hash_hmac_sha2_512;
- break;
- case CRYPTO_RIPEMD160_HMAC:
- thash = &auth_hash_hmac_ripemd_160;
- break;
-#ifdef COMPAT_FREEBSD12
- case CRYPTO_AES_128_NIST_GMAC:
- case CRYPTO_AES_192_NIST_GMAC:
- case CRYPTO_AES_256_NIST_GMAC:
- /* Should always be paired with GCM. */
- if (sop->cipher != CRYPTO_AES_NIST_GCM_16) {
- CRYPTDEB("GMAC without GCM");
- SDT_PROBE1(opencrypto, dev, ioctl, error,
- __LINE__);
- return (EINVAL);
- }
- break;
-#endif
- case CRYPTO_AES_NIST_GMAC:
- switch (sop->mackeylen * 8) {
- case 128:
- thash = &auth_hash_nist_gmac_aes_128;
- break;
- case 192:
- thash = &auth_hash_nist_gmac_aes_192;
- break;
- case 256:
- thash = &auth_hash_nist_gmac_aes_256;
- break;
- default:
- CRYPTDEB("invalid GMAC key length");
- SDT_PROBE1(opencrypto, dev, ioctl, error,
- __LINE__);
- return (EINVAL);
- }
- break;
- case CRYPTO_AES_CCM_CBC_MAC:
- switch (sop->mackeylen) {
- case 16:
- thash = &auth_hash_ccm_cbc_mac_128;
- break;
- case 24:
- thash = &auth_hash_ccm_cbc_mac_192;
- break;
- case 32:
- thash = &auth_hash_ccm_cbc_mac_256;
- break;
- default:
- CRYPTDEB("Invalid CBC MAC key size %d",
- sop->keylen);
- SDT_PROBE1(opencrypto, dev, ioctl,
- error, __LINE__);
- return (EINVAL);
- }
- break;
- case CRYPTO_SHA1:
- thash = &auth_hash_sha1;
- break;
- case CRYPTO_SHA2_224:
- thash = &auth_hash_sha2_224;
- break;
- case CRYPTO_SHA2_256:
- thash = &auth_hash_sha2_256;
- break;
- case CRYPTO_SHA2_384:
- thash = &auth_hash_sha2_384;
- break;
- case CRYPTO_SHA2_512:
- thash = &auth_hash_sha2_512;
- break;
-
- case CRYPTO_NULL_HMAC:
- thash = &auth_hash_null;
- break;
-
- case CRYPTO_BLAKE2B:
- thash = &auth_hash_blake2b;
- break;
- case CRYPTO_BLAKE2S:
- thash = &auth_hash_blake2s;
- break;
-
- default:
- CRYPTDEB("invalid mac");
- SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
- return (EINVAL);
- }
-
- if (txform == NULL && thash == NULL) {
- SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
- return (EINVAL);
- }
-
- memset(&csp, 0, sizeof(csp));
- if (use_outputbuffers)
- csp.csp_flags |= CSP_F_SEPARATE_OUTPUT;
-
- if (sop->cipher == CRYPTO_AES_NIST_GCM_16) {
- switch (sop->mac) {
-#ifdef COMPAT_FREEBSD12
- case CRYPTO_AES_128_NIST_GMAC:
- case CRYPTO_AES_192_NIST_GMAC:
- case CRYPTO_AES_256_NIST_GMAC:
- if (sop->keylen != sop->mackeylen) {
- SDT_PROBE1(opencrypto, dev, ioctl,
- error, __LINE__);
- return (EINVAL);
- }
- break;
-#endif
- case 0:
- break;
- default:
- SDT_PROBE1(opencrypto, dev, ioctl, error,
- __LINE__);
- return (EINVAL);
- }
- csp.csp_mode = CSP_MODE_AEAD;
- } else if (sop->cipher == CRYPTO_AES_CCM_16) {
- switch (sop->mac) {
-#ifdef COMPAT_FREEBSD12
- case CRYPTO_AES_CCM_CBC_MAC:
- if (sop->keylen != sop->mackeylen) {
- SDT_PROBE1(opencrypto, dev, ioctl,
- error, __LINE__);
- return (EINVAL);
- }
- thash = NULL;
- break;
-#endif
- case 0:
- break;
- default:
- SDT_PROBE1(opencrypto, dev, ioctl, error,
- __LINE__);
- return (EINVAL);
- }
- csp.csp_mode = CSP_MODE_AEAD;
- } else if (txform && thash)
- csp.csp_mode = CSP_MODE_ETA;
- else if (txform)
- csp.csp_mode = CSP_MODE_CIPHER;
- else
- csp.csp_mode = CSP_MODE_DIGEST;
-
- switch (csp.csp_mode) {
- case CSP_MODE_AEAD:
- case CSP_MODE_ETA:
- if (use_separate_aad)
- csp.csp_flags |= CSP_F_SEPARATE_AAD;
- break;
- }
-
- if (txform) {
- csp.csp_cipher_alg = txform->type;
- csp.csp_cipher_klen = sop->keylen;
- if (sop->keylen > txform->maxkey ||
- sop->keylen < txform->minkey) {
- CRYPTDEB("invalid cipher parameters");
- error = EINVAL;
- SDT_PROBE1(opencrypto, dev, ioctl, error,
- __LINE__);
- goto bail;
- }
-
- key = malloc(csp.csp_cipher_klen, M_XDATA, M_WAITOK);
- error = copyin(sop->key, key, csp.csp_cipher_klen);
- if (error) {
- CRYPTDEB("invalid key");
- SDT_PROBE1(opencrypto, dev, ioctl, error,
- __LINE__);
- goto bail;
- }
- csp.csp_cipher_key = key;
- csp.csp_ivlen = txform->ivsize;
- }
-
- if (thash) {
- csp.csp_auth_alg = thash->type;
- csp.csp_auth_klen = sop->mackeylen;
- if (sop->mackeylen > thash->keysize ||
- sop->mackeylen < 0) {
- CRYPTDEB("invalid mac key length");
- error = EINVAL;
- SDT_PROBE1(opencrypto, dev, ioctl, error,
- __LINE__);
- goto bail;
- }
-
- if (csp.csp_auth_klen) {
- mackey = malloc(csp.csp_auth_klen, M_XDATA,
- M_WAITOK);
- error = copyin(sop->mackey, mackey,
- csp.csp_auth_klen);
- if (error) {
- CRYPTDEB("invalid mac key");
- SDT_PROBE1(opencrypto, dev, ioctl,
- error, __LINE__);
- goto bail;
- }
- csp.csp_auth_key = mackey;
- }
-
- if (csp.csp_auth_alg == CRYPTO_AES_NIST_GMAC)
- csp.csp_ivlen = AES_GCM_IV_LEN;
- if (csp.csp_auth_alg == CRYPTO_AES_CCM_CBC_MAC)
- csp.csp_ivlen = AES_CCM_IV_LEN;
- }
-
- crid = sop->crid;
- error = checkforsoftware(&crid);
- if (error) {
- CRYPTDEB("checkforsoftware");
- SDT_PROBE1(opencrypto, dev, ioctl, error,
- __LINE__);
- goto bail;
- }
- error = crypto_newsession(&cses, &csp, crid);
- if (error) {
- CRYPTDEB("crypto_newsession");
- SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
- goto bail;
- }
-
- cse = csecreate(fcr, cses, &csp, txform, key, thash, mackey);
-
- if (cse == NULL) {
- crypto_freesession(cses);
- error = EINVAL;
- SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
- CRYPTDEB("csecreate");
- goto bail;
- }
- sop->ses = cse->ses;
-
- /* return hardware/driver id */
- sop->crid = crypto_ses2hid(cse->cses);
-bail:
- if (error) {
- free(key, M_XDATA);
- free(mackey, M_XDATA);
- }
-
+ error = cryptodev_create_session(fcr, sop);
if (cmd == CIOCGSESSION && error == 0)
session2_op_to_op(sop, data);
break;