krb5: Restore 1DES and 3DES

This commit is contained in:
Nicolas Williams
2026-01-10 23:32:45 -06:00
parent cbe156d927
commit dafe6323fb
24 changed files with 1278 additions and 30 deletions

View File

@@ -171,4 +171,51 @@ fi
AC_SUBST(INCLUDE_openssl_crypto)
AC_SUBST(LIB_openssl_crypto)
dnl
dnl Legacy/weak encryption type options
dnl
dnl Single DES (weak crypto) - disabled by default for security
AC_ARG_WITH([1des],
AS_HELP_STRING([--with-1des], [enable single DES encryption (weak, for legacy compatibility)]),
[with_1des=$withval],
[with_1des=no])
AC_MSG_CHECKING([whether to enable single DES encryption])
if test "$with_1des" = "yes"; then
AC_DEFINE([HEIM_WEAK_CRYPTO], 1, [Define to enable single DES encryption support])
AC_MSG_RESULT([yes])
else
AC_MSG_RESULT([no])
fi
AM_CONDITIONAL([HEIM_WEAK_CRYPTO], [test "$with_1des" = "yes"])
dnl Triple DES - enabled by default for legacy compatibility
AC_ARG_WITH([3des],
AS_HELP_STRING([--with-3des], [enable triple DES encryption (default: yes)]),
[with_3des=$withval],
[with_3des=yes])
AC_MSG_CHECKING([whether to enable triple DES encryption])
if test "$with_3des" = "yes"; then
AC_DEFINE([HEIM_DES3], 1, [Define to enable triple DES encryption support])
AC_MSG_RESULT([yes])
else
AC_MSG_RESULT([no])
fi
AM_CONDITIONAL([HEIM_DES3], [test "$with_3des" = "yes"])
dnl ARCFOUR/RC4 - enabled by default (still used by some Windows systems)
AC_ARG_WITH([arcfour],
AS_HELP_STRING([--with-arcfour], [enable ARCFOUR/RC4 encryption (default: yes)]),
[with_arcfour=$withval],
[with_arcfour=yes])
AC_MSG_CHECKING([whether to enable ARCFOUR encryption])
if test "$with_arcfour" = "yes"; then
AC_DEFINE([HEIM_ARCFOUR], 1, [Define to enable ARCFOUR/RC4 encryption support])
AC_MSG_RESULT([yes])
else
AC_MSG_RESULT([no])
fi
AM_CONDITIONAL([HEIM_ARCFOUR], [test "$with_arcfour" = "yes"])
])

View File

