Coverage Report

Created: 2026-08-31 07:18

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ntp-dev/libntp/ssl_init.c
Line
Count
Source
1
/*
2
 * ssl_init.c Common OpenSSL initialization code for the various
3
 *    programs which use it.
4
 *
5
 * Moved from ntpd/ntp_crypto.c crypto_setup()
6
 */
7
#ifdef HAVE_CONFIG_H
8
# include <config.h>
9
#endif
10
#include <ctype.h>
11
#include <ntp.h>
12
#include <ntp_debug.h>
13
#include <lib_strbuf.h>
14
15
#ifdef OPENSSL
16
# include <openssl/crypto.h>
17
# include <openssl/err.h>
18
# include <openssl/evp.h>
19
# include <openssl/opensslv.h>
20
# include "libssl_compat.h"
21
# ifdef HAVE_OPENSSL_CMAC_H
22
#  include <openssl/cmac.h>
23
0
#  define CMAC_LENGTH 16
24
0
#  define CMAC    "AES128CMAC"
25
# endif /*HAVE_OPENSSL_CMAC_H*/
26
27
/* Break apart OpenSSL version number */
28
0
#define SSLV_MAJOR(vn)  (((vn) & 0xf0000000) >> 28)
29
0
#define SSLV_MINOR(vn)  (((vn) & 0x0ff00000) >> 20)
30
#define SSLV_PATCH(vn)  (((vn) & 0x00000ff0) >> 4)
31
32
EVP_MD_CTX *digest_ctx;
33
34
35
static void
36
atexit_ssl_cleanup(void)
37
0
{
38
0
  if (NULL == digest_ctx) {
39
0
    return;
40
0
  }
41
0
  EVP_MD_CTX_free(digest_ctx);
42
0
  digest_ctx = NULL;
43
#if OPENSSL_VERSION_NUMBER < 0x10100000L
44
  EVP_cleanup();
45
  ERR_free_strings();
46
#endif  /* OpenSSL < 1.1 */
47
0
}
48
49
50
void
51
ssl_init(void)
52
0
{
53
0
  init_lib();
54
55
0
  if (NULL == digest_ctx) {
56
#if OPENSSL_VERSION_NUMBER < 0x10100000L
57
    ERR_load_crypto_strings();
58
    OpenSSL_add_all_algorithms();
59
#endif  /* OpenSSL < 1.1 */
60
0
    digest_ctx = EVP_MD_CTX_new();
61
0
    INSIST(digest_ctx != NULL);
62
0
    atexit(&atexit_ssl_cleanup);
63
0
  }
64
0
}
65
66
67
void
68
ssl_check_version(void)
69
0
{
70
0
  const u_long  bv = OPENSSL_VERSION_NUMBER;
71
0
  u_long    rv = OpenSSL_version_num();
72
0
  char *    buf;
73
74
0
  if (   SSLV_MAJOR(bv) != SSLV_MAJOR(rv)
75
0
      || SSLV_MINOR(bv) != SSLV_MINOR(rv)) {
76
77
0
    buf = lib_getbuf();
78
0
    snprintf(buf, LIB_BUFLENGTH,
79
0
      "Using libcrypto %lu.%lu.%lu,"
80
0
      " built for %lu.%lu.%lu.\n",
81
0
      SSLV_MAJOR(rv), SSLV_MINOR(rv), SSLV_PATCH(rv),
82
0
      SSLV_MAJOR(bv), SSLV_MINOR(bv), SSLV_PATCH(bv));
83
0
    msyslog(LOG_WARNING, "%s", buf);
84
0
    fputs(buf, stderr);
85
0
  }
86
0
  INIT_SSL();
87
0
}
88
#endif  /* OPENSSL */
89
90
91
/*
92
 * keytype_from_text  returns OpenSSL NID for digest by name, and
93
 *      optionally the associated digest length.
94
 *
95
 * Used by ntpd authreadkeys(), ntpq and ntpdc keytype()
96
 */
97
int
98
keytype_from_text(
99
  const char *  text,
100
  size_t *  pdigest_len
101
  )
