(root)/
libxcrypt-4.4.36/
lib/
alg-hmac-sha1.c
       1  /*
       2   * Copyright (c) 2017, Björn Esser <besser82@fedoraproject.org>
       3   * All rights reserved.
       4   *
       5   * Redistribution and use in source and binary forms, with or without
       6   * modification, are permitted provided that the following conditions
       7   * are met:
       8   *
       9   * 1. Redistributions of source code must retain the above copyright
      10   *    notice, this list of conditions and the following disclaimer.
      11   *
      12   * 2. Redistributions in binary form must reproduce the above copyright
      13   *    notice, this list of conditions and the following disclaimer in the
      14   *    documentation and/or other materials provided with the distribution.
      15   *
      16   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
      17   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
      18   * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
      19   * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
      20   * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
      21   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
      22   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
      23   * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
      24   * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
      25   * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
      26   * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
      27   */
      28  
      29  /*
      30   * Implement HMAC as described in RFC 2104
      31   *
      32   */
      33  
      34  #include "crypt-port.h"
      35  #include "alg-hmac-sha1.h"
      36  #include "alg-sha1.h"
      37  
      38  #include <stdlib.h>
      39  
      40  #if INCLUDE_sha1crypt
      41  
      42  /* Don't change these */
      43  #define HMAC_IPAD 0x36
      44  #define HMAC_OPAD 0x5c
      45  
      46  /* Nor this */
      47  #ifndef HMAC_BLOCKSZ
      48  # define HMAC_BLOCKSZ 64
      49  # define HASH_LENGTH  20
      50  #endif
      51  
      52  /*
      53   * The logic here is lifted straight from RFC 2104 except that
      54   * rather than filling the pads with 0, copying in the key and then
      55   * XOR with the pad byte, we just fill with the pad byte and
      56   * XOR with the key.
      57   */
      58  void
      59  hmac_sha1_process_data (const uint8_t *text, size_t text_len,
      60                          const uint8_t *key, size_t key_len,
      61                          void *resbuf)
      62  {
      63    struct sha1_ctx ctx;
      64    /* Inner padding key XOR'd with ipad */
      65    uint8_t k_ipad[HMAC_BLOCKSZ];
      66    /* Outer padding key XOR'd with opad */
      67    uint8_t k_opad[HMAC_BLOCKSZ];
      68    /* HASH(key) if needed */
      69    unsigned char tk[HASH_LENGTH];
      70    size_t i;
      71  
      72    /*
      73     * If key is longer than HMAC_BLOCKSZ bytes
      74     * reset it to key=HASH(key)
      75     */
      76    if (key_len > HMAC_BLOCKSZ)
      77      {
      78        struct sha1_ctx tctx;
      79  
      80        sha1_init_ctx (&tctx);
      81        sha1_process_bytes (key, &tctx, key_len);
      82        sha1_finish_ctx(&tctx, &tk);
      83  
      84        key = tk;
      85        key_len = HASH_LENGTH;
      86      }
      87  
      88    /*
      89     * The HMAC_ transform looks like:
      90     *
      91     * HASH(K XOR opad, HASH(K XOR ipad, text))
      92     *
      93     * where K is an n byte key
      94     * ipad is the byte HMAC_IPAD repeated HMAC_BLOCKSZ times
      95     * opad is the byte HMAC_OPAD repeated HMAC_BLOCKSZ times
      96     * and text is the data being protected
      97     */
      98  
      99    /*
     100     * Fill the pads and XOR in the key
     101     */
     102    memset (k_ipad, HMAC_IPAD, sizeof k_ipad);
     103    memset (k_opad, HMAC_OPAD, sizeof k_opad);
     104    for (i = 0; i < key_len; i++)
     105      {
     106        k_ipad[i] ^= key[i];
     107        k_opad[i] ^= key[i];
     108      }
     109  
     110    /* Clean the stack. */
     111    explicit_bzero (tk, HASH_LENGTH);
     112  
     113    /*
     114     * Perform inner HASH.
     115     * Start with inner pad,
     116     * then the text.
     117     */
     118    sha1_init_ctx (&ctx);
     119    sha1_process_bytes (k_ipad, &ctx, HMAC_BLOCKSZ);
     120    sha1_process_bytes (text, &ctx, text_len);
     121    sha1_finish_ctx(&ctx, resbuf);
     122  
     123    /* Clean the stack. */
     124    explicit_bzero (k_ipad, HMAC_BLOCKSZ);
     125  
     126    /*
     127     * Perform outer HASH.
     128     * Start with the outer pad,
     129     * then the result of the inner hash.
     130     */
     131    sha1_init_ctx (&ctx);
     132    sha1_process_bytes (k_opad, &ctx, HMAC_BLOCKSZ);
     133    sha1_process_bytes (resbuf, &ctx, HASH_LENGTH);
     134    sha1_finish_ctx(&ctx, resbuf);
     135  
     136    /* Clean the stack. */
     137    explicit_bzero (k_opad, HMAC_BLOCKSZ);
     138  }
     139  
     140  #endif