root/source4/heimdal/lib/krb5/crypto.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. krb5_DES_random_key
  2. krb5_DES_schedule_old
  3. krb5_DES_AFS3_CMU_string_to_key
  4. krb5_DES_AFS3_Transarc_string_to_key
  5. DES_AFS3_string_to_key
  6. DES_string_to_key_int
  7. krb5_DES_string_to_key
  8. krb5_DES_random_to_key
  9. DES3_random_key
  10. xor
  11. DES3_string_to_key
  12. DES3_string_to_key_derived
  13. DES3_random_to_key
  14. ARCFOUR_schedule
  15. ARCFOUR_string_to_key
  16. AES_string_to_key
  17. evp_schedule
  18. evp_cleanup
  19. krb5_salttype_to_string
  20. krb5_string_to_salttype
  21. krb5_get_pw_salt
  22. krb5_free_salt
  23. krb5_string_to_key_data
  24. krb5_string_to_key
  25. krb5_string_to_key_data_salt
  26. krb5_string_to_key_data_salt_opaque
  27. krb5_string_to_key_salt
  28. krb5_string_to_key_salt_opaque
  29. krb5_enctype_keysize
  30. krb5_enctype_keybits
  31. krb5_generate_random_keyblock
  32. _key_schedule
  33. NONE_checksum
  34. CRC32_checksum
  35. RSA_MD4_checksum
  36. des_checksum
  37. des_verify
  38. RSA_MD4_DES_checksum
  39. RSA_MD4_DES_verify
  40. RSA_MD5_checksum
  41. RSA_MD5_DES_checksum
  42. RSA_MD5_DES_verify
  43. RSA_MD5_DES3_checksum
  44. RSA_MD5_DES3_verify
  45. SHA1_checksum
  46. hmac
  47. krb5_hmac
  48. SP_HMAC_SHA1_checksum
  49. HMAC_MD5_checksum
  50. _find_checksum
  51. get_checksum_key
  52. create_checksum
  53. arcfour_checksum_p
  54. krb5_create_checksum
  55. verify_checksum
  56. krb5_verify_checksum
  57. krb5_crypto_get_checksum_type
  58. krb5_checksumsize
  59. krb5_checksum_is_keyed
  60. krb5_checksum_is_collision_proof
  61. krb5_checksum_disable
  62. NULL_encrypt
  63. evp_encrypt
  64. evp_des_encrypt_null_ivec
  65. evp_des_encrypt_key_ivec
  66. DES_CFB64_encrypt_null_ivec
  67. DES_PCBC_encrypt_key_ivec
  68. ARCFOUR_subencrypt
  69. ARCFOUR_subdecrypt
  70. usage2arcfour
  71. ARCFOUR_encrypt
  72. AES_PRF
  73. _find_enctype
  74. krb5_enctype_to_string
  75. krb5_string_to_enctype
  76. krb5_enctype_to_keytype
  77. krb5_enctype_valid
  78. krb5_cksumtype_to_enctype
  79. krb5_cksumtype_valid
  80. krb5_enctypes_compatible_keys
  81. derived_crypto
  82. special_crypto
  83. encrypt_internal_derived
  84. encrypt_internal
  85. encrypt_internal_special
  86. decrypt_internal_derived
  87. decrypt_internal
  88. decrypt_internal_special
  89. find_iv
  90. krb5_encrypt_iov_ivec
  91. krb5_decrypt_iov_ivec
  92. krb5_create_checksum_iov
  93. krb5_crypto_length
  94. krb5_encrypt_ivec
  95. krb5_encrypt
  96. krb5_encrypt_EncryptedData
  97. krb5_decrypt_ivec
  98. krb5_decrypt
  99. krb5_decrypt_EncryptedData
  100. seed_something
  101. krb5_generate_random_block
  102. DES3_postproc
  103. derive_key
  104. _new_derived_key
  105. krb5_derive_key
  106. _get_derived_key
  107. krb5_crypto_init
  108. free_key_data
  109. free_key_usage
  110. krb5_crypto_destroy
  111. krb5_crypto_getblocksize
  112. krb5_crypto_getenctype
  113. krb5_crypto_getpadsize
  114. krb5_crypto_getconfoundersize
  115. krb5_enctype_disable
  116. krb5_enctype_enable
  117. krb5_string_to_key_derived
  118. wrapped_length
  119. wrapped_length_dervied
  120. krb5_get_wrapped_length
  121. crypto_overhead
  122. crypto_overhead_dervied
  123. krb5_crypto_overhead
  124. krb5_random_to_key
  125. _krb5_pk_octetstring2key
  126. encode_uvinfo
  127. encode_otherinfo
  128. _krb5_pk_kdf
  129. krb5_crypto_prf_length
  130. krb5_crypto_prf
  131. _find_keytype
  132. krb5_keytype_to_enctypes_default
  133. krb5_keytype_to_string
  134. krb5_string_to_keytype
  135. krb5_keytype_to_enctypes

   1 /*
   2  * Copyright (c) 1997 - 2008 Kungliga Tekniska Högskolan
   3  * (Royal Institute of Technology, Stockholm, Sweden).
   4  * All rights reserved.
   5  *
   6  * Redistribution and use in source and binary forms, with or without
   7  * modification, are permitted provided that the following conditions
   8  * are met:
   9  *
  10  * 1. Redistributions of source code must retain the above copyright
  11  *    notice, this list of conditions and the following disclaimer.
  12  *
  13  * 2. Redistributions in binary form must reproduce the above copyright
  14  *    notice, this list of conditions and the following disclaimer in the
  15  *    documentation and/or other materials provided with the distribution.
  16  *
  17  * 3. Neither the name of the Institute nor the names of its contributors
  18  *    may be used to endorse or promote products derived from this software
  19  *    without specific prior written permission.
  20  *
  21  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
  22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
  25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31  * SUCH DAMAGE.
  32  */
  33 
  34 #include "krb5_locl.h"
  35 RCSID("$Id$");
  36 #include <pkinit_asn1.h>
  37 
  38 #undef __attribute__
  39 #define __attribute__(X)
  40 
  41 #define WEAK_ENCTYPES 1
  42 
  43 #ifndef HEIMDAL_SMALLER
  44 #define DES3_OLD_ENCTYPE 1
  45 #endif
  46 
  47 
  48 #ifdef HAVE_OPENSSL /* XXX forward decl for hcrypto glue */
  49 const EVP_CIPHER * _krb5_EVP_hcrypto_aes_128_cts(void);
  50 const EVP_CIPHER * _krb5_EVP_hcrypto_aes_256_cts(void);
  51 #define EVP_hcrypto_aes_128_cts _krb5_EVP_hcrypto_aes_128_cts
  52 #define EVP_hcrypto_aes_256_cts _krb5_EVP_hcrypto_aes_256_cts
  53 #endif
  54 
  55 struct key_data {
  56     krb5_keyblock *key;
  57     krb5_data *schedule;
  58 };
  59 
  60 struct key_usage {
  61     unsigned usage;
  62     struct key_data key;
  63 };
  64 
  65 struct krb5_crypto_data {
  66     struct encryption_type *et;
  67     struct key_data key;
  68     int num_key_usage;
  69     struct key_usage *key_usage;
  70 };
  71 
  72 #define CRYPTO_ETYPE(C) ((C)->et->type)
  73 
  74 /* bits for `flags' below */
  75 #define F_KEYED          1      /* checksum is keyed */
  76 #define F_CPROOF         2      /* checksum is collision proof */
  77 #define F_DERIVED        4      /* uses derived keys */
  78 #define F_VARIANT        8      /* uses `variant' keys (6.4.3) */
  79 #define F_PSEUDO        16      /* not a real protocol type */
  80 #define F_SPECIAL       32      /* backwards */
  81 #define F_DISABLED      64      /* enctype/checksum disabled */
  82 
  83 struct salt_type {
  84     krb5_salttype type;
  85     const char *name;
  86     krb5_error_code (*string_to_key)(krb5_context, krb5_enctype, krb5_data,
  87                                      krb5_salt, krb5_data, krb5_keyblock*);
  88 };
  89 
  90 struct key_type {
  91     krb5_keytype type; /* XXX */
  92     const char *name;
  93     size_t bits;
  94     size_t size;
  95     size_t schedule_size;
  96     void (*random_key)(krb5_context, krb5_keyblock*);
  97     void (*schedule)(krb5_context, struct key_type *, struct key_data *);
  98     struct salt_type *string_to_key;
  99     void (*random_to_key)(krb5_context, krb5_keyblock*, const void*, size_t);
 100     void (*cleanup)(krb5_context, struct key_data *);
 101     const EVP_CIPHER *(*evp)(void);
 102 };
 103 
 104 struct checksum_type {
 105     krb5_cksumtype type;
 106     const char *name;
 107     size_t blocksize;
 108     size_t checksumsize;
 109     unsigned flags;
 110     krb5_enctype (*checksum)(krb5_context context,
 111                              struct key_data *key,
 112                              const void *buf, size_t len,
 113                              unsigned usage,
 114                              Checksum *csum);
 115     krb5_error_code (*verify)(krb5_context context,
 116                               struct key_data *key,
 117                               const void *buf, size_t len,
 118                               unsigned usage,
 119                               Checksum *csum);
 120 };
 121 
 122 struct encryption_type {
 123     krb5_enctype type;
 124     const char *name;
 125     size_t blocksize;
 126     size_t padsize;
 127     size_t confoundersize;
 128     struct key_type *keytype;
 129     struct checksum_type *checksum;
 130     struct checksum_type *keyed_checksum;
 131     unsigned flags;
 132     krb5_error_code (*encrypt)(krb5_context context,
 133                                struct key_data *key,
 134                                void *data, size_t len,
 135                                krb5_boolean encryptp,
 136                                int usage,
 137                                void *ivec);
 138     size_t prf_length;
 139     krb5_error_code (*prf)(krb5_context,
 140                            krb5_crypto, const krb5_data *, krb5_data *);
 141 };
 142 
 143 #define ENCRYPTION_USAGE(U) (((U) << 8) | 0xAA)
 144 #define INTEGRITY_USAGE(U) (((U) << 8) | 0x55)
 145 #define CHECKSUM_USAGE(U) (((U) << 8) | 0x99)
 146 
 147 static struct checksum_type *_find_checksum(krb5_cksumtype type);
 148 static struct encryption_type *_find_enctype(krb5_enctype type);
 149 static krb5_error_code _get_derived_key(krb5_context, krb5_crypto,
 150                                         unsigned, struct key_data**);
 151 static struct key_data *_new_derived_key(krb5_crypto crypto, unsigned usage);
 152 static krb5_error_code derive_key(krb5_context context,
 153                                   struct encryption_type *et,
 154                                   struct key_data *key,
 155                                   const void *constant,
 156                                   size_t len);
 157 static krb5_error_code hmac(krb5_context context,
 158                             struct checksum_type *cm,
 159                             const void *data,
 160                             size_t len,
 161                             unsigned usage,
 162                             struct key_data *keyblock,
 163                             Checksum *result);
 164 static void free_key_data(krb5_context,
 165                           struct key_data *,
 166                           struct encryption_type *);
 167 static krb5_error_code usage2arcfour (krb5_context, unsigned *);
 168 static void xor (DES_cblock *, const unsigned char *);
 169 
 170 /************************************************************
 171  *                                                          *
 172  ************************************************************/
 173 
 174 struct evp_schedule {
 175     EVP_CIPHER_CTX ectx;
 176     EVP_CIPHER_CTX dctx;
 177 };
 178 
 179 
 180 static HEIMDAL_MUTEX crypto_mutex = HEIMDAL_MUTEX_INITIALIZER;
 181 
 182 #ifdef WEAK_ENCTYPES
 183 static void
 184 krb5_DES_random_key(krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
 185                     krb5_keyblock *key)
 186 {
 187     DES_cblock *k = key->keyvalue.data;
 188     do {
 189         krb5_generate_random_block(k, sizeof(DES_cblock));
 190         DES_set_odd_parity(k);
 191     } while(DES_is_weak_key(k));
 192 }
 193 
 194 static void
 195 krb5_DES_schedule_old(krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
 196                       struct key_type *kt,
 197                       struct key_data *key)
 198 {
 199     DES_set_key_unchecked(key->key->keyvalue.data, key->schedule->data);
 200 }
 201 
 202 #ifdef ENABLE_AFS_STRING_TO_KEY
 203 
 204 /* This defines the Andrew string_to_key function.  It accepts a password
 205  * string as input and converts it via a one-way encryption algorithm to a DES
 206  * encryption key.  It is compatible with the original Andrew authentication
 207  * service password database.
 208  */
 209 
 210 /*
 211  * Short passwords, i.e 8 characters or less.
 212  */
 213 static void
 214 krb5_DES_AFS3_CMU_string_to_key (krb5_data pw,
     /* [<][>][^][v][top][bottom][index][help] */
 215                                  krb5_data cell,
 216                                  DES_cblock *key)
 217 {
 218     char  password[8+1];        /* crypt is limited to 8 chars anyway */
 219     int   i;
 220 
 221     for(i = 0; i < 8; i++) {
 222         char c = ((i < pw.length) ? ((char*)pw.data)[i] : 0) ^
 223             ((i < cell.length) ?
 224              tolower(((unsigned char*)cell.data)[i]) : 0);
 225         password[i] = c ? c : 'X';
 226     }
 227     password[8] = '\0';
 228 
 229     memcpy(key, crypt(password, "p1") + 2, sizeof(DES_cblock));
 230 
 231     /* parity is inserted into the LSB so left shift each byte up one
 232        bit. This allows ascii characters with a zero MSB to retain as
 233        much significance as possible. */
 234     for (i = 0; i < sizeof(DES_cblock); i++)
 235         ((unsigned char*)key)[i] <<= 1;
 236     DES_set_odd_parity (key);
 237 }
 238 
 239 /*
 240  * Long passwords, i.e 9 characters or more.
 241  */
 242 static void
 243 krb5_DES_AFS3_Transarc_string_to_key (krb5_data pw,
     /* [<][>][^][v][top][bottom][index][help] */
 244                                       krb5_data cell,
 245                                       DES_cblock *key)
 246 {
 247     DES_key_schedule schedule;
 248     DES_cblock temp_key;
 249     DES_cblock ivec;
 250     char password[512];
 251     size_t passlen;
 252 
 253     memcpy(password, pw.data, min(pw.length, sizeof(password)));
 254     if(pw.length < sizeof(password)) {
 255         int len = min(cell.length, sizeof(password) - pw.length);
 256         int i;
 257 
 258         memcpy(password + pw.length, cell.data, len);
 259         for (i = pw.length; i < pw.length + len; ++i)
 260             password[i] = tolower((unsigned char)password[i]);
 261     }
 262     passlen = min(sizeof(password), pw.length + cell.length);
 263     memcpy(&ivec, "kerberos", 8);
 264     memcpy(&temp_key, "kerberos", 8);
 265     DES_set_odd_parity (&temp_key);
 266     DES_set_key_unchecked (&temp_key, &schedule);
 267     DES_cbc_cksum ((void*)password, &ivec, passlen, &schedule, &ivec);
 268 
 269     memcpy(&temp_key, &ivec, 8);
 270     DES_set_odd_parity (&temp_key);
 271     DES_set_key_unchecked (&temp_key, &schedule);
 272     DES_cbc_cksum ((void*)password, key, passlen, &schedule, &ivec);
 273     memset(&schedule, 0, sizeof(schedule));
 274     memset(&temp_key, 0, sizeof(temp_key));
 275     memset(&ivec, 0, sizeof(ivec));
 276     memset(password, 0, sizeof(password));
 277 
 278     DES_set_odd_parity (key);
 279 }
 280 
 281 static krb5_error_code
 282 DES_AFS3_string_to_key(krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
 283                        krb5_enctype enctype,
 284                        krb5_data password,
 285                        krb5_salt salt,
 286                        krb5_data opaque,
 287                        krb5_keyblock *key)
 288 {
 289     DES_cblock tmp;
 290     if(password.length > 8)
 291         krb5_DES_AFS3_Transarc_string_to_key(password, salt.saltvalue, &tmp);
 292     else
 293         krb5_DES_AFS3_CMU_string_to_key(password, salt.saltvalue, &tmp);
 294     key->keytype = enctype;
 295     krb5_data_copy(&key->keyvalue, tmp, sizeof(tmp));
 296     memset(&key, 0, sizeof(key));
 297     return 0;
 298 }
 299 #endif /* ENABLE_AFS_STRING_TO_KEY */
 300 
 301 static void
 302 DES_string_to_key_int(unsigned char *data, size_t length, DES_cblock *key)
     /* [<][>][^][v][top][bottom][index][help] */
 303 {
 304     DES_key_schedule schedule;
 305     int i;
 306     int reverse = 0;
 307     unsigned char *p;
 308 
 309     unsigned char swap[] = { 0x0, 0x8, 0x4, 0xc, 0x2, 0xa, 0x6, 0xe,
 310                              0x1, 0x9, 0x5, 0xd, 0x3, 0xb, 0x7, 0xf };
 311     memset(key, 0, 8);
 312 
 313     p = (unsigned char*)key;
 314     for (i = 0; i < length; i++) {
 315         unsigned char tmp = data[i];
 316         if (!reverse)
 317             *p++ ^= (tmp << 1);
 318         else
 319             *--p ^= (swap[tmp & 0xf] << 4) | swap[(tmp & 0xf0) >> 4];
 320         if((i % 8) == 7)
 321             reverse = !reverse;
 322     }
 323     DES_set_odd_parity(key);
 324     if(DES_is_weak_key(key))
 325         (*key)[7] ^= 0xF0;
 326     DES_set_key_unchecked(key, &schedule);
 327     DES_cbc_cksum((void*)data, key, length, &schedule, key);
 328     memset(&schedule, 0, sizeof(schedule));
 329     DES_set_odd_parity(key);
 330     if(DES_is_weak_key(key))
 331         (*key)[7] ^= 0xF0;
 332 }
 333 
 334 static krb5_error_code
 335 krb5_DES_string_to_key(krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
 336                        krb5_enctype enctype,
 337                        krb5_data password,
 338                        krb5_salt salt,
 339                        krb5_data opaque,
 340                        krb5_keyblock *key)
 341 {
 342     unsigned char *s;
 343     size_t len;
 344     DES_cblock tmp;
 345 
 346 #ifdef ENABLE_AFS_STRING_TO_KEY
 347     if (opaque.length == 1) {
 348         unsigned long v;
 349         _krb5_get_int(opaque.data, &v, 1);
 350         if (v == 1)
 351             return DES_AFS3_string_to_key(context, enctype, password,
 352                                           salt, opaque, key);
 353     }
 354 #endif
 355 
 356     len = password.length + salt.saltvalue.length;
 357     s = malloc(len);
 358     if(len > 0 && s == NULL) {
 359         krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
 360         return ENOMEM;
 361     }
 362     memcpy(s, password.data, password.length);
 363     memcpy(s + password.length, salt.saltvalue.data, salt.saltvalue.length);
 364     DES_string_to_key_int(s, len, &tmp);
 365     key->keytype = enctype;
 366     krb5_data_copy(&key->keyvalue, tmp, sizeof(tmp));
 367     memset(&tmp, 0, sizeof(tmp));
 368     memset(s, 0, len);
 369     free(s);
 370     return 0;
 371 }
 372 
 373 static void
 374 krb5_DES_random_to_key(krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
 375                        krb5_keyblock *key,
 376                        const void *data,
 377                        size_t size)
 378 {
 379     DES_cblock *k = key->keyvalue.data;
 380     memcpy(k, data, key->keyvalue.length);
 381     DES_set_odd_parity(k);
 382     if(DES_is_weak_key(k))
 383         xor(k, (const unsigned char*)"\0\0\0\0\0\0\0\xf0");
 384 }
 385 #endif
 386 
 387 /*
 388  *
 389  */
 390 
 391 static void
 392 DES3_random_key(krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
 393                 krb5_keyblock *key)
 394 {
 395     DES_cblock *k = key->keyvalue.data;
 396     do {
 397         krb5_generate_random_block(k, 3 * sizeof(DES_cblock));
 398         DES_set_odd_parity(&k[0]);
 399         DES_set_odd_parity(&k[1]);
 400         DES_set_odd_parity(&k[2]);
 401     } while(DES_is_weak_key(&k[0]) ||
 402             DES_is_weak_key(&k[1]) ||
 403             DES_is_weak_key(&k[2]));
 404 }
 405 
 406 /*
 407  * A = A xor B. A & B are 8 bytes.
 408  */
 409 
 410 static void
 411 xor (DES_cblock *key, const unsigned char *b)
     /* [<][>][^][v][top][bottom][index][help] */
 412 {
 413     unsigned char *a = (unsigned char*)key;
 414     a[0] ^= b[0];
 415     a[1] ^= b[1];
 416     a[2] ^= b[2];
 417     a[3] ^= b[3];
 418     a[4] ^= b[4];
 419     a[5] ^= b[5];
 420     a[6] ^= b[6];
 421     a[7] ^= b[7];
 422 }
 423 
 424 #ifdef DES3_OLD_ENCTYPE
 425 static krb5_error_code
 426 DES3_string_to_key(krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
 427                    krb5_enctype enctype,
 428                    krb5_data password,
 429                    krb5_salt salt,
 430                    krb5_data opaque,
 431                    krb5_keyblock *key)
 432 {
 433     char *str;
 434     size_t len;
 435     unsigned char tmp[24];
 436     DES_cblock keys[3];
 437     krb5_error_code ret;
 438 
 439     len = password.length + salt.saltvalue.length;
 440     str = malloc(len);
 441     if(len != 0 && str == NULL) {
 442         krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
 443         return ENOMEM;
 444     }
 445     memcpy(str, password.data, password.length);
 446     memcpy(str + password.length, salt.saltvalue.data, salt.saltvalue.length);
 447     {
 448         DES_cblock ivec;
 449         DES_key_schedule s[3];
 450         int i;
 451         
 452         ret = _krb5_n_fold(str, len, tmp, 24);
 453         if (ret) {
 454             memset(str, 0, len);
 455             free(str);
 456             krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
 457             return ret;
 458         }
 459         
 460         for(i = 0; i < 3; i++){
 461             memcpy(keys + i, tmp + i * 8, sizeof(keys[i]));
 462             DES_set_odd_parity(keys + i);
 463             if(DES_is_weak_key(keys + i))
 464                 xor(keys + i, (const unsigned char*)"\0\0\0\0\0\0\0\xf0");
 465             DES_set_key_unchecked(keys + i, &s[i]);
 466         }
 467         memset(&ivec, 0, sizeof(ivec));
 468         DES_ede3_cbc_encrypt(tmp,
 469                              tmp, sizeof(tmp),
 470                              &s[0], &s[1], &s[2], &ivec, DES_ENCRYPT);
 471         memset(s, 0, sizeof(s));
 472         memset(&ivec, 0, sizeof(ivec));
 473         for(i = 0; i < 3; i++){
 474             memcpy(keys + i, tmp + i * 8, sizeof(keys[i]));
 475             DES_set_odd_parity(keys + i);
 476             if(DES_is_weak_key(keys + i))
 477                 xor(keys + i, (const unsigned char*)"\0\0\0\0\0\0\0\xf0");
 478         }
 479         memset(tmp, 0, sizeof(tmp));
 480     }
 481     key->keytype = enctype;
 482     krb5_data_copy(&key->keyvalue, keys, sizeof(keys));
 483     memset(keys, 0, sizeof(keys));
 484     memset(str, 0, len);
 485     free(str);
 486     return 0;
 487 }
 488 #endif
 489 
 490 static krb5_error_code
 491 DES3_string_to_key_derived(krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
 492                            krb5_enctype enctype,
 493                            krb5_data password,
 494                            krb5_salt salt,
 495                            krb5_data opaque,
 496                            krb5_keyblock *key)
 497 {
 498     krb5_error_code ret;
 499     size_t len = password.length + salt.saltvalue.length;
 500     char *s;
 501 
 502     s = malloc(len);
 503     if(len != 0 && s == NULL) {
 504         krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
 505         return ENOMEM;
 506     }
 507     memcpy(s, password.data, password.length);
 508     memcpy(s + password.length, salt.saltvalue.data, salt.saltvalue.length);
 509     ret = krb5_string_to_key_derived(context,
 510                                      s,
 511                                      len,
 512                                      enctype,
 513                                      key);
 514     memset(s, 0, len);
 515     free(s);
 516     return ret;
 517 }
 518 
 519 static void
 520 DES3_random_to_key(krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
 521                    krb5_keyblock *key,
 522                    const void *data,
 523                    size_t size)
 524 {
 525     unsigned char *x = key->keyvalue.data;
 526     const u_char *q = data;
 527     DES_cblock *k;
 528     int i, j;
 529 
 530     memset(x, 0, sizeof(x));
 531     for (i = 0; i < 3; ++i) {
 532         unsigned char foo;
 533         for (j = 0; j < 7; ++j) {
 534             unsigned char b = q[7 * i + j];
 535 
 536             x[8 * i + j] = b;
 537         }
 538         foo = 0;
 539         for (j = 6; j >= 0; --j) {
 540             foo |= q[7 * i + j] & 1;
 541             foo <<= 1;
 542         }
 543         x[8 * i + 7] = foo;
 544     }
 545     k = key->keyvalue.data;
 546     for (i = 0; i < 3; i++) {
 547         DES_set_odd_parity(&k[i]);
 548         if(DES_is_weak_key(&k[i]))
 549             xor(&k[i], (const unsigned char*)"\0\0\0\0\0\0\0\xf0");
 550     }
 551 }
 552 
 553 /*
 554  * ARCFOUR
 555  */
 556 
 557 static void
 558 ARCFOUR_schedule(krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
 559                  struct key_type *kt,
 560                  struct key_data *kd)
 561 {
 562     RC4_set_key (kd->schedule->data,
 563                  kd->key->keyvalue.length, kd->key->keyvalue.data);
 564 }
 565 
 566 static krb5_error_code
 567 ARCFOUR_string_to_key(krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
 568                       krb5_enctype enctype,
 569                       krb5_data password,
 570                       krb5_salt salt,
 571                       krb5_data opaque,
 572                       krb5_keyblock *key)
 573 {
 574     krb5_error_code ret;
 575     uint16_t *s = NULL;
 576     size_t len, i;
 577     EVP_MD_CTX *m;
 578 
 579     m = EVP_MD_CTX_create();
 580     if (m == NULL) {
 581         ret = ENOMEM;
 582         krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
 583         goto out;
 584     }
 585 
 586     EVP_DigestInit_ex(m, EVP_md4(), NULL);
 587 
 588     ret = wind_utf8ucs2_length(password.data, &len);
 589     if (ret) {
 590         krb5_set_error_message (context, ret,
 591                                 N_("Password not an UCS2 string", ""));
 592         goto out;
 593     }
 594         
 595     s = malloc (len * sizeof(s[0]));
 596     if (len != 0 && s == NULL) {
 597         krb5_set_error_message (context, ENOMEM,
 598                                 N_("malloc: out of memory", ""));
 599         ret = ENOMEM;
 600         goto out;
 601     }
 602 
 603     ret = wind_utf8ucs2(password.data, s, &len);
 604     if (ret) {
 605         krb5_set_error_message (context, ret,
 606                                 N_("Password not an UCS2 string", ""));
 607         goto out;
 608     }
 609 
 610     /* LE encoding */
 611     for (i = 0; i < len; i++) {
 612         unsigned char p;
 613         p = (s[i] & 0xff);
 614         EVP_DigestUpdate (m, &p, 1);
 615         p = (s[i] >> 8) & 0xff;
 616         EVP_DigestUpdate (m, &p, 1);
 617     }
 618 
 619     key->keytype = enctype;
 620     ret = krb5_data_alloc (&key->keyvalue, 16);
 621     if (ret) {
 622         krb5_set_error_message (context, ENOMEM, N_("malloc: out of memory", ""));
 623         goto out;
 624     }
 625     EVP_DigestFinal_ex (m, key->keyvalue.data, NULL);
 626 
 627  out:
 628     EVP_MD_CTX_destroy(m);
 629     if (s)
 630         memset (s, 0, len);
 631     free (s);
 632     return ret;
 633 }
 634 
 635 /*
 636  * AES
 637  */
 638 
 639 int _krb5_AES_string_to_default_iterator = 4096;
 640 
 641 static krb5_error_code
 642 AES_string_to_key(krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
 643                   krb5_enctype enctype,
 644                   krb5_data password,
 645                   krb5_salt salt,
 646                   krb5_data opaque,
 647                   krb5_keyblock *key)
 648 {
 649     krb5_error_code ret;
 650     uint32_t iter;
 651     struct encryption_type *et;
 652     struct key_data kd;
 653 
 654     if (opaque.length == 0)
 655         iter = _krb5_AES_string_to_default_iterator;
 656     else if (opaque.length == 4) {
 657         unsigned long v;
 658         _krb5_get_int(opaque.data, &v, 4);
 659         iter = ((uint32_t)v);
 660     } else
 661         return KRB5_PROG_KEYTYPE_NOSUPP; /* XXX */
 662         
 663     et = _find_enctype(enctype);
 664     if (et == NULL)
 665         return KRB5_PROG_KEYTYPE_NOSUPP;
 666 
 667     kd.schedule = NULL;
 668     ALLOC(kd.key, 1);
 669     if(kd.key == NULL) {
 670         krb5_set_error_message (context, ENOMEM, N_("malloc: out of memory", ""));
 671         return ENOMEM;
 672     }
 673     kd.key->keytype = enctype;
 674     ret = krb5_data_alloc(&kd.key->keyvalue, et->keytype->size);
 675     if (ret) {
 676         krb5_set_error_message (context, ret, N_("malloc: out of memory", ""));
 677         return ret;
 678     }
 679 
 680     ret = PKCS5_PBKDF2_HMAC_SHA1(password.data, password.length,
 681                                  salt.saltvalue.data, salt.saltvalue.length,
 682                                  iter,
 683                                  et->keytype->size, kd.key->keyvalue.data);
 684     if (ret != 1) {
 685         free_key_data(context, &kd, et);
 686         krb5_set_error_message(context, KRB5_PROG_KEYTYPE_NOSUPP,
 687                                "Error calculating s2k");
 688         return KRB5_PROG_KEYTYPE_NOSUPP;
 689     }
 690 
 691     ret = derive_key(context, et, &kd, "kerberos", strlen("kerberos"));
 692     if (ret == 0)
 693         ret = krb5_copy_keyblock_contents(context, kd.key, key);
 694     free_key_data(context, &kd, et);
 695 
 696     return ret;
 697 }
 698 
 699 static void
 700 evp_schedule(krb5_context context, struct key_type *kt, struct key_data *kd)
     /* [<][>][^][v][top][bottom][index][help] */
 701 {
 702     struct evp_schedule *key = kd->schedule->data;
 703     const EVP_CIPHER *c = (*kt->evp)();
 704 
 705     EVP_CIPHER_CTX_init(&key->ectx);
 706     EVP_CIPHER_CTX_init(&key->dctx);
 707 
 708     EVP_CipherInit_ex(&key->ectx, c, NULL, kd->key->keyvalue.data, NULL, 1);
 709     EVP_CipherInit_ex(&key->dctx, c, NULL, kd->key->keyvalue.data, NULL, 0);
 710 }
 711 
 712 static void
 713 evp_cleanup(krb5_context context, struct key_data *kd)
     /* [<][>][^][v][top][bottom][index][help] */
 714 {
 715     struct evp_schedule *key = kd->schedule->data;
 716     EVP_CIPHER_CTX_cleanup(&key->ectx);
 717     EVP_CIPHER_CTX_cleanup(&key->dctx);
 718 }
 719 
 720 /*
 721  *
 722  */
 723 
 724 #ifdef WEAK_ENCTYPES
 725 static struct salt_type des_salt[] = {
 726     {
 727         KRB5_PW_SALT,
 728         "pw-salt",
 729         krb5_DES_string_to_key
 730     },
 731 #ifdef ENABLE_AFS_STRING_TO_KEY
 732     {
 733         KRB5_AFS3_SALT,
 734         "afs3-salt",
 735         DES_AFS3_string_to_key
 736     },
 737 #endif
 738     { 0 }
 739 };
 740 #endif
 741 
 742 #ifdef DES3_OLD_ENCTYPE
 743 static struct salt_type des3_salt[] = {
 744     {
 745         KRB5_PW_SALT,
 746         "pw-salt",
 747         DES3_string_to_key
 748     },
 749     { 0 }
 750 };
 751 #endif
 752 
 753 static struct salt_type des3_salt_derived[] = {
 754     {
 755         KRB5_PW_SALT,
 756         "pw-salt",
 757         DES3_string_to_key_derived
 758     },
 759     { 0 }
 760 };
 761 
 762 static struct salt_type AES_salt[] = {
 763     {
 764         KRB5_PW_SALT,
 765         "pw-salt",
 766         AES_string_to_key
 767     },
 768     { 0 }
 769 };
 770 
 771 static struct salt_type arcfour_salt[] = {
 772     {
 773         KRB5_PW_SALT,
 774         "pw-salt",
 775         ARCFOUR_string_to_key
 776     },
 777     { 0 }
 778 };
 779 
 780 /*
 781  *
 782  */
 783 
 784 static struct key_type keytype_null = {
 785     KEYTYPE_NULL,
 786     "null",
 787     0,
 788     0,
 789     0,
 790     NULL,
 791     NULL,
 792     NULL
 793 };
 794 
 795 #ifdef WEAK_ENCTYPES
 796 static struct key_type keytype_des_old = {
 797     KEYTYPE_DES,
 798     "des-old",
 799     56,
 800     8,
 801     sizeof(DES_key_schedule),
 802     krb5_DES_random_key,
 803     krb5_DES_schedule_old,
 804     des_salt,
 805     krb5_DES_random_to_key
 806 };
 807 
 808 static struct key_type keytype_des = {
 809     KEYTYPE_DES,
 810     "des",
 811     56,
 812     8,
 813     sizeof(struct evp_schedule),
 814     krb5_DES_random_key,
 815     evp_schedule,
 816     des_salt,
 817     krb5_DES_random_to_key,
 818     evp_cleanup,
 819     EVP_des_cbc
 820 };
 821 #endif /* WEAK_ENCTYPES */
 822 
 823 #ifdef DES3_OLD_ENCTYPE
 824 static struct key_type keytype_des3 = {
 825     KEYTYPE_DES3,
 826     "des3",
 827     168,
 828     24,
 829     sizeof(struct evp_schedule),
 830     DES3_random_key,
 831     evp_schedule,
 832     des3_salt,
 833     DES3_random_to_key,
 834     evp_cleanup,
 835     EVP_des_ede3_cbc
 836 };
 837 #endif
 838 
 839 static struct key_type keytype_des3_derived = {
 840     KEYTYPE_DES3,
 841     "des3",
 842     168,
 843     24,
 844     sizeof(struct evp_schedule),
 845     DES3_random_key,
 846     evp_schedule,
 847     des3_salt_derived,
 848     DES3_random_to_key,
 849     evp_cleanup,
 850     EVP_des_ede3_cbc
 851 };
 852 
 853 static struct key_type keytype_aes128 = {
 854     KEYTYPE_AES128,
 855     "aes-128",
 856     128,
 857     16,
 858     sizeof(struct evp_schedule),
 859     NULL,
 860     evp_schedule,
 861     AES_salt,
 862     NULL,
 863     evp_cleanup,
 864     EVP_hcrypto_aes_128_cts
 865 };
 866 
 867 static struct key_type keytype_aes256 = {
 868     KEYTYPE_AES256,
 869     "aes-256",
 870     256,
 871     32,
 872     sizeof(struct evp_schedule),
 873     NULL,
 874     evp_schedule,
 875     AES_salt,
 876     NULL,
 877     evp_cleanup,
 878     EVP_hcrypto_aes_256_cts
 879 };
 880 
 881 static struct key_type keytype_arcfour = {
 882     KEYTYPE_ARCFOUR,
 883     "arcfour",
 884     128,
 885     16,
 886     sizeof(RC4_KEY),
 887     NULL,
 888     ARCFOUR_schedule,
 889     arcfour_salt
 890 };
 891 
 892 krb5_error_code KRB5_LIB_FUNCTION
 893 krb5_salttype_to_string (krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
 894                          krb5_enctype etype,
 895                          krb5_salttype stype,
 896                          char **string)
 897 {
 898     struct encryption_type *e;
 899     struct salt_type *st;
 900 
 901     e = _find_enctype (etype);
 902     if (e == NULL) {
 903         krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
 904                                "encryption type %d not supported",
 905                                etype);
 906         return KRB5_PROG_ETYPE_NOSUPP;
 907     }
 908     for (st = e->keytype->string_to_key; st && st->type; st++) {
 909         if (st->type == stype) {
 910             *string = strdup (st->name);
 911             if (*string == NULL) {
 912                 krb5_set_error_message (context, ENOMEM,
 913                                         N_("malloc: out of memory", ""));
 914                 return ENOMEM;
 915             }
 916             return 0;
 917         }
 918     }
 919     krb5_set_error_message (context, HEIM_ERR_SALTTYPE_NOSUPP,
 920                             "salttype %d not supported", stype);
 921     return HEIM_ERR_SALTTYPE_NOSUPP;
 922 }
 923 
 924 krb5_error_code KRB5_LIB_FUNCTION
 925 krb5_string_to_salttype (krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
 926                          krb5_enctype etype,
 927                          const char *string,
 928                          krb5_salttype *salttype)
 929 {
 930     struct encryption_type *e;
 931     struct salt_type *st;
 932 
 933     e = _find_enctype (etype);
 934     if (e == NULL) {
 935         krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
 936                                N_("encryption type %d not supported", ""),
 937                                etype);
 938         return KRB5_PROG_ETYPE_NOSUPP;
 939     }
 940     for (st = e->keytype->string_to_key; st && st->type; st++) {
 941         if (strcasecmp (st->name, string) == 0) {
 942             *salttype = st->type;
 943             return 0;
 944         }
 945     }
 946     krb5_set_error_message(context, HEIM_ERR_SALTTYPE_NOSUPP,
 947                            N_("salttype %s not supported", ""), string);
 948     return HEIM_ERR_SALTTYPE_NOSUPP;
 949 }
 950 
 951 krb5_error_code KRB5_LIB_FUNCTION
 952 krb5_get_pw_salt(krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
 953                  krb5_const_principal principal,
 954                  krb5_salt *salt)
 955 {
 956     size_t len;
 957     int i;
 958     krb5_error_code ret;
 959     char *p;
 960 
 961     salt->salttype = KRB5_PW_SALT;
 962     len = strlen(principal->realm);
 963     for (i = 0; i < principal->name.name_string.len; ++i)
 964         len += strlen(principal->name.name_string.val[i]);
 965     ret = krb5_data_alloc (&salt->saltvalue, len);
 966     if (ret)
 967         return ret;
 968     p = salt->saltvalue.data;
 969     memcpy (p, principal->realm, strlen(principal->realm));
 970     p += strlen(principal->realm);
 971     for (i = 0; i < principal->name.name_string.len; ++i) {
 972         memcpy (p,
 973                 principal->name.name_string.val[i],
 974                 strlen(principal->name.name_string.val[i]));
 975         p += strlen(principal->name.name_string.val[i]);
 976     }
 977     return 0;
 978 }
 979 
 980 krb5_error_code KRB5_LIB_FUNCTION
 981 krb5_free_salt(krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
 982                krb5_salt salt)
 983 {
 984     krb5_data_free(&salt.saltvalue);
 985     return 0;
 986 }
 987 
 988 krb5_error_code KRB5_LIB_FUNCTION
 989 krb5_string_to_key_data (krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
 990                          krb5_enctype enctype,
 991                          krb5_data password,
 992                          krb5_principal principal,
 993                          krb5_keyblock *key)
 994 {
 995     krb5_error_code ret;
 996     krb5_salt salt;
 997 
 998     ret = krb5_get_pw_salt(context, principal, &salt);
 999     if(ret)
1000         return ret;
1001     ret = krb5_string_to_key_data_salt(context, enctype, password, salt, key);
1002     krb5_free_salt(context, salt);
1003     return ret;
1004 }
1005 
1006 krb5_error_code KRB5_LIB_FUNCTION
1007 krb5_string_to_key (krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
1008                     krb5_enctype enctype,
1009                     const char *password,
1010                     krb5_principal principal,
1011                     krb5_keyblock *key)
1012 {
1013     krb5_data pw;
1014     pw.data = rk_UNCONST(password);
1015     pw.length = strlen(password);
1016     return krb5_string_to_key_data(context, enctype, pw, principal, key);
1017 }
1018 
1019 krb5_error_code KRB5_LIB_FUNCTION
1020 krb5_string_to_key_data_salt (krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
1021                               krb5_enctype enctype,
1022                               krb5_data password,
1023                               krb5_salt salt,
1024                               krb5_keyblock *key)
1025 {
1026     krb5_data opaque;
1027     krb5_data_zero(&opaque);
1028     return krb5_string_to_key_data_salt_opaque(context, enctype, password,
1029                                                salt, opaque, key);
1030 }
1031 
1032 /*
1033  * Do a string -> key for encryption type `enctype' operation on
1034  * `password' (with salt `salt' and the enctype specific data string
1035  * `opaque'), returning the resulting key in `key'
1036  */
1037 
1038 krb5_error_code KRB5_LIB_FUNCTION
1039 krb5_string_to_key_data_salt_opaque (krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
1040                                      krb5_enctype enctype,
1041                                      krb5_data password,
1042                                      krb5_salt salt,
1043                                      krb5_data opaque,
1044                                      krb5_keyblock *key)
1045 {
1046     struct encryption_type *et =_find_enctype(enctype);
1047     struct salt_type *st;
1048     if(et == NULL) {
1049         krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
1050                                N_("encryption type %d not supported", ""),
1051                                enctype);
1052         return KRB5_PROG_ETYPE_NOSUPP;
1053     }
1054     for(st = et->keytype->string_to_key; st && st->type; st++)
1055         if(st->type == salt.salttype)
1056             return (*st->string_to_key)(context, enctype, password,
1057                                         salt, opaque, key);
1058     krb5_set_error_message(context, HEIM_ERR_SALTTYPE_NOSUPP,
1059                            N_("salt type %d not supported", ""),
1060                            salt.salttype);
1061     return HEIM_ERR_SALTTYPE_NOSUPP;
1062 }
1063 
1064 /*
1065  * Do a string -> key for encryption type `enctype' operation on the
1066  * string `password' (with salt `salt'), returning the resulting key
1067  * in `key'
1068  */
1069 
1070 krb5_error_code KRB5_LIB_FUNCTION
1071 krb5_string_to_key_salt (krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
1072                          krb5_enctype enctype,
1073                          const char *password,
1074                          krb5_salt salt,
1075                          krb5_keyblock *key)
1076 {
1077     krb5_data pw;
1078     pw.data = rk_UNCONST(password);
1079     pw.length = strlen(password);
1080     return krb5_string_to_key_data_salt(context, enctype, pw, salt, key);
1081 }
1082 
1083 krb5_error_code KRB5_LIB_FUNCTION
1084 krb5_string_to_key_salt_opaque (krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
1085                                 krb5_enctype enctype,
1086                                 const char *password,
1087                                 krb5_salt salt,
1088                                 krb5_data opaque,
1089                                 krb5_keyblock *key)
1090 {
1091     krb5_data pw;
1092     pw.data = rk_UNCONST(password);
1093     pw.length = strlen(password);
1094     return krb5_string_to_key_data_salt_opaque(context, enctype,
1095                                                pw, salt, opaque, key);
1096 }
1097 
1098 krb5_error_code KRB5_LIB_FUNCTION
1099 krb5_enctype_keysize(krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
1100                      krb5_enctype type,
1101                      size_t *keysize)
1102 {
1103     struct encryption_type *et = _find_enctype(type);
1104     if(et == NULL) {
1105         krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
1106                                N_("encryption type %d not supported", ""),
1107                                type);
1108         return KRB5_PROG_ETYPE_NOSUPP;
1109     }
1110     *keysize = et->keytype->size;
1111     return 0;
1112 }
1113 
1114 krb5_error_code KRB5_LIB_FUNCTION
1115 krb5_enctype_keybits(krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
1116                      krb5_enctype type,
1117                      size_t *keybits)
1118 {
1119     struct encryption_type *et = _find_enctype(type);
1120     if(et == NULL) {
1121         krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
1122                                "encryption type %d not supported",
1123                                type);
1124         return KRB5_PROG_ETYPE_NOSUPP;
1125     }
1126     *keybits = et->keytype->bits;
1127     return 0;
1128 }
1129 
1130 krb5_error_code KRB5_LIB_FUNCTION
1131 krb5_generate_random_keyblock(krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
1132                               krb5_enctype type,
1133                               krb5_keyblock *key)
1134 {
1135     krb5_error_code ret;
1136     struct encryption_type *et = _find_enctype(type);
1137     if(et == NULL) {
1138         krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
1139                                N_("encryption type %d not supported", ""),
1140                                type);
1141         return KRB5_PROG_ETYPE_NOSUPP;
1142     }
1143     ret = krb5_data_alloc(&key->keyvalue, et->keytype->size);
1144     if(ret)
1145         return ret;
1146     key->keytype = type;
1147     if(et->keytype->random_key)
1148         (*et->keytype->random_key)(context, key);
1149     else
1150         krb5_generate_random_block(key->keyvalue.data,
1151                                    key->keyvalue.length);
1152     return 0;
1153 }
1154 
1155 static krb5_error_code
1156 _key_schedule(krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
1157               struct key_data *key)
1158 {
1159     krb5_error_code ret;
1160     struct encryption_type *et = _find_enctype(key->key->keytype);
1161     struct key_type *kt = et->keytype;
1162 
1163     if(kt->schedule == NULL)
1164         return 0;
1165     if (key->schedule != NULL)
1166         return 0;
1167     ALLOC(key->schedule, 1);
1168     if(key->schedule == NULL) {
1169         krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
1170         return ENOMEM;
1171     }
1172     ret = krb5_data_alloc(key->schedule, kt->schedule_size);
1173     if(ret) {
1174         free(key->schedule);
1175         key->schedule = NULL;
1176         return ret;
1177     }
1178     (*kt->schedule)(context, kt, key);
1179     return 0;
1180 }
1181 
1182 /************************************************************
1183  *                                                          *
1184  ************************************************************/
1185 
1186 static krb5_error_code
1187 NONE_checksum(krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
1188               struct key_data *key,
1189               const void *data,
1190               size_t len,
1191               unsigned usage,
1192               Checksum *C)
1193 {
1194     return 0;
1195 }
1196 
1197 static krb5_error_code
1198 CRC32_checksum(krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
1199                struct key_data *key,
1200                const void *data,
1201                size_t len,
1202                unsigned usage,
1203                Checksum *C)
1204 {
1205     uint32_t crc;
1206     unsigned char *r = C->checksum.data;
1207     _krb5_crc_init_table ();
1208     crc = _krb5_crc_update (data, len, 0);
1209     r[0] = crc & 0xff;
1210     r[1] = (crc >> 8)  & 0xff;
1211     r[2] = (crc >> 16) & 0xff;
1212     r[3] = (crc >> 24) & 0xff;
1213     return 0;
1214 }
1215 
1216 static krb5_error_code
1217 RSA_MD4_checksum(krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
1218                  struct key_data *key,
1219                  const void *data,
1220                  size_t len,
1221                  unsigned usage,
1222                  Checksum *C)
1223 {
1224     if (EVP_Digest(data, len, C->checksum.data, NULL, EVP_md4(), NULL) != 1)
1225         krb5_abortx(context, "md4 checksum failed");
1226     return 0;
1227 }
1228 
1229 static krb5_error_code
1230 des_checksum(krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
1231              const EVP_MD *evp_md,
1232              struct key_data *key,
1233              const void *data,
1234              size_t len,
1235              Checksum *cksum)
1236 {
1237     struct evp_schedule *ctx = key->schedule->data;
1238     EVP_MD_CTX *m;
1239     DES_cblock ivec;
1240     unsigned char *p = cksum->checksum.data;
1241 
1242     krb5_generate_random_block(p, 8);
1243 
1244     m = EVP_MD_CTX_create();
1245     if (m == NULL) {
1246         krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
1247         return ENOMEM;
1248     }
1249 
1250     EVP_DigestInit_ex(m, evp_md, NULL);
1251     EVP_DigestUpdate(m, p, 8);
1252     EVP_DigestUpdate(m, data, len);
1253     EVP_DigestFinal_ex (m, p + 8, NULL);
1254     EVP_MD_CTX_destroy(m);
1255     memset (&ivec, 0, sizeof(ivec));
1256     EVP_CipherInit_ex(&ctx->ectx, NULL, NULL, NULL, (void *)&ivec, -1);
1257     EVP_Cipher(&ctx->ectx, p, p, 24);
1258 
1259     return 0;
1260 }
1261 
1262 static krb5_error_code
1263 des_verify(krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
1264            const EVP_MD *evp_md,
1265            struct key_data *key,
1266            const void *data,
1267            size_t len,
1268            Checksum *C)
1269 {
1270     struct evp_schedule *ctx = key->schedule->data;
1271     EVP_MD_CTX *m;
1272     unsigned char tmp[24];
1273     unsigned char res[16];
1274     DES_cblock ivec;
1275     krb5_error_code ret = 0;
1276 
1277     m = EVP_MD_CTX_create();
1278     if (m == NULL) {
1279         krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
1280         return ENOMEM;
1281     }
1282 
1283     memset(&ivec, 0, sizeof(ivec));
1284     EVP_CipherInit_ex(&ctx->dctx, NULL, NULL, NULL, (void *)&ivec, -1);
1285     EVP_Cipher(&ctx->dctx, tmp, C->checksum.data, 24);
1286 
1287     EVP_DigestInit_ex(m, evp_md, NULL);
1288     EVP_DigestUpdate(m, tmp, 8); /* confounder */
1289     EVP_DigestUpdate(m, data, len);
1290     EVP_DigestFinal_ex (m, res, NULL);
1291     EVP_MD_CTX_destroy(m);
1292     if(memcmp(res, tmp + 8, sizeof(res)) != 0) {
1293         krb5_clear_error_message (context);
1294         ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
1295     }
1296     memset(tmp, 0, sizeof(tmp));
1297     memset(res, 0, sizeof(res));
1298     return ret;
1299 }
1300 
1301 static krb5_error_code
1302 RSA_MD4_DES_checksum(krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
1303                      struct key_data *key,
1304                      const void *data,
1305                      size_t len,
1306                      unsigned usage,
1307                      Checksum *cksum)
1308 {
1309     return des_checksum(context, EVP_md4(), key, data, len, cksum);
1310 }
1311 
1312 static krb5_error_code
1313 RSA_MD4_DES_verify(krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
1314                    struct key_data *key,
1315                    const void *data,
1316                    size_t len,
1317                    unsigned usage,
1318                    Checksum *C)
1319 {
1320     return des_verify(context, EVP_md5(), key, data, len, C);
1321 }
1322 
1323 static krb5_error_code
1324 RSA_MD5_checksum(krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
1325                  struct key_data *key,
1326                  const void *data,
1327                  size_t len,
1328                  unsigned usage,
1329                  Checksum *C)
1330 {
1331     if (EVP_Digest(data, len, C->checksum.data, NULL, EVP_md5(), NULL) != 1)
1332         krb5_abortx(context, "md5 checksum failed");
1333     return 0;
1334 }
1335 
1336 static krb5_error_code
1337 RSA_MD5_DES_checksum(krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
1338                      struct key_data *key,
1339                      const void *data,
1340                      size_t len,
1341                      unsigned usage,
1342                      Checksum *C)
1343 {
1344     return des_checksum(context, EVP_md5(), key, data, len, C);
1345 }
1346 
1347 static krb5_error_code
1348 RSA_MD5_DES_verify(krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
1349                    struct key_data *key,
1350                    const void *data,
1351                    size_t len,
1352                    unsigned usage,
1353                    Checksum *C)
1354 {
1355     return des_verify(context, EVP_md5(), key, data, len, C);
1356 }
1357 
1358 #ifdef DES3_OLD_ENCTYPE
1359 static krb5_error_code
1360 RSA_MD5_DES3_checksum(krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
1361                       struct key_data *key,
1362                       const void *data,
1363                       size_t len,
1364                       unsigned usage,
1365                       Checksum *C)
1366 {
1367     return des_checksum(context, EVP_md5(), key, data, len, C);
1368 }
1369 
1370 static krb5_error_code
1371 RSA_MD5_DES3_verify(krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
1372                     struct key_data *key,
1373                     const void *data,
1374                     size_t len,
1375                     unsigned usage,
1376                     Checksum *C)
1377 {
1378     return des_verify(context, EVP_md5(), key, data, len, C);
1379 }
1380 #endif
1381 
1382 static krb5_error_code
1383 SHA1_checksum(krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
1384               struct key_data *key,
1385               const void *data,
1386               size_t len,
1387               unsigned usage,
1388               Checksum *C)
1389 {
1390     if (EVP_Digest(data, len, C->checksum.data, NULL, EVP_sha1(), NULL) != 1)
1391         krb5_abortx(context, "sha1 checksum failed");
1392     return 0;
1393 }
1394 
1395 /* HMAC according to RFC2104 */
1396 static krb5_error_code
1397 hmac(krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
1398      struct checksum_type *cm,
1399      const void *data,
1400      size_t len,
1401      unsigned usage,
1402      struct key_data *keyblock,
1403      Checksum *result)
1404 {
1405     unsigned char *ipad, *opad;
1406     unsigned char *key;
1407     size_t key_len;
1408     int i;
1409 
1410     ipad = malloc(cm->blocksize + len);
1411     if (ipad == NULL)
1412         return ENOMEM;
1413     opad = malloc(cm->blocksize + cm->checksumsize);
1414     if (opad == NULL) {
1415         free(ipad);
1416         return ENOMEM;
1417     }
1418     memset(ipad, 0x36, cm->blocksize);
1419     memset(opad, 0x5c, cm->blocksize);
1420 
1421     if(keyblock->key->keyvalue.length > cm->blocksize){
1422         (*cm->checksum)(context,
1423                         keyblock,
1424                         keyblock->key->keyvalue.data,
1425                         keyblock->key->keyvalue.length,
1426                         usage,
1427                         result);
1428         key = result->checksum.data;
1429         key_len = result->checksum.length;
1430     } else {
1431         key = keyblock->key->keyvalue.data;
1432         key_len = keyblock->key->keyvalue.length;
1433     }
1434     for(i = 0; i < key_len; i++){
1435         ipad[i] ^= key[i];
1436         opad[i] ^= key[i];
1437     }
1438     memcpy(ipad + cm->blocksize, data, len);
1439     (*cm->checksum)(context, keyblock, ipad, cm->blocksize + len,
1440                     usage, result);
1441     memcpy(opad + cm->blocksize, result->checksum.data,
1442            result->checksum.length);
1443     (*cm->checksum)(context, keyblock, opad,
1444                     cm->blocksize + cm->checksumsize, usage, result);
1445     memset(ipad, 0, cm->blocksize + len);
1446     free(ipad);
1447     memset(opad, 0, cm->blocksize + cm->checksumsize);
1448     free(opad);
1449 
1450     return 0;
1451 }
1452 
1453 krb5_error_code KRB5_LIB_FUNCTION
1454 krb5_hmac(krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
1455           krb5_cksumtype cktype,
1456           const void *data,
1457           size_t len,
1458           unsigned usage,
1459           krb5_keyblock *key,
1460           Checksum *result)
1461 {
1462     struct checksum_type *c = _find_checksum(cktype);
1463     struct key_data kd;
1464     krb5_error_code ret;
1465 
1466     if (c == NULL) {
1467         krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
1468                                 N_("checksum type %d not supported", ""),
1469                                 cktype);
1470         return KRB5_PROG_SUMTYPE_NOSUPP;
1471     }
1472 
1473     kd.key = key;
1474     kd.schedule = NULL;
1475 
1476     ret = hmac(context, c, data, len, usage, &kd, result);
1477 
1478     if (kd.schedule)
1479         krb5_free_data(context, kd.schedule);
1480 
1481     return ret;
1482 }
1483 
1484 static krb5_error_code
1485 SP_HMAC_SHA1_checksum(krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
1486                       struct key_data *key,
1487                       const void *data,
1488                       size_t len,
1489                       unsigned usage,
1490                       Checksum *result)
1491 {
1492     struct checksum_type *c = _find_checksum(CKSUMTYPE_SHA1);
1493     Checksum res;
1494     char sha1_data[20];
1495     krb5_error_code ret;
1496 
1497     res.checksum.data = sha1_data;
1498     res.checksum.length = sizeof(sha1_data);
1499 
1500     ret = hmac(context, c, data, len, usage, key, &res);
1501     if (ret)
1502         krb5_abortx(context, "hmac failed");
1503     memcpy(result->checksum.data, res.checksum.data, result->checksum.length);
1504     return 0;
1505 }
1506 
1507 /*
1508  * checksum according to section 5. of draft-brezak-win2k-krb-rc4-hmac-03.txt
1509  */
1510 
1511 static krb5_error_code
1512 HMAC_MD5_checksum(krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
1513                   struct key_data *key,
1514                   const void *data,
1515                   size_t len,
1516                   unsigned usage,
1517                   Checksum *result)
1518 {
1519     EVP_MD_CTX *m;
1520     struct checksum_type *c = _find_checksum (CKSUMTYPE_RSA_MD5);
1521     const char signature[] = "signaturekey";
1522     Checksum ksign_c;
1523     struct key_data ksign;
1524     krb5_keyblock kb;
1525     unsigned char t[4];
1526     unsigned char tmp[16];
1527     unsigned char ksign_c_data[16];
1528     krb5_error_code ret;
1529 
1530     m = EVP_MD_CTX_create();
1531     if (m == NULL) {
1532         krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
1533         return ENOMEM;
1534     }
1535     ksign_c.checksum.length = sizeof(ksign_c_data);
1536     ksign_c.checksum.data   = ksign_c_data;
1537     ret = hmac(context, c, signature, sizeof(signature), 0, key, &ksign_c);
1538     if (ret) {
1539         EVP_MD_CTX_destroy(m);
1540         return ret;
1541     }
1542     ksign.key = &kb;
1543     kb.keyvalue = ksign_c.checksum;
1544     EVP_DigestInit_ex(m, EVP_md5(), NULL);
1545     t[0] = (usage >>  0) & 0xFF;
1546     t[1] = (usage >>  8) & 0xFF;
1547     t[2] = (usage >> 16) & 0xFF;
1548     t[3] = (usage >> 24) & 0xFF;
1549     EVP_DigestUpdate(m, t, 4);
1550     EVP_DigestUpdate(m, data, len);
1551     EVP_DigestFinal_ex (m, tmp, NULL);
1552     EVP_MD_CTX_destroy(m);
1553 
1554     ret = hmac(context, c, tmp, sizeof(tmp), 0, &ksign, result);
1555     if (ret)
1556         return ret;
1557     return 0;
1558 }
1559 
1560 static struct checksum_type checksum_none = {
1561     CKSUMTYPE_NONE,
1562     "none",
1563     1,
1564     0,
1565     0,
1566     NONE_checksum,
1567     NULL
1568 };
1569 static struct checksum_type checksum_crc32 = {
1570     CKSUMTYPE_CRC32,
1571     "crc32",
1572     1,
1573     4,
1574     0,
1575     CRC32_checksum,
1576     NULL
1577 };
1578 static struct checksum_type checksum_rsa_md4 = {
1579     CKSUMTYPE_RSA_MD4,
1580     "rsa-md4",
1581     64,
1582     16,
1583     F_CPROOF,
1584     RSA_MD4_checksum,
1585     NULL
1586 };
1587 static struct checksum_type checksum_rsa_md4_des = {
1588     CKSUMTYPE_RSA_MD4_DES,
1589     "rsa-md4-des",
1590     64,
1591     24,
1592     F_KEYED | F_CPROOF | F_VARIANT,
1593     RSA_MD4_DES_checksum,
1594     RSA_MD4_DES_verify
1595 };
1596 static struct checksum_type checksum_rsa_md5 = {
1597     CKSUMTYPE_RSA_MD5,
1598     "rsa-md5",
1599     64,
1600     16,
1601     F_CPROOF,
1602     RSA_MD5_checksum,
1603     NULL
1604 };
1605 static struct checksum_type checksum_rsa_md5_des = {
1606     CKSUMTYPE_RSA_MD5_DES,
1607     "rsa-md5-des",
1608     64,
1609     24,
1610     F_KEYED | F_CPROOF | F_VARIANT,
1611     RSA_MD5_DES_checksum,
1612     RSA_MD5_DES_verify
1613 };
1614 #ifdef DES3_OLD_ENCTYPE
1615 static struct checksum_type checksum_rsa_md5_des3 = {
1616     CKSUMTYPE_RSA_MD5_DES3,
1617     "rsa-md5-des3",
1618     64,
1619     24,
1620     F_KEYED | F_CPROOF | F_VARIANT,
1621     RSA_MD5_DES3_checksum,
1622     RSA_MD5_DES3_verify
1623 };
1624 #endif
1625 static struct checksum_type checksum_sha1 = {
1626     CKSUMTYPE_SHA1,
1627     "sha1",
1628     64,
1629     20,
1630     F_CPROOF,
1631     SHA1_checksum,
1632     NULL
1633 };
1634 static struct checksum_type checksum_hmac_sha1_des3 = {
1635     CKSUMTYPE_HMAC_SHA1_DES3,
1636     "hmac-sha1-des3",
1637     64,
1638     20,
1639     F_KEYED | F_CPROOF | F_DERIVED,
1640     SP_HMAC_SHA1_checksum,
1641     NULL
1642 };
1643 
1644 static struct checksum_type checksum_hmac_sha1_aes128 = {
1645     CKSUMTYPE_HMAC_SHA1_96_AES_128,
1646     "hmac-sha1-96-aes128",
1647     64,
1648     12,
1649     F_KEYED | F_CPROOF | F_DERIVED,
1650     SP_HMAC_SHA1_checksum,
1651     NULL
1652 };
1653 
1654 static struct checksum_type checksum_hmac_sha1_aes256 = {
1655     CKSUMTYPE_HMAC_SHA1_96_AES_256,
1656     "hmac-sha1-96-aes256",
1657     64,
1658     12,
1659     F_KEYED | F_CPROOF | F_DERIVED,
1660     SP_HMAC_SHA1_checksum,
1661     NULL
1662 };
1663 
1664 static struct checksum_type checksum_hmac_md5 = {
1665     CKSUMTYPE_HMAC_MD5,
1666     "hmac-md5",
1667     64,
1668     16,
1669     F_KEYED | F_CPROOF,
1670     HMAC_MD5_checksum,
1671     NULL
1672 };
1673 
1674 static struct checksum_type *checksum_types[] = {
1675     &checksum_none,
1676     &checksum_crc32,
1677     &checksum_rsa_md4,
1678     &checksum_rsa_md4_des,
1679     &checksum_rsa_md5,
1680     &checksum_rsa_md5_des,
1681 #ifdef DES3_OLD_ENCTYPE
1682     &checksum_rsa_md5_des3,
1683 #endif
1684     &checksum_sha1,
1685     &checksum_hmac_sha1_des3,
1686     &checksum_hmac_sha1_aes128,
1687     &checksum_hmac_sha1_aes256,
1688     &checksum_hmac_md5
1689 };
1690 
1691 static int num_checksums = sizeof(checksum_types) / sizeof(checksum_types[0]);
1692 
1693 static struct checksum_type *
1694 _find_checksum(krb5_cksumtype type)
     /* [<][>][^][v][top][bottom][index][help] */
