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  #include "crypt-port.h"
      30  #include "alg-sha1.h"
      31  #include "alg-hmac-sha1.h"
      32  
      33  #include <stdio.h>
      34  #include <stdlib.h>
      35  
      36  #if INCLUDE_sha1crypt
      37  
      38  #define HASH_LENGTH 20
      39  
      40  static char *
      41  bin_to_char (char *buf, size_t bufsz, const char *data, size_t nbytes)
      42  {
      43    size_t i;
      44  
      45    buf[0] = '\0';
      46    if (bufsz <= (nbytes * 2))
      47      return NULL;
      48    for (i = 0; i < nbytes; i++)
      49      {
      50        (void)sprintf (&buf[i*2], "%02x", (unsigned char)data[i]);
      51      }
      52    return buf;
      53  }
      54  
      55  static int
      56  char_to_bin (char *buf, size_t bufsz, const char *data, size_t nbytes)
      57  {
      58    size_t i;
      59    uint32_t c;
      60  
      61    if (nbytes < 1)
      62      nbytes = strlen (data);
      63    nbytes /= 2;
      64    if (bufsz <= nbytes)
      65      return 0;
      66    for (i = 0; i < nbytes; i++)
      67      {
      68        if (sscanf (&data[i*2], "%02x", &c) < 1)
      69          break;
      70        buf[i] = (char)(c & 0xff);
      71      }
      72    buf[i] = 0;
      73    return (int)i;
      74  }
      75  
      76  /*
      77   * If a test key or data starts with 0x we'll convert to binary.
      78   */
      79  #define X2B(v, b) do { \
      80      if (memcmp (v, "0x", 2) == 0) { \
      81          v += 2; \
      82          char_to_bin (b, sizeof(b), v, strlen(v)); \
      83          v = b; \
      84      } \
      85  } while (0)
      86  
      87  /*
      88   * Run some of the known answer tests from RFC 2202.
      89   */
      90  int
      91  main (void)
      92  {
      93    struct test_s
      94    {
      95      const char *key;
      96      const char *data;
      97      const char *expect;
      98      const size_t data_size;
      99    } tests[] =
     100    {
     101      {
     102        "0x0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b",
     103        "Hi There",
     104        "0xb617318655057264e28bc0b6fb378c8ef146be00",
     105        8,
     106      },
     107      {
     108        "Jefe",
     109        "what do ya want for nothing?",
     110        "0xeffcdf6ae5eb2fa2d27416d5f184df9c259a7c79",
     111        28,
     112      },
     113      {
     114        "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
     115        "0xdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd",
     116        "0x125d7342b9ac11cd91a39af48aa17b4f63f175d3",
     117        50,
     118      },
     119      {
     120        "0x0102030405060708090a0b0c0d0e0f10111213141516171819",
     121        "0xcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd",
     122        "0x4c9007f4026250c6bc8414f9bf50c86c2d7235da",
     123        50,
     124      },
     125      {
     126        "0x0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c",
     127        "Test With Truncation",
     128        "0x4c1a03424b55e07fe7f27be1d58bb9324a9a5a04",
     129        20,
     130      },
     131      {
     132        "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
     133        "Test Using Larger Than Block-Size Key - Hash Key First",
     134        "0xaa4ae5e15272d00e95705637ce8a3b55ed402112",
     135        54,
     136      },
     137      {
     138        "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
     139        "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data",
     140        "0xe8e99d0f45237d786d6bbaa7965c7808bbff1a91",
     141        73,
     142      },
     143      {
     144        0, 0, 0, 0,
     145      },
     146    };
     147    struct test_s *test = tests;
     148    char digest[HASH_LENGTH];
     149    char kbuf[BUFSIZ];
     150    char dbuf[BUFSIZ];
     151    int n = 0;
     152  
     153    for (test = tests; test->key; test++)
     154      {
     155        X2B(test->key, kbuf);
     156        X2B(test->data, dbuf);
     157        hmac_sha1_process_data ((const uint8_t *)test->data, test->data_size,
     158                                (const uint8_t *)test->key, strlen(test->key), digest);
     159        strncpy (dbuf, "0x", BUFSIZ);
     160        bin_to_char (&dbuf[2], (sizeof dbuf) - 2, digest, HASH_LENGTH);
     161  
     162        if (strcmp (dbuf, test->expect) != 0)
     163          {
     164            n = 1;
     165            fputs ("\nkey=", stdout);
     166            fputs (test->key, stdout);
     167            fputs (", data=", stdout);
     168            fputs (test->data, stdout);
     169            fputs (",\nresult=", stdout);
     170            fputs (dbuf, stdout);
     171            fputs (": ", stdout);
     172            fputs (test->expect, stdout);
     173            fputs ("\n", stdout);
     174          }
     175      }
     176    return n;
     177  }
     178  
     179  #else
     180  
     181  int
     182  main (void)
     183  {
     184    return 77; /* UNSUPPORTED */
     185  }
     186  
     187  #endif