LCOV - code coverage report
Current view: top level - third_party/heimdal/lib/krb5 - crypto.c (source / functions) Hit Total Coverage
Test: coverage report for v4-17-test 1498b464 Lines: 702 1466 47.9 %
Date: 2024-06-13 04:01:37 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      135984 : unsupported_enctype(krb5_context context, krb5_enctype etype)
      63             : {
      64             :     krb5_error_code ret;
      65             :     char *name;
      66             : 
      67      135984 :     ret = krb5_enctype_to_string(context, etype, &name);
      68      135984 :     if (ret)
      69      135984 :         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      591863 : krb5_enctype_keysize(krb5_context context,
      84             :                      krb5_enctype type,
      85             :                      size_t *keysize)
      86             : {
      87      591863 :     struct _krb5_encryption_type *et = _krb5_find_enctype(type);
      88      591863 :     if(et == NULL) {
      89           0 :         return unsupported_enctype (context, type);
      90             :     }
      91      591863 :     *keysize = et->keytype->size;
      92      591863 :     return 0;
      93             : }
      94             : 
      95             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
      96      131047 : krb5_enctype_keybits(krb5_context context,
      97             :                      krb5_enctype type,
      98             :                      size_t *keybits)
      99             : {
     100      131047 :     struct _krb5_encryption_type *et = _krb5_find_enctype(type);
     101      131047 :     if(et == NULL) {
     102           0 :         return unsupported_enctype (context, type);
     103             :     }
     104      131047 :     *keybits = et->keytype->bits;
     105      131047 :     return 0;
     106             : }
     107             : 
     108             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
     109      186269 : krb5_generate_random_keyblock(krb5_context context,
     110             :                               krb5_enctype type,
     111             :                               krb5_keyblock *key)
     112             : {
     113             :     krb5_error_code ret;
     114      186269 :     struct _krb5_encryption_type *et = _krb5_find_enctype(type);
     115      186269 :     if(et == NULL) {
     116           0 :         return unsupported_enctype (context, type);
     117             :     }
     118      186269 :     ret = krb5_data_alloc(&key->keyvalue, et->keytype->size);
     119      186269 :     if(ret)
     120           0 :         return ret;
     121      186269 :     key->keytype = type;
     122      186269 :     if(et->keytype->random_key)
     123           0 :         (*et->keytype->random_key)(context, key);
     124             :     else
     125      186269 :         krb5_generate_random_block(key->keyvalue.data,
     126             :                                    key->keyvalue.length);
     127      186269 :     return 0;
     128             : }
     129             : 
     130             : static krb5_error_code
     131     9510564 : _key_schedule(krb5_context context,
     132             :               struct _krb5_key_data *key)
     133             : {
     134             :     krb5_error_code ret;
     135             :     struct _krb5_encryption_type *et;
     136             :     struct _krb5_key_type *kt;
     137             : 
     138     9510564 :     if (key->schedule != NULL)
     139     5192773 :         return 0;
     140             : 
     141     4317791 :     et = _krb5_find_enctype(key->key->keytype);
     142             : 
     143     4317791 :     if (et == NULL) {
     144           0 :         return unsupported_enctype (context,
     145           0 :                                key->key->keytype);
     146             :     }
     147             : 
     148     4317791 :     kt = et->keytype;
     149             : 
     150     4317791 :     if(kt->schedule == NULL)
     151           0 :         return 0;
     152     4317791 :     ALLOC(key->schedule, 1);
     153     4317791 :     if (key->schedule == NULL)
     154           0 :         return krb5_enomem(context);
     155     4317791 :     ret = krb5_data_alloc(key->schedule, kt->schedule_size);
     156     4317791 :     if(ret) {
     157           0 :         free(key->schedule);
     158           0 :         key->schedule = NULL;
     159           0 :         return ret;
     160             :     }
     161     4317791 :     (*kt->schedule)(context, kt, key);
     162     4317791 :     return 0;
     163             : }
     164             : 
     165             : /************************************************************
     166             :  *                                                          *
     167             :  ************************************************************/
     168             : 
     169             : static krb5_error_code
     170      526619 : 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      526619 :     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      526619 :     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      526619 : 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      958994 : _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             :     unsigned char *ipad, *opad;
     221             :     unsigned char *key;
     222             :     struct krb5_crypto_iov *working;
     223             :     size_t key_len;
     224             :     size_t i;
     225             : 
     226      958994 :     ipad = malloc(cm->blocksize);
     227      958994 :     if (ipad == NULL)
     228           0 :         return ENOMEM;
     229             : 
     230      958994 :     opad = malloc(cm->blocksize + cm->checksumsize);
     231      958994 :     if (opad == NULL) {
     232           0 :         free(ipad);
     233           0 :         return ENOMEM;
     234             :     }
     235             : 
     236      958994 :     working = calloc(niov + 1, sizeof(struct krb5_crypto_iov));
     237      958994 :     if (working == NULL) {
     238           0 :         free(ipad);
     239           0 :         free(opad);
     240           0 :         return ENOMEM;
     241             :     }
     242             : 
     243      958994 :     memset(ipad, 0x36, cm->blocksize);
     244      958994 :     memset(opad, 0x5c, cm->blocksize);
     245             : 
     246      958994 :     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      958994 :         key = keyblock->key->keyvalue.data;
     260      958994 :         key_len = keyblock->key->keyvalue.length;
     261             :     }
     262    16302914 :     for(i = 0; i < key_len; i++){
     263    15343920 :         ipad[i] ^= key[i];
     264    15343920 :         opad[i] ^= key[i];
     265             :     }
     266             : 
     267      958994 :     working[0].data.data = ipad;
     268      958994 :     working[0].data.length = cm->blocksize;
     269      958994 :     working[0].flags = KRB5_CRYPTO_TYPE_DATA;
     270     1917988 :     for (i = 0; i < niov; i++)
     271      958994 :         working[i + 1] = iov[i];
     272             : 
     273      958994 :     (*cm->checksum)(context, crypto, keyblock, usage, working, niov + 1, result);
     274      958994 :     memcpy(opad + cm->blocksize, result->checksum.data,
     275             :            result->checksum.length);
     276             : 
     277      958994 :     working[0].data.data = opad;
     278      958994 :     working[0].data.length = cm->blocksize + cm->checksumsize;
     279      958994 :     working[0].flags = KRB5_CRYPTO_TYPE_DATA;
     280      958994 :     (*cm->checksum)(context, crypto, keyblock, usage, working, 1, result);
     281      958994 :     memset(ipad, 0, cm->blocksize);
     282      958994 :     free(ipad);
     283      958994 :     memset(opad, 0, cm->blocksize + cm->checksumsize);
     284      958994 :     free(opad);
     285      958994 :     free(working);
     286             : 
     287      958994 :     return 0;
     288             : }
     289             : 
     290             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
     291      958994 : _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             :     struct krb5_crypto_iov iov[1];
     301             : 
     302      958994 :     iov[0].data.data = (void *) data;
     303      958994 :     iov[0].data.length = len;
     304      958994 :     iov[0].flags = KRB5_CRYPTO_TYPE_DATA;
     305      958994 :     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      487394 : 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      487394 :     struct _krb5_checksum_type *c = _krb5_find_checksum(cktype);
     319             :     struct _krb5_key_data kd;
     320             : 
     321             :     krb5_error_code ret;
     322             : 
     323      487394 :     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      487394 :     kd.key = key;
     331      487394 :     kd.schedule = NULL;
     332             : 
     333      487394 :     ret = _krb5_internal_hmac(context, NULL, c, data, len, usage, &kd, result);
     334             : 
     335      487394 :     if (kd.schedule)
     336           0 :         krb5_free_data(context, kd.schedule);
     337             : 
     338      487394 :     return ret;
     339             : }
     340             : 
     341             : krb5_error_code
     342     2303992 : _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             :     krb5_error_code ret;
     351             :     unsigned char hmac[EVP_MAX_MD_SIZE];
     352     2303992 :     unsigned int hmaclen = sizeof(hmac);
     353             : 
     354     2303992 :     ret = _krb5_evp_hmac_iov(context, crypto, key, iov, niov, hmac, &hmaclen,
     355             :                              EVP_sha1(), NULL);
     356     2303992 :     if (ret)
     357           0 :         return ret;
     358             : 
     359     2303992 :     heim_assert(result->checksum.length <= hmaclen,
     360             :                 "SHA1 checksum too short");
     361     2303992 :     memcpy(result->checksum.data, hmac, result->checksum.length);
     362             : 
     363     2303992 :     return 0;
     364             : }
     365             : 
     366             : krb5_error_code
     367     1570650 : _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             :     krb5_error_code ret;
     376             :     unsigned char hmac[EVP_MAX_MD_SIZE];
     377     1570650 :     unsigned int hmaclen = sizeof(hmac);
     378             :     krb5_data data;
     379             : 
     380     1570650 :     ret = _krb5_evp_hmac_iov(context, crypto, key, iov, niov, hmac, &hmaclen,
     381             :                              EVP_sha1(), NULL);
     382     1570650 :     if (ret)
     383           0 :         return ret;
     384             : 
     385     1570650 :     data.data = hmac;
     386     1570650 :     data.length = min(hmaclen, verify->checksum.length);
     387             : 
     388     1570650 :     if(krb5_data_ct_cmp(&data, &verify->checksum) != 0)
     389         325 :         return KRB5KRB_AP_ERR_BAD_INTEGRITY;
     390             : 
     391     1570325 :     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     3622928 : _krb5_find_checksum(krb5_cksumtype type)
     412             : {
     413             :     int i;
     414    22616542 :     for(i = 0; i < _krb5_num_checksums; i++)
     415    22616528 :         if(_krb5_checksum_types[i]->type == type)
     416     3622914 :             return _krb5_checksum_types[i];
     417          14 :     return NULL;
     418             : }
     419             : 
     420             : static krb5_error_code
     421     4016558 : 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     4016558 :     krb5_error_code ret = 0;
     428     4016558 :     struct _krb5_checksum_type *kct = NULL;
     429             : 
     430     4016558 :     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     4016558 :     kct = crypto->et->keyed_checksum;
     438     4016558 :     if (kct == NULL || kct->type != ct->type) {
     439         208 :         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     4016454 :     if(ct->flags & F_DERIVED)
     448     3874642 :         ret = _get_derived_key(context, crypto, usage, key);
     449      141812 :     else if(ct->flags & F_VARIANT) {
     450             :         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      141812 :         *key = &crypto->key;
     462             :     }
     463     4016454 :     if(ret == 0)
     464     4016454 :         ret = _key_schedule(context, *key);
     465     4016454 :     return ret;
     466             : }
     467             : 
     468             : static krb5_error_code
     469     2449014 : 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             :     krb5_error_code ret;
     479             :     struct _krb5_key_data *dkey;
     480             : 
     481     2449014 :     if (ct->flags & F_DISABLED) {
     482           0 :         krb5_clear_error_message (context);
     483           0 :         return KRB5_PROG_SUMTYPE_NOSUPP;
     484             :     }
     485     2449014 :     if (ct->flags & F_KEYED) {
     486     2444286 :         ret = get_checksum_key(context, crypto, usage, ct, &dkey);
     487     2444286 :         if (ret)
     488           0 :             return ret;
     489        4728 :     } else if ((flags & KRB5_CRYPTO_FLAG_ALLOW_UNKEYED_CHECKSUM) == 0) {
     490           0 :         return EINVAL;
     491             :     } else
     492        4728 :         dkey = NULL;
     493             : 
     494     2449014 :     result->cksumtype = ct->type;
     495             : 
     496     2449014 :     return (*ct->checksum)(context, crypto, dkey, usage, iov, niov, result);
     497             : }
     498             : 
     499             : static krb5_error_code
     500     1390704 : 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             :     int ret;
     510             :     struct krb5_crypto_iov iov[1];
     511             : 
     512     1390704 :     ret = krb5_data_alloc(&result->checksum, ct->checksumsize);
     513     1390704 :     if (ret)
     514           0 :         return ret;
     515             : 
     516     1390704 :     iov[0].data.data = data;
     517     1390704 :     iov[0].data.length = len;
     518     1390704 :     iov[0].flags = KRB5_CRYPTO_TYPE_DATA;
     519             : 
     520     1390704 :     return create_checksum_iov(context, ct, crypto, usage, iov, 1, flags, result);
     521             : }
     522             : 
     523             : static int
     524      908439 : arcfour_checksum_p(struct _krb5_checksum_type *ct, krb5_crypto crypto)
     525             : {
     526     1050355 :     return (ct->type == CKSUMTYPE_HMAC_MD5) &&
     527      141916 :         (crypto->key.key->keytype == KEYTYPE_ARCFOUR);
     528             : }
     529             : 
     530             : static inline krb5_flags
     531      908439 : crypto_flags(krb5_crypto crypto)
     532             : {
     533             :     /* If caller didn't specify a key, unkeyed checksums are the only option */
     534      908439 :     if (crypto == NULL)
     535          77 :         return KRB5_CRYPTO_FLAG_ALLOW_UNKEYED_CHECKSUM;
     536             :     else
     537      908362 :         return crypto->flags;
     538             : }
     539             : 
     540             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
     541      553802 : 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      553802 :     struct _krb5_checksum_type *ct = NULL;
     550             :     unsigned keyusage;
     551             : 
     552             :     /* type 0 -> pick from crypto */
     553      553802 :     if (type) {
     554        4728 :         ct = _krb5_find_checksum(type);
     555      549074 :     } else if (crypto) {
     556      549074 :         ct = crypto->et->keyed_checksum;
     557      549074 :         if (ct == NULL)
     558           0 :             ct = crypto->et->checksum;
     559             :     }
     560             : 
     561      553802 :     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      553802 :     if (arcfour_checksum_p(ct, crypto)) {
     569      140294 :         keyusage = usage;
     570      140294 :         _krb5_usage2arcfour(context, &keyusage);
     571             :     } else
     572      413508 :         keyusage = CHECKSUM_USAGE(usage);
     573             : 
     574      553802 :     return create_checksum(context, ct, crypto, keyusage, data, len,
     575             :                            crypto_flags(crypto), result);
     576             : }
     577             : 
     578             : static krb5_error_code
     579     1575974 : 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             :     krb5_error_code ret;
     588             :     struct _krb5_key_data *dkey;
     589             :     Checksum c;
     590             :     struct _krb5_checksum_type *ct;
     591             : 
     592     1575974 :     ct = _krb5_find_checksum(cksum->cksumtype);
     593     1575974 :     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     1575974 :     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     1575974 :     if (ct->flags & F_KEYED) {
     610     1572272 :         ret = get_checksum_key(context, crypto, usage, ct, &dkey);
     611     1572272 :         if (ret)
     612         104 :             return ret;
     613        3702 :     } 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_BAD_INTEGRITY,
     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        3702 :         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     1575870 :     if(ct->verify) {
     629     1570650 :         ret = (*ct->verify)(context, crypto, dkey, usage, iov, niov, cksum);
     630     1570650 :         if (ret)
     631         975 :             krb5_set_error_message(context, ret,
     632         325 :                                    N_("Decrypt integrity check failed for checksum "
     633             :                                       "type %s, key type %s", ""),
     634         325 :                                    ct->name, (crypto != NULL)? crypto->et->name : "(none)");
     635     1570650 :         return ret;
     636             :     }
     637             : 
     638        5220 :     ret = krb5_data_alloc (&c.checksum, ct->checksumsize);
     639        5220 :     if (ret)
     640           0 :         return ret;
     641             : 
     642        5220 :     ret = (*ct->checksum)(context, crypto, dkey, usage, iov, niov, &c);
     643        5220 :     if (ret) {
     644           0 :         krb5_data_free(&c.checksum);
     645           0 :         return ret;
     646             :     }
     647             : 
     648        5220 :     if(krb5_data_ct_cmp(&c.checksum, &cksum->checksum) != 0) {
     649          27 :         ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
     650          81 :         krb5_set_error_message(context, ret,
     651          27 :                                N_("Decrypt integrity check failed for checksum "
     652             :                                   "type %s, key type %s", ""),
     653          27 :                                ct->name, crypto ? crypto->et->name : "(unkeyed)");
     654             :     } else {
     655        5193 :         ret = 0;
     656             :     }
     657        5220 :     krb5_data_free (&c.checksum);
     658        5220 :     return ret;
     659             : }
     660             : 
     661             : static krb5_error_code
     662     1239141 : 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             :     struct krb5_crypto_iov iov[1];
     671             : 
     672     1239141 :     iov[0].data.data = data;
     673     1239141 :     iov[0].data.length = len;
     674     1239141 :     iov[0].flags = KRB5_CRYPTO_TYPE_DATA;
     675             : 
     676     1239141 :     return verify_checksum_iov(context, crypto, usage, iov, 1, flags, cksum);
     677             : }
     678             : 
     679             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
     680      354639 : 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             :     struct _krb5_checksum_type *ct;
     688             :     unsigned keyusage;
     689             : 
     690      354639 :     ct = _krb5_find_checksum(cksum->cksumtype);
     691      354639 :     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      354637 :     if (arcfour_checksum_p(ct, crypto)) {
     699        1518 :         keyusage = usage;
     700        1518 :         _krb5_usage2arcfour(context, &keyusage);
     701             :     } else
     702      353119 :         keyusage = CHECKSUM_USAGE(usage);
     703             : 
     704      354637 :     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      841971 : krb5_crypto_get_checksum_type(krb5_context context,
     710             :                               krb5_crypto crypto,
     711             :                               krb5_cksumtype *type)
     712             : {
     713      841971 :     struct _krb5_checksum_type *ct = NULL;
     714             : 
     715      841971 :     if (crypto != NULL) {
     716      841971 :         ct = crypto->et->keyed_checksum;
     717      841971 :         if (ct == NULL)
     718           0 :             ct = crypto->et->checksum;
     719             :     }
     720             : 
     721      841971 :     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      841971 :     *type = ct->type;
     728             : 
     729      841971 :     return 0;
     730             : }
     731             : 
     732             : 
     733             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
     734      755204 : krb5_checksumsize(krb5_context context,
     735             :                   krb5_cksumtype type,
     736             :                   size_t *size)
     737             : {
     738      755204 :     struct _krb5_checksum_type *ct = _krb5_find_checksum(type);
     739      755204 :     if(ct == NULL) {
     740          10 :         krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
     741          10 :                                 N_("checksum type %d not supported", ""),
     742             :                                 type);
     743          10 :         return KRB5_PROG_SUMTYPE_NOSUPP;
     744             :     }
     745      755194 :     *size = ct->checksumsize;
     746      755194 :     return 0;
     747             : }
     748             : 
     749             : KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL
     750      190633 : krb5_checksum_is_keyed(krb5_context context,
     751             :                        krb5_cksumtype type)
     752             : {
     753      190633 :     struct _krb5_checksum_type *ct = _krb5_find_checksum(type);
     754      190633 :     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      190631 :     return ct->flags & F_KEYED;
     762             : }
     763             : 
     764             : KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL
     765       37242 : krb5_checksum_is_collision_proof(krb5_context context,
     766             :                                  krb5_cksumtype type)
     767             : {
     768       37242 :     struct _krb5_checksum_type *ct = _krb5_find_checksum(type);
     769       37242 :     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       37242 :     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     9244327 : _krb5_find_enctype(krb5_enctype type)
     801             : {
     802             :     int i;
     803    34075715 :     for(i = 0; i < _krb5_num_etypes; i++)
     804    33803629 :         if(_krb5_etypes[i]->type == type)
     805     8972241 :             return _krb5_etypes[i];
     806      272086 :     return NULL;
     807             : }
     808             : 
     809             : 
     810             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
     811      579887 : krb5_enctype_to_string(krb5_context context,
     812             :                        krb5_enctype etype,
     813             :                        char **string)
     814             : {
     815             :     struct _krb5_encryption_type *e;
     816      579887 :     e = _krb5_find_enctype(etype);
     817      579887 :     if(e == NULL) {
     818      135990 :         krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
     819      135990 :                                 N_("encryption type %d not supported", ""),
     820             :                                 etype);
     821      135990 :         *string = NULL;
     822      135990 :         return KRB5_PROG_ETYPE_NOSUPP;
     823             :     }
     824      443897 :     *string = strdup(e->name);
     825      443897 :     if (*string == NULL)
     826           0 :         return krb5_enomem(context);
     827      443897 :     return 0;
     828             : }
     829             : 
     830             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
     831      391770 : krb5_string_to_enctype(krb5_context context,
     832             :                        const char *string,
     833             :                        krb5_enctype *etype)
     834             : {
     835             :     int i;
     836     3777566 :     for(i = 0; i < _krb5_num_etypes; i++) {
     837     3517658 :         if(strcasecmp(_krb5_etypes[i]->name, string) == 0){
     838      131862 :             *etype = _krb5_etypes[i]->type;
     839      131862 :             return 0;
     840             :         }
     841     5210864 :         if(_krb5_etypes[i]->alias != NULL &&
     842     1825068 :            strcasecmp(_krb5_etypes[i]->alias, string) == 0){
     843           0 :             *etype = _krb5_etypes[i]->type;
     844           0 :             return 0;
     845             :         }
     846             :     }
     847      259908 :     krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
     848      259908 :                             N_("encryption type %s not supported", ""),
     849             :                             string);
     850      259908 :     return KRB5_PROG_ETYPE_NOSUPP;
     851             : }
     852             : 
     853             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
     854       28926 : krb5_enctype_to_keytype(krb5_context context,
     855             :                         krb5_enctype etype,
     856             :                         krb5_keytype *keytype)
     857             : {
     858       28926 :     struct _krb5_encryption_type *e = _krb5_find_enctype(etype);
     859       28926 :     if(e == NULL) {
     860           0 :         return unsupported_enctype (context, etype);
     861             :     }
     862       28926 :     *keytype = e->keytype->type; /* XXX */
     863       28926 :     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     1120922 : krb5_enctype_valid(krb5_context context,
     878             :                    krb5_enctype etype)
     879             : {
     880     1120922 :     struct _krb5_encryption_type *e = _krb5_find_enctype(etype);
     881     1120922 :     if(e && (e->flags & F_DISABLED) == 0)
     882      984938 :         return 0;
     883      135984 :     if (context == NULL)
     884           0 :         return KRB5_PROG_ETYPE_NOSUPP;
     885      135984 :     if(e == NULL) {
     886      135984 :         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          90 : krb5_cksumtype_to_enctype(krb5_context context,
     910             :                           krb5_cksumtype ctype,
     911             :                           krb5_enctype *etype)
     912             : {
     913             :     int i;
     914             : 
     915          90 :     *etype = ETYPE_NULL;
     916             : 
     917         494 :     for(i = 0; i < _krb5_num_etypes; i++) {
     918         876 :         if(_krb5_etypes[i]->keyed_checksum &&
     919         410 :            _krb5_etypes[i]->keyed_checksum->type == ctype)
     920             :             {
     921          62 :                 *etype = _krb5_etypes[i]->type;
     922          62 :                 return 0;
     923             :             }
     924             :     }
     925             : 
     926          28 :     krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
     927          28 :                             N_("checksum type %d not supported", ""),
     928             :                             (int)ctype);
     929          28 :     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     6377966 : derived_crypto(krb5_context context,
     955             :                krb5_crypto crypto)
     956             : {
     957     6377966 :     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      836902 : 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             :     size_t sz, block_sz, checksum_sz, total_sz;
     973             :     Checksum cksum;
     974             :     unsigned char *p, *q;
     975             :     krb5_error_code ret;
     976             :     struct _krb5_key_data *dkey;
     977      836902 :     const struct _krb5_encryption_type *et = crypto->et;
     978             : 
     979      836902 :     checksum_sz = CHECKSUMSIZE(et->keyed_checksum);
     980             : 
     981      836902 :     sz = et->confoundersize + len;
     982      836902 :     block_sz = (sz + et->padsize - 1) &~ (et->padsize - 1); /* pad */
     983      836902 :     total_sz = block_sz + checksum_sz;
     984      836902 :     p = calloc(1, total_sz);
     985      836902 :     if (p == NULL)
     986           0 :         return krb5_enomem(context);
     987             : 
     988      836902 :     q = p;
     989      836902 :     krb5_generate_random_block(q, et->confoundersize); /* XXX */
     990      836902 :     q += et->confoundersize;
     991      836902 :     memcpy(q, data, len);
     992             : 
     993      836902 :     ret = create_checksum(context,
     994             :                           et->keyed_checksum,
     995             :                           crypto,
     996      836902 :                           INTEGRITY_USAGE(usage),
     997             :                           p,
     998             :                           block_sz,
     999             :                           0,
    1000             :                           &cksum);
    1001      836902 :     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      836902 :     if(ret)
    1007           0 :         goto fail;
    1008      836902 :     memcpy(p + block_sz, cksum.checksum.data, cksum.checksum.length);
    1009      836902 :     free_Checksum (&cksum);
    1010      836902 :     ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey);
    1011      836902 :     if(ret)
    1012           0 :         goto fail;
    1013      836902 :     ret = _key_schedule(context, dkey);
    1014      836902 :     if(ret)
    1015           0 :         goto fail;
    1016      836902 :     ret = (*et->encrypt)(context, dkey, p, block_sz, 1, usage, ivec);
    1017      836902 :     if (ret)
    1018           0 :         goto fail;
    1019      836902 :     result->data = p;
    1020      836902 :     result->length = total_sz;
    1021      836902 :     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             :     size_t sz, block_sz, checksum_sz, total_sz;
    1038             :     Checksum cksum;
    1039           0 :     unsigned char *p, *q, *ivc = NULL;
    1040             :     krb5_error_code ret;
    1041             :     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             :                           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             :     size_t sz, block_sz, checksum_sz;
    1118             :     Checksum cksum;
    1119             :     unsigned char *p, *q;
    1120             :     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             :                           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       24544 : 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       24544 :     struct _krb5_encryption_type *et = crypto->et;
    1183       24544 :     size_t cksum_sz = CHECKSUMSIZE(et->checksum);
    1184       24544 :     size_t sz = len + cksum_sz + et->confoundersize;
    1185             :     char *tmp, *p;
    1186             :     krb5_error_code ret;
    1187             : 
    1188       24544 :     tmp = malloc (sz);
    1189       24544 :     if (tmp == NULL)
    1190           0 :         return krb5_enomem(context);
    1191       24544 :     p = tmp;
    1192       24544 :     memset (p, 0, cksum_sz);
    1193       24544 :     p += cksum_sz;
    1194       24544 :     krb5_generate_random_block(p, et->confoundersize);
    1195       24544 :     p += et->confoundersize;
    1196       24544 :     memcpy (p, data, len);
    1197       24544 :     ret = (*et->encrypt)(context, &crypto->key, tmp, sz, TRUE, usage, ivec);
    1198       24544 :     if (ret) {
    1199           0 :         memset(tmp, 0, sz);
    1200           0 :         free(tmp);
    1201           0 :         return ret;
    1202             :     }
    1203       24544 :     result->data   = tmp;
    1204       24544 :     result->length = sz;
    1205       24544 :     return 0;
    1206             : }
    1207             : 
    1208             : static krb5_error_code
    1209      884504 : 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             :     size_t checksum_sz;
    1218             :     Checksum cksum;
    1219             :     unsigned char *p;
    1220             :     krb5_error_code ret;
    1221             :     struct _krb5_key_data *dkey;
    1222      884504 :     struct _krb5_encryption_type *et = crypto->et;
    1223             :     unsigned long l;
    1224             : 
    1225      884504 :     checksum_sz = CHECKSUMSIZE(et->keyed_checksum);
    1226      884504 :     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 + confunder", ""));
    1230           0 :         return KRB5_BAD_MSIZE;
    1231             :     }
    1232             : 
    1233      884504 :     if (((len - checksum_sz) % et->padsize) != 0) {
    1234           0 :         krb5_clear_error_message(context);
    1235           0 :         return KRB5_BAD_MSIZE;
    1236             :     }
    1237             : 
    1238      884504 :     p = malloc(len);
    1239      884504 :     if (len != 0 && p == NULL)
    1240           0 :         return krb5_enomem(context);
    1241      884504 :     memcpy(p, data, len);
    1242             : 
    1243      884504 :     len -= checksum_sz;
    1244             : 
    1245      884504 :     ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey);
    1246      884504 :     if(ret) {
    1247           0 :         free(p);
    1248           0 :         return ret;
    1249             :     }
    1250      884504 :     ret = _key_schedule(context, dkey);
    1251      884504 :     if(ret) {
    1252           0 :         free(p);
    1253           0 :         return ret;
    1254             :     }
    1255      884504 :     ret = (*et->encrypt)(context, dkey, p, len, 0, usage, ivec);
    1256      884504 :     if (ret) {
    1257           0 :         free(p);
    1258           0 :         return ret;
    1259             :     }
    1260             : 
    1261      884504 :     cksum.checksum.data   = p + len;
    1262      884504 :     cksum.checksum.length = checksum_sz;
    1263      884504 :     cksum.cksumtype       = CHECKSUMTYPE(et->keyed_checksum);
    1264             : 
    1265      884504 :     ret = verify_checksum(context,
    1266             :                           crypto,
    1267      884504 :                           INTEGRITY_USAGE(usage),
    1268             :                           p,
    1269             :                           len,
    1270             :                           0,
    1271             :                           &cksum);
    1272      884504 :     if(ret) {
    1273         279 :         free(p);
    1274         279 :         return ret;
    1275             :     }
    1276      884225 :     l = len - et->confoundersize;
    1277      884225 :     memmove(p, p + et->confoundersize, l);
    1278      884225 :     result->data = realloc(p, l);
    1279      884225 :     if(result->data == NULL && l != 0) {
    1280           0 :         free(p);
    1281           0 :         return krb5_enomem(context);
    1282             :     }
    1283      884225 :     result->length = l;
    1284      884225 :     return 0;
    1285             : }
    1286             : 
    1287             : static krb5_error_code
    1288           0 : decrypt_internal_enc_then_cksum(krb5_context context,
    1289             :                                 krb5_crypto crypto,
    1290             :                                 unsigned usage,
    1291             :                                 void *data,
    1292             :                                 size_t len,
    1293             :                                 krb5_data *result,
    1294             :                                 void *ivec)
    1295             : {
    1296             :     size_t checksum_sz;
    1297             :     Checksum cksum;
    1298             :     unsigned char *p;
    1299             :     krb5_error_code ret;
    1300             :     struct _krb5_key_data *dkey;
    1301           0 :     struct _krb5_encryption_type *et = crypto->et;
    1302             :     unsigned long l;
    1303             : 
    1304           0 :     checksum_sz = CHECKSUMSIZE(et->keyed_checksum);
    1305           0 :     if (len < checksum_sz + et->confoundersize) {
    1306           0 :         krb5_set_error_message(context, KRB5_BAD_MSIZE,
    1307           0 :                                N_("Encrypted data shorter then "
    1308             :                                   "checksum + confunder", ""));
    1309           0 :         return KRB5_BAD_MSIZE;
    1310             :     }
    1311             : 
    1312           0 :     if (((len - checksum_sz) % et->padsize) != 0) {
    1313           0 :         krb5_clear_error_message(context);
    1314           0 :         return KRB5_BAD_MSIZE;
    1315             :     }
    1316             : 
    1317           0 :     len -= checksum_sz;
    1318             : 
    1319           0 :     p = malloc(et->blocksize + len);
    1320           0 :     if (p == NULL)
    1321           0 :         return krb5_enomem(context);
    1322             : 
    1323           0 :     if (ivec)
    1324           0 :         memcpy(p, ivec, et->blocksize);
    1325             :     else
    1326           0 :         memset(p, 0, et->blocksize);
    1327           0 :     memcpy(&p[et->blocksize], data, len);
    1328             : 
    1329           0 :     cksum.checksum.data   = (unsigned char *)data + len;
    1330           0 :     cksum.checksum.length = checksum_sz;
    1331           0 :     cksum.cksumtype       = CHECKSUMTYPE(et->keyed_checksum);
    1332             : 
    1333           0 :     ret = verify_checksum(context,
    1334             :                           crypto,
    1335           0 :                           INTEGRITY_USAGE(usage),
    1336             :                           p,
    1337           0 :                           et->blocksize + len,
    1338             :                           0,
    1339             :                           &cksum);
    1340           0 :     if(ret) {
    1341           0 :         free(p);
    1342           0 :         return ret;
    1343             :     }
    1344             : 
    1345           0 :     ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey);
    1346           0 :     if(ret) {
    1347           0 :         free(p);
    1348           0 :         return ret;
    1349             :     }
    1350           0 :     ret = _key_schedule(context, dkey);
    1351           0 :     if(ret) {
    1352           0 :         free(p);
    1353           0 :         return ret;
    1354             :     }
    1355           0 :     ret = (*et->encrypt)(context, dkey, &p[et->blocksize], len, 0, usage, ivec);
    1356           0 :     if (ret) {
    1357           0 :         free(p);
    1358           0 :         return ret;
    1359             :     }
    1360             : 
    1361           0 :     l = len - et->confoundersize;
    1362           0 :     memmove(p, p + et->blocksize + et->confoundersize, l);
    1363           0 :     result->data = realloc(p, l);
    1364           0 :     if(result->data == NULL && l != 0) {
    1365           0 :         free(p);
    1366           0 :         return krb5_enomem(context);
    1367             :     }
    1368           0 :     result->length = l;
    1369           0 :     return 0;
    1370             : }
    1371             : 
    1372             : static krb5_error_code
    1373           0 : decrypt_internal(krb5_context context,
    1374             :                  krb5_crypto crypto,
    1375             :                  void *data,
    1376             :                  size_t len,
    1377             :                  krb5_data *result,
    1378             :                  void *ivec)
    1379             : {
    1380             :     krb5_error_code ret;
    1381             :     unsigned char *p;
    1382             :     Checksum cksum;
    1383             :     size_t checksum_sz, l;
    1384           0 :     struct _krb5_encryption_type *et = crypto->et;
    1385             : 
    1386           0 :     if ((len % et->padsize) != 0) {
    1387           0 :         krb5_clear_error_message(context);
    1388           0 :         return KRB5_BAD_MSIZE;
    1389             :     }
    1390           0 :     checksum_sz = CHECKSUMSIZE(et->checksum);
    1391           0 :     if (len < checksum_sz + et->confoundersize) {
    1392           0 :         krb5_set_error_message(context, KRB5_BAD_MSIZE,
    1393           0 :                                N_("Encrypted data shorter then "
    1394             :                                   "checksum + confunder", ""));
    1395           0 :         return KRB5_BAD_MSIZE;
    1396             :     }
    1397             : 
    1398           0 :     p = malloc(len);
    1399           0 :     if (len != 0 && p == NULL)
    1400           0 :         return krb5_enomem(context);
    1401           0 :     memcpy(p, data, len);
    1402             : 
    1403           0 :     ret = _key_schedule(context, &crypto->key);
    1404           0 :     if(ret) {
    1405           0 :         free(p);
    1406           0 :         return ret;
    1407             :     }
    1408           0 :     ret = (*et->encrypt)(context, &crypto->key, p, len, 0, 0, ivec);
    1409           0 :     if (ret) {
    1410           0 :         free(p);
    1411           0 :         return ret;
    1412             :     }
    1413           0 :     ret = krb5_data_copy(&cksum.checksum, p + et->confoundersize, checksum_sz);
    1414           0 :     if(ret) {
    1415           0 :         free(p);
    1416           0 :         return ret;
    1417             :     }
    1418           0 :     memset(p + et->confoundersize, 0, checksum_sz);
    1419           0 :     cksum.cksumtype = CHECKSUMTYPE(et->checksum);
    1420           0 :     ret = verify_checksum(context, NULL, 0, p, len,
    1421             :                           KRB5_CRYPTO_FLAG_ALLOW_UNKEYED_CHECKSUM, &cksum);
    1422           0 :     free_Checksum(&cksum);
    1423           0 :     if(ret) {
    1424           0 :         free(p);
    1425           0 :         return ret;
    1426             :     }
    1427           0 :     l = len - et->confoundersize - checksum_sz;
    1428           0 :     memmove(p, p + et->confoundersize + checksum_sz, l);
    1429           0 :     result->data = realloc(p, l);
    1430           0 :     if(result->data == NULL && l != 0) {
    1431           0 :         free(p);
    1432           0 :         return krb5_enomem(context);
    1433             :     }
    1434           0 :     result->length = l;
    1435           0 :     return 0;
    1436             : }
    1437             : 
    1438             : static krb5_error_code
    1439       20510 : decrypt_internal_special(krb5_context context,
    1440             :                          krb5_crypto crypto,
    1441             :                          int usage,
    1442             :                          void *data,
    1443             :                          size_t len,
    1444             :                          krb5_data *result,
    1445             :                          void *ivec)
    1446             : {
    1447       20510 :     struct _krb5_encryption_type *et = crypto->et;
    1448       20510 :     size_t cksum_sz = CHECKSUMSIZE(et->checksum);
    1449       20510 :     size_t sz = len - cksum_sz - et->confoundersize;
    1450             :     unsigned char *p;
    1451             :     krb5_error_code ret;
    1452             : 
    1453       20510 :     if ((len % et->padsize) != 0) {
    1454           0 :         krb5_clear_error_message(context);
    1455           0 :         return KRB5_BAD_MSIZE;
    1456             :     }
    1457       20510 :     if (len < cksum_sz + et->confoundersize) {
    1458           0 :         krb5_set_error_message(context, KRB5_BAD_MSIZE,
    1459           0 :                                N_("Encrypted data shorter then "
    1460             :                                   "checksum + confunder", ""));
    1461           0 :         return KRB5_BAD_MSIZE;
    1462             :     }
    1463             : 
    1464       20510 :     p = malloc (len);
    1465       20510 :     if (p == NULL)
    1466           0 :         return krb5_enomem(context);
    1467       20510 :     memcpy(p, data, len);
    1468             : 
    1469       20510 :     ret = (*et->encrypt)(context, &crypto->key, p, len, FALSE, usage, ivec);
    1470       20510 :     if (ret) {
    1471          16 :         free(p);
    1472          16 :         return ret;
    1473             :     }
    1474             : 
    1475       20494 :     memmove (p, p + cksum_sz + et->confoundersize, sz);
    1476       20494 :     result->data = realloc(p, sz);
    1477       20494 :     if(result->data == NULL && sz != 0) {
    1478           0 :         free(p);
    1479           0 :         return krb5_enomem(context);
    1480             :     }
    1481       20494 :     result->length = sz;
    1482       20494 :     return 0;
    1483             : }
    1484             : 
    1485             : static krb5_crypto_iov *
    1486     3848596 : iov_find(krb5_crypto_iov *data, size_t num_data, unsigned type)
    1487             : {
    1488             :     size_t i;
    1489    19627624 :     for (i = 0; i < num_data; i++)
    1490    18569314 :         if (data[i].flags == type)
    1491     2790286 :             return &data[i];
    1492     1058310 :     return NULL;
    1493             : }
    1494             : 
    1495             : static size_t
    1496     1395143 : iov_enc_data_len(krb5_crypto_iov *data, int num_data)
    1497             : {
    1498             :     size_t i, len;
    1499             : 
    1500    11161144 :     for (len = 0, i = 0; i < num_data; i++) {
    1501     9766001 :         if (data[i].flags != KRB5_CRYPTO_TYPE_DATA)
    1502     6975715 :             continue;
    1503     2790286 :         len += data[i].data.length;
    1504             :     }
    1505             : 
    1506     1395143 :     return len;
    1507             : }
    1508             : 
    1509             : static size_t
    1510           0 : iov_sign_data_len(krb5_crypto_iov *data, int num_data)
    1511             : {
    1512             :     size_t i, len;
    1513             : 
    1514           0 :     for (len = 0, i = 0; i < num_data; i++) {
    1515             :         /* Can't use should_sign, because we must only count data, not
    1516             :          * header/trailer */
    1517           0 :         if (data[i].flags == KRB5_CRYPTO_TYPE_DATA ||
    1518           0 :             data[i].flags == KRB5_CRYPTO_TYPE_SIGN_ONLY)
    1519           0 :             len += data[i].data.length;
    1520             :     }
    1521             : 
    1522           0 :     return len;
    1523             : }
    1524             : 
    1525             : static krb5_error_code
    1526           0 : iov_coalesce(krb5_context context,
    1527             :              krb5_data *prefix,
    1528             :              krb5_crypto_iov *data,
    1529             :              int num_data,
    1530             :              krb5_boolean inc_sign_data,
    1531             :              krb5_data *out)
    1532             : {
    1533             :     unsigned char *p, *q;
    1534             :     krb5_crypto_iov *hiv, *piv;
    1535             :     size_t len;
    1536             :     unsigned int i;
    1537             : 
    1538           0 :     hiv = iov_find(data, num_data, KRB5_CRYPTO_TYPE_HEADER);
    1539             : 
    1540           0 :     piv = iov_find(data, num_data, KRB5_CRYPTO_TYPE_PADDING);
    1541             : 
    1542           0 :     len = 0;
    1543           0 :     if (prefix)
    1544           0 :         len += prefix->length;
    1545           0 :     len += hiv->data.length;
    1546           0 :     if (inc_sign_data)
    1547           0 :         len += iov_sign_data_len(data, num_data);
    1548             :     else
    1549           0 :         len += iov_enc_data_len(data, num_data);
    1550           0 :     if (piv)
    1551           0 :         len += piv->data.length;
    1552             : 
    1553           0 :     p = q = malloc(len);
    1554           0 :     if (p == NULL)
    1555           0 :         return krb5_enomem(context);
    1556             : 
    1557           0 :     if (prefix) {
    1558           0 :         memcpy(q, prefix->data, prefix->length);
    1559           0 :         q += prefix->length;
    1560             :     }
    1561           0 :     memcpy(q, hiv->data.data, hiv->data.length);
    1562           0 :     q += hiv->data.length;
    1563           0 :     for (i = 0; i < num_data; i++) {
    1564           0 :         if (data[i].flags == KRB5_CRYPTO_TYPE_DATA ||
    1565           0 :             (inc_sign_data && data[i].flags == KRB5_CRYPTO_TYPE_SIGN_ONLY)) {
    1566           0 :             memcpy(q, data[i].data.data, data[i].data.length);
    1567           0 :             q += data[i].data.length;
    1568             :         }
    1569             :     }
    1570           0 :     if (piv)
    1571           0 :         memset(q, 0, piv->data.length);
    1572             : 
    1573           0 :     out->length = len;
    1574           0 :     out->data = p;
    1575             : 
    1576           0 :     return 0;
    1577             : }
    1578             : 
    1579             : static krb5_error_code
    1580           0 : iov_uncoalesce(krb5_context context,
    1581             :                krb5_data *enc_data,
    1582             :                krb5_crypto_iov *data,
    1583             :                int num_data)
    1584             : {
    1585           0 :     unsigned char *q = enc_data->data;
    1586             :     krb5_crypto_iov *hiv, *piv;
    1587             :     unsigned int i;
    1588             : 
    1589           0 :     hiv = iov_find(data, num_data, KRB5_CRYPTO_TYPE_HEADER);
    1590             : 
    1591           0 :     piv = iov_find(data, num_data, KRB5_CRYPTO_TYPE_PADDING);
    1592             : 
    1593           0 :     memcpy(hiv->data.data, q, hiv->data.length);
    1594           0 :     q += hiv->data.length;
    1595             : 
    1596           0 :     for (i = 0; i < num_data; i++) {
    1597           0 :         if (data[i].flags != KRB5_CRYPTO_TYPE_DATA)
    1598           0 :             continue;
    1599           0 :         memcpy(data[i].data.data, q, data[i].data.length);
    1600           0 :         q += data[i].data.length;
    1601             :     }
    1602           0 :     if (piv)
    1603           0 :         memcpy(piv->data.data, q, piv->data.length);
    1604             : 
    1605           0 :     return 0;
    1606             : }
    1607             : 
    1608             : static krb5_error_code
    1609     1058310 : iov_pad_validate(const struct _krb5_encryption_type *et,
    1610             :                  krb5_crypto_iov *data,
    1611             :                  int num_data,
    1612             :                  krb5_crypto_iov **ppiv)
    1613             : {
    1614             :     krb5_crypto_iov *piv;
    1615             :     size_t sz, headersz, block_sz, pad_sz, len;
    1616             : 
    1617     1058310 :     len = iov_enc_data_len(data, num_data);
    1618             : 
    1619     1058310 :     headersz = et->confoundersize;
    1620             : 
    1621     1058310 :     sz = headersz + len;
    1622     1058310 :     block_sz = (sz + et->padsize - 1) &~ (et->padsize - 1); /* pad */
    1623             : 
    1624     1058310 :     pad_sz = block_sz - sz;
    1625             : 
    1626     1058310 :     piv = iov_find(data, num_data, KRB5_CRYPTO_TYPE_PADDING);
    1627             :     /* its ok to have no TYPE_PADDING if there is no padding */
    1628     1058310 :     if (piv == NULL && pad_sz != 0)
    1629           0 :         return KRB5_BAD_MSIZE;
    1630     1058310 :     if (piv) {
    1631           0 :         if (piv->data.length < pad_sz)
    1632           0 :             return KRB5_BAD_MSIZE;
    1633           0 :         piv->data.length = pad_sz;
    1634           0 :         if (pad_sz)
    1635           0 :             memset(piv->data.data, 0, pad_sz);
    1636             :         else
    1637           0 :             piv = NULL;
    1638             :     }
    1639             : 
    1640     1058310 :     *ppiv = piv;
    1641     1058310 :     return 0;
    1642             : }
    1643             : 
    1644             : /**
    1645             :  * Inline encrypt a kerberos message
    1646             :  *
    1647             :  * @param context Kerberos context
    1648             :  * @param crypto Kerberos crypto context
    1649             :  * @param usage Key usage for this buffer
    1650             :  * @param data array of buffers to process
    1651             :  * @param num_data length of array
    1652             :  * @param ivec initial cbc/cts vector
    1653             :  *
    1654             :  * @return Return an error code or 0.
    1655             :  * @ingroup krb5_crypto
    1656             :  *
    1657             :  * Kerberos encrypted data look like this:
    1658             :  *
    1659             :  * 1. KRB5_CRYPTO_TYPE_HEADER
    1660             :  * 2. array [1,...] KRB5_CRYPTO_TYPE_DATA and array [0,...]
    1661             :  *    KRB5_CRYPTO_TYPE_SIGN_ONLY in any order, however the receiver
    1662             :  *    have to aware of the order. KRB5_CRYPTO_TYPE_SIGN_ONLY is
    1663             :  *    commonly used headers and trailers.
    1664             :  * 3. KRB5_CRYPTO_TYPE_PADDING, at least on padsize long if padsize > 1
    1665             :  * 4. KRB5_CRYPTO_TYPE_TRAILER
    1666             :  */
    1667             : 
    1668             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
    1669     1058310 : krb5_encrypt_iov_ivec(krb5_context context,
    1670             :                       krb5_crypto crypto,
    1671             :                       unsigned usage,
    1672             :                       krb5_crypto_iov *data,
    1673             :                       int num_data,
    1674             :                       void *ivec)
    1675             : {
    1676             :     size_t headersz, trailersz;
    1677             :     Checksum cksum;
    1678             :     krb5_data enc_data, sign_data;
    1679             :     krb5_error_code ret;
    1680             :     struct _krb5_key_data *dkey;
    1681     1058310 :     const struct _krb5_encryption_type *et = crypto->et;
    1682             :     krb5_crypto_iov *tiv, *piv, *hiv;
    1683             : 
    1684     1058310 :     if (num_data < 0) {
    1685           0 :         krb5_clear_error_message(context);
    1686           0 :         return KRB5_CRYPTO_INTERNAL;
    1687             :     }
    1688             : 
    1689     1058310 :     if(!derived_crypto(context, crypto)) {
    1690           0 :         krb5_clear_error_message(context);
    1691           0 :         return KRB5_CRYPTO_INTERNAL;
    1692             :     }
    1693             : 
    1694     1058310 :     krb5_data_zero(&enc_data);
    1695     1058310 :     krb5_data_zero(&sign_data);
    1696             : 
    1697     1058310 :     headersz = et->confoundersize;
    1698     1058310 :     trailersz = CHECKSUMSIZE(et->keyed_checksum);
    1699             : 
    1700             :     /* header */
    1701     1058310 :     hiv = iov_find(data, num_data, KRB5_CRYPTO_TYPE_HEADER);
    1702     1058310 :     if (hiv == NULL || hiv->data.length != headersz)
    1703           0 :         return KRB5_BAD_MSIZE;
    1704     1058310 :     krb5_generate_random_block(hiv->data.data, hiv->data.length);
    1705             : 
    1706             :     /* padding */
    1707     1058310 :     ret = iov_pad_validate(et, data, num_data, &piv);
    1708     1058310 :     if(ret)
    1709           0 :         goto cleanup;
    1710             : 
    1711             :     /* trailer */
    1712     1058310 :     tiv = iov_find(data, num_data, KRB5_CRYPTO_TYPE_TRAILER);
    1713     1058310 :     if (tiv == NULL || tiv->data.length != trailersz) {
    1714           0 :         ret = KRB5_BAD_MSIZE;
    1715           0 :         goto cleanup;
    1716             :     }
    1717             : 
    1718     1058310 :     if (et->flags & F_ENC_THEN_CKSUM) {
    1719             :         unsigned char old_ivec[EVP_MAX_IV_LENGTH];
    1720             :         krb5_data ivec_data;
    1721             : 
    1722           0 :         heim_assert(et->blocksize <= sizeof(old_ivec),
    1723             :                     "blocksize too big for ivec buffer");
    1724             : 
    1725           0 :         ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey);
    1726           0 :         if(ret)
    1727           0 :             goto cleanup;
    1728             : 
    1729           0 :         ret = _key_schedule(context, dkey);
    1730           0 :         if(ret)
    1731           0 :             goto cleanup;
    1732             : 
    1733           0 :         if (ivec)
    1734           0 :             memcpy(old_ivec, ivec, et->blocksize);
    1735             :         else
    1736           0 :             memset(old_ivec, 0, et->blocksize);
    1737             : 
    1738           0 :         if (et->encrypt_iov != NULL) {
    1739           0 :             ret = (*et->encrypt_iov)(context, dkey, data, num_data, 1, usage,
    1740             :                                      ivec);
    1741           0 :             if (ret)
    1742           0 :                 goto cleanup;
    1743             :         } else {
    1744           0 :             ret = iov_coalesce(context, NULL, data, num_data, FALSE, &enc_data);
    1745           0 :             if (ret)
    1746           0 :                 goto cleanup;
    1747             : 
    1748           0 :             ret = (*et->encrypt)(context, dkey, enc_data.data, enc_data.length,
    1749             :                                  1, usage, ivec);
    1750           0 :             if (ret)
    1751           0 :                 goto cleanup;
    1752             : 
    1753           0 :             ret = iov_uncoalesce(context, &enc_data, data, num_data);
    1754           0 :             if (ret)
    1755           0 :                 goto cleanup;
    1756             :         }
    1757             : 
    1758           0 :         ivec_data.length = et->blocksize;
    1759           0 :         ivec_data.data = old_ivec;
    1760             : 
    1761           0 :         ret = iov_coalesce(context, &ivec_data, data, num_data, TRUE, &sign_data);
    1762           0 :         if(ret)
    1763           0 :             goto cleanup;
    1764             : 
    1765           0 :         ret = create_checksum(context,
    1766             :                               et->keyed_checksum,
    1767             :                               crypto,
    1768           0 :                               INTEGRITY_USAGE(usage),
    1769             :                               sign_data.data,
    1770             :                               sign_data.length,
    1771             :                               0,
    1772             :                               &cksum);
    1773             : 
    1774           0 :         if(ret == 0 && cksum.checksum.length != trailersz) {
    1775           0 :             free_Checksum (&cksum);
    1776           0 :             krb5_clear_error_message (context);
    1777           0 :             ret = KRB5_CRYPTO_INTERNAL;
    1778             :         }
    1779           0 :         if (ret)
    1780           0 :             goto cleanup;
    1781             : 
    1782             :         /* save cksum at end */
    1783           0 :         memcpy(tiv->data.data, cksum.checksum.data, cksum.checksum.length);
    1784           0 :         free_Checksum (&cksum);
    1785             : 
    1786             :     } else {
    1787     1058310 :         cksum.checksum = tiv->data;
    1788     1058310 :         ret = create_checksum_iov(context,
    1789             :                               et->keyed_checksum,
    1790             :                               crypto,
    1791     1058310 :                               INTEGRITY_USAGE(usage),
    1792             :                               data,
    1793             :                               num_data,
    1794             :                               0,
    1795             :                               &cksum);
    1796     1058310 :         if (ret)
    1797           0 :             goto cleanup;
    1798             : 
    1799             :         /* create_checksum may realloc the derived key space, so any keys
    1800             :          * obtained before it was called may no longer be valid */
    1801     1058310 :         ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey);
    1802     1058310 :         if(ret)
    1803           0 :             goto cleanup;
    1804             : 
    1805     1058310 :         ret = _key_schedule(context, dkey);
    1806     1058310 :         if(ret)
    1807           0 :             goto cleanup;
    1808             : 
    1809     1058310 :         if (et->encrypt_iov != NULL) {
    1810     1058310 :             ret = (*et->encrypt_iov)(context, dkey, data, num_data, 1, usage,
    1811             :                                      ivec);
    1812     1058310 :             if (ret)
    1813           0 :                 goto cleanup;
    1814             :         } else {
    1815           0 :             ret = iov_coalesce(context, NULL, data, num_data, FALSE, &enc_data);
    1816           0 :             if (ret)
    1817           0 :                 goto cleanup;
    1818             : 
    1819           0 :             ret = (*et->encrypt)(context, dkey, enc_data.data, enc_data.length,
    1820             :                                  1, usage, ivec);
    1821           0 :             if (ret)
    1822           0 :                 goto cleanup;
    1823             : 
    1824           0 :             ret = iov_uncoalesce(context, &enc_data, data, num_data);
    1825           0 :             if (ret)
    1826           0 :                 goto cleanup;
    1827             :         }
    1828             :     }
    1829             : 
    1830     1058310 : cleanup:
    1831     1058310 :     if (enc_data.data) {
    1832           0 :         memset_s(enc_data.data, enc_data.length, 0, enc_data.length);
    1833           0 :         krb5_data_free(&enc_data);
    1834             :     }
    1835     1058310 :     if (sign_data.data) {
    1836           0 :         memset_s(sign_data.data, sign_data.length, 0, sign_data.length);
    1837           0 :         krb5_data_free(&sign_data);
    1838             :     }
    1839     1058310 :     return ret;
    1840             : }
    1841             : 
    1842             : /**
    1843             :  * Inline decrypt a Kerberos message.
    1844             :  *
    1845             :  * @param context Kerberos context
    1846             :  * @param crypto Kerberos crypto context
    1847             :  * @param usage Key usage for this buffer
    1848             :  * @param data array of buffers to process
    1849             :  * @param num_data length of array
    1850             :  * @param ivec initial cbc/cts vector
    1851             :  *
    1852             :  * @return Return an error code or 0.
    1853             :  * @ingroup krb5_crypto
    1854             :  *
    1855             :  * 1. KRB5_CRYPTO_TYPE_HEADER
    1856             :  * 2. one KRB5_CRYPTO_TYPE_DATA and array [0,...] of KRB5_CRYPTO_TYPE_SIGN_ONLY in
    1857             :  *  any order, however the receiver have to aware of the
    1858             :  *  order. KRB5_CRYPTO_TYPE_SIGN_ONLY is commonly used unencrypoted
    1859             :  *  protocol headers and trailers. The output data will be of same
    1860             :  *  size as the input data or shorter.
    1861             :  */
    1862             : 
    1863             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
    1864      336833 : krb5_decrypt_iov_ivec(krb5_context context,
    1865             :                       krb5_crypto crypto,
    1866             :                       unsigned usage,
    1867             :                       krb5_crypto_iov *data,
    1868             :                       unsigned int num_data,
    1869             :                       void *ivec)
    1870             : {
    1871             :     Checksum cksum;
    1872             :     krb5_data enc_data, sign_data;
    1873             :     krb5_error_code ret;
    1874             :     struct _krb5_key_data *dkey;
    1875      336833 :     struct _krb5_encryption_type *et = crypto->et;
    1876             :     krb5_crypto_iov *tiv, *hiv;
    1877             : 
    1878      336833 :     if(!derived_crypto(context, crypto)) {
    1879           0 :         krb5_clear_error_message(context);
    1880           0 :         return KRB5_CRYPTO_INTERNAL;
    1881             :     }
    1882             : 
    1883             :     /* header */
    1884      336833 :     hiv = iov_find(data, num_data, KRB5_CRYPTO_TYPE_HEADER);
    1885      336833 :     if (hiv == NULL || hiv->data.length != et->confoundersize)
    1886           0 :         return KRB5_BAD_MSIZE;
    1887             : 
    1888             :     /* trailer */
    1889      336833 :     tiv = iov_find(data, num_data, KRB5_CRYPTO_TYPE_TRAILER);
    1890      336833 :     if (tiv->data.length != CHECKSUMSIZE(et->keyed_checksum))
    1891           0 :         return KRB5_BAD_MSIZE;
    1892             : 
    1893             :     /* padding */
    1894      336833 :     if ((iov_enc_data_len(data, num_data) % et->padsize) != 0) {
    1895           0 :         krb5_clear_error_message(context);
    1896           0 :         return KRB5_BAD_MSIZE;
    1897             :     }
    1898             : 
    1899      336833 :     krb5_data_zero(&enc_data);
    1900      336833 :     krb5_data_zero(&sign_data);
    1901             : 
    1902      336833 :     if (!(et->flags & F_ENC_THEN_CKSUM)) {
    1903      336833 :         ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey);
    1904      336833 :         if(ret)
    1905           0 :             goto cleanup;
    1906             : 
    1907      336833 :         ret = _key_schedule(context, dkey);
    1908      336833 :         if(ret)
    1909           0 :             goto cleanup;
    1910             : 
    1911      336833 :         if (et->encrypt_iov != NULL) {
    1912      336833 :             ret = (*et->encrypt_iov)(context, dkey, data, num_data,
    1913             :                                      0, usage, ivec);
    1914      336833 :             if(ret)
    1915           0 :                 goto cleanup;
    1916             :         } else {
    1917           0 :             ret = iov_coalesce(context, NULL, data, num_data, FALSE, &enc_data);
    1918           0 :             if(ret)
    1919           0 :                 goto cleanup;
    1920             : 
    1921           0 :             ret = (*et->encrypt)(context, dkey, enc_data.data, enc_data.length,
    1922             :                                  0, usage, ivec);
    1923           0 :             if(ret)
    1924           0 :                 goto cleanup;
    1925             : 
    1926           0 :             ret = iov_uncoalesce(context, &enc_data, data, num_data);
    1927           0 :             if(ret)
    1928           0 :                 goto cleanup;
    1929             :         }
    1930             : 
    1931      336833 :         cksum.checksum.data   = tiv->data.data;
    1932      336833 :         cksum.checksum.length = tiv->data.length;
    1933      336833 :         cksum.cksumtype       = CHECKSUMTYPE(et->keyed_checksum);
    1934             : 
    1935      336833 :         ret = verify_checksum_iov(context, crypto, INTEGRITY_USAGE(usage),
    1936             :                                   data, num_data, 0, &cksum);
    1937      336833 :         if(ret)
    1938           0 :             goto cleanup;
    1939             :     } else {
    1940             :         krb5_data ivec_data;
    1941             :         static unsigned char zero_ivec[EVP_MAX_IV_LENGTH];
    1942             : 
    1943           0 :         heim_assert(et->blocksize <= sizeof(zero_ivec),
    1944             :                     "blocksize too big for ivec buffer");
    1945             : 
    1946           0 :         ivec_data.length = et->blocksize;
    1947           0 :         ivec_data.data = ivec ? ivec : zero_ivec;
    1948             : 
    1949           0 :         ret = iov_coalesce(context, &ivec_data, data, num_data, TRUE, &sign_data);
    1950           0 :         if(ret)
    1951           0 :             goto cleanup;
    1952             : 
    1953           0 :         cksum.checksum.data   = tiv->data.data;
    1954           0 :         cksum.checksum.length = tiv->data.length;
    1955           0 :         cksum.cksumtype       = CHECKSUMTYPE(et->keyed_checksum);
    1956             : 
    1957           0 :         ret = verify_checksum(context,
    1958             :                               crypto,
    1959           0 :                               INTEGRITY_USAGE(usage),
    1960             :                               sign_data.data,
    1961             :                               sign_data.length,
    1962             :                               0,
    1963             :                               &cksum);
    1964           0 :         if(ret)
    1965           0 :             goto cleanup;
    1966             : 
    1967           0 :         ret = iov_coalesce(context, NULL, data, num_data, FALSE, &enc_data);
    1968           0 :         if(ret)
    1969           0 :             goto cleanup;
    1970             : 
    1971           0 :         ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey);
    1972           0 :         if(ret)
    1973           0 :             goto cleanup;
    1974             : 
    1975           0 :         ret = _key_schedule(context, dkey);
    1976           0 :         if(ret)
    1977           0 :             goto cleanup;
    1978             : 
    1979           0 :         ret = (*et->encrypt)(context, dkey, enc_data.data, enc_data.length,
    1980             :                              0, usage, ivec);
    1981           0 :         if(ret)
    1982           0 :             goto cleanup;
    1983             : 
    1984           0 :         ret = iov_uncoalesce(context, &enc_data, data, num_data);
    1985           0 :         if(ret)
    1986           0 :             goto cleanup;
    1987             :     }
    1988             : 
    1989      336833 : cleanup:
    1990      336833 :     if (enc_data.data) {
    1991           0 :         memset_s(enc_data.data, enc_data.length, 0, enc_data.length);
    1992           0 :         krb5_data_free(&enc_data);
    1993             :     }
    1994      336833 :     if (sign_data.data) {
    1995           0 :         memset_s(sign_data.data, sign_data.length, 0, sign_data.length);
    1996           0 :         krb5_data_free(&sign_data);
    1997             :     }
    1998      336833 :     return ret;
    1999             : }
    2000             : 
    2001             : /**
    2002             :  * Create a Kerberos message checksum.
    2003             :  *
    2004             :  * @param context Kerberos context
    2005             :  * @param crypto Kerberos crypto context
    2006             :  * @param usage Key usage for this buffer
    2007             :  * @param data array of buffers to process
    2008             :  * @param num_data length of array
    2009             :  * @param type output data
    2010             :  *
    2011             :  * @return Return an error code or 0.
    2012             :  * @ingroup krb5_crypto
    2013             :  */
    2014             : 
    2015             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
    2016           0 : krb5_create_checksum_iov(krb5_context context,
    2017             :                          krb5_crypto crypto,
    2018             :                          unsigned usage,
    2019             :                          krb5_crypto_iov *data,
    2020             :                          unsigned int num_data,
    2021             :                          krb5_cksumtype *type)
    2022             : {
    2023             :     Checksum cksum;
    2024             :     krb5_crypto_iov *civ;
    2025             :     struct _krb5_checksum_type *ct;
    2026             :     unsigned keyusage;
    2027             :     krb5_error_code ret;
    2028             : 
    2029           0 :     civ = iov_find(data, num_data, KRB5_CRYPTO_TYPE_CHECKSUM);
    2030           0 :     if (civ == NULL)
    2031           0 :         return KRB5_BAD_MSIZE;
    2032             : 
    2033           0 :     ct = crypto->et->keyed_checksum;
    2034           0 :     if (ct == NULL)
    2035           0 :         ct = crypto->et->checksum;
    2036             : 
    2037           0 :     if(ct == NULL) {
    2038           0 :         krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
    2039           0 :                                 N_("checksum type not found", ""));
    2040           0 :         return KRB5_PROG_SUMTYPE_NOSUPP;
    2041             :     }
    2042             : 
    2043           0 :     if (arcfour_checksum_p(ct, crypto)) {
    2044           0 :         keyusage = usage;
    2045           0 :         _krb5_usage2arcfour(context, &keyusage);
    2046             :     } else
    2047           0 :         keyusage = CHECKSUM_USAGE(usage);
    2048             : 
    2049           0 :     if (ct->checksumsize > civ->data.length) {
    2050           0 :         krb5_set_error_message(context, KRB5_BAD_MSIZE,
    2051           0 :                                N_("Checksum larger then input buffer", ""));
    2052           0 :         return KRB5_BAD_MSIZE;
    2053             :     }
    2054             : 
    2055           0 :     cksum.checksum = civ->data;
    2056           0 :     ret = create_checksum_iov(context, ct, crypto, keyusage,
    2057             :                               data, num_data, crypto_flags(crypto), &cksum);
    2058             : 
    2059           0 :     if (ret == 0 && type)
    2060           0 :         *type = cksum.cksumtype;
    2061             : 
    2062           0 :     return ret;
    2063             : }
    2064             : 
    2065             : /**
    2066             :  * Verify a Kerberos message checksum.
    2067             :  *
    2068             :  * @param context Kerberos context
    2069             :  * @param crypto Kerberos crypto context
    2070             :  * @param usage Key usage for this buffer
    2071             :  * @param data array of buffers to process
    2072             :  * @param num_data length of array
    2073             :  * @param type return checksum type if not NULL
    2074             :  *
    2075             :  * @return Return an error code or 0.
    2076             :  * @ingroup krb5_crypto
    2077             :  */
    2078             : 
    2079             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
    2080           0 : krb5_verify_checksum_iov(krb5_context context,
    2081             :                          krb5_crypto crypto,
    2082             :                          unsigned usage,
    2083             :                          krb5_crypto_iov *data,
    2084             :                          unsigned int num_data,
    2085             :                          krb5_cksumtype *type)
    2086             : {
    2087           0 :     struct _krb5_encryption_type *et = crypto->et;
    2088             :     struct _krb5_checksum_type *ct;
    2089             :     Checksum cksum;
    2090             :     krb5_crypto_iov *civ;
    2091             :     krb5_error_code ret;
    2092             :     unsigned keyusage;
    2093             : 
    2094           0 :     civ = iov_find(data, num_data, KRB5_CRYPTO_TYPE_CHECKSUM);
    2095           0 :     if (civ == NULL)
    2096           0 :         return KRB5_BAD_MSIZE;
    2097             : 
    2098           0 :     cksum.cksumtype = CHECKSUMTYPE(et->keyed_checksum);
    2099           0 :     cksum.checksum.length = civ->data.length;
    2100           0 :     cksum.checksum.data = civ->data.data;
    2101             : 
    2102           0 :     ct = _krb5_find_checksum(cksum.cksumtype);
    2103           0 :     if(ct == NULL) {
    2104           0 :         krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
    2105           0 :                                 N_("checksum type %d not supported", ""),
    2106           0 :                                 cksum.cksumtype);
    2107           0 :         return KRB5_PROG_SUMTYPE_NOSUPP;
    2108             :     }
    2109             : 
    2110           0 :     if (arcfour_checksum_p(ct, crypto)) {
    2111           0 :         keyusage = usage;
    2112           0 :         _krb5_usage2arcfour(context, &keyusage);
    2113             :     } else
    2114           0 :         keyusage = CHECKSUM_USAGE(usage);
    2115             : 
    2116           0 :     ret = verify_checksum_iov(context, crypto, keyusage, data, num_data,
    2117             :                               crypto_flags(crypto), &cksum);
    2118             : 
    2119           0 :     if (ret == 0 && type)
    2120           0 :         *type = cksum.cksumtype;
    2121             : 
    2122           0 :     return ret;
    2123             : }
    2124             : 
    2125             : 
    2126             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
    2127     3888067 : krb5_crypto_length(krb5_context context,
    2128             :                    krb5_crypto crypto,
    2129             :                    int type,
    2130             :                    size_t *len)
    2131             : {
    2132     3888067 :     if (!derived_crypto(context, crypto)) {
    2133           0 :         krb5_set_error_message(context, EINVAL, "not a derived crypto");
    2134           0 :         return EINVAL;
    2135             :     }
    2136             : 
    2137     3888067 :     switch(type) {
    2138           0 :     case KRB5_CRYPTO_TYPE_EMPTY:
    2139           0 :         *len = 0;
    2140           0 :         return 0;
    2141     1408300 :     case KRB5_CRYPTO_TYPE_HEADER:
    2142     1408300 :         *len = crypto->et->blocksize;
    2143     1408300 :         return 0;
    2144           0 :     case KRB5_CRYPTO_TYPE_DATA:
    2145             :     case KRB5_CRYPTO_TYPE_SIGN_ONLY:
    2146             :         /* len must already been filled in */
    2147           0 :         return 0;
    2148     1071467 :     case KRB5_CRYPTO_TYPE_PADDING:
    2149     1071467 :         if (crypto->et->padsize > 1)
    2150           0 :             *len = crypto->et->padsize;
    2151             :         else
    2152     1071467 :             *len = 0;
    2153     1071467 :         return 0;
    2154     1408300 :     case KRB5_CRYPTO_TYPE_TRAILER:
    2155     1408300 :         if (crypto->et->keyed_checksum)
    2156     1408300 :             *len = CHECKSUMSIZE(crypto->et->keyed_checksum);
    2157             :         else
    2158           0 :             *len = 0;
    2159     1408300 :         return 0;
    2160           0 :     case KRB5_CRYPTO_TYPE_CHECKSUM:
    2161           0 :         if (crypto->et->keyed_checksum)
    2162           0 :             *len = CHECKSUMSIZE(crypto->et->keyed_checksum);
    2163             :         else
    2164           0 :             *len = CHECKSUMSIZE(crypto->et->checksum);
    2165           0 :         return 0;
    2166             :     }
    2167           0 :     krb5_set_error_message(context, EINVAL,
    2168             :                            "%d not a supported type", type);
    2169           0 :     return EINVAL;
    2170             : }
    2171             : 
    2172             : 
    2173             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
    2174           0 : krb5_crypto_length_iov(krb5_context context,
    2175             :                        krb5_crypto crypto,
    2176             :                        krb5_crypto_iov *data,
    2177             :                        unsigned int num_data)
    2178             : {
    2179             :     krb5_error_code ret;
    2180             :     size_t i;
    2181             : 
    2182           0 :     for (i = 0; i < num_data; i++) {
    2183           0 :         ret = krb5_crypto_length(context, crypto,
    2184           0 :                                  data[i].flags,
    2185           0 :                                  &data[i].data.length);
    2186           0 :         if (ret)
    2187           0 :             return ret;
    2188             :     }
    2189           0 :     return 0;
    2190             : }
    2191             : 
    2192             : 
    2193             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
    2194      861446 : krb5_encrypt_ivec(krb5_context context,
    2195             :                   krb5_crypto crypto,
    2196             :                   unsigned usage,
    2197             :                   const void *data,
    2198             :                   size_t len,
    2199             :                   krb5_data *result,
    2200             :                   void *ivec)
    2201             : {
    2202             :     krb5_error_code ret;
    2203             : 
    2204      861446 :     switch (crypto->et->flags & F_CRYPTO_MASK) {
    2205      836902 :     case F_RFC3961_ENC:
    2206      836902 :         ret = encrypt_internal_derived(context, crypto, usage,
    2207             :                                        data, len, result, ivec);
    2208      836902 :         break;
    2209       24544 :     case F_SPECIAL:
    2210       24544 :         ret = encrypt_internal_special (context, crypto, usage,
    2211             :                                         data, len, result, ivec);
    2212       24544 :         break;
    2213           0 :     case F_ENC_THEN_CKSUM:
    2214           0 :         ret = encrypt_internal_enc_then_cksum(context, crypto, usage,
    2215             :                                               data, len, result, ivec);
    2216           0 :         break;
    2217           0 :     default:
    2218           0 :         ret = encrypt_internal(context, crypto, data, len, result, ivec);
    2219           0 :         break;
    2220             :     }
    2221             : 
    2222      861446 :     return ret;
    2223             : }
    2224             : 
    2225             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
    2226      861446 : krb5_encrypt(krb5_context context,
    2227             :              krb5_crypto crypto,
    2228             :              unsigned usage,
    2229             :              const void *data,
    2230             :              size_t len,
    2231             :              krb5_data *result)
    2232             : {
    2233      861446 :     return krb5_encrypt_ivec(context, crypto, usage, data, len, result, NULL);
    2234             : }
    2235             : 
    2236             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
    2237      187371 : krb5_encrypt_EncryptedData(krb5_context context,
    2238             :                            krb5_crypto crypto,
    2239             :                            unsigned usage,
    2240             :                            void *data,
    2241             :                            size_t len,
    2242             :                            int kvno,
    2243             :                            EncryptedData *result)
    2244             : {
    2245      187371 :     result->etype = CRYPTO_ETYPE(crypto);
    2246      187371 :     if(kvno){
    2247       71814 :         ALLOC(result->kvno, 1);
    2248       71814 :         *result->kvno = kvno;
    2249             :     }else
    2250      115557 :         result->kvno = NULL;
    2251      187371 :     return krb5_encrypt(context, crypto, usage, data, len, &result->cipher);
    2252             : }
    2253             : 
    2254             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
    2255      905014 : krb5_decrypt_ivec(krb5_context context,
    2256             :                   krb5_crypto crypto,
    2257             :                   unsigned usage,
    2258             :                   void *data,
    2259             :                   size_t len,
    2260             :                   krb5_data *result,
    2261             :                   void *ivec)
    2262             : {
    2263             :     krb5_error_code ret;
    2264             : 
    2265      905014 :     switch (crypto->et->flags & F_CRYPTO_MASK) {
    2266      884504 :     case F_RFC3961_ENC:
    2267      884504 :         ret = decrypt_internal_derived(context, crypto, usage,
    2268             :                                 data, len, result, ivec);
    2269      884504 :         break;
    2270       20510 :     case F_SPECIAL:
    2271       20510 :         ret = decrypt_internal_special(context, crypto, usage,
    2272             :                                        data, len, result, ivec);
    2273       20510 :         break;
    2274           0 :     case F_ENC_THEN_CKSUM:
    2275           0 :         ret = decrypt_internal_enc_then_cksum(context, crypto, usage,
    2276             :                                               data, len, result, ivec);
    2277           0 :         break;
    2278           0 :     default:
    2279           0 :         ret = decrypt_internal(context, crypto, data, len, result, ivec);
    2280           0 :         break;
    2281             :     }
    2282             : 
    2283      905014 :     return ret;
    2284             : }
    2285             : 
    2286             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
    2287      905014 : krb5_decrypt(krb5_context context,
    2288             :              krb5_crypto crypto,
    2289             :              unsigned usage,
    2290             :              void *data,
    2291             :              size_t len,
    2292             :              krb5_data *result)
    2293             : {
    2294      905014 :     return krb5_decrypt_ivec (context, crypto, usage, data, len, result,
    2295             :                               NULL);
    2296             : }
    2297             : 
    2298             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
    2299      340639 : krb5_decrypt_EncryptedData(krb5_context context,
    2300             :                            krb5_crypto crypto,
    2301             :                            unsigned usage,
    2302             :                            const EncryptedData *e,
    2303             :                            krb5_data *result)
    2304             : {
    2305      340639 :     return krb5_decrypt(context, crypto, usage,
    2306             :                         e->cipher.data, e->cipher.length, result);
    2307             : }
    2308             : 
    2309             : /************************************************************
    2310             :  *                                                          *
    2311             :  ************************************************************/
    2312             : 
    2313             : static krb5_error_code
    2314     2377561 : derive_key_rfc3961(krb5_context context,
    2315             :                    struct _krb5_encryption_type *et,
    2316             :                    struct _krb5_key_data *key,
    2317             :                    const void *constant,
    2318             :                    size_t len)
    2319             : {
    2320             : 
    2321     2377561 :     unsigned char *k = NULL;
    2322     2377561 :     unsigned int nblocks = 0, i;
    2323     2377561 :     krb5_error_code ret = 0;
    2324     2377561 :     struct _krb5_key_type *kt = et->keytype;
    2325             : 
    2326     4755122 :     if(et->blocksize * 8 < kt->bits || len != et->blocksize) {
    2327     2377561 :         nblocks = (kt->bits + et->blocksize * 8 - 1) / (et->blocksize * 8);
    2328     2377561 :         k = malloc(nblocks * et->blocksize);
    2329     2377561 :         if(k == NULL) {
    2330           0 :             ret = krb5_enomem(context);
    2331           0 :             goto out;
    2332             :         }
    2333     2377561 :         ret = _krb5_n_fold(constant, len, k, et->blocksize);
    2334     2377561 :         if (ret) {
    2335           0 :             krb5_enomem(context);
    2336           0 :             goto out;
    2337             :         }
    2338             : 
    2339     7110672 :         for(i = 0; i < nblocks; i++) {
    2340     4733111 :             if(i > 0)
    2341     4711100 :                 memcpy(k + i * et->blocksize,
    2342     2355550 :                        k + (i - 1) * et->blocksize,
    2343             :                        et->blocksize);
    2344     4733111 :             ret = (*et->encrypt)(context, key, k + i * et->blocksize,
    2345             :                                  et->blocksize, 1, 0, NULL);
    2346     4733111 :             if (ret) {
    2347           0 :                     krb5_set_error_message(context, ret, N_("encrypt failed", ""));
    2348           0 :                     goto out;
    2349             :             }
    2350             :         }
    2351             :     } else {
    2352             :         /* this case is probably broken, but won't be run anyway */
    2353           0 :         void *c = malloc(len);
    2354           0 :         size_t res_len = (kt->bits + 7) / 8;
    2355             : 
    2356           0 :         if(len != 0 && c == NULL) {
    2357           0 :             ret = krb5_enomem(context);
    2358           0 :             goto out;
    2359             :         }
    2360           0 :         memcpy(c, constant, len);
    2361           0 :         ret = (*et->encrypt)(context, key, c, len, 1, 0, NULL);
    2362           0 :         if (ret) {
    2363           0 :                 free(c);
    2364           0 :                 krb5_set_error_message(context, ret, N_("encrypt failed", ""));
    2365           0 :                 goto out;
    2366             :         }
    2367           0 :         k = malloc(res_len);
    2368           0 :         if(res_len != 0 && k == NULL) {
    2369           0 :             free(c);
    2370           0 :             ret = krb5_enomem(context);
    2371           0 :             goto out;
    2372             :         }
    2373           0 :         ret = _krb5_n_fold(c, len, k, res_len);
    2374           0 :         free(c);
    2375           0 :         if (ret) {
    2376           0 :             krb5_enomem(context);
    2377           0 :             goto out;
    2378             :         }
    2379             :     }
    2380             : 
    2381     2377561 :     if (kt->type == KRB5_ENCTYPE_OLD_DES3_CBC_SHA1)
    2382           0 :         _krb5_DES3_random_to_key(context, key->key, k, nblocks * et->blocksize);
    2383             :     else
    2384     2377561 :         memcpy(key->key->keyvalue.data, k, key->key->keyvalue.length);
    2385             : 
    2386     2377561 :  out:
    2387     2377561 :     if (k) {
    2388     2377561 :         memset_s(k, nblocks * et->blocksize, 0, nblocks * et->blocksize);
    2389     2377561 :         free(k);
    2390             :     }
    2391     2377561 :     return ret;
    2392             : }
    2393             : 
    2394             : static krb5_error_code
    2395           0 : derive_key_sp800_hmac(krb5_context context,
    2396             :                       struct _krb5_encryption_type *et,
    2397             :                       struct _krb5_key_data *key,
    2398             :                       const void *constant,
    2399             :                       size_t len)
    2400             : {
    2401             :     krb5_error_code ret;
    2402           0 :     struct _krb5_key_type *kt = et->keytype;
    2403             :     krb5_data label;
    2404           0 :     const EVP_MD *md = NULL;
    2405           0 :     const unsigned char *c = constant;
    2406             :     size_t key_len;
    2407             :     krb5_data K1;
    2408             : 
    2409           0 :     ret = _krb5_aes_sha2_md_for_enctype(context, kt->type, &md);
    2410           0 :     if (ret)
    2411           0 :         return ret;
    2412             : 
    2413             :     /*
    2414             :      * PRF usage: not handled here (output cannot be longer)
    2415             :      * Integrity usage: truncated hash (half length)
    2416             :      * Encryption usage: base key length
    2417             :      */
    2418           0 :     if (len == 5 && (c[4] == 0x99 || c[4] == 0x55))
    2419           0 :         key_len = EVP_MD_size(md) / 2;
    2420             :     else
    2421           0 :         key_len = kt->size;
    2422             : 
    2423           0 :     ret = krb5_data_alloc(&K1, key_len);
    2424           0 :     if (ret)
    2425           0 :         return ret;
    2426             : 
    2427           0 :     label.data = (void *)constant;
    2428           0 :     label.length = len;
    2429             : 
    2430           0 :     ret = _krb5_SP800_108_HMAC_KDF(context, &key->key->keyvalue,
    2431             :                                    &label, NULL, md, &K1);
    2432           0 :     if (ret == 0) {
    2433           0 :         if (key->key->keyvalue.length > key_len)
    2434           0 :             key->key->keyvalue.length = key_len;
    2435           0 :         memcpy(key->key->keyvalue.data, K1.data, key_len);
    2436             :     }
    2437             : 
    2438           0 :     memset_s(K1.data, K1.length, 0, K1.length);
    2439           0 :     krb5_data_free(&K1);
    2440             : 
    2441           0 :     return ret;
    2442             : }
    2443             : 
    2444             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
    2445     2377561 : _krb5_derive_key(krb5_context context,
    2446             :                  struct _krb5_encryption_type *et,
    2447             :                  struct _krb5_key_data *key,
    2448             :                  const void *constant,
    2449             :                  size_t len)
    2450             : {
    2451             :     krb5_error_code ret;
    2452             : 
    2453     2377561 :     ret = _key_schedule(context, key);
    2454     2377561 :     if(ret)
    2455           0 :         return ret;
    2456             : 
    2457     2377561 :     switch (et->flags & F_KDF_MASK) {
    2458     2377561 :     case F_RFC3961_KDF:
    2459     2377561 :         ret = derive_key_rfc3961(context, et, key, constant, len);
    2460     2377561 :         break;
    2461           0 :     case F_SP800_108_HMAC_KDF:
    2462           0 :         ret = derive_key_sp800_hmac(context, et, key, constant, len);
    2463           0 :         break;
    2464           0 :     default:
    2465           0 :         ret = KRB5_CRYPTO_INTERNAL;
    2466           0 :         krb5_set_error_message(context, ret,
    2467           0 :                                N_("derive_key() called with unknown keytype (%u)", ""),
    2468           0 :                                et->keytype->type);
    2469           0 :         break;
    2470             :     }
    2471             : 
    2472     2377561 :     if (key->schedule) {
    2473     2377561 :         free_key_schedule(context, key, et);
    2474     2377561 :         key->schedule = NULL;
    2475             :     }
    2476             : 
    2477     2377561 :     return ret;
    2478             : }
    2479             : 
    2480             : static struct _krb5_key_data *
    2481     1798528 : _new_derived_key(krb5_crypto crypto, unsigned usage)
    2482             : {
    2483     1798528 :     struct _krb5_key_usage *d = crypto->key_usage;
    2484     1798528 :     d = realloc(d, (crypto->num_key_usage + 1) * sizeof(*d));
    2485     1798528 :     if(d == NULL)
    2486           0 :         return NULL;
    2487     1798528 :     crypto->key_usage = d;
    2488     1798528 :     d += crypto->num_key_usage++;
    2489     1798528 :     memset(d, 0, sizeof(*d));
    2490     1798528 :     d->usage = usage;
    2491     1798528 :     return &d->key;
    2492             : }
    2493             : 
    2494             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
    2495      511178 : krb5_derive_key(krb5_context context,
    2496             :                 const krb5_keyblock *key,
    2497             :                 krb5_enctype etype,
    2498             :                 const void *constant,
    2499             :                 size_t constant_len,
    2500             :                 krb5_keyblock **derived_key)
    2501             : {
    2502             :     krb5_error_code ret;
    2503             :     struct _krb5_encryption_type *et;
    2504             :     struct _krb5_key_data d;
    2505             : 
    2506      511178 :     *derived_key = NULL;
    2507             : 
    2508      511178 :     et = _krb5_find_enctype (etype);
    2509      511178 :     if (et == NULL) {
    2510           0 :         return unsupported_enctype (context, etype);
    2511             :     }
    2512             : 
    2513      511178 :     ret = krb5_copy_keyblock(context, key, &d.key);
    2514      511178 :     if (ret)
    2515           0 :         return ret;
    2516             : 
    2517      511178 :     d.schedule = NULL;
    2518      511178 :     ret = _krb5_derive_key(context, et, &d, constant, constant_len);
    2519      511178 :     if (ret == 0)
    2520      511178 :         ret = krb5_copy_keyblock(context, d.key, derived_key);
    2521      511178 :     _krb5_free_key_data(context, &d, et);
    2522      511178 :     return ret;
    2523             : }
    2524             : 
    2525             : static krb5_error_code
    2526     6991191 : _get_derived_key(krb5_context context,
    2527             :                  krb5_crypto crypto,
    2528             :                  unsigned usage,
    2529             :                  struct _krb5_key_data **key)
    2530             : {
    2531             :     int i;
    2532             :     struct _krb5_key_data *d;
    2533             :     unsigned char constant[5];
    2534             : 
    2535     6991191 :     *key = NULL;
    2536    23489078 :     for(i = 0; i < crypto->num_key_usage; i++)
    2537    21690550 :         if(crypto->key_usage[i].usage == usage) {
    2538     5192663 :             *key = &crypto->key_usage[i].key;
    2539     5192663 :             return 0;
    2540             :         }
    2541     1798528 :     d = _new_derived_key(crypto, usage);
    2542     1798528 :     if (d == NULL)
    2543           0 :         return krb5_enomem(context);
    2544     1798528 :     *key = d;
    2545     1798528 :     krb5_copy_keyblock(context, crypto->key.key, &d->key);
    2546     1798528 :     _krb5_put_int(constant, usage, sizeof(constant));
    2547     1798528 :     return _krb5_derive_key(context, crypto->et, d, constant, sizeof(constant));
    2548             : }
    2549             : 
    2550             : /**
    2551             :  * Create a crypto context used for all encryption and signature
    2552             :  * operation. The encryption type to use is taken from the key, but
    2553             :  * can be overridden with the enctype parameter.  This can be useful
    2554             :  * for encryptions types which is compatiable (DES for example).
    2555             :  *
    2556             :  * To free the crypto context, use krb5_crypto_destroy().
    2557             :  *
    2558             :  * @param context Kerberos context
    2559             :  * @param key the key block information with all key data
    2560             :  * @param etype the encryption type
    2561             :  * @param crypto the resulting crypto context
    2562             :  *
    2563             :  * @return Return an error code or 0.
    2564             :  *
    2565             :  * @ingroup krb5_crypto
    2566             :  */
    2567             : 
    2568             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
    2569     1494323 : krb5_crypto_init(krb5_context context,
    2570             :                  const krb5_keyblock *key,
    2571             :                  krb5_enctype etype,
    2572             :                  krb5_crypto *crypto)
    2573             : {
    2574             :     krb5_error_code ret;
    2575     1494323 :     ALLOC(*crypto, 1);
    2576     1494323 :     if (*crypto == NULL)
    2577           0 :         return krb5_enomem(context);
    2578     1494323 :     if(etype == ETYPE_NULL)
    2579     1379701 :         etype = key->keytype;
    2580     1494323 :     (*crypto)->et = _krb5_find_enctype(etype);
    2581     1494323 :     if((*crypto)->et == NULL || ((*crypto)->et->flags & F_DISABLED)) {
    2582           0 :         free(*crypto);
    2583           0 :         *crypto = NULL;
    2584           0 :         return unsupported_enctype(context, etype);
    2585             :     }
    2586     1494323 :     if((*crypto)->et->keytype->size != key->keyvalue.length) {
    2587           0 :         free(*crypto);
    2588           0 :         *crypto = NULL;
    2589           0 :         krb5_set_error_message (context, KRB5_BAD_KEYSIZE,
    2590             :                                 "encryption key has bad length");
    2591           0 :         return KRB5_BAD_KEYSIZE;
    2592             :     }
    2593     1494323 :     ret = krb5_copy_keyblock(context, key, &(*crypto)->key.key);
    2594     1494323 :     if(ret) {
    2595           0 :         free(*crypto);
    2596           0 :         *crypto = NULL;
    2597           0 :         return ret;
    2598             :     }
    2599     1494323 :     (*crypto)->key.schedule = NULL;
    2600     1494323 :     (*crypto)->num_key_usage = 0;
    2601     1494323 :     (*crypto)->key_usage = NULL;
    2602     1494323 :     (*crypto)->flags = 0;
    2603     1494323 :     return 0;
    2604             : }
    2605             : 
    2606             : static void
    2607     4317791 : free_key_schedule(krb5_context context,
    2608             :                   struct _krb5_key_data *key,
    2609             :                   struct _krb5_encryption_type *et)
    2610             : {
    2611     4317791 :     if (et->keytype->cleanup)
    2612     4317791 :         (*et->keytype->cleanup)(context, key);
    2613     4317791 :     memset(key->schedule->data, 0, key->schedule->length);
    2614     4317791 :     krb5_free_data(context, key->schedule);
    2615     4317791 : }
    2616             : 
    2617             : KRB5_LIB_FUNCTION void KRB5_LIB_CALL
    2618     3871846 : _krb5_free_key_data(krb5_context context, struct _krb5_key_data *key,
    2619             :               struct _krb5_encryption_type *et)
    2620             : {
    2621     3871846 :     krb5_free_keyblock(context, key->key);
    2622     3871846 :     if(key->schedule) {
    2623     1940230 :         free_key_schedule(context, key, et);
    2624     1940230 :         key->schedule = NULL;
    2625             :     }
    2626     3871846 : }
    2627             : 
    2628             : static void
    2629     1798528 : free_key_usage(krb5_context context, struct _krb5_key_usage *ku,
    2630             :                struct _krb5_encryption_type *et)
    2631             : {
    2632     1798528 :     _krb5_free_key_data(context, &ku->key, et);
    2633     1798528 : }
    2634             : 
    2635             : /**
    2636             :  * Free a crypto context created by krb5_crypto_init().
    2637             :  *
    2638             :  * @param context Kerberos context
    2639             :  * @param crypto crypto context to free
    2640             :  *
    2641             :  * @return Return an error code or 0.
    2642             :  *
    2643             :  * @ingroup krb5_crypto
    2644             :  */
    2645             : 
    2646             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
    2647     1494285 : krb5_crypto_destroy(krb5_context context,
    2648             :                     krb5_crypto crypto)
    2649             : {
    2650             :     int i;
    2651             : 
    2652     3292813 :     for(i = 0; i < crypto->num_key_usage; i++)
    2653     1798528 :         free_key_usage(context, &crypto->key_usage[i], crypto->et);
    2654     1494285 :     free(crypto->key_usage);
    2655     1494285 :     _krb5_free_key_data(context, &crypto->key, crypto->et);
    2656             : 
    2657     1494285 :     if (crypto->mdctx)
    2658      413324 :         EVP_MD_CTX_destroy(crypto->mdctx);
    2659             : 
    2660     1494285 :     if (crypto->hmacctx)
    2661      874579 :         HMAC_CTX_free(crypto->hmacctx);
    2662             : 
    2663     1494285 :     free (crypto);
    2664     1494285 :     return 0;
    2665             : }
    2666             : 
    2667             : /**
    2668             :  * Return the blocksize used algorithm referenced by the crypto context
    2669             :  *
    2670             :  * @param context Kerberos context
    2671             :  * @param crypto crypto context to query
    2672             :  * @param blocksize the resulting blocksize
    2673             :  *
    2674             :  * @return Return an error code or 0.
    2675             :  *
    2676             :  * @ingroup krb5_crypto
    2677             :  */
    2678             : 
    2679             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
    2680     1071467 : krb5_crypto_getblocksize(krb5_context context,
    2681             :                          krb5_crypto crypto,
    2682             :                          size_t *blocksize)
    2683             : {
    2684     1071467 :     *blocksize = crypto->et->blocksize;
    2685     1071467 :     return 0;
    2686             : }
    2687             : 
    2688             : /**
    2689             :  * Return the encryption type used by the crypto context
    2690             :  *
    2691             :  * @param context Kerberos context
    2692             :  * @param crypto crypto context to query
    2693             :  * @param enctype the resulting encryption type
    2694             :  *
    2695             :  * @return Return an error code or 0.
    2696             :  *
    2697             :  * @ingroup krb5_crypto
    2698             :  */
    2699             : 
    2700             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
    2701           1 : krb5_crypto_getenctype(krb5_context context,
    2702             :                        krb5_crypto crypto,
    2703             :                        krb5_enctype *enctype)
    2704             : {
    2705           1 :     *enctype = crypto->et->type;
    2706           1 :     return 0;
    2707             : }
    2708             : 
    2709             : /**
    2710             :  * Return the padding size used by the crypto context
    2711             :  *
    2712             :  * @param context Kerberos context
    2713             :  * @param crypto crypto context to query
    2714             :  * @param padsize the return padding size
    2715             :  *
    2716             :  * @return Return an error code or 0.
    2717             :  *
    2718             :  * @ingroup krb5_crypto
    2719             :  */
    2720             : 
    2721             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
    2722      564375 : krb5_crypto_getpadsize(krb5_context context,
    2723             :                        krb5_crypto crypto,
    2724             :                        size_t *padsize)
    2725             : {
    2726      564375 :     *padsize = crypto->et->padsize;
    2727      564375 :     return 0;
    2728             : }
    2729             : 
    2730             : /**
    2731             :  * Return the confounder size used by the crypto context
    2732             :  *
    2733             :  * @param context Kerberos context
    2734             :  * @param crypto crypto context to query
    2735             :  * @param confoundersize the returned confounder size
    2736             :  *
    2737             :  * @return Return an error code or 0.
    2738             :  *
    2739             :  * @ingroup krb5_crypto
    2740             :  */
    2741             : 
    2742             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
    2743           0 : krb5_crypto_getconfoundersize(krb5_context context,
    2744             :                               krb5_crypto crypto,
    2745             :                               size_t *confoundersize)
    2746             : {
    2747           0 :     *confoundersize = crypto->et->confoundersize;
    2748           0 :     return 0;
    2749             : }
    2750             : 
    2751             : 
    2752             : /**
    2753             :  * Disable encryption type
    2754             :  *
    2755             :  * @param context Kerberos 5 context
    2756             :  * @param enctype encryption type to disable
    2757             :  *
    2758             :  * @return Return an error code or 0.
    2759             :  *
    2760             :  * @ingroup krb5_crypto
    2761             :  */
    2762             : 
    2763             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
    2764           0 : krb5_enctype_disable(krb5_context context,
    2765             :                      krb5_enctype enctype)
    2766             : {
    2767           0 :     struct _krb5_encryption_type *et = _krb5_find_enctype(enctype);
    2768           0 :     if(et == NULL) {
    2769           0 :         if (context)
    2770           0 :             krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
    2771           0 :                                     N_("encryption type %d not supported", ""),
    2772             :                                     enctype);
    2773           0 :         return KRB5_PROG_ETYPE_NOSUPP;
    2774             :     }
    2775           0 :     et->flags |= F_DISABLED;
    2776           0 :     return 0;
    2777             : }
    2778             : 
    2779             : /**
    2780             :  * Enable encryption type
    2781             :  *
    2782             :  * @param context Kerberos 5 context
    2783             :  * @param enctype encryption type to enable
    2784             :  *
    2785             :  * @return Return an error code or 0.
    2786             :  *
    2787             :  * @ingroup krb5_crypto
    2788             :  */
    2789             : 
    2790             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
    2791           0 : krb5_enctype_enable(krb5_context context,
    2792             :                     krb5_enctype enctype)
    2793             : {
    2794           0 :     struct _krb5_encryption_type *et = _krb5_find_enctype(enctype);
    2795           0 :     if(et == NULL) {
    2796           0 :         if (context)
    2797           0 :             krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
    2798           0 :                                     N_("encryption type %d not supported", ""),
    2799             :                                     enctype);
    2800           0 :         return KRB5_PROG_ETYPE_NOSUPP;
    2801             :     }
    2802           0 :     et->flags &= ~F_DISABLED;
    2803           0 :     return 0;
    2804             : }
    2805             : 
    2806             : /**
    2807             :  * Enable or disable all weak encryption types
    2808             :  *
    2809             :  * @param context Kerberos 5 context
    2810             :  * @param enable true to enable, false to disable
    2811             :  *
    2812             :  * @return Return an error code or 0.
    2813             :  *
    2814             :  * @ingroup krb5_crypto
    2815             :  */
    2816             : 
    2817             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
    2818           0 : krb5_allow_weak_crypto(krb5_context context,
    2819             :                        krb5_boolean enable)
    2820             : {
    2821             :     int i;
    2822             : 
    2823           0 :     for(i = 0; i < _krb5_num_etypes; i++)
    2824           0 :         if(_krb5_etypes[i]->flags & F_WEAK) {
    2825           0 :             if(enable)
    2826           0 :                 _krb5_etypes[i]->flags &= ~F_DISABLED;
    2827             :             else
    2828           0 :                 _krb5_etypes[i]->flags |= F_DISABLED;
    2829             :         }
    2830           0 :     return 0;
    2831             : }
    2832             : 
    2833             : /**
    2834             :  * Returns is the encryption is strong or weak
    2835             :  *
    2836             :  * @param context Kerberos 5 context
    2837             :  * @param enctype encryption type to probe
    2838             :  *
    2839             :  * @return Returns true if encryption type is weak or is not supported.
    2840             :  *
    2841             :  * @ingroup krb5_crypto
    2842             :  */
    2843             : 
    2844             : KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL
    2845        2013 : krb5_is_enctype_weak(krb5_context context, krb5_enctype enctype)
    2846             : {
    2847        2013 :     struct _krb5_encryption_type *et = _krb5_find_enctype(enctype);
    2848        2013 :     if(et == NULL || (et->flags & F_WEAK))
    2849          43 :         return TRUE;
    2850        1970 :     return FALSE;
    2851             : }
    2852             : 
    2853             : /**
    2854             :  * Returns whether the encryption type is new or old
    2855             :  *
    2856             :  * @param context Kerberos 5 context
    2857             :  * @param enctype encryption type to probe
    2858             :  *
    2859             :  * @return Returns true if encryption type is old or is not supported.
    2860             :  *
    2861             :  * @ingroup krb5_crypto
    2862             :  */
    2863             : 
    2864             : KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL
    2865       12170 : krb5_is_enctype_old(krb5_context context, krb5_enctype enctype)
    2866             : {
    2867       12170 :     struct _krb5_encryption_type *et = _krb5_find_enctype(enctype);
    2868       12170 :     if (!et  || (et->flags & F_OLD))
    2869        1100 :         return TRUE;
    2870       11070 :     return FALSE;
    2871             : }
    2872             : 
    2873             : /**
    2874             :  * Returns whether the encryption type should use randomly generated salts
    2875             :  *
    2876             :  * @param context Kerberos 5 context
    2877             :  * @param enctype encryption type to probe
    2878             :  *
    2879             :  * @return Returns true if generated salts should have random component
    2880             :  *
    2881             :  * @ingroup krb5_crypto
    2882             :  */
    2883             : KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL
    2884           0 : _krb5_enctype_requires_random_salt(krb5_context context,
    2885             :                                    krb5_enctype enctype)
    2886             : {
    2887             :     struct _krb5_encryption_type *et;
    2888             : 
    2889           0 :     et = _krb5_find_enctype (enctype);
    2890             : 
    2891           0 :     return et && (et->flags & F_SP800_108_HMAC_KDF);
    2892             : }
    2893             : 
    2894             : static size_t
    2895           0 : wrapped_length (krb5_context context,
    2896             :                 krb5_crypto  crypto,
    2897             :                 size_t       data_len)
    2898             : {
    2899           0 :     struct _krb5_encryption_type *et = crypto->et;
    2900           0 :     size_t padsize = et->padsize;
    2901           0 :     size_t checksumsize = CHECKSUMSIZE(et->checksum);
    2902             :     size_t res;
    2903             : 
    2904           0 :     res =  et->confoundersize + checksumsize + data_len;
    2905           0 :     res =  (res + padsize - 1) / padsize * padsize;
    2906           0 :     return res;
    2907             : }
    2908             : 
    2909             : static size_t
    2910     1094756 : wrapped_length_dervied (krb5_context context,
    2911             :                         krb5_crypto  crypto,
    2912             :                         size_t       data_len)
    2913             : {
    2914     1094756 :     struct _krb5_encryption_type *et = crypto->et;
    2915     1094756 :     size_t padsize = et->padsize;
    2916             :     size_t res;
    2917             : 
    2918     1094756 :     res =  et->confoundersize + data_len;
    2919     1094756 :     res =  (res + padsize - 1) / padsize * padsize;
    2920     1094756 :     if (et->keyed_checksum)
    2921     1094756 :         res += et->keyed_checksum->checksumsize;
    2922             :     else
    2923           0 :         res += et->checksum->checksumsize;
    2924     1094756 :     return res;
    2925             : }
    2926             : 
    2927             : /*
    2928             :  * Return the size of an encrypted packet of length `data_len'
    2929             :  */
    2930             : 
    2931             : KRB5_LIB_FUNCTION size_t KRB5_LIB_CALL
    2932     1094756 : krb5_get_wrapped_length (krb5_context context,
    2933             :                          krb5_crypto  crypto,
    2934             :                          size_t       data_len)
    2935             : {
    2936     1094756 :     if (derived_crypto (context, crypto))
    2937     1094756 :         return wrapped_length_dervied (context, crypto, data_len);
    2938             :     else
    2939           0 :         return wrapped_length (context, crypto, data_len);
    2940             : }
    2941             : 
    2942             : /*
    2943             :  * Return the size of an encrypted packet of length `data_len'
    2944             :  */
    2945             : 
    2946             : static size_t
    2947           0 : crypto_overhead (krb5_context context,
    2948             :                  krb5_crypto  crypto)
    2949             : {
    2950           0 :     struct _krb5_encryption_type *et = crypto->et;
    2951             :     size_t res;
    2952             : 
    2953           0 :     res = CHECKSUMSIZE(et->checksum);
    2954           0 :     res += et->confoundersize;
    2955           0 :     if (et->padsize > 1)
    2956           0 :         res += et->padsize;
    2957           0 :     return res;
    2958             : }
    2959             : 
    2960             : static size_t
    2961           0 : crypto_overhead_dervied (krb5_context context,
    2962             :                          krb5_crypto  crypto)
    2963             : {
    2964           0 :     struct _krb5_encryption_type *et = crypto->et;
    2965             :     size_t res;
    2966             : 
    2967           0 :     if (et->keyed_checksum)
    2968           0 :         res = CHECKSUMSIZE(et->keyed_checksum);
    2969             :     else
    2970           0 :         res = CHECKSUMSIZE(et->checksum);
    2971           0 :     res += et->confoundersize;
    2972           0 :     if (et->padsize > 1)
    2973           0 :         res += et->padsize;
    2974           0 :     return res;
    2975             : }
    2976             : 
    2977             : KRB5_LIB_FUNCTION size_t KRB5_LIB_CALL
    2978           0 : krb5_crypto_overhead (krb5_context context, krb5_crypto crypto)
    2979             : {
    2980           0 :     if (derived_crypto (context, crypto))
    2981           0 :         return crypto_overhead_dervied (context, crypto);
    2982             :     else
    2983           0 :         return crypto_overhead (context, crypto);
    2984             : }
    2985             : 
    2986             : /**
    2987             :  * Converts the random bytestring to a protocol key according to
    2988             :  * Kerberos crypto frame work. It may be assumed that all the bits of
    2989             :  * the input string are equally random, even though the entropy
    2990             :  * present in the random source may be limited.
    2991             :  *
    2992             :  * @param context Kerberos 5 context
    2993             :  * @param type the enctype resulting key will be of
    2994             :  * @param data input random data to convert to a key
    2995             :  * @param size size of input random data, at least krb5_enctype_keysize() long
    2996             :  * @param key key, output key, free with krb5_free_keyblock_contents()
    2997             :  *
    2998             :  * @return Return an error code or 0.
    2999             :  *
    3000             :  * @ingroup krb5_crypto
    3001             :  */
    3002             : 
    3003             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
    3004      131047 : krb5_random_to_key(krb5_context context,
    3005             :                    krb5_enctype type,
    3006             :                    const void *data,
    3007             :                    size_t size,
    3008             :                    krb5_keyblock *key)
    3009             : {
    3010             :     krb5_error_code ret;
    3011      131047 :     struct _krb5_encryption_type *et = _krb5_find_enctype(type);
    3012      131047 :     if(et == NULL) {
    3013           0 :         krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
    3014           0 :                                N_("encryption type %d not supported", ""),
    3015             :                                type);
    3016           0 :         return KRB5_PROG_ETYPE_NOSUPP;
    3017             :     }
    3018      131047 :     if ((et->keytype->bits + 7) / 8 > size) {
    3019           0 :         krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
    3020           0 :                                N_("encryption key %s needs %d bytes "
    3021             :                                   "of random to make an encryption key "
    3022             :                                   "out of it", ""),
    3023           0 :                                et->name, (int)et->keytype->size);
    3024           0 :         return KRB5_PROG_ETYPE_NOSUPP;
    3025             :     }
    3026      131047 :     ret = krb5_data_alloc(&key->keyvalue, et->keytype->size);
    3027      131047 :     if(ret)
    3028           0 :         return ret;
    3029      131047 :     key->keytype = type;
    3030      131047 :     if (et->keytype->random_to_key)
    3031           0 :         (*et->keytype->random_to_key)(context, key, data, size);
    3032             :     else
    3033      131047 :         memcpy(key->keyvalue.data, data, et->keytype->size);
    3034             : 
    3035      131047 :     return 0;
    3036             : }
    3037             : 
    3038             : 
    3039             : 
    3040             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
    3041           0 : krb5_crypto_prf_length(krb5_context context,
    3042             :                        krb5_enctype type,
    3043             :                        size_t *length)
    3044             : {
    3045           0 :     struct _krb5_encryption_type *et = _krb5_find_enctype(type);
    3046             : 
    3047           0 :     if(et == NULL || et->prf_length == 0) {
    3048           0 :         krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
    3049           0 :                                N_("encryption type %d not supported", ""),
    3050             :                                type);
    3051           0 :         return KRB5_PROG_ETYPE_NOSUPP;
    3052             :     }
    3053             : 
    3054           0 :     *length = et->prf_length;
    3055           0 :     return 0;
    3056             : }
    3057             : 
    3058             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
    3059      518860 : krb5_crypto_prf(krb5_context context,
    3060             :                 const krb5_crypto crypto,
    3061             :                 const krb5_data *input,
    3062             :                 krb5_data *output)
    3063             : {
    3064      518860 :     struct _krb5_encryption_type *et = crypto->et;
    3065             : 
    3066      518860 :     krb5_data_zero(output);
    3067             : 
    3068      518860 :     if(et->prf == NULL) {
    3069           0 :         krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
    3070             :                                "kerberos prf for %s not supported",
    3071             :                                et->name);
    3072           0 :         return KRB5_PROG_ETYPE_NOSUPP;
    3073             :     }
    3074             : 
    3075      518860 :     return (*et->prf)(context, crypto, input, output);
    3076             : }
    3077             : 
    3078             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
    3079      263271 : krb5_crypto_prfplus(krb5_context context,
    3080             :                     const krb5_crypto crypto,
    3081             :                     const krb5_data *input,
    3082             :                     size_t length,
    3083             :                     krb5_data *output)
    3084             : {
    3085             :     krb5_error_code ret;
    3086             :     krb5_data input2;
    3087      263271 :     unsigned char i = 1;
    3088             :     unsigned char *p;
    3089             : 
    3090      263271 :     krb5_data_zero(&input2);
    3091      263271 :     krb5_data_zero(output);
    3092             : 
    3093      263271 :     krb5_clear_error_message(context);
    3094             : 
    3095      263271 :     ret = krb5_data_alloc(output, length);
    3096      263271 :     if (ret) goto out;
    3097      263271 :     ret = krb5_data_alloc(&input2, input->length + 1);
    3098      263271 :     if (ret) goto out;
    3099             : 
    3100      263271 :     krb5_clear_error_message(context);
    3101             : 
    3102      263271 :     memcpy(((unsigned char *)input2.data) + 1, input->data, input->length);
    3103             : 
    3104      263271 :     p = output->data;
    3105             : 
    3106     1045402 :     while (length) {
    3107             :         krb5_data block;
    3108             : 
    3109      518860 :         ((unsigned char *)input2.data)[0] = i++;
    3110             : 
    3111      518860 :         ret = krb5_crypto_prf(context, crypto, &input2, &block);
    3112      518860 :         if (ret)
    3113           0 :             goto out;
    3114             : 
    3115      518860 :         if (block.length < length) {
    3116      255589 :             memcpy(p, block.data, block.length);
    3117      255589 :             length -= block.length;
    3118             :         } else {
    3119      263271 :             memcpy(p, block.data, length);
    3120      263271 :             length = 0;
    3121             :         }
    3122      518860 :         p += block.length;
    3123      518860 :         krb5_data_free(&block);
    3124             :     }
    3125             : 
    3126      263271 :  out:
    3127      263271 :     krb5_data_free(&input2);
    3128      263271 :     if (ret)
    3129           0 :         krb5_data_free(output);
    3130      263271 :     return ret;
    3131             : }
    3132             : 
    3133             : /**
    3134             :  * The FX-CF2 key derivation function, used in FAST and preauth framework.
    3135             :  *
    3136             :  * @param context Kerberos 5 context
    3137             :  * @param crypto1 first key to combine
    3138             :  * @param crypto2 second key to combine
    3139             :  * @param pepper1 factor to combine with first key to garante uniqueness
    3140             :  * @param pepper2 factor to combine with second key to garante uniqueness
    3141             :  * @param enctype the encryption type of the resulting key
    3142             :  * @param res allocated key, free with krb5_free_keyblock_contents()
    3143             :  *
    3144             :  * @return Return an error code or 0.
    3145             :  *
    3146             :  * @ingroup krb5_crypto
    3147             :  */
    3148             : 
    3149             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
    3150      131047 : krb5_crypto_fx_cf2(krb5_context context,
    3151             :                    const krb5_crypto crypto1,
    3152             :                    const krb5_crypto crypto2,
    3153             :                    krb5_data *pepper1,
    3154             :                    krb5_data *pepper2,
    3155             :                    krb5_enctype enctype,
    3156             :                    krb5_keyblock *res)
    3157             : {
    3158             :     krb5_error_code ret;
    3159             :     krb5_data os1, os2;
    3160             :     size_t i, keysize;
    3161             : 
    3162      131047 :     memset(res, 0, sizeof(*res));
    3163      131047 :     krb5_data_zero(&os1);
    3164      131047 :     krb5_data_zero(&os2);
    3165             : 
    3166      131047 :     ret = krb5_enctype_keybits(context, enctype, &keysize);
    3167      131047 :     if (ret)
    3168           0 :         return ret;
    3169      131047 :     keysize = (keysize + 7) / 8;
    3170             : 
    3171      131047 :     ret = krb5_crypto_prfplus(context, crypto1, pepper1, keysize, &os1);
    3172      131047 :     if (ret)
    3173           0 :         goto out;
    3174      131047 :     ret = krb5_crypto_prfplus(context, crypto2, pepper2, keysize, &os2);
    3175      131047 :     if (ret)
    3176           0 :         goto out;
    3177             : 
    3178      131047 :     res->keytype = enctype;
    3179             :     {
    3180      131047 :         unsigned char *p1 = os1.data, *p2 = os2.data;
    3181     4263095 :         for (i = 0; i < keysize; i++)
    3182     4132048 :             p1[i] ^= p2[i];
    3183             :     }
    3184      131047 :     ret = krb5_random_to_key(context, enctype, os1.data, keysize, res);
    3185      131047 :  out:
    3186      131047 :     krb5_data_free(&os1);
    3187      131047 :     krb5_data_free(&os2);
    3188             : 
    3189      131047 :     return ret;
    3190             : }
    3191             : 
    3192             : KRB5_LIB_FUNCTION void KRB5_LIB_CALL
    3193       79524 : _krb5_crypto_set_flags(krb5_context context,
    3194             :                        krb5_crypto crypto,
    3195             :                        krb5_flags flags)
    3196             : {
    3197       79524 :     crypto->flags |= flags;
    3198       79524 : }
    3199             : 
    3200             : #ifndef HEIMDAL_SMALLER
    3201             : 
    3202             : /**
    3203             :  * Deprecated: keytypes doesn't exists, they are really enctypes.
    3204             :  *
    3205             :  * @ingroup krb5_deprecated
    3206             :  */
    3207             : 
    3208             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
    3209           0 : krb5_keytype_to_enctypes (krb5_context context,
    3210             :                           krb5_keytype keytype,
    3211             :                           unsigned *len,
    3212             :                           krb5_enctype **val)
    3213             :     KRB5_DEPRECATED_FUNCTION("Use X instead")
    3214             : {
    3215             :     int i;
    3216           0 :     unsigned n = 0;
    3217             :     krb5_enctype *ret;
    3218             : 
    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 :             ++n;
    3224             :     }
    3225           0 :     if (n == 0) {
    3226           0 :         krb5_set_error_message(context, KRB5_PROG_KEYTYPE_NOSUPP,
    3227             :                                "Keytype have no mapping");
    3228           0 :         return KRB5_PROG_KEYTYPE_NOSUPP;
    3229             :     }
    3230             : 
    3231           0 :     ret = malloc(n * sizeof(*ret));
    3232           0 :     if (ret == NULL && n != 0)
    3233           0 :         return krb5_enomem(context);
    3234           0 :     n = 0;
    3235           0 :     for (i = _krb5_num_etypes - 1; i >= 0; --i) {
    3236           0 :         if (_krb5_etypes[i]->keytype->type == keytype
    3237           0 :             && !(_krb5_etypes[i]->flags & F_PSEUDO)
    3238           0 :             && krb5_enctype_valid(context, _krb5_etypes[i]->type) == 0)
    3239           0 :             ret[n++] = _krb5_etypes[i]->type;
    3240             :     }
    3241           0 :     *len = n;
    3242           0 :     *val = ret;
    3243           0 :     return 0;
    3244             : }
    3245             : 
    3246             : /**
    3247             :  * Deprecated: keytypes doesn't exists, they are really enctypes.
    3248             :  *
    3249             :  * @ingroup krb5_deprecated
    3250             :  */
    3251             : 
    3252             : /* if two enctypes have compatible keys */
    3253             : KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL
    3254           0 : krb5_enctypes_compatible_keys(krb5_context context,
    3255             :                               krb5_enctype etype1,
    3256             :                               krb5_enctype etype2)
    3257             :     KRB5_DEPRECATED_FUNCTION("Use X instead")
    3258             : {
    3259           0 :     struct _krb5_encryption_type *e1 = _krb5_find_enctype(etype1);
    3260           0 :     struct _krb5_encryption_type *e2 = _krb5_find_enctype(etype2);
    3261           0 :     return e1 != NULL && e2 != NULL && e1->keytype == e2->keytype;
    3262             : }
    3263             : 
    3264             : #endif /* HEIMDAL_SMALLER */

Generated by: LCOV version 1.13