Coverage Report

Created: 2022-12-01 06:42

/src/curl/lib/hmac.c
Line
Count
Source (jump to first uncovered line)
1
/***************************************************************************
2
 *                                  _   _ ____  _
3
 *  Project                     ___| | | |  _ \| |
4
 *                             / __| | | | |_) | |
5
 *                            | (__| |_| |  _ <| |___
6
 *                             \___|\___/|_| \_\_____|
7
 *
8
 * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
9
 *
10
 * This software is licensed as described in the file COPYING, which
11
 * you should have received as part of this distribution. The terms
12
 * are also available at https://curl.se/docs/copyright.html.
13
 *
14
 * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15
 * copies of the Software, and permit persons to whom the Software is
16
 * furnished to do so, under the terms of the COPYING file.
17
 *
18
 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19
 * KIND, either express or implied.
20
 *
21
 * SPDX-License-Identifier: curl
22
 *
23
 * RFC2104 Keyed-Hashing for Message Authentication
24
 *
25
 ***************************************************************************/
26
27
#include "curl_setup.h"
28
29
#ifndef CURL_DISABLE_CRYPTO_AUTH
30
31
#include <curl/curl.h>
32
33
#include "curl_hmac.h"
34
#include "curl_memory.h"
35
#include "warnless.h"
36
37
/* The last #include file should be: */
38
#include "memdebug.h"
39
40
/*
41
 * Generic HMAC algorithm.
42
 *
43
 *   This module computes HMAC digests based on any hash function. Parameters
44
 * and computing procedures are set-up dynamically at HMAC computation context
45
 * initialization.
46
 */
47
48
static const unsigned char hmac_ipad = 0x36;
49
static const unsigned char hmac_opad = 0x5C;
50
51
52
53
struct HMAC_context *
54
Curl_HMAC_init(const struct HMAC_params *hashparams,
55
               const unsigned char *key,
56
               unsigned int keylen)
57
0
{
58
0
  size_t i;
59
0
  struct HMAC_context *ctxt;
60
0
  unsigned char *hkey;
61
0
  unsigned char b;
62
63
  /* Create HMAC context. */
64
0
  i = sizeof(*ctxt) + 2 * hashparams->hmac_ctxtsize +
65
0
    hashparams->hmac_resultlen;
66
0
  ctxt = malloc(i);
67
68
0
  if(!ctxt)
69
0
    return ctxt;
70
71
0
  ctxt->hmac_hash = hashparams;
72
0
  ctxt->hmac_hashctxt1 = (void *) (ctxt + 1);
73
0
  ctxt->hmac_hashctxt2 = (void *) ((char *) ctxt->hmac_hashctxt1 +
74
0
      hashparams->hmac_ctxtsize);
75
76
  /* If the key is too long, replace it by its hash digest. */
77
0
  if(keylen > hashparams->hmac_maxkeylen) {
78
0
    (*hashparams->hmac_hinit)(ctxt->hmac_hashctxt1);
79
0
    (*hashparams->hmac_hupdate)(ctxt->hmac_hashctxt1, key, keylen);
80
0
    hkey = (unsigned char *) ctxt->hmac_hashctxt2 + hashparams->hmac_ctxtsize;
81
0
    (*hashparams->hmac_hfinal)(hkey, ctxt->hmac_hashctxt1);
82
0
    key = hkey;
83
0
    keylen = hashparams->hmac_resultlen;
84
0
  }
85
86
  /* Prime the two hash contexts with the modified key. */
87
0
  (*hashparams->hmac_hinit)(ctxt->hmac_hashctxt1);
88
0
  (*hashparams->hmac_hinit)(ctxt->hmac_hashctxt2);
89
90
0
  for(i = 0; i < keylen; i++) {
91
0
    b = (unsigned char)(*key ^ hmac_ipad);
92
0
    (*hashparams->hmac_hupdate)(ctxt->hmac_hashctxt1, &b, 1);
93
0
    b = (unsigned char)(*key++ ^ hmac_opad);
94
0
    (*hashparams->hmac_hupdate)(ctxt->hmac_hashctxt2, &b, 1);
95
0
  }
96
97
0
  for(; i < hashparams->hmac_maxkeylen; i++) {
98
0
    (*hashparams->hmac_hupdate)(ctxt->hmac_hashctxt1, &hmac_ipad, 1);
99
0
    (*hashparams->hmac_hupdate)(ctxt->hmac_hashctxt2, &hmac_opad, 1);
100
0
  }
101
102
  /* Done, return pointer to HMAC context. */
103
0
  return ctxt;
104
0
}
105
106
int Curl_HMAC_update(struct HMAC_context *ctxt,
107
                     const unsigned char *data,
108
                     unsigned int len)
109
0
{
110
  /* Update first hash calculation. */
111
0
  (*ctxt->hmac_hash->hmac_hupdate)(ctxt->hmac_hashctxt1, data, len);
112
0
  return 0;
113
0
}
114
115
116
int Curl_HMAC_final(struct HMAC_context *ctxt, unsigned char *result)
117
0
{
118
0
  const struct HMAC_params *hashparams = ctxt->hmac_hash;
119
120
  /* Do not get result if called with a null parameter: only release
121
     storage. */
122
123
0
  if(!result)
124
0
    result = (unsigned char *) ctxt->hmac_hashctxt2 +
125
0
     ctxt->hmac_hash->hmac_ctxtsize;
126
127
0
  (*hashparams->hmac_hfinal)(result, ctxt->hmac_hashctxt1);
128
0
  (*hashparams->hmac_hupdate)(ctxt->hmac_hashctxt2,
129
0
   result, hashparams->hmac_resultlen);
130
0
  (*hashparams->hmac_hfinal)(result, ctxt->hmac_hashctxt2);
131
0
  free((char *) ctxt);
132
0
  return 0;
133
0
}
134
135
/*
136
 * Curl_hmacit()
137
 *
138
 * This is used to generate a HMAC hash, for the specified input data, given
139
 * the specified hash function and key.
140
 *
141
 * Parameters:
142
 *
143
 * hashparams [in]     - The hash function (Curl_HMAC_MD5).
144
 * key        [in]     - The key to use.
145
 * keylen     [in]     - The length of the key.
146
 * data       [in]     - The data to encrypt.
147
 * datalen    [in]     - The length of the data.
148
 * output     [in/out] - The output buffer.
149
 *
150
 * Returns CURLE_OK on success.
151
 */
152
CURLcode Curl_hmacit(const struct HMAC_params *hashparams,
153
                     const unsigned char *key, const size_t keylen,
154
                     const unsigned char *data, const size_t datalen,
155
                     unsigned char *output)
156
0
{
157
0
  struct HMAC_context *ctxt =
158
0
    Curl_HMAC_init(hashparams, key, curlx_uztoui(keylen));
159
160
0
  if(!ctxt)
161
0
    return CURLE_OUT_OF_MEMORY;
162
163
  /* Update the digest with the given challenge */
164
0
  Curl_HMAC_update(ctxt, data, curlx_uztoui(datalen));
165
166
  /* Finalise the digest */
167
0
  Curl_HMAC_final(ctxt, output);
168
169
0
  return CURLE_OK;
170
0
}
171
172
#endif /* CURL_DISABLE_CRYPTO_AUTH */