1695 {
1696     int i;
1697     for(i = 0; i < num_checksums; i++)
1698         if(checksum_types[i]->type == type)
1699             return checksum_types[i];
1700     return NULL;
1701 }
1702 
1703 static krb5_error_code
1704 get_checksum_key(krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
1705                  krb5_crypto crypto,
1706                  unsigned usage,  /* not krb5_key_usage */
1707                  struct checksum_type *ct,
1708                  struct key_data **key)
1709 {
1710     krb5_error_code ret = 0;
1711 
1712     if(ct->flags & F_DERIVED)
1713         ret = _get_derived_key(context, crypto, usage, key);
1714     else if(ct->flags & F_VARIANT) {
1715         int i;
1716 
1717         *key = _new_derived_key(crypto, 0xff/* KRB5_KU_RFC1510_VARIANT */);
1718         if(*key == NULL) {
1719             krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
1720             return ENOMEM;
1721         }
1722         ret = krb5_copy_keyblock(context, crypto->key.key, &(*key)->key);
1723         if(ret)
1724             return ret;
1725         for(i = 0; i < (*key)->key->keyvalue.length; i++)
1726             ((unsigned char*)(*key)->key->keyvalue.data)[i] ^= 0xF0;
1727     } else {
1728         *key = &crypto->key;
1729     }
1730     if(ret == 0)
1731         ret = _key_schedule(context, *key);
1732     return ret;
1733 }
1734 
1735 static krb5_error_code
1736 create_checksum (krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
1737                  struct checksum_type *ct,
1738                  krb5_crypto crypto,
1739                  unsigned usage,
1740                  void *data,
1741                  size_t len,
1742                  Checksum *result)
1743 {
1744     krb5_error_code ret;
1745     struct key_data *dkey;
1746     int keyed_checksum;
1747 
1748     if (ct->flags & F_DISABLED) {
1749         krb5_clear_error_message (context);
1750         return KRB5_PROG_SUMTYPE_NOSUPP;
1751     }
1752     keyed_checksum = (ct->flags & F_KEYED) != 0;
1753     if(keyed_checksum && crypto == NULL) {
1754         krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
1755                                 N_("Checksum type %s is keyed but no "
1756                                    "crypto context (key) was passed in", ""),
1757                                 ct->name);
1758         return KRB5_PROG_SUMTYPE_NOSUPP; /* XXX */
1759     }
1760     if(keyed_checksum) {
1761         ret = get_checksum_key(context, crypto, usage, ct, &dkey);
1762         if (ret)
1763             return ret;
1764     } else
1765         dkey = NULL;
1766     result->cksumtype = ct->type;
1767     ret = krb5_data_alloc(&result->checksum, ct->checksumsize);
1768     if (ret)
1769         return (ret);
1770     return (*ct->checksum)(context, dkey, data, len, usage, result);
1771 }
1772 
1773 static int
1774 arcfour_checksum_p(struct checksum_type *ct, krb5_crypto crypto)
     /* [<][>][^][v][top][bottom][index][help] */