@@ -130,7 +130,7 @@ AC_SUBST([SLC_DEP])
dnl ---
AC_DEFINE(HEIM_WEAK_CRYPTO, 1, [Define if you want support for weak crypto])
dnl HEIM_WEAK_CRYPTO is now controlled by --with-1des in cf/crypto.m4
rk_TEST_PACKAGE(openldap,
[#include <lber.h>

View File

@@ -62,6 +62,9 @@ while(<>) {
if ("$(KRB5)") { print "#define KRB5 1\n"; }
if ("$(KRB4)") { print "#define KRB4 1\n"; }
if ("$(WEAK_CRYPTO)") { print "#define HEIM_WEAK_CRYPTO 1\n"; }
# Always enable 3DES and ARCFOUR for Windows builds (needed for interop)
print "#define HEIM_DES3 1\n";
print "#define HEIM_ARCFOUR 1\n";
if ("$(PKINIT)") { print "#define PKINIT 1\n"; }
if ("$(NO_AFS)") { print "#define NO_AFS 1\n"; }
if ("$(OPENLDAP)") { print "#define OPENLDAP 1\n"; }

Binary file not shown.

Binary file not shown.

View File

@@ -144,6 +144,7 @@ dist_libkrb5_la_SOURCES = \
creds.c \
crypto-des-common.c \
crypto-des.c \
crypto-des3.c \
crypto.c \
crypto.h \
crypto-aes-sha1.c \
@@ -230,6 +231,8 @@ dist_libkrb5_la_SOURCES = \
salt-aes-sha1.c \
salt-aes-sha2.c \
salt-arcfour.c \
salt-des.c \
salt-des3.c \
sp800-108-kdf.c \
scache.c \
send_to_kdc.c \
@@ -291,6 +294,7 @@ librfc3961_la_SOURCES = \
crc.c \
crypto-des-common.c \
crypto-des.c \
crypto-des3.c \
crypto.c \
crypto.h \
crypto-aes-sha1.c \
@@ -311,6 +315,8 @@ librfc3961_la_SOURCES = \
salt-aes-sha1.c \
salt-aes-sha2.c \
salt-arcfour.c \
salt-des.c \
salt-des3.c \
sp800-108-kdf.c \
store-int.c \
warn.c

View File

@@ -64,6 +64,7 @@ libkrb5_OBJS = \
$(OBJ)\crypto-arcfour.obj \
$(OBJ)\crypto-des-common.obj \
$(OBJ)\crypto-des.obj \
$(OBJ)\crypto-des3.obj \
$(OBJ)\crypto-evp.obj \
$(OBJ)\crypto-null.obj \
$(OBJ)\crypto-pk.obj \
@@ -139,6 +140,8 @@ libkrb5_OBJS = \
$(OBJ)\salt-aes-sha1.obj \
$(OBJ)\salt-aes-sha2.obj \
$(OBJ)\salt-arcfour.obj \
$(OBJ)\salt-des.obj \
$(OBJ)\salt-des3.obj \
$(OBJ)\salt.obj \
$(OBJ)\scache.obj \
$(OBJ)\send_to_kdc.obj \
@@ -221,6 +224,7 @@ dist_libkrb5_la_SOURCES = \
crypto-algs.c \
crypto-arcfour.c \
crypto-des.c \
crypto-des3.c \
crypto-des-common.c \
crypto-evp.c \
crypto-pk.c \
@@ -298,6 +302,8 @@ dist_libkrb5_la_SOURCES = \
salt-aes-sha1.c \
salt-aes-sha2.c \
salt-arcfour.c \
salt-des.c \
salt-des3.c \
scache.c \
send_to_kdc.c \
sendauth.c \
@@ -389,6 +395,7 @@ librfc3961_OBJS=\
$(OBJ)\crypto-algs.obj \
$(OBJ)\crypto-arcfour.obj \
$(OBJ)\crypto-des.obj \
$(OBJ)\crypto-des3.obj \
$(OBJ)\crypto-des-common.obj \
$(OBJ)\crypto-evp.obj \
$(OBJ)\crypto-null.obj \
@@ -403,6 +410,8 @@ librfc3961_OBJS=\
$(OBJ)\salt-aes-sha1.obj \
$(OBJ)\salt-aes-sha2.obj \
$(OBJ)\salt-arcfour.obj \
$(OBJ)\salt-des.obj \
$(OBJ)\salt-des3.obj \
$(OBJ)\sp800-108-kdf.obj \
$(OBJ)\store-int.obj \
$(OBJ)\warn.obj

View File

@@ -177,7 +177,10 @@ make_openssl_context(krb5_context context,
ossl->aes128_cts = EVP_CIPHER_fetch(ossl->libctx, "AES-128-CBC-CTS", ossl->propq);
ossl->aes192_cts = EVP_CIPHER_fetch(ossl->libctx, "AES-192-CBC-CTS", ossl->propq);
ossl->aes256_cts = EVP_CIPHER_fetch(ossl->libctx, "AES-256-CBC-CTS", ossl->propq);
ossl->des_cbc = EVP_CIPHER_fetch(ossl->libctx, "DES-CBC", ossl->propq);
ossl->des_ede3_cbc = EVP_CIPHER_fetch(ossl->libctx, "DES-EDE3-CBC", ossl->propq);
ossl->hmac = EVP_MAC_fetch(ossl->libctx, "HMAC", ossl->propq);
ossl->md4 = EVP_MD_fetch(ossl->libctx, "MD4", ossl->propq);
ossl->md5 = EVP_MD_fetch(ossl->libctx, "MD5", ossl->propq);
ossl->sha1 = EVP_MD_fetch(ossl->libctx, "SHA1", ossl->propq);
ossl->sha256 = EVP_MD_fetch(ossl->libctx, "SHA256", ossl->propq);
@@ -204,7 +207,10 @@ free_openssl(krb5_context_ossl *osslp)
EVP_CIPHER_free(p->aes128_cts);
EVP_CIPHER_free(p->aes192_cts);
EVP_CIPHER_free(p->aes256_cts);
EVP_CIPHER_free(p->des_cbc);
EVP_CIPHER_free(p->des_ede3_cbc);
EVP_MAC_free(p->hmac);
EVP_MD_free(p->md4);
EVP_MD_free(p->md5);
EVP_MD_free(p->sha1);
EVP_MD_free(p->sha256);

View File

@@ -33,14 +33,19 @@
#include "krb5_locl.h"
#ifndef HEIMDAL_SMALLER
#define DES3_OLD_ENCTYPE 1
#endif
struct _krb5_checksum_type *_krb5_checksum_types[] = {
&_krb5_checksum_none,
#ifdef HEIM_WEAK_CRYPTO
&_krb5_checksum_crc32,
&_krb5_checksum_rsa_md4,
&_krb5_checksum_rsa_md4_des,
&_krb5_checksum_rsa_md5_des,
#endif
#ifdef HEIM_DES3
&_krb5_checksum_rsa_md5_des3,
#endif
#if defined(HEIM_DES3) || defined(HEIM_WEAK_CRYPTO)
&_krb5_checksum_hmac_sha1_des3,
#endif
&_krb5_checksum_rsa_md5,
&_krb5_checksum_sha1,
@@ -48,7 +53,9 @@ struct _krb5_checksum_type *_krb5_checksum_types[] = {
&_krb5_checksum_hmac_sha1_aes256,
&_krb5_checksum_hmac_sha256_128_aes128,
&_krb5_checksum_hmac_sha384_192_aes256,
#ifdef HEIM_ARCFOUR
&_krb5_checksum_hmac_md5,
#endif
&_krb5_checksum_sha256,
&_krb5_checksum_sha384,
&_krb5_checksum_sha512
@@ -66,7 +73,25 @@ struct _krb5_encryption_type *_krb5_etypes[] = {
&_krb5_enctype_aes128_cts_hmac_sha256_128,
&_krb5_enctype_aes256_cts_hmac_sha1,
&_krb5_enctype_aes128_cts_hmac_sha1,
#ifdef HEIM_ARCFOUR
&_krb5_enctype_arcfour_hmac_md5,
#endif
#if defined(HEIM_DES3) || defined(HEIM_WEAK_CRYPTO)
&_krb5_enctype_des3_cbc_sha1,
&_krb5_enctype_des3_cbc_none,
#endif
#ifdef HEIM_DES3
&_krb5_enctype_des3_cbc_md5,
&_krb5_enctype_old_des3_cbc_sha1,
#endif
#ifdef HEIM_WEAK_CRYPTO
&_krb5_enctype_des_cbc_crc,
&_krb5_enctype_des_cbc_md4,
&_krb5_enctype_des_cbc_md5,
&_krb5_enctype_des_cbc_none,
&_krb5_enctype_des_cfb64_none,
&_krb5_enctype_des_pcbc_none,
#endif
&_krb5_enctype_null
};

View File

@@ -37,6 +37,8 @@
#include "krb5_locl.h"
#ifdef HEIM_ARCFOUR
static EVP_CIPHER *
heim_EVP_rc4(krb5_context context)
{
@@ -406,3 +408,5 @@ struct _krb5_encryption_type _krb5_enctype_arcfour_hmac_md5 = {
0,
ARCFOUR_prf
};
#endif /* HEIM_ARCFOUR */

View File

@@ -31,6 +31,8 @@
* SUCH DAMAGE.
*/
/* Functions which are used by both single and triple DES enctypes */
#include "krb5_locl.h"
/*
@@ -50,6 +52,114 @@ _krb5_xor8(unsigned char *a, const unsigned char *b)
a[7] ^= b[7];
}
#if defined(HEIM_DES3) || defined(HEIM_WEAK_CRYPTO)
KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
_krb5_des_checksum(krb5_context context,
const EVP_MD *evp_md,
struct _krb5_key_data *key,
const struct krb5_crypto_iov *iov,
int niov,
Checksum *cksum)
{
struct _krb5_evp_schedule *ctx = key->schedule->data;
EVP_MD_CTX *m;
DES_cblock ivec;
int i;
unsigned char *p = cksum->checksum.data;
if (evp_md == NULL) {
krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
"1DES not supported");
return KRB5_PROG_ETYPE_NOSUPP;
}
krb5_generate_random_block(p, 8);
m = EVP_MD_CTX_new();
if (m == NULL)
return krb5_enomem(context);
if (EVP_DigestInit_ex(m, evp_md, NULL) != 1 ||
EVP_DigestUpdate(m, p, 8) != 1)
goto err;
for (i = 0; i < niov; i++) {
if (_krb5_crypto_iov_should_sign(&iov[i]) &&
EVP_DigestUpdate(m, iov[i].data.data, iov[i].data.length) != 1)
goto err;
}
if (EVP_DigestFinal_ex(m, p + 8, NULL) != 1)
goto err;
EVP_MD_CTX_free(m);
memset_s(&ivec, sizeof(ivec), 0, sizeof(ivec));
if (EVP_CipherInit_ex(ctx->ectx, NULL, NULL, NULL, (void *)&ivec, -1) != 1 ||
EVP_Cipher(ctx->ectx, p, p, 24) < 0)
return KRB5_CRYPTO_INTERNAL;
return 0;
err:
EVP_MD_CTX_free(m);
return KRB5_CRYPTO_INTERNAL;
}
KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
_krb5_des_verify(krb5_context context,
const EVP_MD *evp_md,
struct _krb5_key_data *key,
const struct krb5_crypto_iov *iov,
int niov,
Checksum *C)
{
struct _krb5_evp_schedule *ctx = key->schedule->data;
EVP_MD_CTX *m;
unsigned char tmp[24];
unsigned char res[16];
DES_cblock ivec;
krb5_error_code ret = 0;
int i;
if (evp_md == NULL) {
krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
"1DES not supported");
return KRB5_PROG_ETYPE_NOSUPP;
}
m = EVP_MD_CTX_new();
if (m == NULL)
return krb5_enomem(context);
memset_s(&ivec, sizeof(ivec), 0, sizeof(ivec));
if (EVP_CipherInit_ex(ctx->dctx, NULL, NULL, NULL, (void *)&ivec, -1) != 1 ||
EVP_Cipher(ctx->dctx, tmp, C->checksum.data, 24) < 0)
goto err;
if (EVP_DigestInit_ex(m, evp_md, NULL) != 1 ||
EVP_DigestUpdate(m, tmp, 8) != 1) /* confounder */
goto err;
for (i = 0; i < niov; i++) {
if (_krb5_crypto_iov_should_sign(&iov[i]) &&
EVP_DigestUpdate(m, iov[i].data.data, iov[i].data.length) != 1)
goto err;
}
if (EVP_DigestFinal_ex(m, res, NULL) != 1)
goto err;
EVP_MD_CTX_free(m);
if(ct_memcmp(res, tmp + 8, sizeof(res)) != 0) {
krb5_clear_error_message (context);
ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
}
memset_s(tmp, sizeof(tmp), 0, sizeof(tmp));
memset_s(res, sizeof(res), 0, sizeof(res));
return ret;
err:
EVP_MD_CTX_free(m);
memset_s(tmp, sizeof(tmp), 0, sizeof(tmp));
return KRB5_CRYPTO_INTERNAL;
}
#endif
static krb5_error_code
RSA_MD5_checksum(krb5_context context,
krb5_crypto crypto,
@@ -60,7 +170,7 @@ RSA_MD5_checksum(krb5_context context,
Checksum *C)
{
if (_krb5_evp_digest_iov(crypto, iov, niov, C->checksum.data,
NULL, EVP_md5(), NULL) != 1)
NULL, context->ossl->md5, NULL) != 1)
krb5_abortx(context, "md5 checksum failed");
return 0;

View File

@@ -31,10 +31,84 @@
* SUCH DAMAGE.
*/
/*
* Suppress OpenSSL deprecation warnings - we need these legacy DES functions
* for backward compatibility with old Kerberos encryption types.
*/
#define OPENSSL_SUPPRESS_DEPRECATED
#include "krb5_locl.h"
#ifdef HEIM_WEAK_CRYPTO
static void
krb5_DES_random_key(krb5_context context,
krb5_keyblock *key)
{
DES_cblock *k = key->keyvalue.data;
do {
krb5_generate_random_block(k, sizeof(DES_cblock));
DES_set_odd_parity(k);
} while(DES_is_weak_key(k));
}
static int
krb5_DES_schedule_old(krb5_context context,
struct _krb5_key_type *kt,
struct _krb5_key_data *key)
{
DES_set_key_unchecked(key->key->keyvalue.data, key->schedule->data);
return 0;
}
static void
krb5_DES_random_to_key(krb5_context context,
krb5_keyblock *key,
const void *data,
size_t size)
{
DES_cblock *k = key->keyvalue.data;
memcpy(k, data, key->keyvalue.length);
DES_set_odd_parity(k);
if(DES_is_weak_key(k))
_krb5_xor8(*k, (const unsigned char*)"\0\0\0\0\0\0\0\xf0");
}
static struct _krb5_key_type keytype_des_old = {
ETYPE_DES_CBC_CRC,
"des-old",
56,
8,
sizeof(DES_key_schedule),
krb5_DES_random_key,
krb5_DES_schedule_old,
_krb5_des_salt,
krb5_DES_random_to_key,
NULL,
NULL
};
static EVP_CIPHER *
_krb5_evp_des_cbc(krb5_context context)
{
return context->ossl->des_cbc;
}
static struct _krb5_key_type keytype_des = {
ETYPE_DES_CBC_CRC,
"des",
56,
8,
sizeof(struct _krb5_evp_schedule),
krb5_DES_random_key,
_krb5_evp_schedule,
_krb5_des_salt,
krb5_DES_random_to_key,
_krb5_evp_cleanup,
_krb5_evp_des_cbc
};
static krb5_error_code
CRC32_checksum(krb5_context context,
krb5_crypto crypto,
@@ -72,11 +146,59 @@ RSA_MD4_checksum(krb5_context context,
Checksum *C)
{
if (_krb5_evp_digest_iov(crypto, iov, niov, C->checksum.data,
NULL, EVP_md4(), NULL) != 1)
NULL, context->ossl->md4, NULL) != 1)
krb5_abortx(context, "md4 checksum failed");
return 0;
}
static krb5_error_code
RSA_MD4_DES_checksum(krb5_context context,
krb5_crypto crypto,
struct _krb5_key_data *key,
unsigned usage,
const struct krb5_crypto_iov *iov,
int niov,
Checksum *cksum)
{
return _krb5_des_checksum(context, context->ossl->md4, key, iov, niov, cksum);
}
static krb5_error_code
RSA_MD4_DES_verify(krb5_context context,
krb5_crypto crypto,
struct _krb5_key_data *key,
unsigned usage,
const struct krb5_crypto_iov *iov,
int niov,
Checksum *C)
{
return _krb5_des_verify(context, context->ossl->md4, key, iov, niov, C);
}
static krb5_error_code
RSA_MD5_DES_checksum(krb5_context context,
krb5_crypto crypto,
struct _krb5_key_data *key,
unsigned usage,
const struct krb5_crypto_iov *iov,
int niov,
Checksum *C)
{
return _krb5_des_checksum(context, context->ossl->md5, key, iov, niov, C);
}
static krb5_error_code
RSA_MD5_DES_verify(krb5_context context,
krb5_crypto crypto,
struct _krb5_key_data *key,
unsigned usage,
const struct krb5_crypto_iov *iov,
int niov,
Checksum *C)
{
return _krb5_des_verify(context, context->ossl->md5, key, iov, niov, C);
}
struct _krb5_checksum_type _krb5_checksum_crc32 = {
CKSUMTYPE_CRC32,
"crc32",
@@ -97,4 +219,200 @@ struct _krb5_checksum_type _krb5_checksum_rsa_md4 = {
NULL
};
struct _krb5_checksum_type _krb5_checksum_rsa_md4_des = {
CKSUMTYPE_RSA_MD4_DES,
"rsa-md4-des",
64,
24,
F_KEYED | F_CPROOF | F_VARIANT,
RSA_MD4_DES_checksum,
RSA_MD4_DES_verify
};
struct _krb5_checksum_type _krb5_checksum_rsa_md5_des = {
CKSUMTYPE_RSA_MD5_DES,
"rsa-md5-des",
64,
24,
F_KEYED | F_CPROOF | F_VARIANT,
RSA_MD5_DES_checksum,
RSA_MD5_DES_verify
};
static krb5_error_code
evp_des_encrypt_null_ivec(krb5_context context,
struct _krb5_key_data *key,
void *data,
size_t len,
krb5_boolean encryptp,
int usage,
void *ignore_ivec)
{
struct _krb5_evp_schedule *ctx = key->schedule->data;
EVP_CIPHER_CTX *c;
DES_cblock ivec;
memset(&ivec, 0, sizeof(ivec));
c = encryptp ? ctx->ectx : ctx->dctx;
if (EVP_CipherInit_ex(c, NULL, NULL, NULL, (void *)&ivec, -1) != 1 ||
EVP_Cipher(c, data, data, len) < 0)
return KRB5_CRYPTO_INTERNAL;
return 0;
}
static krb5_error_code
evp_des_encrypt_key_ivec(krb5_context context,
struct _krb5_key_data *key,
void *data,
size_t len,
krb5_boolean encryptp,
int usage,
void *ignore_ivec)
{
struct _krb5_evp_schedule *ctx = key->schedule->data;
EVP_CIPHER_CTX *c;
DES_cblock ivec;
memcpy(&ivec, key->key->keyvalue.data, sizeof(ivec));
c = encryptp ? ctx->ectx : ctx->dctx;
if (EVP_CipherInit_ex(c, NULL, NULL, NULL, (void *)&ivec, -1) != 1 ||
EVP_Cipher(c, data, data, len) < 0)
return KRB5_CRYPTO_INTERNAL;
return 0;
}
static krb5_error_code
DES_CFB64_encrypt_null_ivec(krb5_context context,
struct _krb5_key_data *key,
void *data,
size_t len,
krb5_boolean encryptp,
int usage,
void *ignore_ivec)
{
DES_cblock ivec;
int num = 0;
DES_key_schedule *s = key->schedule->data;
memset(&ivec, 0, sizeof(ivec));
DES_cfb64_encrypt(data, data, len, s, &ivec, &num, encryptp);
return 0;
}
static krb5_error_code
DES_PCBC_encrypt_key_ivec(krb5_context context,
struct _krb5_key_data *key,
void *data,
size_t len,
krb5_boolean encryptp,
int usage,
void *ignore_ivec)
{
DES_cblock ivec;
DES_key_schedule *s = key->schedule->data;
memcpy(&ivec, key->key->keyvalue.data, sizeof(ivec));
DES_pcbc_encrypt(data, data, len, s, &ivec, encryptp);
return 0;
}
struct _krb5_encryption_type _krb5_enctype_des_cbc_crc = {
ETYPE_DES_CBC_CRC,
"des-cbc-crc",
NULL,
8,
8,
8,
&keytype_des,
&_krb5_checksum_crc32,
NULL,
F_DISABLED|F_WEAK|F_OLD,
evp_des_encrypt_key_ivec,
NULL,
0,
NULL
};
struct _krb5_encryption_type _krb5_enctype_des_cbc_md4 = {
ETYPE_DES_CBC_MD4,
"des-cbc-md4",
NULL,
8,
8,
8,
&keytype_des,
&_krb5_checksum_rsa_md4,
&_krb5_checksum_rsa_md4_des,
F_DISABLED|F_WEAK|F_OLD,
evp_des_encrypt_null_ivec,
NULL,
0,
NULL
};
struct _krb5_encryption_type _krb5_enctype_des_cbc_md5 = {
ETYPE_DES_CBC_MD5,
"des-cbc-md5",
NULL,
8,
8,
8,
&keytype_des,
&_krb5_checksum_rsa_md5,
&_krb5_checksum_rsa_md5_des,
F_DISABLED|F_WEAK|F_OLD,
evp_des_encrypt_null_ivec,
NULL,
0,
NULL
};
struct _krb5_encryption_type _krb5_enctype_des_cbc_none = {
ETYPE_DES_CBC_NONE,
"des-cbc-none",
NULL,
8,
8,
0,
&keytype_des,
&_krb5_checksum_none,
NULL,
F_PSEUDO|F_DISABLED|F_WEAK|F_OLD,
evp_des_encrypt_null_ivec,
NULL,
0,
NULL
};
struct _krb5_encryption_type _krb5_enctype_des_cfb64_none = {
ETYPE_DES_CFB64_NONE,
"des-cfb64-none",
NULL,
1,
1,
0,
&keytype_des_old,
&_krb5_checksum_none,
NULL,
F_PSEUDO|F_DISABLED|F_WEAK|F_OLD,
DES_CFB64_encrypt_null_ivec,
NULL,
0,
NULL
};
struct _krb5_encryption_type _krb5_enctype_des_pcbc_none = {
ETYPE_DES_PCBC_NONE,
"des-pcbc-none",
NULL,
8,
8,
0,
&keytype_des_old,
&_krb5_checksum_none,
NULL,
F_PSEUDO|F_DISABLED|F_WEAK|F_OLD,
DES_PCBC_encrypt_key_ivec,
NULL,
0,
NULL
};
#endif /* HEIM_WEAK_CRYPTO */

339
lib/krb5/crypto-des3.c Normal file
View File

@@ -0,0 +1,339 @@
/*
* Copyright (c) 1997 - 2008 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/*
* Suppress OpenSSL deprecation warnings - we need these legacy DES functions
* for backward compatibility with old Kerberos encryption types.
*/
#define OPENSSL_SUPPRESS_DEPRECATED
#include "krb5_locl.h"
#if defined(HEIM_DES3) || defined(HEIM_WEAK_CRYPTO)
/*
*
*/
static void
DES3_random_key(krb5_context context,
krb5_keyblock *key)
{
DES_cblock *k = key->keyvalue.data;
do {
krb5_generate_random_block(k, 3 * sizeof(DES_cblock));
DES_set_odd_parity(&k[0]);
DES_set_odd_parity(&k[1]);
DES_set_odd_parity(&k[2]);
} while(DES_is_weak_key(&k[0]) ||
DES_is_weak_key(&k[1]) ||
DES_is_weak_key(&k[2]));
}
static krb5_error_code
DES3_prf(krb5_context context,
krb5_crypto crypto,
const krb5_data *in,
krb5_data *out)
{
struct _krb5_checksum_type *ct = crypto->et->checksum;
struct krb5_crypto_iov iov[1];
krb5_error_code ret;
Checksum result;
krb5_keyblock *derived;
result.cksumtype = ct->type;
ret = krb5_data_alloc(&result.checksum, ct->checksumsize);
if (ret) {
krb5_set_error_message(context, ret, N_("malloc: out memory", ""));
return ret;
}
iov[0].data = *in;
iov[0].flags = KRB5_CRYPTO_TYPE_DATA;
ret = (*ct->checksum)(context, crypto, NULL, 0, iov, 1, &result);
if (ret) {
krb5_data_free(&result.checksum);
return ret;
}
if (result.checksum.length < crypto->et->blocksize)
krb5_abortx(context, "internal prf error");
derived = NULL;
ret = krb5_derive_key(context, crypto->key.key,
crypto->et->type, "prf", 3, &derived);
if (ret)
krb5_abortx(context, "krb5_derive_key");
ret = krb5_data_alloc(out, crypto->et->prf_length);
if (ret)
krb5_abortx(context, "malloc failed");
{
const EVP_CIPHER *c = (*crypto->et->keytype->evp)(context);
EVP_CIPHER_CTX *ctx;
unsigned char zero_ivec[EVP_MAX_IV_LENGTH] = { 0 };
if (c == NULL) {
krb5_data_free(out);
krb5_data_free(&result.checksum);
krb5_free_keyblock(context, derived);
krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
"Encryption type not supported: %s",
crypto->et->keytype->name);
return KRB5_PROG_ETYPE_NOSUPP;
}
ctx = EVP_CIPHER_CTX_new();
if (ctx == NULL) {
krb5_data_free(out);
krb5_data_free(&result.checksum);
krb5_free_keyblock(context, derived);
return krb5_enomem(context);
}
if (EVP_CipherInit_ex(ctx, c, NULL, derived->keyvalue.data, zero_ivec, 1) != 1 ||
EVP_Cipher(ctx, out->data, result.checksum.data,
crypto->et->prf_length) < 0) {
EVP_CIPHER_CTX_free(ctx);
krb5_data_free(out);
krb5_data_free(&result.checksum);
krb5_free_keyblock(context, derived);
return KRB5_CRYPTO_INTERNAL;
}
EVP_CIPHER_CTX_free(ctx);
}
krb5_data_free(&result.checksum);
krb5_free_keyblock(context, derived);
return ret;
}
static EVP_CIPHER *
_krb5_evp_des_ede3_cbc(krb5_context context)
{
return context->ossl->des_ede3_cbc;
}
#endif /* HEIM_DES3 || HEIM_WEAK_CRYPTO */
#ifdef HEIM_DES3
static struct _krb5_key_type keytype_des3 = {
ETYPE_OLD_DES3_CBC_SHA1,
"des3",
168,
24,
sizeof(struct _krb5_evp_schedule),
DES3_random_key,
_krb5_evp_schedule,
_krb5_des3_salt,
_krb5_DES3_random_to_key,
_krb5_evp_cleanup,
_krb5_evp_des_ede3_cbc
};
#endif
#if defined(HEIM_DES3) || defined(HEIM_WEAK_CRYPTO)
static struct _krb5_key_type keytype_des3_derived = {
ETYPE_OLD_DES3_CBC_SHA1,
"des3",
168,
24,
sizeof(struct _krb5_evp_schedule),
DES3_random_key,
_krb5_evp_schedule,
_krb5_des3_salt_derived,
_krb5_DES3_random_to_key,
_krb5_evp_cleanup,
_krb5_evp_des_ede3_cbc
};
#endif
#ifdef HEIM_DES3
static krb5_error_code
RSA_MD5_DES3_checksum(krb5_context context,
krb5_crypto crypto,
struct _krb5_key_data *key,
unsigned usage,
const struct krb5_crypto_iov *iov,
int niov,
Checksum *C)
{
return _krb5_des_checksum(context, context->ossl->md5, key, iov, niov, C);
}
static krb5_error_code
RSA_MD5_DES3_verify(krb5_context context,
krb5_crypto crypto,
struct _krb5_key_data *key,
unsigned usage,
const struct krb5_crypto_iov *iov,
int niov,
Checksum *C)
{
return _krb5_des_verify(context, context->ossl->md5, key, iov, niov, C);
}
struct _krb5_checksum_type _krb5_checksum_rsa_md5_des3 = {
CKSUMTYPE_RSA_MD5_DES3,
"rsa-md5-des3",
64,
24,
F_KEYED | F_CPROOF | F_VARIANT,
RSA_MD5_DES3_checksum,
RSA_MD5_DES3_verify
};
#endif
#if defined(HEIM_DES3) || defined(HEIM_WEAK_CRYPTO)
struct _krb5_checksum_type _krb5_checksum_hmac_sha1_des3 = {
CKSUMTYPE_HMAC_SHA1_DES3,
"hmac-sha1-des3",
64,
20,
F_KEYED | F_CPROOF | F_DERIVED,
_krb5_SP_HMAC_SHA1_checksum,
NULL
};
#endif
#ifdef HEIM_DES3
struct _krb5_encryption_type _krb5_enctype_des3_cbc_md5 = {
ETYPE_DES3_CBC_MD5,
"des3-cbc-md5",
NULL,
8,
8,
8,
&keytype_des3,
&_krb5_checksum_rsa_md5,
&_krb5_checksum_rsa_md5_des3,
F_OLD,
_krb5_evp_encrypt,
_krb5_evp_encrypt_iov,
0,
NULL
};
#endif
#if defined(HEIM_DES3) || defined(HEIM_WEAK_CRYPTO)
struct _krb5_encryption_type _krb5_enctype_des3_cbc_sha1 = {
ETYPE_DES3_CBC_SHA1,
"des3-cbc-sha1",
NULL,
8,
8,
8,
&keytype_des3_derived,
&_krb5_checksum_sha1,
&_krb5_checksum_hmac_sha1_des3,
F_DERIVED | F_RFC3961_ENC | F_RFC3961_KDF | F_OLD,
_krb5_evp_encrypt,
_krb5_evp_encrypt_iov,
16,
DES3_prf
};
#endif
#ifdef HEIM_DES3
struct _krb5_encryption_type _krb5_enctype_old_des3_cbc_sha1 = {
ETYPE_OLD_DES3_CBC_SHA1,
"old-des3-cbc-sha1",
NULL,
8,
8,
8,
&keytype_des3,
&_krb5_checksum_sha1,
&_krb5_checksum_hmac_sha1_des3,
F_OLD,
_krb5_evp_encrypt,
_krb5_evp_encrypt_iov,
0,
NULL
};
#endif
#if defined(HEIM_DES3) || defined(HEIM_WEAK_CRYPTO)
struct _krb5_encryption_type _krb5_enctype_des3_cbc_none = {
ETYPE_DES3_CBC_NONE,
"des3-cbc-none",
NULL,
8,
8,
0,
&keytype_des3_derived,
&_krb5_checksum_none,
NULL,
F_PSEUDO | F_OLD,
_krb5_evp_encrypt,
_krb5_evp_encrypt_iov,
0,
NULL
};
#endif
#if defined(HEIM_DES3) || defined(HEIM_WEAK_CRYPTO)
void
_krb5_DES3_random_to_key(krb5_context context,
krb5_keyblock *key,
const void *data,
size_t size)
{
unsigned char *x = key->keyvalue.data;
const u_char *q = data;
DES_cblock *k;
int i, j;
memset(key->keyvalue.data, 0, key->keyvalue.length);
for (i = 0; i < 3; ++i) {
unsigned char foo;
for (j = 0; j < 7; ++j) {
unsigned char b = q[7 * i + j];
x[8 * i + j] = b;
}
foo = 0;
for (j = 6; j >= 0; --j) {
foo |= q[7 * i + j] & 1;
foo <<= 1;
}
x[8 * i + 7] = foo;
}
k = key->keyvalue.data;
for (i = 0; i < 3; i++) {
DES_set_odd_parity(&k[i]);
if(DES_is_weak_key(&k[i]))
_krb5_xor8(k[i], (const unsigned char*)"\0\0\0\0\0\0\0\xf0");
}
}
#endif /* HEIM_DES3 || HEIM_WEAK_CRYPTO */

View File

@@ -248,7 +248,6 @@ _krb5_evp_encrypt(krb5_context context,
{
struct _krb5_evp_schedule *ctx = key->schedule->data;
EVP_CIPHER_CTX *c;
int ret = 0;
c = encryptp ? ctx->ectx : ctx->dctx;
if (ivec == NULL) {
@@ -259,16 +258,18 @@ _krb5_evp_encrypt(krb5_context context,
return krb5_enomem(context);
memset(loiv, 0, len2);
if (EVP_CipherInit_ex(c, NULL, NULL, NULL, loiv, -1) != 1) {
ret = _krb5_set_error_message_openssl(context, KRB5_CRYPTO_INTERNAL,
"Failed to initialize cipher");
free(loiv);
return _krb5_set_error_message_openssl(context, KRB5_CRYPTO_INTERNAL,
"Failed to initialize cipher");
}
free(loiv);
} else if (EVP_CipherInit_ex(c, NULL, NULL, NULL, ivec, -1) != 1) {
ret = _krb5_set_error_message_openssl(context, KRB5_CRYPTO_INTERNAL,
"Failed to initialize cipher");
return _krb5_set_error_message_openssl(context, KRB5_CRYPTO_INTERNAL,
"Failed to initialize cipher");
}
EVP_Cipher(c, data, data, len);
return ret;
if (EVP_Cipher(c, data, data, len) < 0)
return KRB5_CRYPTO_INTERNAL;
return 0;
}
struct _krb5_evp_iov_cursor
@@ -755,7 +756,9 @@ _krb5_evp_encrypt_cts(krb5_context context,
if (encryptp) {
p = data;
i = ((len - 1) / blocksize) * blocksize;
EVP_Cipher(c, p, p, i);
if (EVP_Cipher(c, p, p, i) != (int)i)
return _krb5_set_error_message_openssl(context, EINVAL,
"Failed to encrypt");
p += i - blocksize;
len -= i;
memcpy(ivec2, p, blocksize);
@@ -781,7 +784,9 @@ _krb5_evp_encrypt_cts(krb5_context context,
/* remove last two blocks and round up, decrypt this with cbc, then do cts dance */
i = ((((len - blocksize * 2) + blocksize - 1) / blocksize) * blocksize);
memcpy(ivec2, p + i - blocksize, blocksize);
EVP_Cipher(c, p, p, i);
if (EVP_Cipher(c, p, p, i) != (int)i)
return _krb5_set_error_message_openssl(context, EINVAL,
"Failed to decrypt");
p += i;
len -= i + blocksize;
} else {

View File

@@ -33,10 +33,6 @@
#include "krb5_locl.h"
#ifndef HEIMDAL_SMALLER
#define DES3_OLD_ENCTYPE 1
#endif
static struct _krb5_key_type keytype_null = {
KRB5_ENCTYPE_NULL,
"null",

View File

@@ -39,6 +39,7 @@ KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_init_context(krb5_context *context)
{
krb5_context p;
krb5_context_ossl ossl;
*context = NULL;
@@ -49,6 +50,27 @@ krb5_init_context(krb5_context *context)
if(!p)
return ENOMEM;
/* Initialize minimal OpenSSL context for crypto operations */
ossl = calloc(1, sizeof(*ossl));
if (ossl == NULL) {
free(p);
return ENOMEM;
}
ossl->libctx = OSSL_LIB_CTX_get0_global_default();
ossl->openssl_leg = OSSL_PROVIDER_load(ossl->libctx, "legacy");
ossl->openssl_def = OSSL_PROVIDER_load(ossl->libctx, "default");
ossl->des_cbc = EVP_CIPHER_fetch(ossl->libctx, "DES-CBC", NULL);
ossl->des_ede3_cbc = EVP_CIPHER_fetch(ossl->libctx, "DES-EDE3-CBC", NULL);
ossl->rc4 = EVP_CIPHER_fetch(ossl->libctx, "RC4", NULL);
ossl->aes128_cbc = EVP_CIPHER_fetch(ossl->libctx, "AES-128-CBC", NULL);
ossl->aes256_cbc = EVP_CIPHER_fetch(ossl->libctx, "AES-256-CBC", NULL);
ossl->md4 = EVP_MD_fetch(ossl->libctx, "MD4", NULL);
ossl->md5 = EVP_MD_fetch(ossl->libctx, "MD5", NULL);
ossl->sha1 = EVP_MD_fetch(ossl->libctx, "SHA1", NULL);
ossl->sha256 = EVP_MD_fetch(ossl->libctx, "SHA256", NULL);
ossl->sha384 = EVP_MD_fetch(ossl->libctx, "SHA384", NULL);
p->ossl = ossl;
*context = p;
return 0;
}
@@ -62,6 +84,25 @@ krb5_free_context(krb5_context context)
rk_SOCK_EXIT();
}
/* Clean up OpenSSL context */
if (context->ossl) {
EVP_CIPHER_free(context->ossl->des_cbc);
EVP_CIPHER_free(context->ossl->des_ede3_cbc);
EVP_CIPHER_free(context->ossl->rc4);
EVP_CIPHER_free(context->ossl->aes128_cbc);
EVP_CIPHER_free(context->ossl->aes256_cbc);
EVP_MD_free(context->ossl->md4);
EVP_MD_free(context->ossl->md5);
EVP_MD_free(context->ossl->sha1);
EVP_MD_free(context->ossl->sha256);
EVP_MD_free(context->ossl->sha384);
if (context->ossl->openssl_leg)
OSSL_PROVIDER_unload(context->ossl->openssl_leg);
if (context->ossl->openssl_def)
OSSL_PROVIDER_unload(context->ossl->openssl_def);
free(context->ossl);
}
memset(context, 0, sizeof(*context));
free(context);
}

View File

@@ -39,10 +39,6 @@ struct _krb5_key_usage {
};
#ifndef HEIMDAL_SMALLER
#define DES3_OLD_ENCTYPE 1
#endif
static krb5_error_code _get_derived_key(krb5_context, krb5_crypto,
unsigned, struct _krb5_key_data**);
static struct _krb5_key_data *_new_derived_key(krb5_crypto crypto, unsigned usage);
@@ -2408,7 +2404,20 @@ derive_key_rfc3961(krb5_context context,
}
}
memcpy(key->key->keyvalue.data, k, key->key->keyvalue.length);
/*
* RFC 3961: DK(Key, Constant) = random-to-key(DR(Key, Constant))
*
* For keytypes where bits != size*8 (e.g., DES3: 168 bits, 24 bytes),
* we need to truncate the DR output to bits/8 bytes and apply
* random-to-key to convert to the final key.
*/
if (kt->random_to_key) {
/* Truncate DR output to key-generation-seed-length and apply random-to-key */
(*kt->random_to_key)(context, key->key, k, kt->bits / 8);
} else {
/* For keytypes like AES where bits == size*8, just copy */
memcpy(key->key->keyvalue.data, k, key->key->keyvalue.length);
}
out:
if (k) {

View File

@@ -31,9 +31,12 @@
* SUCH DAMAGE.
*/
#ifndef HEIMDAL_SMALLER
#define DES3_OLD_ENCTYPE 1
#endif
/*
* Legacy encryption type support is controlled by config.h macros:
* HEIM_WEAK_CRYPTO - enables single DES (--with-1des)
* HEIM_DES3 - enables triple DES (--with-3des)
* HEIM_ARCFOUR - enables ARCFOUR/RC4 (--with-arcfour)
*/
struct _krb5_key_data {
krb5_keyblock *key;
@@ -140,7 +143,12 @@ struct _krb5_encryption_type {
extern struct _krb5_checksum_type _krb5_checksum_none;
extern struct _krb5_checksum_type _krb5_checksum_crc32;
extern struct _krb5_checksum_type _krb5_checksum_rsa_md4;
extern struct _krb5_checksum_type _krb5_checksum_rsa_md4_des;
extern struct _krb5_checksum_type _krb5_checksum_rsa_md5;
extern struct _krb5_checksum_type _krb5_checksum_rsa_md5_des;
extern struct _krb5_checksum_type _krb5_checksum_rsa_md5_des3;
extern struct _krb5_checksum_type _krb5_checksum_hmac_sha1_des3;
extern struct _krb5_checksum_type _krb5_checksum_hmac_sha1_aes128;
extern struct _krb5_checksum_type _krb5_checksum_hmac_sha1_aes256;
extern struct _krb5_checksum_type _krb5_checksum_hmac_sha256_128_aes128;
@@ -158,7 +166,16 @@ extern int _krb5_num_checksums;
extern struct salt_type _krb5_AES_SHA1_salt[];
extern struct salt_type _krb5_AES_SHA2_salt[];
#ifdef HEIM_ARCFOUR
extern struct salt_type _krb5_arcfour_salt[];
#endif
#ifdef HEIM_WEAK_CRYPTO
extern struct salt_type _krb5_des_salt[];
#endif
#if defined(HEIM_DES3) || defined(HEIM_WEAK_CRYPTO)
extern struct salt_type _krb5_des3_salt[];
extern struct salt_type _krb5_des3_salt_derived[];
#endif
/* Encryption types */
@@ -166,7 +183,25 @@ extern struct _krb5_encryption_type _krb5_enctype_aes256_cts_hmac_sha1;
extern struct _krb5_encryption_type _krb5_enctype_aes128_cts_hmac_sha1;
extern struct _krb5_encryption_type _krb5_enctype_aes128_cts_hmac_sha256_128;
extern struct _krb5_encryption_type _krb5_enctype_aes256_cts_hmac_sha384_192;
#ifdef HEIM_ARCFOUR
extern struct _krb5_encryption_type _krb5_enctype_arcfour_hmac_md5;
#endif
#if defined(HEIM_DES3) || defined(HEIM_WEAK_CRYPTO)
extern struct _krb5_encryption_type _krb5_enctype_des3_cbc_sha1;
extern struct _krb5_encryption_type _krb5_enctype_des3_cbc_none;
#endif
#ifdef HEIM_DES3
extern struct _krb5_encryption_type _krb5_enctype_des3_cbc_md5;
extern struct _krb5_encryption_type _krb5_enctype_old_des3_cbc_sha1;
#endif
#ifdef HEIM_WEAK_CRYPTO
extern struct _krb5_encryption_type _krb5_enctype_des_cbc_crc;
extern struct _krb5_encryption_type _krb5_enctype_des_cbc_md4;
extern struct _krb5_encryption_type _krb5_enctype_des_cbc_md5;
extern struct _krb5_encryption_type _krb5_enctype_des_cbc_none;
extern struct _krb5_encryption_type _krb5_enctype_des_cfb64_none;
extern struct _krb5_encryption_type _krb5_enctype_des_pcbc_none;
#endif
extern struct _krb5_encryption_type _krb5_enctype_null;
extern struct _krb5_encryption_type *_krb5_etypes[];
@@ -207,3 +242,19 @@ struct krb5_crypto_data {
* key material is available.
*/
#define KRB5_CRYPTO_FLAG_ALLOW_UNKEYED_CHECKSUM 0x01
/* DES/3DES helper functions */
#if defined(HEIM_DES3) || defined(HEIM_WEAK_CRYPTO)
KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
_krb5_des_checksum(krb5_context, const EVP_MD *,
struct _krb5_key_data *,
const struct krb5_crypto_iov *, int,
Checksum *);
KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
_krb5_des_verify(krb5_context, const EVP_MD *,
struct _krb5_key_data *,
const struct krb5_crypto_iov *, int,
Checksum *);
void _krb5_DES3_random_to_key(krb5_context, krb5_keyblock *,
const void *, size_t);
#endif

View File

@@ -298,7 +298,10 @@ struct krb5_context_ossl_data {
EVP_CIPHER *aes128_cts;
EVP_CIPHER *aes192_cts;
EVP_CIPHER *aes256_cts;
EVP_CIPHER *des_cbc;
EVP_CIPHER *des_ede3_cbc;
EVP_MAC *hmac;
EVP_MD *md4;
EVP_MD *md5;
EVP_MD *sha1;
EVP_MD *sha256;

View File

@@ -33,6 +33,8 @@
#include "krb5_locl.h"
#ifdef HEIM_ARCFOUR
static krb5_error_code
ARCFOUR_string_to_key(krb5_context context,
krb5_enctype enctype,
@@ -105,3 +107,5 @@ struct salt_type _krb5_arcfour_salt[] = {
},
{ 0, NULL, NULL }
};
#endif /* HEIM_ARCFOUR */

View File

@@ -31,6 +31,12 @@
* SUCH DAMAGE.
*/
/*
* Suppress OpenSSL deprecation warnings - we need these legacy DES functions
* for backward compatibility with old Kerberos encryption types.
*/
#define OPENSSL_SUPPRESS_DEPRECATED
#include "krb5_locl.h"
#ifdef HEIM_WEAK_CRYPTO

View File

@@ -31,9 +31,15 @@
* SUCH DAMAGE.
*/
/*
* Suppress OpenSSL deprecation warnings - we need these legacy DES functions
* for backward compatibility with old Kerberos encryption types.
*/
#define OPENSSL_SUPPRESS_DEPRECATED
#include "krb5_locl.h"
#ifdef DES3_OLD_ENCTYPE
#ifdef HEIM_DES3
static krb5_error_code
DES3_string_to_key(krb5_context context,
krb5_enctype enctype,
@@ -126,7 +132,7 @@ DES3_string_to_key_derived(krb5_context context,
}
#ifdef DES3_OLD_ENCTYPE
#ifdef HEIM_DES3
struct salt_type _krb5_des3_salt[] = {
{
KRB5_PW_SALT,

View File

@@ -309,8 +309,61 @@ krb5_string_to_key_derived(krb5_context context,
krb5_enctype etype,
krb5_keyblock *key)
{
#if defined(HEIM_DES3) || defined(HEIM_WEAK_CRYPTO)
struct _krb5_encryption_type *et = _krb5_find_enctype(etype);
krb5_error_code ret;
struct _krb5_key_data kd;
size_t keylen;
u_char *tmp;
if(et == NULL) {
krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
N_("encryption type %d not supported", ""),
etype);
return KRB5_PROG_ETYPE_NOSUPP;
}
keylen = et->keytype->bits / 8;
ALLOC(kd.key, 1);
if(kd.key == NULL)
return krb5_enomem(context);
ret = krb5_data_alloc(&kd.key->keyvalue, et->keytype->size);
if(ret) {
free(kd.key);
return ret;
}
kd.key->keytype = etype;
tmp = malloc (keylen);
if(tmp == NULL) {
krb5_free_keyblock(context, kd.key);
return krb5_enomem(context);
}
ret = _krb5_n_fold(str, len, tmp, keylen);
if (ret) {
free(tmp);
krb5_free_keyblock(context, kd.key);
return ret;
}
kd.schedule = NULL;
_krb5_DES3_random_to_key(context, kd.key, tmp, keylen);
memset(tmp, 0, keylen);
free(tmp);
ret = _krb5_derive_key(context,
et,
&kd,
"kerberos",
strlen("kerberos"));
if (ret) {
_krb5_free_key_data(context, &kd, et);
return ret;
}
ret = krb5_copy_keyblock_contents(context, kd.key, key);
_krb5_free_key_data(context, &kd, et);
return ret;
#else
krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
N_("encryption type %d not supported", ""),
etype);
return KRB5_PROG_ETYPE_NOSUPP;
#endif
}

View File

@@ -374,6 +374,211 @@ static struct rfc2202 rfc2202_vectors[] =
}
};
/* RFC 3961 A.2: DES string-to-key test vectors */
struct des_s2k_test {
const char *password;
size_t password_len;
const char *salt;
size_t salt_len;
unsigned char expected_key[8];
};
static struct des_s2k_test rfc3961_des_vectors[] = {
{
"password", 8,
"ATHENA.MIT.EDUraeburn", 21,
{0xcb, 0xc2, 0x2f, 0xae, 0x23, 0x52, 0x98, 0xe3}
},
{
"potatoe", 7,
"WHITEHOUSE.GOVdanny", 19,
{0xdf, 0x3d, 0x32, 0xa7, 0x4f, 0xd9, 0x2a, 0x01}
},
{
/* password: g-clef U+1011E encoded as UTF-8 */
"\xf0\x9d\x84\x9e", 4,
"EXAMPLE.COMpianist", 18,
{0x4f, 0xfb, 0x26, 0xba, 0xb0, 0xcd, 0x94, 0x13}
},
{
/* password: eszett U+00DF encoded as UTF-8 */
"\xc3\x9f", 2,
/* salt: "ATHENA.MIT.EDUJuri" + s-caron(U+0161) + "i" + c-acute(U+0107) */
"ATHENA.MIT.EDUJuri\xc5\xa1i\xc4\x87", 23,
{0x62, 0xc8, 0x1a, 0x52, 0x32, 0xb5, 0xe6, 0x9d}
},
{
/* Weak key fixup test case 1 */
"11119999", 8,
"AAAAAAAA", 8,
{0x98, 0x40, 0x54, 0xd0, 0xf1, 0xa7, 0x3e, 0x31}
},
{
/* Weak key fixup test case 2 */
"NNNN6666", 8,
"FFFFAAAA", 8,
{0xc4, 0xbf, 0x6b, 0x25, 0xad, 0xf7, 0xa4, 0xf8}
}
};
/* RFC 3961 A.4: DES3 string-to-key test vectors */
struct des3_s2k_test {
const char *password;
size_t password_len;
const char *salt;
size_t salt_len;
unsigned char expected_key[24];
};
static struct des3_s2k_test rfc3961_des3_vectors[] = {
{
"password", 8,
"ATHENA.MIT.EDUraeburn", 21,
{0x85, 0x0b, 0xb5, 0x13, 0x58, 0x54, 0x8c, 0xd0,
0x5e, 0x86, 0x76, 0x8c, 0x31, 0x3e, 0x3b, 0xfe,
0xf7, 0x51, 0x19, 0x37, 0xdc, 0xf7, 0x2c, 0x3e}
},
{
"potatoe", 7,
"WHITEHOUSE.GOVdanny", 19,
{0xdf, 0xcd, 0x23, 0x3d, 0xd0, 0xa4, 0x32, 0x04,
0xea, 0x6d, 0xc4, 0x37, 0xfb, 0x15, 0xe0, 0x61,
0xb0, 0x29, 0x79, 0xc1, 0xf7, 0x4f, 0x37, 0x7a}
},
{
"penny", 5,
"EXAMPLE.COMbuckaroo", 19,
{0x6d, 0x2f, 0xcd, 0xf2, 0xd6, 0xfb, 0xbc, 0x3d,
0xdc, 0xad, 0xb5, 0xda, 0x57, 0x10, 0xa2, 0x34,
0x89, 0xb0, 0xd3, 0xb6, 0x9d, 0x5d, 0x9d, 0x4a}
},
{
/* password: eszett U+00DF encoded as UTF-8 */
"\xc3\x9f", 2,
/* salt: "ATHENA.MIT.EDUJuri" + s-caron(U+0161) + "i" + c-acute(U+0107) */
"ATHENA.MIT.EDUJuri\xc5\xa1i\xc4\x87", 23,
{0x16, 0xd5, 0xa4, 0x0e, 0x1c, 0xe3, 0xba, 0xcb,
0x61, 0xb9, 0xdc, 0xe0, 0x04, 0x70, 0x32, 0x4c,
0x83, 0x19, 0x73, 0xa7, 0xb9, 0x52, 0xfe, 0xb0}
},
{
/* password: g-clef U+1011E encoded as UTF-8 */
"\xf0\x9d\x84\x9e", 4,
"EXAMPLE.COMpianist", 18,
{0x85, 0x76, 0x37, 0x26, 0x58, 0x5d, 0xbc, 0x1c,
0xce, 0x6e, 0xc4, 0x3e, 0x1f, 0x75, 0x1f, 0x07,
0xf1, 0xc4, 0xcb, 0xb0, 0x98, 0xf4, 0x0b, 0x19}
}
};
/* RFC 3961 test for DES string-to-key */
static void
test_rfc3961_des_s2k(krb5_context context)
{
size_t num_tests;
size_t i;
krb5_error_code ret;
num_tests = sizeof(rfc3961_des_vectors) / sizeof(rfc3961_des_vectors[0]);
printf("Running %zu RFC3961 DES string-to-key tests\n", num_tests);
krb5_enctype_enable(context, ETYPE_DES_CBC_CRC);
for (i = 0; i < num_tests; i++) {
krb5_keyblock key;
krb5_salt salt;
krb5_data opaque;
salt.salttype = KRB5_PW_SALT;
salt.saltvalue.data = rk_UNCONST(rfc3961_des_vectors[i].salt);
salt.saltvalue.length = rfc3961_des_vectors[i].salt_len;
opaque.data = NULL;
opaque.length = 0;
ret = krb5_string_to_key_salt_opaque(context,
ETYPE_DES_CBC_CRC,
rfc3961_des_vectors[i].password,
salt, opaque, &key);
if (ret)
errx(1, "DES string-to-key failed on test %zu: %d", i + 1, ret);
if (key.keyvalue.length != 8)
errx(1, "DES key length wrong on test %zu: got %zu, expected 8",
i + 1, key.keyvalue.length);
if (memcmp(key.keyvalue.data, rfc3961_des_vectors[i].expected_key, 8) != 0) {
printf("DES test %zu FAILED\n", i + 1);
printf(" Expected: ");
for (size_t j = 0; j < 8; j++)
printf("%02x", rfc3961_des_vectors[i].expected_key[j]);
printf("\n Got: ");
for (size_t j = 0; j < 8; j++)
printf("%02x", ((unsigned char *)key.keyvalue.data)[j]);
printf("\n");
errx(1, "DES key mismatch on test %zu", i + 1);
}
krb5_free_keyblock_contents(context, &key);
printf("DES string-to-key test %zu okay\n", i + 1);
}
}
/* RFC 3961 test for DES3 string-to-key */
static void
test_rfc3961_des3_s2k(krb5_context context)
{
size_t num_tests;
size_t i;
krb5_error_code ret;
num_tests = sizeof(rfc3961_des3_vectors) / sizeof(rfc3961_des3_vectors[0]);
printf("Running %zu RFC3961 DES3 string-to-key tests\n", num_tests);
krb5_enctype_enable(context, ETYPE_DES3_CBC_SHA1);
for (i = 0; i < num_tests; i++) {
krb5_keyblock key;
krb5_salt salt;
krb5_data opaque;
salt.salttype = KRB5_PW_SALT;
salt.saltvalue.data = rk_UNCONST(rfc3961_des3_vectors[i].salt);
salt.saltvalue.length = rfc3961_des3_vectors[i].salt_len;
opaque.data = NULL;
opaque.length = 0;
ret = krb5_string_to_key_salt_opaque(context,
ETYPE_DES3_CBC_SHA1,
rfc3961_des3_vectors[i].password,
salt, opaque, &key);
if (ret)
errx(1, "DES3 string-to-key failed on test %zu: %d", i + 1, ret);
if (key.keyvalue.length != 24)
errx(1, "DES3 key length wrong on test %zu: got %zu, expected 24",
i + 1, key.keyvalue.length);
if (memcmp(key.keyvalue.data, rfc3961_des3_vectors[i].expected_key, 24) != 0) {
printf("DES3 test %zu FAILED\n", i + 1);
printf(" Expected: ");
for (size_t j = 0; j < 24; j++)
printf("%02x", rfc3961_des3_vectors[i].expected_key[j]);
printf("\n Got: ");
for (size_t j = 0; j < 24; j++)
printf("%02x", ((unsigned char *)key.keyvalue.data)[j]);
printf("\n");
errx(1, "DES3 key mismatch on test %zu", i + 1);
}
krb5_free_keyblock_contents(context, &key);
printf("DES3 string-to-key test %zu okay\n", i + 1);
}
}
/* RFC 2202 test vectors for HMAC-SHA1 */
static void
test_rfc2202(krb5_context context)
@@ -474,6 +679,8 @@ main(int argc, char **argv)
errx (1, "krb5_init_context failed: %d", ret);
test_rfc2202(context);
test_rfc3961_des_s2k(context);
test_rfc3961_des3_s2k(context);
enciter = 1000;
hmaciter = 10000;