Coverage Report

Created: 2026-02-26 06:20

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
EVP_MD_CTX *digest_ctx;
28
29
30
static void
31
atexit_ssl_cleanup(void)
32
0
{
33
0
  if (NULL == digest_ctx) {
34
0
    return;
35
0
  }
36
0
  EVP_MD_CTX_free(digest_ctx);
37
0
  digest_ctx = NULL;
38
#if OPENSSL_VERSION_NUMBER < 0x10100000L
39
  EVP_cleanup();
40
  ERR_free_strings();
41
#endif  /* OpenSSL < 1.1 */
42
0
}
43
44
45
void
46
ssl_init(void)
47
0
{
48
0
  init_lib();
49
50
0
  if (NULL == digest_ctx) {
51
#if OPENSSL_VERSION_NUMBER < 0x10100000L
52
    ERR_load_crypto_strings();
53
    OpenSSL_add_all_algorithms();
54
#endif  /* OpenSSL < 1.1 */
55
0
    digest_ctx = EVP_MD_CTX_new();
56
0
    INSIST(digest_ctx != NULL);
57
0
    atexit(&atexit_ssl_cleanup);
58
0
  }
59
0
}
60
61
62
void
63
ssl_check_version(void)
64
0
{
65
0
  u_long  v;
66
0
  char *  buf;
67
68
0
  v = OpenSSL_version_num();
69
0
  if ((v ^ OPENSSL_VERSION_NUMBER) & ~0xff0L) {
70
0
    LIB_GETBUF(buf);
71
0
    snprintf(buf, LIB_BUFLENGTH, 
72
0
       "OpenSSL version mismatch."
73
0
       "Built against %lx, you have %lx\n",
74
0
       (u_long)OPENSSL_VERSION_NUMBER, v);
75
0
    msyslog(LOG_WARNING, "%s", buf);
76
0
    fputs(buf, stderr);
77
0
  }
78
0
  INIT_SSL();
79
0
}
80
#endif  /* OPENSSL */
81
82
83
/*
84
 * keytype_from_text  returns OpenSSL NID for digest by name, and
85
 *      optionally the associated digest length.
86
 *
87
 * Used by ntpd authreadkeys(), ntpq and ntpdc keytype()
88
 */
89
int
90
keytype_from_text(
91
  const char *  text,
92
  size_t *  pdigest_len
93
  )
