summaryrefslogtreecommitdiffstats
path: root/crypto/heimdal/lib/krb5/crypto.c
diff options
context:
space:
mode:
Diffstat (limited to 'crypto/heimdal/lib/krb5/crypto.c')
-rw-r--r--crypto/heimdal/lib/krb5/crypto.c212
1 files changed, 140 insertions, 72 deletions
diff --git a/crypto/heimdal/lib/krb5/crypto.c b/crypto/heimdal/lib/krb5/crypto.c
index 186b384..7ecd458 100644
--- a/crypto/heimdal/lib/krb5/crypto.c
+++ b/crypto/heimdal/lib/krb5/crypto.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997 - 2001 Kungliga Tekniska Högskolan
+ * Copyright (c) 1997 - 2002 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
@@ -32,7 +32,7 @@
*/
#include "krb5_locl.h"
-RCSID("$Id: crypto.c,v 1.50 2001/05/14 06:14:45 assar Exp $");
+RCSID("$Id: crypto.c,v 1.60 2002/01/06 23:12:51 assar Exp $");
#undef CRYPTO_DEBUG
#ifdef CRYPTO_DEBUG
@@ -156,6 +156,37 @@ DES_schedule(krb5_context context,
des_set_key(key->key->keyvalue.data, key->schedule->data);
}
+static void
+DES_string_to_key_int(unsigned char *data, size_t length, des_cblock *key)
+{
+ des_key_schedule schedule;
+ int i;
+ int reverse = 0;
+ unsigned char *p;
+
+ unsigned char swap[] = { 0x0, 0x8, 0x4, 0xc, 0x2, 0xa, 0x6, 0xe,
+ 0x1, 0x9, 0x5, 0xd, 0x3, 0xb, 0x7, 0xf };
+ memset(key, 0, 8);
+
+ p = (unsigned char*)key;
+ for (i = 0; i < length; i++) {
+ unsigned char tmp = data[i];
+ if (!reverse)
+ *p++ ^= (tmp << 1);
+ else
+ *--p ^= (swap[tmp & 0xf] << 4) | swap[(tmp & 0xf0) >> 4];
+ if((i % 8) == 7)
+ reverse = !reverse;
+ }
+ des_set_odd_parity(key);
+ if(des_is_weak_key(key))
+ (*key)[7] ^= 0xF0;
+ des_set_key(key, schedule);
+ des_cbc_cksum((void*)data, key, length, schedule, key);
+ memset(schedule, 0, sizeof(schedule));
+ des_set_odd_parity(key);
+}
+
static krb5_error_code
DES_string_to_key(krb5_context context,
krb5_enctype enctype,
@@ -163,20 +194,19 @@ DES_string_to_key(krb5_context context,
krb5_salt salt,
krb5_keyblock *key)
{
- char *s;
+ unsigned char *s;
size_t len;
des_cblock tmp;
- len = password.length + salt.saltvalue.length + 1;
+ len = password.length + salt.saltvalue.length;
s = malloc(len);
- if(s == NULL) {
+ if(len > 0 && s == NULL) {
krb5_set_error_string(context, "malloc: out of memory");
return ENOMEM;
}
memcpy(s, password.data, password.length);
memcpy(s + password.length, salt.saltvalue.data, salt.saltvalue.length);
- s[len - 1] = '\0';
- des_string_to_key(s, &tmp);
+ DES_string_to_key_int(s, len, &tmp);
key->keytype = enctype;
krb5_data_copy(&key->keyvalue, tmp, sizeof(tmp));
memset(&tmp, 0, sizeof(tmp));
@@ -248,12 +278,12 @@ DES_AFS3_Transarc_string_to_key (krb5_data pw,
memcpy(&temp_key, "kerberos", 8);
des_set_odd_parity (&temp_key);
des_set_key (&temp_key, schedule);
- des_cbc_cksum ((des_cblock *)password, &ivec, passlen, schedule, &ivec);
+ des_cbc_cksum (password, &ivec, passlen, schedule, &ivec);
memcpy(&temp_key, &ivec, 8);
des_set_odd_parity (&temp_key);
des_set_key (&temp_key, schedule);
- des_cbc_cksum ((des_cblock *)password, key, passlen, schedule, &ivec);
+ des_cbc_cksum (password, key, passlen, schedule, &ivec);
memset(&schedule, 0, sizeof(schedule));
memset(&temp_key, 0, sizeof(temp_key));
memset(&ivec, 0, sizeof(ivec));
@@ -359,8 +389,8 @@ DES3_string_to_key(krb5_context context,
des_set_key(keys + i, s[i]);
}
memset(&ivec, 0, sizeof(ivec));
- des_ede3_cbc_encrypt((des_cblock *)tmp,
- (des_cblock *)tmp, sizeof(tmp),
+ des_ede3_cbc_encrypt(tmp,
+ tmp, sizeof(tmp),
s[0], s[1], s[2], &ivec, DES_ENCRYPT);
memset(s, 0, sizeof(s));
memset(&ivec, 0, sizeof(ivec));
@@ -895,8 +925,8 @@ RSA_MD4_DES_checksum(krb5_context context,
MD4_Update (&md4, data, len);
MD4_Final (p + 8, &md4);
memset (&ivec, 0, sizeof(ivec));
- des_cbc_encrypt((des_cblock*)p,
- (des_cblock*)p,
+ des_cbc_encrypt(p,
+ p,
24,
key->schedule->data,
&ivec,
@@ -970,8 +1000,8 @@ RSA_MD5_DES_checksum(krb5_context context,
MD5_Update (&md5, data, len);
MD5_Final (p + 8, &md5);
memset (&ivec, 0, sizeof(ivec));
- des_cbc_encrypt((des_cblock*)p,
- (des_cblock*)p,
+ des_cbc_encrypt(p,
+ p,
24,
key->schedule->data,
&ivec,
@@ -1032,8 +1062,8 @@ RSA_MD5_DES3_checksum(krb5_context context,
MD5_Update (&md5, data, len);
MD5_Final (p + 8, &md5);
memset (&ivec, 0, sizeof(ivec));
- des_ede3_cbc_encrypt((des_cblock*)p,
- (des_cblock*)p,
+ des_ede3_cbc_encrypt(p,
+ p,
24,
sched[0], sched[1], sched[2],
&ivec,
@@ -1447,7 +1477,7 @@ do_checksum (krb5_context context,
static krb5_error_code
create_checksum(krb5_context context,
krb5_crypto crypto,
- krb5_key_usage usage, /* not krb5_key_usage */
+ unsigned usage, /* not krb5_key_usage */
krb5_cksumtype type, /* 0 -> pick from crypto */
void *data,
size_t len,
@@ -1725,7 +1755,7 @@ ARCFOUR_subencrypt(krb5_context context,
krb5_keyblock kb;
unsigned char t[4];
RC4_KEY rc4_key;
- char *cdata = (char *)data;
+ unsigned char *cdata = data;
unsigned char k1_c_data[16], k2_c_data[16], k3_c_data[16];
t[0] = (usage >> 0) & 0xFF;
@@ -1781,7 +1811,7 @@ ARCFOUR_subdecrypt(krb5_context context,
krb5_keyblock kb;
unsigned char t[4];
RC4_KEY rc4_key;
- char *cdata = (char *)data;
+ unsigned char *cdata = data;
unsigned char k1_c_data[16], k2_c_data[16], k3_c_data[16];
unsigned char cksum_data[16];
@@ -1949,7 +1979,7 @@ static struct encryption_type enctype_arcfour_hmac_md5 = {
1,
8,
&keytype_arcfour,
- &checksum_hmac_md5_enc,
+ &checksum_hmac_md5,
&checksum_hmac_md5_enc,
F_SPECIAL,
ARCFOUR_encrypt
@@ -2143,18 +2173,18 @@ krb5_error_code
krb5_keytype_to_enctypes (krb5_context context,
krb5_keytype keytype,
unsigned *len,
- int **val)
+ krb5_enctype **val)
{
int i;
unsigned n = 0;
- int *ret;
+ krb5_enctype *ret;
for (i = num_etypes - 1; i >= 0; --i) {
if (etypes[i]->keytype->type == keytype
&& !(etypes[i]->flags & F_PSEUDO))
++n;
}
- ret = malloc(n * sizeof(int));
+ ret = malloc(n * sizeof(*ret));
if (ret == NULL && n != 0) {
krb5_set_error_string(context, "malloc: out of memory");
return ENOMEM;
@@ -2179,10 +2209,10 @@ krb5_error_code
krb5_keytype_to_enctypes_default (krb5_context context,
krb5_keytype keytype,
unsigned *len,
- int **val)
+ krb5_enctype **val)
{
int i, n;
- int *ret;
+ krb5_enctype *ret;
if (keytype != KEYTYPE_DES || context->etypes_des == NULL)
return krb5_keytype_to_enctypes (context, keytype, len, val);
@@ -2245,20 +2275,23 @@ encrypt_internal_derived(krb5_context context,
krb5_data *result,
void *ivec)
{
- size_t sz, block_sz, checksum_sz;
+ size_t sz, block_sz, checksum_sz, total_sz;
Checksum cksum;
unsigned char *p, *q;
krb5_error_code ret;
struct key_data *dkey;
- struct encryption_type *et = crypto->et;
+ const struct encryption_type *et = crypto->et;
checksum_sz = CHECKSUMSIZE(et->keyed_checksum);
- sz = et->confoundersize + /* 4 - length */ len;
+ sz = et->confoundersize + len;
block_sz = (sz + et->blocksize - 1) &~ (et->blocksize - 1); /* pad */
- p = calloc(1, block_sz + checksum_sz);
- if(p == NULL)
+ total_sz = block_sz + checksum_sz;
+ p = calloc(1, total_sz);
+ if(p == NULL) {
+ krb5_set_error_string(context, "malloc: out of memory");
return ENOMEM;
+ }
q = p;
krb5_generate_random_block(q, et->confoundersize); /* XXX */
@@ -2277,34 +2310,32 @@ encrypt_internal_derived(krb5_context context,
krb5_clear_error_string (context);
ret = KRB5_CRYPTO_INTERNAL;
}
- if(ret) {
- memset(p, 0, block_sz + checksum_sz);
- free(p);
- return ret;
- }
+ if(ret)
+ goto fail;
memcpy(p + block_sz, cksum.checksum.data, cksum.checksum.length);
free_Checksum (&cksum);
ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey);
- if(ret) {
- memset(p, 0, block_sz + checksum_sz);
- free(p);
- return ret;
- }
+ if(ret)
+ goto fail;
ret = _key_schedule(context, dkey);
- if(ret) {
- memset(p, 0, block_sz);
- free(p);
- return ret;
- }
+ if(ret)
+ goto fail;
#ifdef CRYPTO_DEBUG
krb5_crypto_debug(context, 1, block_sz, dkey->key);
#endif
- (*et->encrypt)(context, dkey, p, block_sz, 1, usage, ivec);
+ ret = (*et->encrypt)(context, dkey, p, block_sz, 1, usage, ivec);
+ if (ret)
+ goto fail;
result->data = p;
- result->length = block_sz + checksum_sz;
+ result->length = total_sz;
return 0;
+ fail:
+ memset(p, 0, total_sz);
+ free(p);
+ return ret;
}
+
static krb5_error_code
encrypt_internal(krb5_context context,
krb5_crypto crypto,
@@ -2317,7 +2348,7 @@ encrypt_internal(krb5_context context,
Checksum cksum;
unsigned char *p, *q;
krb5_error_code ret;
- struct encryption_type *et = crypto->et;
+ const struct encryption_type *et = crypto->et;
checksum_sz = CHECKSUMSIZE(et->checksum);
@@ -2345,29 +2376,32 @@ encrypt_internal(krb5_context context,
&cksum);
if(ret == 0 && cksum.checksum.length != checksum_sz) {
krb5_clear_error_string (context);
- ret = KRB5_CRYPTO_INTERNAL;
- }
- if(ret) {
- memset(p, 0, block_sz);
- free(p);
free_Checksum(&cksum);
- return ret;
+ ret = KRB5_CRYPTO_INTERNAL;
}
+ if(ret)
+ goto fail;
memcpy(p + et->confoundersize, cksum.checksum.data, cksum.checksum.length);
free_Checksum(&cksum);
ret = _key_schedule(context, &crypto->key);
- if(ret) {
+ if(ret)
+ goto fail;
+#ifdef CRYPTO_DEBUG
+ krb5_crypto_debug(context, 1, block_sz, crypto->key.key);
+#endif
+ ret = (*et->encrypt)(context, &crypto->key, p, block_sz, 1, 0, ivec);
+ if (ret) {
memset(p, 0, block_sz);
free(p);
return ret;
}
-#ifdef CRYPTO_DEBUG
- krb5_crypto_debug(context, 1, block_sz, crypto->key.key);
-#endif
- (*et->encrypt)(context, &crypto->key, p, block_sz, 1, 0, ivec);
result->data = p;
result->length = block_sz;
return 0;
+ fail:
+ memset(p, 0, block_sz);
+ free(p);
+ return ret;
}
static krb5_error_code
@@ -2383,6 +2417,7 @@ encrypt_internal_special(krb5_context context,
size_t cksum_sz = CHECKSUMSIZE(et->checksum);
size_t sz = len + cksum_sz + et->confoundersize;
char *tmp, *p;
+ krb5_error_code ret;
tmp = malloc (sz);
if (tmp == NULL) {
@@ -2395,7 +2430,12 @@ encrypt_internal_special(krb5_context context,
krb5_generate_random_block(p, et->confoundersize);
p += et->confoundersize;
memcpy (p, data, len);
- (*et->encrypt)(context, &crypto->key, tmp, sz, TRUE, usage, ivec);
+ ret = (*et->encrypt)(context, &crypto->key, tmp, sz, TRUE, usage, ivec);
+ if (ret) {
+ memset(tmp, 0, sz);
+ free(tmp);
+ return ret;
+ }
result->data = tmp;
result->length = sz;
return 0;
@@ -2446,7 +2486,11 @@ decrypt_internal_derived(krb5_context context,
#ifdef CRYPTO_DEBUG
krb5_crypto_debug(context, 0, len, dkey->key);
#endif
- (*et->encrypt)(context, dkey, p, len, 0, usage, ivec);
+ ret = (*et->encrypt)(context, dkey, p, len, 0, usage, ivec);
+ if (ret) {
+ free(p);
+ return ret;
+ }
cksum.checksum.data = p + len;
cksum.checksum.length = checksum_sz;
@@ -2504,7 +2548,11 @@ decrypt_internal(krb5_context context,
#ifdef CRYPTO_DEBUG
krb5_crypto_debug(context, 0, len, crypto->key.key);
#endif
- (*et->encrypt)(context, &crypto->key, p, len, 0, 0, ivec);
+ ret = (*et->encrypt)(context, &crypto->key, p, len, 0, 0, ivec);
+ if (ret) {
+ free(p);
+ return ret;
+ }
ret = krb5_data_copy(&cksum.checksum, p + et->confoundersize, checksum_sz);
if(ret) {
free(p);
@@ -2544,6 +2592,7 @@ decrypt_internal_special(krb5_context context,
size_t sz = len - cksum_sz - et->confoundersize;
char *cdata = (char *)data;
char *tmp;
+ krb5_error_code ret;
tmp = malloc (sz);
if (tmp == NULL) {
@@ -2551,7 +2600,11 @@ decrypt_internal_special(krb5_context context,
return ENOMEM;
}
- (*et->encrypt)(context, &crypto->key, data, len, FALSE, usage, ivec);
+ ret = (*et->encrypt)(context, &crypto->key, data, len, FALSE, usage, ivec);
+ if (ret) {
+ free(tmp);
+ return ret;
+ }
memcpy (tmp, cdata + cksum_sz + et->confoundersize, sz);
@@ -2655,7 +2708,7 @@ krb5_decrypt_EncryptedData(krb5_context context,
* *
************************************************************/
-#ifdef HAVE_OPENSSL_DES_H
+#ifdef HAVE_OPENSSL
#include <openssl/rand.h>
/* From openssl/crypto/rand/rand_lcl.h */
@@ -2664,7 +2717,6 @@ static int
seed_something(void)
{
int fd = -1;
- size_t len;
char buf[1024], seedfile[256];
/* If there is a seed file, load it. But such a file cannot be trusted,
@@ -2684,7 +2736,7 @@ seed_something(void)
we do not have to deal with it. */
if (RAND_status() != 1) {
krb5_context context;
- char *p;
+ const char *p;
/* Try using egd */
if (!krb5_init_context(&context)) {
@@ -3000,6 +3052,7 @@ krb5_string_to_key_derived(krb5_context context,
struct encryption_type *et = _find_enctype(etype);
krb5_error_code ret;
struct key_data kd;
+ size_t keylen = et->keytype->bits / 8;
u_char *tmp;
if(et == NULL) {
@@ -3008,13 +3061,28 @@ krb5_string_to_key_derived(krb5_context context,
return KRB5_PROG_ETYPE_NOSUPP;
}
ALLOC(kd.key, 1);
+ if(kd.key == NULL) {
+ krb5_set_error_string (context, "malloc: out of memory");
+ return ENOMEM;
+ }
+ ret = krb5_data_alloc(&kd.key->keyvalue, et->keytype->size);
+ if(ret) {
+ free(kd.key);
+ return ret;
+ }
kd.key->keytype = etype;
- tmp = malloc (et->keytype->bits / 8);
- _krb5_n_fold(str, len, tmp, et->keytype->bits / 8);
- krb5_data_alloc(&kd.key->keyvalue, et->keytype->size);
+ tmp = malloc (keylen);
+ if(tmp == NULL) {
+ krb5_free_keyblock(context, kd.key);
+ krb5_set_error_string (context, "malloc: out of memory");
+ return ENOMEM;
+ }
+ _krb5_n_fold(str, len, tmp, keylen);
kd.schedule = NULL;
- DES3_postproc (context, tmp, et->keytype->bits / 8, &kd); /* XXX */
- ret = derive_key(context,
+ DES3_postproc (context, tmp, keylen, &kd); /* XXX */
+ memset(tmp, 0, keylen);
+ free(tmp);
+ ret = derive_key(context,
et,
&kd,
"kerberos", /* XXX well known constant */
OpenPOWER on IntegriCloud