1775 {
1776     return (ct->type == CKSUMTYPE_HMAC_MD5) &&
1777         (crypto->key.key->keytype == KEYTYPE_ARCFOUR);
1778 }
1779 
1780 krb5_error_code KRB5_LIB_FUNCTION
1781 krb5_create_checksum(krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
1782                      krb5_crypto crypto,
1783                      krb5_key_usage usage,
1784                      int type,
1785                      void *data,
1786                      size_t len,
1787                      Checksum *result)
1788 {
1789     struct checksum_type *ct = NULL;
1790     unsigned keyusage;
1791 
1792     /* type 0 -> pick from crypto */
1793     if (type) {
1794         ct = _find_checksum(type);
1795     } else if (crypto) {
1796         ct = crypto->et->keyed_checksum;
1797         if (ct == NULL)
1798             ct = crypto->et->checksum;
1799     }
1800 
1801     if(ct == NULL) {
1802         krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
1803                                 N_("checksum type %d not supported", ""),
1804                                 type);
1805         return KRB5_PROG_SUMTYPE_NOSUPP;
1806     }
1807 
1808     if (arcfour_checksum_p(ct, crypto)) {
1809         keyusage = usage;
1810         usage2arcfour(context, &keyusage);
1811     } else
1812         keyusage = CHECKSUM_USAGE(usage);
1813 
1814     return create_checksum(context, ct, crypto, keyusage,
1815                            data, len, result);
1816 }
1817 
1818 static krb5_error_code
1819 verify_checksum(krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
1820                 krb5_crypto crypto,
1821                 unsigned usage, /* not krb5_key_usage */
1822                 void *data,
1823                 size_t len,
1824                 Checksum *cksum)
1825 {
1826     krb5_error_code ret;
1827     struct key_data *dkey;
1828     int keyed_checksum;
1829     Checksum c;
1830     struct checksum_type *ct;
1831 
1832     ct = _find_checksum(cksum->cksumtype);
1833     if (ct == NULL || (ct->flags & F_DISABLED)) {
1834         krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
1835                                 N_("checksum type %d not supported", ""),
1836                                 cksum->cksumtype);
1837         return KRB5_PROG_SUMTYPE_NOSUPP;
1838     }
1839     if(ct->checksumsize != cksum->checksum.length) {
1840         krb5_clear_error_message (context);
1841         return KRB5KRB_AP_ERR_BAD_INTEGRITY; /* XXX */
1842     }
1843     keyed_checksum = (ct->flags & F_KEYED) != 0;
1844     if(keyed_checksum && crypto == NULL) {
1845         krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
1846                                 N_("Checksum type %s is keyed but no "
1847                                    "crypto context (key) was passed in", ""),
1848                                 ct->name);
1849         return KRB5_PROG_SUMTYPE_NOSUPP; /* XXX */
1850     }
1851     if(keyed_checksum) {
1852         ret = get_checksum_key(context, crypto, usage, ct, &dkey);
1853         if (ret)
1854             return ret;
1855     } else
1856         dkey = NULL;
1857     if(ct->verify)
1858         return (*ct->verify)(context, dkey, data, len, usage, cksum);
1859 
1860     ret = krb5_data_alloc (&c.checksum, ct->checksumsize);
1861     if (ret)
1862         return ret;
1863 
1864     ret = (*ct->checksum)(context, dkey, data, len, usage, &c);
1865     if (ret) {
1866         krb5_data_free(&c.checksum);
1867         return ret;
1868     }
1869 
1870     if(c.checksum.length != cksum->checksum.length ||
1871        memcmp(c.checksum.data, cksum->checksum.data, c.checksum.length)) {
1872         krb5_clear_error_message (context);
1873         ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
1874     } else {
1875         ret = 0;
1876     }
1877     krb5_data_free (&c.checksum);
1878     return ret;
1879 }
1880 
1881 krb5_error_code KRB5_LIB_FUNCTION
1882 krb5_verify_checksum(krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
1883                      krb5_crypto crypto,
1884                      krb5_key_usage usage,
1885                      void *data,
1886                      size_t len,
1887                      Checksum *cksum)
1888 {
1889     struct checksum_type *ct;
1890     unsigned keyusage;
1891 
1892     ct = _find_checksum(cksum->cksumtype);
1893     if(ct == NULL) {
1894         krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
1895                                 N_("checksum type %d not supported", ""),
1896                                 cksum->cksumtype);
1897         return KRB5_PROG_SUMTYPE_NOSUPP;
1898     }
1899 
1900     if (arcfour_checksum_p(ct, crypto)) {
1901         keyusage = usage;
1902         usage2arcfour(context, &keyusage);
1903     } else
1904         keyusage = CHECKSUM_USAGE(usage);
1905 
1906     return verify_checksum(context, crypto, keyusage,
1907                            data, len, cksum);
1908 }
1909 
1910 krb5_error_code KRB5_LIB_FUNCTION
1911 krb5_crypto_get_checksum_type(krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
1912                               krb5_crypto crypto,
1913                               krb5_cksumtype *type)
1914 {
1915     struct checksum_type *ct = NULL;
1916 
1917     if (crypto != NULL) {
1918         ct = crypto->et->keyed_checksum;
1919         if (ct == NULL)
1920             ct = crypto->et->checksum;
1921     }
1922 
1923     if (ct == NULL) {
1924         krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
1925                                 N_("checksum type not found", ""));
1926         return KRB5_PROG_SUMTYPE_NOSUPP;
1927     }
1928 
1929     *type = ct->type;
1930 
1931     return 0;
1932 }
1933 
1934 
1935 krb5_error_code KRB5_LIB_FUNCTION
1936 krb5_checksumsize(krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
1937                   krb5_cksumtype type,
1938                   size_t *size)
1939 {
1940     struct checksum_type *ct = _find_checksum(type);
1941     if(ct == NULL) {
1942         krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
1943                                 N_("checksum type %d not supported", ""),
1944                                 type);
1945         return KRB5_PROG_SUMTYPE_NOSUPP;
1946     }
1947     *size = ct->checksumsize;
1948     return 0;
1949 }
1950 
1951 krb5_boolean KRB5_LIB_FUNCTION
1952 krb5_checksum_is_keyed(krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
1953                        krb5_cksumtype type)
1954 {
1955     struct checksum_type *ct = _find_checksum(type);
1956     if(ct == NULL) {
1957         if (context)
1958             krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
1959                                     N_("checksum type %d not supported", ""),
1960                                     type);
1961         return KRB5_PROG_SUMTYPE_NOSUPP;
1962     }
1963     return ct->flags & F_KEYED;
1964 }
1965 
1966 krb5_boolean KRB5_LIB_FUNCTION
1967 krb5_checksum_is_collision_proof(krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
1968                                  krb5_cksumtype type)
1969 {
1970     struct checksum_type *ct = _find_checksum(type);
1971     if(ct == NULL) {
1972         if (context)
1973             krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
1974                                     N_("checksum type %d not supported", ""),
1975                                     type);
1976         return KRB5_PROG_SUMTYPE_NOSUPP;
1977     }
1978     return ct->flags & F_CPROOF;
1979 }
1980 
1981 krb5_error_code KRB5_LIB_FUNCTION
1982 krb5_checksum_disable(krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
1983                       krb5_cksumtype type)
1984 {
1985     struct checksum_type *ct = _find_checksum(type);
1986     if(ct == NULL) {
1987         if (context)
1988             krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
1989                                     N_("checksum type %d not supported", ""),
1990                                     type);
1991         return KRB5_PROG_SUMTYPE_NOSUPP;
1992     }
1993     ct->flags |= F_DISABLED;
1994     return 0;
1995 }
1996 
1997 /************************************************************
1998  *                                                          *
1999  ************************************************************/
2000 
2001 static krb5_error_code
2002 NULL_encrypt(krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
2003              struct key_data *key,
2004              void *data,
2005              size_t len,
2006              krb5_boolean encryptp,
2007              int usage,
2008              void *ivec)
2009 {
2010     return 0;
2011 }
2012 
2013 static krb5_error_code
2014 evp_encrypt(krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
2015             struct key_data *key,
2016             void *data,
2017             size_t len,
2018             krb5_boolean encryptp,
2019             int usage,
2020             void *ivec)
2021 {
2022     struct evp_schedule *ctx = key->schedule->data;
2023     EVP_CIPHER_CTX *c;
2024     c = encryptp ? &ctx->ectx : &ctx->dctx;
2025     if (ivec == NULL) {
2026         /* alloca ? */
2027         size_t len = EVP_CIPHER_CTX_iv_length(c);
2028         void *loiv = malloc(len);
2029         if (loiv == NULL) {
2030             krb5_clear_error_message(context);
2031             return ENOMEM;
2032         }
2033         memset(loiv, 0, len);
2034         EVP_CipherInit_ex(c, NULL, NULL, NULL, loiv, -1);
2035         free(loiv);
2036     } else
2037         EVP_CipherInit_ex(c, NULL, NULL, NULL, ivec, -1);
2038     EVP_Cipher(c, data, data, len);
2039     return 0;
2040 }
2041 
2042 #ifdef WEAK_ENCTYPES
2043 static krb5_error_code
2044 evp_des_encrypt_null_ivec(krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
2045                           struct key_data *key,
2046                           void *data,
2047                           size_t len,
2048                           krb5_boolean encryptp,
2049                           int usage,
2050                           void *ignore_ivec)
2051 {
2052     struct evp_schedule *ctx = key->schedule->data;
2053     EVP_CIPHER_CTX *c;
2054     DES_cblock ivec;
2055     memset(&ivec, 0, sizeof(ivec));
2056     c = encryptp ? &ctx->ectx : &ctx->dctx;
2057     EVP_CipherInit_ex(c, NULL, NULL, NULL, (void *)&ivec, -1);
2058     EVP_Cipher(c, data, data, len);
2059     return 0;
2060 }
2061 
2062 static krb5_error_code
2063 evp_des_encrypt_key_ivec(krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
2064                          struct key_data *key,
2065                          void *data,
2066                          size_t len,
2067                          krb5_boolean encryptp,
2068                          int usage,
2069                          void *ignore_ivec)
2070 {
2071     struct evp_schedule *ctx = key->schedule->data;
2072     EVP_CIPHER_CTX *c;
2073     DES_cblock ivec;
2074     memcpy(&ivec, key->key->keyvalue.data, sizeof(ivec));
2075     c = encryptp ? &ctx->ectx : &ctx->dctx;
2076     EVP_CipherInit_ex(c, NULL, NULL, NULL, (void *)&ivec, -1);
2077     EVP_Cipher(c, data, data, len);
2078     return 0;
2079 }
2080 
2081 static krb5_error_code
2082 DES_CFB64_encrypt_null_ivec(krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
2083                             struct key_data *key,
2084                             void *data,
2085                             size_t len,
2086                             krb5_boolean encryptp,
2087                             int usage,
2088                             void *ignore_ivec)
2089 {
2090     DES_cblock ivec;
2091     int num = 0;
2092     DES_key_schedule *s = key->schedule->data;
2093     memset(&ivec, 0, sizeof(ivec));
2094 
2095     DES_cfb64_encrypt(data, data, len, s, &ivec, &num, encryptp);
2096     return 0;
2097 }
2098 
2099 static krb5_error_code
2100 DES_PCBC_encrypt_key_ivec(krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
2101                           struct key_data *key,
2102                           void *data,
2103                           size_t len,
2104                           krb5_boolean encryptp,
2105                           int usage,
2106                           void *ignore_ivec)
2107 {
2108     DES_cblock ivec;
2109     DES_key_schedule *s = key->schedule->data;
2110     memcpy(&ivec, key->key->keyvalue.data, sizeof(ivec));
2111 
2112     DES_pcbc_encrypt(data, data, len, s, &ivec, encryptp);
2113     return 0;
2114 }
2115 #endif
2116 
2117 /*
2118  * section 6 of draft-brezak-win2k-krb-rc4-hmac-03
2119  *
2120  * warning: not for small children
2121  */
2122 
2123 static krb5_error_code
2124 ARCFOUR_subencrypt(krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
2125                    struct key_data *key,
2126                    void *data,
2127                    size_t len,
2128                    unsigned usage,
2129                    void *ivec)
2130 {
2131     struct checksum_type *c = _find_checksum (CKSUMTYPE_RSA_MD5);
2132     Checksum k1_c, k2_c, k3_c, cksum;
2133     struct key_data ke;
2134     krb5_keyblock kb;
2135     unsigned char t[4];
2136     RC4_KEY rc4_key;
2137     unsigned char *cdata = data;
2138     unsigned char k1_c_data[16], k2_c_data[16], k3_c_data[16];
2139     krb5_error_code ret;
2140 
2141     t[0] = (usage >>  0) & 0xFF;
2142     t[1] = (usage >>  8) & 0xFF;
2143     t[2] = (usage >> 16) & 0xFF;
2144     t[3] = (usage >> 24) & 0xFF;
2145 
2146     k1_c.checksum.length = sizeof(k1_c_data);
2147     k1_c.checksum.data   = k1_c_data;
2148 
2149     ret = hmac(NULL, c, t, sizeof(t), 0, key, &k1_c);
2150     if (ret)
2151         krb5_abortx(context, "hmac failed");
2152 
2153     memcpy (k2_c_data, k1_c_data, sizeof(k1_c_data));
2154 
2155     k2_c.checksum.length = sizeof(k2_c_data);
2156     k2_c.checksum.data   = k2_c_data;
2157 
2158     ke.key = &kb;
2159     kb.keyvalue = k2_c.checksum;
2160 
2161     cksum.checksum.length = 16;
2162     cksum.checksum.data   = data;
2163 
2164     ret = hmac(NULL, c, cdata + 16, len - 16, 0, &ke, &cksum);
2165     if (ret)
2166         krb5_abortx(context, "hmac failed");
2167 
2168     ke.key = &kb;
2169     kb.keyvalue = k1_c.checksum;
2170 
2171     k3_c.checksum.length = sizeof(k3_c_data);
2172     k3_c.checksum.data   = k3_c_data;
2173 
2174     ret = hmac(NULL, c, data, 16, 0, &ke, &k3_c);
2175     if (ret)
2176         krb5_abortx(context, "hmac failed");
2177 
2178     RC4_set_key (&rc4_key, k3_c.checksum.length, k3_c.checksum.data);
2179     RC4 (&rc4_key, len - 16, cdata + 16, cdata + 16);
2180     memset (k1_c_data, 0, sizeof(k1_c_data));
2181     memset (k2_c_data, 0, sizeof(k2_c_data));
2182     memset (k3_c_data, 0, sizeof(k3_c_data));
2183     return 0;
2184 }
2185 
2186 static krb5_error_code
2187 ARCFOUR_subdecrypt(krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
2188                    struct key_data *key,
2189                    void *data,
2190                    size_t len,
2191                    unsigned usage,
2192                    void *ivec)
2193 {
2194     struct checksum_type *c = _find_checksum (CKSUMTYPE_RSA_MD5);
2195     Checksum k1_c, k2_c, k3_c, cksum;
2196     struct key_data ke;
2197     krb5_keyblock kb;
2198     unsigned char t[4];
2199     RC4_KEY rc4_key;
2200     unsigned char *cdata = data;
2201     unsigned char k1_c_data[16], k2_c_data[16], k3_c_data[16];
2202     unsigned char cksum_data[16];
2203     krb5_error_code ret;
2204 
2205     t[0] = (usage >>  0) & 0xFF;
2206     t[1] = (usage >>  8) & 0xFF;
2207     t[2] = (usage >> 16) & 0xFF;
2208     t[3] = (usage >> 24) & 0xFF;
2209 
2210     k1_c.checksum.length = sizeof(k1_c_data);
2211     k1_c.checksum.data   = k1_c_data;
2212 
2213     ret = hmac(NULL, c, t, sizeof(t), 0, key, &k1_c);
2214     if (ret)
2215         krb5_abortx(context, "hmac failed");
2216 
2217     memcpy (k2_c_data, k1_c_data, sizeof(k1_c_data));
2218 
2219     k2_c.checksum.length = sizeof(k2_c_data);
2220     k2_c.checksum.data   = k2_c_data;
2221 
2222     ke.key = &kb;
2223     kb.keyvalue = k1_c.checksum;
2224 
2225     k3_c.checksum.length = sizeof(k3_c_data);
2226     k3_c.checksum.data   = k3_c_data;
2227 
2228     ret = hmac(NULL, c, cdata, 16, 0, &ke, &k3_c);
2229     if (ret)
2230         krb5_abortx(context, "hmac failed");
2231 
2232     RC4_set_key (&rc4_key, k3_c.checksum.length, k3_c.checksum.data);
2233     RC4 (&rc4_key, len - 16, cdata + 16, cdata + 16);
2234 
2235     ke.key = &kb;
2236     kb.keyvalue = k2_c.checksum;
2237 
2238     cksum.checksum.length = 16;
2239     cksum.checksum.data   = cksum_data;
2240 
2241     ret = hmac(NULL, c, cdata + 16, len - 16, 0, &ke, &cksum);
2242     if (ret)
2243         krb5_abortx(context, "hmac failed");
2244 
2245     memset (k1_c_data, 0, sizeof(k1_c_data));
2246     memset (k2_c_data, 0, sizeof(k2_c_data));
2247     memset (k3_c_data, 0, sizeof(k3_c_data));
2248 
2249     if (memcmp (cksum.checksum.data, data, 16) != 0) {
2250         krb5_clear_error_message (context);
2251         return KRB5KRB_AP_ERR_BAD_INTEGRITY;
2252     } else {
2253         return 0;
2254     }
2255 }
2256 
2257 /*
2258  * convert the usage numbers used in
2259  * draft-ietf-cat-kerb-key-derivation-00.txt to the ones in
2260  * draft-brezak-win2k-krb-rc4-hmac-04.txt
2261  */
2262 
2263 static krb5_error_code
2264 usage2arcfour (krb5_context context, unsigned *usage)
     /* [<][>][^][v][top][bottom][index][help] */
