LCOV - code coverage report
Current view: top level - third_party/heimdal/lib/krb5 - crypto-arcfour.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 156 174 89.7 %
Date: 2024-04-21 15:09:00 Functions: 6 6 100.0 %

          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             : /*
      35             :  * ARCFOUR
      36             :  */
      37             : 
      38             : #include "krb5_locl.h"
      39             : 
      40             : static struct _krb5_key_type keytype_arcfour = {
      41             :     KRB5_ENCTYPE_ARCFOUR_HMAC_MD5,
      42             :     "arcfour",
      43             :     128,
      44             :     16,
      45             :     sizeof(struct _krb5_evp_schedule),
      46             :     NULL,
      47             :     _krb5_evp_schedule,
      48             :     _krb5_arcfour_salt,
      49             :     NULL,
      50             :     _krb5_evp_cleanup,
      51             :     EVP_rc4
      52             : };
      53             : 
      54             : /*
      55             :  * checksum according to section 5. of draft-brezak-win2k-krb-rc4-hmac-03.txt
      56             :  */
      57             : 
      58             : krb5_error_code
      59      194047 : _krb5_HMAC_MD5_checksum(krb5_context context,
      60             :                         krb5_crypto crypto,
      61             :                         struct _krb5_key_data *key,
      62             :                         unsigned usage,
      63             :                         const struct krb5_crypto_iov *iov,
      64             :                         int niov,
      65             :                         Checksum *result)
      66             : {
      67          44 :     EVP_MD_CTX *m;
      68      194047 :     struct _krb5_checksum_type *c = _krb5_find_checksum (CKSUMTYPE_RSA_MD5);
      69      194047 :     const char signature[] = "signaturekey";
      70          44 :     Checksum ksign_c;
      71          44 :     struct _krb5_key_data ksign;
      72          44 :     krb5_keyblock kb;
      73          44 :     unsigned char t[4];
      74          44 :     unsigned char tmp[16];
      75          44 :     unsigned char ksign_c_data[16];
      76          44 :     krb5_error_code ret;
      77          44 :     int i;
      78             : 
      79      194047 :     if (crypto != NULL) {
      80      169134 :         if (crypto->mdctx == NULL)
      81      169032 :             crypto->mdctx = EVP_MD_CTX_create();
      82      169134 :         if (crypto->mdctx == NULL)
      83           0 :             return krb5_enomem(context);
      84      169090 :         m = crypto->mdctx;
      85             :     } else
      86       24913 :         m = EVP_MD_CTX_create();
      87             : 
      88      194047 :     ksign_c.checksum.length = sizeof(ksign_c_data);
      89      194047 :     ksign_c.checksum.data   = ksign_c_data;
      90      194047 :     ret = _krb5_internal_hmac(context, crypto, c, signature, sizeof(signature),
      91             :                               0, key, &ksign_c);
      92      194047 :     if (ret)
      93           0 :         goto out;
      94             : 
      95      194047 :     ksign.key = &kb;
      96      194047 :     kb.keyvalue = ksign_c.checksum;
      97      194047 :     EVP_DigestInit_ex(m, EVP_md5(), NULL);
      98      194047 :     t[0] = (usage >>  0) & 0xFF;
      99      194047 :     t[1] = (usage >>  8) & 0xFF;
     100      194047 :     t[2] = (usage >> 16) & 0xFF;
     101      194047 :     t[3] = (usage >> 24) & 0xFF;
     102      194047 :     EVP_DigestUpdate(m, t, 4);
     103      388138 :     for (i = 0; i < niov; i++) {
     104      194047 :         if (_krb5_crypto_iov_should_sign(&iov[i]))
     105      194047 :             EVP_DigestUpdate(m, iov[i].data.data, iov[i].data.length);
     106             :     }
     107      194047 :     EVP_DigestFinal_ex (m, tmp, NULL);
     108             : 
     109      194047 :     ret = _krb5_internal_hmac(context, crypto, c, tmp, sizeof(tmp), 0, &ksign, result);
     110      194047 : out:
     111      194047 :     if (crypto == NULL)
     112       24913 :         EVP_MD_CTX_destroy(m);
     113             : 
     114      194003 :     return ret;
     115             : }
     116             : 
     117             : struct _krb5_checksum_type _krb5_checksum_hmac_md5 = {
     118             :     CKSUMTYPE_HMAC_MD5,
     119             :     "hmac-md5",
     120             :     64,
     121             :     16,
     122             :     F_KEYED | F_CPROOF,
     123             :     _krb5_HMAC_MD5_checksum,
     124             :     NULL
     125             : };
     126             : 
     127             : /*
     128             :  * section 6 of draft-brezak-win2k-krb-rc4-hmac-03
     129             :  *
     130             :  * warning: not for small children
     131             :  */
     132             : 
     133             : static krb5_error_code
     134       26903 : ARCFOUR_subencrypt(krb5_context context,
     135             :                    struct _krb5_key_data *key,
     136             :                    void *data,
     137             :                    size_t len,
     138             :                    unsigned usage,
     139             :                    void *ivec)
     140             : {
     141          18 :     EVP_CIPHER_CTX ctx;
     142       26903 :     struct _krb5_checksum_type *c = _krb5_find_checksum (CKSUMTYPE_RSA_MD5);
     143          18 :     Checksum k1_c, k2_c, k3_c, cksum;
     144          18 :     struct _krb5_key_data ke;
     145          18 :     krb5_keyblock kb;
     146          18 :     unsigned char t[4];
     147       26903 :     unsigned char *cdata = data;
     148          18 :     unsigned char k1_c_data[16], k2_c_data[16], k3_c_data[16];
     149          18 :     krb5_error_code ret;
     150             : 
     151       26903 :     if (len < 16) {
     152           0 :             return KRB5KRB_AP_ERR_INAPP_CKSUM;
     153             :     }
     154             : 
     155       26903 :     t[0] = (usage >>  0) & 0xFF;
     156       26903 :     t[1] = (usage >>  8) & 0xFF;
     157       26903 :     t[2] = (usage >> 16) & 0xFF;
     158       26903 :     t[3] = (usage >> 24) & 0xFF;
     159             : 
     160       26903 :     k1_c.checksum.length = sizeof(k1_c_data);
     161       26903 :     k1_c.checksum.data   = k1_c_data;
     162             : 
     163       26903 :     ret = _krb5_internal_hmac(context, NULL, c, t, sizeof(t), 0, key, &k1_c);
     164       26903 :     if (ret)
     165           0 :         krb5_abortx(context, "hmac failed");
     166             : 
     167       26903 :     memcpy (k2_c_data, k1_c_data, sizeof(k1_c_data));
     168             : 
     169       26903 :     k2_c.checksum.length = sizeof(k2_c_data);
     170       26903 :     k2_c.checksum.data   = k2_c_data;
     171             : 
     172       26903 :     ke.key = &kb;
     173       26903 :     kb.keyvalue = k2_c.checksum;
     174             : 
     175       26903 :     cksum.checksum.length = 16;
     176       26903 :     cksum.checksum.data   = data;
     177             : 
     178       26903 :     ret = _krb5_internal_hmac(context, NULL, c, cdata + 16, len - 16, 0, &ke, &cksum);
     179       26903 :     if (ret)
     180           0 :         krb5_abortx(context, "hmac failed");
     181             : 
     182       26903 :     ke.key = &kb;
     183       26903 :     kb.keyvalue = k1_c.checksum;
     184             : 
     185       26903 :     k3_c.checksum.length = sizeof(k3_c_data);
     186       26903 :     k3_c.checksum.data   = k3_c_data;
     187             : 
     188       26903 :     ret = _krb5_internal_hmac(context, NULL, c, data, 16, 0, &ke, &k3_c);
     189       26903 :     if (ret)
     190           0 :         krb5_abortx(context, "hmac failed");
     191             : 
     192       26903 :     EVP_CIPHER_CTX_init(&ctx);
     193             : 
     194       26903 :     EVP_CipherInit_ex(&ctx, EVP_rc4(), NULL, k3_c.checksum.data, NULL, 1);
     195       26903 :     EVP_Cipher(&ctx, cdata + 16, cdata + 16, len - 16);
     196       26903 :     EVP_CIPHER_CTX_cleanup(&ctx);
     197             : 
     198       26903 :     memset_s(k1_c_data, sizeof(k1_c_data), 0, sizeof(k1_c_data));
     199       26903 :     memset_s(k2_c_data, sizeof(k2_c_data), 0, sizeof(k2_c_data));
     200       26903 :     memset_s(k3_c_data, sizeof(k3_c_data), 0, sizeof(k3_c_data));
     201       26903 :     return 0;
     202             : }
     203             : 
     204             : static krb5_error_code
     205       21212 : ARCFOUR_subdecrypt(krb5_context context,
     206             :                    struct _krb5_key_data *key,
     207             :                    void *data,
     208             :                    size_t len,
     209             :                    unsigned usage,
     210             :                    void *ivec)
     211             : {
     212          18 :     EVP_CIPHER_CTX ctx;
     213       21212 :     struct _krb5_checksum_type *c = _krb5_find_checksum (CKSUMTYPE_RSA_MD5);
     214          18 :     Checksum k1_c, k2_c, k3_c, cksum;
     215          18 :     struct _krb5_key_data ke;
     216          18 :     krb5_keyblock kb;
     217          18 :     unsigned char t[4];
     218       21212 :     unsigned char *cdata = data;
     219          18 :     unsigned char k1_c_data[16], k2_c_data[16], k3_c_data[16];
     220          18 :     unsigned char cksum_data[16];
     221          18 :     krb5_error_code ret;
     222             : 
     223       21212 :     if (len < 16) {
     224           0 :             return KRB5KRB_AP_ERR_INAPP_CKSUM;
     225             :     }
     226             : 
     227       21212 :     t[0] = (usage >>  0) & 0xFF;
     228       21212 :     t[1] = (usage >>  8) & 0xFF;
     229       21212 :     t[2] = (usage >> 16) & 0xFF;
     230       21212 :     t[3] = (usage >> 24) & 0xFF;
     231             : 
     232       21212 :     k1_c.checksum.length = sizeof(k1_c_data);
     233       21212 :     k1_c.checksum.data   = k1_c_data;
     234             : 
     235       21212 :     ret = _krb5_internal_hmac(context, NULL, c, t, sizeof(t), 0, key, &k1_c);
     236       21212 :     if (ret)
     237           0 :         krb5_abortx(context, "hmac failed");
     238             : 
     239       21212 :     memcpy (k2_c_data, k1_c_data, sizeof(k1_c_data));
     240             : 
     241       21212 :     k2_c.checksum.length = sizeof(k2_c_data);
     242       21212 :     k2_c.checksum.data   = k2_c_data;
     243             : 
     244       21212 :     ke.key = &kb;
     245       21212 :     kb.keyvalue = k1_c.checksum;
     246             : 
     247       21212 :     k3_c.checksum.length = sizeof(k3_c_data);
     248       21212 :     k3_c.checksum.data   = k3_c_data;
     249             : 
     250       21212 :     ret = _krb5_internal_hmac(context, NULL, c, cdata, 16, 0, &ke, &k3_c);
     251       21212 :     if (ret)
     252           0 :         krb5_abortx(context, "hmac failed");
     253             : 
     254       21212 :     EVP_CIPHER_CTX_init(&ctx);
     255       21212 :     EVP_CipherInit_ex(&ctx, EVP_rc4(), NULL, k3_c.checksum.data, NULL, 0);
     256       21212 :     EVP_Cipher(&ctx, cdata + 16, cdata + 16, len - 16);
     257       21212 :     EVP_CIPHER_CTX_cleanup(&ctx);
     258             : 
     259       21212 :     ke.key = &kb;
     260       21212 :     kb.keyvalue = k2_c.checksum;
     261             : 
     262       21212 :     cksum.checksum.length = 16;
     263       21212 :     cksum.checksum.data   = cksum_data;
     264             : 
     265       21212 :     ret = _krb5_internal_hmac(context, NULL, c, cdata + 16, len - 16, 0, &ke, &cksum);
     266       21212 :     if (ret)
     267           0 :         krb5_abortx(context, "hmac failed");
     268             : 
     269       21212 :     memset_s(k1_c_data, sizeof(k1_c_data), 0, sizeof(k1_c_data));
     270       21212 :     memset_s(k2_c_data, sizeof(k2_c_data), 0, sizeof(k2_c_data));
     271       21212 :     memset_s(k3_c_data, sizeof(k3_c_data), 0, sizeof(k3_c_data));
     272             : 
     273       21212 :     if (ct_memcmp (cksum.checksum.data, data, 16) != 0) {
     274          17 :         krb5_clear_error_message (context);
     275          17 :         return KRB5KRB_AP_ERR_BAD_INTEGRITY;
     276             :     } else {
     277       21177 :         return 0;
     278             :     }
     279             : }
     280             : 
     281             : /*
     282             :  * convert the usage numbers used in
     283             :  * draft-ietf-cat-kerb-key-derivation-00.txt to the ones in
     284             :  * draft-brezak-win2k-krb-rc4-hmac-04.txt
     285             :  */
     286             : 
     287             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
     288      217249 : _krb5_usage2arcfour(krb5_context context, unsigned *usage)
     289             : {
     290      217249 :     switch (*usage) {
     291        1836 :     case KRB5_KU_AS_REP_ENC_PART : /* 3 */
     292        1836 :         *usage = 8;
     293        1836 :         return 0;
     294      132298 :     case KRB5_KU_USAGE_SEAL :  /* 22 */
     295      132298 :         *usage = 13;
     296      132298 :         return 0;
     297       30342 :     case KRB5_KU_USAGE_SIGN : /* 23 */
     298       30342 :         *usage = 15;
     299       30342 :         return 0;
     300           0 :     case KRB5_KU_USAGE_SEQ: /* 24 */
     301           0 :         *usage = 0;
     302           0 :         return 0;
     303       52711 :     default :
     304       52711 :         return 0;
     305             :     }
     306             : }
     307             : 
     308             : static krb5_error_code
     309       48115 : ARCFOUR_encrypt(krb5_context context,
     310             :                 struct _krb5_key_data *key,
     311             :                 void *data,
     312             :                 size_t len,
     313             :                 krb5_boolean encryptp,
     314             :                 int usage,
     315             :                 void *ivec)
     316             : {
     317          36 :     krb5_error_code ret;
     318       48115 :     unsigned keyusage = usage;
     319             : 
     320       48115 :     if((ret = _krb5_usage2arcfour (context, &keyusage)) != 0)
     321           0 :         return ret;
     322             : 
     323       48115 :     if (encryptp)
     324       26903 :         return ARCFOUR_subencrypt (context, key, data, len, keyusage, ivec);
     325             :     else
     326       21212 :         return ARCFOUR_subdecrypt (context, key, data, len, keyusage, ivec);
     327             : }
     328             : 
     329             : static krb5_error_code
     330        7804 : ARCFOUR_prf(krb5_context context,
     331             :             krb5_crypto crypto,
     332             :             const krb5_data *in,
     333             :             krb5_data *out)
     334             : {
     335        7804 :     struct _krb5_checksum_type *c = _krb5_find_checksum(CKSUMTYPE_SHA1);
     336           0 :     krb5_error_code ret;
     337           0 :     Checksum res;
     338             : 
     339        7804 :     ret = krb5_data_alloc(out, c->checksumsize);
     340        7804 :     if (ret)
     341           0 :         return ret;
     342             : 
     343        7804 :     res.checksum.data = out->data;
     344        7804 :     res.checksum.length = out->length;
     345             : 
     346        7804 :     ret = _krb5_internal_hmac(context, crypto, c, in->data, in->length, 0, &crypto->key, &res);
     347        7804 :     if (ret)
     348           0 :         krb5_data_free(out);
     349        7804 :     return 0;
     350             : }
     351             : 
     352             : 
     353             : struct _krb5_encryption_type _krb5_enctype_arcfour_hmac_md5 = {
     354             :     ETYPE_ARCFOUR_HMAC_MD5,
     355             :     "arcfour-hmac-md5",
     356             :     "rc4-hmac",
     357             :     1,
     358             :     1,
     359             :     8,
     360             :     &keytype_arcfour,
     361             :     &_krb5_checksum_hmac_md5,
     362             :     &_krb5_checksum_hmac_md5,
     363             :     F_SPECIAL | F_WEAK | F_OLD,
     364             :     ARCFOUR_encrypt,
     365             :     NULL,
     366             :     0,
     367             :     ARCFOUR_prf
     368             : };

Generated by: LCOV version 1.14