1 /* BLURB lgpl
2 			Coda File System
3 			    Release 6
4 
5 	 Copyright (c) 2006-2016 Carnegie Mellon University
6 		  Additional copyrights listed below
7 
8 This  code  is  distributed "AS IS" without warranty of any kind under
9 the  terms of the  GNU  Library General Public Licence  Version 2,  as
10 shown in the file LICENSE. The technical and financial contributors to
11 Coda are listed in the file CREDITS.
12 
13 			Additional copyrights
14 #*/
15 
16 #include <netinet/in.h>
17 #include <stdio.h>
18 #include <string.h>
19 #include <syslog.h>
20 
21 #include <rpc2/secure.h>
22 #include "aes.h"
23 #include "grunt.h"
24 
25 #ifndef LOG_AUTHPRIV
26 #define LOG_AUTHPRIV LOG_AUTH
27 #endif
28 
29 /* max formatted address length = hex ipv6 addr + decimal port + "[]:\0" */
30 #define MAXADDR (32 + 5 + 4)
31 
32 /* Authentication algorithms. */
33 extern struct secure_auth
34     secure_AUTH_NONE,
35     secure_AUTH_AES_XCBC_MAC_96;
36 
37 static const struct secure_auth *alg_auth[] = {
38     &secure_AUTH_NONE,
39     &secure_AUTH_AES_XCBC_MAC_96,
40     NULL
41 };
42 
43 /* Encryption algorithms. */
44 extern struct secure_encr
45     secure_ENCR_NULL,
46     secure_ENCR_AES_CBC,
47     secure_ENCR_AES_CCM_8,
48     secure_ENCR_AES_CCM_12,
49     secure_ENCR_AES_CCM_16;
50 
51 static const struct secure_encr *alg_encr[] = {
52     &secure_ENCR_NULL,
53     &secure_ENCR_AES_CBC,
54     &secure_ENCR_AES_CCM_8,
55     &secure_ENCR_AES_CCM_12,
56     &secure_ENCR_AES_CCM_16,
57     NULL
58 };
59 
secure_init(int verbose)60 void secure_init(int verbose)
61 {
62     /* Should we pass argv[0] down, or leave the openlog up to the caller? */
63     openlog("RPC2", LOG_PID, LOG_AUTHPRIV);
64 
65     /* Initialize and run the AES test vectors */
66     secure_aes_init(verbose);
67 
68     /* Initialize and test the PRNG */
69     secure_random_init(verbose);
70 
71     /* Run the PBKDF timing test */
72     secure_pbkdf_init(verbose);
73 }
74 
secure_release(void)75 void secure_release(void)
76 {
77     secure_random_release();
78     closelog();
79 }
80 
secure_get_auth_byid(int id)81 const struct secure_auth *secure_get_auth_byid(int id)
82 {
83     int i = 0;
84     while (alg_auth[i] && id != alg_auth[i]->id) i++;
85     return alg_auth[i];
86 }
87 
secure_get_encr_byid(int id)88 const struct secure_encr *secure_get_encr_byid(int id)
89 {
90     int i = 0;
91     while (alg_encr[i] && alg_encr[i]->id != id) i++;
92     return alg_encr[i];
93 }
94 
95 /* format_addr is surprisingly similar to RPC2_formataddrinfo, but this way we
96  * don't introduce a dependency on RPC2 (and this formats sockaddr) */
format_addr(const struct sockaddr * sa,char * buf,size_t blen)97 static void format_addr(const struct sockaddr *sa, char *buf, size_t blen)
98 {
99     int n, port = 0;
100     void *addr = NULL;
101     char *p = buf;
102 
103     blen--;
104     if (!sa) {
105 	strncpy(buf, "(missing address)", blen);
106 	buf[blen] = '\0';
107 	return;
108     }
109 
110     switch (sa->sa_family) {
111     case PF_INET:
112 	addr = &((struct sockaddr_in *)sa)->sin_addr;
113 	port = ((struct sockaddr_in *)sa)->sin_port;
114 	break;
115 
116 #ifdef PF_INET6
117     case PF_INET6:
118 	addr = &((struct sockaddr_in6 *)sa)->sin6_addr;
119 	port = ((struct sockaddr_in6 *)sa)->sin6_port;
120 	*(p++) = '[';
121 	break;
122 #endif
123     }
124 
125     /* format address */
126     if (!addr || !inet_ntop(sa->sa_family, addr, p, buf + blen - p)) {
127 	strncpy(buf, "(untranslatable address)", blen);
128 	p = buf;
129     }
130     buf[blen] = '\0';
131 
132     /* append port */
133     n = strlen(buf);
134     if (port)
135 	snprintf(buf + n, blen - n, "%s:%u", p != buf ? "]" : "", ntohs(port));
136     buf[blen] = '\0';
137 }
138 
139 /* RFC 2406 -- The audit log entry ... SHOULD include the SPI value, date/time
140  * received, Source Address, Destination Address, Sequence Number, and (in
141  * IPv6) the Flow ID. */
142 /* I don't actually have the destination address and ipv6 flow id readily
143  * available, so this will have to do. */
secure_audit(const char * event,uint32_t spi,uint32_t seq,const struct sockaddr * src)144 void secure_audit(const char *event, uint32_t spi, uint32_t seq,
145 		  const struct sockaddr *src)
146 {
147     char src_buf[MAXADDR];
148 
149     format_addr(src, src_buf, sizeof(src_buf));
150 
151     syslog(LOG_AUTHPRIV | LOG_NOTICE, "%s: spi %x, seq %d, src %s\n",
152 	   event, spi, seq, src_buf);
153 }
154 
155 /* Constant time comparison, returns true when both buffers are identical */
secure_compare(const void * user_data,size_t user_len,const void * secret,size_t secret_len)156 int secure_compare(const void *user_data, size_t user_len,
157                     const void *secret, size_t secret_len)
158 {
159     volatile const char *cmp, *to = secret;
160     size_t i;
161     int different;
162 
163     /* Make sure we always compare 'secret_len' bytes */
164     if (user_len == secret_len) {
165         cmp = user_data;
166         different = 0;
167     }
168     if (user_len != secret_len) {
169         cmp = to;
170         different = 1;
171     }
172 
173     for (i = 0; i < secret_len; i++) {
174         different |= cmp[i] ^ to[i];
175     }
176 
177     return (different == 0);
178 }
179