2265 {
2266     switch (*usage) {
2267     case KRB5_KU_AS_REP_ENC_PART : /* 3 */
2268     case KRB5_KU_TGS_REP_ENC_PART_SUB_KEY : /* 9 */
2269         *usage = 8;
2270         return 0;
2271     case KRB5_KU_USAGE_SEAL :  /* 22 */
2272         *usage = 13;
2273         return 0;
2274     case KRB5_KU_USAGE_SIGN : /* 23 */
2275         *usage = 15;
2276         return 0;
2277     case KRB5_KU_USAGE_SEQ: /* 24 */
2278         *usage = 0;
2279         return 0;
2280     default :
2281         return 0;
2282     }
2283 }
2284 
2285 static krb5_error_code
2286 ARCFOUR_encrypt(krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
2287                 struct key_data *key,
2288                 void *data,
2289                 size_t len,
2290                 krb5_boolean encryptp,
2291                 int usage,
2292                 void *ivec)
2293 {
2294     krb5_error_code ret;
2295     unsigned keyusage = usage;
2296 
2297     if((ret = usage2arcfour (context, &keyusage)) != 0)
2298         return ret;
2299 
2300     if (encryptp)
2301         return ARCFOUR_subencrypt (context, key, data, len, keyusage, ivec);
2302     else
2303         return ARCFOUR_subdecrypt (context, key, data, len, keyusage, ivec);
2304 }
2305 
2306 
2307 /*
2308  *
2309  */
2310 
2311 static krb5_error_code
2312 AES_PRF(krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
2313         krb5_crypto crypto,
2314         const krb5_data *in,
2315         krb5_data *out)
2316 {
2317     struct checksum_type *ct = crypto->et->checksum;
2318     krb5_error_code ret;
2319     Checksum result;
2320     krb5_keyblock *derived;
2321 
2322     result.cksumtype = ct->type;
2323     ret = krb5_data_alloc(&result.checksum, ct->checksumsize);
2324     if (ret) {
2325         krb5_set_error_message(context, ret, N_("malloc: out memory", ""));
2326         return ret;
2327     }
2328 
2329     ret = (*ct->checksum)(context, NULL, in->data, in->length, 0, &result);
2330     if (ret) {
2331         krb5_data_free(&result.checksum);
2332         return ret;
2333     }
2334 
2335     if (result.checksum.length < crypto->et->blocksize)
2336         krb5_abortx(context, "internal prf error");
2337 
2338     derived = NULL;
2339     ret = krb5_derive_key(context, crypto->key.key,
2340                           crypto->et->type, "prf", 3, &derived);
2341     if (ret)
2342         krb5_abortx(context, "krb5_derive_key");
2343 
2344     ret = krb5_data_alloc(out, crypto->et->blocksize);
2345     if (ret)
2346         krb5_abortx(context, "malloc failed");
2347 
2348     {
2349         const EVP_CIPHER *c = (*crypto->et->keytype->evp)();
2350         EVP_CIPHER_CTX ctx;
2351         /* XXX blksz 1 for cts, so we can't use that */
2352         EVP_CIPHER_CTX_init(&ctx); /* ivec all zero */
2353         EVP_CipherInit_ex(&ctx, c, NULL, derived->keyvalue.data, NULL, 1);
2354         EVP_Cipher(&ctx, out->data, result.checksum.data, 16);
2355         EVP_CIPHER_CTX_cleanup(&ctx);
2356     }
2357 
2358     krb5_data_free(&result.checksum);
2359     krb5_free_keyblock(context, derived);
2360 
2361     return ret;
2362 }
2363 
2364 /*
2365  * these should currently be in reverse preference order.
2366  * (only relevant for !F_PSEUDO) */
2367 
2368 static struct encryption_type enctype_null = {
2369     ETYPE_NULL,
2370     "null",
2371     1,
2372     1,
2373     0,
2374     &keytype_null,
2375     &checksum_none,
2376     NULL,
2377     F_DISABLED,
2378     NULL_encrypt,
2379     0,
2380     NULL
2381 };
2382 static struct encryption_type enctype_arcfour_hmac_md5 = {
2383     ETYPE_ARCFOUR_HMAC_MD5,
2384     "arcfour-hmac-md5",
2385     1,
2386     1,
2387     8,
2388     &keytype_arcfour,
2389     &checksum_hmac_md5,
2390     NULL,
2391     F_SPECIAL,
2392     ARCFOUR_encrypt,
2393     0,
2394     NULL
2395 };
2396 #ifdef DES3_OLD_ENCTYPE
2397 static struct encryption_type enctype_des3_cbc_md5 = {
2398     ETYPE_DES3_CBC_MD5,
2399     "des3-cbc-md5",
2400     8,
2401     8,
2402     8,
2403     &keytype_des3,
2404     &checksum_rsa_md5,
2405     &checksum_rsa_md5_des3,
2406     0,
2407     evp_encrypt,
2408     0,
2409     NULL
2410 };
2411 #endif
2412 static struct encryption_type enctype_des3_cbc_sha1 = {
2413     ETYPE_DES3_CBC_SHA1,
2414     "des3-cbc-sha1",
2415     8,
2416     8,
2417     8,
2418     &keytype_des3_derived,
2419     &checksum_sha1,
2420     &checksum_hmac_sha1_des3,
2421     F_DERIVED,
2422     evp_encrypt,
2423     0,
2424     NULL
2425 };
2426 #ifdef DES3_OLD_ENCTYPE
2427 static struct encryption_type enctype_old_des3_cbc_sha1 = {
2428     ETYPE_OLD_DES3_CBC_SHA1,
2429     "old-des3-cbc-sha1",
2430     8,
2431     8,
2432     8,
2433     &keytype_des3,
2434     &checksum_sha1,
2435     &checksum_hmac_sha1_des3,
2436     0,
2437     evp_encrypt,
2438     0,
2439     NULL
2440 };
2441 #endif
2442 static struct encryption_type enctype_aes128_cts_hmac_sha1 = {
2443     ETYPE_AES128_CTS_HMAC_SHA1_96,
2444     "aes128-cts-hmac-sha1-96",
2445     16,
2446     1,
2447     16,
2448     &keytype_aes128,
2449     &checksum_sha1,
2450     &checksum_hmac_sha1_aes128,
2451     F_DERIVED,
2452     evp_encrypt,
2453     16,
2454     AES_PRF
2455 };
2456 static struct encryption_type enctype_aes256_cts_hmac_sha1 = {
2457     ETYPE_AES256_CTS_HMAC_SHA1_96,
2458     "aes256-cts-hmac-sha1-96",
2459     16,
2460     1,
2461     16,
2462     &keytype_aes256,
2463     &checksum_sha1,
2464     &checksum_hmac_sha1_aes256,
2465     F_DERIVED,
2466     evp_encrypt,
2467     16,
2468     AES_PRF
2469 };
2470 static struct encryption_type enctype_des3_cbc_none = {
2471     ETYPE_DES3_CBC_NONE,
2472     "des3-cbc-none",
2473     8,
2474     8,
2475     0,
2476     &keytype_des3_derived,
2477     &checksum_none,
2478     NULL,
2479     F_PSEUDO,
2480     evp_encrypt,
2481     0,
2482     NULL
2483 };
2484 #ifdef WEAK_ENCTYPES
2485 static struct encryption_type enctype_des_cbc_crc = {
2486     ETYPE_DES_CBC_CRC,
2487     "des-cbc-crc",
2488     8,
2489     8,
2490     8,
2491     &keytype_des,
2492     &checksum_crc32,
2493     NULL,
2494     F_DISABLED,
2495     evp_des_encrypt_key_ivec,
2496     0,
2497     NULL
2498 };
2499 static struct encryption_type enctype_des_cbc_md4 = {
2500     ETYPE_DES_CBC_MD4,
2501     "des-cbc-md4",
2502     8,
2503     8,
2504     8,
2505     &keytype_des,
2506     &checksum_rsa_md4,
2507     &checksum_rsa_md4_des,
2508     F_DISABLED,
2509     evp_des_encrypt_null_ivec,
2510     0,
2511     NULL
2512 };
2513 static struct encryption_type enctype_des_cbc_md5 = {
2514     ETYPE_DES_CBC_MD5,
2515     "des-cbc-md5",
2516     8,
2517     8,
2518     8,
2519     &keytype_des,
2520     &checksum_rsa_md5,
2521     &checksum_rsa_md5_des,
2522     F_DISABLED,
2523     evp_des_encrypt_null_ivec,
2524     0,
2525     NULL
2526 };
2527 static struct encryption_type enctype_des_cbc_none = {
2528     ETYPE_DES_CBC_NONE,
2529     "des-cbc-none",
2530     8,
2531     8,
2532     0,
2533     &keytype_des,
2534     &checksum_none,
2535     NULL,
2536     F_PSEUDO|F_DISABLED,
2537     evp_des_encrypt_null_ivec,
2538     0,
2539     NULL
2540 };
2541 static struct encryption_type enctype_des_cfb64_none = {
2542     ETYPE_DES_CFB64_NONE,
2543     "des-cfb64-none",
2544     1,
2545     1,
2546     0,
2547     &keytype_des_old,
2548     &checksum_none,
2549     NULL,
2550     F_PSEUDO|F_DISABLED,
2551     DES_CFB64_encrypt_null_ivec,
2552     0,
2553     NULL
2554 };
2555 static struct encryption_type enctype_des_pcbc_none = {
2556     ETYPE_DES_PCBC_NONE,
2557     "des-pcbc-none",
2558     8,
2559     8,
2560     0,
2561     &keytype_des_old,
2562     &checksum_none,
2563     NULL,
2564     F_PSEUDO|F_DISABLED,
2565     DES_PCBC_encrypt_key_ivec,
2566     0,
2567     NULL
2568 };
2569 #endif /* WEAK_ENCTYPES */
2570 
2571 static struct encryption_type *etypes[] = {
2572     &enctype_aes256_cts_hmac_sha1,
2573     &enctype_aes128_cts_hmac_sha1,
2574     &enctype_des3_cbc_sha1,
2575     &enctype_des3_cbc_none, /* used by the gss-api mech */
2576     &enctype_arcfour_hmac_md5,
2577 #ifdef DES3_OLD_ENCTYPE
2578     &enctype_des3_cbc_md5,
2579     &enctype_old_des3_cbc_sha1,
2580 #endif
2581 #ifdef WEAK_ENCTYPES
2582     &enctype_des_cbc_crc,
2583     &enctype_des_cbc_md4,
2584     &enctype_des_cbc_md5,
2585     &enctype_des_cbc_none,
2586     &enctype_des_cfb64_none,
2587     &enctype_des_pcbc_none,
2588 #endif
2589     &enctype_null
2590 };
2591 
2592 static unsigned num_etypes = sizeof(etypes) / sizeof(etypes[0]);
2593 
2594 
2595 static struct encryption_type *
2596 _find_enctype(krb5_enctype type)
     /* [<][>][^][v][top][bottom][index][help] */
