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