94
0
{
95
0
  int   key_type;
96
0
  u_int   digest_len;
97
0
#ifdef OPENSSL  /* --*-- OpenSSL code --*-- */
98
0
  const u_long  max_digest_len = MAX_MDG_LEN;
99
0
  char *    upcased;
100
0
  char *    pch;
101
0
  EVP_MD const *  md;
102
103
  /*
104
   * OpenSSL digest short names are capitalized, so uppercase the
105
   * digest name before passing to OBJ_sn2nid().  If it is not
106
   * recognized but matches our CMAC string use NID_cmac, or if
107
   * it begins with 'M' or 'm' use NID_md5 to be consistent with
108
   * past behavior.
109
   */
110
0
  INIT_SSL();
111
112
  /* get name in uppercase */
113
0
  LIB_GETBUF(upcased);
114
0
  strlcpy(upcased, text, LIB_BUFLENGTH);
115
116
0
  for (pch = upcased; '\0' != *pch; pch++) {
117
0
    *pch = (char)toupper((unsigned char)*pch);
118
0
  }
119
120
0
  key_type = OBJ_sn2nid(upcased);
121
122
0
#   ifdef ENABLE_CMAC
123
0
  if (!key_type && !strncmp(CMAC, upcased, strlen(CMAC) + 1)) {
124
0
    key_type = NID_cmac;
125
126
0
    if (debug) {
127
0
      fprintf(stderr, "%s:%d:%s():%s:key\n",
128
0
        __FILE__, __LINE__, __func__, CMAC);
129
0
    }
130
0
  }
131
0
#   endif /*ENABLE_CMAC*/
132
#else
133
134
  key_type = 0;
135
#endif
136
137
0
  if (!key_type && 'm' == tolower((unsigned char)text[0])) {
138
0
    key_type = NID_md5;
139
0
  }
140
141
0
  if (!key_type) {
142
0
    return 0;
143
0
  }
144
145
0
  if (NULL != pdigest_len) {
146
0
#ifdef OPENSSL
147
0
    md = EVP_get_digestbynid(key_type);
148
0
    digest_len = (md) ? EVP_MD_size(md) : 0;
149
150
0
    if (!md || digest_len <= 0) {
151
0
#   ifdef ENABLE_CMAC
152
0
        if (key_type == NID_cmac) {
153
0
      digest_len = CMAC_LENGTH;
154
155
0
      if (debug) {
156
0
        fprintf(stderr, "%s:%d:%s():%s:len\n",
157
0
          __FILE__, __LINE__, __func__, CMAC);
158
0
      }
159
0
        } else
160
0
#   endif /*ENABLE_CMAC*/
161
0
        {
162
0
      fprintf(stderr,
163
0
        "key type %s is not supported by OpenSSL\n",
164
0
        keytype_name(key_type));
165
0
      msyslog(LOG_ERR,
166
0
        "key type %s is not supported by OpenSSL\n",
167
0
        keytype_name(key_type));
168
0
      return 0;
169
0
        }
170
0
    }
171
172
0
    if (digest_len > max_digest_len) {
173
0
        fprintf(stderr,
174
0
          "key type %s %u octet digests are too big, max %lu\n",
175
0
          keytype_name(key_type), digest_len,
176
0
          max_digest_len);
177
0
        msyslog(LOG_ERR,
178
0
          "key type %s %u octet digests are too big, max %lu",
179
0
          keytype_name(key_type), digest_len,
180
0
          max_digest_len);
181
0
        return 0;
182
0
    }
183
#else
184
    digest_len = MD5_LENGTH;
185
#endif
186
0
    *pdigest_len = digest_len;
187
0
  }
188
189
0
  return key_type;
190
0
}
191
192
193
/*
194
 * keytype_name   returns OpenSSL short name for digest by NID.
195
 *
196
 * Used by ntpq and ntpdc keytype()
197
 */
198
const char *
199
keytype_name(
200
  int type
201
  )
202
0
{
203
0
  static const char unknown_type[] = "(unknown key type)";
204
0
  const char *name;
205
206
0
#ifdef OPENSSL
207
0
  INIT_SSL();
208
0
  name = OBJ_nid2sn(type);
209
210
0
#   ifdef ENABLE_CMAC
211
0
  if (NID_cmac == type) {
212
0
    name = CMAC;
213
0
  } else
214
0
#   endif /*ENABLE_CMAC*/
215
0
  if (NULL == name) {
216
0
    name = unknown_type;
217
0
  }
218
#else /* !OPENSSL follows */
219
  if (NID_md5 == type)
220
    name = "MD5";
221
  else
222
    name = unknown_type;
223
#endif
224
0
  return name;
225
0
}
226
227
228
/*
229
 * Use getpassphrase() if configure.ac detected it, as Suns that
230
 * have it truncate the password in getpass() to 8 characters.
231
 */
232
#ifdef HAVE_GETPASSPHRASE
233
# define  getpass(str)  getpassphrase(str)
234
#endif
235
236
/*
237
 * getpass_keytype() -- shared between ntpq and ntpdc, only vaguely
238
 *      related to the rest of ssl_init.c.
239
 */
240
char *
241
getpass_keytype(
242
  int type
243
  )
244
0
{
245
0
  char  pass_prompt[64 + 11 + 1]; /* 11 for " Password: " */
246
247
0
  snprintf(pass_prompt, sizeof(pass_prompt),
248
0
     "%.64s Password: ", keytype_name(type));
249
250
0
  return getpass(pass_prompt);
251
0
}
252