2597 {
2598     int i;
2599     for(i = 0; i < num_etypes; i++)
2600         if(etypes[i]->type == type)
2601             return etypes[i];
2602     return NULL;
2603 }
2604 
2605 
2606 krb5_error_code KRB5_LIB_FUNCTION
2607 krb5_enctype_to_string(krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
2608                        krb5_enctype etype,
2609                        char **string)
2610 {
2611     struct encryption_type *e;
2612     e = _find_enctype(etype);
2613     if(e == NULL) {
2614         krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
2615                                 N_("encryption type %d not supported", ""),
2616                                 etype);
2617         *string = NULL;
2618         return KRB5_PROG_ETYPE_NOSUPP;
2619     }
2620     *string = strdup(e->name);
2621     if(*string == NULL) {
2622         krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
2623         return ENOMEM;
2624     }
2625     return 0;
2626 }
2627 
2628 krb5_error_code KRB5_LIB_FUNCTION
2629 krb5_string_to_enctype(krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
2630                        const char *string,
2631                        krb5_enctype *etype)
2632 {
2633     int i;
2634     for(i = 0; i < num_etypes; i++)
2635         if(strcasecmp(etypes[i]->name, string) == 0){
2636             *etype = etypes[i]->type;
2637             return 0;
2638         }
2639     krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
2640                             N_("encryption type %s not supported", ""),
2641                             string);
2642     return KRB5_PROG_ETYPE_NOSUPP;
2643 }
2644 
2645 krb5_error_code KRB5_LIB_FUNCTION
2646 krb5_enctype_to_keytype(krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
2647                         krb5_enctype etype,
2648                         krb5_keytype *keytype)
2649 {
2650     struct encryption_type *e = _find_enctype(etype);
2651     if(e == NULL) {
2652         krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
2653                                 N_("encryption type %d not supported", ""),
2654                                 etype);
2655         return KRB5_PROG_ETYPE_NOSUPP;
2656     }
2657     *keytype = e->keytype->type; /* XXX */
2658     return 0;
2659 }
2660 
2661 krb5_error_code KRB5_LIB_FUNCTION
2662 krb5_enctype_valid(krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
2663                    krb5_enctype etype)
2664 {
2665     struct encryption_type *e = _find_enctype(etype);
2666     if(e == NULL) {
2667         krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
2668                                 N_("encryption type %d not supported", ""),
2669                                 etype);
2670         return KRB5_PROG_ETYPE_NOSUPP;
2671     }
2672     if (e->flags & F_DISABLED) {
2673         krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
2674                                 N_("encryption type %s is disabled", ""),
2675                                 e->name);
2676         return KRB5_PROG_ETYPE_NOSUPP;
2677     }
2678     return 0;
2679 }
2680 
2681 /**
2682  * Return the coresponding encryption type for a checksum type.
2683  *
2684  * @param context Kerberos context
2685  * @param ctype The checksum type to get the result enctype for
2686  * @param etype The returned encryption, when the matching etype is
2687  * not found, etype is set to ETYPE_NULL.
2688  *
2689  * @return Return an error code for an failure or 0 on success.
2690  * @ingroup krb5_crypto
2691  */
2692 
2693 
2694 krb5_error_code KRB5_LIB_FUNCTION
2695 krb5_cksumtype_to_enctype(krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
2696                           krb5_cksumtype ctype,
2697                           krb5_enctype *etype)
2698 {
2699     int i;
2700 
2701     *etype = ETYPE_NULL;
2702 
2703     for(i = 0; i < num_etypes; i++) {
2704         if(etypes[i]->keyed_checksum &&
2705            etypes[i]->keyed_checksum->type == ctype)
2706             {
2707                 *etype = etypes[i]->type;
2708                 return 0;
2709             }
2710     }
2711 
2712     krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
2713                             N_("checksum type %d not supported", ""),
2714                             (int)ctype);
2715     return KRB5_PROG_SUMTYPE_NOSUPP;
2716 }
2717 
2718 
2719 krb5_error_code KRB5_LIB_FUNCTION
2720 krb5_cksumtype_valid(krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
2721                      krb5_cksumtype ctype)
2722 {
2723     struct checksum_type *c = _find_checksum(ctype);
2724     if (c == NULL) {
2725         krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
2726                                 N_("checksum type %d not supported", ""),
2727                                 ctype);
2728         return KRB5_PROG_SUMTYPE_NOSUPP;
2729     }
2730     if (c->flags & F_DISABLED) {
2731         krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
2732                                 N_("checksum type %s is disabled", ""),
2733                                 c->name);
2734         return KRB5_PROG_SUMTYPE_NOSUPP;
2735     }
2736     return 0;
2737 }
2738 
2739 
2740 /* if two enctypes have compatible keys */
2741 krb5_boolean KRB5_LIB_FUNCTION
2742 krb5_enctypes_compatible_keys(krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
2743                               krb5_enctype etype1,
2744                               krb5_enctype etype2)
2745 {
2746     struct encryption_type *e1 = _find_enctype(etype1);
2747     struct encryption_type *e2 = _find_enctype(etype2);
2748     return e1 != NULL && e2 != NULL && e1->keytype == e2->keytype;
2749 }
2750 
2751 static krb5_boolean
2752 derived_crypto(krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
2753                krb5_crypto crypto)
2754 {
2755     return (crypto->et->flags & F_DERIVED) != 0;
2756 }
2757 
2758 static krb5_boolean
2759 special_crypto(krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
2760                krb5_crypto crypto)
2761 {
2762     return (crypto->et->flags & F_SPECIAL) != 0;
2763 }
2764 
2765 #define CHECKSUMSIZE(C) ((C)->checksumsize)
2766 #define CHECKSUMTYPE(C) ((C)->type)
2767 
2768 static krb5_error_code
2769 encrypt_internal_derived(krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
2770                          krb5_crypto crypto,
2771                          unsigned usage,
2772                          const void *data,
2773                          size_t len,
2774                          krb5_data *result,
2775                          void *ivec)
2776 {
2777     size_t sz, block_sz, checksum_sz, total_sz;
2778     Checksum cksum;
2779     unsigned char *p, *q;
2780     krb5_error_code ret;
2781     struct key_data *dkey;
2782     const struct encryption_type *et = crypto->et;
2783 
2784     checksum_sz = CHECKSUMSIZE(et->keyed_checksum);
2785 
2786     sz = et->confoundersize + len;
2787     block_sz = (sz + et->padsize - 1) &~ (et->padsize - 1); /* pad */
2788     total_sz = block_sz + checksum_sz;
2789     p = calloc(1, total_sz);
2790     if(p == NULL) {
2791         krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
2792         return ENOMEM;
2793     }
2794 
2795     q = p;
2796     krb5_generate_random_block(q, et->confoundersize); /* XXX */
2797     q += et->confoundersize;
2798     memcpy(q, data, len);
2799 
2800     ret = create_checksum(context,
2801                           et->keyed_checksum,
2802                           crypto,
2803                           INTEGRITY_USAGE(usage),
2804                           p,
2805                           block_sz,
2806                           &cksum);
2807     if(ret == 0 && cksum.checksum.length != checksum_sz) {
2808         free_Checksum (&cksum);
2809         krb5_clear_error_message (context);
2810         ret = KRB5_CRYPTO_INTERNAL;
2811     }
2812     if(ret)
2813         goto fail;
2814     memcpy(p + block_sz, cksum.checksum.data, cksum.checksum.length);
2815     free_Checksum (&cksum);
2816     ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey);
2817     if(ret)
2818         goto fail;
2819     ret = _key_schedule(context, dkey);
2820     if(ret)
2821         goto fail;
2822     ret = (*et->encrypt)(context, dkey, p, block_sz, 1, usage, ivec);
2823     if (ret)
2824         goto fail;
2825     result->data = p;
2826     result->length = total_sz;
2827     return 0;
2828  fail:
2829     memset(p, 0, total_sz);
2830     free(p);
2831     return ret;
2832 }
2833 
2834 
2835 static krb5_error_code
2836 encrypt_internal(krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
2837                  krb5_crypto crypto,
2838                  const void *data,
2839                  size_t len,
2840                  krb5_data *result,
2841                  void *ivec)
2842 {
2843     size_t sz, block_sz, checksum_sz;
2844     Checksum cksum;
2845     unsigned char *p, *q;
2846     krb5_error_code ret;
2847     const struct encryption_type *et = crypto->et;
2848 
2849     checksum_sz = CHECKSUMSIZE(et->checksum);
2850 
2851     sz = et->confoundersize + checksum_sz + len;
2852     block_sz = (sz + et->padsize - 1) &~ (et->padsize - 1); /* pad */
2853     p = calloc(1, block_sz);
2854     if(p == NULL) {
2855         krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
2856         return ENOMEM;
2857     }
2858 
2859     q = p;
2860     krb5_generate_random_block(q, et->confoundersize); /* XXX */
2861     q += et->confoundersize;
2862     memset(q, 0, checksum_sz);
2863     q += checksum_sz;
2864     memcpy(q, data, len);
2865 
2866     ret = create_checksum(context,
2867                           et->checksum,
2868                           crypto,
2869                           0,
2870                           p,
2871                           block_sz,
2872                           &cksum);
2873     if(ret == 0 && cksum.checksum.length != checksum_sz) {
2874         krb5_clear_error_message (context);
2875         free_Checksum(&cksum);
2876         ret = KRB5_CRYPTO_INTERNAL;
2877     }
2878     if(ret)
2879         goto fail;
2880     memcpy(p + et->confoundersize, cksum.checksum.data, cksum.checksum.length);
2881     free_Checksum(&cksum);
2882     ret = _key_schedule(context, &crypto->key);
2883     if(ret)
2884         goto fail;
2885     ret = (*et->encrypt)(context, &crypto->key, p, block_sz, 1, 0, ivec);
2886     if (ret) {
2887         memset(p, 0, block_sz);
2888         free(p);
2889         return ret;
2890     }
2891     result->data = p;
2892     result->length = block_sz;
2893     return 0;
2894  fail:
2895     memset(p, 0, block_sz);
2896     free(p);
2897     return ret;
2898 }
2899 
2900 static krb5_error_code
2901 encrypt_internal_special(krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
2902                          krb5_crypto crypto,
2903                          int usage,
2904                          const void *data,
2905                          size_t len,
2906                          krb5_data *result,
2907                          void *ivec)
2908 {
2909     struct encryption_type *et = crypto->et;
2910     size_t cksum_sz = CHECKSUMSIZE(et->checksum);
2911     size_t sz = len + cksum_sz + et->confoundersize;
2912     char *tmp, *p;
2913     krb5_error_code ret;
2914 
2915     tmp = malloc (sz);
2916     if (tmp == NULL) {
2917         krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
2918         return ENOMEM;
2919     }
2920     p = tmp;
2921     memset (p, 0, cksum_sz);
2922     p += cksum_sz;
2923     krb5_generate_random_block(p, et->confoundersize);
2924     p += et->confoundersize;
2925     memcpy (p, data, len);
2926     ret = (*et->encrypt)(context, &crypto->key, tmp, sz, TRUE, usage, ivec);
2927     if (ret) {
2928         memset(tmp, 0, sz);
2929         free(tmp);
2930         return ret;
2931     }
2932     result->data   = tmp;
2933     result->length = sz;
2934     return 0;
2935 }
2936 
2937 static krb5_error_code
2938 decrypt_internal_derived(krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
2939                          krb5_crypto crypto,
2940                          unsigned usage,
2941                          void *data,
2942                          size_t len,
2943                          krb5_data *result,
2944                          void *ivec)
2945 {
2946     size_t checksum_sz;
2947     Checksum cksum;
2948     unsigned char *p;
2949     krb5_error_code ret;
2950     struct key_data *dkey;
2951     struct encryption_type *et = crypto->et;
2952     unsigned long l;
2953 
2954     checksum_sz = CHECKSUMSIZE(et->keyed_checksum);
2955     if (len < checksum_sz + et->confoundersize) {
2956         krb5_set_error_message(context, KRB5_BAD_MSIZE,
2957                                N_("Encrypted data shorter then "
2958                                   "checksum + confunder", ""));
2959         return KRB5_BAD_MSIZE;
2960     }
2961 
2962     if (((len - checksum_sz) % et->padsize) != 0) {
2963         krb5_clear_error_message(context);
2964         return KRB5_BAD_MSIZE;
2965     }
2966 
2967     p = malloc(len);
2968     if(len != 0 && p == NULL) {
2969         krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
2970         return ENOMEM;
2971     }
2972     memcpy(p, data, len);
2973 
2974     len -= checksum_sz;
2975 
2976     ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey);
2977     if(ret) {
2978         free(p);
2979         return ret;
2980     }
2981     ret = _key_schedule(context, dkey);
2982     if(ret) {
2983         free(p);
2984         return ret;
2985     }
2986     ret = (*et->encrypt)(context, dkey, p, len, 0, usage, ivec);
2987     if (ret) {
2988         free(p);
2989         return ret;
2990     }
2991 
2992     cksum.checksum.data   = p + len;
2993     cksum.checksum.length = checksum_sz;
2994     cksum.cksumtype       = CHECKSUMTYPE(et->keyed_checksum);
2995 
2996     ret = verify_checksum(context,
2997                           crypto,
2998                           INTEGRITY_USAGE(usage),
2999                           p,
3000                           len,
3001                           &cksum);
3002     if(ret) {
3003         free(p);
3004         return ret;
3005     }
3006     l = len - et->confoundersize;
3007     memmove(p, p + et->confoundersize, l);
3008     result->data = realloc(p, l);
3009     if(result->data == NULL && l != 0) {
3010         free(p);
3011         krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
3012         return ENOMEM;
3013     }
3014     result->length = l;
3015     return 0;
3016 }
3017 
3018 static krb5_error_code
3019 decrypt_internal(krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
3020                  krb5_crypto crypto,
3021                  void *data,
3022                  size_t len,
3023                  krb5_data *result,
3024                  void *ivec)
3025 {
3026     krb5_error_code ret;
3027     unsigned char *p;
3028     Checksum cksum;
3029     size_t checksum_sz, l;
3030     struct encryption_type *et = crypto->et;
3031 
3032     if ((len % et->padsize) != 0) {
3033         krb5_clear_error_message(context);
3034         return KRB5_BAD_MSIZE;
3035     }
3036 
3037     checksum_sz = CHECKSUMSIZE(et->checksum);
3038     p = malloc(len);
3039     if(len != 0 && p == NULL) {
3040         krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
3041         return ENOMEM;
3042     }
3043     memcpy(p, data, len);
3044 
3045     ret = _key_schedule(context, &crypto->key);
3046     if(ret) {
3047         free(p);
3048         return ret;
3049     }
3050     ret = (*et->encrypt)(context, &crypto->key, p, len, 0, 0, ivec);
3051     if (ret) {
3052         free(p);
3053         return ret;
3054     }
3055     ret = krb5_data_copy(&cksum.checksum, p + et->confoundersize, checksum_sz);
3056     if(ret) {
3057         free(p);
3058         return ret;
3059     }
3060     memset(p + et->confoundersize, 0, checksum_sz);
3061     cksum.cksumtype = CHECKSUMTYPE(et->checksum);
3062     ret = verify_checksum(context, NULL, 0, p, len, &cksum);
3063     free_Checksum(&cksum);
3064     if(ret) {
3065         free(p);
3066         return ret;
3067     }
3068     l = len - et->confoundersize - checksum_sz;
3069     memmove(p, p + et->confoundersize + checksum_sz, l);
3070     result->data = realloc(p, l);
3071     if(result->data == NULL && l != 0) {
3072         free(p);
3073         krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
3074         return ENOMEM;
3075     }
3076     result->length = l;
3077     return 0;
3078 }
3079 
3080 static krb5_error_code
3081 decrypt_internal_special(krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
3082                          krb5_crypto crypto,
3083                          int usage,
3084                          void *data,
3085                          size_t len,
3086                          krb5_data *result,
3087                          void *ivec)
3088 {
3089     struct encryption_type *et = crypto->et;
3090     size_t cksum_sz = CHECKSUMSIZE(et->checksum);
3091     size_t sz = len - cksum_sz - et->confoundersize;
3092     unsigned char *p;
3093     krb5_error_code ret;
3094 
3095     if ((len % et->padsize) != 0) {
3096         krb5_clear_error_message(context);
3097         return KRB5_BAD_MSIZE;
3098     }
3099 
3100     p = malloc (len);
3101     if (p == NULL) {
3102         krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
3103         return ENOMEM;
3104     }
3105     memcpy(p, data, len);
3106 
3107     ret = (*et->encrypt)(context, &crypto->key, p, len, FALSE, usage, ivec);
3108     if (ret) {
3109         free(p);
3110         return ret;
3111     }
3112 
3113     memmove (p, p + cksum_sz + et->confoundersize, sz);
3114     result->data = realloc(p, sz);
3115     if(result->data == NULL && sz != 0) {
3116         free(p);
3117         krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
3118         return ENOMEM;
3119     }
3120     result->length = sz;
3121     return 0;
3122 }
3123 
3124 static krb5_crypto_iov *
3125 find_iv(krb5_crypto_iov *data, int num_data, int type)
     /* [<][>][^][v][top][bottom][index][help] */
