xref: /freebsd/contrib/ntp/libntp/a_md5encrypt.c (revision 1b6c76a2fe091c74f08427e6c870851025a9cf67)
1 /*
2  *	MD5 interface for rsaref2.0
3  *
4  * These routines implement an interface for the RSA Laboratories
5  * implementation of the Message Digest 5 (MD5) algorithm. This
6  * algorithm is included in the rsaref2.0 package available from RSA in
7  * the US and foreign countries. Further information is available at
8  * www.rsa.com.
9  */
10 
11 #include "ntp_machine.h"
12 
13 #ifdef HAVE_CONFIG_H
14 #include <config.h>
15 #endif
16 
17 #ifdef MD5
18 #include <stdio.h>
19 
20 #include "ntp_types.h"
21 #include "ntp_fp.h"
22 #include "ntp_string.h"
23 #include "global.h"
24 #include "md5.h"
25 #include "ntp_stdlib.h"
26 
27 #define BLOCK_OCTETS	16	/* message digest size */
28 #define NTP_MAXKEY	65535	/* max identifier from ntp.h */
29 
30 
31 /*
32  * MD5authencrypt - generate MD5 message authenticator
33  *
34  * Returns length of authenticator field.
35  */
36 int
37 MD5authencrypt(
38 	u_char *key,		/* key pointer */
39 	u_int32 *pkt,		/* packet pointer */
40 	int length		/* packet length */
41 	)
42 {
43 	MD5_CTX ctx;
44 	u_char digest[BLOCK_OCTETS];
45 	int i;
46 
47 	/*
48 	 * MD5 with key identifier concatenated with packet.
49 	 */
50 	MD5Init(&ctx);
51 	MD5Update(&ctx, key, (u_int)cache_keylen);
52 	MD5Update(&ctx, (u_char *)pkt, (u_int)length);
53 	MD5Final(digest, &ctx);
54 	i = length / 4;
55 	memmove((char *)&pkt[i + 1], (char *)digest, BLOCK_OCTETS);
56 	return (BLOCK_OCTETS + 4);
57 }
58 
59 
60 /*
61  * MD5authdecrypt - verify MD5 message authenticator
62  *
63  * Returns one if authenticator valid, zero if invalid.
64  */
65 int
66 MD5authdecrypt(
67 	u_char *key,		/* key pointer */
68 	u_int32 *pkt,		/* packet pointer */
69 	int length, 	/* packet length */
70 	int size		/* MAC size */
71 	)
72 {
73 	MD5_CTX ctx;
74 	u_char digest[BLOCK_OCTETS];
75 
76 	/*
77 	 * MD5 with key identifier concatenated with packet.
78 	 */
79 	if (size != BLOCK_OCTETS + 4)
80 		return (0);
81 	MD5Init(&ctx);
82 	MD5Update(&ctx, key, (u_int)cache_keylen);
83 	MD5Update(&ctx, (u_char *)pkt, (u_int)length);
84 	MD5Final(digest, &ctx);
85 	return (!memcmp((char *)digest, (char *)pkt + length + 4,
86 		BLOCK_OCTETS));
87 }
88 
89 
90 /*
91  * session_key - generate session key from supplied plaintext.
92  *
93  * Returns hashed session key for validation.
94  */
95 u_long
96 session_key(
97 	u_int32 srcadr, 	/* source address */
98 	u_int32 dstadr, 	/* destination address */
99 	u_long keyno,		/* key identifier */
100 	u_long lifetime 	/* key lifetime */
101 	)
102 {
103 	MD5_CTX ctx;
104 	u_int32 header[3];
105 	u_long keyid;
106 	u_char digest[BLOCK_OCTETS];
107 
108 	/*
109 	 * Generate the session key and retrieve the hash for later. If
110 	 * the lifetime is greater than zero, call the key trusted.
111 	 */
112 	header[0] = htonl(srcadr);
113 	header[1] = htonl(dstadr);
114 	header[2] = htonl(keyno);
115 	MD5Init(&ctx);
116 	MD5Update(&ctx, (u_char *)header, sizeof(header));
117 	MD5Final(digest, &ctx);
118 	memcpy(&keyid, digest, 4);
119 	if (lifetime != 0) {
120 		MD5auth_setkey(keyno, digest, BLOCK_OCTETS);
121 		authtrust(keyno, (int)lifetime);
122 	}
123 #ifdef DEBUG
124 	if (debug > 1)
125 		printf(
126 			"session_key: from %s to %s keyid %08lx hash %08lx life %ld\n",
127 			numtoa(htonl(srcadr)), numtoa(htonl(dstadr)), keyno,
128 			keyid, lifetime);
129 #endif
130 	return (keyid);
131 }
132 #endif /* MD5 */
133