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 v4-17-test 1498b464 Lines: 131 147 89.1 %
Date: 2024-06-13 04:01:37 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      164378 : _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             :     EVP_MD_CTX *m;
      68      164378 :     struct _krb5_checksum_type *c = _krb5_find_checksum (CKSUMTYPE_RSA_MD5);
      69      164378 :     const char signature[] = "signaturekey";
      70             :     Checksum ksign_c;
      71             :     struct _krb5_key_data ksign;
      72             :     krb5_keyblock kb;
      73             :     unsigned char t[4];
      74             :     unsigned char tmp[16];
      75             :     unsigned char ksign_c_data[16];
      76             :     krb5_error_code ret;
      77             :     int i;
      78             : 
      79      164378 :     if (crypto != NULL) {
      80      141812 :         if (crypto->mdctx == NULL)
      81      141702 :             crypto->mdctx = EVP_MD_CTX_create();
      82      141812 :         if (crypto->mdctx == NULL)
      83           0 :             return krb5_enomem(context);
      84      141812 :         m = crypto->mdctx;
      85             :     } else
      86       22566 :         m = EVP_MD_CTX_create();
      87             : 
      88      164378 :     ksign_c.checksum.length = sizeof(ksign_c_data);
      89      164378 :     ksign_c.checksum.data   = ksign_c_data;
      90      164378 :     ret = _krb5_internal_hmac(context, crypto, c, signature, sizeof(signature),
      91             :                               0, key, &ksign_c);
      92      164378 :     if (ret)
      93           0 :         goto out;
      94             : 
      95      164378 :     ksign.key = &kb;
      96      164378 :     kb.keyvalue = ksign_c.checksum;
      97      164378 :     EVP_DigestInit_ex(m, EVP_md5(), NULL);
      98      164378 :     t[0] = (usage >>  0) & 0xFF;
      99      164378 :     t[1] = (usage >>  8) & 0xFF;
     100      164378 :     t[2] = (usage >> 16) & 0xFF;
     101      164378 :     t[3] = (usage >> 24) & 0xFF;
     102      164378 :     EVP_DigestUpdate(m, t, 4);
     103      328756 :     for (i = 0; i < niov; i++) {
     104      164378 :         if (_krb5_crypto_iov_should_sign(&iov[i]))
     105      164378 :             EVP_DigestUpdate(m, iov[i].data.data, iov[i].data.length);
     106             :     }
     107      164378 :     EVP_DigestFinal_ex (m, tmp, NULL);
     108             : 
     109      164378 :     ret = _krb5_internal_hmac(context, crypto, c, tmp, sizeof(tmp), 0, &ksign, result);
     110      164378 : out:
     111      164378 :     if (crypto == NULL)
     112       22566 :         EVP_MD_CTX_destroy(m);
     113             : 
     114      164378 :     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       24544 : 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             :     EVP_CIPHER_CTX ctx;
     142       24544 :     struct _krb5_checksum_type *c = _krb5_find_checksum (CKSUMTYPE_RSA_MD5);
     143             :     Checksum k1_c, k2_c, k3_c, cksum;
     144             :     struct _krb5_key_data ke;
     145             :     krb5_keyblock kb;
     146             :     unsigned char t[4];
     147       24544 :     unsigned char *cdata = data;
     148             :     unsigned char k1_c_data[16], k2_c_data[16], k3_c_data[16];
     149             :     krb5_error_code ret;
     150             : 
     151       24544 :     if (len < 16) {
     152           0 :             return KRB5KRB_AP_ERR_INAPP_CKSUM;
     153             :     }
     154             : 
     155       24544 :     t[0] = (usage >>  0) & 0xFF;
     156       24544 :     t[1] = (usage >>  8) & 0xFF;
     157       24544 :     t[2] = (usage >> 16) & 0xFF;
     158       24544 :     t[3] = (usage >> 24) & 0xFF;
     159             : 
     160       24544 :     k1_c.checksum.length = sizeof(k1_c_data);
     161       24544 :     k1_c.checksum.data   = k1_c_data;
     162             : 
     163       24544 :     ret = _krb5_internal_hmac(context, NULL, c, t, sizeof(t), 0, key, &k1_c);
     164       24544 :     if (ret)
     165           0 :         krb5_abortx(context, "hmac failed");
     166             : 
     167       24544 :     memcpy (k2_c_data, k1_c_data, sizeof(k1_c_data));
     168             : 
     169       24544 :     k2_c.checksum.length = sizeof(k2_c_data);
     170       24544 :     k2_c.checksum.data   = k2_c_data;
     171             : 
     172       24544 :     ke.key = &kb;
     173       24544 :     kb.keyvalue = k2_c.checksum;
     174             : 
     175       24544 :     cksum.checksum.length = 16;
     176       24544 :     cksum.checksum.data   = data;
     177             : 
     178       24544 :     ret = _krb5_internal_hmac(context, NULL, c, cdata + 16, len - 16, 0, &ke, &cksum);
     179       24544 :     if (ret)
     180           0 :         krb5_abortx(context, "hmac failed");
     181             : 
     182       24544 :     ke.key = &kb;
     183       24544 :     kb.keyvalue = k1_c.checksum;
     184             : 
     185       24544 :     k3_c.checksum.length = sizeof(k3_c_data);
     186       24544 :     k3_c.checksum.data   = k3_c_data;
     187             : 
     188       24544 :     ret = _krb5_internal_hmac(context, NULL, c, data, 16, 0, &ke, &k3_c);
     189       24544 :     if (ret)
     190           0 :         krb5_abortx(context, "hmac failed");
     191             : 
     192       24544 :     EVP_CIPHER_CTX_init(&ctx);
     193             : 
     194       24544 :     EVP_CipherInit_ex(&ctx, EVP_rc4(), NULL, k3_c.checksum.data, NULL, 1);
     195       24544 :     EVP_Cipher(&ctx, cdata + 16, cdata + 16, len - 16);
     196       24544 :     EVP_CIPHER_CTX_cleanup(&ctx);
     197             : 
     198       24544 :     memset_s(k1_c_data, sizeof(k1_c_data), 0, sizeof(k1_c_data));
     199       24544 :     memset_s(k2_c_data, sizeof(k2_c_data), 0, sizeof(k2_c_data));
     200       24544 :     memset_s(k3_c_data, sizeof(k3_c_data), 0, sizeof(k3_c_data));
     201       24544 :     return 0;
     202             : }
     203             : 
     204             : static krb5_error_code
     205       20510 : 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             :     EVP_CIPHER_CTX ctx;
     213       20510 :     struct _krb5_checksum_type *c = _krb5_find_checksum (CKSUMTYPE_RSA_MD5);
     214             :     Checksum k1_c, k2_c, k3_c, cksum;
     215             :     struct _krb5_key_data ke;
     216             :     krb5_keyblock kb;
     217             :     unsigned char t[4];
     218       20510 :     unsigned char *cdata = data;
     219             :     unsigned char k1_c_data[16], k2_c_data[16], k3_c_data[16];
     220             :     unsigned char cksum_data[16];
     221             :     krb5_error_code ret;
     222             : 
     223       20510 :     if (len < 16) {
     224           0 :             return KRB5KRB_AP_ERR_INAPP_CKSUM;
     225             :     }
     226             : 
     227       20510 :     t[0] = (usage >>  0) & 0xFF;
     228       20510 :     t[1] = (usage >>  8) & 0xFF;
     229       20510 :     t[2] = (usage >> 16) & 0xFF;
     230       20510 :     t[3] = (usage >> 24) & 0xFF;
     231             : 
     232       20510 :     k1_c.checksum.length = sizeof(k1_c_data);
     233       20510 :     k1_c.checksum.data   = k1_c_data;
     234             : 
     235       20510 :     ret = _krb5_internal_hmac(context, NULL, c, t, sizeof(t), 0, key, &k1_c);
     236       20510 :     if (ret)
     237           0 :         krb5_abortx(context, "hmac failed");
     238             : 
     239       20510 :     memcpy (k2_c_data, k1_c_data, sizeof(k1_c_data));
     240             : 
     241       20510 :     k2_c.checksum.length = sizeof(k2_c_data);
     242       20510 :     k2_c.checksum.data   = k2_c_data;
     243             : 
     244       20510 :     ke.key = &kb;
     245       20510 :     kb.keyvalue = k1_c.checksum;
     246             : 
     247       20510 :     k3_c.checksum.length = sizeof(k3_c_data);
     248       20510 :     k3_c.checksum.data   = k3_c_data;
     249             : 
     250       20510 :     ret = _krb5_internal_hmac(context, NULL, c, cdata, 16, 0, &ke, &k3_c);
     251       20510 :     if (ret)
     252           0 :         krb5_abortx(context, "hmac failed");
     253             : 
     254       20510 :     EVP_CIPHER_CTX_init(&ctx);
     255       20510 :     EVP_CipherInit_ex(&ctx, EVP_rc4(), NULL, k3_c.checksum.data, NULL, 0);
     256       20510 :     EVP_Cipher(&ctx, cdata + 16, cdata + 16, len - 16);
     257       20510 :     EVP_CIPHER_CTX_cleanup(&ctx);
     258             : 
     259       20510 :     ke.key = &kb;
     260       20510 :     kb.keyvalue = k2_c.checksum;
     261             : 
     262       20510 :     cksum.checksum.length = 16;
     263       20510 :     cksum.checksum.data   = cksum_data;
     264             : 
     265       20510 :     ret = _krb5_internal_hmac(context, NULL, c, cdata + 16, len - 16, 0, &ke, &cksum);
     266       20510 :     if (ret)
     267           0 :         krb5_abortx(context, "hmac failed");
     268             : 
     269       20510 :     memset_s(k1_c_data, sizeof(k1_c_data), 0, sizeof(k1_c_data));
     270       20510 :     memset_s(k2_c_data, sizeof(k2_c_data), 0, sizeof(k2_c_data));
     271       20510 :     memset_s(k3_c_data, sizeof(k3_c_data), 0, sizeof(k3_c_data));
     272             : 
     273       20510 :     if (ct_memcmp (cksum.checksum.data, data, 16) != 0) {
     274          16 :         krb5_clear_error_message (context);
     275          16 :         return KRB5KRB_AP_ERR_BAD_INTEGRITY;
     276             :     } else {
     277       20494 :         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      186866 : _krb5_usage2arcfour(krb5_context context, unsigned *usage)
     289             : {
     290      186866 :     switch (*usage) {
     291        1727 :     case KRB5_KU_AS_REP_ENC_PART : /* 3 */
     292        1727 :         *usage = 8;
     293        1727 :         return 0;
     294      108248 :     case KRB5_KU_USAGE_SEAL :  /* 22 */
     295      108248 :         *usage = 13;
     296      108248 :         return 0;
     297       27201 :     case KRB5_KU_USAGE_SIGN : /* 23 */
     298       27201 :         *usage = 15;
     299       27201 :         return 0;
     300           0 :     case KRB5_KU_USAGE_SEQ: /* 24 */
     301           0 :         *usage = 0;
     302           0 :         return 0;
     303       49690 :     default :
     304       49690 :         return 0;
     305             :     }
     306             : }
     307             : 
     308             : static krb5_error_code
     309       45054 : 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             :     krb5_error_code ret;
     318       45054 :     unsigned keyusage = usage;
     319             : 
     320       45054 :     if((ret = _krb5_usage2arcfour (context, &keyusage)) != 0)
     321           0 :         return ret;
     322             : 
     323       45054 :     if (encryptp)
     324       24544 :         return ARCFOUR_subencrypt (context, key, data, len, keyusage, ivec);
     325             :     else
     326       20510 :         return ARCFOUR_subdecrypt (context, key, data, len, keyusage, ivec);
     327             : }
     328             : 
     329             : static krb5_error_code
     330        7682 : ARCFOUR_prf(krb5_context context,
     331             :             krb5_crypto crypto,
     332             :             const krb5_data *in,
     333             :             krb5_data *out)
     334             : {
     335        7682 :     struct _krb5_checksum_type *c = _krb5_find_checksum(CKSUMTYPE_SHA1);
     336             :     krb5_error_code ret;
     337             :     Checksum res;
     338             : 
     339        7682 :     ret = krb5_data_alloc(out, c->checksumsize);
     340        7682 :     if (ret)
     341           0 :         return ret;
     342             : 
     343        7682 :     res.checksum.data = out->data;
     344        7682 :     res.checksum.length = out->length;
     345             : 
     346        7682 :     ret = _krb5_internal_hmac(context, crypto, c, in->data, in->length, 0, &crypto->key, &res);
     347        7682 :     if (ret)
     348           0 :         krb5_data_free(out);
     349        7682 :     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.13