3126 {
3127     int i;
3128     for (i = 0; i < num_data; i++)
3129         if (data[i].flags == type)
3130             return &data[i];
3131     return NULL;
3132 }
3133 
3134 /**
3135  * Inline encrypt a kerberos message
3136  *
3137  * @param context Kerberos context
3138  * @param crypto Kerberos crypto context
3139  * @param usage Key usage for this buffer
3140  * @param data array of buffers to process
3141  * @param num_data length of array
3142  * @param ivec initial cbc/cts vector
3143  *
3144  * @return Return an error code or 0.
3145  * @ingroup krb5_crypto
3146  *
3147  * Kerberos encrypted data look like this:
3148  *
3149  * 1. KRB5_CRYPTO_TYPE_HEADER
3150  * 2. array KRB5_CRYPTO_TYPE_DATA and KRB5_CRYPTO_TYPE_SIGN_ONLY in
3151  *  any order, however the receiver have to aware of the
3152  *  order. KRB5_CRYPTO_TYPE_SIGN_ONLY is commonly used headers and
3153  *  trailers.
3154  * 3. KRB5_CRYPTO_TYPE_PADDING, at least on padsize long if padsize > 1
3155  * 4. KRB5_CRYPTO_TYPE_TRAILER
3156  */
3157 
3158 krb5_error_code KRB5_LIB_FUNCTION
3159 krb5_encrypt_iov_ivec(krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
3160                       krb5_crypto crypto,
3161                       unsigned usage,
3162                       krb5_crypto_iov *data,
3163                       size_t num_data,
3164                       void *ivec)
3165 {
3166     size_t headersz, trailersz, len;
3167     size_t i, sz, block_sz, pad_sz;
3168     Checksum cksum;
3169     unsigned char *p, *q;
3170     krb5_error_code ret;
3171     struct key_data *dkey;
3172     const struct encryption_type *et = crypto->et;
3173     krb5_crypto_iov *tiv, *piv, *hiv;
3174 
3175     if(!derived_crypto(context, crypto)) {
3176         krb5_clear_error_message(context);
3177         return KRB5_CRYPTO_INTERNAL;
3178     }
3179 
3180     headersz = et->confoundersize;
3181     trailersz = CHECKSUMSIZE(et->keyed_checksum);
3182 
3183     for (len = 0, i = 0; i < num_data; i++) {
3184         if (data[i].flags != KRB5_CRYPTO_TYPE_HEADER &&
3185             data[i].flags == KRB5_CRYPTO_TYPE_DATA) {
3186             len += data[i].data.length;
3187         }
3188     }
3189 
3190     sz = headersz + len;
3191     block_sz = (sz + et->padsize - 1) &~ (et->padsize - 1); /* pad */
3192 
3193     pad_sz = block_sz - sz;
3194     trailersz += pad_sz;
3195 
3196     /* header */
3197 
3198     hiv = find_iv(data, num_data, KRB5_CRYPTO_TYPE_HEADER);
3199     if (hiv == NULL || hiv->data.length != headersz)
3200         return KRB5_BAD_MSIZE;
3201 
3202     krb5_generate_random_block(hiv->data.data, hiv->data.length);
3203 
3204     /* padding */
3205 
3206     piv = find_iv(data, num_data, KRB5_CRYPTO_TYPE_PADDING);
3207     /* its ok to have no TYPE_PADDING if there is no padding */
3208     if (piv == NULL && pad_sz != 0)
3209         return KRB5_BAD_MSIZE;
3210     if (piv) {
3211         if (piv->data.length < pad_sz)
3212             return KRB5_BAD_MSIZE;
3213         piv->data.length = pad_sz;
3214     }
3215 
3216 
3217     /* trailer */
3218 
3219     tiv = find_iv(data, num_data, KRB5_CRYPTO_TYPE_TRAILER);
3220     if (tiv == NULL || tiv->data.length != trailersz)
3221         return KRB5_BAD_MSIZE;
3222 
3223 
3224     /*
3225      * XXX replace with EVP_Sign? at least make create_checksum an iov
3226      * function.
3227      * XXX CTS EVP is broken, can't handle multi buffers :(
3228      */
3229 
3230     len = hiv->data.length;
3231     for (i = 0; i < num_data; i++) {
3232         if (data[i].flags != KRB5_CRYPTO_TYPE_DATA &&
3233             data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY)
3234             continue;
3235         len += data[i].data.length;
3236     }
3237 
3238     p = q = malloc(len);
3239 
3240     memcpy(q, hiv->data.data, hiv->data.length);
3241     q += hiv->data.length;
3242     for (i = 0; i < num_data; i++) {
3243         if (data[i].flags != KRB5_CRYPTO_TYPE_DATA &&
3244             data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY)
3245             continue;
3246         memcpy(q, data[i].data.data, data[i].data.length);
3247         q += data[i].data.length;
3248     }
3249 
3250     ret = create_checksum(context,
3251                           et->keyed_checksum,
3252                           crypto,
3253                           INTEGRITY_USAGE(usage),
3254                           p,
3255                           len,
3256                           &cksum);
3257     free(p);
3258     if(ret == 0 && cksum.checksum.length != trailersz) {
3259         free_Checksum (&cksum);
3260         krb5_clear_error_message (context);
3261         ret = KRB5_CRYPTO_INTERNAL;
3262     }
3263     if(ret)
3264         return ret;
3265 
3266     /* save cksum at end */
3267     memcpy(tiv->data.data, cksum.checksum.data, cksum.checksum.length);
3268     free_Checksum (&cksum);
3269 
3270     /* now encrypt data */
3271 
3272     ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey);
3273     if(ret)
3274         return ret;
3275     ret = _key_schedule(context, dkey);
3276     if(ret)
3277         return ret;
3278 
3279     /* XXX replace with EVP_Cipher */
3280 
3281     len = hiv->data.length;
3282     for (i = 0; i < num_data; i++) {
3283         if (data[i].flags != KRB5_CRYPTO_TYPE_DATA &&
3284             data[i].flags != KRB5_CRYPTO_TYPE_PADDING)
3285             continue;
3286         len += data[i].data.length;
3287     }
3288 
3289     p = q = malloc(len);
3290     if(p == NULL)
3291         return ENOMEM;
3292 
3293     memcpy(q, hiv->data.data, hiv->data.length);
3294     q += hiv->data.length;
3295     for (i = 0; i < num_data; i++) {
3296         if (data[i].flags != KRB5_CRYPTO_TYPE_DATA &&
3297             data[i].flags != KRB5_CRYPTO_TYPE_PADDING)
3298             continue;
3299         memcpy(q, data[i].data.data, data[i].data.length);
3300         q += data[i].data.length;
3301     }
3302 
3303     ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey);
3304     if(ret) {
3305         free(p);
3306         return ret;
3307     }
3308     ret = _key_schedule(context, dkey);
3309     if(ret) {
3310         free(p);
3311         return ret;
3312     }
3313 
3314     ret = (*et->encrypt)(context, dkey, p, len, 1, usage, ivec);
3315     if (ret) {
3316         free(p);
3317         return ret;
3318     }
3319 
3320     /* now copy data back to buffers */
3321     q = p;
3322     memcpy(hiv->data.data, q, hiv->data.length);
3323     q += hiv->data.length;
3324 
3325     for (i = 0; i < num_data; i++) {
3326         if (data[i].flags != KRB5_CRYPTO_TYPE_DATA &&
3327             data[i].flags != KRB5_CRYPTO_TYPE_PADDING)
3328             continue;
3329         memcpy(data[i].data.data, q, data[i].data.length);
3330         q += data[i].data.length;
3331     }
3332     free(p);
3333 
3334     return ret;
3335 }
3336 
3337 /**
3338  * Inline decrypt a Kerberos message.
3339  *
3340  * @param context Kerberos context
3341  * @param crypto Kerberos crypto context
3342  * @param usage Key usage for this buffer
3343  * @param data array of buffers to process
3344  * @param num_data length of array
3345  * @param ivec initial cbc/cts vector
3346  *
3347  * @return Return an error code or 0.
3348  * @ingroup krb5_crypto
3349  *
3350  * 1. KRB5_CRYPTO_TYPE_HEADER
3351  * 2. array KRB5_CRYPTO_TYPE_DATA and KRB5_CRYPTO_TYPE_SIGN_ONLY in
3352  *  any order, however the receiver have to aware of the
3353  *  order. KRB5_CRYPTO_TYPE_SIGN_ONLY is commonly used unencrypoted
3354  *  protocol headers and trailers. The output data will be of same
3355  *  size as the input data or shorter.
3356  */
3357 
3358 krb5_error_code KRB5_LIB_FUNCTION
3359 krb5_decrypt_iov_ivec(krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
3360                       krb5_crypto crypto,
3361                       unsigned usage,
3362                       krb5_crypto_iov *data,
3363                       size_t num_data,
3364                       void *ivec)
3365 {
3366     size_t headersz, trailersz, len;
3367     size_t i, sz, block_sz, pad_sz;
3368     Checksum cksum;
3369     unsigned char *p, *q;
3370     krb5_error_code ret;
3371     struct key_data *dkey;
3372     struct encryption_type *et = crypto->et;
3373     krb5_crypto_iov *tiv, *hiv;
3374 
3375     if(!derived_crypto(context, crypto)) {
3376         krb5_clear_error_message(context);
3377         return KRB5_CRYPTO_INTERNAL;
3378     }
3379 
3380     headersz = et->confoundersize;
3381     trailersz = CHECKSUMSIZE(et->keyed_checksum);
3382 
3383     for (len = 0, i = 0; i < num_data; i++)
3384         if (data[i].flags == KRB5_CRYPTO_TYPE_DATA)
3385             len += data[i].data.length;
3386 
3387     sz = headersz + len;
3388     block_sz = (sz + et->padsize - 1) &~ (et->padsize - 1); /* pad */
3389 
3390     pad_sz = block_sz - sz;
3391     trailersz += pad_sz;
3392 
3393     /* header */
3394 
3395     hiv = find_iv(data, num_data, KRB5_CRYPTO_TYPE_HEADER);
3396     if (hiv == NULL || hiv->data.length < headersz)
3397         return KRB5_BAD_MSIZE;
3398     hiv->data.length = headersz;
3399 
3400     /* trailer */
3401 
3402     tiv = find_iv(data, num_data, KRB5_CRYPTO_TYPE_TRAILER);
3403     if (tiv == NULL || tiv->data.length < trailersz)
3404         return KRB5_BAD_MSIZE;
3405     tiv->data.length = trailersz;
3406 
3407     /* body */
3408 
3409     /* XXX replace with EVP_Cipher */
3410 
3411     for (len = 0, i = 0; i < num_data; i++) {
3412         if (data[i].flags != KRB5_CRYPTO_TYPE_HEADER &&
3413             data[i].flags != KRB5_CRYPTO_TYPE_DATA)
3414             continue;
3415         len += data[i].data.length;
3416     }
3417 
3418     p = q = malloc(len);
3419     if (p == NULL)
3420         return ENOMEM;
3421 
3422     memcpy(q, hiv->data.data, hiv->data.length);
3423     q += hiv->data.length;
3424     for (i = 0; i < num_data; i++) {
3425         if (data[i].flags != KRB5_CRYPTO_TYPE_DATA)
3426             continue;
3427         memcpy(q, data[i].data.data, data[i].data.length);
3428         q += data[i].data.length;
3429     }
3430 
3431     ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey);
3432     if(ret) {
3433         free(p);
3434         return ret;
3435     }
3436     ret = _key_schedule(context, dkey);
3437     if(ret) {
3438         free(p);
3439         return ret;
3440     }
3441 
3442     ret = (*et->encrypt)(context, dkey, p, len, 0, usage, ivec);
3443     if (ret) {
3444         free(p);
3445         return ret;
3446     }
3447 
3448     /* XXX now copy data back to buffers */
3449     q = p;
3450     memcpy(hiv->data.data, q, hiv->data.length);
3451     q += hiv->data.length;
3452     len -= hiv->data.length;
3453 
3454     for (i = 0; i < num_data; i++) {
3455         if (data[i].flags != KRB5_CRYPTO_TYPE_DATA)
3456             continue;
3457         if (len < data[i].data.length)
3458             data[i].data.length = len;
3459         memcpy(data[i].data.data, q, data[i].data.length);
3460         q += data[i].data.length;
3461         len -= data[i].data.length;
3462     }
3463     free(p);
3464     if (len)
3465         krb5_abortx(context, "data still in the buffer");
3466 
3467     len = hiv->data.length;
3468     for (i = 0; i < num_data; i++) {
3469         if (data[i].flags != KRB5_CRYPTO_TYPE_DATA &&
3470             data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY)
3471             continue;
3472         len += data[i].data.length;
3473     }
3474 
3475     p = q = malloc(len);
3476 
3477     memcpy(q, hiv->data.data, hiv->data.length);
3478     q += hiv->data.length;
3479     for (i = 0; i < num_data; i++) {
3480         if (data[i].flags != KRB5_CRYPTO_TYPE_DATA &&
3481             data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY)
3482             continue;
3483         memcpy(q, data[i].data.data, data[i].data.length);
3484         q += data[i].data.length;
3485     }
3486 
3487     cksum.checksum.data   = tiv->data.data;
3488     cksum.checksum.length = tiv->data.length;
3489     cksum.cksumtype       = CHECKSUMTYPE(et->keyed_checksum);
3490 
3491     ret = verify_checksum(context,
3492                           crypto,
3493                           INTEGRITY_USAGE(usage),
3494                           p,
3495                           len,
3496                           &cksum);
3497     free(p);
3498     return ret;
3499 }
3500 
3501 /**
3502  * Create a Kerberos message checksum.
3503  *
3504  * @param context Kerberos context
3505  * @param crypto Kerberos crypto context
3506  * @param usage Key usage for this buffer
3507  * @param data array of buffers to process
3508  * @param num_data length of array
3509  * @param result output data
3510  *
3511  * @return Return an error code or 0.
3512  * @ingroup krb5_crypto
3513  */
3514 
3515 krb5_error_code KRB5_LIB_FUNCTION
3516 krb5_create_checksum_iov(krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
3517                          krb5_crypto crypto,
3518                          unsigned usage,
3519                          krb5_crypto_iov *data,
3520                          size_t num_data,
3521                          krb5_cksumtype *type)
3522 {
3523     Checksum cksum;
3524     krb5_crypto_iov *civ;
3525     krb5_error_code ret;
3526     unsigned int i;
3527     size_t len;
3528     char *p, *q;
3529 
3530     if(!derived_crypto(context, crypto)) {
3531         krb5_clear_error_message(context);
3532         return KRB5_CRYPTO_INTERNAL;
3533     }
3534 
3535     civ = find_iv(data, num_data, KRB5_CRYPTO_TYPE_CHECKSUM);
3536     if (civ == NULL)
3537         return KRB5_BAD_MSIZE;
3538 
3539     len = 0;
3540     for (i = 0; i < num_data; i++) {
3541         if (data[i].flags != KRB5_CRYPTO_TYPE_DATA &&
3542             data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY)
3543             continue;
3544         len += data[i].data.length;
3545     }
3546 
3547     p = q = malloc(len);
3548 
3549     for (i = 0; i < num_data; i++) {
3550         if (data[i].flags != KRB5_CRYPTO_TYPE_DATA &&
3551             data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY)
3552             continue;
3553         memcpy(q, data[i].data.data, data[i].data.length);
3554         q += data[i].data.length;
3555     }
3556 
3557     ret = krb5_create_checksum(context, crypto, usage, 0, p, len, &cksum);
3558     free(p);
3559     if (ret)
3560         return ret;
3561 
3562     if (type)
3563         *type = cksum.cksumtype;
3564 
3565     if (cksum.checksum.length > civ->data.length) {
3566         krb5_set_error_message(context, KRB5_BAD_MSIZE,
3567                                N_("Checksum larger then input buffer", ""));
3568         free_Checksum(&cksum);
3569         return KRB5_BAD_MSIZE;
3570     }
3571 
3572     civ->data.length = cksum.checksum.length;
3573     memcpy(civ->data.data, cksum.checksum.data, civ->data.length);
3574     free_Checksum(&cksum);
3575 
3576     return 0;
3577 }
3578 
3579 
3580 size_t KRB5_LIB_FUNCTION
3581 krb5_crypto_length(krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
3582                    krb5_crypto crypto,
3583                    int type)
3584 {
3585     if (!derived_crypto(context, crypto))
3586         return (size_t)-1;
3587     switch(type) {
3588     case KRB5_CRYPTO_TYPE_EMPTY:
3589         return 0;
3590     case KRB5_CRYPTO_TYPE_HEADER:
3591         return crypto->et->blocksize;
3592     case KRB5_CRYPTO_TYPE_PADDING:
3593         if (crypto->et->padsize > 1)
3594             return crypto->et->padsize;
3595         return 0;
3596     case KRB5_CRYPTO_TYPE_TRAILER:
3597         return CHECKSUMSIZE(crypto->et->keyed_checksum);
3598     case KRB5_CRYPTO_TYPE_CHECKSUM:
3599         if (crypto->et->keyed_checksum)
3600             return CHECKSUMSIZE(crypto->et->keyed_checksum);
3601         return CHECKSUMSIZE(crypto->et->checksum);
3602     }
3603     return (size_t)-1;
3604 }
3605 
3606 krb5_error_code KRB5_LIB_FUNCTION
3607 krb5_encrypt_ivec(krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
3608                   krb5_crypto crypto,
3609                   unsigned usage,
3610                   const void *data,
3611                   size_t len,
3612                   krb5_data *result,
3613                   void *ivec)
3614 {
3615     if(derived_crypto(context, crypto))
3616         return encrypt_internal_derived(context, crypto, usage,
3617                                         data, len, result, ivec);
3618     else if (special_crypto(context, crypto))
3619         return encrypt_internal_special (context, crypto, usage,
3620                                          data, len, result, ivec);
3621     else
3622         return encrypt_internal(context, crypto, data, len, result, ivec);
3623 }
3624 
3625 krb5_error_code KRB5_LIB_FUNCTION
3626 krb5_encrypt(krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
3627              krb5_crypto crypto,
3628              unsigned usage,
3629              const void *data,
3630              size_t len,
3631              krb5_data *result)
3632 {
3633     return krb5_encrypt_ivec(context, crypto, usage, data, len, result, NULL);
3634 }
3635 
3636 krb5_error_code KRB5_LIB_FUNCTION
3637 krb5_encrypt_EncryptedData(krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
3638                            krb5_crypto crypto,
3639                            unsigned usage,
3640                            void *data,
3641                            size_t len,
3642                            int kvno,
3643                            EncryptedData *result)
3644 {
3645     result->etype = CRYPTO_ETYPE(crypto);
3646     if(kvno){
3647         ALLOC(result->kvno, 1);
3648         *result->kvno = kvno;
3649     }else
3650         result->kvno = NULL;
3651     return krb5_encrypt(context, crypto, usage, data, len, &result->cipher);
3652 }
3653 
3654 krb5_error_code KRB5_LIB_FUNCTION
3655 krb5_decrypt_ivec(krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
3656                   krb5_crypto crypto,
3657                   unsigned usage,
3658                   void *data,
3659                   size_t len,
3660                   krb5_data *result,
3661                   void *ivec)
3662 {
3663     if(derived_crypto(context, crypto))
3664         return decrypt_internal_derived(context, crypto, usage,
3665                                         data, len, result, ivec);
3666     else if (special_crypto (context, crypto))
3667         return decrypt_internal_special(context, crypto, usage,
3668                                         data, len, result, ivec);
3669     else
3670         return decrypt_internal(context, crypto, data, len, result, ivec);
3671 }
3672 
3673 krb5_error_code KRB5_LIB_FUNCTION
3674 krb5_decrypt(krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
3675              krb5_crypto crypto,
3676              unsigned usage,
3677              void *data,
3678              size_t len,
3679              krb5_data *result)
3680 {
3681     return krb5_decrypt_ivec (context, crypto, usage, data, len, result,
3682                               NULL);
3683 }
3684 
3685 krb5_error_code KRB5_LIB_FUNCTION
3686 krb5_decrypt_EncryptedData(krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
3687                            krb5_crypto crypto,
3688                            unsigned usage,
3689                            const EncryptedData *e,
3690                            krb5_data *result)
3691 {
3692     return krb5_decrypt(context, crypto, usage,
3693                         e->cipher.data, e->cipher.length, result);
3694 }
3695 
3696 /************************************************************
3697  *                                                          *
3698  ************************************************************/
3699 
3700 #define ENTROPY_NEEDED 128
3701 
3702 static int
3703 seed_something(void)
     /* [<][>][^][v][top][bottom][index][help] */
