LCOV - code coverage report
Current view: top level - third_party/heimdal/lib/krb5 - crypto.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 784 1598 49.1 %
Date: 2024-04-21 15:09:00 Functions: 71 99 71.7 %

          Line data    Source code
       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             : 
      36             : struct _krb5_key_usage {
      37             :     unsigned usage;
      38             :     struct _krb5_key_data key;
      39             : };
      40             : 
      41             : 
      42             : #ifndef HEIMDAL_SMALLER
      43             : #define DES3_OLD_ENCTYPE 1
      44             : #endif
      45             : 
      46             : static krb5_error_code _get_derived_key(krb5_context, krb5_crypto,
      47             :                                         unsigned, struct _krb5_key_data**);
      48             : static struct _krb5_key_data *_new_derived_key(krb5_crypto crypto, unsigned usage);
      49             : 
      50             : static void free_key_schedule(krb5_context,
      51             :                               struct _krb5_key_data *,
      52             :                               struct _krb5_encryption_type *);
      53             : 
      54             : /*
      55             :  * Converts etype to a user readable string and sets as a side effect
      56             :  * the krb5_error_message containing this string. Returns
      57             :  * KRB5_PROG_ETYPE_NOSUPP in not the conversion of the etype failed in
      58             :  * which case the error code of the etype convesion is returned.
      59             :  */
      60             : 
      61             : static krb5_error_code
      62      223808 : unsupported_enctype(krb5_context context, krb5_enctype etype)
      63             : {
      64        6826 :     krb5_error_code ret;
      65        6826 :     char *name;
      66             : 
      67      223808 :     ret = krb5_enctype_to_string(context, etype, &name);
      68      223808 :     if (ret)
      69      216982 :         return ret;
      70             : 
      71           0 :     krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
      72           0 :                            N_("Encryption type %s not supported", ""),
      73             :                            name);
      74           0 :     free(name);
      75           0 :     return KRB5_PROG_ETYPE_NOSUPP;
      76             : }
      77             : 
      78             : /*
      79             :  *
      80             :  */
      81             : 
      82             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
      83      871419 : krb5_enctype_keysize(krb5_context context,
      84             :                      krb5_enctype type,
      85             :                      size_t *keysize)
      86             : {
      87      871419 :     struct _krb5_encryption_type *et = _krb5_find_enctype(type);
      88      871419 :     if(et == NULL) {
      89           0 :         return unsupported_enctype (context, type);
      90             :     }
      91      871419 :     *keysize = et->keytype->size;
      92      871419 :     return 0;
      93             : }
      94             : 
      95             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
      96      180537 : krb5_enctype_keybits(krb5_context context,
      97             :                      krb5_enctype type,
      98             :                      size_t *keybits)
      99             : {
     100      180537 :     struct _krb5_encryption_type *et = _krb5_find_enctype(type);
     101      180537 :     if(et == NULL) {
     102           0 :         return unsupported_enctype (context, type);
     103             :     }
     104      180537 :     *keybits = et->keytype->bits;
     105      180537 :     return 0;
     106             : }
     107             : 
     108             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
     109      250057 : krb5_generate_random_keyblock(krb5_context context,
     110             :                               krb5_enctype type,
     111             :                               krb5_keyblock *key)
     112             : {
     113        8060 :     krb5_error_code ret;
     114      250057 :     struct _krb5_encryption_type *et = _krb5_find_enctype(type);
     115      250057 :     if(et == NULL) {
     116           0 :         return unsupported_enctype (context, type);
     117             :     }
     118      250057 :     ret = krb5_data_alloc(&key->keyvalue, et->keytype->size);
     119      250057 :     if(ret)
     120           0 :         return ret;
     121      250057 :     key->keytype = type;
     122      250057 :     if(et->keytype->random_key)
     123           0 :         (*et->keytype->random_key)(context, key);
     124             :     else
     125      250057 :         krb5_generate_random_block(key->keyvalue.data,
     126             :                                    key->keyvalue.length);
     127      241997 :     return 0;
     128             : }
     129             : 
     130             : static krb5_error_code
     131    11968827 : _key_schedule(krb5_context context,
     132             :               struct _krb5_key_data *key)
     133             : {
     134      186076 :     krb5_error_code ret;
     135      186076 :     struct _krb5_encryption_type *et;
     136      186076 :     struct _krb5_key_type *kt;
     137             : 
     138    11968827 :     if (key->schedule != NULL)
     139     6145991 :         return 0;
     140             : 
     141     5815328 :     et = _krb5_find_enctype(key->key->keytype);
     142             : 
     143     5815328 :     if (et == NULL) {
     144           0 :         return unsupported_enctype (context,
     145           0 :                                key->key->keytype);
     146             :     }
     147             : 
     148     5815328 :     kt = et->keytype;
     149             : 
     150     5815328 :     if(kt->schedule == NULL)
     151           0 :         return 0;
     152     5815328 :     ALLOC(key->schedule, 1);
     153     5815328 :     if (key->schedule == NULL)
     154           0 :         return krb5_enomem(context);
     155     5815328 :     ret = krb5_data_alloc(key->schedule, kt->schedule_size);
     156     5815328 :     if(ret) {
     157           0 :         free(key->schedule);
     158           0 :         key->schedule = NULL;
     159           0 :         return ret;
     160             :     }
     161     5815328 :     (*kt->schedule)(context, kt, key);
     162     5815328 :     return 0;
     163             : }
     164             : 
     165             : /************************************************************
     166             :  *                                                          *
     167             :  ************************************************************/
     168             : 
     169             : static krb5_error_code
     170      722331 : EVP_unkeyed_checksum(krb5_context context,
     171             :                      krb5_crypto crypto,
     172             :                      struct _krb5_key_data *key,
     173             :                      unsigned usage,
     174             :                      const struct krb5_crypto_iov *iov,
     175             :                      int niov,
     176             :                      Checksum *C,
     177             :                      const EVP_MD *md)
     178             : {
     179      722331 :     if (_krb5_evp_digest_iov(crypto,
     180             :                              iov, niov,
     181             :                              C->checksum.data, NULL,
     182             :                              md, NULL) != 1)
     183           0 :         krb5_abortx(context, "unkeyed checksum failed");
     184             : 
     185      722331 :     return 0;
     186             : }
     187             : 
     188             : #define EVP_SHA_CHECKSUM(name)                              \
     189             :                                                             \
     190             :     static krb5_error_code                                  \
     191             :     SHA ## name ##_checksum(krb5_context context,           \
     192             :                        krb5_crypto crypto,                  \
     193             :                        struct _krb5_key_data *key,          \
     194             :                        unsigned usage,                      \
     195             :                        const struct krb5_crypto_iov *iov,   \
     196             :                        int niov,                            \
     197             :                        Checksum *C)                         \
     198             :     {                                                       \
     199             :         return EVP_unkeyed_checksum(context, crypto, key,   \
     200             :                                     usage, iov, niov,       \
     201             :                                     C, EVP_sha##name());    \
     202             :     }
     203             : 
     204      722331 : EVP_SHA_CHECKSUM(1)
     205           0 : EVP_SHA_CHECKSUM(256)
     206           0 : EVP_SHA_CHECKSUM(384)
     207           0 : EVP_SHA_CHECKSUM(512)
     208             : 
     209             : /* HMAC according to RFC2104 */
     210             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
     211     1130119 : _krb5_internal_hmac_iov(krb5_context context,
     212             :                         krb5_crypto crypto,
     213             :                         struct _krb5_checksum_type *cm,
     214             :                         unsigned usage,
     215             :                         const struct krb5_crypto_iov *iov,
     216             :                         int niov,
     217             :                         struct _krb5_key_data *keyblock,
     218             :                         Checksum *result)
     219             : {
     220         196 :     unsigned char *ipad, *opad;
     221         196 :     unsigned char *key;
     222         196 :     struct krb5_crypto_iov *working;
     223         196 :     size_t key_len;
     224         196 :     size_t i;
     225             : 
     226     1130119 :     ipad = malloc(cm->blocksize);
     227     1130119 :     if (ipad == NULL)
     228           0 :         return ENOMEM;
     229             : 
     230     1130119 :     opad = malloc(cm->blocksize + cm->checksumsize);
     231     1130119 :     if (opad == NULL) {
     232           0 :         free(ipad);
     233           0 :         return ENOMEM;
     234             :     }
     235             : 
     236     1130119 :     working = calloc(niov + 1, sizeof(struct krb5_crypto_iov));
     237     1130119 :     if (working == NULL) {
     238           0 :         free(ipad);
     239           0 :         free(opad);
     240           0 :         return ENOMEM;
     241             :     }
     242             : 
     243     1130119 :     memset(ipad, 0x36, cm->blocksize);
     244     1130119 :     memset(opad, 0x5c, cm->blocksize);
     245             : 
     246     1130119 :     if(keyblock->key->keyvalue.length > cm->blocksize){
     247           0 :         working[0].data = keyblock->key->keyvalue;
     248           0 :         working[0].flags = KRB5_CRYPTO_TYPE_DATA;
     249           0 :         (*cm->checksum)(context,
     250             :                         crypto,
     251             :                         keyblock,
     252             :                         usage,
     253             :                         working,
     254             :                         1,
     255             :                         result);
     256           0 :         key = result->checksum.data;
     257           0 :         key_len = result->checksum.length;
     258             :     } else {
     259     1130119 :         key = keyblock->key->keyvalue.data;
     260     1130119 :         key_len = keyblock->key->keyvalue.length;
     261             :     }
     262    19212039 :     for(i = 0; i < key_len; i++){
     263    18081920 :         ipad[i] ^= key[i];
     264    18081920 :         opad[i] ^= key[i];
     265             :     }
     266             : 
     267     1130119 :     working[0].data.data = ipad;
     268     1130119 :     working[0].data.length = cm->blocksize;
     269     1130119 :     working[0].flags = KRB5_CRYPTO_TYPE_DATA;
     270     2260238 :     for (i = 0; i < niov; i++)
     271     1130119 :         working[i + 1] = iov[i];
     272             : 
     273     1130119 :     (*cm->checksum)(context, crypto, keyblock, usage, working, niov + 1, result);
     274     1130119 :     memcpy(opad + cm->blocksize, result->checksum.data,
     275             :            result->checksum.length);
     276             : 
     277     1130119 :     working[0].data.data = opad;
     278     1130119 :     working[0].data.length = cm->blocksize + cm->checksumsize;
     279     1130119 :     working[0].flags = KRB5_CRYPTO_TYPE_DATA;
     280     1130119 :     (*cm->checksum)(context, crypto, keyblock, usage, working, 1, result);
     281     1130119 :     memset(ipad, 0, cm->blocksize);
     282     1130119 :     free(ipad);
     283     1130119 :     memset(opad, 0, cm->blocksize + cm->checksumsize);
     284     1130119 :     free(opad);
     285     1130119 :     free(working);
     286             : 
     287     1130119 :     return 0;
     288             : }
     289             : 
     290             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
     291     1130119 : _krb5_internal_hmac(krb5_context context,
     292             :                     krb5_crypto crypto,
     293             :                     struct _krb5_checksum_type *cm,
     294             :                     const void *data,
     295             :                     size_t len,
     296             :                     unsigned usage,
     297             :                     struct _krb5_key_data *keyblock,
     298             :                     Checksum *result)
     299             : {
     300         196 :     struct krb5_crypto_iov iov[1];
     301             : 
     302     1130119 :     iov[0].data.data = (void *) data;
     303     1130119 :     iov[0].data.length = len;
     304     1130119 :     iov[0].flags = KRB5_CRYPTO_TYPE_DATA;
     305     1130119 :     return _krb5_internal_hmac_iov(context, crypto, cm, usage, iov, 1,
     306             :                                    keyblock, result);
     307             : }
     308             : 
     309             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
     310      589876 : krb5_hmac(krb5_context context,
     311             :           krb5_cksumtype cktype,
     312             :           const void *data,
     313             :           size_t len,
     314             :           unsigned usage,
     315             :           krb5_keyblock *key,
     316             :           Checksum *result)
     317             : {
     318      589876 :     struct _krb5_checksum_type *c = _krb5_find_checksum(cktype);
     319           0 :     struct _krb5_key_data kd;
     320             : 
     321           0 :     krb5_error_code ret;
     322             : 
     323      589876 :     if (c == NULL) {
     324           0 :         krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
     325           0 :                                 N_("checksum type %d not supported", ""),
     326             :                                 cktype);
     327           0 :         return KRB5_PROG_SUMTYPE_NOSUPP;
     328             :     }
     329             : 
     330      589876 :     kd.key = key;
     331      589876 :     kd.schedule = NULL;
     332             : 
     333      589876 :     ret = _krb5_internal_hmac(context, NULL, c, data, len, usage, &kd, result);
     334             : 
     335      589876 :     if (kd.schedule)
     336           0 :         krb5_free_data(context, kd.schedule);
     337             : 
     338      589876 :     return ret;
     339             : }
     340             : 
     341             : krb5_error_code
     342     2796492 : _krb5_SP_HMAC_SHA1_checksum(krb5_context context,
     343             :                             krb5_crypto crypto,
     344             :                             struct _krb5_key_data *key,
     345             :                             unsigned usage,
     346             :                             const struct krb5_crypto_iov *iov,
     347             :                             int niov,
     348             :                             Checksum *result)
     349             : {
     350       28803 :     krb5_error_code ret;
     351       28803 :     unsigned char hmac[EVP_MAX_MD_SIZE];
     352     2796492 :     unsigned int hmaclen = sizeof(hmac);
     353             : 
     354     2796492 :     ret = _krb5_evp_hmac_iov(context, crypto, key, iov, niov, hmac, &hmaclen,
     355             :                              EVP_sha1(), NULL);
     356     2796492 :     if (ret)
     357           0 :         return ret;
     358             : 
     359     2796492 :     heim_assert(result->checksum.length <= hmaclen,
     360             :                 "SHA1 checksum too short");
     361     2796492 :     memcpy(result->checksum.data, hmac, result->checksum.length);
     362             : 
     363     2796492 :     return 0;
     364             : }
     365             : 
     366             : krb5_error_code
     367     2027794 : _krb5_SP_HMAC_SHA1_verify(krb5_context context,
     368             :                           krb5_crypto crypto,
     369             :                           struct _krb5_key_data *key,
     370             :                           unsigned usage,
     371             :                           const struct krb5_crypto_iov *iov,
     372             :                           int niov,
     373             :                           Checksum *verify)
     374             : {
     375       23420 :     krb5_error_code ret;
     376       23420 :     unsigned char hmac[EVP_MAX_MD_SIZE];
     377     2027794 :     unsigned int hmaclen = sizeof(hmac);
     378       23420 :     krb5_data data;
     379             : 
     380     2027794 :     ret = _krb5_evp_hmac_iov(context, crypto, key, iov, niov, hmac, &hmaclen,
     381             :                              EVP_sha1(), NULL);
     382     2027794 :     if (ret)
     383           0 :         return ret;
     384             : 
     385     2027794 :     data.data = hmac;
     386     2027794 :     data.length = min(hmaclen, verify->checksum.length);
     387             : 
     388     2027794 :     if(krb5_data_ct_cmp(&data, &verify->checksum) != 0)
     389         477 :         return KRB5KRB_AP_ERR_BAD_INTEGRITY;
     390             : 
     391     2003897 :     return 0;
     392             : }
     393             : 
     394             : #define SHA_CHECKSUM(name, blocksize, outputsize)           \
     395             :     struct _krb5_checksum_type _krb5_checksum_sha##name = { \
     396             :         CKSUMTYPE_SHA##name,                                \
     397             :         "sha" #name,                                      \
     398             :         blocksize,                                          \
     399             :         outputsize,                                         \
     400             :         F_CPROOF,                                           \
     401             :         SHA##name##_checksum,                               \
     402             :         NULL                                                \
     403             :     };
     404             : 
     405             : SHA_CHECKSUM(1,   64,  20);
     406             : SHA_CHECKSUM(256, 64,  32);
     407             : SHA_CHECKSUM(384, 128, 48);
     408             : SHA_CHECKSUM(512, 128, 64);
     409             : 
     410             : KRB5_LIB_FUNCTION struct _krb5_checksum_type * KRB5_LIB_CALL
     411     4639485 : _krb5_find_checksum(krb5_cksumtype type)
     412             : {
     413       50927 :     int i;
     414    29203735 :     for(i = 0; i < _krb5_num_checksums; i++)
     415    29203716 :         if(_krb5_checksum_types[i]->type == type)
     416     4639466 :             return _krb5_checksum_types[i];
     417          19 :     return NULL;
     418             : }
     419             : 
     420             : static krb5_error_code
     421     4993524 : get_checksum_key(krb5_context context,
     422             :                  krb5_crypto crypto,
     423             :                  unsigned usage,  /* not krb5_key_usage */
     424             :                  struct _krb5_checksum_type *ct,
     425             :                  struct _krb5_key_data **key)
     426             : {
     427     4993524 :     krb5_error_code ret = 0;
     428     4993524 :     struct _krb5_checksum_type *kct = NULL;
     429             : 
     430     4993524 :     if (crypto == NULL) {
     431           0 :         krb5_set_error_message(context, KRB5_BAD_ENCTYPE,
     432           0 :                                N_("Checksum type %s is keyed but no "
     433             :                                   "crypto context (key) was passed in", ""),
     434             :                                ct->name);
     435           0 :         return KRB5_BAD_ENCTYPE;
     436             :     }
     437     4993524 :     kct = crypto->et->keyed_checksum;
     438     4993524 :     if (kct == NULL || kct->type != ct->type) {
     439         104 :         krb5_set_error_message(context, KRB5_BAD_ENCTYPE,
     440         104 :                                N_("Checksum type %s is keyed, but "
     441             :                                   "the key type %s passed didnt have that checksum "
     442             :                                   "type as the keyed type", ""),
     443         104 :                                ct->name, crypto->et->name);
     444         104 :         return KRB5_BAD_ENCTYPE;
     445             :     }
     446             : 
     447     4993420 :     if(ct->flags & F_DERIVED)
     448     4824286 :         ret = _get_derived_key(context, crypto, usage, key);
     449      169134 :     else if(ct->flags & F_VARIANT) {
     450           0 :         size_t i;
     451             : 
     452           0 :         *key = _new_derived_key(crypto, 0xff/* KRB5_KU_RFC1510_VARIANT */);
     453           0 :         if (*key == NULL)
     454           0 :             return krb5_enomem(context);
     455           0 :         ret = krb5_copy_keyblock(context, crypto->key.key, &(*key)->key);
     456           0 :         if(ret)
     457           0 :             return ret;
     458           0 :         for(i = 0; i < (*key)->key->keyvalue.length; i++)
     459           0 :             ((unsigned char*)(*key)->key->keyvalue.data)[i] ^= 0xF0;
     460             :     } else {
     461      169134 :         *key = &crypto->key;
     462             :     }
     463     4993420 :     if(ret == 0)
     464     4993420 :         ret = _key_schedule(context, *key);
     465     4941153 :     return ret;
     466             : }
     467             : 
     468             : static krb5_error_code
     469     2968974 : create_checksum_iov(krb5_context context,
     470             :                     struct _krb5_checksum_type *ct,
     471             :                     krb5_crypto crypto,
     472             :                     unsigned usage,
     473             :                     struct krb5_crypto_iov *iov,
     474             :                     int niov,
     475             :                     krb5_flags flags,
     476             :                     Checksum *result)
     477             : {
     478       28827 :     krb5_error_code ret;
     479       28827 :     struct _krb5_key_data *dkey;
     480             : 
     481     2968974 :     if (ct->flags & F_DISABLED) {
     482           0 :         krb5_clear_error_message (context);
     483           0 :         return KRB5_PROG_SUMTYPE_NOSUPP;
     484             :     }
     485     2968974 :     if (ct->flags & F_KEYED) {
     486     2964073 :         ret = get_checksum_key(context, crypto, usage, ct, &dkey);
     487     2964073 :         if (ret)
     488           0 :             return ret;
     489        4901 :     } else if ((flags & KRB5_CRYPTO_FLAG_ALLOW_UNKEYED_CHECKSUM) == 0) {
     490           0 :         return EINVAL;
     491             :     } else
     492        4901 :         dkey = NULL;
     493             : 
     494     2968974 :     result->cksumtype = ct->type;
     495             : 
     496     2968974 :     return (*ct->checksum)(context, crypto, dkey, usage, iov, niov, result);
     497             : }
     498             : 
     499             : static krb5_error_code
     500     1826746 : create_checksum (krb5_context context,
     501             :                  struct _krb5_checksum_type *ct,
     502             :                  krb5_crypto crypto,
     503             :                  unsigned usage,
     504             :                  void *data,
     505             :                  size_t len,
     506             :                  krb5_flags flags,
     507             :                  Checksum *result)
     508             : {
     509       27514 :     int ret;
     510       27514 :     struct krb5_crypto_iov iov[1];
     511             : 
     512     1826746 :     ret = krb5_data_alloc(&result->checksum, ct->checksumsize);
     513     1826746 :     if (ret)
     514           0 :         return ret;
     515             : 
     516     1826746 :     iov[0].data.data = data;
     517     1826746 :     iov[0].data.length = len;
     518     1826746 :     iov[0].flags = KRB5_CRYPTO_TYPE_DATA;
     519             : 
     520     1826746 :     return create_checksum_iov(context, ct, crypto, usage, iov, 1, flags, result);
     521             : }
     522             : 
     523             : static int
     524     1246492 : arcfour_checksum_p(struct _krb5_checksum_type *ct, krb5_crypto crypto)
     525             : {
     526     1415730 :     return (ct->type == CKSUMTYPE_HMAC_MD5) &&
     527      169238 :         (crypto->key.key->keytype == KEYTYPE_ARCFOUR);
     528             : }
     529             : 
     530             : static inline krb5_flags
     531     1246492 : crypto_flags(krb5_crypto crypto)
     532             : {
     533             :     /* If caller didn't specify a key, unkeyed checksums are the only option */
     534     1246492 :     if (crypto == NULL)
     535         179 :         return KRB5_CRYPTO_FLAG_ALLOW_UNKEYED_CHECKSUM;
     536             :     else
     537     1246313 :         return crypto->flags;
     538             : }
     539             : 
     540             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
     541      757737 : krb5_create_checksum(krb5_context context,
     542             :                      krb5_crypto crypto,
     543             :                      krb5_key_usage usage,
     544             :                      int type,
     545             :                      void *data,
     546             :                      size_t len,
     547             :                      Checksum *result)
     548             : {
     549      757737 :     struct _krb5_checksum_type *ct = NULL;
     550       13375 :     unsigned keyusage;
     551             : 
     552             :     /* type 0 -> pick from crypto */
     553      757737 :     if (type) {
     554        4901 :         ct = _krb5_find_checksum(type);
     555      752836 :     } else if (crypto) {
     556      752836 :         ct = crypto->et->keyed_checksum;
     557      752836 :         if (ct == NULL)
     558           0 :             ct = crypto->et->checksum;
     559             :     }
     560             : 
     561      757737 :     if(ct == NULL) {
     562           0 :         krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
     563           0 :                                 N_("checksum type %d not supported", ""),
     564             :                                 type);
     565           0 :         return KRB5_PROG_SUMTYPE_NOSUPP;
     566             :     }
     567             : 
     568      757737 :     if (arcfour_checksum_p(ct, crypto)) {
     569      167581 :         keyusage = usage;
     570      167581 :         _krb5_usage2arcfour(context, &keyusage);
     571             :     } else
     572      590156 :         keyusage = CHECKSUM_USAGE(usage);
     573             : 
     574      771112 :     return create_checksum(context, ct, crypto, keyusage, data, len,
     575             :                            crypto_flags(crypto), result);
     576             : }
     577             : 
     578             : static krb5_error_code
     579     2033224 : verify_checksum_iov(krb5_context context,
     580             :                     krb5_crypto crypto,
     581             :                     unsigned usage, /* not krb5_key_usage */
     582             :                     struct krb5_crypto_iov *iov,
     583             :                     int niov,
     584             :                     krb5_flags flags,
     585             :                     Checksum *cksum)
     586             : {
     587       23440 :     krb5_error_code ret;
     588       23440 :     struct _krb5_key_data *dkey;
     589       23440 :     Checksum c;
     590       23440 :     struct _krb5_checksum_type *ct;
     591             : 
     592     2033224 :     ct = _krb5_find_checksum(cksum->cksumtype);
     593     2033224 :     if (ct == NULL || (ct->flags & F_DISABLED)) {
     594           0 :         krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
     595           0 :                                 N_("checksum type %d not supported", ""),
     596           0 :                                 cksum->cksumtype);
     597           0 :         return KRB5_PROG_SUMTYPE_NOSUPP;
     598             :     }
     599     2033224 :     if(ct->checksumsize != cksum->checksum.length) {
     600           0 :         krb5_clear_error_message (context);
     601           0 :         krb5_set_error_message(context, KRB5KRB_AP_ERR_BAD_INTEGRITY,
     602           0 :                                N_("Decrypt integrity check failed for checksum type %s, "
     603             :                                   "length was %u, expected %u", ""),
     604           0 :                                ct->name, (unsigned)cksum->checksum.length,
     605           0 :                                (unsigned)ct->checksumsize);
     606             : 
     607           0 :         return KRB5KRB_AP_ERR_BAD_INTEGRITY; /* XXX */
     608             :     }
     609     2033224 :     if (ct->flags & F_KEYED) {
     610     2029451 :         ret = get_checksum_key(context, crypto, usage, ct, &dkey);
     611     2029451 :         if (ret)
     612         104 :             return ret;
     613        3773 :     } else if ((flags & KRB5_CRYPTO_FLAG_ALLOW_UNKEYED_CHECKSUM) == 0) {
     614           0 :         krb5_clear_error_message (context);
     615           0 :         krb5_set_error_message(context, KRB5KRB_AP_ERR_INAPP_CKSUM,
     616           0 :                                N_("Unkeyed checksum type %s provided where keyed "
     617             :                                   "checksum was expected", ""), ct->name);
     618             : 
     619           0 :         return KRB5KRB_AP_ERR_INAPP_CKSUM;
     620             :     } else
     621        3773 :         dkey = NULL;
     622             : 
     623             :     /*
     624             :      * If checksum have a verify function, lets use that instead of
     625             :      * calling ->checksum and then compare result.
     626             :      */
     627             : 
     628     2033120 :     if(ct->verify) {
     629     2027794 :         ret = (*ct->verify)(context, crypto, dkey, usage, iov, niov, cksum);
     630     2027794 :         if (ret)
     631         477 :             krb5_set_error_message(context, ret,
     632         477 :                                    N_("Decrypt integrity check failed for checksum "
     633             :                                       "type %s, key type %s", ""),
     634         477 :                                    ct->name, (crypto != NULL)? crypto->et->name : "(none)");
     635     2027794 :         return ret;
     636             :     }
     637             : 
     638        5326 :     ret = krb5_data_alloc (&c.checksum, ct->checksumsize);
     639        5326 :     if (ret)
     640           0 :         return ret;
     641             : 
     642        5326 :     ret = (*ct->checksum)(context, crypto, dkey, usage, iov, niov, &c);
     643        5326 :     if (ret) {
     644           0 :         krb5_data_free(&c.checksum);
     645           0 :         return ret;
     646             :     }
     647             : 
     648        5326 :     if(krb5_data_ct_cmp(&c.checksum, &cksum->checksum) != 0) {
     649          28 :         ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
     650          28 :         krb5_set_error_message(context, ret,
     651          28 :                                N_("Decrypt integrity check failed for checksum "
     652             :                                   "type %s, key type %s", ""),
     653          28 :                                ct->name, crypto ? crypto->et->name : "(unkeyed)");
     654             :     } else {
     655        5278 :         ret = 0;
     656             :     }
     657        5326 :     krb5_data_free (&c.checksum);
     658        5326 :     return ret;
     659             : }
     660             : 
     661             : static krb5_error_code
     662     1607545 : verify_checksum(krb5_context context,
     663             :                 krb5_crypto crypto,
     664             :                 unsigned usage, /* not krb5_key_usage */
     665             :                 void *data,
     666             :                 size_t len,
     667             :                 krb5_flags flags,
     668             :                 Checksum *cksum)
     669             : {
     670       22128 :     struct krb5_crypto_iov iov[1];
     671             : 
     672     1607545 :     iov[0].data.data = data;
     673     1607545 :     iov[0].data.length = len;
     674     1607545 :     iov[0].flags = KRB5_CRYPTO_TYPE_DATA;
     675             : 
     676     1607545 :     return verify_checksum_iov(context, crypto, usage, iov, 1, flags, cksum);
     677             : }
     678             : 
     679             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
     680      488757 : krb5_verify_checksum(krb5_context context,
     681             :                      krb5_crypto crypto,
     682             :                      krb5_key_usage usage,
     683             :                      void *data,
     684             :                      size_t len,
     685             :                      Checksum *cksum)
     686             : {
     687        8429 :     struct _krb5_checksum_type *ct;
     688        8429 :     unsigned keyusage;
     689             : 
     690      488757 :     ct = _krb5_find_checksum(cksum->cksumtype);
     691      488757 :     if(ct == NULL) {
     692           2 :         krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
     693           2 :                                 N_("checksum type %d not supported", ""),
     694           2 :                                 cksum->cksumtype);
     695           2 :         return KRB5_PROG_SUMTYPE_NOSUPP;
     696             :     }
     697             : 
     698      488755 :     if (arcfour_checksum_p(ct, crypto)) {
     699        1553 :         keyusage = usage;
     700        1553 :         _krb5_usage2arcfour(context, &keyusage);
     701             :     } else
     702      487202 :         keyusage = CHECKSUM_USAGE(usage);
     703             : 
     704      497184 :     return verify_checksum(context, crypto, keyusage,
     705             :                            data, len, crypto_flags(crypto), cksum);
     706             : }
     707             : 
     708             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
     709     1089695 : krb5_crypto_get_checksum_type(krb5_context context,
     710             :                               krb5_crypto crypto,
     711             :                               krb5_cksumtype *type)
     712             : {
     713     1089695 :     struct _krb5_checksum_type *ct = NULL;
     714             : 
     715     1089695 :     if (crypto != NULL) {
     716     1089695 :         ct = crypto->et->keyed_checksum;
     717     1089695 :         if (ct == NULL)
     718           0 :             ct = crypto->et->checksum;
     719             :     }
     720             : 
     721     1089695 :     if (ct == NULL) {
     722           0 :         krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
     723           0 :                                 N_("checksum type not found", ""));
     724           0 :         return KRB5_PROG_SUMTYPE_NOSUPP;
     725             :     }
     726             : 
     727     1089695 :     *type = ct->type;
     728             : 
     729     1089695 :     return 0;
     730             : }
     731             : 
     732             : 
     733             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
     734      957240 : krb5_checksumsize(krb5_context context,
     735             :                   krb5_cksumtype type,
     736             :                   size_t *size)
     737             : {
     738      957240 :     struct _krb5_checksum_type *ct = _krb5_find_checksum(type);
     739      957240 :     if(ct == NULL) {
     740          15 :         krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
     741          15 :                                 N_("checksum type %d not supported", ""),
     742             :                                 type);
     743          15 :         return KRB5_PROG_SUMTYPE_NOSUPP;
     744             :     }
     745      957225 :     *size = ct->checksumsize;
     746      957225 :     return 0;
     747             : }
     748             : 
     749             : KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL
     750      264359 : krb5_checksum_is_keyed(krb5_context context,
     751             :                        krb5_cksumtype type)
     752             : {
     753      264359 :     struct _krb5_checksum_type *ct = _krb5_find_checksum(type);
     754      264359 :     if(ct == NULL) {
     755           2 :         if (context)
     756           2 :             krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
     757           2 :                                     N_("checksum type %d not supported", ""),
     758             :                                     type);
     759           2 :         return KRB5_PROG_SUMTYPE_NOSUPP;
     760             :     }
     761      264357 :     return ct->flags & F_KEYED;
     762             : }
     763             : 
     764             : KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL
     765       51162 : krb5_checksum_is_collision_proof(krb5_context context,
     766             :                                  krb5_cksumtype type)
     767             : {
     768       51162 :     struct _krb5_checksum_type *ct = _krb5_find_checksum(type);
     769       51162 :     if(ct == NULL) {
     770           0 :         if (context)
     771           0 :             krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
     772           0 :                                     N_("checksum type %d not supported", ""),
     773             :                                     type);
     774           0 :         return KRB5_PROG_SUMTYPE_NOSUPP;
     775             :     }
     776       51162 :     return ct->flags & F_CPROOF;
     777             : }
     778             : 
     779             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
     780           0 : krb5_checksum_disable(krb5_context context,
     781             :                       krb5_cksumtype type)
     782             : {
     783           0 :     struct _krb5_checksum_type *ct = _krb5_find_checksum(type);
     784           0 :     if(ct == NULL) {
     785           0 :         if (context)
     786           0 :             krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
     787           0 :                                     N_("checksum type %d not supported", ""),
     788             :                                     type);
     789           0 :         return KRB5_PROG_SUMTYPE_NOSUPP;
     790             :     }
     791           0 :     ct->flags |= F_DISABLED;
     792           0 :     return 0;
     793             : }
     794             : 
     795             : /************************************************************
     796             :  *                                                          *
     797             :  ************************************************************/
     798             : 
     799             : KRB5_LIB_FUNCTION struct _krb5_encryption_type * KRB5_LIB_CALL
     800    12718278 : _krb5_find_enctype(krb5_enctype type)
     801             : {
     802      397559 :     int i;
     803    46987276 :     for(i = 0; i < _krb5_num_etypes; i++)
     804    46539522 :         if(_krb5_etypes[i]->type == type)
     805    12270524 :             return _krb5_etypes[i];
     806      434102 :     return NULL;
     807             : }
     808             : 
     809             : 
     810             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
     811      881097 : krb5_enctype_to_string(krb5_context context,
     812             :                        krb5_enctype etype,
     813             :                        char **string)
     814             : {
     815       31790 :     struct _krb5_encryption_type *e;
     816      881097 :     e = _krb5_find_enctype(etype);
     817      881097 :     if(e == NULL) {
     818      223834 :         krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
     819      223834 :                                 N_("encryption type %d not supported", ""),
     820             :                                 etype);
     821      223834 :         *string = NULL;
     822      223834 :         return KRB5_PROG_ETYPE_NOSUPP;
     823             :     }
     824      657263 :     *string = strdup(e->name);
     825      657263 :     if (*string == NULL)
     826           0 :         return krb5_enomem(context);
     827      632299 :     return 0;
     828             : }
     829             : 
     830             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
     831      415811 : krb5_string_to_enctype(krb5_context context,
     832             :                        const char *string,
     833             :                        krb5_enctype *etype)
     834             : {
     835           0 :     int i;
     836     3994878 :     for(i = 0; i < _krb5_num_etypes; i++) {
     837     3720954 :         if(strcasecmp(_krb5_etypes[i]->name, string) == 0){
     838      141887 :             *etype = _krb5_etypes[i]->type;
     839      141887 :             return 0;
     840             :         }
     841     3579067 :         if(_krb5_etypes[i]->alias != NULL &&
     842     1932241 :            strcasecmp(_krb5_etypes[i]->alias, string) == 0){
     843           0 :             *etype = _krb5_etypes[i]->type;
     844           0 :             return 0;
     845             :         }
     846             :     }
     847      273924 :     krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
     848      273924 :                             N_("encryption type %s not supported", ""),
     849             :                             string);
     850      273924 :     return KRB5_PROG_ETYPE_NOSUPP;
     851             : }
     852             : 
     853             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
     854       30260 : krb5_enctype_to_keytype(krb5_context context,
     855             :                         krb5_enctype etype,
     856             :                         krb5_keytype *keytype)
     857             : {
     858       30260 :     struct _krb5_encryption_type *e = _krb5_find_enctype(etype);
     859       30260 :     if(e == NULL) {
     860           0 :         return unsupported_enctype (context, etype);
     861             :     }
     862       30260 :     *keytype = (krb5_keytype)e->keytype->type;
     863       30260 :     return 0;
     864             : }
     865             : 
     866             : /**
     867             :  * Check if a enctype is valid, return 0 if it is.
     868             :  *
     869             :  * @param context Kerberos context
     870             :  * @param etype enctype to check if its valid or not
     871             :  *
     872             :  * @return Return an error code for an failure or 0 on success (enctype valid).
     873             :  * @ingroup krb5_crypto
     874             :  */
     875             : 
     876             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
     877     1599683 : krb5_enctype_valid(krb5_context context,
     878             :                    krb5_enctype etype)
     879             : {
     880     1599683 :     struct _krb5_encryption_type *e = _krb5_find_enctype(etype);
     881     1599683 :     if(e && (e->flags & F_DISABLED) == 0)
     882     1336519 :         return 0;
     883      223808 :     if (context == NULL)
     884           0 :         return KRB5_PROG_ETYPE_NOSUPP;
     885      223808 :     if(e == NULL) {
     886      223808 :         return unsupported_enctype (context, etype);
     887             :     }
     888             :     /* Must be (e->flags & F_DISABLED) */
     889           0 :     krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
     890           0 :                             N_("encryption type %s is disabled", ""),
     891             :                             e->name);
     892           0 :     return KRB5_PROG_ETYPE_NOSUPP;
     893             : }
     894             : 
     895             : /**
     896             :  * Return the coresponding encryption type for a checksum type.
     897             :  *
     898             :  * @param context Kerberos context
     899             :  * @param ctype The checksum type to get the result enctype for
     900             :  * @param etype The returned encryption, when the matching etype is
     901             :  * not found, etype is set to ETYPE_NULL.
     902             :  *
     903             :  * @return Return an error code for an failure or 0 on success.
     904             :  * @ingroup krb5_crypto
     905             :  */
     906             : 
     907             : 
     908             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
     909         221 : krb5_cksumtype_to_enctype(krb5_context context,
     910             :                           krb5_cksumtype ctype,
     911             :                           krb5_enctype *etype)
     912             : {
     913           0 :     int i;
     914             : 
     915         221 :     *etype = ETYPE_NULL;
     916             : 
     917         951 :     for(i = 0; i < _krb5_num_etypes; i++) {
     918         915 :         if(_krb5_etypes[i]->keyed_checksum &&
     919         843 :            _krb5_etypes[i]->keyed_checksum->type == ctype)
     920             :             {
     921         185 :                 *etype = _krb5_etypes[i]->type;
     922         185 :                 return 0;
     923             :             }
     924             :     }
     925             : 
     926          36 :     krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
     927          36 :                             N_("checksum type %d not supported", ""),
     928             :                             (int)ctype);
     929          36 :     return KRB5_PROG_SUMTYPE_NOSUPP;
     930             : }
     931             : 
     932             : 
     933             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
     934           0 : krb5_cksumtype_valid(krb5_context context,
     935             :                      krb5_cksumtype ctype)
     936             : {
     937           0 :     struct _krb5_checksum_type *c = _krb5_find_checksum(ctype);
     938           0 :     if (c == NULL) {
     939           0 :         krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
     940           0 :                                 N_("checksum type %d not supported", ""),
     941             :                                 ctype);
     942           0 :         return KRB5_PROG_SUMTYPE_NOSUPP;
     943             :     }
     944           0 :     if (c->flags & F_DISABLED) {
     945           0 :         krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
     946           0 :                                 N_("checksum type %s is disabled", ""),
     947             :                                 c->name);
     948           0 :         return KRB5_PROG_SUMTYPE_NOSUPP;
     949             :     }
     950           0 :     return 0;
     951             : }
     952             : 
     953             : static krb5_boolean
     954     7279890 : derived_crypto(krb5_context context,
     955             :                krb5_crypto crypto)
     956             : {
     957     7279890 :     return (crypto->et->flags & F_DERIVED) != 0;
     958             : }
     959             : 
     960             : #define CHECKSUMSIZE(C) ((C)->checksumsize)
     961             : #define CHECKSUMTYPE(C) ((C)->type)
     962             : 
     963             : static krb5_error_code
     964     1069009 : encrypt_internal_derived(krb5_context context,
     965             :                          krb5_crypto crypto,
     966             :                          unsigned usage,
     967             :                          const void *data,
     968             :                          size_t len,
     969             :                          krb5_data *result,
     970             :                          void *ivec)
     971             : {
     972       14139 :     size_t sz, block_sz, checksum_sz, total_sz;
     973       14139 :     Checksum cksum;
     974       14139 :     unsigned char *p, *q;
     975       14139 :     krb5_error_code ret;
     976       14139 :     struct _krb5_key_data *dkey;
     977     1069009 :     const struct _krb5_encryption_type *et = crypto->et;
     978             : 
     979     1069009 :     checksum_sz = CHECKSUMSIZE(et->keyed_checksum);
     980             : 
     981     1069009 :     sz = et->confoundersize + len;
     982     1069009 :     block_sz = (sz + et->padsize - 1) &~ (et->padsize - 1); /* pad */
     983     1069009 :     total_sz = block_sz + checksum_sz;
     984     1069009 :     p = calloc(1, total_sz);
     985     1069009 :     if (p == NULL)
     986           0 :         return krb5_enomem(context);
     987             : 
     988     1069009 :     q = p;
     989     1069009 :     krb5_generate_random_block(q, et->confoundersize); /* XXX */
     990     1069009 :     q += et->confoundersize;
     991     1069009 :     memcpy(q, data, len);
     992             : 
     993     1083148 :     ret = create_checksum(context,
     994     1069009 :                           et->keyed_checksum,
     995             :                           crypto,
     996     1069009 :                           INTEGRITY_USAGE(usage),
     997             :                           p,
     998             :                           block_sz,
     999             :                           0,
    1000             :                           &cksum);
    1001     1069009 :     if(ret == 0 && cksum.checksum.length != checksum_sz) {
    1002           0 :         free_Checksum (&cksum);
    1003           0 :         krb5_clear_error_message (context);
    1004           0 :         ret = KRB5_CRYPTO_INTERNAL;
    1005             :     }
    1006     1069009 :     if(ret)
    1007           0 :         goto fail;
    1008     1069009 :     memcpy(p + block_sz, cksum.checksum.data, cksum.checksum.length);
    1009     1069009 :     free_Checksum (&cksum);
    1010     1069009 :     ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey);
    1011     1069009 :     if(ret)
    1012           0 :         goto fail;
    1013     1069009 :     ret = _key_schedule(context, dkey);
    1014     1069009 :     if(ret)
    1015           0 :         goto fail;
    1016     1069009 :     ret = (*et->encrypt)(context, dkey, p, block_sz, 1, usage, ivec);
    1017     1069009 :     if (ret)
    1018           0 :         goto fail;
    1019     1069009 :     result->data = p;
    1020     1069009 :     result->length = total_sz;
    1021     1069009 :     return 0;
    1022           0 :  fail:
    1023           0 :     memset(p, 0, total_sz);
    1024           0 :     free(p);
    1025           0 :     return ret;
    1026             : }
    1027             : 
    1028             : static krb5_error_code
    1029           0 : encrypt_internal_enc_then_cksum(krb5_context context,
    1030             :                                 krb5_crypto crypto,
    1031             :                                 unsigned usage,
    1032             :                                 const void *data,
    1033             :                                 size_t len,
    1034             :                                 krb5_data *result,
    1035             :                                 void *ivec)
    1036             : {
    1037           0 :     size_t sz, block_sz, checksum_sz, total_sz;
    1038           0 :     Checksum cksum;
    1039           0 :     unsigned char *p, *q, *ivc = NULL;
    1040           0 :     krb5_error_code ret;
    1041           0 :     struct _krb5_key_data *dkey;
    1042           0 :     const struct _krb5_encryption_type *et = crypto->et;
    1043             : 
    1044           0 :     checksum_sz = CHECKSUMSIZE(et->keyed_checksum);
    1045             : 
    1046           0 :     sz = et->confoundersize + len;
    1047           0 :     block_sz = (sz + et->padsize - 1) &~ (et->padsize - 1); /* pad */
    1048           0 :     total_sz = block_sz + checksum_sz;
    1049           0 :     p = calloc(1, total_sz);
    1050           0 :     if (p == NULL)
    1051           0 :         return krb5_enomem(context);
    1052             : 
    1053           0 :     q = p;
    1054           0 :     krb5_generate_random_block(q, et->confoundersize); /* XXX */
    1055           0 :     q += et->confoundersize;
    1056           0 :     memcpy(q, data, len);
    1057             : 
    1058           0 :     ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey);
    1059           0 :     if(ret)
    1060           0 :         goto fail;
    1061           0 :     ret = _key_schedule(context, dkey);
    1062           0 :     if(ret)
    1063           0 :         goto fail;
    1064             : 
    1065             :     /* XXX EVP style update API would avoid needing to allocate here */
    1066           0 :     ivc = malloc(et->blocksize + block_sz);
    1067           0 :     if (ivc == NULL) {
    1068           0 :         ret = krb5_enomem(context);
    1069           0 :         goto fail;
    1070             :     }
    1071           0 :     if (ivec)
    1072           0 :         memcpy(ivc, ivec, et->blocksize);
    1073             :     else
    1074           0 :         memset(ivc, 0, et->blocksize);
    1075             : 
    1076           0 :     ret = (*et->encrypt)(context, dkey, p, block_sz, 1, usage, ivec);
    1077           0 :     if (ret)
    1078           0 :         goto fail;
    1079           0 :     memcpy(&ivc[et->blocksize], p, block_sz);
    1080             : 
    1081           0 :     ret = create_checksum(context,
    1082           0 :                           et->keyed_checksum,
    1083             :                           crypto,
    1084           0 :                           INTEGRITY_USAGE(usage),
    1085             :                           ivc,
    1086           0 :                           et->blocksize + block_sz,
    1087             :                           0,
    1088             :                           &cksum);
    1089           0 :     if(ret == 0 && cksum.checksum.length != checksum_sz) {
    1090           0 :         free_Checksum (&cksum);
    1091           0 :         krb5_clear_error_message (context);
    1092           0 :         ret = KRB5_CRYPTO_INTERNAL;
    1093             :     }
    1094           0 :     if(ret)
    1095           0 :         goto fail;
    1096           0 :     memcpy(p + block_sz, cksum.checksum.data, cksum.checksum.length);
    1097           0 :     free_Checksum (&cksum);
    1098           0 :     result->data = p;
    1099           0 :     result->length = total_sz;
    1100           0 :     free(ivc);
    1101           0 :     return 0;
    1102           0 :  fail:
    1103           0 :     memset_s(p, total_sz, 0, total_sz);
    1104           0 :     free(p);
    1105           0 :     free(ivc);
    1106           0 :     return ret;
    1107             : }
    1108             : 
    1109             : static krb5_error_code
    1110           0 : encrypt_internal(krb5_context context,
    1111             :                  krb5_crypto crypto,
    1112             :                  const void *data,
    1113             :                  size_t len,
    1114             :                  krb5_data *result,
    1115             :                  void *ivec)
    1116             : {
    1117           0 :     size_t sz, block_sz, checksum_sz;
    1118           0 :     Checksum cksum;
    1119           0 :     unsigned char *p, *q;
    1120           0 :     krb5_error_code ret;
    1121           0 :     const struct _krb5_encryption_type *et = crypto->et;
    1122             : 
    1123           0 :     checksum_sz = CHECKSUMSIZE(et->checksum);
    1124             : 
    1125           0 :     sz = et->confoundersize + checksum_sz + len;
    1126           0 :     block_sz = (sz + et->padsize - 1) &~ (et->padsize - 1); /* pad */
    1127           0 :     p = calloc(1, block_sz);
    1128           0 :     if (p == NULL)
    1129           0 :         return krb5_enomem(context);
    1130             : 
    1131           0 :     q = p;
    1132           0 :     krb5_generate_random_block(q, et->confoundersize); /* XXX */
    1133           0 :     q += et->confoundersize;
    1134           0 :     memset(q, 0, checksum_sz);
    1135           0 :     q += checksum_sz;
    1136           0 :     memcpy(q, data, len);
    1137             : 
    1138           0 :     ret = create_checksum(context,
    1139           0 :                           et->checksum,
    1140             :                           crypto,
    1141             :                           0,
    1142             :                           p,
    1143             :                           block_sz,
    1144             :                           KRB5_CRYPTO_FLAG_ALLOW_UNKEYED_CHECKSUM,
    1145             :                           &cksum);
    1146           0 :     if(ret == 0 && cksum.checksum.length != checksum_sz) {
    1147           0 :         krb5_clear_error_message (context);
    1148           0 :         free_Checksum(&cksum);
    1149           0 :         ret = KRB5_CRYPTO_INTERNAL;
    1150             :     }
    1151           0 :     if(ret)
    1152           0 :         goto fail;
    1153           0 :     memcpy(p + et->confoundersize, cksum.checksum.data, cksum.checksum.length);
    1154           0 :     free_Checksum(&cksum);
    1155           0 :     ret = _key_schedule(context, &crypto->key);
    1156           0 :     if(ret)
    1157           0 :         goto fail;
    1158           0 :     ret = (*et->encrypt)(context, &crypto->key, p, block_sz, 1, 0, ivec);
    1159           0 :     if (ret) {
    1160           0 :         memset(p, 0, block_sz);
    1161           0 :         free(p);
    1162           0 :         return ret;
    1163             :     }
    1164           0 :     result->data = p;
    1165           0 :     result->length = block_sz;
    1166           0 :     return 0;
    1167           0 :  fail:
    1168           0 :     memset(p, 0, block_sz);
    1169           0 :     free(p);
    1170           0 :     return ret;
    1171             : }
    1172             : 
    1173             : static krb5_error_code
    1174       26903 : encrypt_internal_special(krb5_context context,
    1175             :                          krb5_crypto crypto,
    1176             :                          int usage,
    1177             :                          const void *data,
    1178             :                          size_t len,
    1179             :                          krb5_data *result,
    1180             :                          void *ivec)
    1181             : {
    1182       26903 :     struct _krb5_encryption_type *et = crypto->et;
    1183       26903 :     size_t cksum_sz = CHECKSUMSIZE(et->checksum);
    1184       26903 :     size_t sz = len + cksum_sz + et->confoundersize;
    1185          18 :     char *tmp, *p;
    1186          18 :     krb5_error_code ret;
    1187             : 
    1188       26903 :     tmp = malloc (sz);
    1189       26903 :     if (tmp == NULL)
    1190           0 :         return krb5_enomem(context);
    1191       26903 :     p = tmp;
    1192       26903 :     memset (p, 0, cksum_sz);
    1193       26903 :     p += cksum_sz;
    1194       26903 :     krb5_generate_random_block(p, et->confoundersize);
    1195       26903 :     p += et->confoundersize;
    1196       26903 :     memcpy (p, data, len);
    1197       26903 :     ret = (*et->encrypt)(context, &crypto->key, tmp, sz, TRUE, usage, ivec);
    1198       26903 :     if (ret) {
    1199           0 :         memset(tmp, 0, sz);
    1200           0 :         free(tmp);
    1201           0 :         return ret;
    1202             :     }
    1203       26903 :     result->data   = tmp;
    1204       26903 :     result->length = sz;
    1205       26903 :     return 0;
    1206             : }
    1207             : 
    1208             : static krb5_error_code
    1209     1118790 : decrypt_internal_derived(krb5_context context,
    1210             :                          krb5_crypto crypto,
    1211             :                          unsigned usage,
    1212             :                          void *data,
    1213             :                          size_t len,
    1214             :                          krb5_data *result,
    1215             :                          void *ivec)
    1216             : {
    1217       13699 :     size_t checksum_sz;
    1218       13699 :     Checksum cksum;
    1219       13699 :     unsigned char *p;
    1220       13699 :     krb5_error_code ret;
    1221       13699 :     struct _krb5_key_data *dkey;
    1222     1118790 :     struct _krb5_encryption_type *et = crypto->et;
    1223       13699 :     unsigned long l;
    1224             : 
    1225     1118790 :     checksum_sz = CHECKSUMSIZE(et->keyed_checksum);
    1226     1118790 :     if (len < checksum_sz + et->confoundersize) {
    1227           0 :         krb5_set_error_message(context, KRB5_BAD_MSIZE,
    1228           0 :                                N_("Encrypted data shorter then "
    1229             :                                   "checksum + confounder", ""));
    1230           0 :         return KRB5_BAD_MSIZE;
    1231             :     }
    1232             : 
    1233     1118790 :     if (((len - checksum_sz) % et->padsize) != 0) {
    1234           0 :         krb5_clear_error_message(context);
    1235           0 :         return KRB5_BAD_MSIZE;
    1236             :     }
    1237             : 
    1238     1118790 :     p = malloc(len);
    1239     1118790 :     if (len != 0 && p == NULL)
    1240           0 :         return krb5_enomem(context);
    1241     1118790 :     memcpy(p, data, len);
    1242             : 
    1243     1118790 :     len -= checksum_sz;
    1244             : 
    1245     1118790 :     ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey);
    1246     1118790 :     if(ret) {
    1247           0 :         free(p);
    1248           0 :         return ret;
    1249             :     }
    1250     1118790 :     ret = _key_schedule(context, dkey);
    1251     1118790 :     if(ret) {
    1252           0 :         free(p);
    1253           0 :         return ret;
    1254             :     }
    1255     1118790 :     ret = (*et->encrypt)(context, dkey, p, len, 0, usage, ivec);
    1256     1118790 :     if (ret) {
    1257           0 :         free(p);
    1258           0 :         return ret;
    1259             :     }
    1260             : 
    1261     1118790 :     cksum.checksum.data   = p + len;
    1262     1118790 :     cksum.checksum.length = checksum_sz;
    1263     1118790 :     cksum.cksumtype       = CHECKSUMTYPE(et->keyed_checksum);
    1264             : 
    1265     1118790 :     ret = verify_checksum(context,
    1266             :                           crypto,
    1267     1105091 :                           INTEGRITY_USAGE(usage),
    1268             :                           p,
    1269             :                           len,
    1270             :                           0,
    1271             :                           &cksum);
    1272     1118790 :     if(ret) {
    1273         419 :         free(p);
    1274         419 :         return ret;
    1275             :     }
    1276     1118371 :     l = len - et->confoundersize;
    1277     1118371 :     memmove(p, p + et->confoundersize, l);
    1278     1118371 :     result->data = p;
    1279     1118371 :     result->length = l;
    1280     1118371 :     return 0;
    1281             : }
    1282             : 
    1283             : static krb5_error_code
    1284           0 : decrypt_internal_enc_then_cksum(krb5_context context,
    1285             :                                 krb5_crypto crypto,
    1286             :                                 unsigned usage,
    1287             :                                 void *data,
    1288             :                                 size_t len,
    1289             :                                 krb5_data *result,
    1290             :                                 void *ivec)
    1291             : {
    1292           0 :     size_t checksum_sz;
    1293           0 :     Checksum cksum;
    1294           0 :     unsigned char *p;
    1295           0 :     krb5_error_code ret;
    1296           0 :     struct _krb5_key_data *dkey;
    1297           0 :     struct _krb5_encryption_type *et = crypto->et;
    1298           0 :     unsigned long l;
    1299             : 
    1300           0 :     checksum_sz = CHECKSUMSIZE(et->keyed_checksum);
    1301           0 :     if (len < checksum_sz + et->confoundersize) {
    1302           0 :         krb5_set_error_message(context, KRB5_BAD_MSIZE,
    1303           0 :                                N_("Encrypted data shorter then "
    1304             :                                   "checksum + confounder", ""));
    1305           0 :         return KRB5_BAD_MSIZE;
    1306             :     }
    1307             : 
    1308           0 :     if (((len - checksum_sz) % et->padsize) != 0) {
    1309           0 :         krb5_clear_error_message(context);
    1310           0 :         return KRB5_BAD_MSIZE;
    1311             :     }
    1312             : 
    1313           0 :     len -= checksum_sz;
    1314             : 
    1315           0 :     p = malloc(et->blocksize + len);
    1316           0 :     if (p == NULL)
    1317           0 :         return krb5_enomem(context);
    1318             : 
    1319           0 :     if (ivec)
    1320           0 :         memcpy(p, ivec, et->blocksize);
    1321             :     else
    1322           0 :         memset(p, 0, et->blocksize);
    1323           0 :     memcpy(&p[et->blocksize], data, len);
    1324             : 
    1325           0 :     cksum.checksum.data   = (unsigned char *)data + len;
    1326           0 :     cksum.checksum.length = checksum_sz;
    1327           0 :     cksum.cksumtype       = CHECKSUMTYPE(et->keyed_checksum);
    1328             : 
    1329           0 :     ret = verify_checksum(context,
    1330             :                           crypto,
    1331           0 :                           INTEGRITY_USAGE(usage),
    1332             :                           p,
    1333           0 :                           et->blocksize + len,
    1334             :                           0,
    1335             :                           &cksum);
    1336           0 :     if(ret) {
    1337           0 :         free(p);
    1338           0 :         return ret;
    1339             :     }
    1340             : 
    1341           0 :     ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey);
    1342           0 :     if(ret) {
    1343           0 :         free(p);
    1344           0 :         return ret;
    1345             :     }
    1346           0 :     ret = _key_schedule(context, dkey);
    1347           0 :     if(ret) {
    1348           0 :         free(p);
    1349           0 :         return ret;
    1350             :     }
    1351           0 :     ret = (*et->encrypt)(context, dkey, &p[et->blocksize], len, 0, usage, ivec);
    1352           0 :     if (ret) {
    1353           0 :         free(p);
    1354           0 :         return ret;
    1355             :     }
    1356             : 
    1357           0 :     l = len - et->confoundersize;
    1358           0 :     memmove(p, p + et->blocksize + et->confoundersize, l);
    1359           0 :     result->data = p;
    1360           0 :     result->length = l;
    1361           0 :     return 0;
    1362             : }
    1363             : 
    1364             : static krb5_error_code
    1365           0 : decrypt_internal(krb5_context context,
    1366             :                  krb5_crypto crypto,
    1367             :                  void *data,
    1368             :                  size_t len,
    1369             :                  krb5_data *result,
    1370             :                  void *ivec)
    1371             : {
    1372           0 :     krb5_error_code ret;
    1373           0 :     unsigned char *p;
    1374           0 :     Checksum cksum;
    1375           0 :     size_t checksum_sz, l;
    1376           0 :     struct _krb5_encryption_type *et = crypto->et;
    1377             : 
    1378           0 :     if ((len % et->padsize) != 0) {
    1379           0 :         krb5_clear_error_message(context);
    1380           0 :         return KRB5_BAD_MSIZE;
    1381             :     }
    1382           0 :     checksum_sz = CHECKSUMSIZE(et->checksum);
    1383           0 :     if (len < checksum_sz + et->confoundersize) {
    1384           0 :         krb5_set_error_message(context, KRB5_BAD_MSIZE,
    1385           0 :                                N_("Encrypted data shorter then "
    1386             :                                   "checksum + confounder", ""));
    1387           0 :         return KRB5_BAD_MSIZE;
    1388             :     }
    1389             : 
    1390           0 :     p = malloc(len);
    1391           0 :     if (len != 0 && p == NULL)
    1392           0 :         return krb5_enomem(context);
    1393           0 :     memcpy(p, data, len);
    1394             : 
    1395           0 :     ret = _key_schedule(context, &crypto->key);
    1396           0 :     if(ret) {
    1397           0 :         free(p);
    1398           0 :         return ret;
    1399             :     }
    1400           0 :     ret = (*et->encrypt)(context, &crypto->key, p, len, 0, 0, ivec);
    1401           0 :     if (ret) {
    1402           0 :         free(p);
    1403           0 :         return ret;
    1404             :     }
    1405           0 :     ret = krb5_data_copy(&cksum.checksum, p + et->confoundersize, checksum_sz);
    1406           0 :     if(ret) {
    1407           0 :         free(p);
    1408           0 :         return ret;
    1409             :     }
    1410           0 :     memset(p + et->confoundersize, 0, checksum_sz);
    1411           0 :     cksum.cksumtype = CHECKSUMTYPE(et->checksum);
    1412           0 :     ret = verify_checksum(context, NULL, 0, p, len,
    1413             :                           KRB5_CRYPTO_FLAG_ALLOW_UNKEYED_CHECKSUM, &cksum);
    1414           0 :     free_Checksum(&cksum);
    1415           0 :     if(ret) {
    1416           0 :         free(p);
    1417           0 :         return ret;
    1418             :     }
    1419           0 :     l = len - et->confoundersize - checksum_sz;
    1420           0 :     memmove(p, p + et->confoundersize + checksum_sz, l);
    1421           0 :     result->data = p;
    1422           0 :     result->length = l;
    1423           0 :     return 0;
    1424             : }
    1425             : 
    1426             : static krb5_error_code
    1427       21212 : decrypt_internal_special(krb5_context context,
    1428             :                          krb5_crypto crypto,
    1429             :                          int usage,
    1430             :                          void *data,
    1431             :                          size_t len,
    1432             :                          krb5_data *result,
    1433             :                          void *ivec)
    1434             : {
    1435       21212 :     struct _krb5_encryption_type *et = crypto->et;
    1436       21212 :     size_t cksum_sz = CHECKSUMSIZE(et->checksum);
    1437       21212 :     size_t sz = len - cksum_sz - et->confoundersize;
    1438          18 :     unsigned char *p;
    1439          18 :     krb5_error_code ret;
    1440             : 
    1441       21212 :     if ((len % et->padsize) != 0) {
    1442           0 :         krb5_clear_error_message(context);
    1443           0 :         return KRB5_BAD_MSIZE;
    1444             :     }
    1445       21212 :     if (len < cksum_sz + et->confoundersize) {
    1446           0 :         krb5_set_error_message(context, KRB5_BAD_MSIZE,
    1447           0 :                                N_("Encrypted data shorter then "
    1448             :                                   "checksum + confounder", ""));
    1449           0 :         return KRB5_BAD_MSIZE;
    1450             :     }
    1451             : 
    1452       21212 :     p = malloc (len);
    1453       21212 :     if (p == NULL)
    1454           0 :         return krb5_enomem(context);
    1455       21212 :     memcpy(p, data, len);
    1456             : 
    1457       21212 :     ret = (*et->encrypt)(context, &crypto->key, p, len, FALSE, usage, ivec);
    1458       21212 :     if (ret) {
    1459          17 :         free(p);
    1460          17 :         return ret;
    1461             :     }
    1462             : 
    1463       21195 :     memmove (p, p + cksum_sz + et->confoundersize, sz);
    1464       21195 :     result->data = p;
    1465       21195 :     result->length = sz;
    1466       21195 :     return 0;
    1467             : }
    1468             : 
    1469             : static krb5_crypto_iov *
    1470     4275417 : iov_find(krb5_crypto_iov *data, size_t num_data, unsigned type)
    1471             : {
    1472        2625 :     size_t i;
    1473    21681080 :     for (i = 0; i < num_data; i++)
    1474    20538852 :         if (data[i].flags == type)
    1475     3130564 :             return &data[i];
    1476     1140915 :     return NULL;
    1477             : }
    1478             : 
    1479             : static size_t
    1480     1567907 : iov_enc_data_len(krb5_crypto_iov *data, int num_data)
    1481             : {
    1482        2625 :     size_t i, len;
    1483             : 
    1484    12543256 :     for (len = 0, i = 0; i < num_data; i++) {
    1485    10975349 :         if (data[i].flags != KRB5_CRYPTO_TYPE_DATA)
    1486     7839535 :             continue;
    1487     3135814 :         len += data[i].data.length;
    1488             :     }
    1489             : 
    1490     1567907 :     return len;
    1491             : }
    1492             : 
    1493             : static size_t
    1494           0 : iov_sign_data_len(krb5_crypto_iov *data, int num_data)
    1495             : {
    1496             :     size_t i, len;
    1497             : 
    1498           0 :     for (len = 0, i = 0; i < num_data; i++) {
    1499             :         /* Can't use should_sign, because we must only count data, not
    1500             :          * header/trailer */
    1501           0 :         if (data[i].flags == KRB5_CRYPTO_TYPE_DATA ||
    1502           0 :             data[i].flags == KRB5_CRYPTO_TYPE_SIGN_ONLY)
    1503           0 :             len += data[i].data.length;
    1504             :     }
    1505             : 
    1506           0 :     return len;
    1507             : }
    1508             : 
    1509             : static krb5_error_code
    1510           0 : iov_coalesce(krb5_context context,
    1511             :              krb5_data *prefix,
    1512             :              krb5_crypto_iov *data,
    1513             :              int num_data,
    1514             :              krb5_boolean inc_sign_data,
    1515             :              krb5_data *out)
    1516             : {
    1517           0 :     unsigned char *p, *q;
    1518           0 :     krb5_crypto_iov *hiv, *piv;
    1519           0 :     size_t len;
    1520           0 :     unsigned int i;
    1521             : 
    1522           0 :     hiv = iov_find(data, num_data, KRB5_CRYPTO_TYPE_HEADER);
    1523             : 
    1524           0 :     piv = iov_find(data, num_data, KRB5_CRYPTO_TYPE_PADDING);
    1525             : 
    1526           0 :     len = 0;
    1527           0 :     if (prefix)
    1528           0 :         len += prefix->length;
    1529           0 :     len += hiv->data.length;
    1530           0 :     if (inc_sign_data)
    1531           0 :         len += iov_sign_data_len(data, num_data);
    1532             :     else
    1533           0 :         len += iov_enc_data_len(data, num_data);
    1534           0 :     if (piv)
    1535           0 :         len += piv->data.length;
    1536             : 
    1537           0 :     p = q = malloc(len);
    1538           0 :     if (p == NULL)
    1539           0 :         return krb5_enomem(context);
    1540             : 
    1541           0 :     if (prefix) {
    1542           0 :         memcpy(q, prefix->data, prefix->length);
    1543           0 :         q += prefix->length;
    1544             :     }
    1545           0 :     memcpy(q, hiv->data.data, hiv->data.length);
    1546           0 :     q += hiv->data.length;
    1547           0 :     for (i = 0; i < num_data; i++) {
    1548           0 :         if (data[i].flags == KRB5_CRYPTO_TYPE_DATA ||
    1549           0 :             (inc_sign_data && data[i].flags == KRB5_CRYPTO_TYPE_SIGN_ONLY)) {
    1550           0 :             memcpy(q, data[i].data.data, data[i].data.length);
    1551           0 :             q += data[i].data.length;
    1552             :         }
    1553             :     }
    1554           0 :     if (piv)
    1555           0 :         memset(q, 0, piv->data.length);
    1556             : 
    1557           0 :     out->length = len;
    1558           0 :     out->data = p;
    1559             : 
    1560           0 :     return 0;
    1561             : }
    1562             : 
    1563             : static krb5_error_code
    1564           0 : iov_uncoalesce(krb5_context context,
    1565             :                krb5_data *enc_data,
    1566             :                krb5_crypto_iov *data,
    1567             :                int num_data)
    1568             : {
    1569           0 :     unsigned char *q = enc_data->data;
    1570           0 :     krb5_crypto_iov *hiv, *piv;
    1571           0 :     unsigned int i;
    1572             : 
    1573           0 :     hiv = iov_find(data, num_data, KRB5_CRYPTO_TYPE_HEADER);
    1574             : 
    1575           0 :     piv = iov_find(data, num_data, KRB5_CRYPTO_TYPE_PADDING);
    1576             : 
    1577           0 :     memcpy(hiv->data.data, q, hiv->data.length);
    1578           0 :     q += hiv->data.length;
    1579             : 
    1580           0 :     for (i = 0; i < num_data; i++) {
    1581           0 :         if (data[i].flags != KRB5_CRYPTO_TYPE_DATA)
    1582           0 :             continue;
    1583           0 :         memcpy(data[i].data.data, q, data[i].data.length);
    1584           0 :         q += data[i].data.length;
    1585             :     }
    1586           0 :     if (piv)
    1587           0 :         memcpy(piv->data.data, q, piv->data.length);
    1588             : 
    1589           0 :     return 0;
    1590             : }
    1591             : 
    1592             : static krb5_error_code
    1593     1142228 : iov_pad_validate(const struct _krb5_encryption_type *et,
    1594             :                  krb5_crypto_iov *data,
    1595             :                  int num_data,
    1596             :                  krb5_crypto_iov **ppiv)
    1597             : {
    1598        1313 :     krb5_crypto_iov *piv;
    1599        1313 :     size_t sz, headersz, block_sz, pad_sz, len;
    1600             : 
    1601     1142228 :     len = iov_enc_data_len(data, num_data);
    1602             : 
    1603     1142228 :     headersz = et->confoundersize;
    1604             : 
    1605     1142228 :     sz = headersz + len;
    1606     1142228 :     block_sz = (sz + et->padsize - 1) &~ (et->padsize - 1); /* pad */
    1607             : 
    1608     1142228 :     pad_sz = block_sz - sz;
    1609             : 
    1610     1142228 :     piv = iov_find(data, num_data, KRB5_CRYPTO_TYPE_PADDING);
    1611             :     /* its ok to have no TYPE_PADDING if there is no padding */
    1612     1142228 :     if (piv == NULL && pad_sz != 0)
    1613           0 :         return KRB5_BAD_MSIZE;
    1614     1142228 :     if (piv) {
    1615           0 :         if (piv->data.length < pad_sz)
    1616           0 :             return KRB5_BAD_MSIZE;
    1617           0 :         piv->data.length = pad_sz;
    1618           0 :         if (pad_sz)
    1619           0 :             memset(piv->data.data, 0, pad_sz);
    1620             :         else
    1621           0 :             piv = NULL;
    1622             :     }
    1623             : 
    1624     1142228 :     *ppiv = piv;
    1625     1142228 :     return 0;
    1626             : }
    1627             : 
    1628             : /**
    1629             :  * Inline encrypt a kerberos message
    1630             :  *
    1631             :  * @param context Kerberos context
    1632             :  * @param crypto Kerberos crypto context
    1633             :  * @param usage Key usage for this buffer
    1634             :  * @param data array of buffers to process
    1635             :  * @param num_data length of array
    1636             :  * @param ivec initial cbc/cts vector
    1637             :  *
    1638             :  * @return Return an error code or 0.
    1639             :  * @ingroup krb5_crypto
    1640             :  *
    1641             :  * Kerberos encrypted data look like this:
    1642             :  *
    1643             :  * 1. KRB5_CRYPTO_TYPE_HEADER
    1644             :  * 2. array [1,...] KRB5_CRYPTO_TYPE_DATA and array [0,...]
    1645             :  *    KRB5_CRYPTO_TYPE_SIGN_ONLY in any order, however the receiver
    1646             :  *    have to aware of the order. KRB5_CRYPTO_TYPE_SIGN_ONLY is
    1647             :  *    commonly used headers and trailers.
    1648             :  * 3. KRB5_CRYPTO_TYPE_PADDING, at least on padsize long if padsize > 1
    1649             :  * 4. KRB5_CRYPTO_TYPE_TRAILER
    1650             :  */
    1651             : 
    1652             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
    1653     1142228 : krb5_encrypt_iov_ivec(krb5_context context,
    1654             :                       krb5_crypto crypto,
    1655             :                       unsigned usage,
    1656             :                       krb5_crypto_iov *data,
    1657             :                       int num_data,
    1658             :                       void *ivec)
    1659             : {
    1660        1313 :     size_t headersz, trailersz;
    1661        1313 :     Checksum cksum;
    1662        1313 :     krb5_data enc_data, sign_data;
    1663        1313 :     krb5_error_code ret;
    1664        1313 :     struct _krb5_key_data *dkey;
    1665     1142228 :     const struct _krb5_encryption_type *et = crypto->et;
    1666        1313 :     krb5_crypto_iov *tiv, *piv, *hiv;
    1667             : 
    1668     1142228 :     if (num_data < 0) {
    1669           0 :         krb5_clear_error_message(context);
    1670           0 :         return KRB5_CRYPTO_INTERNAL;
    1671             :     }
    1672             : 
    1673     1142228 :     if(!derived_crypto(context, crypto)) {
    1674           0 :         krb5_clear_error_message(context);
    1675           0 :         return KRB5_CRYPTO_INTERNAL;
    1676             :     }
    1677             : 
    1678     1142228 :     krb5_data_zero(&enc_data);
    1679     1142228 :     krb5_data_zero(&sign_data);
    1680             : 
    1681     1142228 :     headersz = et->confoundersize;
    1682     1142228 :     trailersz = CHECKSUMSIZE(et->keyed_checksum);
    1683             : 
    1684             :     /* header */
    1685     1142228 :     hiv = iov_find(data, num_data, KRB5_CRYPTO_TYPE_HEADER);
    1686     1142228 :     if (hiv == NULL || hiv->data.length != headersz)
    1687           0 :         return KRB5_BAD_MSIZE;
    1688     1142228 :     krb5_generate_random_block(hiv->data.data, hiv->data.length);
    1689             : 
    1690             :     /* padding */
    1691     1142228 :     ret = iov_pad_validate(et, data, num_data, &piv);
    1692     1142228 :     if(ret)
    1693           0 :         goto cleanup;
    1694             : 
    1695             :     /* trailer */
    1696     1142228 :     tiv = iov_find(data, num_data, KRB5_CRYPTO_TYPE_TRAILER);
    1697     1142228 :     if (tiv == NULL || tiv->data.length != trailersz) {
    1698           0 :         ret = KRB5_BAD_MSIZE;
    1699           0 :         goto cleanup;
    1700             :     }
    1701             : 
    1702     1142228 :     if (et->flags & F_ENC_THEN_CKSUM) {
    1703           0 :         unsigned char old_ivec[EVP_MAX_IV_LENGTH];
    1704           0 :         krb5_data ivec_data;
    1705             : 
    1706           0 :         heim_assert(et->blocksize <= sizeof(old_ivec),
    1707             :                     "blocksize too big for ivec buffer");
    1708             : 
    1709           0 :         ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey);
    1710           0 :         if(ret)
    1711           0 :             goto cleanup;
    1712             : 
    1713           0 :         ret = _key_schedule(context, dkey);
    1714           0 :         if(ret)
    1715           0 :             goto cleanup;
    1716             : 
    1717           0 :         if (ivec)
    1718           0 :             memcpy(old_ivec, ivec, et->blocksize);
    1719             :         else
    1720           0 :             memset(old_ivec, 0, et->blocksize);
    1721             : 
    1722           0 :         if (et->encrypt_iov != NULL) {
    1723           0 :             ret = (*et->encrypt_iov)(context, dkey, data, num_data, 1, usage,
    1724             :                                      ivec);
    1725           0 :             if (ret)
    1726           0 :                 goto cleanup;
    1727             :         } else {
    1728           0 :             ret = iov_coalesce(context, NULL, data, num_data, FALSE, &enc_data);
    1729           0 :             if (ret)
    1730           0 :                 goto cleanup;
    1731             : 
    1732           0 :             ret = (*et->encrypt)(context, dkey, enc_data.data, enc_data.length,
    1733             :                                  1, usage, ivec);
    1734           0 :             if (ret)
    1735           0 :                 goto cleanup;
    1736             : 
    1737           0 :             ret = iov_uncoalesce(context, &enc_data, data, num_data);
    1738           0 :             if (ret)
    1739           0 :                 goto cleanup;
    1740             :         }
    1741             : 
    1742           0 :         ivec_data.length = et->blocksize;
    1743           0 :         ivec_data.data = old_ivec;
    1744             : 
    1745           0 :         ret = iov_coalesce(context, &ivec_data, data, num_data, TRUE, &sign_data);
    1746           0 :         if(ret)
    1747           0 :             goto cleanup;
    1748             : 
    1749           0 :         ret = create_checksum(context,
    1750           0 :                               et->keyed_checksum,
    1751             :                               crypto,
    1752           0 :                               INTEGRITY_USAGE(usage),
    1753             :                               sign_data.data,
    1754             :                               sign_data.length,
    1755             :                               0,
    1756             :                               &cksum);
    1757             : 
    1758           0 :         if(ret == 0 && cksum.checksum.length != trailersz) {
    1759           0 :             free_Checksum (&cksum);
    1760           0 :             krb5_clear_error_message (context);
    1761           0 :             ret = KRB5_CRYPTO_INTERNAL;
    1762             :         }
    1763           0 :         if (ret)
    1764           0 :             goto cleanup;
    1765             : 
    1766             :         /* save cksum at end */
    1767           0 :         memcpy(tiv->data.data, cksum.checksum.data, cksum.checksum.length);
    1768           0 :         free_Checksum (&cksum);
    1769             : 
    1770             :     } else {
    1771     1142228 :         cksum.checksum = tiv->data;
    1772     1143541 :         ret = create_checksum_iov(context,
    1773     1142228 :                               et->keyed_checksum,
    1774             :                               crypto,
    1775     1142228 :                               INTEGRITY_USAGE(usage),
    1776             :                               data,
    1777             :                               num_data,
    1778             :                               0,
    1779             :                               &cksum);
    1780     1142228 :         if (ret)
    1781           0 :             goto cleanup;
    1782             : 
    1783             :         /* create_checksum may realloc the derived key space, so any keys
    1784             :          * obtained before it was called may no longer be valid */
    1785     1142228 :         ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey);
    1786     1142228 :         if(ret)
    1787           0 :             goto cleanup;
    1788             : 
    1789     1142228 :         ret = _key_schedule(context, dkey);
    1790     1142228 :         if(ret)
    1791           0 :             goto cleanup;
    1792             : 
    1793     1142228 :         if (et->encrypt_iov != NULL) {
    1794     1142228 :             ret = (*et->encrypt_iov)(context, dkey, data, num_data, 1, usage,
    1795             :                                      ivec);
    1796     1142228 :             if (ret)
    1797           0 :                 goto cleanup;
    1798             :         } else {
    1799           0 :             ret = iov_coalesce(context, NULL, data, num_data, FALSE, &enc_data);
    1800           0 :             if (ret)
    1801           0 :                 goto cleanup;
    1802             : 
    1803           0 :             ret = (*et->encrypt)(context, dkey, enc_data.data, enc_data.length,
    1804             :                                  1, usage, ivec);
    1805           0 :             if (ret)
    1806           0 :                 goto cleanup;
    1807             : 
    1808           0 :             ret = iov_uncoalesce(context, &enc_data, data, num_data);
    1809           0 :             if (ret)
    1810           0 :                 goto cleanup;
    1811             :         }
    1812             :     }
    1813             : 
    1814           0 : cleanup:
    1815     1142228 :     if (enc_data.data) {
    1816           0 :         memset_s(enc_data.data, enc_data.length, 0, enc_data.length);
    1817           0 :         krb5_data_free(&enc_data);
    1818             :     }
    1819     1142228 :     if (sign_data.data) {
    1820           0 :         memset_s(sign_data.data, sign_data.length, 0, sign_data.length);
    1821           0 :         krb5_data_free(&sign_data);
    1822             :     }
    1823     1140915 :     return ret;
    1824             : }
    1825             : 
    1826             : /**
    1827             :  * Inline decrypt a Kerberos message.
    1828             :  *
    1829             :  * @param context Kerberos context
    1830             :  * @param crypto Kerberos crypto context
    1831             :  * @param usage Key usage for this buffer
    1832             :  * @param data array of buffers to process
    1833             :  * @param num_data length of array
    1834             :  * @param ivec initial cbc/cts vector
    1835             :  *
    1836             :  * @return Return an error code or 0.
    1837             :  * @ingroup krb5_crypto
    1838             :  *
    1839             :  * 1. KRB5_CRYPTO_TYPE_HEADER
    1840             :  * 2. one KRB5_CRYPTO_TYPE_DATA and array [0,...] of KRB5_CRYPTO_TYPE_SIGN_ONLY in
    1841             :  *  any order, however the receiver have to aware of the
    1842             :  *  order. KRB5_CRYPTO_TYPE_SIGN_ONLY is commonly used unencrypoted
    1843             :  *  protocol headers and trailers. The output data will be of same
    1844             :  *  size as the input data or shorter.
    1845             :  */
    1846             : 
    1847             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
    1848      425679 : krb5_decrypt_iov_ivec(krb5_context context,
    1849             :                       krb5_crypto crypto,
    1850             :                       unsigned usage,
    1851             :                       krb5_crypto_iov *data,
    1852             :                       unsigned int num_data,
    1853             :                       void *ivec)
    1854             : {
    1855        1312 :     Checksum cksum;
    1856        1312 :     krb5_data enc_data, sign_data;
    1857        1312 :     krb5_error_code ret;
    1858        1312 :     struct _krb5_key_data *dkey;
    1859      425679 :     struct _krb5_encryption_type *et = crypto->et;
    1860        1312 :     krb5_crypto_iov *tiv, *hiv;
    1861             : 
    1862      425679 :     if(!derived_crypto(context, crypto)) {
    1863           0 :         krb5_clear_error_message(context);
    1864           0 :         return KRB5_CRYPTO_INTERNAL;
    1865             :     }
    1866             : 
    1867             :     /* header */
    1868      425679 :     hiv = iov_find(data, num_data, KRB5_CRYPTO_TYPE_HEADER);
    1869      425679 :     if (hiv == NULL || hiv->data.length != et->confoundersize)
    1870           0 :         return KRB5_BAD_MSIZE;
    1871             : 
    1872             :     /* trailer */
    1873      425679 :     tiv = iov_find(data, num_data, KRB5_CRYPTO_TYPE_TRAILER);
    1874      425679 :     if (tiv->data.length != CHECKSUMSIZE(et->keyed_checksum))
    1875           0 :         return KRB5_BAD_MSIZE;
    1876             : 
    1877             :     /* padding */
    1878      426991 :     if ((iov_enc_data_len(data, num_data) % et->padsize) != 0) {
    1879           0 :         krb5_clear_error_message(context);
    1880           0 :         return KRB5_BAD_MSIZE;
    1881             :     }
    1882             : 
    1883      425679 :     krb5_data_zero(&enc_data);
    1884      425679 :     krb5_data_zero(&sign_data);
    1885             : 
    1886      425679 :     if (!(et->flags & F_ENC_THEN_CKSUM)) {
    1887      425679 :         ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey);
    1888      425679 :         if(ret)
    1889           0 :             goto cleanup;
    1890             : 
    1891      425679 :         ret = _key_schedule(context, dkey);
    1892      425679 :         if(ret)
    1893           0 :             goto cleanup;
    1894             : 
    1895      425679 :         if (et->encrypt_iov != NULL) {
    1896      425679 :             ret = (*et->encrypt_iov)(context, dkey, data, num_data,
    1897             :                                      0, usage, ivec);
    1898      425679 :             if(ret)
    1899           0 :                 goto cleanup;
    1900             :         } else {
    1901           0 :             ret = iov_coalesce(context, NULL, data, num_data, FALSE, &enc_data);
    1902           0 :             if(ret)
    1903           0 :                 goto cleanup;
    1904             : 
    1905           0 :             ret = (*et->encrypt)(context, dkey, enc_data.data, enc_data.length,
    1906             :                                  0, usage, ivec);
    1907           0 :             if(ret)
    1908           0 :                 goto cleanup;
    1909             : 
    1910           0 :             ret = iov_uncoalesce(context, &enc_data, data, num_data);
    1911           0 :             if(ret)
    1912           0 :                 goto cleanup;
    1913             :         }
    1914             : 
    1915      425679 :         cksum.checksum.data   = tiv->data.data;
    1916      425679 :         cksum.checksum.length = tiv->data.length;
    1917      425679 :         cksum.cksumtype       = CHECKSUMTYPE(et->keyed_checksum);
    1918             : 
    1919      425679 :         ret = verify_checksum_iov(context, crypto, INTEGRITY_USAGE(usage),
    1920             :                                   data, num_data, 0, &cksum);
    1921      425679 :         if(ret)
    1922           0 :             goto cleanup;
    1923             :     } else {
    1924           0 :         krb5_data ivec_data;
    1925           0 :         static const unsigned char zero_ivec[EVP_MAX_IV_LENGTH];
    1926             : 
    1927           0 :         heim_assert(et->blocksize <= sizeof(zero_ivec),
    1928             :                     "blocksize too big for ivec buffer");
    1929             : 
    1930           0 :         ivec_data.length = et->blocksize;
    1931           0 :         ivec_data.data = ivec ? ivec : rk_UNCONST(zero_ivec);
    1932             : 
    1933           0 :         ret = iov_coalesce(context, &ivec_data, data, num_data, TRUE, &sign_data);
    1934           0 :         if(ret)
    1935           0 :             goto cleanup;
    1936             : 
    1937           0 :         cksum.checksum.data   = tiv->data.data;
    1938           0 :         cksum.checksum.length = tiv->data.length;
    1939           0 :         cksum.cksumtype       = CHECKSUMTYPE(et->keyed_checksum);
    1940             : 
    1941           0 :         ret = verify_checksum(context,
    1942             :                               crypto,
    1943           0 :                               INTEGRITY_USAGE(usage),
    1944             :                               sign_data.data,
    1945             :                               sign_data.length,
    1946             :                               0,
    1947             :                               &cksum);
    1948           0 :         if(ret)
    1949           0 :             goto cleanup;
    1950             : 
    1951           0 :         ret = iov_coalesce(context, NULL, data, num_data, FALSE, &enc_data);
    1952           0 :         if(ret)
    1953           0 :             goto cleanup;
    1954             : 
    1955           0 :         ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey);
    1956           0 :         if(ret)
    1957           0 :             goto cleanup;
    1958             : 
    1959           0 :         ret = _key_schedule(context, dkey);
    1960           0 :         if(ret)
    1961           0 :             goto cleanup;
    1962             : 
    1963           0 :         ret = (*et->encrypt)(context, dkey, enc_data.data, enc_data.length,
    1964             :                              0, usage, ivec);
    1965           0 :         if(ret)
    1966           0 :             goto cleanup;
    1967             : 
    1968           0 :         ret = iov_uncoalesce(context, &enc_data, data, num_data);
    1969           0 :         if(ret)
    1970           0 :             goto cleanup;
    1971             :     }
    1972             : 
    1973      425679 : cleanup:
    1974      425679 :     if (enc_data.data) {
    1975           0 :         memset_s(enc_data.data, enc_data.length, 0, enc_data.length);
    1976           0 :         krb5_data_free(&enc_data);
    1977             :     }
    1978      425679 :     if (sign_data.data) {
    1979           0 :         memset_s(sign_data.data, sign_data.length, 0, sign_data.length);
    1980           0 :         krb5_data_free(&sign_data);
    1981             :     }
    1982      424367 :     return ret;
    1983             : }
    1984             : 
    1985             : /**
    1986             :  * Create a Kerberos message checksum.
    1987             :  *
    1988             :  * @param context Kerberos context
    1989             :  * @param crypto Kerberos crypto context
    1990             :  * @param usage Key usage for this buffer
    1991             :  * @param data array of buffers to process
    1992             :  * @param num_data length of array
    1993             :  * @param type output data
    1994             :  *
    1995             :  * @return Return an error code or 0.
    1996             :  * @ingroup krb5_crypto
    1997             :  */
    1998             : 
    1999             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
    2000           0 : krb5_create_checksum_iov(krb5_context context,
    2001             :                          krb5_crypto crypto,
    2002             :                          unsigned usage,
    2003             :                          krb5_crypto_iov *data,
    2004             :                          unsigned int num_data,
    2005             :                          krb5_cksumtype *type)
    2006             : {
    2007           0 :     Checksum cksum;
    2008           0 :     krb5_crypto_iov *civ;
    2009           0 :     struct _krb5_checksum_type *ct;
    2010           0 :     unsigned keyusage;
    2011           0 :     krb5_error_code ret;
    2012             : 
    2013           0 :     civ = iov_find(data, num_data, KRB5_CRYPTO_TYPE_CHECKSUM);
    2014           0 :     if (civ == NULL)
    2015           0 :         return KRB5_BAD_MSIZE;
    2016             : 
    2017           0 :     ct = crypto->et->keyed_checksum;
    2018           0 :     if (ct == NULL)
    2019           0 :         ct = crypto->et->checksum;
    2020             : 
    2021           0 :     if(ct == NULL) {
    2022           0 :         krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
    2023           0 :                                 N_("checksum type not found", ""));
    2024           0 :         return KRB5_PROG_SUMTYPE_NOSUPP;
    2025             :     }
    2026             : 
    2027           0 :     if (arcfour_checksum_p(ct, crypto)) {
    2028           0 :         keyusage = usage;
    2029           0 :         _krb5_usage2arcfour(context, &keyusage);
    2030             :     } else
    2031           0 :         keyusage = CHECKSUM_USAGE(usage);
    2032             : 
    2033           0 :     if (ct->checksumsize > civ->data.length) {
    2034           0 :         krb5_set_error_message(context, KRB5_BAD_MSIZE,
    2035           0 :                                N_("Checksum larger then input buffer", ""));
    2036           0 :         return KRB5_BAD_MSIZE;
    2037             :     }
    2038             : 
    2039           0 :     cksum.checksum = civ->data;
    2040           0 :     ret = create_checksum_iov(context, ct, crypto, keyusage,
    2041             :                               data, num_data, crypto_flags(crypto), &cksum);
    2042             : 
    2043           0 :     if (ret == 0 && type)
    2044           0 :         *type = cksum.cksumtype;
    2045             : 
    2046           0 :     return ret;
    2047             : }
    2048             : 
    2049             : /**
    2050             :  * Verify a Kerberos message checksum.
    2051             :  *
    2052             :  * @param context Kerberos context
    2053             :  * @param crypto Kerberos crypto context
    2054             :  * @param usage Key usage for this buffer
    2055             :  * @param data array of buffers to process
    2056             :  * @param num_data length of array
    2057             :  * @param type return checksum type if not NULL
    2058             :  *
    2059             :  * @return Return an error code or 0.
    2060             :  * @ingroup krb5_crypto
    2061             :  */
    2062             : 
    2063             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
    2064           0 : krb5_verify_checksum_iov(krb5_context context,
    2065             :                          krb5_crypto crypto,
    2066             :                          unsigned usage,
    2067             :                          krb5_crypto_iov *data,
    2068             :                          unsigned int num_data,
    2069             :                          krb5_cksumtype *type)
    2070             : {
    2071           0 :     struct _krb5_encryption_type *et = crypto->et;
    2072           0 :     struct _krb5_checksum_type *ct;
    2073           0 :     Checksum cksum;
    2074           0 :     krb5_crypto_iov *civ;
    2075           0 :     krb5_error_code ret;
    2076           0 :     unsigned keyusage;
    2077             : 
    2078           0 :     civ = iov_find(data, num_data, KRB5_CRYPTO_TYPE_CHECKSUM);
    2079           0 :     if (civ == NULL)
    2080           0 :         return KRB5_BAD_MSIZE;
    2081             : 
    2082           0 :     cksum.cksumtype = CHECKSUMTYPE(et->keyed_checksum);
    2083           0 :     cksum.checksum.length = civ->data.length;
    2084           0 :     cksum.checksum.data = civ->data.data;
    2085             : 
    2086           0 :     ct = _krb5_find_checksum(cksum.cksumtype);
    2087           0 :     if(ct == NULL) {
    2088           0 :         krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
    2089           0 :                                 N_("checksum type %d not supported", ""),
    2090           0 :                                 cksum.cksumtype);
    2091           0 :         return KRB5_PROG_SUMTYPE_NOSUPP;
    2092             :     }
    2093             : 
    2094           0 :     if (arcfour_checksum_p(ct, crypto)) {
    2095           0 :         keyusage = usage;
    2096           0 :         _krb5_usage2arcfour(context, &keyusage);
    2097             :     } else
    2098           0 :         keyusage = CHECKSUM_USAGE(usage);
    2099             : 
    2100           0 :     ret = verify_checksum_iov(context, crypto, keyusage, data, num_data,
    2101             :                               crypto_flags(crypto), &cksum);
    2102             : 
    2103           0 :     if (ret == 0 && type)
    2104           0 :         *type = cksum.cksumtype;
    2105             : 
    2106           0 :     return ret;
    2107             : }
    2108             : 
    2109             : 
    2110             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
    2111     4322601 : krb5_crypto_length(krb5_context context,
    2112             :                    krb5_crypto crypto,
    2113             :                    int type,
    2114             :                    size_t *len)
    2115             : {
    2116     4322601 :     if (!derived_crypto(context, crypto)) {
    2117           0 :         krb5_set_error_message(context, EINVAL, "not a derived crypto");
    2118           0 :         return EINVAL;
    2119             :     }
    2120             : 
    2121     4322601 :     switch(type) {
    2122           0 :     case KRB5_CRYPTO_TYPE_EMPTY:
    2123           0 :         *len = 0;
    2124           0 :         return 0;
    2125     1582760 :     case KRB5_CRYPTO_TYPE_HEADER:
    2126     1582760 :         *len = crypto->et->blocksize;
    2127     1582760 :         return 0;
    2128           0 :     case KRB5_CRYPTO_TYPE_DATA:
    2129             :     case KRB5_CRYPTO_TYPE_SIGN_ONLY:
    2130             :         /* len must already been filled in */
    2131           0 :         return 0;
    2132     1157081 :     case KRB5_CRYPTO_TYPE_PADDING:
    2133     1157081 :         if (crypto->et->padsize > 1)
    2134           0 :             *len = crypto->et->padsize;
    2135             :         else
    2136     1157081 :             *len = 0;
    2137     1155584 :         return 0;
    2138     1582760 :     case KRB5_CRYPTO_TYPE_TRAILER:
    2139     1582760 :         if (crypto->et->keyed_checksum)
    2140     1582760 :             *len = CHECKSUMSIZE(crypto->et->keyed_checksum);
    2141             :         else
    2142           0 :             *len = 0;
    2143     1579951 :         return 0;
    2144           0 :     case KRB5_CRYPTO_TYPE_CHECKSUM:
    2145           0 :         if (crypto->et->keyed_checksum)
    2146           0 :             *len = CHECKSUMSIZE(crypto->et->keyed_checksum);
    2147             :         else
    2148           0 :             *len = CHECKSUMSIZE(crypto->et->checksum);
    2149           0 :         return 0;
    2150             :     }
    2151           0 :     krb5_set_error_message(context, EINVAL,
    2152             :                            "%d not a supported type", type);
    2153           0 :     return EINVAL;
    2154             : }
    2155             : 
    2156             : 
    2157             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
    2158           0 : krb5_crypto_length_iov(krb5_context context,
    2159             :                        krb5_crypto crypto,
    2160             :                        krb5_crypto_iov *data,
    2161             :                        unsigned int num_data)
    2162             : {
    2163           0 :     krb5_error_code ret;
    2164           0 :     size_t i;
    2165             : 
    2166           0 :     for (i = 0; i < num_data; i++) {
    2167           0 :         ret = krb5_crypto_length(context, crypto,
    2168           0 :                                  data[i].flags,
    2169           0 :                                  &data[i].data.length);
    2170           0 :         if (ret)
    2171           0 :             return ret;
    2172             :     }
    2173           0 :     return 0;
    2174             : }
    2175             : 
    2176             : 
    2177             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
    2178     1095912 : krb5_encrypt_ivec(krb5_context context,
    2179             :                   krb5_crypto crypto,
    2180             :                   unsigned usage,
    2181             :                   const void *data,
    2182             :                   size_t len,
    2183             :                   krb5_data *result,
    2184             :                   void *ivec)
    2185             : {
    2186       14157 :     krb5_error_code ret;
    2187             : 
    2188     1095912 :     switch (crypto->et->flags & F_CRYPTO_MASK) {
    2189     1069009 :     case F_RFC3961_ENC:
    2190     1069009 :         ret = encrypt_internal_derived(context, crypto, usage,
    2191             :                                        data, len, result, ivec);
    2192     1069009 :         break;
    2193       26903 :     case F_SPECIAL:
    2194       26903 :         ret = encrypt_internal_special (context, crypto, usage,
    2195             :                                         data, len, result, ivec);
    2196       26903 :         break;
    2197           0 :     case F_ENC_THEN_CKSUM:
    2198           0 :         ret = encrypt_internal_enc_then_cksum(context, crypto, usage,
    2199             :                                               data, len, result, ivec);
    2200           0 :         break;
    2201           0 :     default:
    2202           0 :         ret = encrypt_internal(context, crypto, data, len, result, ivec);
    2203           0 :         break;
    2204             :     }
    2205             : 
    2206     1095912 :     return ret;
    2207             : }
    2208             : 
    2209             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
    2210     1095912 : krb5_encrypt(krb5_context context,
    2211             :              krb5_crypto crypto,
    2212             :              unsigned usage,
    2213             :              const void *data,
    2214             :              size_t len,
    2215             :              krb5_data *result)
    2216             : {
    2217     1095912 :     return krb5_encrypt_ivec(context, crypto, usage, data, len, result, NULL);
    2218             : }
    2219             : 
    2220             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
    2221      267693 : krb5_encrypt_EncryptedData(krb5_context context,
    2222             :                            krb5_crypto crypto,
    2223             :                            unsigned usage,
    2224             :                            void *data,
    2225             :                            size_t len,
    2226             :                            int kvno,
    2227             :                            EncryptedData *result)
    2228             : {
    2229      267693 :     result->etype = CRYPTO_ETYPE(crypto);
    2230      267693 :     if(kvno){
    2231      108800 :         ALLOC(result->kvno, 1);
    2232      108800 :         *result->kvno = kvno;
    2233             :     }else
    2234      158893 :         result->kvno = NULL;
    2235      267693 :     return krb5_encrypt(context, crypto, usage, data, len, &result->cipher);
    2236             : }
    2237             : 
    2238             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
    2239     1140002 : krb5_decrypt_ivec(krb5_context context,
    2240             :                   krb5_crypto crypto,
    2241             :                   unsigned usage,
    2242             :                   void *data,
    2243             :                   size_t len,
    2244             :                   krb5_data *result,
    2245             :                   void *ivec)
    2246             : {
    2247       13717 :     krb5_error_code ret;
    2248             : 
    2249     1140002 :     switch (crypto->et->flags & F_CRYPTO_MASK) {
    2250     1118790 :     case F_RFC3961_ENC:
    2251     1118790 :         ret = decrypt_internal_derived(context, crypto, usage,
    2252             :                                 data, len, result, ivec);
    2253     1118790 :         break;
    2254       21212 :     case F_SPECIAL:
    2255       21212 :         ret = decrypt_internal_special(context, crypto, usage,
    2256             :                                        data, len, result, ivec);
    2257       21212 :         break;
    2258           0 :     case F_ENC_THEN_CKSUM:
    2259           0 :         ret = decrypt_internal_enc_then_cksum(context, crypto, usage,
    2260             :                                               data, len, result, ivec);
    2261           0 :         break;
    2262           0 :     default:
    2263           0 :         ret = decrypt_internal(context, crypto, data, len, result, ivec);
    2264           0 :         break;
    2265             :     }
    2266             : 
    2267     1140002 :     return ret;
    2268             : }
    2269             : 
    2270             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
    2271     1139998 : krb5_decrypt(krb5_context context,
    2272             :              krb5_crypto crypto,
    2273             :              unsigned usage,
    2274             :              void *data,
    2275             :              size_t len,
    2276             :              krb5_data *result)
    2277             : {
    2278     1139998 :     return krb5_decrypt_ivec (context, crypto, usage, data, len, result,
    2279             :                               NULL);
    2280             : }
    2281             : 
    2282             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
    2283      447634 : krb5_decrypt_EncryptedData(krb5_context context,
    2284             :                            krb5_crypto crypto,
    2285             :                            unsigned usage,
    2286             :                            const EncryptedData *e,
    2287             :                            krb5_data *result)
    2288             : {
    2289      895268 :     return krb5_decrypt(context, crypto, usage,
    2290      447634 :                         e->cipher.data, e->cipher.length, result);
    2291             : }
    2292             : 
    2293             : /************************************************************
    2294             :  *                                                          *
    2295             :  ************************************************************/
    2296             : 
    2297             : static krb5_error_code
    2298     3219701 : derive_key_rfc3961(krb5_context context,
    2299             :                    struct _krb5_encryption_type *et,
    2300             :                    struct _krb5_key_data *key,
    2301             :                    const void *constant,
    2302             :                    size_t len)
    2303             : {
    2304             : 
    2305     3219701 :     unsigned char *k = NULL;
    2306     3219701 :     unsigned int nblocks = 0, i;
    2307     3219701 :     krb5_error_code ret = 0;
    2308     3219701 :     struct _krb5_key_type *kt = et->keytype;
    2309             : 
    2310     3219701 :     if(et->blocksize * 8 < kt->bits || len != et->blocksize) {
    2311     3219701 :         nblocks = (kt->bits + et->blocksize * 8 - 1) / (et->blocksize * 8);
    2312     3219701 :         k = malloc(nblocks * et->blocksize);
    2313     3219701 :         if(k == NULL) {
    2314           0 :             ret = krb5_enomem(context);
    2315           0 :             goto out;
    2316             :         }
    2317     3219701 :         ret = _krb5_n_fold(constant, len, k, et->blocksize);
    2318     3219701 :         if (ret) {
    2319           0 :             krb5_enomem(context);
    2320           0 :             goto out;
    2321             :         }
    2322             : 
    2323     9631863 :         for(i = 0; i < nblocks; i++) {
    2324     6412162 :             if(i > 0)
    2325     3398928 :                 memcpy(k + i * et->blocksize,
    2326     3192461 :                        k + (i - 1) * et->blocksize,
    2327             :                        et->blocksize);
    2328     6412162 :             ret = (*et->encrypt)(context, key, k + i * et->blocksize,
    2329             :                                  et->blocksize, 1, 0, NULL);
    2330     6412162 :             if (ret) {
    2331           0 :                     krb5_set_error_message(context, ret, N_("encrypt failed", ""));
    2332           0 :                     goto out;
    2333             :             }
    2334             :         }
    2335             :     } else {
    2336             :         /* this case is probably broken, but won't be run anyway */
    2337           0 :         void *c = malloc(len);
    2338           0 :         size_t res_len = (kt->bits + 7) / 8;
    2339             : 
    2340           0 :         if(len != 0 && c == NULL) {
    2341           0 :             ret = krb5_enomem(context);
    2342           0 :             goto out;
    2343             :         }
    2344           0 :         memcpy(c, constant, len);
    2345           0 :         ret = (*et->encrypt)(context, key, c, len, 1, 0, NULL);
    2346           0 :         if (ret) {
    2347           0 :                 free(c);
    2348           0 :                 krb5_set_error_message(context, ret, N_("encrypt failed", ""));
    2349           0 :                 goto out;
    2350             :         }
    2351           0 :         k = malloc(res_len);
    2352           0 :         if(res_len != 0 && k == NULL) {
    2353           0 :             free(c);
    2354           0 :             ret = krb5_enomem(context);
    2355           0 :             goto out;
    2356             :         }
    2357           0 :         ret = _krb5_n_fold(c, len, k, res_len);
    2358           0 :         free(c);
    2359           0 :         if (ret) {
    2360           0 :             krb5_enomem(context);
    2361           0 :             goto out;
    2362             :         }
    2363             :     }
    2364             : 
    2365     3219701 :     if (kt->type == KRB5_ENCTYPE_OLD_DES3_CBC_SHA1)
    2366           0 :         _krb5_DES3_random_to_key(context, key->key, k, nblocks * et->blocksize);
    2367             :     else
    2368     3219701 :         memcpy(key->key->keyvalue.data, k, key->key->keyvalue.length);
    2369             : 
    2370     3219701 :  out:
    2371     3219701 :     if (k) {
    2372     3219701 :         memset_s(k, nblocks * et->blocksize, 0, nblocks * et->blocksize);
    2373     3219701 :         free(k);
    2374             :     }
    2375     3219701 :     return ret;
    2376             : }
    2377             : 
    2378             : static krb5_error_code
    2379           0 : derive_key_sp800_hmac(krb5_context context,
    2380             :                       struct _krb5_encryption_type *et,
    2381             :                       struct _krb5_key_data *key,
    2382             :                       const void *constant,
    2383             :                       size_t len)
    2384             : {
    2385           0 :     krb5_error_code ret;
    2386           0 :     struct _krb5_key_type *kt = et->keytype;
    2387           0 :     krb5_data label;
    2388           0 :     const EVP_MD *md = NULL;
    2389           0 :     const unsigned char *c = constant;
    2390           0 :     size_t key_len;
    2391           0 :     krb5_data K1;
    2392             : 
    2393           0 :     ret = _krb5_aes_sha2_md_for_enctype(context, kt->type, &md);
    2394           0 :     if (ret)
    2395           0 :         return ret;
    2396             : 
    2397             :     /*
    2398             :      * PRF usage: not handled here (output cannot be longer)
    2399             :      * Integrity usage: truncated hash (half length)
    2400             :      * Encryption usage: base key length
    2401             :      */
    2402           0 :     if (len == 5 && (c[4] == 0x99 || c[4] == 0x55))
    2403           0 :         key_len = EVP_MD_size(md) / 2;
    2404             :     else
    2405           0 :         key_len = kt->size;
    2406             : 
    2407           0 :     ret = krb5_data_alloc(&K1, key_len);
    2408           0 :     if (ret)
    2409           0 :         return ret;
    2410             : 
    2411           0 :     label.data = (void *)constant;
    2412           0 :     label.length = len;
    2413             : 
    2414           0 :     ret = _krb5_SP800_108_HMAC_KDF(context, &key->key->keyvalue,
    2415             :                                    &label, NULL, md, &K1);
    2416           0 :     if (ret == 0) {
    2417           0 :         if (key->key->keyvalue.length > key_len)
    2418           0 :             key->key->keyvalue.length = key_len;
    2419           0 :         memcpy(key->key->keyvalue.data, K1.data, key_len);
    2420             :     }
    2421             : 
    2422           0 :     memset_s(K1.data, K1.length, 0, K1.length);
    2423           0 :     krb5_data_free(&K1);
    2424             : 
    2425           0 :     return ret;
    2426             : }
    2427             : 
    2428             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
    2429     3219701 : _krb5_derive_key(krb5_context context,
    2430             :                  struct _krb5_encryption_type *et,
    2431             :                  struct _krb5_key_data *key,
    2432             :                  const void *constant,
    2433             :                  size_t len)
    2434             : {
    2435      103346 :     krb5_error_code ret;
    2436             : 
    2437     3219701 :     ret = _key_schedule(context, key);
    2438     3219701 :     if(ret)
    2439           0 :         return ret;
    2440             : 
    2441     3219701 :     switch (et->flags & F_KDF_MASK) {
    2442     3219701 :     case F_RFC3961_KDF:
    2443     3219701 :         ret = derive_key_rfc3961(context, et, key, constant, len);
    2444     3219701 :         break;
    2445           0 :     case F_SP800_108_HMAC_KDF:
    2446           0 :         ret = derive_key_sp800_hmac(context, et, key, constant, len);
    2447           0 :         break;
    2448           0 :     default:
    2449           0 :         ret = KRB5_CRYPTO_INTERNAL;
    2450           0 :         krb5_set_error_message(context, ret,
    2451           0 :                                N_("derive_key() called with unknown keytype (%u)", ""),
    2452           0 :                                et->keytype->type);
    2453           0 :         break;
    2454             :     }
    2455             : 
    2456     3219701 :     if (key->schedule) {
    2457     3219701 :         free_key_schedule(context, key, et);
    2458     3219701 :         key->schedule = NULL;
    2459             :     }
    2460             : 
    2461     3116355 :     return ret;
    2462             : }
    2463             : 
    2464             : static struct _krb5_key_data *
    2465     2426595 : _new_derived_key(krb5_crypto crypto, unsigned usage)
    2466             : {
    2467     2426595 :     struct _krb5_key_usage *d = crypto->key_usage;
    2468     2426595 :     d = realloc(d, (crypto->num_key_usage + 1) * sizeof(*d));
    2469     2426595 :     if(d == NULL)
    2470           0 :         return NULL;
    2471     2426595 :     crypto->key_usage = d;
    2472     2426595 :     d += crypto->num_key_usage++;
    2473     2426595 :     memset(d, 0, sizeof(*d));
    2474     2426595 :     d->usage = usage;
    2475     2426595 :     return &d->key;
    2476             : }
    2477             : 
    2478             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
    2479      706544 : krb5_derive_key(krb5_context context,
    2480             :                 const krb5_keyblock *key,
    2481             :                 krb5_enctype etype,
    2482             :                 const void *constant,
    2483             :                 size_t constant_len,
    2484             :                 krb5_keyblock **derived_key)
    2485             : {
    2486       26528 :     krb5_error_code ret;
    2487       26528 :     struct _krb5_encryption_type *et;
    2488       26528 :     struct _krb5_key_data d;
    2489             : 
    2490      706544 :     *derived_key = NULL;
    2491             : 
    2492      706544 :     et = _krb5_find_enctype (etype);
    2493      706544 :     if (et == NULL) {
    2494           0 :         return unsupported_enctype (context, etype);
    2495             :     }
    2496             : 
    2497      706544 :     ret = krb5_copy_keyblock(context, key, &d.key);
    2498      706544 :     if (ret)
    2499           0 :         return ret;
    2500             : 
    2501      706544 :     d.schedule = NULL;
    2502      706544 :     ret = _krb5_derive_key(context, et, &d, constant, constant_len);
    2503      706544 :     if (ret == 0)
    2504      706544 :         ret = krb5_copy_keyblock(context, d.key, derived_key);
    2505      706544 :     _krb5_free_key_data(context, &d, et);
    2506      706544 :     return ret;
    2507             : }
    2508             : 
    2509             : static krb5_error_code
    2510     8579992 : _get_derived_key(krb5_context context,
    2511             :                  krb5_crypto crypto,
    2512             :                  unsigned usage,
    2513             :                  struct _krb5_key_data **key)
    2514             : {
    2515       82686 :     int i;
    2516       82686 :     struct _krb5_key_data *d;
    2517       82686 :     unsigned char constant[5];
    2518             : 
    2519     8579992 :     *key = NULL;
    2520    27530285 :     for(i = 0; i < crypto->num_key_usage; i++)
    2521    25103690 :         if(crypto->key_usage[i].usage == usage) {
    2522     6153397 :             *key = &crypto->key_usage[i].key;
    2523     6153397 :             return 0;
    2524             :         }
    2525     2426595 :     d = _new_derived_key(crypto, usage);
    2526     2426595 :     if (d == NULL)
    2527           0 :         return krb5_enomem(context);
    2528     2426595 :     *key = d;
    2529     2426595 :     krb5_copy_keyblock(context, crypto->key.key, &d->key);
    2530     2426595 :     _krb5_put_int(constant, usage, sizeof(constant));
    2531     2426595 :     return _krb5_derive_key(context, crypto->et, d, constant, sizeof(constant));
    2532             : }
    2533             : 
    2534             : /**
    2535             :  * Create a crypto context used for all encryption and signature
    2536             :  * operation. The encryption type to use is taken from the key, but
    2537             :  * can be overridden with the enctype parameter.  This can be useful
    2538             :  * for encryptions types which is compatiable (DES for example).
    2539             :  *
    2540             :  * To free the crypto context, use krb5_crypto_destroy().
    2541             :  *
    2542             :  * @param context Kerberos context
    2543             :  * @param key the key block information with all key data
    2544             :  * @param etype the encryption type
    2545             :  * @param crypto the resulting crypto context
    2546             :  *
    2547             :  * @return Return an error code or 0.
    2548             :  *
    2549             :  * @ingroup krb5_crypto
    2550             :  */
    2551             : 
    2552             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
    2553     2005551 : krb5_crypto_init(krb5_context context,
    2554             :                  const krb5_keyblock *key,
    2555             :                  krb5_enctype etype,
    2556             :                  krb5_crypto *crypto)
    2557             : {
    2558       58798 :     krb5_error_code ret;
    2559     2005551 :     ALLOC(*crypto, 1);
    2560     2005551 :     if (*crypto == NULL)
    2561           0 :         return krb5_enomem(context);
    2562     2005551 :     if(etype == ETYPE_NULL)
    2563     1847301 :         etype = key->keytype;
    2564     2005551 :     (*crypto)->et = _krb5_find_enctype(etype);
    2565     2005551 :     if((*crypto)->et == NULL || ((*crypto)->et->flags & F_DISABLED)) {
    2566           0 :         free(*crypto);
    2567           0 :         *crypto = NULL;
    2568           0 :         return unsupported_enctype(context, etype);
    2569             :     }
    2570     2005551 :     if((*crypto)->et->keytype->size != key->keyvalue.length) {
    2571           0 :         free(*crypto);
    2572           0 :         *crypto = NULL;
    2573           0 :         krb5_set_error_message (context, KRB5_BAD_KEYSIZE,
    2574             :                                 "encryption key has bad length");
    2575           0 :         return KRB5_BAD_KEYSIZE;
    2576             :     }
    2577     2005551 :     ret = krb5_copy_keyblock(context, key, &(*crypto)->key.key);
    2578     2005551 :     if(ret) {
    2579           0 :         free(*crypto);
    2580           0 :         *crypto = NULL;
    2581           0 :         return ret;
    2582             :     }
    2583     2005551 :     (*crypto)->key.schedule = NULL;
    2584     2005551 :     (*crypto)->num_key_usage = 0;
    2585     2005551 :     (*crypto)->key_usage = NULL;
    2586     2005551 :     (*crypto)->flags = 0;
    2587     2005551 :     return 0;
    2588             : }
    2589             : 
    2590             : static void
    2591     5815328 : free_key_schedule(krb5_context context,
    2592             :                   struct _krb5_key_data *key,
    2593             :                   struct _krb5_encryption_type *et)
    2594             : {
    2595     5815328 :     if (et->keytype->cleanup)
    2596     5815328 :         (*et->keytype->cleanup)(context, key);
    2597     5815328 :     memset(key->schedule->data, 0, key->schedule->length);
    2598     5815328 :     krb5_free_data(context, key->schedule);
    2599     5815328 : }
    2600             : 
    2601             : KRB5_LIB_FUNCTION void KRB5_LIB_CALL
    2602     5225203 : _krb5_free_key_data(krb5_context context, struct _krb5_key_data *key,
    2603             :               struct _krb5_encryption_type *et)
    2604             : {
    2605     5225203 :     krb5_free_keyblock(context, key->key);
    2606     5225203 :     if(key->schedule) {
    2607     2595627 :         free_key_schedule(context, key, et);
    2608     2595627 :         key->schedule = NULL;
    2609             :     }
    2610     5225203 : }
    2611             : 
    2612             : static void
    2613     2426595 : free_key_usage(krb5_context context, struct _krb5_key_usage *ku,
    2614             :                struct _krb5_encryption_type *et)
    2615             : {
    2616     2426595 :     _krb5_free_key_data(context, &ku->key, et);
    2617     2351417 : }
    2618             : 
    2619             : /**
    2620             :  * Free a crypto context created by krb5_crypto_init().
    2621             :  *
    2622             :  * @param context Kerberos context
    2623             :  * @param crypto crypto context to free
    2624             :  *
    2625             :  * @return Return an error code or 0.
    2626             :  *
    2627             :  * @ingroup krb5_crypto
    2628             :  */
    2629             : 
    2630             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
    2631     2005502 : krb5_crypto_destroy(krb5_context context,
    2632             :                     krb5_crypto crypto)
    2633             : {
    2634       58793 :     int i;
    2635             : 
    2636     4432097 :     for(i = 0; i < crypto->num_key_usage; i++)
    2637     2426595 :         free_key_usage(context, &crypto->key_usage[i], crypto->et);
    2638     2005502 :     free(crypto->key_usage);
    2639     2005502 :     _krb5_free_key_data(context, &crypto->key, crypto->et);
    2640             : 
    2641     2005502 :     if (crypto->mdctx)
    2642      538264 :         EVP_MD_CTX_destroy(crypto->mdctx);
    2643             : 
    2644     2005502 :     if (crypto->hmacctx)
    2645     1193564 :         HMAC_CTX_free(crypto->hmacctx);
    2646             : 
    2647     2005502 :     free (crypto);
    2648     2005502 :     return 0;
    2649             : }
    2650             : 
    2651             : /**
    2652             :  * Return the blocksize used algorithm referenced by the crypto context
    2653             :  *
    2654             :  * @param context Kerberos context
    2655             :  * @param crypto crypto context to query
    2656             :  * @param blocksize the resulting blocksize
    2657             :  *
    2658             :  * @return Return an error code or 0.
    2659             :  *
    2660             :  * @ingroup krb5_crypto
    2661             :  */
    2662             : 
    2663             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
    2664     1157081 : krb5_crypto_getblocksize(krb5_context context,
    2665             :                          krb5_crypto crypto,
    2666             :                          size_t *blocksize)
    2667             : {
    2668     1157081 :     *blocksize = crypto->et->blocksize;
    2669     1157081 :     return 0;
    2670             : }
    2671             : 
    2672             : /**
    2673             :  * Return the encryption type used by the crypto context
    2674             :  *
    2675             :  * @param context Kerberos context
    2676             :  * @param crypto crypto context to query
    2677             :  * @param enctype the resulting encryption type
    2678             :  *
    2679             :  * @return Return an error code or 0.
    2680             :  *
    2681             :  * @ingroup krb5_crypto
    2682             :  */
    2683             : 
    2684             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
    2685         225 : krb5_crypto_getenctype(krb5_context context,
    2686             :                        krb5_crypto crypto,
    2687             :                        krb5_enctype *enctype)
    2688             : {
    2689         225 :     *enctype = crypto->et->type;
    2690         225 :     return 0;
    2691             : }
    2692             : 
    2693             : /**
    2694             :  * Return the padding size used by the crypto context
    2695             :  *
    2696             :  * @param context Kerberos context
    2697             :  * @param crypto crypto context to query
    2698             :  * @param padsize the return padding size
    2699             :  *
    2700             :  * @return Return an error code or 0.
    2701             :  *
    2702             :  * @ingroup krb5_crypto
    2703             :  */
    2704             : 
    2705             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
    2706      692512 : krb5_crypto_getpadsize(krb5_context context,
    2707             :                        krb5_crypto crypto,
    2708             :                        size_t *padsize)
    2709             : {
    2710      692512 :     *padsize = crypto->et->padsize;
    2711      692512 :     return 0;
    2712             : }
    2713             : 
    2714             : /**
    2715             :  * Return the confounder size used by the crypto context
    2716             :  *
    2717             :  * @param context Kerberos context
    2718             :  * @param crypto crypto context to query
    2719             :  * @param confoundersize the returned confounder size
    2720             :  *
    2721             :  * @return Return an error code or 0.
    2722             :  *
    2723             :  * @ingroup krb5_crypto
    2724             :  */
    2725             : 
    2726             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
    2727           0 : krb5_crypto_getconfoundersize(krb5_context context,
    2728             :                               krb5_crypto crypto,
    2729             :                               size_t *confoundersize)
    2730             : {
    2731           0 :     *confoundersize = crypto->et->confoundersize;
    2732           0 :     return 0;
    2733             : }
    2734             : 
    2735             : 
    2736             : /**
    2737             :  * Disable encryption type
    2738             :  *
    2739             :  * @param context Kerberos 5 context
    2740             :  * @param enctype encryption type to disable
    2741             :  *
    2742             :  * @return Return an error code or 0.
    2743             :  *
    2744             :  * @ingroup krb5_crypto
    2745             :  */
    2746             : 
    2747             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
    2748           0 : krb5_enctype_disable(krb5_context context,
    2749             :                      krb5_enctype enctype)
    2750             : {
    2751           0 :     struct _krb5_encryption_type *et = _krb5_find_enctype(enctype);
    2752           0 :     if(et == NULL) {
    2753           0 :         if (context)
    2754           0 :             krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
    2755           0 :                                     N_("encryption type %d not supported", ""),
    2756             :                                     enctype);
    2757           0 :         return KRB5_PROG_ETYPE_NOSUPP;
    2758             :     }
    2759           0 :     et->flags |= F_DISABLED;
    2760           0 :     return 0;
    2761             : }
    2762             : 
    2763             : /**
    2764             :  * Enable encryption type
    2765             :  *
    2766             :  * @param context Kerberos 5 context
    2767             :  * @param enctype encryption type to enable
    2768             :  *
    2769             :  * @return Return an error code or 0.
    2770             :  *
    2771             :  * @ingroup krb5_crypto
    2772             :  */
    2773             : 
    2774             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
    2775           0 : krb5_enctype_enable(krb5_context context,
    2776             :                     krb5_enctype enctype)
    2777             : {
    2778           0 :     struct _krb5_encryption_type *et = _krb5_find_enctype(enctype);
    2779           0 :     if(et == NULL) {
    2780           0 :         if (context)
    2781           0 :             krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
    2782           0 :                                     N_("encryption type %d not supported", ""),
    2783             :                                     enctype);
    2784           0 :         return KRB5_PROG_ETYPE_NOSUPP;
    2785             :     }
    2786           0 :     et->flags &= ~F_DISABLED;
    2787           0 :     return 0;
    2788             : }
    2789             : 
    2790             : /**
    2791             :  * Enable or disable all weak encryption types
    2792             :  *
    2793             :  * @param context Kerberos 5 context
    2794             :  * @param enable true to enable, false to disable
    2795             :  *
    2796             :  * @return Return an error code or 0.
    2797             :  *
    2798             :  * @ingroup krb5_crypto
    2799             :  */
    2800             : 
    2801             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
    2802           0 : krb5_allow_weak_crypto(krb5_context context,
    2803             :                        krb5_boolean enable)
    2804             : {
    2805           0 :     int i;
    2806             : 
    2807           0 :     for(i = 0; i < _krb5_num_etypes; i++)
    2808           0 :         if(_krb5_etypes[i]->flags & F_WEAK) {
    2809           0 :             if(enable)
    2810           0 :                 _krb5_etypes[i]->flags &= ~F_DISABLED;
    2811             :             else
    2812           0 :                 _krb5_etypes[i]->flags |= F_DISABLED;
    2813             :         }
    2814           0 :     return 0;
    2815             : }
    2816             : 
    2817             : /**
    2818             :  * Returns is the encryption is strong or weak
    2819             :  *
    2820             :  * @param context Kerberos 5 context
    2821             :  * @param enctype encryption type to probe
    2822             :  *
    2823             :  * @return Returns true if encryption type is weak or is not supported.
    2824             :  *
    2825             :  * @ingroup krb5_crypto
    2826             :  */
    2827             : 
    2828             : KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL
    2829        3424 : krb5_is_enctype_weak(krb5_context context, krb5_enctype enctype)
    2830             : {
    2831        3424 :     struct _krb5_encryption_type *et = _krb5_find_enctype(enctype);
    2832        3424 :     if(et == NULL || (et->flags & F_WEAK))
    2833          43 :         return TRUE;
    2834        3381 :     return FALSE;
    2835             : }
    2836             : 
    2837             : /**
    2838             :  * Returns whether the encryption type is new or old
    2839             :  *
    2840             :  * @param context Kerberos 5 context
    2841             :  * @param enctype encryption type to probe
    2842             :  *
    2843             :  * @return Returns true if encryption type is old or is not supported.
    2844             :  *
    2845             :  * @ingroup krb5_crypto
    2846             :  */
    2847             : 
    2848             : KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL
    2849       19461 : krb5_is_enctype_old(krb5_context context, krb5_enctype enctype)
    2850             : {
    2851       19461 :     struct _krb5_encryption_type *et = _krb5_find_enctype(enctype);
    2852       19461 :     if (!et  || (et->flags & F_OLD))
    2853        1477 :         return TRUE;
    2854       17399 :     return FALSE;
    2855             : }
    2856             : 
    2857             : /**
    2858             :  * Returns whether the encryption type should use randomly generated salts
    2859             :  *
    2860             :  * @param context Kerberos 5 context
    2861             :  * @param enctype encryption type to probe
    2862             :  *
    2863             :  * @return Returns true if generated salts should have random component
    2864             :  *
    2865             :  * @ingroup krb5_crypto
    2866             :  */
    2867             : KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL
    2868           0 : _krb5_enctype_requires_random_salt(krb5_context context,
    2869             :                                    krb5_enctype enctype)
    2870             : {
    2871           0 :     struct _krb5_encryption_type *et;
    2872             : 
    2873           0 :     et = _krb5_find_enctype (enctype);
    2874             : 
    2875           0 :     return et && (et->flags & F_SP800_108_HMAC_KDF);
    2876             : }
    2877             : 
    2878             : static size_t
    2879           0 : wrapped_length (krb5_context context,
    2880             :                 krb5_crypto  crypto,
    2881             :                 size_t       data_len)
    2882             : {
    2883           0 :     struct _krb5_encryption_type *et = crypto->et;
    2884           0 :     size_t padsize = et->padsize;
    2885           0 :     size_t checksumsize = CHECKSUMSIZE(et->checksum);
    2886           0 :     size_t res;
    2887             : 
    2888           0 :     res =  et->confoundersize + checksumsize + data_len;
    2889           0 :     res =  (res + padsize - 1) / padsize * padsize;
    2890           0 :     return res;
    2891             : }
    2892             : 
    2893             : static size_t
    2894     1389382 : wrapped_length_dervied (krb5_context context,
    2895             :                         krb5_crypto  crypto,
    2896             :                         size_t       data_len)
    2897             : {
    2898     1389382 :     struct _krb5_encryption_type *et = crypto->et;
    2899     1389382 :     size_t padsize = et->padsize;
    2900        8006 :     size_t res;
    2901             : 
    2902     1389382 :     res =  et->confoundersize + data_len;
    2903     1389382 :     res =  (res + padsize - 1) / padsize * padsize;
    2904     1389382 :     if (et->keyed_checksum)
    2905     1389382 :         res += et->keyed_checksum->checksumsize;
    2906             :     else
    2907           0 :         res += et->checksum->checksumsize;
    2908     1389382 :     return res;
    2909             : }
    2910             : 
    2911             : /*
    2912             :  * Return the size of an encrypted packet of length `data_len'
    2913             :  */
    2914             : 
    2915             : KRB5_LIB_FUNCTION size_t KRB5_LIB_CALL
    2916     1389382 : krb5_get_wrapped_length (krb5_context context,
    2917             :                          krb5_crypto  crypto,
    2918             :                          size_t       data_len)
    2919             : {
    2920     1389382 :     if (derived_crypto (context, crypto))
    2921     1397388 :         return wrapped_length_dervied (context, crypto, data_len);
    2922             :     else
    2923           0 :         return wrapped_length (context, crypto, data_len);
    2924             : }
    2925             : 
    2926             : /*
    2927             :  * Return the size of an encrypted packet of length `data_len'
    2928             :  */
    2929             : 
    2930             : static size_t
    2931           0 : crypto_overhead (krb5_context context,
    2932             :                  krb5_crypto  crypto)
    2933             : {
    2934           0 :     struct _krb5_encryption_type *et = crypto->et;
    2935           0 :     size_t res;
    2936             : 
    2937           0 :     res = CHECKSUMSIZE(et->checksum);
    2938           0 :     res += et->confoundersize;
    2939           0 :     if (et->padsize > 1)
    2940           0 :         res += et->padsize;
    2941           0 :     return res;
    2942             : }
    2943             : 
    2944             : static size_t
    2945           0 : crypto_overhead_dervied (krb5_context context,
    2946             :                          krb5_crypto  crypto)
    2947             : {
    2948           0 :     struct _krb5_encryption_type *et = crypto->et;
    2949           0 :     size_t res;
    2950             : 
    2951           0 :     if (et->keyed_checksum)
    2952           0 :         res = CHECKSUMSIZE(et->keyed_checksum);
    2953             :     else
    2954           0 :         res = CHECKSUMSIZE(et->checksum);
    2955           0 :     res += et->confoundersize;
    2956           0 :     if (et->padsize > 1)
    2957           0 :         res += et->padsize;
    2958           0 :     return res;
    2959             : }
    2960             : 
    2961             : KRB5_LIB_FUNCTION size_t KRB5_LIB_CALL
    2962           0 : krb5_crypto_overhead (krb5_context context, krb5_crypto crypto)
    2963             : {
    2964           0 :     if (derived_crypto (context, crypto))
    2965           0 :         return crypto_overhead_dervied (context, crypto);
    2966             :     else
    2967           0 :         return crypto_overhead (context, crypto);
    2968             : }
    2969             : 
    2970             : /**
    2971             :  * Converts the random bytestring to a protocol key according to
    2972             :  * Kerberos crypto frame work. It may be assumed that all the bits of
    2973             :  * the input string are equally random, even though the entropy
    2974             :  * present in the random source may be limited.
    2975             :  *
    2976             :  * @param context Kerberos 5 context
    2977             :  * @param type the enctype resulting key will be of
    2978             :  * @param data input random data to convert to a key
    2979             :  * @param size size of input random data, at least krb5_enctype_keysize() long
    2980             :  * @param key key, output key, free with krb5_free_keyblock_contents()
    2981             :  *
    2982             :  * @return Return an error code or 0.
    2983             :  *
    2984             :  * @ingroup krb5_crypto
    2985             :  */
    2986             : 
    2987             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
    2988      180574 : krb5_random_to_key(krb5_context context,
    2989             :                    krb5_enctype type,
    2990             :                    const void *data,
    2991             :                    size_t size,
    2992             :                    krb5_keyblock *key)
    2993             : {
    2994        6632 :     krb5_error_code ret;
    2995      180574 :     struct _krb5_encryption_type *et = _krb5_find_enctype(type);
    2996      180574 :     if(et == NULL) {
    2997           0 :         krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
    2998           0 :                                N_("encryption type %d not supported", ""),
    2999             :                                type);
    3000           0 :         return KRB5_PROG_ETYPE_NOSUPP;
    3001             :     }
    3002      180574 :     if ((et->keytype->bits + 7) / 8 > size) {
    3003           0 :         krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
    3004           0 :                                N_("encryption key %s needs %d bytes "
    3005             :                                   "of random to make an encryption key "
    3006             :                                   "out of it", ""),
    3007           0 :                                et->name, (int)et->keytype->size);
    3008           0 :         return KRB5_PROG_ETYPE_NOSUPP;
    3009             :     }
    3010      180574 :     ret = krb5_data_alloc(&key->keyvalue, et->keytype->size);
    3011      180574 :     if(ret)
    3012           0 :         return ret;
    3013      180574 :     key->keytype = type;
    3014      180574 :     if (et->keytype->random_to_key)
    3015           0 :         (*et->keytype->random_to_key)(context, key, data, size);
    3016             :     else
    3017      180574 :         memcpy(key->keyvalue.data, data, et->keytype->size);
    3018             : 
    3019      173942 :     return 0;
    3020             : }
    3021             : 
    3022             : 
    3023             : 
    3024             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
    3025           0 : krb5_crypto_prf_length(krb5_context context,
    3026             :                        krb5_enctype type,
    3027             :                        size_t *length)
    3028             : {
    3029           0 :     struct _krb5_encryption_type *et = _krb5_find_enctype(type);
    3030             : 
    3031           0 :     if(et == NULL || et->prf_length == 0) {
    3032           0 :         krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
    3033           0 :                                N_("encryption type %d not supported", ""),
    3034             :                                type);
    3035           0 :         return KRB5_PROG_ETYPE_NOSUPP;
    3036             :     }
    3037             : 
    3038           0 :     *length = et->prf_length;
    3039           0 :     return 0;
    3040             : }
    3041             : 
    3042             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
    3043      714348 : krb5_crypto_prf(krb5_context context,
    3044             :                 const krb5_crypto crypto,
    3045             :                 const krb5_data *input,
    3046             :                 krb5_data *output)
    3047             : {
    3048      714348 :     struct _krb5_encryption_type *et = crypto->et;
    3049             : 
    3050      714348 :     krb5_data_zero(output);
    3051             : 
    3052      714348 :     if(et->prf == NULL) {
    3053           0 :         krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
    3054             :                                "kerberos prf for %s not supported",
    3055             :                                et->name);
    3056           0 :         return KRB5_PROG_ETYPE_NOSUPP;
    3057             :     }
    3058             : 
    3059      714348 :     return (*et->prf)(context, crypto, input, output);
    3060             : }
    3061             : 
    3062             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
    3063      361074 : krb5_crypto_prfplus(krb5_context context,
    3064             :                     const krb5_crypto crypto,
    3065             :                     const krb5_data *input,
    3066             :                     size_t length,
    3067             :                     krb5_data *output)
    3068             : {
    3069       13264 :     krb5_error_code ret;
    3070       13264 :     krb5_data input2;
    3071      361074 :     unsigned char i = 1;
    3072       13264 :     unsigned char *p;
    3073             : 
    3074      361074 :     krb5_data_zero(&input2);
    3075      361074 :     krb5_data_zero(output);
    3076             : 
    3077      361074 :     krb5_clear_error_message(context);
    3078             : 
    3079      361074 :     ret = krb5_data_alloc(output, length);
    3080      361074 :     if (ret) goto out;
    3081      361074 :     ret = krb5_data_alloc(&input2, input->length + 1);
    3082      361074 :     if (ret) goto out;
    3083             : 
    3084      361074 :     krb5_clear_error_message(context);
    3085             : 
    3086      361074 :     memcpy(((unsigned char *)input2.data) + 1, input->data, input->length);
    3087             : 
    3088      361074 :     p = output->data;
    3089             : 
    3090     1075422 :     while (length) {
    3091       26528 :         krb5_data block;
    3092             : 
    3093      714348 :         ((unsigned char *)input2.data)[0] = i++;
    3094             : 
    3095      714348 :         ret = krb5_crypto_prf(context, crypto, &input2, &block);
    3096      714348 :         if (ret)
    3097           0 :             goto out;
    3098             : 
    3099      714348 :         if (block.length < length) {
    3100      353274 :             memcpy(p, block.data, block.length);
    3101      353274 :             length -= block.length;
    3102             :         } else {
    3103      361074 :             memcpy(p, block.data, length);
    3104      361074 :             length = 0;
    3105             :         }
    3106      714348 :         p += block.length;
    3107      714348 :         krb5_data_free(&block);
    3108             :     }
    3109             : 
    3110      361074 :  out:
    3111      361074 :     krb5_data_free(&input2);
    3112      361074 :     if (ret)
    3113           0 :         krb5_data_free(output);
    3114      361074 :     return ret;
    3115             : }
    3116             : 
    3117             : /**
    3118             :  * The FX-CF2 key derivation function, used in FAST and preauth framework.
    3119             :  *
    3120             :  * @param context Kerberos 5 context
    3121             :  * @param crypto1 first key to combine
    3122             :  * @param crypto2 second key to combine
    3123             :  * @param pepper1 factor to combine with first key to guarantee uniqueness
    3124             :  * @param pepper2 factor to combine with second key to guarantee uniqueness
    3125             :  * @param enctype the encryption type of the resulting key
    3126             :  * @param res allocated key, free with krb5_free_keyblock_contents()
    3127             :  *
    3128             :  * @return Return an error code or 0.
    3129             :  *
    3130             :  * @ingroup krb5_crypto
    3131             :  */
    3132             : 
    3133             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
    3134      180537 : krb5_crypto_fx_cf2(krb5_context context,
    3135             :                    const krb5_crypto crypto1,
    3136             :                    const krb5_crypto crypto2,
    3137             :                    krb5_data *pepper1,
    3138             :                    krb5_data *pepper2,
    3139             :                    krb5_enctype enctype,
    3140             :                    krb5_keyblock *res)
    3141             : {
    3142        6632 :     krb5_error_code ret;
    3143        6632 :     krb5_data os1, os2;
    3144        6632 :     size_t i, keysize;
    3145             : 
    3146      180537 :     memset(res, 0, sizeof(*res));
    3147      180537 :     krb5_data_zero(&os1);
    3148      180537 :     krb5_data_zero(&os2);
    3149             : 
    3150      180537 :     ret = krb5_enctype_keybits(context, enctype, &keysize);
    3151      180537 :     if (ret)
    3152           0 :         return ret;
    3153      180537 :     keysize = (keysize + 7) / 8;
    3154             : 
    3155      180537 :     ret = krb5_crypto_prfplus(context, crypto1, pepper1, keysize, &os1);
    3156      180537 :     if (ret)
    3157           0 :         goto out;
    3158      180537 :     ret = krb5_crypto_prfplus(context, crypto2, pepper2, keysize, &os2);
    3159      180537 :     if (ret)
    3160           0 :         goto out;
    3161             : 
    3162      180537 :     res->keytype = enctype;
    3163             :     {
    3164      180537 :         unsigned char *p1 = os1.data, *p2 = os2.data;
    3165     5895321 :         for (i = 0; i < keysize; i++)
    3166     5714784 :             p1[i] ^= p2[i];
    3167             :     }
    3168      180537 :     ret = krb5_random_to_key(context, enctype, os1.data, keysize, res);
    3169      180537 :  out:
    3170      180537 :     krb5_data_free(&os1);
    3171      180537 :     krb5_data_free(&os2);
    3172             : 
    3173      180537 :     return ret;
    3174             : }
    3175             : 
    3176             : KRB5_LIB_FUNCTION void KRB5_LIB_CALL
    3177      105538 : _krb5_crypto_set_flags(krb5_context context,
    3178             :                        krb5_crypto crypto,
    3179             :                        krb5_flags flags)
    3180             : {
    3181      105538 :     crypto->flags |= flags;
    3182      105538 : }
    3183             : 
    3184             : #ifndef HEIMDAL_SMALLER
    3185             : 
    3186             : /**
    3187             :  * Deprecated: keytypes don't exist, they are really enctypes.
    3188             :  *
    3189             :  * @ingroup krb5_deprecated
    3190             :  */
    3191             : 
    3192             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
    3193           0 : krb5_keytype_to_enctypes (krb5_context context,
    3194             :                           krb5_keytype keytype,
    3195             :                           unsigned *len,
    3196             :                           krb5_enctype **val)
    3197             :     KRB5_DEPRECATED_FUNCTION("Use X instead")
    3198             : {
    3199           0 :     int i;
    3200           0 :     unsigned n = 0;
    3201           0 :     krb5_enctype *ret;
    3202             : 
    3203           0 :     for (i = _krb5_num_etypes - 1; i >= 0; --i) {
    3204           0 :         if (_krb5_etypes[i]->keytype->type == keytype
    3205           0 :             && !(_krb5_etypes[i]->flags & F_PSEUDO)
    3206           0 :             && krb5_enctype_valid(context, _krb5_etypes[i]->type) == 0)
    3207           0 :             ++n;
    3208             :     }
    3209           0 :     if (n == 0) {
    3210           0 :         krb5_set_error_message(context, KRB5_PROG_KEYTYPE_NOSUPP,
    3211             :                                "Keytype has no mapping");
    3212           0 :         return KRB5_PROG_KEYTYPE_NOSUPP;
    3213             :     }
    3214             : 
    3215           0 :     ret = malloc(n * sizeof(*ret));
    3216           0 :     if (ret == NULL && n != 0)
    3217           0 :         return krb5_enomem(context);
    3218           0 :     n = 0;
    3219           0 :     for (i = _krb5_num_etypes - 1; i >= 0; --i) {
    3220           0 :         if (_krb5_etypes[i]->keytype->type == keytype
    3221           0 :             && !(_krb5_etypes[i]->flags & F_PSEUDO)
    3222           0 :             && krb5_enctype_valid(context, _krb5_etypes[i]->type) == 0)
    3223           0 :             ret[n++] = _krb5_etypes[i]->type;
    3224             :     }
    3225           0 :     *len = n;
    3226           0 :     *val = ret;
    3227           0 :     return 0;
    3228             : }
    3229             : 
    3230             : /**
    3231             :  * Deprecated: keytypes don't exist, they are really enctypes.
    3232             :  *
    3233             :  * @ingroup krb5_deprecated
    3234             :  */
    3235             : 
    3236             : /* if two enctypes have compatible keys */
    3237             : KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL
    3238           0 : krb5_enctypes_compatible_keys(krb5_context context,
    3239             :                               krb5_enctype etype1,
    3240             :                               krb5_enctype etype2)
    3241             :     KRB5_DEPRECATED_FUNCTION("Use X instead")
    3242             : {
    3243           0 :     struct _krb5_encryption_type *e1 = _krb5_find_enctype(etype1);
    3244           0 :     struct _krb5_encryption_type *e2 = _krb5_find_enctype(etype2);
    3245           0 :     return e1 != NULL && e2 != NULL && e1->keytype == e2->keytype;
    3246             : }
    3247             : 
    3248             : #endif /* HEIMDAL_SMALLER */

Generated by: LCOV version 1.14