Changeset View
Changeset View
Standalone View
Standalone View
sys/opencrypto/crypto.c
/*- | /*- | ||||
* Copyright (c) 2002-2006 Sam Leffler. All rights reserved. | * Copyright (c) 2002-2006 Sam Leffler. All rights reserved. | ||||
* Copyright (c) 2021 The FreeBSD Foundation | |||||
* | * | ||||
* Portions of this software were developed by Ararat River | |||||
* Consulting, LLC under sponsorship of the FreeBSD Foundation. | |||||
* | |||||
* Redistribution and use in source and binary forms, with or without | * Redistribution and use in source and binary forms, with or without | ||||
* modification, are permitted provided that the following conditions | * modification, are permitted provided that the following conditions | ||||
* are met: | * are met: | ||||
* 1. Redistributions of source code must retain the above copyright | * 1. Redistributions of source code must retain the above copyright | ||||
* notice, this list of conditions and the following disclaimer. | * notice, this list of conditions and the following disclaimer. | ||||
* 2. Redistributions in binary form must reproduce the above copyright | * 2. Redistributions in binary form must reproduce the above copyright | ||||
* notice, this list of conditions and the following disclaimer in the | * notice, this list of conditions and the following disclaimer in the | ||||
* documentation and/or other materials provided with the distribution. | * documentation and/or other materials provided with the distribution. | ||||
▲ Show 20 Lines • Show All 696 Lines • ▼ Show 20 Lines | |||||
static bool | static bool | ||||
alg_is_aead(int alg) | alg_is_aead(int alg) | ||||
{ | { | ||||
return (alg_type(alg) == ALG_AEAD); | return (alg_type(alg) == ALG_AEAD); | ||||
} | } | ||||
static bool | |||||
ccm_tag_length_valid(int len) | |||||
{ | |||||
/* RFC 3610 */ | |||||
switch (len) { | |||||
case 4: | |||||
case 6: | |||||
case 8: | |||||
case 10: | |||||
case 12: | |||||
case 14: | |||||
case 16: | |||||
return (true); | |||||
default: | |||||
return (false); | |||||
} | |||||
} | |||||
#define SUPPORTED_SES (CSP_F_SEPARATE_OUTPUT | CSP_F_SEPARATE_AAD | CSP_F_ESN) | #define SUPPORTED_SES (CSP_F_SEPARATE_OUTPUT | CSP_F_SEPARATE_AAD | CSP_F_ESN) | ||||
/* Various sanity checks on crypto session parameters. */ | /* Various sanity checks on crypto session parameters. */ | ||||
static bool | static bool | ||||
check_csp(const struct crypto_session_params *csp) | check_csp(const struct crypto_session_params *csp) | ||||
{ | { | ||||
const struct auth_hash *axf; | const struct auth_hash *axf; | ||||
▲ Show 20 Lines • Show All 41 Lines • ▼ Show 20 Lines | check_csp(const struct crypto_session_params *csp) | ||||
case CSP_MODE_DIGEST: | case CSP_MODE_DIGEST: | ||||
if (csp->csp_cipher_alg != 0 || csp->csp_cipher_klen != 0) | if (csp->csp_cipher_alg != 0 || csp->csp_cipher_klen != 0) | ||||
return (false); | return (false); | ||||
if (csp->csp_flags & CSP_F_SEPARATE_AAD) | if (csp->csp_flags & CSP_F_SEPARATE_AAD) | ||||
return (false); | return (false); | ||||
/* IV is optional for digests (e.g. GMAC). */ | /* IV is optional for digests (e.g. GMAC). */ | ||||
if (csp->csp_ivlen >= EALG_MAX_BLOCK_LEN) | switch (csp->csp_auth_alg) { | ||||
case CRYPTO_AES_CCM_CBC_MAC: | |||||
if (csp->csp_ivlen < 7 || csp->csp_ivlen > 13) | |||||
return (false); | return (false); | ||||
break; | |||||
case CRYPTO_AES_NIST_GMAC: | |||||
if (csp->csp_ivlen != AES_GCM_IV_LEN) | |||||
return (false); | |||||
break; | |||||
default: | |||||
if (csp->csp_ivlen != 0) | |||||
return (false); | |||||
break; | |||||
} | |||||
if (!alg_is_digest(csp->csp_auth_alg)) | if (!alg_is_digest(csp->csp_auth_alg)) | ||||
return (false); | return (false); | ||||
/* Key is optional for BLAKE2 digests. */ | /* Key is optional for BLAKE2 digests. */ | ||||
if (csp->csp_auth_alg == CRYPTO_BLAKE2B || | if (csp->csp_auth_alg == CRYPTO_BLAKE2B || | ||||
csp->csp_auth_alg == CRYPTO_BLAKE2S) | csp->csp_auth_alg == CRYPTO_BLAKE2S) | ||||
; | ; | ||||
else if (alg_is_keyed_digest(csp->csp_auth_alg)) { | else if (alg_is_keyed_digest(csp->csp_auth_alg)) { | ||||
if (csp->csp_auth_klen == 0) | if (csp->csp_auth_klen == 0) | ||||
return (false); | return (false); | ||||
} else { | } else { | ||||
if (csp->csp_auth_klen != 0) | if (csp->csp_auth_klen != 0) | ||||
return (false); | return (false); | ||||
} | } | ||||
if (csp->csp_auth_mlen != 0) { | if (csp->csp_auth_mlen != 0) { | ||||
axf = crypto_auth_hash(csp); | axf = crypto_auth_hash(csp); | ||||
if (axf == NULL || csp->csp_auth_mlen > axf->hashsize) | if (axf == NULL || csp->csp_auth_mlen > axf->hashsize) | ||||
return (false); | return (false); | ||||
if (csp->csp_auth_alg == CRYPTO_AES_CCM_CBC_MAC && | |||||
!ccm_tag_length_valid(csp->csp_auth_mlen)) | |||||
return (false); | |||||
} | } | ||||
break; | break; | ||||
case CSP_MODE_AEAD: | case CSP_MODE_AEAD: | ||||
if (!alg_is_aead(csp->csp_cipher_alg)) | if (!alg_is_aead(csp->csp_cipher_alg)) | ||||
return (false); | return (false); | ||||
if (csp->csp_cipher_klen == 0) | if (csp->csp_cipher_klen == 0) | ||||
return (false); | return (false); | ||||
if (csp->csp_ivlen == 0 || | if (csp->csp_ivlen == 0 || | ||||
csp->csp_ivlen >= EALG_MAX_BLOCK_LEN) | csp->csp_ivlen >= EALG_MAX_BLOCK_LEN) | ||||
return (false); | return (false); | ||||
if (csp->csp_auth_alg != 0 || csp->csp_auth_klen != 0) | if (csp->csp_auth_alg != 0 || csp->csp_auth_klen != 0) | ||||
return (false); | return (false); | ||||
/* | |||||
* XXX: Would be nice to have a better way to get this | |||||
* value. | |||||
*/ | |||||
switch (csp->csp_cipher_alg) { | switch (csp->csp_cipher_alg) { | ||||
case CRYPTO_AES_NIST_GCM_16: | |||||
case CRYPTO_AES_CCM_16: | case CRYPTO_AES_CCM_16: | ||||
if (csp->csp_auth_mlen != 0 && | |||||
!ccm_tag_length_valid(csp->csp_auth_mlen)) | |||||
return (false); | |||||
if (csp->csp_ivlen < 7 || csp->csp_ivlen > 13) | |||||
return (false); | |||||
break; | |||||
case CRYPTO_AES_NIST_GCM_16: | |||||
case CRYPTO_CHACHA20_POLY1305: | case CRYPTO_CHACHA20_POLY1305: | ||||
if (csp->csp_auth_mlen > 16) | if (csp->csp_auth_mlen > 16) | ||||
return (false); | return (false); | ||||
break; | break; | ||||
} | } | ||||
break; | break; | ||||
case CSP_MODE_ETA: | case CSP_MODE_ETA: | ||||
if (!alg_is_cipher(csp->csp_cipher_alg)) | if (!alg_is_cipher(csp->csp_cipher_alg)) | ||||
▲ Show 20 Lines • Show All 1,098 Lines • Show Last 20 Lines |