102
0
{
103
0
  int   key_type;
104
0
  u_int   digest_len;
105
0
#ifdef OPENSSL
106
0
  char *    upcased;
107
0
  EVP_MD const *  md;
108
109
  /*
110
   * If key type string is not recognized but matches our CMAC string
111
   * use NID_cmac, or if it begins with 'M' or 'm' use NID_md5.  The
112
   * single-letter alias M has long been used by ntp-keygen for MD5
113
   * when generating ntp.keys.
114
   * When built with OpenSSL MD5 may not be available for symmetric
115
   * authentication due to FIPS hardening or OpenSSL deprecation,
116
   * though we'll still have it available for IPv6 refid derivation
117
   * and mode 6 nonces, where other concerns outweigh the reasons
118
   * for its deprecation.
119
   */
120
0
  INIT_SSL();
121
122
0
  if ('m' == tolower(text[0]) && '\0' == text[1]) {
123
0
    upcased = strdup("MD5");
124
0
  } else {
125
0
    upcased = _strupr(strdup(text));
126
0
  }
127
0
  key_type = OBJ_sn2nid(upcased);
128
129
0
# ifdef ENABLE_CMAC
130
0
  if (!key_type && !strcmp(CMAC, upcased)) {
131
0
    key_type = NID_cmac;
132
0
  }
133
0
# endif
134
0
  free(upcased);
135
0
  upcased = NULL;
136
137
#else /* !OPENSSL follows */
138
  if ('m' == tolower(text[0])) {
139
    key_type = NID_md5;
140
  } else {
141
    key_type = 0;
142
  }
143
#endif
144
0
  if (0 == key_type) {
145
0
    return 0;
146
0
  }
147
148
0
  if (NULL != pdigest_len) {
149
0
#ifdef OPENSSL
150
0
    md = EVP_get_digestbynid(key_type);
151
0
    digest_len = (md) ? EVP_MD_size(md) : 0;
152
153
0
    if (NULL == md || 0 == digest_len) {
154
0
# ifdef ENABLE_CMAC
155
0
      if (NID_cmac == key_type) {
156
0
        digest_len = CMAC_LENGTH;
157
0
      } else
158
0
# endif
159
0
      {
160
0
        msyslog(LOG_ERR,
161
0
          "key type %s is not supported by OpenSSL\n",
162
0
          keytype_name(key_type));
163
0
        return 0;
164
0
      }
165
0
    }
166
#else /* !OPENSSL follows */
167
    digest_len = MD5_LENGTH;
168
#endif
169
0
    *pdigest_len = min(digest_len, MAX_MDG_LEN);
170
0
  }
171
172
0
  return key_type;
173
0
}
174
175
176
/*
177
 * keytype_name   returns OpenSSL short name for digest by NID.
178
 *
179
 * Used by ntpq and ntpdc keytype()
180
 */
181
const char *
182
keytype_name(
183
  int type
184
  )
185
0
{
186
0
  static const char unknown_type[] = "(unknown key type)";
187
0
  const char *name;
188
189
0
#ifdef OPENSSL
190
0
  INIT_SSL();
191
0
  name = OBJ_nid2sn(type);
192
193
0
#   ifdef ENABLE_CMAC
194
0
  if (NID_cmac == type) {
195
0
    name = CMAC;
196
0
  } else
197
0
#   endif /*ENABLE_CMAC*/
198
0
  if (NULL == name) {
199
0
    name = unknown_type;
200
0
  }
201
#else /* !OPENSSL follows */
202
  if (NID_md5 == type)
203
    name = "MD5";
204
  else
205
    name = unknown_type;
206
#endif
207
0
  return name;
208
0
}
209
210
211
/*
212
 * Use getpassphrase() if configure.ac detected it, as Suns that
213
 * have it truncate the password in getpass() to 8 characters.
214
 */
215
#ifdef HAVE_GETPASSPHRASE
216
# define  getpass(str)  getpassphrase(str)
217
#endif
218
219
/*
220
 * getpass_keytype() -- shared between ntpq and ntpdc, only vaguely
221
 *      related to the rest of ssl_init.c.
222
 */
223
char *
224
getpass_keytype(
225
  int type
226
  )
227
0
{
228
0
  char  pass_prompt[64 + 11 + 1]; /* 11 for " Password: " */
229
230
0
  snprintf(pass_prompt, sizeof(pass_prompt),
231
0
     "%.64s Password: ", keytype_name(type));
232
233
0
  return getpass(pass_prompt);
234
0
}
235