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-11-21 22:18:42 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             :  * SPDX-License-Identifier: MIT
      15             :  ****************************************************************************/
      16             : 
      17             : #include <string.h>
      18             : #include "cpl_sha1.h"
      19             : 
      20             : typedef struct
      21             : {
      22             :     GByte data[64];
      23             :     GUInt32 datalen;
      24             :     GUIntBig bitlen;
      25             :     GUInt32 state[5];
      26             : } CPL_SHA1Context;
      27             : 
      28             : #define ROTLEFT(a, b) ((a << b) | (a >> (32 - b)))
      29             : 
      30             : /************************************************************************/
      31             : /*                         sha1_transform()                             */
      32             : /************************************************************************/
      33             : 
      34             : CPL_NOSANITIZE_UNSIGNED_INT_OVERFLOW
      35         435 : static void sha1_transform(CPL_SHA1Context *ctx, const GByte data[])
      36             : {
      37             :     GUInt32 a, b, c, d, e, i, j, t, m[80];
      38             : 
      39        7395 :     for (i = 0, j = 0; i < 16; ++i, j += 4)
      40        6960 :         m[i] = (data[j] << 24) + (data[j + 1] << 16) + (data[j + 2] << 8) +
      41        6960 :                (data[j + 3]);
      42       28275 :     for (; i < 80; ++i)
      43             :     {
      44       27840 :         m[i] = (m[i - 3] ^ m[i - 8] ^ m[i - 14] ^ m[i - 16]);
      45       27840 :         m[i] = (m[i] << 1) | (m[i] >> 31);
      46             :     }
      47             : 
      48         435 :     a = ctx->state[0];
      49         435 :     b = ctx->state[1];
      50         435 :     c = ctx->state[2];
      51         435 :     d = ctx->state[3];
      52         435 :     e = ctx->state[4];
      53             : 
      54        9135 :     for (i = 0; i < 20; ++i)
      55             :     {
      56        8700 :         t = ROTLEFT(a, 5) + ((b & c) ^ (~b & d)) + e + 0x5a827999U + m[i];
      57        8700 :         e = d;
      58        8700 :         d = c;
      59        8700 :         c = ROTLEFT(b, 30);
      60        8700 :         b = a;
      61        8700 :         a = t;
      62             :     }
      63        9135 :     for (; i < 40; ++i)
      64             :     {
      65        8700 :         t = ROTLEFT(a, 5) + (b ^ c ^ d) + e + 0x6ed9eba1U + m[i];
      66        8700 :         e = d;
      67        8700 :         d = c;
      68        8700 :         c = ROTLEFT(b, 30);
      69        8700 :         b = a;
      70        8700 :         a = t;
      71             :     }
      72        9135 :     for (; i < 60; ++i)
      73             :     {
      74        8700 :         t = ROTLEFT(a, 5) + ((b & c) ^ (b & d) ^ (c & d)) + e + 0x8f1bbcdcU +
      75        8700 :             m[i];
      76        8700 :         e = d;
      77        8700 :         d = c;
      78        8700 :         c = ROTLEFT(b, 30);
      79        8700 :         b = a;
      80        8700 :         a = t;
      81             :     }
      82        9135 :     for (; i < 80; ++i)
      83             :     {
      84        8700 :         t = ROTLEFT(a, 5) + (b ^ c ^ d) + e + 0xca62c1d6U + m[i];
      85        8700 :         e = d;
      86        8700 :         d = c;
      87        8700 :         c = ROTLEFT(b, 30);
      88        8700 :         b = a;
      89        8700 :         a = t;
      90             :     }
      91             : 
      92         435 :     ctx->state[0] += a;
      93         435 :     ctx->state[1] += b;
      94         435 :     ctx->state[2] += c;
      95         435 :     ctx->state[3] += d;
      96         435 :     ctx->state[4] += e;
      97         435 : }
      98             : 
      99             : /************************************************************************/
     100             : /*                           CPL_SHA1Init()                             */
     101             : /************************************************************************/
     102             : 
     103         208 : static void CPL_SHA1Init(CPL_SHA1Context *ctx)
     104             : {
     105         208 :     ctx->datalen = 0;
     106         208 :     ctx->bitlen = 0;
     107         208 :     ctx->state[0] = 0x67452301U;
     108         208 :     ctx->state[1] = 0xEFCDAB89U;
     109         208 :     ctx->state[2] = 0x98BADCFEU;
     110         208 :     ctx->state[3] = 0x10325476U;
     111         208 :     ctx->state[4] = 0xc3d2e1f0U;
     112         208 : }
     113             : 
     114             : /************************************************************************/
     115             : /*                          CPL_SHA1Update()                            */
     116             : /************************************************************************/
     117             : 
     118         416 : static void CPL_SHA1Update(CPL_SHA1Context *ctx, const GByte data[], size_t len)
     119             : {
     120             :     size_t i;
     121             : 
     122       21106 :     for (i = 0; i < len; ++i)
     123             :     {
     124       20690 :         ctx->data[ctx->datalen] = data[i];
     125       20690 :         ctx->datalen++;
     126       20690 :         if (ctx->datalen == 64)
     127             :         {
     128         222 :             sha1_transform(ctx, ctx->data);
     129         222 :             ctx->bitlen += 512;
     130         222 :             ctx->datalen = 0;
     131             :         }
     132             :     }
     133         416 : }
     134             : 
     135             : /************************************************************************/
     136             : /*                           CPL_SHA1Final()                            */
     137             : /************************************************************************/
     138             : 
     139         208 : static void CPL_SHA1Final(CPL_SHA1Context *ctx, GByte hash[CPL_SHA1_HASH_SIZE])
     140             : {
     141             :     GUInt32 i;
     142             : 
     143         208 :     i = ctx->datalen;
     144             : 
     145             :     // Pad whatever data is left in the buffer.
     146         208 :     if (ctx->datalen < 56)
     147             :     {
     148         203 :         ctx->data[i++] = 0x80;
     149        5183 :         while (i < 56)
     150        4980 :             ctx->data[i++] = 0x00;
     151             :     }
     152             :     else
     153             :     {
     154           5 :         ctx->data[i++] = 0x80;
     155          23 :         while (i < 64)
     156          18 :             ctx->data[i++] = 0x00;
     157           5 :         sha1_transform(ctx, ctx->data);
     158           5 :         memset(ctx->data, 0, 56);
     159             :     }
     160             : 
     161             :     // Append to the padding the total message's length in bits and transform.
     162         208 :     ctx->bitlen += ctx->datalen * 8;
     163         208 :     ctx->data[63] = static_cast<GByte>((ctx->bitlen) & 0xFFU);
     164         208 :     ctx->data[62] = static_cast<GByte>((ctx->bitlen >> 8) & 0xFFU);
     165         208 :     ctx->data[61] = static_cast<GByte>((ctx->bitlen >> 16) & 0xFFU);
     166         208 :     ctx->data[60] = static_cast<GByte>((ctx->bitlen >> 24) & 0xFFU);
     167         208 :     ctx->data[59] = static_cast<GByte>((ctx->bitlen >> 32) & 0xFFU);
     168         208 :     ctx->data[58] = static_cast<GByte>((ctx->bitlen >> 40) & 0xFFU);
     169         208 :     ctx->data[57] = static_cast<GByte>((ctx->bitlen >> 48) & 0xFFU);
     170         208 :     ctx->data[56] = static_cast<GByte>((ctx->bitlen >> 56) & 0xFFU);
     171         208 :     sha1_transform(ctx, ctx->data);
     172             : 
     173             :     // Since this implementation uses little endian byte ordering and MD uses
     174             :     // big endian, reverse all the bytes when copying the final state to the
     175             :     // output hash.
     176        1040 :     for (i = 0; i < 4; ++i)
     177             :     {
     178         832 :         hash[i] =
     179         832 :             static_cast<GByte>((ctx->state[0] >> (24 - i * 8)) & 0x000000ffU);
     180         832 :         hash[i + 4] =
     181         832 :             static_cast<GByte>((ctx->state[1] >> (24 - i * 8)) & 0x000000ffU);
     182         832 :         hash[i + 8] =
     183         832 :             static_cast<GByte>((ctx->state[2] >> (24 - i * 8)) & 0x000000ffU);
     184         832 :         hash[i + 12] =
     185         832 :             static_cast<GByte>((ctx->state[3] >> (24 - i * 8)) & 0x000000ffU);
     186         832 :         hash[i + 16] =
     187         832 :             static_cast<GByte>((ctx->state[4] >> (24 - i * 8)) & 0x000000ffU);
     188             :     }
     189         208 : }
     190             : 
     191             : /************************************************************************/
     192             : /*                              CPL_SHA1()                              */
     193             : /************************************************************************/
     194             : 
     195           0 : static void CPL_SHA1(const void *data, size_t len,
     196             :                      GByte hash[CPL_SHA1_HASH_SIZE])
     197             : {
     198             :     CPL_SHA1Context sSHA1Ctxt;
     199           0 :     CPL_SHA1Init(&sSHA1Ctxt);
     200           0 :     CPL_SHA1Update(&sSHA1Ctxt, static_cast<const GByte *>(data), len);
     201           0 :     CPL_SHA1Final(&sSHA1Ctxt, hash);
     202           0 :     memset(&sSHA1Ctxt, 0, sizeof(sSHA1Ctxt));
     203           0 : }
     204             : 
     205             : /************************************************************************/
     206             : /*                           CPL_HMAC_SHA1()                            */
     207             : /************************************************************************/
     208             : 
     209             : #define CPL_HMAC_SHA1_BLOCKSIZE 64U
     210             : 
     211             : // See
     212             : // https://en.wikipedia.org/wiki/Hash-based_message_authentication_code#Implementation
     213         104 : void CPL_HMAC_SHA1(const void *pKey, size_t nKeyLen, const void *pabyMessage,
     214             :                    size_t nMessageLen, GByte abyDigest[CPL_SHA1_HASH_SIZE])
     215             : {
     216         104 :     GByte abyPad[CPL_HMAC_SHA1_BLOCKSIZE] = {};
     217         104 :     if (nKeyLen > CPL_HMAC_SHA1_BLOCKSIZE)
     218             :     {
     219           0 :         CPL_SHA1(pKey, nKeyLen, abyPad);
     220             :     }
     221             :     else
     222             :     {
     223         104 :         memcpy(abyPad, pKey, nKeyLen);
     224             :     }
     225             : 
     226             :     // Compute ipad.
     227        6760 :     for (size_t i = 0; i < CPL_HMAC_SHA1_BLOCKSIZE; i++)
     228        6656 :         abyPad[i] = 0x36 ^ abyPad[i];
     229             : 
     230             :     CPL_SHA1Context sSHA1Ctxt;
     231         104 :     CPL_SHA1Init(&sSHA1Ctxt);
     232         104 :     CPL_SHA1Update(&sSHA1Ctxt, abyPad, CPL_HMAC_SHA1_BLOCKSIZE);
     233         104 :     CPL_SHA1Update(&sSHA1Ctxt, static_cast<const GByte *>(pabyMessage),
     234             :                    nMessageLen);
     235         104 :     CPL_SHA1Final(&sSHA1Ctxt, abyDigest);
     236             : 
     237             :     // Compute opad.
     238        6760 :     for (size_t i = 0; i < CPL_HMAC_SHA1_BLOCKSIZE; i++)
     239        6656 :         abyPad[i] = (0x36 ^ 0x5C) ^ abyPad[i];
     240             : 
     241         104 :     CPL_SHA1Init(&sSHA1Ctxt);
     242         104 :     CPL_SHA1Update(&sSHA1Ctxt, abyPad, CPL_HMAC_SHA1_BLOCKSIZE);
     243         104 :     CPL_SHA1Update(&sSHA1Ctxt, abyDigest, CPL_SHA1_HASH_SIZE);
     244         104 :     CPL_SHA1Final(&sSHA1Ctxt, abyDigest);
     245             : 
     246         104 :     memset(&sSHA1Ctxt, 0, sizeof(sSHA1Ctxt));
     247         104 :     memset(abyPad, 0, CPL_HMAC_SHA1_BLOCKSIZE);
     248         104 : }

Generated by: LCOV version 1.14