1 /* $NetBSD: prsa_par.y,v 1.8 2022/01/23 14:55:28 christos Exp $ */
2
3 /* Id: prsa_par.y,v 1.3 2004/11/08 12:04:23 ludvigm Exp */
4
5 %{
6 /*
7 * Copyright (C) 2004 SuSE Linux AG, Nuernberg, Germany.
8 * Contributed by: Michal Ludvig <mludvig@suse.cz>, SUSE Labs
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. Neither the name of the project nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 */
35
36 /* This file contains a parser for FreeS/WAN-style ipsec.secrets RSA keys. */
37
38 #include "config.h"
39
40 #include <stdio.h>
41 #include <stdarg.h>
42 #include <string.h>
43 #include <errno.h>
44 #include <unistd.h>
45
46 #ifdef HAVE_STDARG_H
47 #include <stdarg.h>
48 #else
49 #include <varargs.h>
50 #endif
51
52 #include <netdb.h>
53 #include <netinet/in.h>
54 #include <sys/socket.h>
55 #include <arpa/inet.h>
56 #include <sys/types.h>
57
58 #include <sys/stat.h>
59 #include <unistd.h>
60
61 #include <openssl/bn.h>
62 #include <openssl/rsa.h>
63
64 #include "misc.h"
65 #include "vmbuf.h"
66 #include "plog.h"
67 #include "oakley.h"
68 #include "isakmp_var.h"
69 #include "handler.h"
70 #include "crypto_openssl.h"
71 #include "sockmisc.h"
72 #include "rsalist.h"
73
74 extern void prsaerror(const char *str, ...);
75 extern int prsawrap (void);
76 extern int prsalex (void);
77
78 extern char *prsatext;
79 extern int prsa_cur_lineno;
80 extern char *prsa_cur_fname;
81 extern FILE *prsain;
82
83 int prsa_cur_lineno = 0;
84 char *prsa_cur_fname = NULL;
85 struct genlist *prsa_cur_list = NULL;
86 enum rsa_key_type prsa_cur_type = RSA_TYPE_ANY;
87
88 static RSA *rsa_cur;
89
90 static BIGNUM *bn_n = NULL; /* Modulus */
91 static BIGNUM *bn_e = NULL; /* Public Exponent */
92 static BIGNUM *bn_d = NULL; /* Private Exponent */
93 static BIGNUM *bn_p = NULL; /* Prime1 */
94 static BIGNUM *bn_q = NULL; /* Prime2 */
95 static BIGNUM *bn_dmp1 = NULL; /* Exponent1 */
96 static BIGNUM *bn_dmq1 = NULL; /* Exponent2 */
97 static BIGNUM *bn_iqmp = NULL; /* Coefficient */
98
99 void
prsaerror(const char * s,...)100 prsaerror(const char *s, ...)
101 {
102 char fmt[512];
103
104 va_list ap;
105 #ifdef HAVE_STDARG_H
106 va_start(ap, s);
107 #else
108 va_start(ap);
109 #endif
110 snprintf(fmt, sizeof(fmt), "%s:%d: %s",
111 prsa_cur_fname, prsa_cur_lineno, s);
112 plogv(LLV_ERROR, LOCATION, NULL, fmt, ap);
113 va_end(ap);
114 }
115
116 void
prsawarning(const char * s,...)117 prsawarning(const char *s, ...)
118 {
119 char fmt[512];
120
121 va_list ap;
122 #ifdef HAVE_STDARG_H
123 va_start(ap, s);
124 #else
125 va_start(ap);
126 #endif
127 snprintf(fmt, sizeof(fmt), "%s:%d: %s",
128 prsa_cur_fname, prsa_cur_lineno, s);
129 plogv(LLV_WARNING, LOCATION, NULL, fmt, ap);
130 va_end(ap);
131 }
132
133 int
prsawrap()134 prsawrap()
135 {
136 return 1;
137 }
138 %}
139 %union {
140 BIGNUM *bn;
141 RSA *rsa;
142 char *chr;
143 long num;
144 struct netaddr *naddr;
145 }
146
147 %token COLON HEX
148 %token OBRACE EBRACE COLON HEX
149 %token TAG_RSA TAG_PUB TAG_PSK
150 %token MODULUS PUBLIC_EXPONENT PRIVATE_EXPONENT
151 %token PRIME1 PRIME2 EXPONENT1 EXPONENT2 COEFFICIENT
152 %token ADDR4 ADDR6 ADDRANY SLASH NUMBER BASE64
153
154 %type <bn> HEX
155 %type <num> NUMBER
156 %type <chr> ADDR4 ADDR6 BASE64
157
158 %type <rsa> rsa_statement
159 %type <num> prefix
160 %type <naddr> addr4 addr6 addr
161
162 %%
163 statements:
164 statements statement
165 | statement
166 ;
167
168 statement:
169 addr addr COLON rsa_statement
170 {
171 rsa_key_insert(prsa_cur_list, $1, $2, $4);
172 }
173 | addr COLON rsa_statement
174 {
175 rsa_key_insert(prsa_cur_list, NULL, $1, $3);
176 }
177 | COLON rsa_statement
178 {
179 rsa_key_insert(prsa_cur_list, NULL, NULL, $2);
180 }
181 ;
182
183 rsa_statement:
184 TAG_RSA OBRACE params EBRACE
185 {
186 if (prsa_cur_type == RSA_TYPE_PUBLIC) {
187 prsawarning("Using private key for public key purpose.\n");
188 if (!bn_n || !bn_e) {
189 prsaerror("Either of mandatory public key parameters "
190 " - n, d - are missing!\n");
191 YYABORT;
192 } else if (1 != RSA_set0_key(rsa_cur, bn_n, bn_e, NULL)) {
193 prsaerror("Invalid parameters. Public key not set up!\n");
194 YYABORT;
195 }
196 } else {
197 if (!bn_n || !bn_e || !bn_d) {
198 prsaerror("Either of mandatory private key parameters "
199 "- n, e, d -- are missing!\n");
200 YYABORT;
201 } else if (1 != RSA_set0_key(rsa_cur, bn_n, bn_e, bn_d)) {
202 prsaerror("Can not use mandatory private key parameters!\n");
203 YYABORT;
204 } else if (!bn_p || !bn_q || !bn_dmp1 || !bn_dmq1 || !bn_iqmp) {
205 /* If any of the suplementary parameters is missing, continue
206 * without setting them up.
207 */
208 } else if (1 != RSA_set0_factors(rsa_cur, bn_p, bn_q)) {
209 prsaerror("Invalid p or q parameter. Private key not set up!\n");
210 YYABORT;
211 } else if (1 != RSA_set0_crt_params(rsa_cur, bn_dmp1, bn_dmq1, bn_iqmp)) {
212 prsaerror("Invalid dmp1, dmq1 or iqmp parameters. "
213 "Private key not set up!\n");
214 YYABORT;
215 }
216 }
217 $$ = rsa_cur;
218 rsa_cur = RSA_new();
219 }
220 | TAG_PUB BASE64
221 {
222 if (prsa_cur_type == RSA_TYPE_PRIVATE) {
223 prsaerror("Public key in private-key file!\n");
224 YYABORT;
225 }
226 $$ = base64_pubkey2rsa($2);
227 free($2);
228 }
229 | TAG_PUB HEX
230 {
231 if (prsa_cur_type == RSA_TYPE_PRIVATE) {
232 prsaerror("Public key in private-key file!\n");
233 YYABORT;
234 }
235 $$ = bignum_pubkey2rsa($2);
236 }
237 ;
238
239 addr:
240 addr4
241 | addr6
242 | ADDRANY
243 {
244 $$ = NULL;
245 }
246 ;
247
248 addr4:
249 ADDR4 prefix
250 {
251 int err;
252 struct sockaddr_in *sap;
253 struct addrinfo hints, *res;
254
255 if ($2 == -1) $2 = 32;
256 if ($2 < 0 || $2 > 32) {
257 prsaerror ("Invalid IPv4 prefix\n");
258 YYABORT;
259 }
260 $$ = calloc (sizeof(struct netaddr), 1);
261 $$->prefix = $2;
262 sap = (struct sockaddr_in *)(&$$->sa);
263 memset(&hints, 0, sizeof(hints));
264 hints.ai_family = AF_INET;
265 hints.ai_flags = AI_NUMERICHOST;
266 err = getaddrinfo($1, NULL, &hints, &res);
267 if (err < 0) {
268 prsaerror("getaddrinfo(%s): %s\n", $1, gai_strerror(err));
269 YYABORT;
270 }
271 memcpy(sap, res->ai_addr, res->ai_addrlen);
272 freeaddrinfo(res);
273 free($1);
274 }
275 ;
276
277 addr6:
278 ADDR6 prefix
279 {
280 int err;
281 struct sockaddr_in6 *sap;
282 struct addrinfo hints, *res;
283
284 if ($2 == -1) $2 = 128;
285 if ($2 < 0 || $2 > 128) {
286 prsaerror ("Invalid IPv6 prefix\n");
287 YYABORT;
288 }
289 $$ = calloc (sizeof(struct netaddr), 1);
290 $$->prefix = $2;
291 sap = (struct sockaddr_in6 *)(&$$->sa);
292 memset(&hints, 0, sizeof(hints));
293 hints.ai_family = AF_INET6;
294 hints.ai_flags = AI_NUMERICHOST;
295 err = getaddrinfo($1, NULL, &hints, &res);
296 if (err < 0) {
297 prsaerror("getaddrinfo(%s): %s\n", $1, gai_strerror(err));
298 YYABORT;
299 }
300 memcpy(sap, res->ai_addr, res->ai_addrlen);
301 freeaddrinfo(res);
302 free($1);
303 }
304 ;
305
306 prefix:
307 /* nothing */ { $$ = -1; }
308 | SLASH NUMBER { $$ = $2; }
309 ;
310 params:
311 params param
312 | param
313 ;
314
315 param:
316 MODULUS COLON HEX
317 {
318 if (bn_n) {
319 prsaerror("Modulus already defined\n");
320 YYABORT;
321 } else {
322 bn_n = $3;
323 }
324 }
325 | PUBLIC_EXPONENT COLON HEX
326 {
327 if (bn_e) {
328 prsaerror("PublicExponent already defined\n");
329 YYABORT;
330 } else {
331 bn_e = $3;
332 }
333 }
334 | PRIVATE_EXPONENT COLON HEX
335 {
336 if (bn_d) {
337 prsaerror("PrivateExponent already defined\n");
338 YYABORT;
339 } else {
340 bn_d = $3;
341 }
342 }
343 | PRIME1 COLON HEX
344 {
345 if (bn_p) {
346 prsaerror("Prime1 already defined\n");
347 YYABORT;
348 } else {
349 bn_p = $3;
350 }
351 }
352 | PRIME2 COLON HEX
353 {
354 if (bn_q) {
355 prsaerror("Prime2 already defined\n");
356 YYABORT;
357 } else {
358 bn_q = $3;
359 }
360 }
361 | EXPONENT1 COLON HEX
362 {
363 if (bn_dmp1) {
364 prsaerror("Exponent1 already defined\n");
365 YYABORT;
366 } else {
367 bn_dmp1 = $3;
368 }
369 }
370 | EXPONENT2 COLON HEX
371 {
372 if (bn_dmq1) {
373 prsaerror("Exponent2 already defined\n");
374 YYABORT;
375 } else {
376 bn_dmq1 = $3;
377 }
378 }
379 | COEFFICIENT COLON HEX
380 {
381 if (bn_iqmp) {
382 prsaerror("Coefficient already defined\n");
383 YYABORT;
384 } else {
385 bn_iqmp = $3;
386 }
387 }
388 ;
389 %%
390
391 int prsaparse(void);
392
393 int
prsa_parse_file(struct genlist * list,char * fname,enum rsa_key_type type)394 prsa_parse_file(struct genlist *list, char *fname, enum rsa_key_type type)
395 {
396 FILE *fp = NULL;
397 int ret;
398
399 if (!fname)
400 return -1;
401 if (type == RSA_TYPE_PRIVATE) {
402 struct stat st;
403 if (stat(fname, &st) < 0)
404 return -1;
405 if (st.st_mode & (S_IRWXG | S_IRWXO)) {
406 plog(LLV_ERROR, LOCATION, NULL,
407 "Too slack permissions on private key '%s'\n",
408 fname);
409 plog(LLV_ERROR, LOCATION, NULL,
410 "Should be at most 0600, now is 0%o\n",
411 st.st_mode & 0777);
412 return -1;
413 }
414 }
415 fp = fopen(fname, "r");
416 if (!fp)
417 return -1;
418 prsain = fp;
419 prsa_cur_lineno = 1;
420 prsa_cur_fname = fname;
421 prsa_cur_list = list;
422 prsa_cur_type = type;
423 rsa_cur = RSA_new();
424 ret = prsaparse();
425 if (rsa_cur) {
426 RSA_free(rsa_cur);
427 rsa_cur = NULL;
428 }
429 fclose (fp);
430 prsain = NULL;
431 return ret;
432 }
433