LCOV - code coverage report
Current view: top level - source4/heimdal/lib/krb5 - crypto.c (source / functions) Hit Total Coverage
Test: coverage report for abartlet/fix-coverage dd10fb34 Lines: 606 1214 49.9 %
Date: 2021-09-23 10:06:22 Functions: 56 79 70.9 %

          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             :  *                                                          *
      56             :  ************************************************************/
      57             : 
      58             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
      59      684137 : krb5_enctype_keysize(krb5_context context,
      60             :                      krb5_enctype type,
      61             :                      size_t *keysize)
      62             : {
      63      684137 :     struct _krb5_encryption_type *et = _krb5_find_enctype(type);
      64      684137 :     if(et == NULL) {
      65         328 :         krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
      66         328 :                                N_("encryption type %d not supported", ""),
      67             :                                type);
      68         328 :         return KRB5_PROG_ETYPE_NOSUPP;
      69             :     }
      70      683809 :     *keysize = et->keytype->size;
      71      683809 :     return 0;
      72             : }
      73             : 
      74             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
      75           0 : krb5_enctype_keybits(krb5_context context,
      76             :                      krb5_enctype type,
      77             :                      size_t *keybits)
      78             : {
      79           0 :     struct _krb5_encryption_type *et = _krb5_find_enctype(type);
      80           0 :     if(et == NULL) {
      81           0 :         krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
      82             :                                "encryption type %d not supported",
      83             :                                type);
      84           0 :         return KRB5_PROG_ETYPE_NOSUPP;
      85             :     }
      86           0 :     *keybits = et->keytype->bits;
      87           0 :     return 0;
      88             : }
      89             : 
      90             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
      91      175493 : krb5_generate_random_keyblock(krb5_context context,
      92             :                               krb5_enctype type,
      93             :                               krb5_keyblock *key)
      94             : {
      95             :     krb5_error_code ret;
      96      175493 :     struct _krb5_encryption_type *et = _krb5_find_enctype(type);
      97      175493 :     if(et == NULL) {
      98           0 :         krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
      99           0 :                                N_("encryption type %d not supported", ""),
     100             :                                type);
     101           0 :         return KRB5_PROG_ETYPE_NOSUPP;
     102             :     }
     103      175493 :     ret = krb5_data_alloc(&key->keyvalue, et->keytype->size);
     104      175493 :     if(ret)
     105           0 :         return ret;
     106      175493 :     key->keytype = type;
     107      175493 :     if(et->keytype->random_key)
     108           0 :         (*et->keytype->random_key)(context, key);
     109             :     else
     110      175493 :         krb5_generate_random_block(key->keyvalue.data,
     111             :                                    key->keyvalue.length);
     112      171237 :     return 0;
     113             : }
     114             : 
     115             : static krb5_error_code
     116     7348096 : _key_schedule(krb5_context context,
     117             :               struct _krb5_key_data *key)
     118             : {
     119             :     krb5_error_code ret;
     120     7348096 :     struct _krb5_encryption_type *et = _krb5_find_enctype(key->key->keytype);
     121             :     struct _krb5_key_type *kt;
     122             : 
     123     7348096 :     if (et == NULL) {
     124           0 :         krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
     125           0 :                                 N_("encryption type %d not supported", ""),
     126           0 :                                 key->key->keytype);
     127           0 :         return KRB5_PROG_ETYPE_NOSUPP;
     128             :     }
     129             : 
     130     7348096 :     kt = et->keytype;
     131             : 
     132     7348096 :     if(kt->schedule == NULL)
     133           0 :         return 0;
     134     7348096 :     if (key->schedule != NULL)
     135     4035128 :         return 0;
     136     3306830 :     ALLOC(key->schedule, 1);
     137     3306830 :     if(key->schedule == NULL) {
     138           0 :         krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
     139           0 :         return ENOMEM;
     140             :     }
     141     3306830 :     ret = krb5_data_alloc(key->schedule, kt->schedule_size);
     142     3306830 :     if(ret) {
     143           0 :         free(key->schedule);
     144           0 :         key->schedule = NULL;
     145           0 :         return ret;
     146             :     }
     147     3306830 :     (*kt->schedule)(context, kt, key);
     148     3306830 :     return 0;
     149             : }
     150             : 
     151             : /************************************************************
     152             :  *                                                          *
     153             :  ************************************************************/
     154             : 
     155             : static krb5_error_code
     156     6857780 : SHA1_checksum(krb5_context context,
     157             :               struct _krb5_key_data *key,
     158             :               const void *data,
     159             :               size_t len,
     160             :               unsigned usage,
     161             :               Checksum *C)
     162             : {
     163     6857780 :     if (EVP_Digest(data, len, C->checksum.data, NULL, EVP_sha1(), NULL) != 1)
     164           0 :         krb5_abortx(context, "sha1 checksum failed");
     165     6857780 :     return 0;
     166             : }
     167             : 
     168             : /* HMAC according to RFC2104 */
     169             : krb5_error_code
     170     4371839 : _krb5_internal_hmac(krb5_context context,
     171             :                     struct _krb5_checksum_type *cm,
     172             :                     const void *data,
     173             :                     size_t len,
     174             :                     unsigned usage,
     175             :                     struct _krb5_key_data *keyblock,
     176             :                     Checksum *result)
     177             : {
     178             :     unsigned char *ipad, *opad;
     179             :     unsigned char *key;
     180             :     size_t key_len;
     181             :     size_t i;
     182             : 
     183     4371839 :     ipad = malloc(cm->blocksize + len);
     184     4371839 :     if (ipad == NULL)
     185           0 :         return ENOMEM;
     186     4371839 :     opad = malloc(cm->blocksize + cm->checksumsize);
     187     4371839 :     if (opad == NULL) {
     188           0 :         free(ipad);
     189           0 :         return ENOMEM;
     190             :     }
     191     4402176 :     memset(ipad, 0x36, cm->blocksize);
     192     4402176 :     memset(opad, 0x5c, cm->blocksize);
     193             : 
     194     4371839 :     if(keyblock->key->keyvalue.length > cm->blocksize){
     195           0 :         (*cm->checksum)(context,
     196             :                         keyblock,
     197           0 :                         keyblock->key->keyvalue.data,
     198           0 :                         keyblock->key->keyvalue.length,
     199             :                         usage,
     200             :                         result);
     201           0 :         key = result->checksum.data;
     202           0 :         key_len = result->checksum.length;
     203             :     } else {
     204     4371839 :         key = keyblock->key->keyvalue.data;
     205     4371839 :         key_len = keyblock->key->keyvalue.length;
     206             :     }
     207   129182927 :     for(i = 0; i < key_len; i++){
     208   124811088 :         ipad[i] ^= key[i];
     209   124811088 :         opad[i] ^= key[i];
     210             :     }
     211     4402176 :     memcpy(ipad + cm->blocksize, data, len);
     212     4371839 :     (*cm->checksum)(context, keyblock, ipad, cm->blocksize + len,
     213             :                     usage, result);
     214     4402176 :     memcpy(opad + cm->blocksize, result->checksum.data,
     215             :            result->checksum.length);
     216     8743678 :     (*cm->checksum)(context, keyblock, opad,
     217     4371839 :                     cm->blocksize + cm->checksumsize, usage, result);
     218     4402176 :     memset(ipad, 0, cm->blocksize + len);
     219     4371839 :     free(ipad);
     220     4402176 :     memset(opad, 0, cm->blocksize + cm->checksumsize);
     221     4371839 :     free(opad);
     222             : 
     223     4371839 :     return 0;
     224             : }
     225             : 
     226             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
     227      423954 : krb5_hmac(krb5_context context,
     228             :           krb5_cksumtype cktype,
     229             :           const void *data,
     230             :           size_t len,
     231             :           unsigned usage,
     232             :           krb5_keyblock *key,
     233             :           Checksum *result)
     234             : {
     235      423954 :     struct _krb5_checksum_type *c = _krb5_find_checksum(cktype);
     236             :     struct _krb5_key_data kd;
     237             :     krb5_error_code ret;
     238             : 
     239      423954 :     if (c == NULL) {
     240           0 :         krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
     241           0 :                                 N_("checksum type %d not supported", ""),
     242             :                                 cktype);
     243           0 :         return KRB5_PROG_SUMTYPE_NOSUPP;
     244             :     }
     245             : 
     246      423954 :     kd.key = key;
     247      423954 :     kd.schedule = NULL;
     248             : 
     249      423954 :     ret = _krb5_internal_hmac(context, c, data, len, usage, &kd, result);
     250             : 
     251      423954 :     if (kd.schedule)
     252           0 :         krb5_free_data(context, kd.schedule);
     253             : 
     254      423954 :     return ret;
     255             : }
     256             : 
     257             : krb5_error_code
     258     3428853 : _krb5_SP_HMAC_SHA1_checksum(krb5_context context,
     259             :                             struct _krb5_key_data *key,
     260             :                             const void *data,
     261             :                             size_t len,
     262             :                             unsigned usage,
     263             :                             Checksum *result)
     264             : {
     265     3428853 :     struct _krb5_checksum_type *c = _krb5_find_checksum(CKSUMTYPE_SHA1);
     266             :     Checksum res;
     267             :     char sha1_data[20];
     268             :     krb5_error_code ret;
     269             : 
     270     3428853 :     res.checksum.data = sha1_data;
     271     3428853 :     res.checksum.length = sizeof(sha1_data);
     272             : 
     273     3428853 :     ret = _krb5_internal_hmac(context, c, data, len, usage, key, &res);
     274     3428853 :     if (ret)
     275           0 :         krb5_abortx(context, "hmac failed");
     276     3457326 :     memcpy(result->checksum.data, res.checksum.data, result->checksum.length);
     277     3428853 :     return 0;
     278             : }
     279             : 
     280             : struct _krb5_checksum_type _krb5_checksum_sha1 = {
     281             :     CKSUMTYPE_SHA1,
     282             :     "sha1",
     283             :     64,
     284             :     20,
     285             :     F_CPROOF,
     286             :     SHA1_checksum,
     287             :     NULL
     288             : };
     289             : 
     290             : struct _krb5_checksum_type *
     291     7072951 : _krb5_find_checksum(krb5_cksumtype type)
     292             : {
     293             :     int i;
     294    36614340 :     for(i = 0; i < _krb5_num_checksums; i++)
     295    36614338 :         if(_krb5_checksum_types[i]->type == type)
     296     7012824 :             return _krb5_checksum_types[i];
     297           2 :     return NULL;
     298             : }
     299             : 
     300             : static krb5_error_code
     301     3556049 : get_checksum_key(krb5_context context,
     302             :                  krb5_crypto crypto,
     303             :                  unsigned usage,  /* not krb5_key_usage */
     304             :                  struct _krb5_checksum_type *ct,
     305             :                  struct _krb5_key_data **key)
     306             : {
     307     3556049 :     krb5_error_code ret = 0;
     308     3556049 :     struct _krb5_checksum_type *kct = NULL;
     309             : 
     310     3556049 :     if (crypto == NULL) {
     311           0 :         krb5_set_error_message(context, KRB5_BAD_ENCTYPE,
     312           0 :                                N_("Checksum type %s is keyed but no "
     313             :                                   "crypto context (key) was passed in", ""),
     314             :                                ct->name);
     315           0 :         return KRB5_BAD_ENCTYPE;
     316             :     }
     317     3556049 :     kct = crypto->et->keyed_checksum;
     318     3556049 :     if (kct == NULL || kct->type != ct->type) {
     319           0 :         krb5_set_error_message(context, KRB5_BAD_ENCTYPE,
     320           0 :                                N_("Checksum type %s is keyed, but "
     321             :                                   "the key type %s passed didnt have that checksum "
     322             :                                   "type as the keyed type", ""),
     323           0 :                                ct->name, crypto->et->name);
     324           0 :         return KRB5_BAD_ENCTYPE;
     325             :     }
     326             : 
     327     3556049 :     if(ct->flags & F_DERIVED)
     328     3428853 :         ret = _get_derived_key(context, crypto, usage, key);
     329      127196 :     else if(ct->flags & F_VARIANT) {
     330             :         size_t i;
     331             : 
     332           0 :         *key = _new_derived_key(crypto, 0xff/* KRB5_KU_RFC1510_VARIANT */);
     333           0 :         if(*key == NULL) {
     334           0 :             krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
     335           0 :             return ENOMEM;
     336             :         }
     337           0 :         ret = krb5_copy_keyblock(context, crypto->key.key, &(*key)->key);
     338           0 :         if(ret)
     339           0 :             return ret;
     340           0 :         for(i = 0; i < (*key)->key->keyvalue.length; i++)
     341           0 :             ((unsigned char*)(*key)->key->keyvalue.data)[i] ^= 0xF0;
     342             :     } else {
     343      127196 :         *key = &crypto->key;
     344             :     }
     345     3556023 :     if(ret == 0)
     346     3556049 :         ret = _key_schedule(context, *key);
     347     3527550 :     return ret;
     348             : }
     349             : 
     350             : static krb5_error_code
     351     2132307 : create_checksum (krb5_context context,
     352             :                  struct _krb5_checksum_type *ct,
     353             :                  krb5_crypto crypto,
     354             :                  unsigned usage,
     355             :                  void *data,
     356             :                  size_t len,
     357             :                  Checksum *result)
     358             : {
     359             :     krb5_error_code ret;
     360             :     struct _krb5_key_data *dkey;
     361             : 
     362     2132307 :     if (ct->flags & F_DISABLED) {
     363           0 :         krb5_clear_error_message (context);
     364           0 :         return KRB5_PROG_SUMTYPE_NOSUPP;
     365             :     }
     366     2132307 :     if (ct->flags & F_KEYED) {
     367     2125179 :         ret = get_checksum_key(context, crypto, usage, ct, &dkey);
     368     2125179 :         if (ret)
     369           0 :             return ret;
     370             :     } else
     371        7128 :         dkey = NULL;
     372     2132307 :     result->cksumtype = ct->type;
     373     2132307 :     ret = krb5_data_alloc(&result->checksum, ct->checksumsize);
     374     2132307 :     if (ret)
     375           0 :         return (ret);
     376     2132307 :     return (*ct->checksum)(context, dkey, data, len, usage, result);
     377             : }
     378             : 
     379             : static int
     380     1379299 : arcfour_checksum_p(struct _krb5_checksum_type *ct, krb5_crypto crypto)
     381             : {
     382     1520237 :     return (ct->type == CKSUMTYPE_HMAC_MD5) &&
     383      127196 :         (crypto->key.key->keytype == KEYTYPE_ARCFOUR);
     384             : }
     385             : 
     386             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
     387      769691 : krb5_create_checksum(krb5_context context,
     388             :                      krb5_crypto crypto,
     389             :                      krb5_key_usage usage,
     390             :                      int type,
     391             :                      void *data,
     392             :                      size_t len,
     393             :                      Checksum *result)
     394             : {
     395      769691 :     struct _krb5_checksum_type *ct = NULL;
     396             :     unsigned keyusage;
     397             : 
     398             :     /* type 0 -> pick from crypto */
     399      769691 :     if (type) {
     400        7128 :         ct = _krb5_find_checksum(type);
     401      762563 :     } else if (crypto) {
     402      762563 :         ct = crypto->et->keyed_checksum;
     403      762563 :         if (ct == NULL)
     404           0 :             ct = crypto->et->checksum;
     405             :     }
     406             : 
     407      769691 :     if(ct == NULL) {
     408           0 :         krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
     409           0 :                                 N_("checksum type %d not supported", ""),
     410             :                                 type);
     411           0 :         return KRB5_PROG_SUMTYPE_NOSUPP;
     412             :     }
     413             : 
     414      769691 :     if (arcfour_checksum_p(ct, crypto)) {
     415      119180 :         keyusage = usage;
     416      119180 :         _krb5_usage2arcfour(context, &keyusage);
     417             :     } else
     418      650511 :         keyusage = CHECKSUM_USAGE(usage);
     419             : 
     420      769691 :     return create_checksum(context, ct, crypto, keyusage,
     421             :                            data, len, result);
     422             : }
     423             : 
     424             : static krb5_error_code
     425     1434814 : verify_checksum(krb5_context context,
     426             :                 krb5_crypto crypto,
     427             :                 unsigned usage, /* not krb5_key_usage */
     428             :                 void *data,
     429             :                 size_t len,
     430             :                 Checksum *cksum)
     431             : {
     432             :     krb5_error_code ret;
     433             :     struct _krb5_key_data *dkey;
     434             :     Checksum c;
     435             :     struct _krb5_checksum_type *ct;
     436             : 
     437     1434814 :     ct = _krb5_find_checksum(cksum->cksumtype);
     438     1434814 :     if (ct == NULL || (ct->flags & F_DISABLED)) {
     439           0 :         krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
     440           0 :                                 N_("checksum type %d not supported", ""),
     441           0 :                                 cksum->cksumtype);
     442           0 :         return KRB5_PROG_SUMTYPE_NOSUPP;
     443             :     }
     444     1434814 :     if(ct->checksumsize != cksum->checksum.length) {
     445           1 :         krb5_clear_error_message (context);
     446           3 :         krb5_set_error_message(context, KRB5KRB_AP_ERR_BAD_INTEGRITY,
     447           1 :                                N_("Decrypt integrity check failed for checksum type %s, "
     448             :                                   "length was %u, expected %u", ""),
     449           1 :                                ct->name, (unsigned)cksum->checksum.length,
     450           1 :                                (unsigned)ct->checksumsize);
     451             : 
     452           1 :         return KRB5KRB_AP_ERR_BAD_INTEGRITY; /* XXX */
     453             :     }
     454     1434813 :     if (ct->flags & F_KEYED) {
     455     1430870 :         ret = get_checksum_key(context, crypto, usage, ct, &dkey);
     456     1430870 :         if (ret)
     457           0 :             return ret;
     458             :     } else
     459        3943 :         dkey = NULL;
     460             : 
     461             :     /*
     462             :      * If checksum have a verify function, lets use that instead of
     463             :      * calling ->checksum and then compare result.
     464             :      */
     465             : 
     466     1434813 :     if(ct->verify) {
     467           0 :         ret = (*ct->verify)(context, dkey, data, len, usage, cksum);
     468           0 :         if (ret)
     469           0 :             krb5_set_error_message(context, ret,
     470           0 :                                    N_("Decrypt integrity check failed for checksum "
     471             :                                       "type %s, key type %s", ""),
     472           0 :                                    ct->name, (crypto != NULL)? crypto->et->name : "(none)");
     473           0 :         return ret;
     474             :     }
     475             : 
     476     1434813 :     ret = krb5_data_alloc (&c.checksum, ct->checksumsize);
     477     1434813 :     if (ret)
     478           0 :         return ret;
     479             : 
     480     1434813 :     ret = (*ct->checksum)(context, dkey, data, len, usage, &c);
     481     1434813 :     if (ret) {
     482           0 :         krb5_data_free(&c.checksum);
     483           0 :         return ret;
     484             :     }
     485             : 
     486     1434813 :     if(krb5_data_ct_cmp(&c.checksum, &cksum->checksum) != 0) {
     487         251 :         ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
     488         753 :         krb5_set_error_message(context, ret,
     489         251 :                                N_("Decrypt integrity check failed for checksum "
     490             :                                   "type %s, key type %s", ""),
     491         251 :                                ct->name, crypto ? crypto->et->name : "(unkeyed)");
     492             :     } else {
     493     1420730 :         ret = 0;
     494             :     }
     495     1434813 :     krb5_data_free (&c.checksum);
     496     1434813 :     return ret;
     497             : }
     498             : 
     499             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
     500      623351 : krb5_verify_checksum(krb5_context context,
     501             :                      krb5_crypto crypto,
     502             :                      krb5_key_usage usage,
     503             :                      void *data,
     504             :                      size_t len,
     505             :                      Checksum *cksum)
     506             : {
     507             :     struct _krb5_checksum_type *ct;
     508             :     unsigned keyusage;
     509             : 
     510      623351 :     ct = _krb5_find_checksum(cksum->cksumtype);
     511      623351 :     if(ct == NULL) {
     512           1 :         krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
     513           1 :                                 N_("checksum type %d not supported", ""),
     514           1 :                                 cksum->cksumtype);
     515           1 :         return KRB5_PROG_SUMTYPE_NOSUPP;
     516             :     }
     517             : 
     518      623350 :     if (arcfour_checksum_p(ct, crypto)) {
     519        8016 :         keyusage = usage;
     520        8016 :         _krb5_usage2arcfour(context, &keyusage);
     521             :     } else
     522      615334 :         keyusage = CHECKSUM_USAGE(usage);
     523             : 
     524      623350 :     return verify_checksum(context, crypto, keyusage,
     525             :                            data, len, cksum);
     526             : }
     527             : 
     528             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
     529     1093273 : krb5_crypto_get_checksum_type(krb5_context context,
     530             :                               krb5_crypto crypto,
     531             :                               krb5_cksumtype *type)
     532             : {
     533     1093273 :     struct _krb5_checksum_type *ct = NULL;
     534             : 
     535     1093273 :     if (crypto != NULL) {
     536     1093273 :         ct = crypto->et->keyed_checksum;
     537     1093273 :         if (ct == NULL)
     538           0 :             ct = crypto->et->checksum;
     539             :     }
     540             : 
     541     1093273 :     if (ct == NULL) {
     542           0 :         krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
     543           0 :                                 N_("checksum type not found", ""));
     544           0 :         return KRB5_PROG_SUMTYPE_NOSUPP;
     545             :     }
     546             : 
     547     1093273 :     *type = ct->type;
     548             : 
     549     1093273 :     return 0;
     550             : }
     551             : 
     552             : 
     553             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
     554      670900 : krb5_checksumsize(krb5_context context,
     555             :                   krb5_cksumtype type,
     556             :                   size_t *size)
     557             : {
     558      670900 :     struct _krb5_checksum_type *ct = _krb5_find_checksum(type);
     559      670900 :     if(ct == NULL) {
     560           0 :         krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
     561           0 :                                 N_("checksum type %d not supported", ""),
     562             :                                 type);
     563           0 :         return KRB5_PROG_SUMTYPE_NOSUPP;
     564             :     }
     565      670900 :     *size = ct->checksumsize;
     566      670900 :     return 0;
     567             : }
     568             : 
     569             : KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL
     570      220428 : krb5_checksum_is_keyed(krb5_context context,
     571             :                        krb5_cksumtype type)
     572             : {
     573      220428 :     struct _krb5_checksum_type *ct = _krb5_find_checksum(type);
     574      220428 :     if(ct == NULL) {
     575           1 :         if (context)
     576           1 :             krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
     577           1 :                                     N_("checksum type %d not supported", ""),
     578             :                                     type);
     579           1 :         return KRB5_PROG_SUMTYPE_NOSUPP;
     580             :     }
     581      220427 :     return ct->flags & F_KEYED;
     582             : }
     583             : 
     584             : KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL
     585       40652 : krb5_checksum_is_collision_proof(krb5_context context,
     586             :                                  krb5_cksumtype type)
     587             : {
     588       40652 :     struct _krb5_checksum_type *ct = _krb5_find_checksum(type);
     589       40652 :     if(ct == NULL) {
     590           0 :         if (context)
     591           0 :             krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
     592           0 :                                     N_("checksum type %d not supported", ""),
     593             :                                     type);
     594           0 :         return KRB5_PROG_SUMTYPE_NOSUPP;
     595             :     }
     596       40652 :     return ct->flags & F_CPROOF;
     597             : }
     598             : 
     599             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
     600           0 : krb5_checksum_disable(krb5_context context,
     601             :                       krb5_cksumtype type)
     602             : {
     603           0 :     struct _krb5_checksum_type *ct = _krb5_find_checksum(type);
     604           0 :     if(ct == NULL) {
     605           0 :         if (context)
     606           0 :             krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
     607           0 :                                     N_("checksum type %d not supported", ""),
     608             :                                     type);
     609           0 :         return KRB5_PROG_SUMTYPE_NOSUPP;
     610             :     }
     611           0 :     ct->flags |= F_DISABLED;
     612           0 :     return 0;
     613             : }
     614             : 
     615             : /************************************************************
     616             :  *                                                          *
     617             :  ************************************************************/
     618             : 
     619             : struct _krb5_encryption_type *
     620    11068750 : _krb5_find_enctype(krb5_enctype type)
     621             : {
     622             :     int i;
     623    17792404 :     for(i = 0; i < _krb5_num_etypes; i++)
     624    17643702 :         if(_krb5_etypes[i]->type == type)
     625    10758983 :             return _krb5_etypes[i];
     626      146932 :     return NULL;
     627             : }
     628             : 
     629             : 
     630             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
     631      205459 : krb5_enctype_to_string(krb5_context context,
     632             :                        krb5_enctype etype,
     633             :                        char **string)
     634             : {
     635             :     struct _krb5_encryption_type *e;
     636      205459 :     e = _krb5_find_enctype(etype);
     637      205459 :     if(e == NULL) {
     638           0 :         krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
     639           0 :                                 N_("encryption type %d not supported", ""),
     640             :                                 etype);
     641           0 :         *string = NULL;
     642           0 :         return KRB5_PROG_ETYPE_NOSUPP;
     643             :     }
     644      205459 :     *string = strdup(e->name);
     645      205459 :     if(*string == NULL) {
     646           0 :         krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
     647           0 :         return ENOMEM;
     648             :     }
     649      200739 :     return 0;
     650             : }
     651             : 
     652             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
     653      420574 : krb5_string_to_enctype(krb5_context context,
     654             :                        const char *string,
     655             :                        krb5_enctype *etype)
     656             : {
     657             :     int i;
     658     3209888 :     for(i = 0; i < _krb5_num_etypes; i++)
     659     2931078 :         if(strcasecmp(_krb5_etypes[i]->name, string) == 0){
     660      141764 :             *etype = _krb5_etypes[i]->type;
     661      141764 :             return 0;
     662             :         }
     663      278810 :     krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
     664      278810 :                             N_("encryption type %s not supported", ""),
     665             :                             string);
     666      278810 :     return KRB5_PROG_ETYPE_NOSUPP;
     667             : }
     668             : 
     669             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
     670       24004 : krb5_enctype_to_keytype(krb5_context context,
     671             :                         krb5_enctype etype,
     672             :                         krb5_keytype *keytype)
     673             : {
     674       24004 :     struct _krb5_encryption_type *e = _krb5_find_enctype(etype);
     675       24004 :     if(e == NULL) {
     676           0 :         krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
     677           0 :                                 N_("encryption type %d not supported", ""),
     678             :                                 etype);
     679           0 :         return KRB5_PROG_ETYPE_NOSUPP;
     680             :     }
     681       24004 :     *keytype = e->keytype->type; /* XXX */
     682       24004 :     return 0;
     683             : }
     684             : 
     685             : /**
     686             :  * Check if a enctype is valid, return 0 if it is.
     687             :  *
     688             :  * @param context Kerberos context
     689             :  * @param etype enctype to check if its valid or not
     690             :  *
     691             :  * @return Return an error code for an failure or 0 on success (enctype valid).
     692             :  * @ingroup krb5_crypto
     693             :  */
     694             : 
     695             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
     696     1154093 : krb5_enctype_valid(krb5_context context,
     697             :                    krb5_enctype etype)
     698             : {
     699     1154093 :     struct _krb5_encryption_type *e = _krb5_find_enctype(etype);
     700     1154093 :     if(e && (e->flags & F_DISABLED) == 0)
     701      984774 :         return 0;
     702      148374 :     if (context == NULL)
     703           0 :         return KRB5_PROG_ETYPE_NOSUPP;
     704      148374 :     if(e == NULL) {
     705      148374 :         krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
     706      148374 :                                 N_("encryption type %d not supported", ""),
     707             :                                 etype);
     708      148374 :         return KRB5_PROG_ETYPE_NOSUPP;
     709             :     }
     710             :     /* Must be (e->flags & F_DISABLED) */
     711           0 :     krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
     712           0 :                             N_("encryption type %s is disabled", ""),
     713             :                             e->name);
     714           0 :     return KRB5_PROG_ETYPE_NOSUPP;
     715             : }
     716             : 
     717             : /**
     718             :  * Return the coresponding encryption type for a checksum type.
     719             :  *
     720             :  * @param context Kerberos context
     721             :  * @param ctype The checksum type to get the result enctype for
     722             :  * @param etype The returned encryption, when the matching etype is
     723             :  * not found, etype is set to ETYPE_NULL.
     724             :  *
     725             :  * @return Return an error code for an failure or 0 on success.
     726             :  * @ingroup krb5_crypto
     727             :  */
     728             : 
     729             : 
     730             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
     731       36186 : krb5_cksumtype_to_enctype(krb5_context context,
     732             :                           krb5_cksumtype ctype,
     733             :                           krb5_enctype *etype)
     734             : {
     735             :     int i;
     736             : 
     737       36186 :     *etype = ETYPE_NULL;
     738             : 
     739       36474 :     for(i = 0; i < _krb5_num_etypes; i++) {
     740       72804 :         if(_krb5_etypes[i]->keyed_checksum &&
     741       36366 :            _krb5_etypes[i]->keyed_checksum->type == ctype)
     742             :             {
     743       36150 :                 *etype = _krb5_etypes[i]->type;
     744       36150 :                 return 0;
     745             :             }
     746             :     }
     747             : 
     748          36 :     krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
     749          36 :                             N_("checksum type %d not supported", ""),
     750             :                             (int)ctype);
     751          36 :     return KRB5_PROG_SUMTYPE_NOSUPP;
     752             : }
     753             : 
     754             : 
     755             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
     756           0 : krb5_cksumtype_valid(krb5_context context,
     757             :                      krb5_cksumtype ctype)
     758             : {
     759           0 :     struct _krb5_checksum_type *c = _krb5_find_checksum(ctype);
     760           0 :     if (c == NULL) {
     761           0 :         krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
     762           0 :                                 N_("checksum type %d not supported", ""),
     763             :                                 ctype);
     764           0 :         return KRB5_PROG_SUMTYPE_NOSUPP;
     765             :     }
     766           0 :     if (c->flags & F_DISABLED) {
     767           0 :         krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
     768           0 :                                 N_("checksum type %s is disabled", ""),
     769             :                                 c->name);
     770           0 :         return KRB5_PROG_SUMTYPE_NOSUPP;
     771             :     }
     772           0 :     return 0;
     773             : }
     774             : 
     775             : 
     776             : static krb5_boolean
     777     5998872 : derived_crypto(krb5_context context,
     778             :                krb5_crypto crypto)
     779             : {
     780     6021404 :     return (crypto->et->flags & F_DERIVED) != 0;
     781             : }
     782             : 
     783             : static krb5_boolean
     784       72686 : special_crypto(krb5_context context,
     785             :                krb5_crypto crypto)
     786             : {
     787       73290 :     return (crypto->et->flags & F_SPECIAL) != 0;
     788             : }
     789             : 
     790             : #define CHECKSUMSIZE(C) ((C)->checksumsize)
     791             : #define CHECKSUMTYPE(C) ((C)->type)
     792             : 
     793             : static krb5_error_code
     794      458327 : encrypt_internal_derived(krb5_context context,
     795             :                          krb5_crypto crypto,
     796             :                          unsigned usage,
     797             :                          const void *data,
     798             :                          size_t len,
     799             :                          krb5_data *result,
     800             :                          void *ivec)
     801             : {
     802             :     size_t sz, block_sz, checksum_sz, total_sz;
     803             :     Checksum cksum;
     804             :     unsigned char *p, *q;
     805             :     krb5_error_code ret;
     806             :     struct _krb5_key_data *dkey;
     807      458327 :     const struct _krb5_encryption_type *et = crypto->et;
     808             : 
     809      458327 :     checksum_sz = CHECKSUMSIZE(et->keyed_checksum);
     810             : 
     811      458327 :     sz = et->confoundersize + len;
     812      458327 :     block_sz = (sz + et->padsize - 1) &~ (et->padsize - 1); /* pad */
     813      458327 :     total_sz = block_sz + checksum_sz;
     814      458327 :     p = calloc(1, total_sz);
     815      458327 :     if(p == NULL) {
     816           0 :         krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
     817           0 :         return ENOMEM;
     818             :     }
     819             : 
     820      458327 :     q = p;
     821      458327 :     krb5_generate_random_block(q, et->confoundersize); /* XXX */
     822      458327 :     q += et->confoundersize;
     823      458327 :     memcpy(q, data, len);
     824             : 
     825      458327 :     ret = create_checksum(context,
     826             :                           et->keyed_checksum,
     827             :                           crypto,
     828      458327 :                           INTEGRITY_USAGE(usage),
     829             :                           p,
     830             :                           block_sz,
     831             :                           &cksum);
     832      458327 :     if(ret == 0 && cksum.checksum.length != checksum_sz) {
     833           0 :         free_Checksum (&cksum);
     834           0 :         krb5_clear_error_message (context);
     835           0 :         ret = KRB5_CRYPTO_INTERNAL;
     836             :     }
     837      458327 :     if(ret)
     838           0 :         goto fail;
     839      464351 :     memcpy(p + block_sz, cksum.checksum.data, cksum.checksum.length);
     840      458327 :     free_Checksum (&cksum);
     841      458327 :     ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey);
     842      458327 :     if(ret)
     843           0 :         goto fail;
     844      458327 :     ret = _key_schedule(context, dkey);
     845      458327 :     if(ret)
     846           0 :         goto fail;
     847      458327 :     ret = (*et->encrypt)(context, dkey, p, block_sz, 1, usage, ivec);
     848      458327 :     if (ret)
     849           0 :         goto fail;
     850      458327 :     result->data = p;
     851      458327 :     result->length = total_sz;
     852      458327 :     return 0;
     853           0 :  fail:
     854           0 :     memset(p, 0, total_sz);
     855           0 :     free(p);
     856           0 :     return ret;
     857             : }
     858             : 
     859             : 
     860             : static krb5_error_code
     861           0 : encrypt_internal(krb5_context context,
     862             :                  krb5_crypto crypto,
     863             :                  const void *data,
     864             :                  size_t len,
     865             :                  krb5_data *result,
     866             :                  void *ivec)
     867             : {
     868             :     size_t sz, block_sz, checksum_sz;
     869             :     Checksum cksum;
     870             :     unsigned char *p, *q;
     871             :     krb5_error_code ret;
     872           0 :     const struct _krb5_encryption_type *et = crypto->et;
     873             : 
     874           0 :     checksum_sz = CHECKSUMSIZE(et->checksum);
     875             : 
     876           0 :     sz = et->confoundersize + checksum_sz + len;
     877           0 :     block_sz = (sz + et->padsize - 1) &~ (et->padsize - 1); /* pad */
     878           0 :     p = calloc(1, block_sz);
     879           0 :     if(p == NULL) {
     880           0 :         krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
     881           0 :         return ENOMEM;
     882             :     }
     883             : 
     884           0 :     q = p;
     885           0 :     krb5_generate_random_block(q, et->confoundersize); /* XXX */
     886           0 :     q += et->confoundersize;
     887           0 :     memset(q, 0, checksum_sz);
     888           0 :     q += checksum_sz;
     889           0 :     memcpy(q, data, len);
     890             : 
     891           0 :     ret = create_checksum(context,
     892             :                           et->checksum,
     893             :                           crypto,
     894             :                           0,
     895             :                           p,
     896             :                           block_sz,
     897             :                           &cksum);
     898           0 :     if(ret == 0 && cksum.checksum.length != checksum_sz) {
     899           0 :         krb5_clear_error_message (context);
     900           0 :         free_Checksum(&cksum);
     901           0 :         ret = KRB5_CRYPTO_INTERNAL;
     902             :     }
     903           0 :     if(ret)
     904           0 :         goto fail;
     905           0 :     memcpy(p + et->confoundersize, cksum.checksum.data, cksum.checksum.length);
     906           0 :     free_Checksum(&cksum);
     907           0 :     ret = _key_schedule(context, &crypto->key);
     908           0 :     if(ret)
     909           0 :         goto fail;
     910           0 :     ret = (*et->encrypt)(context, &crypto->key, p, block_sz, 1, 0, ivec);
     911           0 :     if (ret) {
     912           0 :         memset(p, 0, block_sz);
     913           0 :         free(p);
     914           0 :         return ret;
     915             :     }
     916           0 :     result->data = p;
     917           0 :     result->length = block_sz;
     918           0 :     return 0;
     919           0 :  fail:
     920           0 :     memset(p, 0, block_sz);
     921           0 :     free(p);
     922           0 :     return ret;
     923             : }
     924             : 
     925             : static krb5_error_code
     926       38201 : encrypt_internal_special(krb5_context context,
     927             :                          krb5_crypto crypto,
     928             :                          int usage,
     929             :                          const void *data,
     930             :                          size_t len,
     931             :                          krb5_data *result,
     932             :                          void *ivec)
     933             : {
     934       38201 :     struct _krb5_encryption_type *et = crypto->et;
     935       38201 :     size_t cksum_sz = CHECKSUMSIZE(et->checksum);
     936       38201 :     size_t sz = len + cksum_sz + et->confoundersize;
     937             :     char *tmp, *p;
     938             :     krb5_error_code ret;
     939             : 
     940       38201 :     tmp = malloc (sz);
     941       38201 :     if (tmp == NULL) {
     942           0 :         krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
     943           0 :         return ENOMEM;
     944             :     }
     945       38201 :     p = tmp;
     946       38201 :     memset (p, 0, cksum_sz);
     947       38201 :     p += cksum_sz;
     948       38201 :     krb5_generate_random_block(p, et->confoundersize);
     949       38201 :     p += et->confoundersize;
     950       38201 :     memcpy (p, data, len);
     951       38201 :     ret = (*et->encrypt)(context, &crypto->key, tmp, sz, TRUE, usage, ivec);
     952       38201 :     if (ret) {
     953           0 :         memset(tmp, 0, sz);
     954           0 :         free(tmp);
     955           0 :         return ret;
     956             :     }
     957       38201 :     result->data   = tmp;
     958       38201 :     result->length = sz;
     959       38201 :     return 0;
     960             : }
     961             : 
     962             : static krb5_error_code
     963      498882 : decrypt_internal_derived(krb5_context context,
     964             :                          krb5_crypto crypto,
     965             :                          unsigned usage,
     966             :                          void *data,
     967             :                          size_t len,
     968             :                          krb5_data *result,
     969             :                          void *ivec)
     970             : {
     971             :     size_t checksum_sz;
     972             :     Checksum cksum;
     973             :     unsigned char *p;
     974             :     krb5_error_code ret;
     975             :     struct _krb5_key_data *dkey;
     976      498882 :     struct _krb5_encryption_type *et = crypto->et;
     977             :     unsigned long l;
     978             : 
     979      498882 :     checksum_sz = CHECKSUMSIZE(et->keyed_checksum);
     980      498882 :     if (len < checksum_sz + et->confoundersize) {
     981           0 :         krb5_set_error_message(context, KRB5_BAD_MSIZE,
     982           0 :                                N_("Encrypted data shorter then "
     983             :                                   "checksum + confunder", ""));
     984           0 :         return KRB5_BAD_MSIZE;
     985             :     }
     986             : 
     987      498882 :     if (((len - checksum_sz) % et->padsize) != 0) {
     988           0 :         krb5_clear_error_message(context);
     989           0 :         return KRB5_BAD_MSIZE;
     990             :     }
     991             : 
     992      498882 :     p = malloc(len);
     993      498882 :     if(len != 0 && p == NULL) {
     994           0 :         krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
     995           0 :         return ENOMEM;
     996             :     }
     997      498882 :     memcpy(p, data, len);
     998             : 
     999      498882 :     len -= checksum_sz;
    1000             : 
    1001      498882 :     ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey);
    1002      498882 :     if(ret) {
    1003           0 :         free(p);
    1004           0 :         return ret;
    1005             :     }
    1006      498882 :     ret = _key_schedule(context, dkey);
    1007      498882 :     if(ret) {
    1008           0 :         free(p);
    1009           0 :         return ret;
    1010             :     }
    1011      498882 :     ret = (*et->encrypt)(context, dkey, p, len, 0, usage, ivec);
    1012      498882 :     if (ret) {
    1013           0 :         free(p);
    1014           0 :         return ret;
    1015             :     }
    1016             : 
    1017      498882 :     cksum.checksum.data   = p + len;
    1018      498882 :     cksum.checksum.length = checksum_sz;
    1019      498882 :     cksum.cksumtype       = CHECKSUMTYPE(et->keyed_checksum);
    1020             : 
    1021      498882 :     ret = verify_checksum(context,
    1022             :                           crypto,
    1023      492718 :                           INTEGRITY_USAGE(usage),
    1024             :                           p,
    1025             :                           len,
    1026             :                           &cksum);
    1027      498882 :     if(ret) {
    1028         195 :         free(p);
    1029         195 :         return ret;
    1030             :     }
    1031      498687 :     l = len - et->confoundersize;
    1032      504851 :     memmove(p, p + et->confoundersize, l);
    1033      498687 :     result->data = realloc(p, l);
    1034      498687 :     if(result->data == NULL && l != 0) {
    1035           0 :         free(p);
    1036           0 :         krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
    1037           0 :         return ENOMEM;
    1038             :     }
    1039      498687 :     result->length = l;
    1040      498687 :     return 0;
    1041             : }
    1042             : 
    1043             : static krb5_error_code
    1044           0 : decrypt_internal(krb5_context context,
    1045             :                  krb5_crypto crypto,
    1046             :                  void *data,
    1047             :                  size_t len,
    1048             :                  krb5_data *result,
    1049             :                  void *ivec)
    1050             : {
    1051             :     krb5_error_code ret;
    1052             :     unsigned char *p;
    1053             :     Checksum cksum;
    1054             :     size_t checksum_sz, l;
    1055           0 :     struct _krb5_encryption_type *et = crypto->et;
    1056             : 
    1057           0 :     if ((len % et->padsize) != 0) {
    1058           0 :         krb5_clear_error_message(context);
    1059           0 :         return KRB5_BAD_MSIZE;
    1060             :     }
    1061           0 :     checksum_sz = CHECKSUMSIZE(et->checksum);
    1062           0 :     if (len < checksum_sz + et->confoundersize) {
    1063           0 :         krb5_set_error_message(context, KRB5_BAD_MSIZE,
    1064           0 :                                N_("Encrypted data shorter then "
    1065             :                                   "checksum + confunder", ""));
    1066           0 :         return KRB5_BAD_MSIZE;
    1067             :     }
    1068             : 
    1069           0 :     p = malloc(len);
    1070           0 :     if(len != 0 && p == NULL) {
    1071           0 :         krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
    1072           0 :         return ENOMEM;
    1073             :     }
    1074           0 :     memcpy(p, data, len);
    1075             : 
    1076           0 :     ret = _key_schedule(context, &crypto->key);
    1077           0 :     if(ret) {
    1078           0 :         free(p);
    1079           0 :         return ret;
    1080             :     }
    1081           0 :     ret = (*et->encrypt)(context, &crypto->key, p, len, 0, 0, ivec);
    1082           0 :     if (ret) {
    1083           0 :         free(p);
    1084           0 :         return ret;
    1085             :     }
    1086           0 :     ret = krb5_data_copy(&cksum.checksum, p + et->confoundersize, checksum_sz);
    1087           0 :     if(ret) {
    1088           0 :         free(p);
    1089           0 :         return ret;
    1090             :     }
    1091           0 :     memset(p + et->confoundersize, 0, checksum_sz);
    1092           0 :     cksum.cksumtype = CHECKSUMTYPE(et->checksum);
    1093           0 :     ret = verify_checksum(context, NULL, 0, p, len, &cksum);
    1094           0 :     free_Checksum(&cksum);
    1095           0 :     if(ret) {
    1096           0 :         free(p);
    1097           0 :         return ret;
    1098             :     }
    1099           0 :     l = len - et->confoundersize - checksum_sz;
    1100           0 :     memmove(p, p + et->confoundersize + checksum_sz, l);
    1101           0 :     result->data = realloc(p, l);
    1102           0 :     if(result->data == NULL && l != 0) {
    1103           0 :         free(p);
    1104           0 :         krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
    1105           0 :         return ENOMEM;
    1106             :     }
    1107           0 :     result->length = l;
    1108           0 :     return 0;
    1109             : }
    1110             : 
    1111             : static krb5_error_code
    1112       35089 : decrypt_internal_special(krb5_context context,
    1113             :                          krb5_crypto crypto,
    1114             :                          int usage,
    1115             :                          void *data,
    1116             :                          size_t len,
    1117             :                          krb5_data *result,
    1118             :                          void *ivec)
    1119             : {
    1120       35089 :     struct _krb5_encryption_type *et = crypto->et;
    1121       35089 :     size_t cksum_sz = CHECKSUMSIZE(et->checksum);
    1122       35089 :     size_t sz = len - cksum_sz - et->confoundersize;
    1123             :     unsigned char *p;
    1124             :     krb5_error_code ret;
    1125             : 
    1126       35089 :     if ((len % et->padsize) != 0) {
    1127           0 :         krb5_clear_error_message(context);
    1128           0 :         return KRB5_BAD_MSIZE;
    1129             :     }
    1130       35089 :     if (len < cksum_sz + et->confoundersize) {
    1131           0 :         krb5_set_error_message(context, KRB5_BAD_MSIZE,
    1132           0 :                                N_("Encrypted data shorter then "
    1133             :                                   "checksum + confunder", ""));
    1134           0 :         return KRB5_BAD_MSIZE;
    1135             :     }
    1136             : 
    1137       35089 :     p = malloc (len);
    1138       35089 :     if (p == NULL) {
    1139           0 :         krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
    1140           0 :         return ENOMEM;
    1141             :     }
    1142       35089 :     memcpy(p, data, len);
    1143             : 
    1144       35089 :     ret = (*et->encrypt)(context, &crypto->key, p, len, FALSE, usage, ivec);
    1145       35089 :     if (ret) {
    1146         104 :         free(p);
    1147         104 :         return ret;
    1148             :     }
    1149             : 
    1150       35287 :     memmove (p, p + cksum_sz + et->confoundersize, sz);
    1151       34985 :     result->data = realloc(p, sz);
    1152       34985 :     if(result->data == NULL && sz != 0) {
    1153           0 :         free(p);
    1154           0 :         krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
    1155           0 :         return ENOMEM;
    1156             :     }
    1157       34985 :     result->length = sz;
    1158       34985 :     return 0;
    1159             : }
    1160             : 
    1161             : static krb5_crypto_iov *
    1162     3331468 : find_iv(krb5_crypto_iov *data, size_t num_data, unsigned type)
    1163             : {
    1164             :     size_t i;
    1165    16969280 :     for (i = 0; i < num_data; i++)
    1166    16064991 :         if (data[i].flags == type)
    1167     2428492 :             return &data[i];
    1168      902976 :     return NULL;
    1169             : }
    1170             : 
    1171             : /**
    1172             :  * Inline encrypt a kerberos message
    1173             :  *
    1174             :  * @param context Kerberos context
    1175             :  * @param crypto Kerberos crypto context
    1176             :  * @param usage Key usage for this buffer
    1177             :  * @param data array of buffers to process
    1178             :  * @param num_data length of array
    1179             :  * @param ivec initial cbc/cts vector
    1180             :  *
    1181             :  * @return Return an error code or 0.
    1182             :  * @ingroup krb5_crypto
    1183             :  *
    1184             :  * Kerberos encrypted data look like this:
    1185             :  *
    1186             :  * 1. KRB5_CRYPTO_TYPE_HEADER
    1187             :  * 2. array [1,...] KRB5_CRYPTO_TYPE_DATA and array [0,...]
    1188             :  *    KRB5_CRYPTO_TYPE_SIGN_ONLY in any order, however the receiver
    1189             :  *    have to aware of the order. KRB5_CRYPTO_TYPE_SIGN_ONLY is
    1190             :  *    commonly used headers and trailers.
    1191             :  * 3. KRB5_CRYPTO_TYPE_PADDING, at least on padsize long if padsize > 1
    1192             :  * 4. KRB5_CRYPTO_TYPE_TRAILER
    1193             :  */
    1194             : 
    1195             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
    1196      904289 : krb5_encrypt_iov_ivec(krb5_context context,
    1197             :                       krb5_crypto crypto,
    1198             :                       unsigned usage,
    1199             :                       krb5_crypto_iov *data,
    1200             :                       int num_data,
    1201             :                       void *ivec)
    1202             : {
    1203             :     size_t headersz, trailersz, len;
    1204             :     int i;
    1205             :     size_t sz, block_sz, pad_sz;
    1206             :     Checksum cksum;
    1207             :     unsigned char *p, *q;
    1208             :     krb5_error_code ret;
    1209             :     struct _krb5_key_data *dkey;
    1210      904289 :     const struct _krb5_encryption_type *et = crypto->et;
    1211             :     krb5_crypto_iov *tiv, *piv, *hiv;
    1212             : 
    1213      904289 :     if (num_data < 0) {
    1214           0 :         krb5_clear_error_message(context);
    1215           0 :         return KRB5_CRYPTO_INTERNAL;
    1216             :     }
    1217             : 
    1218      905602 :     if(!derived_crypto(context, crypto)) {
    1219           0 :         krb5_clear_error_message(context);
    1220           0 :         return KRB5_CRYPTO_INTERNAL;
    1221             :     }
    1222             : 
    1223      904289 :     headersz = et->confoundersize;
    1224      904289 :     trailersz = CHECKSUMSIZE(et->keyed_checksum);
    1225             : 
    1226     7234312 :     for (len = 0, i = 0; i < num_data; i++) {
    1227     6330023 :         if (data[i].flags != KRB5_CRYPTO_TYPE_DATA)
    1228     4521445 :             continue;
    1229     1808578 :         len += data[i].data.length;
    1230             :     }
    1231             : 
    1232      904289 :     sz = headersz + len;
    1233      904289 :     block_sz = (sz + et->padsize - 1) &~ (et->padsize - 1); /* pad */
    1234             : 
    1235      904289 :     pad_sz = block_sz - sz;
    1236             : 
    1237             :     /* header */
    1238             : 
    1239      905602 :     hiv = find_iv(data, num_data, KRB5_CRYPTO_TYPE_HEADER);
    1240      904289 :     if (hiv == NULL || hiv->data.length != headersz)
    1241           0 :         return KRB5_BAD_MSIZE;
    1242             : 
    1243      904289 :     krb5_generate_random_block(hiv->data.data, hiv->data.length);
    1244             : 
    1245             :     /* padding */
    1246      905602 :     piv = find_iv(data, num_data, KRB5_CRYPTO_TYPE_PADDING);
    1247             :     /* its ok to have no TYPE_PADDING if there is no padding */
    1248      904289 :     if (piv == NULL && pad_sz != 0)
    1249           0 :         return KRB5_BAD_MSIZE;
    1250      904289 :     if (piv) {
    1251           0 :         if (piv->data.length < pad_sz)
    1252           0 :             return KRB5_BAD_MSIZE;
    1253           0 :         piv->data.length = pad_sz;
    1254           0 :         if (pad_sz)
    1255           0 :             memset(piv->data.data, pad_sz, pad_sz);
    1256             :         else
    1257           0 :             piv = NULL;
    1258             :     }
    1259             : 
    1260             :     /* trailer */
    1261      905602 :     tiv = find_iv(data, num_data, KRB5_CRYPTO_TYPE_TRAILER);
    1262      904289 :     if (tiv == NULL || tiv->data.length != trailersz)
    1263           0 :         return KRB5_BAD_MSIZE;
    1264             : 
    1265             :     /*
    1266             :      * XXX replace with EVP_Sign? at least make create_checksum an iov
    1267             :      * function.
    1268             :      * XXX CTS EVP is broken, can't handle multi buffers :(
    1269             :      */
    1270             : 
    1271      902976 :     len = block_sz;
    1272     7232999 :     for (i = 0; i < num_data; i++) {
    1273     6330023 :         if (data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY)
    1274     4535525 :             continue;
    1275     1794498 :         len += data[i].data.length;
    1276             :     }
    1277             : 
    1278      904289 :     p = q = malloc(len);
    1279             : 
    1280      905602 :     memcpy(q, hiv->data.data, hiv->data.length);
    1281      904289 :     q += hiv->data.length;
    1282     7234312 :     for (i = 0; i < num_data; i++) {
    1283    10844903 :         if (data[i].flags != KRB5_CRYPTO_TYPE_DATA &&
    1284     4514880 :             data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY)
    1285     2726947 :             continue;
    1286     3608328 :         memcpy(q, data[i].data.data, data[i].data.length);
    1287     3603076 :         q += data[i].data.length;
    1288             :     }
    1289      904289 :     if (piv)
    1290           0 :         memset(q, 0, piv->data.length);
    1291             : 
    1292      904289 :     ret = create_checksum(context,
    1293             :                           et->keyed_checksum,
    1294             :                           crypto,
    1295      904289 :                           INTEGRITY_USAGE(usage),
    1296             :                           p,
    1297             :                           len,
    1298             :                           &cksum);
    1299      904289 :     free(p);
    1300      904289 :     if(ret == 0 && cksum.checksum.length != trailersz) {
    1301           0 :         free_Checksum (&cksum);
    1302           0 :         krb5_clear_error_message (context);
    1303           0 :         ret = KRB5_CRYPTO_INTERNAL;
    1304             :     }
    1305      904289 :     if(ret)
    1306           0 :         return ret;
    1307             : 
    1308             :     /* save cksum at end */
    1309      905602 :     memcpy(tiv->data.data, cksum.checksum.data, cksum.checksum.length);
    1310      904289 :     free_Checksum (&cksum);
    1311             : 
    1312             :     /* XXX replace with EVP_Cipher */
    1313      904289 :     p = q = malloc(block_sz);
    1314      904289 :     if(p == NULL)
    1315           0 :         return ENOMEM;
    1316             : 
    1317      905602 :     memcpy(q, hiv->data.data, hiv->data.length);
    1318      904289 :     q += hiv->data.length;
    1319             : 
    1320     7234312 :     for (i = 0; i < num_data; i++) {
    1321     6330023 :         if (data[i].flags != KRB5_CRYPTO_TYPE_DATA)
    1322     4521445 :             continue;
    1323     1811204 :         memcpy(q, data[i].data.data, data[i].data.length);
    1324     1808578 :         q += data[i].data.length;
    1325             :     }
    1326      904289 :     if (piv)
    1327           0 :         memset(q, 0, piv->data.length);
    1328             : 
    1329             : 
    1330      904289 :     ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey);
    1331      904289 :     if(ret) {
    1332           0 :         free(p);
    1333           0 :         return ret;
    1334             :     }
    1335      904289 :     ret = _key_schedule(context, dkey);
    1336      904289 :     if(ret) {
    1337           0 :         free(p);
    1338           0 :         return ret;
    1339             :     }
    1340             : 
    1341      904289 :     ret = (*et->encrypt)(context, dkey, p, block_sz, 1, usage, ivec);
    1342      904289 :     if (ret) {
    1343           0 :         free(p);
    1344           0 :         return ret;
    1345             :     }
    1346             : 
    1347             :     /* now copy data back to buffers */
    1348      904289 :     q = p;
    1349             : 
    1350      905602 :     memcpy(hiv->data.data, q, hiv->data.length);
    1351      904289 :     q += hiv->data.length;
    1352             : 
    1353     7234312 :     for (i = 0; i < num_data; i++) {
    1354     6330023 :         if (data[i].flags != KRB5_CRYPTO_TYPE_DATA)
    1355     4521445 :             continue;
    1356     1811204 :         memcpy(data[i].data.data, q, data[i].data.length);
    1357     1808578 :         q += data[i].data.length;
    1358             :     }
    1359      904289 :     if (piv)
    1360           0 :         memcpy(piv->data.data, q, pad_sz);
    1361             : 
    1362      904289 :     free(p);
    1363             : 
    1364      904289 :     return ret;
    1365             : }
    1366             : 
    1367             : /**
    1368             :  * Inline decrypt a Kerberos message.
    1369             :  *
    1370             :  * @param context Kerberos context
    1371             :  * @param crypto Kerberos crypto context
    1372             :  * @param usage Key usage for this buffer
    1373             :  * @param data array of buffers to process
    1374             :  * @param num_data length of array
    1375             :  * @param ivec initial cbc/cts vector
    1376             :  *
    1377             :  * @return Return an error code or 0.
    1378             :  * @ingroup krb5_crypto
    1379             :  *
    1380             :  * 1. KRB5_CRYPTO_TYPE_HEADER
    1381             :  * 2. one KRB5_CRYPTO_TYPE_DATA and array [0,...] of KRB5_CRYPTO_TYPE_SIGN_ONLY in
    1382             :  *  any order, however the receiver have to aware of the
    1383             :  *  order. KRB5_CRYPTO_TYPE_SIGN_ONLY is commonly used unencrypoted
    1384             :  *  protocol headers and trailers. The output data will be of same
    1385             :  *  size as the input data or shorter.
    1386             :  */
    1387             : 
    1388             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
    1389      312582 : krb5_decrypt_iov_ivec(krb5_context context,
    1390             :                       krb5_crypto crypto,
    1391             :                       unsigned usage,
    1392             :                       krb5_crypto_iov *data,
    1393             :                       unsigned int num_data,
    1394             :                       void *ivec)
    1395             : {
    1396             :     unsigned int i;
    1397             :     size_t headersz, trailersz, len;
    1398             :     Checksum cksum;
    1399             :     unsigned char *p, *q;
    1400             :     krb5_error_code ret;
    1401             :     struct _krb5_key_data *dkey;
    1402      312582 :     struct _krb5_encryption_type *et = crypto->et;
    1403             :     krb5_crypto_iov *tiv, *hiv;
    1404             : 
    1405      313894 :     if(!derived_crypto(context, crypto)) {
    1406           0 :         krb5_clear_error_message(context);
    1407           0 :         return KRB5_CRYPTO_INTERNAL;
    1408             :     }
    1409             : 
    1410      312582 :     headersz = et->confoundersize;
    1411             : 
    1412      313894 :     hiv = find_iv(data, num_data, KRB5_CRYPTO_TYPE_HEADER);
    1413      312582 :     if (hiv == NULL || hiv->data.length != headersz)
    1414           0 :         return KRB5_BAD_MSIZE;
    1415             : 
    1416             :     /* trailer */
    1417      312582 :     trailersz = CHECKSUMSIZE(et->keyed_checksum);
    1418             : 
    1419      313894 :     tiv = find_iv(data, num_data, KRB5_CRYPTO_TYPE_TRAILER);
    1420      312582 :     if (tiv->data.length != trailersz)
    1421           0 :         return KRB5_BAD_MSIZE;
    1422             : 
    1423             :     /* Find length of data we will decrypt */
    1424             : 
    1425      311270 :     len = headersz;
    1426     2499344 :     for (i = 0; i < num_data; i++) {
    1427     2188074 :         if (data[i].flags != KRB5_CRYPTO_TYPE_DATA)
    1428     1562910 :             continue;
    1429      625164 :         len += data[i].data.length;
    1430             :     }
    1431             : 
    1432      312582 :     if ((len % et->padsize) != 0) {
    1433           0 :         krb5_clear_error_message(context);
    1434           0 :         return KRB5_BAD_MSIZE;
    1435             :     }
    1436             : 
    1437             :     /* XXX replace with EVP_Cipher */
    1438             : 
    1439      312582 :     p = q = malloc(len);
    1440      312582 :     if (p == NULL)
    1441           0 :         return ENOMEM;
    1442             : 
    1443      313894 :     memcpy(q, hiv->data.data, hiv->data.length);
    1444      312582 :     q += hiv->data.length;
    1445             : 
    1446     2500656 :     for (i = 0; i < num_data; i++) {
    1447     2188074 :         if (data[i].flags != KRB5_CRYPTO_TYPE_DATA)
    1448     1562910 :             continue;
    1449      627788 :         memcpy(q, data[i].data.data, data[i].data.length);
    1450      625164 :         q += data[i].data.length;
    1451             :     }
    1452             : 
    1453      312582 :     ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey);
    1454      312582 :     if(ret) {
    1455           0 :         free(p);
    1456           0 :         return ret;
    1457             :     }
    1458      312582 :     ret = _key_schedule(context, dkey);
    1459      312582 :     if(ret) {
    1460           0 :         free(p);
    1461           0 :         return ret;
    1462             :     }
    1463             : 
    1464      312582 :     ret = (*et->encrypt)(context, dkey, p, len, 0, usage, ivec);
    1465      312582 :     if (ret) {
    1466           0 :         free(p);
    1467           0 :         return ret;
    1468             :     }
    1469             : 
    1470             :     /* copy data back to buffers */
    1471      313894 :     memcpy(hiv->data.data, p, hiv->data.length);
    1472      312582 :     q = p + hiv->data.length;
    1473     2500656 :     for (i = 0; i < num_data; i++) {
    1474     2188074 :         if (data[i].flags != KRB5_CRYPTO_TYPE_DATA)
    1475     1562910 :             continue;
    1476      627788 :         memcpy(data[i].data.data, q, data[i].data.length);
    1477      625164 :         q += data[i].data.length;
    1478             :     }
    1479             : 
    1480      312582 :     free(p);
    1481             : 
    1482             :     /* check signature */
    1483     2500656 :     for (i = 0; i < num_data; i++) {
    1484     2188074 :         if (data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY)
    1485     1576948 :             continue;
    1486      611126 :         len += data[i].data.length;
    1487             :     }
    1488             : 
    1489      312582 :     p = q = malloc(len);
    1490      312582 :     if (p == NULL)
    1491           0 :         return ENOMEM;
    1492             : 
    1493      313894 :     memcpy(q, hiv->data.data, hiv->data.length);
    1494      312582 :     q += hiv->data.length;
    1495     2500656 :     for (i = 0; i < num_data; i++) {
    1496     3744424 :         if (data[i].flags != KRB5_CRYPTO_TYPE_DATA &&
    1497     1556350 :             data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY)
    1498      951784 :             continue;
    1499     1241538 :         memcpy(q, data[i].data.data, data[i].data.length);
    1500     1236290 :         q += data[i].data.length;
    1501             :     }
    1502             : 
    1503      312582 :     cksum.checksum.data   = tiv->data.data;
    1504      312582 :     cksum.checksum.length = tiv->data.length;
    1505      312582 :     cksum.cksumtype       = CHECKSUMTYPE(et->keyed_checksum);
    1506             : 
    1507      312582 :     ret = verify_checksum(context,
    1508             :                           crypto,
    1509      311270 :                           INTEGRITY_USAGE(usage),
    1510             :                           p,
    1511             :                           len,
    1512             :                           &cksum);
    1513      312582 :     free(p);
    1514      312582 :     return ret;
    1515             : }
    1516             : 
    1517             : /**
    1518             :  * Create a Kerberos message checksum.
    1519             :  *
    1520             :  * @param context Kerberos context
    1521             :  * @param crypto Kerberos crypto context
    1522             :  * @param usage Key usage for this buffer
    1523             :  * @param data array of buffers to process
    1524             :  * @param num_data length of array
    1525             :  * @param type output data
    1526             :  *
    1527             :  * @return Return an error code or 0.
    1528             :  * @ingroup krb5_crypto
    1529             :  */
    1530             : 
    1531             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
    1532           0 : krb5_create_checksum_iov(krb5_context context,
    1533             :                          krb5_crypto crypto,
    1534             :                          unsigned usage,
    1535             :                          krb5_crypto_iov *data,
    1536             :                          unsigned int num_data,
    1537             :                          krb5_cksumtype *type)
    1538             : {
    1539             :     Checksum cksum;
    1540             :     krb5_crypto_iov *civ;
    1541             :     krb5_error_code ret;
    1542             :     size_t i;
    1543             :     size_t len;
    1544             :     char *p, *q;
    1545             : 
    1546           0 :     if(!derived_crypto(context, crypto)) {
    1547           0 :         krb5_clear_error_message(context);
    1548           0 :         return KRB5_CRYPTO_INTERNAL;
    1549             :     }
    1550             : 
    1551           0 :     civ = find_iv(data, num_data, KRB5_CRYPTO_TYPE_CHECKSUM);
    1552           0 :     if (civ == NULL)
    1553           0 :         return KRB5_BAD_MSIZE;
    1554             : 
    1555           0 :     len = 0;
    1556           0 :     for (i = 0; i < num_data; i++) {
    1557           0 :         if (data[i].flags != KRB5_CRYPTO_TYPE_DATA &&
    1558           0 :             data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY)
    1559           0 :             continue;
    1560           0 :         len += data[i].data.length;
    1561             :     }
    1562             : 
    1563           0 :     p = q = malloc(len);
    1564             : 
    1565           0 :     for (i = 0; i < num_data; i++) {
    1566           0 :         if (data[i].flags != KRB5_CRYPTO_TYPE_DATA &&
    1567           0 :             data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY)
    1568           0 :             continue;
    1569           0 :         memcpy(q, data[i].data.data, data[i].data.length);
    1570           0 :         q += data[i].data.length;
    1571             :     }
    1572             : 
    1573           0 :     ret = krb5_create_checksum(context, crypto, usage, 0, p, len, &cksum);
    1574           0 :     free(p);
    1575           0 :     if (ret)
    1576           0 :         return ret;
    1577             : 
    1578           0 :     if (type)
    1579           0 :         *type = cksum.cksumtype;
    1580             : 
    1581           0 :     if (cksum.checksum.length > civ->data.length) {
    1582           0 :         krb5_set_error_message(context, KRB5_BAD_MSIZE,
    1583           0 :                                N_("Checksum larger then input buffer", ""));
    1584           0 :         free_Checksum(&cksum);
    1585           0 :         return KRB5_BAD_MSIZE;
    1586             :     }
    1587             : 
    1588           0 :     civ->data.length = cksum.checksum.length;
    1589           0 :     memcpy(civ->data.data, cksum.checksum.data, civ->data.length);
    1590           0 :     free_Checksum(&cksum);
    1591             : 
    1592           0 :     return 0;
    1593             : }
    1594             : 
    1595             : /**
    1596             :  * Verify a Kerberos message checksum.
    1597             :  *
    1598             :  * @param context Kerberos context
    1599             :  * @param crypto Kerberos crypto context
    1600             :  * @param usage Key usage for this buffer
    1601             :  * @param data array of buffers to process
    1602             :  * @param num_data length of array
    1603             :  * @param type return checksum type if not NULL
    1604             :  *
    1605             :  * @return Return an error code or 0.
    1606             :  * @ingroup krb5_crypto
    1607             :  */
    1608             : 
    1609             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
    1610           0 : krb5_verify_checksum_iov(krb5_context context,
    1611             :                          krb5_crypto crypto,
    1612             :                          unsigned usage,
    1613             :                          krb5_crypto_iov *data,
    1614             :                          unsigned int num_data,
    1615             :                          krb5_cksumtype *type)
    1616             : {
    1617           0 :     struct _krb5_encryption_type *et = crypto->et;
    1618             :     Checksum cksum;
    1619             :     krb5_crypto_iov *civ;
    1620             :     krb5_error_code ret;
    1621             :     size_t i;
    1622             :     size_t len;
    1623             :     char *p, *q;
    1624             : 
    1625           0 :     if(!derived_crypto(context, crypto)) {
    1626           0 :         krb5_clear_error_message(context);
    1627           0 :         return KRB5_CRYPTO_INTERNAL;
    1628             :     }
    1629             : 
    1630           0 :     civ = find_iv(data, num_data, KRB5_CRYPTO_TYPE_CHECKSUM);
    1631           0 :     if (civ == NULL)
    1632           0 :         return KRB5_BAD_MSIZE;
    1633             : 
    1634           0 :     len = 0;
    1635           0 :     for (i = 0; i < num_data; i++) {
    1636           0 :         if (data[i].flags != KRB5_CRYPTO_TYPE_DATA &&
    1637           0 :             data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY)
    1638           0 :             continue;
    1639           0 :         len += data[i].data.length;
    1640             :     }
    1641             : 
    1642           0 :     p = q = malloc(len);
    1643             : 
    1644           0 :     for (i = 0; i < num_data; i++) {
    1645           0 :         if (data[i].flags != KRB5_CRYPTO_TYPE_DATA &&
    1646           0 :             data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY)
    1647           0 :             continue;
    1648           0 :         memcpy(q, data[i].data.data, data[i].data.length);
    1649           0 :         q += data[i].data.length;
    1650             :     }
    1651             : 
    1652           0 :     cksum.cksumtype = CHECKSUMTYPE(et->keyed_checksum);
    1653           0 :     cksum.checksum.length = civ->data.length;
    1654           0 :     cksum.checksum.data = civ->data.data;
    1655             : 
    1656           0 :     ret = krb5_verify_checksum(context, crypto, usage, p, len, &cksum);
    1657           0 :     free(p);
    1658             : 
    1659           0 :     if (ret == 0 && type)
    1660           0 :         *type = cksum.cksumtype;
    1661             : 
    1662           0 :     return ret;
    1663             : }
    1664             : 
    1665             : 
    1666             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
    1667     3374307 : krb5_crypto_length(krb5_context context,
    1668             :                    krb5_crypto crypto,
    1669             :                    int type,
    1670             :                    size_t *len)
    1671             : {
    1672     3381422 :     if (!derived_crypto(context, crypto)) {
    1673           0 :         krb5_set_error_message(context, EINVAL, "not a derived crypto");
    1674           0 :         return EINVAL;
    1675             :     }
    1676             : 
    1677     3374307 :     switch(type) {
    1678           0 :     case KRB5_CRYPTO_TYPE_EMPTY:
    1679           0 :         *len = 0;
    1680           0 :         return 0;
    1681     1228963 :     case KRB5_CRYPTO_TYPE_HEADER:
    1682     1228963 :         *len = crypto->et->blocksize;
    1683     1228963 :         return 0;
    1684           0 :     case KRB5_CRYPTO_TYPE_DATA:
    1685             :     case KRB5_CRYPTO_TYPE_SIGN_ONLY:
    1686             :         /* len must already been filled in */
    1687           0 :         return 0;
    1688      916381 :     case KRB5_CRYPTO_TYPE_PADDING:
    1689      916381 :         if (crypto->et->padsize > 1)
    1690           0 :             *len = crypto->et->padsize;
    1691             :         else
    1692      916381 :             *len = 0;
    1693      914884 :         return 0;
    1694     1228963 :     case KRB5_CRYPTO_TYPE_TRAILER:
    1695     1228963 :         *len = CHECKSUMSIZE(crypto->et->keyed_checksum);
    1696     1228963 :         return 0;
    1697           0 :     case KRB5_CRYPTO_TYPE_CHECKSUM:
    1698           0 :         if (crypto->et->keyed_checksum)
    1699           0 :             *len = CHECKSUMSIZE(crypto->et->keyed_checksum);
    1700             :         else
    1701           0 :             *len = CHECKSUMSIZE(crypto->et->checksum);
    1702           0 :         return 0;
    1703             :     }
    1704           0 :     krb5_set_error_message(context, EINVAL,
    1705             :                            "%d not a supported type", type);
    1706           0 :     return EINVAL;
    1707             : }
    1708             : 
    1709             : 
    1710             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
    1711           0 : krb5_crypto_length_iov(krb5_context context,
    1712             :                        krb5_crypto crypto,
    1713             :                        krb5_crypto_iov *data,
    1714             :                        unsigned int num_data)
    1715             : {
    1716             :     krb5_error_code ret;
    1717             :     size_t i;
    1718             : 
    1719           0 :     for (i = 0; i < num_data; i++) {
    1720           0 :         ret = krb5_crypto_length(context, crypto,
    1721           0 :                                  data[i].flags,
    1722           0 :                                  &data[i].data.length);
    1723           0 :         if (ret)
    1724           0 :             return ret;
    1725             :     }
    1726           0 :     return 0;
    1727             : }
    1728             : 
    1729             : 
    1730             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
    1731      496528 : krb5_encrypt_ivec(krb5_context context,
    1732             :                   krb5_crypto crypto,
    1733             :                   unsigned usage,
    1734             :                   const void *data,
    1735             :                   size_t len,
    1736             :                   krb5_data *result,
    1737             :                   void *ivec)
    1738             : {
    1739      502854 :     if(derived_crypto(context, crypto))
    1740      458327 :         return encrypt_internal_derived(context, crypto, usage,
    1741             :                                         data, len, result, ivec);
    1742       38503 :     else if (special_crypto(context, crypto))
    1743       38201 :         return encrypt_internal_special (context, crypto, usage,
    1744             :                                          data, len, result, ivec);
    1745             :     else
    1746           0 :         return encrypt_internal(context, crypto, data, len, result, ivec);
    1747             : }
    1748             : 
    1749             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
    1750      496528 : krb5_encrypt(krb5_context context,
    1751             :              krb5_crypto crypto,
    1752             :              unsigned usage,
    1753             :              const void *data,
    1754             :              size_t len,
    1755             :              krb5_data *result)
    1756             : {
    1757      496528 :     return krb5_encrypt_ivec(context, crypto, usage, data, len, result, NULL);
    1758             : }
    1759             : 
    1760             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
    1761      146572 : krb5_encrypt_EncryptedData(krb5_context context,
    1762             :                            krb5_crypto crypto,
    1763             :                            unsigned usage,
    1764             :                            void *data,
    1765             :                            size_t len,
    1766             :                            int kvno,
    1767             :                            EncryptedData *result)
    1768             : {
    1769      146572 :     result->etype = CRYPTO_ETYPE(crypto);
    1770      146572 :     if(kvno){
    1771       91887 :         ALLOC(result->kvno, 1);
    1772       91887 :         *result->kvno = kvno;
    1773             :     }else
    1774       54685 :         result->kvno = NULL;
    1775      146572 :     return krb5_encrypt(context, crypto, usage, data, len, &result->cipher);
    1776             : }
    1777             : 
    1778             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
    1779      533971 : krb5_decrypt_ivec(krb5_context context,
    1780             :                   krb5_crypto crypto,
    1781             :                   unsigned usage,
    1782             :                   void *data,
    1783             :                   size_t len,
    1784             :                   krb5_data *result,
    1785             :                   void *ivec)
    1786             : {
    1787      540437 :     if(derived_crypto(context, crypto))
    1788      498882 :         return decrypt_internal_derived(context, crypto, usage,
    1789             :                                         data, len, result, ivec);
    1790       35391 :     else if (special_crypto (context, crypto))
    1791       35089 :         return decrypt_internal_special(context, crypto, usage,
    1792             :                                         data, len, result, ivec);
    1793             :     else
    1794           0 :         return decrypt_internal(context, crypto, data, len, result, ivec);
    1795             : }
    1796             : 
    1797             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
    1798      533967 : krb5_decrypt(krb5_context context,
    1799             :              krb5_crypto crypto,
    1800             :              unsigned usage,
    1801             :              void *data,
    1802             :              size_t len,
    1803             :              krb5_data *result)
    1804             : {
    1805      533967 :     return krb5_decrypt_ivec (context, crypto, usage, data, len, result,
    1806             :                               NULL);
    1807             : }
    1808             : 
    1809             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
    1810      303571 : krb5_decrypt_EncryptedData(krb5_context context,
    1811             :                            krb5_crypto crypto,
    1812             :                            unsigned usage,
    1813             :                            const EncryptedData *e,
    1814             :                            krb5_data *result)
    1815             : {
    1816      303571 :     return krb5_decrypt(context, crypto, usage,
    1817             :                         e->cipher.data, e->cipher.length, result);
    1818             : }
    1819             : 
    1820             : /************************************************************
    1821             :  *                                                          *
    1822             :  ************************************************************/
    1823             : 
    1824             : krb5_error_code
    1825     1617967 : _krb5_derive_key(krb5_context context,
    1826             :                  struct _krb5_encryption_type *et,
    1827             :                  struct _krb5_key_data *key,
    1828             :                  const void *constant,
    1829             :                  size_t len)
    1830             : {
    1831     1617967 :     unsigned char *k = NULL;
    1832     1617967 :     unsigned int nblocks = 0, i;
    1833     1617967 :     krb5_error_code ret = 0;
    1834     1617967 :     struct _krb5_key_type *kt = et->keytype;
    1835             : 
    1836     1617967 :     ret = _key_schedule(context, key);
    1837     1617967 :     if(ret)
    1838           0 :         return ret;
    1839     3197918 :     if(et->blocksize * 8 < kt->bits || len != et->blocksize) {
    1840     1617967 :         nblocks = (kt->bits + et->blocksize * 8 - 1) / (et->blocksize * 8);
    1841     1617967 :         k = malloc(nblocks * et->blocksize);
    1842     1617967 :         if(k == NULL) {
    1843           0 :             ret = ENOMEM;
    1844           0 :             krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
    1845           0 :             goto out;
    1846             :         }
    1847     1617967 :         ret = _krb5_n_fold(constant, len, k, et->blocksize);
    1848     1617967 :         if (ret) {
    1849           0 :             krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
    1850           0 :             goto out;
    1851             :         }
    1852             : 
    1853     4796982 :         for(i = 0; i < nblocks; i++) {
    1854     3217031 :             if(i > 0)
    1855     3198128 :                 memcpy(k + i * et->blocksize,
    1856     1599064 :                        k + (i - 1) * et->blocksize,
    1857             :                        et->blocksize);
    1858     3217031 :             ret = (*et->encrypt)(context, key, k + i * et->blocksize,
    1859             :                                  et->blocksize, 1, 0, NULL);
    1860     3217031 :             if (ret) {
    1861           0 :                     krb5_set_error_message(context, ret, N_("encrypt failed", ""));
    1862           0 :                     goto out;
    1863             :             }
    1864             :         }
    1865             :     } else {
    1866             :         /* this case is probably broken, but won't be run anyway */
    1867           0 :         void *c = malloc(len);
    1868           0 :         size_t res_len = (kt->bits + 7) / 8;
    1869             : 
    1870           0 :         if(len != 0 && c == NULL) {
    1871           0 :             ret = ENOMEM;
    1872           0 :             krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
    1873           0 :             goto out;
    1874             :         }
    1875           0 :         memcpy(c, constant, len);
    1876           0 :         ret = (*et->encrypt)(context, key, c, len, 1, 0, NULL);
    1877           0 :         if (ret) {
    1878           0 :                 free(c);
    1879           0 :                 krb5_set_error_message(context, ret, N_("encrypt failed", ""));
    1880           0 :                 goto out;
    1881             :         }
    1882           0 :         k = malloc(res_len);
    1883           0 :         if(res_len != 0 && k == NULL) {
    1884           0 :             free(c);
    1885           0 :             ret = ENOMEM;
    1886           0 :             krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
    1887           0 :             goto out;
    1888             :         }
    1889           0 :         ret = _krb5_n_fold(c, len, k, res_len);
    1890           0 :         free(c);
    1891           0 :         if (ret) {
    1892           0 :             krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
    1893           0 :             goto out;
    1894             :         }
    1895             :     }
    1896             : 
    1897             :     /* XXX keytype dependent post-processing */
    1898     1617967 :     switch(kt->type) {
    1899           0 :     case KRB5_ENCTYPE_OLD_DES3_CBC_SHA1:
    1900           0 :         _krb5_DES3_random_to_key(context, key->key, k, nblocks * et->blocksize);
    1901           0 :         break;
    1902     1617967 :     case KRB5_ENCTYPE_AES128_CTS_HMAC_SHA1_96:
    1903             :     case KRB5_ENCTYPE_AES256_CTS_HMAC_SHA1_96:
    1904     1617967 :         memcpy(key->key->keyvalue.data, k, key->key->keyvalue.length);
    1905     1579951 :         break;
    1906           0 :     default:
    1907           0 :         ret = KRB5_CRYPTO_INTERNAL;
    1908           0 :         krb5_set_error_message(context, ret,
    1909           0 :                                N_("derive_key() called with unknown keytype (%u)", ""),
    1910           0 :                                kt->type);
    1911           0 :         break;
    1912             :     }
    1913     1617967 :  out:
    1914     1617967 :     if (key->schedule) {
    1915     1617967 :         free_key_schedule(context, key, et);
    1916     1617967 :         key->schedule = NULL;
    1917             :     }
    1918     1617967 :     if (k) {
    1919     1655983 :         memset(k, 0, nblocks * et->blocksize);
    1920     1617967 :         free(k);
    1921             :     }
    1922     1579951 :     return ret;
    1923             : }
    1924             : 
    1925             : static struct _krb5_key_data *
    1926     1561667 : _new_derived_key(krb5_crypto crypto, unsigned usage)
    1927             : {
    1928     1561667 :     struct _krb5_key_usage *d = crypto->key_usage;
    1929     1561667 :     d = realloc(d, (crypto->num_key_usage + 1) * sizeof(*d));
    1930     1561667 :     if(d == NULL)
    1931           0 :         return NULL;
    1932     1561667 :     crypto->key_usage = d;
    1933     1561667 :     d += crypto->num_key_usage++;
    1934     1561667 :     memset(d, 0, sizeof(*d));
    1935     1561667 :     d->usage = usage;
    1936     1561667 :     return &d->key;
    1937             : }
    1938             : 
    1939             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
    1940           0 : krb5_derive_key(krb5_context context,
    1941             :                 const krb5_keyblock *key,
    1942             :                 krb5_enctype etype,
    1943             :                 const void *constant,
    1944             :                 size_t constant_len,
    1945             :                 krb5_keyblock **derived_key)
    1946             : {
    1947             :     krb5_error_code ret;
    1948             :     struct _krb5_encryption_type *et;
    1949             :     struct _krb5_key_data d;
    1950             : 
    1951           0 :     *derived_key = NULL;
    1952             : 
    1953           0 :     et = _krb5_find_enctype (etype);
    1954           0 :     if (et == NULL) {
    1955           0 :         krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
    1956           0 :                                N_("encryption type %d not supported", ""),
    1957             :                                etype);
    1958           0 :         return KRB5_PROG_ETYPE_NOSUPP;
    1959             :     }
    1960             : 
    1961           0 :     ret = krb5_copy_keyblock(context, key, &d.key);
    1962           0 :     if (ret)
    1963           0 :         return ret;
    1964             : 
    1965           0 :     d.schedule = NULL;
    1966           0 :     ret = _krb5_derive_key(context, et, &d, constant, constant_len);
    1967           0 :     if (ret == 0)
    1968           0 :         ret = krb5_copy_keyblock(context, d.key, derived_key);
    1969           0 :     _krb5_free_key_data(context, &d, et);
    1970           0 :     return ret;
    1971             : }
    1972             : 
    1973             : static krb5_error_code
    1974     5602933 : _get_derived_key(krb5_context context,
    1975             :                  krb5_crypto crypto,
    1976             :                  unsigned usage,
    1977             :                  struct _krb5_key_data **key)
    1978             : {
    1979             :     int i;
    1980             :     struct _krb5_key_data *d;
    1981             :     unsigned char constant[5];
    1982             : 
    1983    17830859 :     for(i = 0; i < crypto->num_key_usage; i++)
    1984    16269192 :         if(crypto->key_usage[i].usage == usage) {
    1985     4041266 :             *key = &crypto->key_usage[i].key;
    1986     4041266 :             return 0;
    1987             :         }
    1988     1561667 :     d = _new_derived_key(crypto, usage);
    1989     1561667 :     if(d == NULL) {
    1990           0 :         krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
    1991           0 :         return ENOMEM;
    1992             :     }
    1993     1561667 :     krb5_copy_keyblock(context, crypto->key.key, &d->key);
    1994     1561667 :     _krb5_put_int(constant, usage, 5);
    1995     1561667 :     _krb5_derive_key(context, crypto->et, d, constant, sizeof(constant));
    1996     1561667 :     *key = d;
    1997     1561667 :     return 0;
    1998             : }
    1999             : 
    2000             : /**
    2001             :  * Create a crypto context used for all encryption and signature
    2002             :  * operation. The encryption type to use is taken from the key, but
    2003             :  * can be overridden with the enctype parameter.  This can be useful
    2004             :  * for encryptions types which is compatiable (DES for example).
    2005             :  *
    2006             :  * To free the crypto context, use krb5_crypto_destroy().
    2007             :  *
    2008             :  * @param context Kerberos context
    2009             :  * @param key the key block information with all key data
    2010             :  * @param etype the encryption type
    2011             :  * @param crypto the resulting crypto context
    2012             :  *
    2013             :  * @return Return an error code or 0.
    2014             :  *
    2015             :  * @ingroup krb5_crypto
    2016             :  */
    2017             : 
    2018             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
    2019     1355099 : krb5_crypto_init(krb5_context context,
    2020             :                  const krb5_keyblock *key,
    2021             :                  krb5_enctype etype,
    2022             :                  krb5_crypto *crypto)
    2023             : {
    2024             :     krb5_error_code ret;
    2025     1355099 :     ALLOC(*crypto, 1);
    2026     1355099 :     if(*crypto == NULL) {
    2027           0 :         krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
    2028           0 :         return ENOMEM;
    2029             :     }
    2030     1355099 :     if(etype == ETYPE_NULL)
    2031     1219136 :         etype = key->keytype;
    2032     1355099 :     (*crypto)->et = _krb5_find_enctype(etype);
    2033     1355099 :     if((*crypto)->et == NULL || ((*crypto)->et->flags & F_DISABLED)) {
    2034           0 :         free(*crypto);
    2035           0 :         *crypto = NULL;
    2036           0 :         krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
    2037           0 :                                 N_("encryption type %d not supported", ""),
    2038             :                                 etype);
    2039           0 :         return KRB5_PROG_ETYPE_NOSUPP;
    2040             :     }
    2041     1355099 :     if((*crypto)->et->keytype->size != key->keyvalue.length) {
    2042           0 :         free(*crypto);
    2043           0 :         *crypto = NULL;
    2044           0 :         krb5_set_error_message (context, KRB5_BAD_KEYSIZE,
    2045             :                                 "encryption key has bad length");
    2046           0 :         return KRB5_BAD_KEYSIZE;
    2047             :     }
    2048     1355099 :     ret = krb5_copy_keyblock(context, key, &(*crypto)->key.key);
    2049     1355099 :     if(ret) {
    2050           0 :         free(*crypto);
    2051           0 :         *crypto = NULL;
    2052           0 :         return ret;
    2053             :     }
    2054     1355099 :     (*crypto)->key.schedule = NULL;
    2055     1355099 :     (*crypto)->num_key_usage = 0;
    2056     1355099 :     (*crypto)->key_usage = NULL;
    2057     1355099 :     return 0;
    2058             : }
    2059             : 
    2060             : static void
    2061     3306796 : free_key_schedule(krb5_context context,
    2062             :                   struct _krb5_key_data *key,
    2063             :                   struct _krb5_encryption_type *et)
    2064             : {
    2065     3306796 :     if (et->keytype->cleanup)
    2066     3306796 :         (*et->keytype->cleanup)(context, key);
    2067     3381986 :     memset(key->schedule->data, 0, key->schedule->length);
    2068     3306796 :     krb5_free_data(context, key->schedule);
    2069     3306796 : }
    2070             : 
    2071             : void
    2072     2972931 : _krb5_free_key_data(krb5_context context, struct _krb5_key_data *key,
    2073             :               struct _krb5_encryption_type *et)
    2074             : {
    2075     2972931 :     krb5_free_keyblock(context, key->key);
    2076     2972931 :     if(key->schedule) {
    2077     1688829 :         free_key_schedule(context, key, et);
    2078     1688829 :         key->schedule = NULL;
    2079             :     }
    2080     2972931 : }
    2081             : 
    2082             : static void
    2083     1524485 : free_key_usage(krb5_context context, struct _krb5_key_usage *ku,
    2084             :                struct _krb5_encryption_type *et)
    2085             : {
    2086     1561633 :     _krb5_free_key_data(context, &ku->key, et);
    2087     1524485 : }
    2088             : 
    2089             : /**
    2090             :  * Free a crypto context created by krb5_crypto_init().
    2091             :  *
    2092             :  * @param context Kerberos context
    2093             :  * @param crypto crypto context to free
    2094             :  *
    2095             :  * @return Return an error code or 0.
    2096             :  *
    2097             :  * @ingroup krb5_crypto
    2098             :  */
    2099             : 
    2100             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
    2101     1354998 : krb5_crypto_destroy(krb5_context context,
    2102             :                     krb5_crypto crypto)
    2103             : {
    2104             :     int i;
    2105             : 
    2106     2916631 :     for(i = 0; i < crypto->num_key_usage; i++)
    2107     1598781 :         free_key_usage(context, &crypto->key_usage[i], crypto->et);
    2108     1354998 :     free(crypto->key_usage);
    2109     1354998 :     _krb5_free_key_data(context, &crypto->key, crypto->et);
    2110     1354998 :     free (crypto);
    2111     1354998 :     return 0;
    2112             : }
    2113             : 
    2114             : /**
    2115             :  * Return the blocksize used algorithm referenced by the crypto context
    2116             :  *
    2117             :  * @param context Kerberos context
    2118             :  * @param crypto crypto context to query
    2119             :  * @param blocksize the resulting blocksize
    2120             :  *
    2121             :  * @return Return an error code or 0.
    2122             :  *
    2123             :  * @ingroup krb5_crypto
    2124             :  */
    2125             : 
    2126             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
    2127      916381 : krb5_crypto_getblocksize(krb5_context context,
    2128             :                          krb5_crypto crypto,
    2129             :                          size_t *blocksize)
    2130             : {
    2131      916381 :     *blocksize = crypto->et->blocksize;
    2132      916381 :     return 0;
    2133             : }
    2134             : 
    2135             : /**
    2136             :  * Return the encryption type used by the crypto context
    2137             :  *
    2138             :  * @param context Kerberos context
    2139             :  * @param crypto crypto context to query
    2140             :  * @param enctype the resulting encryption type
    2141             :  *
    2142             :  * @return Return an error code or 0.
    2143             :  *
    2144             :  * @ingroup krb5_crypto
    2145             :  */
    2146             : 
    2147             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
    2148          26 : krb5_crypto_getenctype(krb5_context context,
    2149             :                        krb5_crypto crypto,
    2150             :                        krb5_enctype *enctype)
    2151             : {
    2152          26 :     *enctype = crypto->et->type;
    2153          26 :     return 0;
    2154             : }
    2155             : 
    2156             : /**
    2157             :  * Return the padding size used by the crypto context
    2158             :  *
    2159             :  * @param context Kerberos context
    2160             :  * @param crypto crypto context to query
    2161             :  * @param padsize the return padding size
    2162             :  *
    2163             :  * @return Return an error code or 0.
    2164             :  *
    2165             :  * @ingroup krb5_crypto
    2166             :  */
    2167             : 
    2168             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
    2169      230396 : krb5_crypto_getpadsize(krb5_context context,
    2170             :                        krb5_crypto crypto,
    2171             :                        size_t *padsize)
    2172             : {
    2173      230396 :     *padsize = crypto->et->padsize;
    2174      230396 :     return 0;
    2175             : }
    2176             : 
    2177             : /**
    2178             :  * Return the confounder size used by the crypto context
    2179             :  *
    2180             :  * @param context Kerberos context
    2181             :  * @param crypto crypto context to query
    2182             :  * @param confoundersize the returned confounder size
    2183             :  *
    2184             :  * @return Return an error code or 0.
    2185             :  *
    2186             :  * @ingroup krb5_crypto
    2187             :  */
    2188             : 
    2189             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
    2190           0 : krb5_crypto_getconfoundersize(krb5_context context,
    2191             :                               krb5_crypto crypto,
    2192             :                               size_t *confoundersize)
    2193             : {
    2194           0 :     *confoundersize = crypto->et->confoundersize;
    2195           0 :     return 0;
    2196             : }
    2197             : 
    2198             : 
    2199             : /**
    2200             :  * Disable encryption type
    2201             :  *
    2202             :  * @param context Kerberos 5 context
    2203             :  * @param enctype encryption type to disable
    2204             :  *
    2205             :  * @return Return an error code or 0.
    2206             :  *
    2207             :  * @ingroup krb5_crypto
    2208             :  */
    2209             : 
    2210             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
    2211           0 : krb5_enctype_disable(krb5_context context,
    2212             :                      krb5_enctype enctype)
    2213             : {
    2214           0 :     struct _krb5_encryption_type *et = _krb5_find_enctype(enctype);
    2215           0 :     if(et == NULL) {
    2216           0 :         if (context)
    2217           0 :             krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
    2218           0 :                                     N_("encryption type %d not supported", ""),
    2219             :                                     enctype);
    2220           0 :         return KRB5_PROG_ETYPE_NOSUPP;
    2221             :     }
    2222           0 :     et->flags |= F_DISABLED;
    2223           0 :     return 0;
    2224             : }
    2225             : 
    2226             : /**
    2227             :  * Enable encryption type
    2228             :  *
    2229             :  * @param context Kerberos 5 context
    2230             :  * @param enctype encryption type to enable
    2231             :  *
    2232             :  * @return Return an error code or 0.
    2233             :  *
    2234             :  * @ingroup krb5_crypto
    2235             :  */
    2236             : 
    2237             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
    2238           0 : krb5_enctype_enable(krb5_context context,
    2239             :                     krb5_enctype enctype)
    2240             : {
    2241           0 :     struct _krb5_encryption_type *et = _krb5_find_enctype(enctype);
    2242           0 :     if(et == NULL) {
    2243           0 :         if (context)
    2244           0 :             krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
    2245           0 :                                     N_("encryption type %d not supported", ""),
    2246             :                                     enctype);
    2247           0 :         return KRB5_PROG_ETYPE_NOSUPP;
    2248             :     }
    2249           0 :     et->flags &= ~F_DISABLED;
    2250           0 :     return 0;
    2251             : }
    2252             : 
    2253             : /**
    2254             :  * Enable or disable all weak encryption types
    2255             :  *
    2256             :  * @param context Kerberos 5 context
    2257             :  * @param enable true to enable, false to disable
    2258             :  *
    2259             :  * @return Return an error code or 0.
    2260             :  *
    2261             :  * @ingroup krb5_crypto
    2262             :  */
    2263             : 
    2264             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
    2265           0 : krb5_allow_weak_crypto(krb5_context context,
    2266             :                        krb5_boolean enable)
    2267             : {
    2268             :     int i;
    2269             : 
    2270           0 :     for(i = 0; i < _krb5_num_etypes; i++)
    2271           0 :         if(_krb5_etypes[i]->flags & F_WEAK) {
    2272           0 :             if(enable)
    2273           0 :                 _krb5_etypes[i]->flags &= ~F_DISABLED;
    2274             :             else
    2275           0 :                 _krb5_etypes[i]->flags |= F_DISABLED;
    2276             :         }
    2277           0 :     return 0;
    2278             : }
    2279             : 
    2280             : static size_t
    2281           0 : wrapped_length (krb5_context context,
    2282             :                 krb5_crypto  crypto,
    2283             :                 size_t       data_len)
    2284             : {
    2285           0 :     struct _krb5_encryption_type *et = crypto->et;
    2286           0 :     size_t padsize = et->padsize;
    2287           0 :     size_t checksumsize = CHECKSUMSIZE(et->checksum);
    2288             :     size_t res;
    2289             : 
    2290           0 :     res =  et->confoundersize + checksumsize + data_len;
    2291           0 :     res =  (res + padsize - 1) / padsize * padsize;
    2292           0 :     return res;
    2293             : }
    2294             : 
    2295             : static size_t
    2296      399727 : wrapped_length_dervied (krb5_context context,
    2297             :                         krb5_crypto  crypto,
    2298             :                         size_t       data_len)
    2299             : {
    2300      399727 :     struct _krb5_encryption_type *et = crypto->et;
    2301      399727 :     size_t padsize = et->padsize;
    2302             :     size_t res;
    2303             : 
    2304      399727 :     res =  et->confoundersize + data_len;
    2305      399727 :     res =  (res + padsize - 1) / padsize * padsize;
    2306      399727 :     if (et->keyed_checksum)
    2307      399727 :         res += et->keyed_checksum->checksumsize;
    2308             :     else
    2309           0 :         res += et->checksum->checksumsize;
    2310      399727 :     return res;
    2311             : }
    2312             : 
    2313             : /*
    2314             :  * Return the size of an encrypted packet of length `data_len'
    2315             :  */
    2316             : 
    2317             : KRB5_LIB_FUNCTION size_t KRB5_LIB_CALL
    2318      399727 : krb5_get_wrapped_length (krb5_context context,
    2319             :                          krb5_crypto  crypto,
    2320             :                          size_t       data_len)
    2321             : {
    2322      399727 :     if (derived_crypto (context, crypto))
    2323      399727 :         return wrapped_length_dervied (context, crypto, data_len);
    2324             :     else
    2325           0 :         return wrapped_length (context, crypto, data_len);
    2326             : }
    2327             : 
    2328             : /*
    2329             :  * Return the size of an encrypted packet of length `data_len'
    2330             :  */
    2331             : 
    2332             : static size_t
    2333           0 : crypto_overhead (krb5_context context,
    2334             :                  krb5_crypto  crypto)
    2335             : {
    2336           0 :     struct _krb5_encryption_type *et = crypto->et;
    2337             :     size_t res;
    2338             : 
    2339           0 :     res = CHECKSUMSIZE(et->checksum);
    2340           0 :     res += et->confoundersize;
    2341           0 :     if (et->padsize > 1)
    2342           0 :         res += et->padsize;
    2343           0 :     return res;
    2344             : }
    2345             : 
    2346             : static size_t
    2347           0 : crypto_overhead_dervied (krb5_context context,
    2348             :                          krb5_crypto  crypto)
    2349             : {
    2350           0 :     struct _krb5_encryption_type *et = crypto->et;
    2351             :     size_t res;
    2352             : 
    2353           0 :     if (et->keyed_checksum)
    2354           0 :         res = CHECKSUMSIZE(et->keyed_checksum);
    2355             :     else
    2356           0 :         res = CHECKSUMSIZE(et->checksum);
    2357           0 :     res += et->confoundersize;
    2358           0 :     if (et->padsize > 1)
    2359           0 :         res += et->padsize;
    2360           0 :     return res;
    2361             : }
    2362             : 
    2363             : KRB5_LIB_FUNCTION size_t KRB5_LIB_CALL
    2364           0 : krb5_crypto_overhead (krb5_context context, krb5_crypto crypto)
    2365             : {
    2366           0 :     if (derived_crypto (context, crypto))
    2367           0 :         return crypto_overhead_dervied (context, crypto);
    2368             :     else
    2369           0 :         return crypto_overhead (context, crypto);
    2370             : }
    2371             : 
    2372             : /**
    2373             :  * Converts the random bytestring to a protocol key according to
    2374             :  * Kerberos crypto frame work. It may be assumed that all the bits of
    2375             :  * the input string are equally random, even though the entropy
    2376             :  * present in the random source may be limited.
    2377             :  *
    2378             :  * @param context Kerberos 5 context
    2379             :  * @param type the enctype resulting key will be of
    2380             :  * @param data input random data to convert to a key
    2381             :  * @param size size of input random data, at least krb5_enctype_keysize() long
    2382             :  * @param key key, output key, free with krb5_free_keyblock_contents()
    2383             :  *
    2384             :  * @return Return an error code or 0.
    2385             :  *
    2386             :  * @ingroup krb5_crypto
    2387             :  */
    2388             : 
    2389             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
    2390          52 : krb5_random_to_key(krb5_context context,
    2391             :                    krb5_enctype type,
    2392             :                    const void *data,
    2393             :                    size_t size,
    2394             :                    krb5_keyblock *key)
    2395             : {
    2396             :     krb5_error_code ret;
    2397          52 :     struct _krb5_encryption_type *et = _krb5_find_enctype(type);
    2398          52 :     if(et == NULL) {
    2399           0 :         krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
    2400           0 :                                N_("encryption type %d not supported", ""),
    2401             :                                type);
    2402           0 :         return KRB5_PROG_ETYPE_NOSUPP;
    2403             :     }
    2404          52 :     if ((et->keytype->bits + 7) / 8 > size) {
    2405           0 :         krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
    2406           0 :                                N_("encryption key %s needs %d bytes "
    2407             :                                   "of random to make an encryption key "
    2408             :                                   "out of it", ""),
    2409           0 :                                et->name, (int)et->keytype->size);
    2410           0 :         return KRB5_PROG_ETYPE_NOSUPP;
    2411             :     }
    2412          52 :     ret = krb5_data_alloc(&key->keyvalue, et->keytype->size);
    2413          52 :     if(ret)
    2414           0 :         return ret;
    2415          52 :     key->keytype = type;
    2416          52 :     if (et->keytype->random_to_key)
    2417           0 :         (*et->keytype->random_to_key)(context, key, data, size);
    2418             :     else
    2419          52 :         memcpy(key->keyvalue.data, data, et->keytype->size);
    2420             : 
    2421          52 :     return 0;
    2422             : }
    2423             : 
    2424             : 
    2425             : 
    2426             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
    2427           0 : krb5_crypto_prf_length(krb5_context context,
    2428             :                        krb5_enctype type,
    2429             :                        size_t *length)
    2430             : {
    2431           0 :     struct _krb5_encryption_type *et = _krb5_find_enctype(type);
    2432             : 
    2433           0 :     if(et == NULL || et->prf_length == 0) {
    2434           0 :         krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
    2435           0 :                                N_("encryption type %d not supported", ""),
    2436             :                                type);
    2437           0 :         return KRB5_PROG_ETYPE_NOSUPP;
    2438             :     }
    2439             : 
    2440           0 :     *length = et->prf_length;
    2441           0 :     return 0;
    2442             : }
    2443             : 
    2444             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
    2445           0 : krb5_crypto_prf(krb5_context context,
    2446             :                 const krb5_crypto crypto,
    2447             :                 const krb5_data *input,
    2448             :                 krb5_data *output)
    2449             : {
    2450           0 :     struct _krb5_encryption_type *et = crypto->et;
    2451             : 
    2452           0 :     krb5_data_zero(output);
    2453             : 
    2454           0 :     if(et->prf == NULL) {
    2455           0 :         krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
    2456             :                                "kerberos prf for %s not supported",
    2457             :                                et->name);
    2458           0 :         return KRB5_PROG_ETYPE_NOSUPP;
    2459             :     }
    2460             : 
    2461           0 :     return (*et->prf)(context, crypto, input, output);
    2462             : }
    2463             : 
    2464             : static krb5_error_code
    2465           0 : krb5_crypto_prfplus(krb5_context context,
    2466             :                     const krb5_crypto crypto,
    2467             :                     const krb5_data *input,
    2468             :                     size_t length,
    2469             :                     krb5_data *output)
    2470             : {
    2471             :     krb5_error_code ret;
    2472             :     krb5_data input2;
    2473           0 :     unsigned char i = 1;
    2474             :     unsigned char *p;
    2475             : 
    2476           0 :     krb5_data_zero(&input2);
    2477           0 :     krb5_data_zero(output);
    2478             : 
    2479           0 :     krb5_clear_error_message(context);
    2480             : 
    2481           0 :     ret = krb5_data_alloc(output, length);
    2482           0 :     if (ret) goto out;
    2483           0 :     ret = krb5_data_alloc(&input2, input->length + 1);
    2484           0 :     if (ret) goto out;
    2485             : 
    2486           0 :     krb5_clear_error_message(context);
    2487             : 
    2488           0 :     memcpy(((unsigned char *)input2.data) + 1, input->data, input->length);
    2489             : 
    2490           0 :     p = output->data;
    2491             : 
    2492           0 :     while (length) {
    2493             :         krb5_data block;
    2494             : 
    2495           0 :         ((unsigned char *)input2.data)[0] = i++;
    2496             : 
    2497           0 :         ret = krb5_crypto_prf(context, crypto, &input2, &block);
    2498           0 :         if (ret)
    2499           0 :             goto out;
    2500             : 
    2501           0 :         if (block.length < length) {
    2502           0 :             memcpy(p, block.data, block.length);
    2503           0 :             length -= block.length;
    2504             :         } else {
    2505           0 :             memcpy(p, block.data, length);
    2506           0 :             length = 0;
    2507             :         }
    2508           0 :         p += block.length;
    2509           0 :         krb5_data_free(&block);
    2510             :     }
    2511             : 
    2512           0 :  out:
    2513           0 :     krb5_data_free(&input2);
    2514           0 :     if (ret)
    2515           0 :         krb5_data_free(output);
    2516           0 :     return 0;
    2517             : }
    2518             : 
    2519             : /**
    2520             :  * The FX-CF2 key derivation function, used in FAST and preauth framework.
    2521             :  *
    2522             :  * @param context Kerberos 5 context
    2523             :  * @param crypto1 first key to combine
    2524             :  * @param crypto2 second key to combine
    2525             :  * @param pepper1 factor to combine with first key to garante uniqueness
    2526             :  * @param pepper2 factor to combine with second key to garante uniqueness
    2527             :  * @param enctype the encryption type of the resulting key
    2528             :  * @param res allocated key, free with krb5_free_keyblock_contents()
    2529             :  *
    2530             :  * @return Return an error code or 0.
    2531             :  *
    2532             :  * @ingroup krb5_crypto
    2533             :  */
    2534             : 
    2535             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
    2536           0 : krb5_crypto_fx_cf2(krb5_context context,
    2537             :                    const krb5_crypto crypto1,
    2538             :                    const krb5_crypto crypto2,
    2539             :                    krb5_data *pepper1,
    2540             :                    krb5_data *pepper2,
    2541             :                    krb5_enctype enctype,
    2542             :                    krb5_keyblock *res)
    2543             : {
    2544             :     krb5_error_code ret;
    2545             :     krb5_data os1, os2;
    2546             :     size_t i, keysize;
    2547             : 
    2548           0 :     memset(res, 0, sizeof(*res));
    2549             : 
    2550           0 :     ret = krb5_enctype_keysize(context, enctype, &keysize);
    2551           0 :     if (ret)
    2552           0 :         return ret;
    2553             : 
    2554           0 :     ret = krb5_data_alloc(&res->keyvalue, keysize);
    2555           0 :     if (ret)
    2556           0 :         goto out;
    2557           0 :     ret = krb5_crypto_prfplus(context, crypto1, pepper1, keysize, &os1);
    2558           0 :     if (ret)
    2559           0 :         goto out;
    2560           0 :     ret = krb5_crypto_prfplus(context, crypto2, pepper2, keysize, &os2);
    2561           0 :     if (ret)
    2562           0 :         goto out;
    2563             : 
    2564           0 :     res->keytype = enctype;
    2565             :     {
    2566           0 :         unsigned char *p1 = os1.data, *p2 = os2.data, *p3 = res->keyvalue.data;
    2567           0 :         for (i = 0; i < keysize; i++)
    2568           0 :             p3[i] = p1[i] ^ p2[i];
    2569             :     }
    2570           0 :  out:
    2571           0 :     if (ret)
    2572           0 :         krb5_data_free(&res->keyvalue);
    2573           0 :     krb5_data_free(&os1);
    2574           0 :     krb5_data_free(&os2);
    2575             : 
    2576           0 :     return ret;
    2577             : }
    2578             : 
    2579             : 
    2580             : 
    2581             : #ifndef HEIMDAL_SMALLER
    2582             : 
    2583             : /**
    2584             :  * Deprecated: keytypes doesn't exists, they are really enctypes.
    2585             :  *
    2586             :  * @ingroup krb5_deprecated
    2587             :  */
    2588             : 
    2589             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
    2590           0 : krb5_keytype_to_enctypes (krb5_context context,
    2591             :                           krb5_keytype keytype,
    2592             :                           unsigned *len,
    2593             :                           krb5_enctype **val)
    2594             :     KRB5_DEPRECATED_FUNCTION("Use X instead")
    2595             : {
    2596             :     int i;
    2597           0 :     unsigned n = 0;
    2598             :     krb5_enctype *ret;
    2599             : 
    2600           0 :     for (i = _krb5_num_etypes - 1; i >= 0; --i) {
    2601           0 :         if (_krb5_etypes[i]->keytype->type == keytype
    2602           0 :             && !(_krb5_etypes[i]->flags & F_PSEUDO)
    2603           0 :             && krb5_enctype_valid(context, _krb5_etypes[i]->type) == 0)
    2604           0 :             ++n;
    2605             :     }
    2606           0 :     if (n == 0) {
    2607           0 :         krb5_set_error_message(context, KRB5_PROG_KEYTYPE_NOSUPP,
    2608             :                                "Keytype have no mapping");
    2609           0 :         return KRB5_PROG_KEYTYPE_NOSUPP;
    2610             :     }
    2611             : 
    2612           0 :     ret = malloc(n * sizeof(*ret));
    2613           0 :     if (ret == NULL && n != 0) {
    2614           0 :         krb5_set_error_message(context, ENOMEM, "malloc: out of memory");
    2615           0 :         return ENOMEM;
    2616             :     }
    2617           0 :     n = 0;
    2618           0 :     for (i = _krb5_num_etypes - 1; i >= 0; --i) {
    2619           0 :         if (_krb5_etypes[i]->keytype->type == keytype
    2620           0 :             && !(_krb5_etypes[i]->flags & F_PSEUDO)
    2621           0 :             && krb5_enctype_valid(context, _krb5_etypes[i]->type) == 0)
    2622           0 :             ret[n++] = _krb5_etypes[i]->type;
    2623             :     }
    2624           0 :     *len = n;
    2625           0 :     *val = ret;
    2626           0 :     return 0;
    2627             : }
    2628             : 
    2629             : /**
    2630             :  * Deprecated: keytypes doesn't exists, they are really enctypes.
    2631             :  *
    2632             :  * @ingroup krb5_deprecated
    2633             :  */
    2634             : 
    2635             : /* if two enctypes have compatible keys */
    2636             : KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL
    2637           0 : krb5_enctypes_compatible_keys(krb5_context context,
    2638             :                               krb5_enctype etype1,
    2639             :                               krb5_enctype etype2)
    2640             :     KRB5_DEPRECATED_FUNCTION("Use X instead")
    2641             : {
    2642           0 :     struct _krb5_encryption_type *e1 = _krb5_find_enctype(etype1);
    2643           0 :     struct _krb5_encryption_type *e2 = _krb5_find_enctype(etype2);
    2644           0 :     return e1 != NULL && e2 != NULL && e1->keytype == e2->keytype;
    2645             : }
    2646             : 
    2647             : #endif /* HEIMDAL_SMALLER */

Generated by: LCOV version 1.13