3704 {
3705     char buf[1024], seedfile[256];
3706 
3707     /* If there is a seed file, load it. But such a file cannot be trusted,
3708        so use 0 for the entropy estimate */
3709     if (RAND_file_name(seedfile, sizeof(seedfile))) {
3710         int fd;
3711         fd = open(seedfile, O_RDONLY | O_BINARY | O_CLOEXEC);
3712         if (fd >= 0) {
3713             ssize_t ret;
3714             rk_cloexec(fd);
3715             ret = read(fd, buf, sizeof(buf));
3716             if (ret > 0)
3717                 RAND_add(buf, ret, 0.0);
3718             close(fd);
3719         } else
3720             seedfile[0] = '\0';
3721     } else
3722         seedfile[0] = '\0';
3723 
3724     /* Calling RAND_status() will try to use /dev/urandom if it exists so
3725        we do not have to deal with it. */
3726     if (RAND_status() != 1) {
3727         krb5_context context;
3728         const char *p;
3729 
3730         /* Try using egd */
3731         if (!krb5_init_context(&context)) {
3732             p = krb5_config_get_string(context, NULL, "libdefaults",
3733                                        "egd_socket", NULL);
3734             if (p != NULL)
3735                 RAND_egd_bytes(p, ENTROPY_NEEDED);
3736             krb5_free_context(context);
3737         }
3738     }
3739 
3740     if (RAND_status() == 1)     {
3741         /* Update the seed file */
3742         if (seedfile[0])
3743             RAND_write_file(seedfile);
3744 
3745         return 0;
3746     } else
3747         return -1;
3748 }
3749 
3750 void KRB5_LIB_FUNCTION
3751 krb5_generate_random_block(void *buf, size_t len)
     /* [<][>][^][v][top][bottom][index][help] */
3752 {
3753     static int rng_initialized = 0;
3754 
3755     HEIMDAL_MUTEX_lock(&crypto_mutex);
3756     if (!rng_initialized) {
3757         if (seed_something())
3758             krb5_abortx(NULL, "Fatal: could not seed the "
3759                         "random number generator");
3760         
3761         rng_initialized = 1;
3762     }
3763     HEIMDAL_MUTEX_unlock(&crypto_mutex);
3764     if (RAND_bytes(buf, len) != 1)
3765         krb5_abortx(NULL, "Failed to generate random block");
3766 }
3767 
3768 static void
3769 DES3_postproc(krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
3770               unsigned char *k, size_t len, struct key_data *key)
3771 {
3772     DES3_random_to_key(context, key->key, k, len);
3773 
3774     if (key->schedule) {
3775         krb5_free_data(context, key->schedule);
3776         key->schedule = NULL;
3777     }
3778 }
3779 
3780 static krb5_error_code
3781 derive_key(krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
3782            struct encryption_type *et,
3783            struct key_data *key,
3784            const void *constant,
3785            size_t len)
3786 {
3787     unsigned char *k;
3788     unsigned int nblocks = 0, i;
3789     krb5_error_code ret = 0;
3790     struct key_type *kt = et->keytype;
3791 
3792     ret = _key_schedule(context, key);
3793     if(ret)
3794         return ret;
3795     if(et->blocksize * 8 < kt->bits || len != et->blocksize) {
3796         nblocks = (kt->bits + et->blocksize * 8 - 1) / (et->blocksize * 8);
3797         k = malloc(nblocks * et->blocksize);
3798         if(k == NULL) {
3799             krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
3800             return ENOMEM;
3801         }
3802         ret = _krb5_n_fold(constant, len, k, et->blocksize);
3803         if (ret) {
3804             free(k);
3805             krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
3806             return ret;
3807         }
3808         for(i = 0; i < nblocks; i++) {
3809             if(i > 0)
3810                 memcpy(k + i * et->blocksize,
3811                        k + (i - 1) * et->blocksize,
3812                        et->blocksize);
3813             (*et->encrypt)(context, key, k + i * et->blocksize, et->blocksize,
3814                            1, 0, NULL);
3815         }
3816     } else {
3817         /* this case is probably broken, but won't be run anyway */
3818         void *c = malloc(len);
3819         size_t res_len = (kt->bits + 7) / 8;
3820 
3821         if(len != 0 && c == NULL) {
3822             krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
3823             return ENOMEM;
3824         }
3825         memcpy(c, constant, len);
3826         (*et->encrypt)(context, key, c, len, 1, 0, NULL);
3827         k = malloc(res_len);
3828         if(res_len != 0 && k == NULL) {
3829             free(c);
3830             krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
3831             return ENOMEM;
3832         }
3833         ret = _krb5_n_fold(c, len, k, res_len);
3834         if (ret) {
3835             free(k);
3836             krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
3837             return ret;
3838         }
3839         free(c);
3840     }
3841 
3842     /* XXX keytype dependent post-processing */
3843     switch(kt->type) {
3844     case KEYTYPE_DES3:
3845         DES3_postproc(context, k, nblocks * et->blocksize, key);
3846         break;
3847     case KEYTYPE_AES128:
3848     case KEYTYPE_AES256:
3849         memcpy(key->key->keyvalue.data, k, key->key->keyvalue.length);
3850         break;
3851     default:
3852         ret = KRB5_CRYPTO_INTERNAL;
3853         krb5_set_error_message(context, ret,
3854                                N_("derive_key() called with unknown keytype (%u)", ""),
3855                                kt->type);
3856         break;
3857     }
3858     if (key->schedule) {
3859         krb5_free_data(context, key->schedule);
3860         key->schedule = NULL;
3861     }
3862     memset(k, 0, nblocks * et->blocksize);
3863     free(k);
3864     return ret;
3865 }
3866 
3867 static struct key_data *
3868 _new_derived_key(krb5_crypto crypto, unsigned usage)
     /* [<][>][^][v][top][bottom][index][help] */
3869 {
3870     struct key_usage *d = crypto->key_usage;
3871     d = realloc(d, (crypto->num_key_usage + 1) * sizeof(*d));
3872     if(d == NULL)
3873         return NULL;
3874     crypto->key_usage = d;
3875     d += crypto->num_key_usage++;
3876     memset(d, 0, sizeof(*d));
3877     d->usage = usage;
3878     return &d->key;
3879 }
3880 
3881 krb5_error_code KRB5_LIB_FUNCTION
3882 krb5_derive_key(krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
3883                 const krb5_keyblock *key,
3884                 krb5_enctype etype,
3885                 const void *constant,
3886                 size_t constant_len,
3887                 krb5_keyblock **derived_key)
3888 {
3889     krb5_error_code ret;
3890     struct encryption_type *et;
3891     struct key_data d;
3892 
3893     *derived_key = NULL;
3894 
3895     et = _find_enctype (etype);
3896     if (et == NULL) {
3897         krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
3898                                N_("encryption type %d not supported", ""),
3899                                etype);
3900         return KRB5_PROG_ETYPE_NOSUPP;
3901     }
3902 
3903     ret = krb5_copy_keyblock(context, key, &d.key);
3904     if (ret)
3905         return ret;
3906 
3907     d.schedule = NULL;
3908     ret = derive_key(context, et, &d, constant, constant_len);
3909     if (ret == 0)
3910         ret = krb5_copy_keyblock(context, d.key, derived_key);
3911     free_key_data(context, &d, et);
3912     return ret;
3913 }
3914 
3915 static krb5_error_code
3916 _get_derived_key(krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
3917                  krb5_crypto crypto,
3918                  unsigned usage,
3919                  struct key_data **key)
3920 {
3921     int i;
3922     struct key_data *d;
3923     unsigned char constant[5];
3924 
3925     for(i = 0; i < crypto->num_key_usage; i++)
3926         if(crypto->key_usage[i].usage == usage) {
3927             *key = &crypto->key_usage[i].key;
3928             return 0;
3929         }
3930     d = _new_derived_key(crypto, usage);
3931     if(d == NULL) {
3932         krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
3933         return ENOMEM;
3934     }
3935     krb5_copy_keyblock(context, crypto->key.key, &d->key);
3936     _krb5_put_int(constant, usage, 5);
3937     derive_key(context, crypto->et, d, constant, sizeof(constant));
3938     *key = d;
3939     return 0;
3940 }
3941 
3942 
3943 krb5_error_code KRB5_LIB_FUNCTION
3944 krb5_crypto_init(krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
3945                  const krb5_keyblock *key,
3946                  krb5_enctype etype,
3947                  krb5_crypto *crypto)
3948 {
3949     krb5_error_code ret;
3950     ALLOC(*crypto, 1);
3951     if(*crypto == NULL) {
3952         krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
3953         return ENOMEM;
3954     }
3955     if(etype == ETYPE_NULL)
3956         etype = key->keytype;
3957     (*crypto)->et = _find_enctype(etype);
3958     if((*crypto)->et == NULL || ((*crypto)->et->flags & F_DISABLED)) {
3959         free(*crypto);
3960         *crypto = NULL;
3961         krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
3962                                 N_("encryption type %d not supported", ""),
3963                                 etype);
3964         return KRB5_PROG_ETYPE_NOSUPP;
3965     }
3966     if((*crypto)->et->keytype->size != key->keyvalue.length) {
3967         free(*crypto);
3968         *crypto = NULL;
3969         krb5_set_error_message (context, KRB5_BAD_KEYSIZE,
3970                                 "encryption key has bad length");
3971         return KRB5_BAD_KEYSIZE;
3972     }
3973     ret = krb5_copy_keyblock(context, key, &(*crypto)->key.key);
3974     if(ret) {
3975         free(*crypto);
3976         *crypto = NULL;
3977         return ret;
3978     }
3979     (*crypto)->key.schedule = NULL;
3980     (*crypto)->num_key_usage = 0;
3981     (*crypto)->key_usage = NULL;
3982     return 0;
3983 }
3984 
3985 static void
3986 free_key_data(krb5_context context, struct key_data *key,
     /* [<][>][^][v][top][bottom][index][help] */
3987               struct encryption_type *et)
3988 {
3989     krb5_free_keyblock(context, key->key);
3990     if(key->schedule) {
3991         if (et->keytype->cleanup)
3992             (*et->keytype->cleanup)(context, key);
3993         memset(key->schedule->data, 0, key->schedule->length);
3994         krb5_free_data(context, key->schedule);
3995     }
3996 }
3997 
3998 static void
3999 free_key_usage(krb5_context context, struct key_usage *ku,
     /* [<][>][^][v][top][bottom][index][help] */
4000                struct encryption_type *et)
4001 {
4002     free_key_data(context, &ku->key, et);
4003 }
4004 
4005 krb5_error_code KRB5_LIB_FUNCTION
4006 krb5_crypto_destroy(krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
4007                     krb5_crypto crypto)
4008 {
4009     int i;
4010 
4011     for(i = 0; i < crypto->num_key_usage; i++)
4012         free_key_usage(context, &crypto->key_usage[i], crypto->et);
4013     free(crypto->key_usage);
4014     free_key_data(context, &crypto->key, crypto->et);
4015     free (crypto);
4016     return 0;
4017 }
4018 
4019 krb5_error_code KRB5_LIB_FUNCTION
4020 krb5_crypto_getblocksize(krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
4021                          krb5_crypto crypto,
4022                          size_t *blocksize)
4023 {
4024     *blocksize = crypto->et->blocksize;
4025     return 0;
4026 }
4027 
4028 krb5_error_code KRB5_LIB_FUNCTION
4029 krb5_crypto_getenctype(krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
4030                        krb5_crypto crypto,
4031                        krb5_enctype *enctype)
4032 {
4033     *enctype = crypto->et->type;
4034     return 0;
4035 }
4036 
4037 krb5_error_code KRB5_LIB_FUNCTION
4038 krb5_crypto_getpadsize(krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
4039                        krb5_crypto crypto,
4040                        size_t *padsize)
4041 {
4042     *padsize = crypto->et->padsize;
4043     return 0;
4044 }
4045 
4046 krb5_error_code KRB5_LIB_FUNCTION
4047 krb5_crypto_getconfoundersize(krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
4048                               krb5_crypto crypto,
4049                               size_t *confoundersize)
4050 {
4051     *confoundersize = crypto->et->confoundersize;
4052     return 0;
4053 }
4054 
4055 
4056 /**
4057  * Disable encryption type
4058  *
4059  * @param context Kerberos 5 context
4060  * @param enctype encryption type to disable
4061  *
4062  * @return Return an error code or 0.
4063  *
4064  * @ingroup krb5_crypto
4065  */
4066 
4067 krb5_error_code KRB5_LIB_FUNCTION
4068 krb5_enctype_disable(krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
4069                      krb5_enctype enctype)
4070 {
4071     struct encryption_type *et = _find_enctype(enctype);
4072     if(et == NULL) {
4073         if (context)
4074             krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
4075                                     N_("encryption type %d not supported", ""),
4076                                     enctype);
4077         return KRB5_PROG_ETYPE_NOSUPP;
4078     }
4079     et->flags |= F_DISABLED;
4080     return 0;
4081 }
4082 
4083 /**
4084  * Enable encryption type
4085  *
4086  * @param context Kerberos 5 context
4087  * @param enctype encryption type to enable
4088  *
4089  * @return Return an error code or 0.
4090  *
4091  * @ingroup krb5_crypto
4092  */
4093 
4094 krb5_error_code KRB5_LIB_FUNCTION
4095 krb5_enctype_enable(krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
4096                     krb5_enctype enctype)
4097 {
4098     struct encryption_type *et = _find_enctype(enctype);
4099     if(et == NULL) {
4100         if (context)
4101             krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
4102                                     N_("encryption type %d not supported", ""),
4103                                     enctype);
4104         return KRB5_PROG_ETYPE_NOSUPP;
4105     }
4106     et->flags &= ~F_DISABLED;
4107     return 0;
4108 }
4109 
4110 
4111 krb5_error_code KRB5_LIB_FUNCTION
4112 krb5_string_to_key_derived(krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
4113                            const void *str,
4114                            size_t len,
4115                            krb5_enctype etype,
4116                            krb5_keyblock *key)
4117 {
4118     struct encryption_type *et = _find_enctype(etype);
4119     krb5_error_code ret;
4120     struct key_data kd;
4121     size_t keylen;
4122     u_char *tmp;
4123 
4124     if(et == NULL) {
4125         krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
4126                                 N_("encryption type %d not supported", ""),
4127                                 etype);
4128         return KRB5_PROG_ETYPE_NOSUPP;
4129     }
4130     keylen = et->keytype->bits / 8;
4131 
4132     ALLOC(kd.key, 1);
4133     if(kd.key == NULL) {
4134         krb5_set_error_message (context, ENOMEM,
4135                                 N_("malloc: out of memory", ""));
4136         return ENOMEM;
4137     }
4138     ret = krb5_data_alloc(&kd.key->keyvalue, et->keytype->size);
4139     if(ret) {
4140         free(kd.key);
4141         return ret;
4142     }
4143     kd.key->keytype = etype;
4144     tmp = malloc (keylen);
4145     if(tmp == NULL) {
4146         krb5_free_keyblock(context, kd.key);
4147         krb5_set_error_message (context, ENOMEM, N_("malloc: out of memory", ""));
4148         return ENOMEM;
4149     }
4150     ret = _krb5_n_fold(str, len, tmp, keylen);
4151     if (ret) {
4152         free(tmp);
4153         krb5_set_error_message (context, ENOMEM, N_("malloc: out of memory", ""));
4154         return ret;
4155     }
4156     kd.schedule = NULL;
4157     DES3_postproc (context, tmp, keylen, &kd); /* XXX */
4158     memset(tmp, 0, keylen);
4159     free(tmp);
4160     ret = derive_key(context,
4161                      et,
4162                      &kd,
4163                      "kerberos", /* XXX well known constant */
4164                      strlen("kerberos"));
4165     if (ret) {
4166         free_key_data(context, &kd, et);
4167         return ret;
4168     }
4169     ret = krb5_copy_keyblock_contents(context, kd.key, key);
4170     free_key_data(context, &kd, et);
4171     return ret;
4172 }
4173 
4174 static size_t
4175 wrapped_length (krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
4176                 krb5_crypto  crypto,
4177                 size_t       data_len)
4178 {
4179     struct encryption_type *et = crypto->et;
4180     size_t padsize = et->padsize;
4181     size_t checksumsize = CHECKSUMSIZE(et->checksum);
4182     size_t res;
4183 
4184     res =  et->confoundersize + checksumsize + data_len;
4185     res =  (res + padsize - 1) / padsize * padsize;
4186     return res;
4187 }
4188 
4189 static size_t
4190 wrapped_length_dervied (krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
4191                         krb5_crypto  crypto,
4192                         size_t       data_len)
4193 {
4194     struct encryption_type *et = crypto->et;
4195     size_t padsize = et->padsize;
4196     size_t res;
4197 
4198     res =  et->confoundersize + data_len;
4199     res =  (res + padsize - 1) / padsize * padsize;
4200     if (et->keyed_checksum)
4201         res += et->keyed_checksum->checksumsize;
4202     else
4203         res += et->checksum->checksumsize;
4204     return res;
4205 }
4206 
4207 /*
4208  * Return the size of an encrypted packet of length `data_len'
4209  */
4210 
4211 size_t
4212 krb5_get_wrapped_length (krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
4213                          krb5_crypto  crypto,
4214                          size_t       data_len)
4215 {
4216     if (derived_crypto (context, crypto))
4217         return wrapped_length_dervied (context, crypto, data_len);
4218     else
4219         return wrapped_length (context, crypto, data_len);
4220 }
4221 
4222 /*
4223  * Return the size of an encrypted packet of length `data_len'
4224  */
4225 
4226 static size_t
4227 crypto_overhead (krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
4228                  krb5_crypto  crypto)
4229 {
4230     struct encryption_type *et = crypto->et;
4231     size_t res;
4232 
4233     res = CHECKSUMSIZE(et->checksum);
4234     res += et->confoundersize;
4235     if (et->padsize > 1)
4236         res += et->padsize;
4237     return res;
4238 }
4239 
4240 static size_t
4241 crypto_overhead_dervied (krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
4242                          krb5_crypto  crypto)
4243 {
4244     struct encryption_type *et = crypto->et;
4245     size_t res;
4246 
4247     if (et->keyed_checksum)
4248         res = CHECKSUMSIZE(et->keyed_checksum);
4249     else
4250         res = CHECKSUMSIZE(et->checksum);
4251     res += et->confoundersize;
4252     if (et->padsize > 1)
4253         res += et->padsize;
4254     return res;
4255 }
4256 
4257 size_t
4258 krb5_crypto_overhead (krb5_context context, krb5_crypto crypto)
     /* [<][>][^][v][top][bottom][index][help] */
