digest.c
Go to the documentation of this file.
1 /* ========================================================================== */
2 /*! \file
3  * \brief Message Digests
4  *
5  * Copyright (c) 2012-2020 by the developers. See the LICENSE file for details.
6  *
7  * If nothing else is specified, function return zero to indicate success
8  * and a negative value to indicate an error.
9  */
10 
11 
12 /* ========================================================================== */
13 /* Include headers */
14 
15 #include "posix.h" /* Include this first because of feature test macros */
16 
17 #include "config.h"
18 
19 #if CFG_USE_TLS /* This requires data from "config.h" */
20 # include <openssl/evp.h>
21 #endif /* CFG_USE_TLS */
22 #include <string.h>
23 
24 #include "digest.h"
25 #include "main.h"
26 
27 
28 /* ========================================================================== */
29 /*! \defgroup DIGEST DIGEST: Hash algorithms
30  *
31  * This module provides optional support for message digest algorithms. It is
32  * intended to comply with RFC 3174.
33  *
34  * \attention
35  * This module currently works only if TLS support is available (because both
36  * share the cryptographic functions provided by OpenSSL).
37  */
38 /*! @{ */
39 
40 
41 /* ========================================================================== */
42 /* Constants */
43 
44 /*! \brief Message prefix for DIGEST module */
45 #define MAIN_ERR_PREFIX "DIGEST: "
46 
47 
48 /* ========================================================================== */
49 /* Data types */
50 
51 enum digest_alg
52 {
53  DIGEST_ALG_SHA1_160,
54  DIGEST_ALG_SHA2_256
55 };
56 
57 
58 /* ========================================================================== */
59 /* Delegate digest calculation to OpenSSL */
60 
61 static int digest_openssl(enum digest_alg alg, const char* text,
62  size_t text_len, unsigned char* md)
63 {
64  int res = -1;
65 #if CFG_USE_TLS
66  EVP_MD_CTX* (*openssl_evp_md_ctx_new)(void);
67  void (*openssl_evp_md_ctx_free)(EVP_MD_CTX*);
68  EVP_MD_CTX* ctx;
69  const EVP_MD* md_id;
70  size_t md_len_check = 1; /* Value never used by real digest */
71  unsigned int md_len = 0;
72  int rv;
73 
74  /* Setup context management functions (changed in API 1.1) */
75 #if CFG_USE_OPENSSL_API_1_1
76  openssl_evp_md_ctx_new = EVP_MD_CTX_new;
77  openssl_evp_md_ctx_free = EVP_MD_CTX_free;
78 #else /* CFG_USE_OPENSSL_API_1_1 */
79  openssl_evp_md_ctx_new = EVP_MD_CTX_create;
80  openssl_evp_md_ctx_free = EVP_MD_CTX_destroy;
81 #endif /* CFG_USE_OPENSSL_API_1_1 */
82 
83  /* Select digest algorithm */
84  switch(alg)
85  {
86  case DIGEST_ALG_SHA1_160:
87  {
88  md_id = EVP_sha1();
89  md_len_check = DIGEST_SHA1_160_LEN;
90  break;
91  }
92  case DIGEST_ALG_SHA2_256:
93  {
94  md_id = EVP_sha256();
95  md_len_check = DIGEST_SHA2_256_LEN;
96  break;
97  }
98  default:
99  {
100  PRINT_ERROR("Requested algorithm not supported");
101  md_id = NULL;
102  break;
103  }
104  }
105  if(NULL != md_id)
106  {
107  /* Create context */
108  ctx = openssl_evp_md_ctx_new();
109  if(NULL == ctx) { PRINT_ERROR("Creating context failed"); }
110  /* Check whether length value can be represented as data type 'int' */
111  else if(!(POSIX_INT_MAX >= text_len))
112  {
113  PRINT_ERROR("Message is too long");
114  }
115  else
116  {
117  /* Delegate job to OpenSSL */
118  rv = EVP_DigestInit_ex(ctx, md_id, NULL);
119  if(1 == rv)
120  {
121  rv = EVP_DigestUpdate(ctx, (void*) text, text_len);
122  if(1 == rv)
123  {
124  rv = EVP_DigestFinal_ex(ctx, md, &md_len);
125  if(1 == rv && md_len_check == (size_t) md_len)
126  {
127  /* Success */
128  res = 0;
129  }
130  }
131  }
132  }
133  /* Destroy context */
134  if(NULL != ctx) { openssl_evp_md_ctx_free(ctx); }
135  }
136 #endif /* CFG_USE_TLS */
137 
138  return(res);
139 }
140 
141 
142 /* ========================================================================== */
143 /*! \brief Secure Hash Algorithm SHA1-160
144  *
145  * \param[in] text Message
146  * \param[in] text_len Message length
147  * \param[out] md Message digest
148  *
149  * The values of paramater \e text_len must represent bytes.
150  *
151  * On success, the result is written to \e md and has a length of
152  * \c DIGEST_SHA1_160_LEN bytes.
153  *
154  * \return
155  * - 0 on success
156  * - -1 on error
157  */
158 
159 int digest_sha1_160(const char* text, size_t text_len, unsigned char* md)
160 {
161  return(digest_openssl(DIGEST_ALG_SHA1_160, text, text_len, md));
162 }
163 
164 
165 /* ========================================================================== */
166 /*! \brief Secure Hash Algorithm SHA2-256
167  *
168  * \param[in] text Message
169  * \param[in] text_len Message length
170  * \param[out] md Message digest
171  *
172  * The values of paramater \e text_len must represent bytes.
173  *
174  * On success, the result is written to \e md and has a length of
175  * \c DIGEST_SHA2_256_LEN bytes.
176  *
177  * \return
178  * - 0 on success
179  * - -1 on error
180  */
181 
182 int digest_sha2_256(const char* text, size_t text_len, unsigned char* md)
183 {
184  return(digest_openssl(DIGEST_ALG_SHA2_256, text, text_len, md));
185 }
186 
187 
188 /* ========================================================================== */
189 /*! \brief Initialize message digest module */
190 
191 void digest_init(void)
192 {
193  return;
194 }
195 
196 
197 /* ========================================================================== */
198 /*! \brief Shutdown message digest module */
199 
200 void digest_exit(void)
201 {
202  /*
203  * Note:
204  * \c EVP_cleanup() must be called by the exit handler of the TLS module.
205  */
206 
207  return;
208 }
209 
210 
211 /*! @} */
212 
213 /* EOF */
digest_sha1_160
int digest_sha1_160(const char *text, size_t text_len, unsigned char *md)
Secure Hash Algorithm SHA1-160.
Definition: digest.c:159
digest_exit
void digest_exit(void)
Shutdown message digest module.
Definition: digest.c:200
PRINT_ERROR
#define PRINT_ERROR(s)
Prepend module prefix and print error message.
Definition: main.h:19
DIGEST_SHA2_256_LEN
#define DIGEST_SHA2_256_LEN
256 bit
Definition: digest.h:19
DIGEST_SHA1_160_LEN
#define DIGEST_SHA1_160_LEN
160 bit
Definition: digest.h:18
digest_init
void digest_init(void)
Initialize message digest module.
Definition: digest.c:191
digest_sha2_256
int digest_sha2_256(const char *text, size_t text_len, unsigned char *md)
Secure Hash Algorithm SHA2-256.
Definition: digest.c:182

Generated at 2024-04-27 using  doxygen