LCOV - code coverage report
Current view: top level - port - cpl_sha1.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 117 124 94.4 %
Date: 2024-04-29 01:40:10 Functions: 5 6 83.3 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  CPL - Common Portability Library
       4             :  * Purpose:  Implement SHA1
       5             :  * Author:   Even Rouault, even.rouault at spatialys.com
       6             :  *
       7             :  * SHA1 computation coming from Public Domain code at:
       8             :  * https://github.com/B-Con/crypto-algorithms/blob/master/sha1.c
       9             :  * by Brad Conte (brad AT bradconte.com)
      10             :  *
      11             :  ******************************************************************************
      12             :  * Copyright (c) 2017, Even Rouault <even.rouault at spatialys.com>
      13             :  *
      14             :  * Permission is hereby granted, free of charge, to any person obtaining a
      15             :  * copy of this software and associated documentation files (the "Software"),
      16             :  * to deal in the Software without restriction, including without limitation
      17             :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      18             :  * and/or sell copies of the Software, and to permit persons to whom the
      19             :  * Software is furnished to do so, subject to the following conditions:
      20             :  *
      21             :  * The above copyright notice and this permission notice shall be included
      22             :  * in all copies or substantial portions of the Software.
      23             :  *
      24             :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      25             :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      26             :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      27             :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      28             :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      29             :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      30             :  * DEALINGS IN THE SOFTWARE.
      31             :  ****************************************************************************/
      32             : 
      33             : #include <string.h>
      34             : #include "cpl_sha1.h"
      35             : 
      36             : typedef struct
      37             : {
      38             :     GByte data[64];
      39             :     GUInt32 datalen;
      40             :     GUIntBig bitlen;
      41             :     GUInt32 state[5];
      42             : } CPL_SHA1Context;
      43             : 
      44             : #define ROTLEFT(a, b) ((a << b) | (a >> (32 - b)))
      45             : 
      46             : /************************************************************************/
      47             : /*                         sha1_transform()                             */
      48             : /************************************************************************/
      49             : 
      50             : CPL_NOSANITIZE_UNSIGNED_INT_OVERFLOW
      51         530 : static void sha1_transform(CPL_SHA1Context *ctx, const GByte data[])
      52             : {
      53             :     GUInt32 a, b, c, d, e, i, j, t, m[80];
      54             : 
      55        9010 :     for (i = 0, j = 0; i < 16; ++i, j += 4)
      56        8480 :         m[i] = (data[j] << 24) + (data[j + 1] << 16) + (data[j + 2] << 8) +
      57        8480 :                (data[j + 3]);
      58       34450 :     for (; i < 80; ++i)
      59             :     {
      60       33920 :         m[i] = (m[i - 3] ^ m[i - 8] ^ m[i - 14] ^ m[i - 16]);
      61       33920 :         m[i] = (m[i] << 1) | (m[i] >> 31);
      62             :     }
      63             : 
      64         530 :     a = ctx->state[0];
      65         530 :     b = ctx->state[1];
      66         530 :     c = ctx->state[2];
      67         530 :     d = ctx->state[3];
      68         530 :     e = ctx->state[4];
      69             : 
      70       11130 :     for (i = 0; i < 20; ++i)
      71             :     {
      72       10600 :         t = ROTLEFT(a, 5) + ((b & c) ^ (~b & d)) + e + 0x5a827999U + m[i];
      73       10600 :         e = d;
      74       10600 :         d = c;
      75       10600 :         c = ROTLEFT(b, 30);
      76       10600 :         b = a;
      77       10600 :         a = t;
      78             :     }
      79       11130 :     for (; i < 40; ++i)
      80             :     {
      81       10600 :         t = ROTLEFT(a, 5) + (b ^ c ^ d) + e + 0x6ed9eba1U + m[i];
      82       10600 :         e = d;
      83       10600 :         d = c;
      84       10600 :         c = ROTLEFT(b, 30);
      85       10600 :         b = a;
      86       10600 :         a = t;
      87             :     }
      88       11130 :     for (; i < 60; ++i)
      89             :     {
      90       10600 :         t = ROTLEFT(a, 5) + ((b & c) ^ (b & d) ^ (c & d)) + e + 0x8f1bbcdcU +
      91       10600 :             m[i];
      92       10600 :         e = d;
      93       10600 :         d = c;
      94       10600 :         c = ROTLEFT(b, 30);
      95       10600 :         b = a;
      96       10600 :         a = t;
      97             :     }
      98       11130 :     for (; i < 80; ++i)
      99             :     {
     100       10600 :         t = ROTLEFT(a, 5) + (b ^ c ^ d) + e + 0xca62c1d6U + m[i];
     101       10600 :         e = d;
     102       10600 :         d = c;
     103       10600 :         c = ROTLEFT(b, 30);
     104       10600 :         b = a;
     105       10600 :         a = t;
     106             :     }
     107             : 
     108         530 :     ctx->state[0] += a;
     109         530 :     ctx->state[1] += b;
     110         530 :     ctx->state[2] += c;
     111         530 :     ctx->state[3] += d;
     112         530 :     ctx->state[4] += e;
     113         530 : }
     114             : 
     115             : /************************************************************************/
     116             : /*                           CPL_SHA1Init()                             */
     117             : /************************************************************************/
     118             : 
     119         246 : static void CPL_SHA1Init(CPL_SHA1Context *ctx)
     120             : {
     121         246 :     ctx->datalen = 0;
     122         246 :     ctx->bitlen = 0;
     123         246 :     ctx->state[0] = 0x67452301U;
     124         246 :     ctx->state[1] = 0xEFCDAB89U;
     125         246 :     ctx->state[2] = 0x98BADCFEU;
     126         246 :     ctx->state[3] = 0x10325476U;
     127         246 :     ctx->state[4] = 0xc3d2e1f0U;
     128         246 : }
     129             : 
     130             : /************************************************************************/
     131             : /*                          CPL_SHA1Update()                            */
     132             : /************************************************************************/
     133             : 
     134         492 : static void CPL_SHA1Update(CPL_SHA1Context *ctx, const GByte data[], size_t len)
     135             : {
     136             :     size_t i;
     137             : 
     138       25672 :     for (i = 0; i < len; ++i)
     139             :     {
     140       25180 :         ctx->data[ctx->datalen] = data[i];
     141       25180 :         ctx->datalen++;
     142       25180 :         if (ctx->datalen == 64)
     143             :         {
     144         278 :             sha1_transform(ctx, ctx->data);
     145         278 :             ctx->bitlen += 512;
     146         278 :             ctx->datalen = 0;
     147             :         }
     148             :     }
     149         492 : }
     150             : 
     151             : /************************************************************************/
     152             : /*                           CPL_SHA1Final()                            */
     153             : /************************************************************************/
     154             : 
     155         246 : static void CPL_SHA1Final(CPL_SHA1Context *ctx, GByte hash[CPL_SHA1_HASH_SIZE])
     156             : {
     157             :     GUInt32 i;
     158             : 
     159         246 :     i = ctx->datalen;
     160             : 
     161             :     // Pad whatever data is left in the buffer.
     162         246 :     if (ctx->datalen < 56)
     163             :     {
     164         240 :         ctx->data[i++] = 0x80;
     165        6409 :         while (i < 56)
     166        6169 :             ctx->data[i++] = 0x00;
     167             :     }
     168             :     else
     169             :     {
     170           6 :         ctx->data[i++] = 0x80;
     171          27 :         while (i < 64)
     172          21 :             ctx->data[i++] = 0x00;
     173           6 :         sha1_transform(ctx, ctx->data);
     174           6 :         memset(ctx->data, 0, 56);
     175             :     }
     176             : 
     177             :     // Append to the padding the total message's length in bits and transform.
     178         246 :     ctx->bitlen += ctx->datalen * 8;
     179         246 :     ctx->data[63] = static_cast<GByte>((ctx->bitlen) & 0xFFU);
     180         246 :     ctx->data[62] = static_cast<GByte>((ctx->bitlen >> 8) & 0xFFU);
     181         246 :     ctx->data[61] = static_cast<GByte>((ctx->bitlen >> 16) & 0xFFU);
     182         246 :     ctx->data[60] = static_cast<GByte>((ctx->bitlen >> 24) & 0xFFU);
     183         246 :     ctx->data[59] = static_cast<GByte>((ctx->bitlen >> 32) & 0xFFU);
     184         246 :     ctx->data[58] = static_cast<GByte>((ctx->bitlen >> 40) & 0xFFU);
     185         246 :     ctx->data[57] = static_cast<GByte>((ctx->bitlen >> 48) & 0xFFU);
     186         246 :     ctx->data[56] = static_cast<GByte>((ctx->bitlen >> 56) & 0xFFU);
     187         246 :     sha1_transform(ctx, ctx->data);
     188             : 
     189             :     // Since this implementation uses little endian byte ordering and MD uses
     190             :     // big endian, reverse all the bytes when copying the final state to the
     191             :     // output hash.
     192        1230 :     for (i = 0; i < 4; ++i)
     193             :     {
     194         984 :         hash[i] =
     195         984 :             static_cast<GByte>((ctx->state[0] >> (24 - i * 8)) & 0x000000ffU);
     196         984 :         hash[i + 4] =
     197         984 :             static_cast<GByte>((ctx->state[1] >> (24 - i * 8)) & 0x000000ffU);
     198         984 :         hash[i + 8] =
     199         984 :             static_cast<GByte>((ctx->state[2] >> (24 - i * 8)) & 0x000000ffU);
     200         984 :         hash[i + 12] =
     201         984 :             static_cast<GByte>((ctx->state[3] >> (24 - i * 8)) & 0x000000ffU);
     202         984 :         hash[i + 16] =
     203         984 :             static_cast<GByte>((ctx->state[4] >> (24 - i * 8)) & 0x000000ffU);
     204             :     }
     205         246 : }
     206             : 
     207             : /************************************************************************/
     208             : /*                              CPL_SHA1()                              */
     209             : /************************************************************************/
     210             : 
     211           0 : static void CPL_SHA1(const void *data, size_t len,
     212             :                      GByte hash[CPL_SHA1_HASH_SIZE])
     213             : {
     214             :     CPL_SHA1Context sSHA1Ctxt;
     215           0 :     CPL_SHA1Init(&sSHA1Ctxt);
     216           0 :     CPL_SHA1Update(&sSHA1Ctxt, static_cast<const GByte *>(data), len);
     217           0 :     CPL_SHA1Final(&sSHA1Ctxt, hash);
     218           0 :     memset(&sSHA1Ctxt, 0, sizeof(sSHA1Ctxt));
     219           0 : }
     220             : 
     221             : /************************************************************************/
     222             : /*                           CPL_HMAC_SHA1()                            */
     223             : /************************************************************************/
     224             : 
     225             : #define CPL_HMAC_SHA1_BLOCKSIZE 64U
     226             : 
     227             : // See
     228             : // https://en.wikipedia.org/wiki/Hash-based_message_authentication_code#Implementation
     229         123 : void CPL_HMAC_SHA1(const void *pKey, size_t nKeyLen, const void *pabyMessage,
     230             :                    size_t nMessageLen, GByte abyDigest[CPL_SHA1_HASH_SIZE])
     231             : {
     232         123 :     GByte abyPad[CPL_HMAC_SHA1_BLOCKSIZE] = {};
     233         123 :     if (nKeyLen > CPL_HMAC_SHA1_BLOCKSIZE)
     234             :     {
     235           0 :         CPL_SHA1(pKey, nKeyLen, abyPad);
     236             :     }
     237             :     else
     238             :     {
     239         123 :         memcpy(abyPad, pKey, nKeyLen);
     240             :     }
     241             : 
     242             :     // Compute ipad.
     243        7995 :     for (size_t i = 0; i < CPL_HMAC_SHA1_BLOCKSIZE; i++)
     244        7872 :         abyPad[i] = 0x36 ^ abyPad[i];
     245             : 
     246             :     CPL_SHA1Context sSHA1Ctxt;
     247         123 :     CPL_SHA1Init(&sSHA1Ctxt);
     248         123 :     CPL_SHA1Update(&sSHA1Ctxt, abyPad, CPL_HMAC_SHA1_BLOCKSIZE);
     249         123 :     CPL_SHA1Update(&sSHA1Ctxt, static_cast<const GByte *>(pabyMessage),
     250             :                    nMessageLen);
     251         123 :     CPL_SHA1Final(&sSHA1Ctxt, abyDigest);
     252             : 
     253             :     // Compute opad.
     254        7995 :     for (size_t i = 0; i < CPL_HMAC_SHA1_BLOCKSIZE; i++)
     255        7872 :         abyPad[i] = (0x36 ^ 0x5C) ^ abyPad[i];
     256             : 
     257         123 :     CPL_SHA1Init(&sSHA1Ctxt);
     258         123 :     CPL_SHA1Update(&sSHA1Ctxt, abyPad, CPL_HMAC_SHA1_BLOCKSIZE);
     259         123 :     CPL_SHA1Update(&sSHA1Ctxt, abyDigest, CPL_SHA1_HASH_SIZE);
     260         123 :     CPL_SHA1Final(&sSHA1Ctxt, abyDigest);
     261             : 
     262         123 :     memset(&sSHA1Ctxt, 0, sizeof(sSHA1Ctxt));
     263         123 :     memset(abyPad, 0, CPL_HMAC_SHA1_BLOCKSIZE);
     264         123 : }

Generated by: LCOV version 1.14