4259 {
4260     if (derived_crypto (context, crypto))
4261         return crypto_overhead_dervied (context, crypto);
4262     else
4263         return crypto_overhead (context, crypto);
4264 }
4265 
4266 krb5_error_code KRB5_LIB_FUNCTION
4267 krb5_random_to_key(krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
4268                    krb5_enctype type,
4269                    const void *data,
4270                    size_t size,
4271                    krb5_keyblock *key)
4272 {
4273     krb5_error_code ret;
4274     struct encryption_type *et = _find_enctype(type);
4275     if(et == NULL) {
4276         krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
4277                                N_("encryption type %d not supported", ""),
4278                                type);
4279         return KRB5_PROG_ETYPE_NOSUPP;
4280     }
4281     if ((et->keytype->bits + 7) / 8 > size) {
4282         krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
4283                                N_("encryption key %s needs %d bytes "
4284                                   "of random to make an encryption key "
4285                                   "out of it", ""),
4286                                et->name, (int)et->keytype->size);
4287         return KRB5_PROG_ETYPE_NOSUPP;
4288     }
4289     ret = krb5_data_alloc(&key->keyvalue, et->keytype->size);
4290     if(ret)
4291         return ret;
4292     key->keytype = type;
4293     if (et->keytype->random_to_key)
4294         (*et->keytype->random_to_key)(context, key, data, size);
4295     else
4296         memcpy(key->keyvalue.data, data, et->keytype->size);
4297 
4298     return 0;
4299 }
4300 
4301 krb5_error_code
4302 _krb5_pk_octetstring2key(krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
4303                          krb5_enctype type,
4304                          const void *dhdata,
4305                          size_t dhsize,
4306                          const heim_octet_string *c_n,
4307                          const heim_octet_string *k_n,
4308                          krb5_keyblock *key)
4309 {
4310     struct encryption_type *et = _find_enctype(type);
4311     krb5_error_code ret;
4312     size_t keylen, offset;
4313     void *keydata;
4314     unsigned char counter;
4315     unsigned char shaoutput[20];
4316 
4317     if(et == NULL) {
4318         krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
4319                                N_("encryption type %d not supported", ""),
4320                                type);
4321         return KRB5_PROG_ETYPE_NOSUPP;
4322     }
4323     keylen = (et->keytype->bits + 7) / 8;
4324 
4325     keydata = malloc(keylen);
4326     if (keydata == NULL) {
4327         krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
4328         return ENOMEM;
4329     }
4330 
4331     counter = 0;
4332     offset = 0;
4333     do {
4334         SHA_CTX m;
4335         
4336         SHA1_Init(&m);
4337         SHA1_Update(&m, &counter, 1);
4338         SHA1_Update(&m, dhdata, dhsize);
4339         if (c_n)
4340             SHA1_Update(&m, c_n->data, c_n->length);
4341         if (k_n)
4342             SHA1_Update(&m, k_n->data, k_n->length);
4343         SHA1_Final(shaoutput, &m);
4344 
4345         memcpy((unsigned char *)keydata + offset,
4346                shaoutput,
4347                min(keylen - offset, sizeof(shaoutput)));
4348 
4349         offset += sizeof(shaoutput);
4350         counter++;
4351     } while(offset < keylen);
4352     memset(shaoutput, 0, sizeof(shaoutput));
4353 
4354     ret = krb5_random_to_key(context, type, keydata, keylen, key);
4355     memset(keydata, 0, sizeof(keylen));
4356     free(keydata);
4357     return ret;
4358 }
4359 
4360 static krb5_error_code
4361 encode_uvinfo(krb5_context context, krb5_const_principal p, krb5_data *data)
     /* [<][>][^][v][top][bottom][index][help] */
4362 {
4363     KRB5PrincipalName pn;
4364     krb5_error_code ret;
4365     size_t size;
4366 
4367     pn.principalName = p->name;
4368     pn.realm = p->realm;
4369 
4370     ASN1_MALLOC_ENCODE(KRB5PrincipalName, data->data, data->length,
4371                        &pn, &size, ret);
4372     if (ret) {
4373         krb5_data_zero(data);
4374         krb5_set_error_message(context, ret,
4375                                N_("Failed to encode KRB5PrincipalName", ""));
4376         return ret;
4377     }
4378     if (data->length != size)
4379         krb5_abortx(context, "asn1 compiler internal error");
4380     return 0;
4381 }
4382 
4383 static krb5_error_code
4384 encode_otherinfo(krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
4385                  const AlgorithmIdentifier *ai,
4386                  krb5_const_principal client,
4387                  krb5_const_principal server,
4388                  krb5_enctype enctype,
4389                  const krb5_data *as_req,
4390                  const krb5_data *pk_as_rep,
4391                  const Ticket *ticket,
4392                  krb5_data *other)
4393 {
4394     PkinitSP80056AOtherInfo otherinfo;
4395     PkinitSuppPubInfo pubinfo;
4396     krb5_error_code ret;
4397     krb5_data pub;
4398     size_t size;
4399 
4400     krb5_data_zero(other);
4401     memset(&otherinfo, 0, sizeof(otherinfo));
4402     memset(&pubinfo, 0, sizeof(pubinfo));
4403 
4404     pubinfo.enctype = enctype;
4405     pubinfo.as_REQ = *as_req;
4406     pubinfo.pk_as_rep = *pk_as_rep;
4407     pubinfo.ticket = *ticket;
4408     ASN1_MALLOC_ENCODE(PkinitSuppPubInfo, pub.data, pub.length,
4409                        &pubinfo, &size, ret);
4410     if (ret) {
4411         krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
4412         return ret;
4413     }
4414     if (pub.length != size)
4415         krb5_abortx(context, "asn1 compiler internal error");
4416 
4417     ret = encode_uvinfo(context, client, &otherinfo.partyUInfo);
4418     if (ret) {
4419         free(pub.data);
4420         return ret;
4421     }
4422     ret = encode_uvinfo(context, server, &otherinfo.partyVInfo);
4423     if (ret) {
4424         free(otherinfo.partyUInfo.data);
4425         free(pub.data);
4426         return ret;
4427     }
4428 
4429     otherinfo.algorithmID = *ai;
4430     otherinfo.suppPubInfo = &pub;
4431 
4432     ASN1_MALLOC_ENCODE(PkinitSP80056AOtherInfo, other->data, other->length,
4433                        &otherinfo, &size, ret);
4434     free(otherinfo.partyUInfo.data);
4435     free(otherinfo.partyVInfo.data);
4436     free(pub.data);
4437     if (ret) {
4438         krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
4439         return ret;
4440     }
4441     if (other->length != size)
4442         krb5_abortx(context, "asn1 compiler internal error");
4443 
4444     return 0;
4445 }
4446 
4447 krb5_error_code
4448 _krb5_pk_kdf(krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
4449              const struct AlgorithmIdentifier *ai,
4450              const void *dhdata,
4451              size_t dhsize,
4452              krb5_const_principal client,
4453              krb5_const_principal server,
4454              krb5_enctype enctype,
4455              const krb5_data *as_req,
4456              const krb5_data *pk_as_rep,
4457              const Ticket *ticket,
4458              krb5_keyblock *key)
4459 {
4460     struct encryption_type *et;
4461     krb5_error_code ret;
4462     krb5_data other;
4463     size_t keylen, offset;
4464     uint32_t counter;
4465     unsigned char *keydata;
4466     unsigned char shaoutput[20];
4467 
4468     if (der_heim_oid_cmp(oid_id_pkinit_kdf_ah_sha1(), &ai->algorithm) != 0) {
4469         krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
4470                                N_("KDF not supported", ""));
4471         return KRB5_PROG_ETYPE_NOSUPP;
4472     }
4473     if (ai->parameters != NULL &&
4474         (ai->parameters->length != 2 ||
4475          memcmp(ai->parameters->data, "\x05\x00", 2) != 0))
4476         {
4477             krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
4478                                    N_("kdf params not NULL or the NULL-type",
4479                                       ""));
4480             return KRB5_PROG_ETYPE_NOSUPP;
4481         }
4482 
4483     et = _find_enctype(enctype);
4484     if(et == NULL) {
4485         krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
4486                                N_("encryption type %d not supported", ""),
4487                                enctype);
4488         return KRB5_PROG_ETYPE_NOSUPP;
4489     }
4490     keylen = (et->keytype->bits + 7) / 8;
4491 
4492     keydata = malloc(keylen);
4493     if (keydata == NULL) {
4494         krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
4495         return ENOMEM;
4496     }
4497 
4498     ret = encode_otherinfo(context, ai, client, server,
4499                            enctype, as_req, pk_as_rep, ticket, &other);
4500     if (ret) {
4501         free(keydata);
4502         return ret;
4503     }
4504 
4505     offset = 0;
4506     counter = 1;
4507     do {
4508         unsigned char cdata[4];
4509         SHA_CTX m;
4510         
4511         SHA1_Init(&m);
4512         _krb5_put_int(cdata, counter, 4);
4513         SHA1_Update(&m, cdata, 4);
4514         SHA1_Update(&m, dhdata, dhsize);
4515         SHA1_Update(&m, other.data, other.length);
4516         SHA1_Final(shaoutput, &m);
4517 
4518         memcpy((unsigned char *)keydata + offset,
4519                shaoutput,
4520                min(keylen - offset, sizeof(shaoutput)));
4521 
4522         offset += sizeof(shaoutput);
4523         counter++;
4524     } while(offset < keylen);
4525     memset(shaoutput, 0, sizeof(shaoutput));
4526 
4527     free(other.data);
4528 
4529     ret = krb5_random_to_key(context, enctype, keydata, keylen, key);
4530     memset(keydata, 0, sizeof(keylen));
4531     free(keydata);
4532 
4533     return ret;
4534 }
4535 
4536 
4537 krb5_error_code KRB5_LIB_FUNCTION
4538 krb5_crypto_prf_length(krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
4539                        krb5_enctype type,
4540                        size_t *length)
4541 {
4542     struct encryption_type *et = _find_enctype(type);
4543 
4544     if(et == NULL || et->prf_length == 0) {
4545         krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
4546                                N_("encryption type %d not supported", ""),
4547                                type);
4548         return KRB5_PROG_ETYPE_NOSUPP;
4549     }
4550 
4551     *length = et->prf_length;
4552     return 0;
4553 }
4554 
4555 krb5_error_code KRB5_LIB_FUNCTION
4556 krb5_crypto_prf(krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
4557                 const krb5_crypto crypto,
4558                 const krb5_data *input,
4559                 krb5_data *output)
4560 {
4561     struct encryption_type *et = crypto->et;
4562 
4563     krb5_data_zero(output);
4564 
4565     if(et->prf == NULL) {
4566         krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
4567                                "kerberos prf for %s not supported",
4568                                et->name);
4569         return KRB5_PROG_ETYPE_NOSUPP;
4570     }
4571 
4572     return (*et->prf)(context, crypto, input, output);
4573 }
4574 
4575 #ifndef HEIMDAL_SMALLER
4576 
4577 static struct key_type *keytypes[] = {
4578     &keytype_null,
4579     &keytype_des,
4580     &keytype_des3_derived,
4581 #ifdef DES3_OLD_ENCTYPE
4582     &keytype_des3,
4583 #endif
4584     &keytype_aes128,
4585     &keytype_aes256,
4586     &keytype_arcfour
4587 };
4588 
4589 static int num_keytypes = sizeof(keytypes) / sizeof(keytypes[0]);
4590 
4591 
4592 static struct key_type *
4593 _find_keytype(krb5_keytype type)
     /* [<][>][^][v][top][bottom][index][help] */
4594 {
4595     int i;
4596     for(i = 0; i < num_keytypes; i++)
4597         if(keytypes[i]->type == type)
4598             return keytypes[i];
4599     return NULL;
4600 }
4601 
4602 /*
4603  * First take the configured list of etypes for `keytype' if available,
4604  * else, do `krb5_keytype_to_enctypes'.
4605  */
4606 
4607 krb5_error_code KRB5_LIB_FUNCTION
4608 krb5_keytype_to_enctypes_default (krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
4609                                   krb5_keytype keytype,
4610                                   unsigned *len,
4611                                   krb5_enctype **val)
4612     __attribute__((deprecated))
4613 {
4614     unsigned int i, n;
4615     krb5_enctype *ret;
4616 
4617     if (keytype != KEYTYPE_DES || context->etypes_des == NULL)
4618         return krb5_keytype_to_enctypes (context, keytype, len, val);
4619 
4620     for (n = 0; context->etypes_des[n]; ++n)
4621         ;
4622     ret = malloc (n * sizeof(*ret));
4623     if (ret == NULL && n != 0) {
4624         krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
4625         return ENOMEM;
4626     }
4627     for (i = 0; i < n; ++i)
4628         ret[i] = context->etypes_des[i];
4629     *len = n;
4630     *val = ret;
4631     return 0;
4632 }
4633 
4634 krb5_error_code KRB5_LIB_FUNCTION
4635 krb5_keytype_to_string(krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
4636                        krb5_keytype keytype,
4637                        char **string)
4638     __attribute__((deprecated))
4639 {
4640     struct key_type *kt = _find_keytype(keytype);
4641     if(kt == NULL) {
4642         krb5_set_error_message(context, KRB5_PROG_KEYTYPE_NOSUPP,
4643                                "key type %d not supported", keytype);
4644         return KRB5_PROG_KEYTYPE_NOSUPP;
4645     }
4646     *string = strdup(kt->name);
4647     if(*string == NULL) {
4648         krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
4649         return ENOMEM;
4650     }
4651     return 0;
4652 }
4653 
4654 
4655 krb5_error_code KRB5_LIB_FUNCTION
4656 krb5_string_to_keytype(krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
4657                        const char *string,
4658                        krb5_keytype *keytype)
4659     __attribute__((deprecated))
4660 {
4661     char *end;
4662     int i;
4663 
4664     for(i = 0; i < num_keytypes; i++)
4665         if(strcasecmp(keytypes[i]->name, string) == 0){
4666             *keytype = keytypes[i]->type;
4667             return 0;
4668         }
4669 
4670     /* check if the enctype is a number */
4671     *keytype = strtol(string, &end, 0);
4672     if(*end == '\0' && *keytype != 0) {
4673         if (krb5_enctype_valid(context, *keytype) == 0)
4674             return 0;
4675     }
4676 
4677     krb5_set_error_message(context, KRB5_PROG_KEYTYPE_NOSUPP,
4678                            "key type %s not supported", string);
4679     return KRB5_PROG_KEYTYPE_NOSUPP;
4680 }
4681 
4682 krb5_error_code KRB5_LIB_FUNCTION
4683 krb5_keytype_to_enctypes (krb5_context context,
     /* [<][>][^][v][top][bottom][index][help] */
4684                           krb5_keytype keytype,
4685                           unsigned *len,
4686                           krb5_enctype **val)
4687 {
4688     int i;
4689     unsigned n = 0;
4690     krb5_enctype *ret;
4691 
4692     for (i = num_etypes - 1; i >= 0; --i) {
4693         if (etypes[i]->keytype->type == keytype
4694             && !(etypes[i]->flags & F_PSEUDO))
4695             ++n;
4696     }
4697     ret = malloc(n * sizeof(*ret));
4698     if (ret == NULL && n != 0) {
4699         krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
4700         return ENOMEM;
4701     }
4702     n = 0;
4703     for (i = num_etypes - 1; i >= 0; --i) {
4704         if (etypes[i]->keytype->type == keytype
4705             && !(etypes[i]->flags & F_PSEUDO))
4706             ret[n++] = etypes[i]->type;
4707     }
4708     *len = n;
4709     *val = ret;
4710     return 0;
4711 }
4712 
4713 #endif /* HEIMDAL_SMALLER */

/* [<][>][^][v][top][bottom][index][help] */