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/err.h"
17#include "openssl/rand.h"
18
19
20int ssl_init_done;
21
22void
23ssl_init(void)
24{
25	if (ssl_init_done)
26		return;
27
28	ERR_load_crypto_strings();
29	OpenSSL_add_all_algorithms();
30
31	ssl_init_done = 1;
32}
33
34
35void
36ssl_check_version(void)
37{
38	if ((SSLeay() ^ OPENSSL_VERSION_NUMBER) & ~0xff0L) {
39		msyslog(LOG_WARNING,
40		    "OpenSSL version mismatch. Built against %lx, you have %lx",
41		    OPENSSL_VERSION_NUMBER, SSLeay());
42		fprintf(stderr,
43		    "OpenSSL version mismatch. Built against %lx, you have %lx\n",
44		    OPENSSL_VERSION_NUMBER, SSLeay());
45	}
46
47	INIT_SSL();
48}
49#endif	/* OPENSSL */
50
51
52/*
53 * keytype_from_text	returns OpenSSL NID for digest by name, and
54 *			optionally the associated digest length.
55 *
56 * Used by ntpd authreadkeys(), ntpq and ntpdc keytype()
57 */
58int
59keytype_from_text(
60	const char *text,
61	size_t *pdigest_len
62	)
63{
64	int		key_type;
65	u_int		digest_len;
66#ifdef OPENSSL
67	u_char		digest[EVP_MAX_MD_SIZE];
68	char *		upcased;
69	char *		pch;
70	EVP_MD_CTX	ctx;
71
72	/*
73	 * OpenSSL digest short names are capitalized, so uppercase the
74	 * digest name before passing to OBJ_sn2nid().  If it is not
75	 * recognized but begins with 'M' use NID_md5 to be consistent
76	 * with past behavior.
77	 */
78	INIT_SSL();
79	LIB_GETBUF(upcased);
80	strncpy(upcased, text, LIB_BUFLENGTH);
81	for (pch = upcased; '\0' != *pch; pch++)
82		*pch = (char)toupper(*pch);
83	key_type = OBJ_sn2nid(upcased);
84#else
85	key_type = 0;
86#endif
87
88	if (!key_type && 'm' == tolower(text[0]))
89		key_type = NID_md5;
90
91	if (!key_type)
92		return 0;
93
94	if (NULL != pdigest_len) {
95#ifdef OPENSSL
96		EVP_DigestInit(&ctx, EVP_get_digestbynid(key_type));
97		EVP_DigestFinal(&ctx, digest, &digest_len);
98		if (digest_len + sizeof(keyid_t) > MAX_MAC_LEN) {
99			fprintf(stderr,
100				"key type %s %u octet digests are too big, max %u\n",
101				keytype_name(key_type), digest_len,
102				MAX_MAC_LEN - sizeof(keyid_t));
103			msyslog(LOG_ERR,
104				"key type %s %u octet digests are too big, max %u",
105				keytype_name(key_type), digest_len,
106				MAX_MAC_LEN - sizeof(keyid_t));
107			return 0;
108		}
109#else
110		digest_len = 16;
111#endif
112		*pdigest_len = digest_len;
113	}
114
115	return key_type;
116}
117
118
119/*
120 * keytype_name		returns OpenSSL short name for digest by NID.
121 *
122 * Used by ntpq and ntpdc keytype()
123 */
124const char *
125keytype_name(
126	int nid
127	)
128{
129	static const char unknown_type[] = "(unknown key type)";
130	const char *name;
131
132#ifdef OPENSSL
133	INIT_SSL();
134	name = OBJ_nid2sn(nid);
135	if (NULL == name)
136		name = unknown_type;
137#else	/* !OPENSSL follows */
138	if (NID_md5 == nid)
139		name = "MD5";
140	else
141		name = unknown_type;
142#endif
143	return name;
144}
145
146