xref: /netbsd-src/crypto/external/bsd/netpgp/dist/src/lib/netpgp.c (revision 63d4abf06d37aace2f9e41a494102a64fe3abddb)
1 /*-
2  * Copyright (c) 2009 The NetBSD Foundation, Inc.
3  * All rights reserved.
4  *
5  * This code is derived from software contributed to The NetBSD Foundation
6  * by Alistair Crooks (agc@NetBSD.org)
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
18  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
21  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27  * POSSIBILITY OF SUCH DAMAGE.
28  */
29 #include "config.h"
30 
31 #ifdef HAVE_SYS_CDEFS_H
32 #include <sys/cdefs.h>
33 #endif
34 
35 #if defined(__NetBSD__)
36 __COPYRIGHT("@(#) Copyright (c) 2009 The NetBSD Foundation, Inc. All rights reserved.");
37 __RCSID("$NetBSD: netpgp.c,v 1.40 2010/02/23 01:24:44 agc Exp $");
38 #endif
39 
40 #include <sys/types.h>
41 #include <sys/stat.h>
42 #include <sys/param.h>
43 #include <sys/mman.h>
44 
45 #ifdef HAVE_SYS_RESOURCE_H
46 #include <sys/resource.h>
47 #endif
48 
49 #ifdef HAVE_FCNTL_H
50 #include <fcntl.h>
51 #endif
52 
53 #include <errno.h>
54 #include <regex.h>
55 #include <stdarg.h>
56 #include <stdlib.h>
57 #include <string.h>
58 #include <time.h>
59 
60 #ifdef HAVE_UNISTD_H
61 #include <unistd.h>
62 #endif
63 
64 #include <errno.h>
65 
66 #ifdef HAVE_LIMITS_H
67 #include <limits.h>
68 #endif
69 
70 #include <netpgp.h>
71 
72 #include "packet.h"
73 #include "packet-parse.h"
74 #include "keyring.h"
75 #include "errors.h"
76 #include "packet-show.h"
77 #include "create.h"
78 #include "netpgpsdk.h"
79 #include "memory.h"
80 #include "validate.h"
81 #include "readerwriter.h"
82 #include "netpgpdefs.h"
83 #include "crypto.h"
84 #include "ops-ssh.h"
85 #include "defs.h"
86 
87 /* read any gpg config file */
88 static int
89 conffile(netpgp_t *netpgp, char *homedir, char *userid, size_t length)
90 {
91 	regmatch_t	 matchv[10];
92 	regex_t		 keyre;
93 	char		 buf[BUFSIZ];
94 	FILE		*fp;
95 
96 	__OPS_USED(netpgp);
97 	(void) snprintf(buf, sizeof(buf), "%s/gpg.conf", homedir);
98 	if ((fp = fopen(buf, "r")) == NULL) {
99 		return 0;
100 	}
101 	(void) memset(&keyre, 0x0, sizeof(keyre));
102 	(void) regcomp(&keyre, "^[ \t]*default-key[ \t]+([0-9a-zA-F]+)",
103 		REG_EXTENDED);
104 	while (fgets(buf, sizeof(buf), fp) != NULL) {
105 		if (regexec(&keyre, buf, 10, matchv, 0) == 0) {
106 			(void) memcpy(userid, &buf[(int)matchv[1].rm_so],
107 				MIN((unsigned)(matchv[1].rm_eo -
108 						matchv[1].rm_so), length));
109 			if (netpgp->passfp == NULL) {
110 				(void) fprintf(stderr,
111 				"netpgp: default key set to \"%.*s\"\n",
112 				(int)(matchv[1].rm_eo - matchv[1].rm_so),
113 				&buf[(int)matchv[1].rm_so]);
114 			}
115 		}
116 	}
117 	(void) fclose(fp);
118 	return 1;
119 }
120 
121 /* small function to pretty print an 8-character raw userid */
122 static char    *
123 userid_to_id(const unsigned char *userid, char *id)
124 {
125 	static const char *hexes = "0123456789abcdef";
126 	int		   i;
127 
128 	for (i = 0; i < 8 ; i++) {
129 		id[i * 2] = hexes[(unsigned)(userid[i] & 0xf0) >> 4];
130 		id[(i * 2) + 1] = hexes[userid[i] & 0xf];
131 	}
132 	id[8 * 2] = 0x0;
133 	return id;
134 }
135 
136 /* print out the successful signature information */
137 static void
138 resultp(__ops_io_t *io,
139 	const char *f,
140 	__ops_validation_t *res,
141 	__ops_keyring_t *ring)
142 {
143 	const __ops_key_t	*pubkey;
144 	unsigned		 from;
145 	unsigned		 i;
146 	time_t			 t;
147 	char			 id[MAX_ID_LENGTH + 1];
148 
149 	for (i = 0; i < res->validc; i++) {
150 		(void) fprintf(io->res,
151 			"Good signature for %s made %s",
152 			(f) ? f : "<stdin>",
153 			ctime(&res->valid_sigs[i].birthtime));
154 		if (res->duration > 0) {
155 			t = res->birthtime + res->duration;
156 			(void) fprintf(io->res, "Valid until %s", ctime(&t));
157 		}
158 		(void) fprintf(io->res,
159 			"using %s key %s\n",
160 			__ops_show_pka(res->valid_sigs[i].key_alg),
161 			userid_to_id(res->valid_sigs[i].signer_id, id));
162 		from = 0;
163 		pubkey = __ops_getkeybyid(io, ring,
164 			(const unsigned char *) res->valid_sigs[i].signer_id,
165 			&from);
166 		__ops_print_keydata(io, pubkey, "pub", &pubkey->key.pubkey);
167 	}
168 }
169 
170 /* check there's enough space in the arrays */
171 static int
172 size_arrays(netpgp_t *netpgp, unsigned needed)
173 {
174 	char	**temp;
175 
176 	if (netpgp->size == 0) {
177 		/* only get here first time around */
178 		netpgp->size = needed;
179 		if ((netpgp->name = calloc(sizeof(char *), needed)) == NULL) {
180 			(void) fprintf(stderr, "size_arrays: bad alloc\n");
181 			return 0;
182 		}
183 		if ((netpgp->value = calloc(sizeof(char *), needed)) == NULL) {
184 			free(netpgp->name);
185 			(void) fprintf(stderr, "size_arrays: bad alloc\n");
186 			return 0;
187 		}
188 	} else if (netpgp->c == netpgp->size) {
189 		/* only uses 'needed' when filled array */
190 		netpgp->size += needed;
191 		temp = realloc(netpgp->name, sizeof(char *) * needed);
192 		if (temp == NULL) {
193 			(void) fprintf(stderr, "size_arrays: bad alloc\n");
194 			return 0;
195 		}
196 		netpgp->name = temp;
197 		temp = realloc(netpgp->value, sizeof(char *) * needed);
198 		if (temp == NULL) {
199 			(void) fprintf(stderr, "size_arrays: bad alloc\n");
200 			return 0;
201 		}
202 		netpgp->value = temp;
203 	}
204 	return 1;
205 }
206 
207 /* find the name in the array */
208 static int
209 findvar(netpgp_t *netpgp, const char *name)
210 {
211 	unsigned	i;
212 
213 	for (i = 0 ; i < netpgp->c && strcmp(netpgp->name[i], name) != 0; i++) {
214 	}
215 	return (i == netpgp->c) ? -1 : (int)i;
216 }
217 
218 /* read a keyring and return it */
219 static void *
220 readkeyring(netpgp_t *netpgp, const char *name)
221 {
222 	__ops_keyring_t	*keyring;
223 	const unsigned	 noarmor = 0;
224 	char		 f[MAXPATHLEN];
225 	char		*filename;
226 	char		*homedir;
227 
228 	homedir = netpgp_getvar(netpgp, "homedir");
229 	if ((filename = netpgp_getvar(netpgp, name)) == NULL) {
230 		(void) snprintf(f, sizeof(f), "%s/%s.gpg", homedir, name);
231 		filename = f;
232 	}
233 	if ((keyring = calloc(1, sizeof(*keyring))) == NULL) {
234 		(void) fprintf(stderr, "readkeyring: bad alloc\n");
235 		return NULL;
236 	}
237 	if (!__ops_keyring_fileread(keyring, noarmor, filename)) {
238 		free(keyring);
239 		(void) fprintf(stderr, "Can't read %s %s\n", name, filename);
240 		return NULL;
241 	}
242 	netpgp_setvar(netpgp, name, filename);
243 	return keyring;
244 }
245 
246 /* read keys from ssh key files */
247 static int
248 readsshkeys(netpgp_t *netpgp, char *homedir)
249 {
250 	__ops_keyring_t	*pubring;
251 	__ops_keyring_t	*secring;
252 	char		 f[MAXPATHLEN];
253 	char		*filename;
254 
255 	if ((filename = netpgp_getvar(netpgp, "sshkeyfile")) == NULL) {
256 		(void) snprintf(f, sizeof(f), "%s/.ssh/is_rsa.pub", homedir);
257 		filename = f;
258 	}
259 	if ((pubring = calloc(1, sizeof(*pubring))) == NULL) {
260 		(void) fprintf(stderr, "readsshkeys: bad alloc\n");
261 		return 0;
262 	}
263 	if (!__ops_ssh2_readkeys(netpgp->io, pubring, NULL, filename, NULL)) {
264 		free(pubring);
265 		(void) fprintf(stderr, "readsshkeys: can't read %s\n",
266 				filename);
267 		return 0;
268 	}
269 	if (netpgp->pubring == NULL) {
270 		netpgp->pubring = pubring;
271 	} else {
272 		__ops_append_keyring(netpgp->pubring, pubring);
273 	}
274 	netpgp_setvar(netpgp, "sshpubfile", filename);
275 	/* try to take the ".pub" off the end */
276 	if (filename == f) {
277 		f[strlen(f) - 4] = 0x0;
278 	} else {
279 		(void) snprintf(f, sizeof(f), "%.*s",
280 				(int)strlen(filename) - 4, filename);
281 		filename = f;
282 	}
283 	if ((secring = calloc(1, sizeof(*secring))) == NULL) {
284 		(void) fprintf(stderr, "readsshkeys: bad alloc\n");
285 		return 0;
286 	}
287 	if (__ops_ssh2_readkeys(netpgp->io, pubring, secring, NULL, filename)) {
288 		netpgp->secring = secring;
289 		netpgp_setvar(netpgp, "sshsecfile", filename);
290 	} else {
291 		(void) fprintf(stderr, "readsshkeys: can't read sec %s (%d)\n",
292 				filename, errno);
293 	}
294 	return 1;
295 }
296 
297 /* set ssh uid to first one in ring */
298 static void
299 set_ssh_userid(__ops_keyring_t *pubring, char *id, size_t len, int last)
300 {
301 	unsigned char	*src;
302 	int		 i;
303 	int		 n;
304 
305 	(void) memset(id, 0x0, len);
306 	src = pubring->keys[(last) ? pubring->keyc - 1 : 0].key_id;
307 	for (i = 0, n = 0 ; i < OPS_KEY_ID_SIZE ; i += 2) {
308 		n += snprintf(&id[n], len - n, "%02x%02x", src[i], src[i + 1]);
309 	}
310 	id[n] = 0x0;
311 }
312 
313 /* get expiration in seconds */
314 static uint64_t
315 get_duration(char *s)
316 {
317 	struct tm	 tm;
318 	uint64_t	 now;
319 	char		*mult;
320 
321 	if (s == NULL) {
322 		return 0;
323 	}
324 	now = strtoull(s, NULL, 10);
325 	if ((mult = strchr("hdwmy", s[strlen(s) - 1])) != NULL) {
326 		switch(*mult) {
327 		case 'h':
328 			return now * 60 * 60;
329 		case 'd':
330 			return now * 60 * 60 * 24;
331 		case 'w':
332 			return now * 60 * 60 * 24 * 7;
333 		case 'm':
334 			return now * 60 * 60 * 24 * 31;
335 		case 'y':
336 			return now * 60 * 60 * 24 * 365;
337 		}
338 	}
339 	if (strptime(s, "%Y-%m-%d", &tm) != NULL) {
340 		return mktime(&tm);
341 	}
342 	if (strptime(s, "%Y/%m/%d", &tm) != NULL) {
343 		return mktime(&tm);
344 	}
345 	return (uint64_t)strtoll(s, NULL, 10);
346 }
347 
348 /* get birthtime in seconds */
349 static int64_t
350 get_birthtime(char *s)
351 {
352 	struct tm	 tm;
353 
354 	if (s == NULL) {
355 		return time(NULL);
356 	}
357 	if (strptime(s, "%Y-%m-%d", &tm) != NULL) {
358 		return mktime(&tm);
359 	}
360 	if (strptime(s, "%Y/%m/%d", &tm) != NULL) {
361 		return mktime(&tm);
362 	}
363 	return (uint64_t)strtoll(s, NULL, 10);
364 }
365 
366 /***************************************************************************/
367 /* exported functions start here */
368 /***************************************************************************/
369 
370 /* initialise a netpgp_t structure */
371 int
372 netpgp_init(netpgp_t *netpgp)
373 {
374 	__ops_io_t	*io;
375 	char		 id[MAX_ID_LENGTH];
376 	char		*homedir;
377 	char		*userid;
378 	char		*stream;
379 	char		*passfd;
380 	char		*results;
381 	int		 coredumps;
382 	int		 last;
383 
384 #ifdef HAVE_SYS_RESOURCE_H
385 	struct rlimit	limit;
386 
387 	coredumps = netpgp_getvar(netpgp, "coredumps") != NULL;
388 	if (!coredumps) {
389 		(void) memset(&limit, 0x0, sizeof(limit));
390 		if (setrlimit(RLIMIT_CORE, &limit) != 0) {
391 			(void) fprintf(stderr,
392 			"netpgp: warning - can't turn off core dumps\n");
393 			coredumps = 1;
394 		}
395 	}
396 #else
397 	coredumps = 1;
398 #endif
399 	if ((io = calloc(1, sizeof(*io))) == NULL) {
400 		(void) fprintf(stderr, "netpgp_init: bad alloc\n");
401 		return 0;
402 	}
403 	io->outs = stdout;
404 	if ((stream = netpgp_getvar(netpgp, "stdout")) != NULL &&
405 	    strcmp(stream, "stderr") == 0) {
406 		io->outs = stderr;
407 	}
408 	io->errs = stderr;
409 	if ((stream = netpgp_getvar(netpgp, "stderr")) != NULL &&
410 	    strcmp(stream, "stdout") == 0) {
411 		io->errs = stdout;
412 	}
413 	if ((results = netpgp_getvar(netpgp, "results")) == NULL) {
414 		io->res = io->errs;
415 	} else if ((io->res = fopen(results, "w")) == NULL) {
416 		(void) fprintf(io->errs, "Can't open results %s for writing\n",
417 			results);
418 		free(io);
419 		return 0;
420 	}
421 	netpgp->io = io;
422 	if ((passfd = netpgp_getvar(netpgp, "pass-fd")) != NULL &&
423 	    (netpgp->passfp = fdopen(atoi(passfd), "r")) == NULL) {
424 		(void) fprintf(io->errs, "Can't open fd %s for reading\n",
425 			passfd);
426 		return 0;
427 	}
428 	if (coredumps) {
429 		(void) fprintf(io->errs,
430 			"netpgp: warning: core dumps enabled\n");
431 	}
432 	if ((homedir = netpgp_getvar(netpgp, "homedir")) == NULL) {
433 		(void) fprintf(io->errs, "netpgp: bad homedir\n");
434 		return 0;
435 	}
436 	/* read from either gpg files or ssh keys */
437 	if (netpgp_getvar(netpgp, "ssh keys") == NULL) {
438 		if ((userid = netpgp_getvar(netpgp, "userid")) == NULL) {
439 			(void) memset(id, 0x0, sizeof(id));
440 			(void) conffile(netpgp, homedir, id, sizeof(id));
441 			if (id[0] != 0x0) {
442 				netpgp_setvar(netpgp, "userid", userid = id);
443 			}
444 		}
445 		if (userid == NULL) {
446 			if (netpgp_getvar(netpgp, "need userid") != NULL) {
447 				(void) fprintf(io->errs,
448 						"Cannot find user id\n");
449 				return 0;
450 			}
451 		} else {
452 			(void) netpgp_setvar(netpgp, "userid", userid);
453 		}
454 		netpgp->pubring = readkeyring(netpgp, "pubring");
455 		if (netpgp->pubring == NULL) {
456 			(void) fprintf(io->errs, "Can't read pub keyring\n");
457 			return 0;
458 		}
459 		netpgp->secring = readkeyring(netpgp, "secring");
460 		if (netpgp->secring == NULL) {
461 			(void) fprintf(io->errs, "Can't read sec keyring\n");
462 			return 0;
463 		}
464 	} else {
465 		last = (netpgp->pubring != NULL);
466 		if (!readsshkeys(netpgp, homedir)) {
467 			(void) fprintf(io->errs, "Can't read ssh pub key\n");
468 			return 0;
469 		}
470 		if ((userid = netpgp_getvar(netpgp, "userid")) == NULL) {
471 			set_ssh_userid(netpgp->pubring, id, sizeof(id), last);
472 			netpgp_setvar(netpgp, "userid", userid = id);
473 		}
474 		if (userid == NULL) {
475 			if (netpgp_getvar(netpgp, "need userid") != NULL) {
476 				(void) fprintf(io->errs,
477 						"Cannot find user id\n");
478 				return 0;
479 			}
480 		} else {
481 			(void) netpgp_setvar(netpgp, "userid", userid);
482 		}
483 	}
484 	return 1;
485 }
486 
487 /* finish off with the netpgp_t struct */
488 int
489 netpgp_end(netpgp_t *netpgp)
490 {
491 	unsigned	i;
492 
493 	for (i = 0 ; i < netpgp->c ; i++) {
494 		if (netpgp->name[i] != NULL) {
495 			free(netpgp->name[i]);
496 		}
497 		if (netpgp->value[i] != NULL) {
498 			free(netpgp->value[i]);
499 		}
500 	}
501 	if (netpgp->name != NULL) {
502 		free(netpgp->name);
503 	}
504 	if (netpgp->value != NULL) {
505 		free(netpgp->value);
506 	}
507 	if (netpgp->pubring != NULL) {
508 		__ops_keyring_free(netpgp->pubring);
509 	}
510 	if (netpgp->secring != NULL) {
511 		__ops_keyring_free(netpgp->secring);
512 	}
513 	free(netpgp->io);
514 	return 1;
515 }
516 
517 /* list the keys in a keyring */
518 int
519 netpgp_list_keys(netpgp_t *netpgp)
520 {
521 	return __ops_keyring_list(netpgp->io, netpgp->pubring);
522 }
523 
524 DEFINE_ARRAY(strings_t, char *);
525 
526 #ifndef HKP_VERSION
527 #define HKP_VERSION	1
528 #endif
529 
530 /* find and list some keys in a keyring */
531 int
532 netpgp_match_keys(netpgp_t *netpgp, char *name, const char *fmt, void *vp)
533 {
534 	const __ops_key_t	*key;
535 	unsigned		 k;
536 	strings_t		 pubs;
537 	FILE			*fp = (FILE *)vp;
538 
539 	(void) memset(&pubs, 0x0, sizeof(pubs));
540 	k = 0;
541 	do {
542 		key = __ops_getnextkeybyname(netpgp->io, netpgp->pubring,
543 						name, &k);
544 		if (key != NULL) {
545 			ALLOC(char *, pubs.v, pubs.size, pubs.c, 10, 10,
546 					"netpgp_match_keys", return 0);
547 			if (strcmp(fmt, "mr") == 0) {
548 				__ops_hkp_sprint_keydata(
549 						key, &pubs.v[pubs.c],
550 						&key->key.pubkey);
551 			} else {
552 				__ops_sprint_keydata(
553 						key, &pubs.v[pubs.c],
554 						"pub",
555 						&key->key.pubkey);
556 			}
557 			pubs.c += 1;
558 			k += 1;
559 		}
560 	} while (key != NULL);
561 	if (strcmp(fmt, "mr") == 0) {
562 		(void) fprintf(fp, "info:%d:%d\n", HKP_VERSION, pubs.c);
563 	} else {
564 		(void) fprintf(fp, "%d keys found\n", pubs.c);
565 	}
566 	for (k = 0 ; k < pubs.c ; k++) {
567 		(void) fprintf(fp, "%s", pubs.v[k]);
568 		free(pubs.v[k]);
569 	}
570 	free(pubs.v);
571 	return pubs.c;
572 }
573 
574 /* find and list some public keys in a keyring */
575 int
576 netpgp_match_pubkeys(netpgp_t *netpgp, char *name, void *vp)
577 {
578 	const __ops_key_t	*key;
579 	unsigned		 k;
580 	strings_t		 pubs;
581 	FILE			*fp = (FILE *)vp;
582 
583 	(void) memset(&pubs, 0x0, sizeof(pubs));
584 	do {
585 		key = __ops_getnextkeybyname(netpgp->io, netpgp->pubring,
586 						name, &k);
587 		if (key != NULL) {
588 			char	out[1024 * 64];
589 
590 			ALLOC(char *, pubs.v, pubs.size, pubs.c, 10, 10,
591 					"netpgp_match_pubkeys", return 0);
592 			(void) __ops_sprint_pubkey(key, out, sizeof(out));
593 			pubs.v[pubs.c++] = strdup(out);
594 			k += 1;
595 		}
596 	} while (key != NULL);
597 	(void) fprintf(fp, "info:%d:%d\n", HKP_VERSION, pubs.c);
598 	for (k = 0 ; k < pubs.c ; k++) {
599 		(void) fprintf(fp, "%s", pubs.v[k]);
600 		free(pubs.v[k]);
601 	}
602 	free(pubs.v);
603 	return pubs.c;
604 }
605 
606 /* find a key in a keyring */
607 int
608 netpgp_find_key(netpgp_t *netpgp, char *id)
609 {
610 	__ops_io_t	*io;
611 
612 	io = netpgp->io;
613 	if (id == NULL) {
614 		(void) fprintf(io->errs, "NULL id to search for\n");
615 		return 0;
616 	}
617 	return __ops_getkeybyname(netpgp->io, netpgp->pubring, id) != NULL;
618 }
619 
620 /* get a key in a keyring */
621 char *
622 netpgp_get_key(netpgp_t *netpgp, const char *id)
623 {
624 	const __ops_key_t	*key;
625 	__ops_io_t		*io;
626 	char			*newkey;
627 
628 	io = netpgp->io;
629 	if (id == NULL) {
630 		/* just get the default userid */
631 		id = netpgp_getvar(netpgp, "userid");
632 	}
633 	key = __ops_getkeybyname(netpgp->io, netpgp->pubring, id);
634 	if (key == NULL) {
635 		(void) fprintf(io->errs, "Can't find key '%s'\n", id);
636 		return NULL;
637 	}
638 	return (__ops_sprint_keydata(key, &newkey, "pub",
639 				&key->key.pubkey) > 0) ? newkey : NULL;
640 }
641 
642 /* export a given key */
643 int
644 netpgp_export_key(netpgp_t *netpgp, char *userid)
645 {
646 	const __ops_key_t	*keypair;
647 	__ops_io_t		*io;
648 
649 	io = netpgp->io;
650 	if (userid == NULL) {
651 		userid = netpgp_getvar(netpgp, "userid");
652 	}
653 	keypair = __ops_getkeybyname(io, netpgp->pubring, userid);
654 	if (keypair == NULL) {
655 		(void) fprintf(io->errs,
656 			"Cannot find own key \"%s\" in keyring\n", userid);
657 		return 0;
658 	}
659 	return __ops_export_key(keypair, NULL);
660 }
661 
662 /* import a key into our keyring */
663 int
664 netpgp_import_key(netpgp_t *netpgp, char *f)
665 {
666 	const unsigned	noarmor = 0;
667 	const unsigned	armor = 1;
668 	__ops_io_t	*io;
669 	int		done;
670 
671 	io = netpgp->io;
672 	if ((done = __ops_keyring_fileread(netpgp->pubring, noarmor, f)) == 0) {
673 		done = __ops_keyring_fileread(netpgp->pubring, armor, f);
674 	}
675 	if (!done) {
676 		(void) fprintf(io->errs, "Cannot import key from file %s\n",
677 				f);
678 		return 0;
679 	}
680 	return __ops_keyring_list(io, netpgp->pubring);
681 }
682 
683 /* generate a new key */
684 int
685 netpgp_generate_key(netpgp_t *netpgp, char *id, int numbits)
686 {
687 	__ops_key_t		*keypair;
688 	__ops_userid_t		 uid;
689 	__ops_output_t		*create;
690 	const unsigned		 noarmor = 0;
691 	__ops_io_t		*io;
692 	char			*ringfile;
693 	int             	 fd;
694 
695 	(void) memset(&uid, 0x0, sizeof(uid));
696 	io = netpgp->io;
697 	/* generate a new key for 'id' */
698 	uid.userid = (unsigned char *) id;
699 	keypair = __ops_rsa_new_selfsign_key(numbits, 65537UL, &uid);
700 	if (keypair == NULL) {
701 		(void) fprintf(io->errs, "Cannot generate key\n");
702 		return 0;
703 	}
704 	/* write public key, and try to re-read it */
705 	ringfile = netpgp_getvar(netpgp, "pubring");
706 	fd = __ops_setup_file_append(&create, ringfile);
707 	if (!__ops_write_xfer_pubkey(create, keypair, noarmor)) {
708 		(void) fprintf(io->errs, "Cannot write pubkey\n");
709 		return 0;
710 	}
711 	__ops_teardown_file_write(create, fd);
712 	__ops_keyring_free(netpgp->pubring);
713 	if (!__ops_keyring_fileread(netpgp->pubring, noarmor, ringfile)) {
714 		(void) fprintf(io->errs, "Cannot read pubring %s\n", ringfile);
715 		return 0;
716 	}
717 	/* write secret key, and try to re-read it */
718 	ringfile = netpgp_getvar(netpgp, "sec ring file");
719 	fd = __ops_setup_file_append(&create, ringfile);
720 	if (!__ops_write_xfer_seckey(create, keypair, NULL, 0, noarmor)) {
721 		(void) fprintf(io->errs, "Cannot write seckey\n");
722 		return 0;
723 	}
724 	__ops_teardown_file_write(create, fd);
725 	__ops_keyring_free(netpgp->secring);
726 	if (!__ops_keyring_fileread(netpgp->secring, noarmor, ringfile)) {
727 		(void) fprintf(io->errs, "Can't read secring %s\n", ringfile);
728 		return 0;
729 	}
730 	__ops_keydata_free(keypair);
731 	return 1;
732 }
733 
734 /* encrypt a file */
735 int
736 netpgp_encrypt_file(netpgp_t *netpgp,
737 			const char *userid,
738 			const char *f,
739 			char *out,
740 			int armored)
741 {
742 	const __ops_key_t	*keypair;
743 	const unsigned		 overwrite = 1;
744 	const char		*suffix;
745 	__ops_io_t		*io;
746 	char			 outname[MAXPATHLEN];
747 
748 	io = netpgp->io;
749 	if (f == NULL) {
750 		(void) fprintf(io->errs,
751 			"netpgp_encrypt_file: no filename specified\n");
752 		return 0;
753 	}
754 	if (userid == NULL) {
755 		userid = netpgp_getvar(netpgp, "userid");
756 	}
757 	suffix = (armored) ? ".asc" : ".gpg";
758 	keypair = __ops_getkeybyname(io, netpgp->pubring, userid);
759 	if (keypair == NULL) {
760 		(void) fprintf(io->errs, "Userid '%s' not found in keyring\n",
761 					userid);
762 		return 0;
763 	}
764 	if (out == NULL) {
765 		(void) snprintf(outname, sizeof(outname), "%s%s", f, suffix);
766 		out = outname;
767 	}
768 	return (int)__ops_encrypt_file(io, f, out, keypair, (unsigned)armored,
769 					overwrite);
770 }
771 
772 #define ARMOR_HEAD	"-----BEGIN PGP MESSAGE-----\r\n"
773 
774 /* decrypt a file */
775 int
776 netpgp_decrypt_file(netpgp_t *netpgp, const char *f, char *out, int armored)
777 {
778 	const unsigned	 overwrite = 1;
779 	__ops_io_t	*io;
780 	unsigned	 realarmour;
781 	FILE		*fp;
782 	char		 buf[BUFSIZ];
783 
784 	io = netpgp->io;
785 	if (f == NULL) {
786 		(void) fprintf(io->errs,
787 			"netpgp_decrypt_file: no filename specified\n");
788 		return 0;
789 	}
790 	realarmour = (unsigned)armored;
791 	if ((fp = fopen(f, "r")) == NULL) {
792 		(void) fprintf(io->errs,
793 			"netpgp_decrypt_file: can't open '%s'\n", f);
794 		return 0;
795 	}
796 	if (fgets(buf, sizeof(buf), fp) == NULL) {
797 		realarmour = 0;
798 	} else {
799 		realarmour = (strcmp(buf, ARMOR_HEAD) == 0);
800 	}
801 	(void) fclose(fp);
802 	return __ops_decrypt_file(netpgp->io, f, out, netpgp->secring,
803 				netpgp->pubring,
804 				(unsigned)realarmour, overwrite,
805 				netpgp->passfp, get_passphrase_cb);
806 }
807 
808 /* sign a file */
809 int
810 netpgp_sign_file(netpgp_t *netpgp,
811 		const char *userid,
812 		const char *f,
813 		char *out,
814 		int armored,
815 		int cleartext,
816 		int detached)
817 {
818 	const __ops_key_t	*keypair;
819 	const __ops_key_t	*pubkey;
820 	__ops_seckey_t		*seckey;
821 	const unsigned		 overwrite = 1;
822 	__ops_io_t		*io;
823 	char			*hashalg;
824 	int			 ret;
825 
826 	io = netpgp->io;
827 	if (f == NULL) {
828 		(void) fprintf(io->errs,
829 			"netpgp_sign_file: no filename specified\n");
830 		return 0;
831 	}
832 	if (userid == NULL) {
833 		userid = netpgp_getvar(netpgp, "userid");
834 	}
835 	/* get key with which to sign */
836 	keypair = __ops_getkeybyname(io, netpgp->secring, userid);
837 	if (keypair == NULL) {
838 		(void) fprintf(io->errs, "Userid '%s' not found in secring\n",
839 				userid);
840 		return 0;
841 	}
842 	ret = 1;
843 	do {
844 		if (netpgp->passfp == NULL) {
845 			/* print out the user id */
846 			pubkey = __ops_getkeybyname(io, netpgp->pubring, userid);
847 			if (pubkey == NULL) {
848 				(void) fprintf(io->errs,
849 					"netpgp: warning - using pubkey from secring\n");
850 				__ops_print_keydata(io, keypair, "pub",
851 					&keypair->key.seckey.pubkey);
852 			} else {
853 				__ops_print_keydata(io, pubkey, "pub", &pubkey->key.pubkey);
854 			}
855 		}
856 		if (netpgp_getvar(netpgp, "ssh keys") == NULL) {
857 			/* now decrypt key */
858 			seckey = __ops_decrypt_seckey(keypair, netpgp->passfp);
859 			if (seckey == NULL) {
860 				(void) fprintf(io->errs, "Bad passphrase\n");
861 			}
862 		} else {
863 			__ops_keyring_t	*secring;
864 
865 			secring = netpgp->secring;
866 			seckey = &secring->keys[0].key.seckey;
867 		}
868 	} while (seckey == NULL);
869 	/* sign file */
870 	hashalg = netpgp_getvar(netpgp, "hash");
871 	if (detached) {
872 		ret = __ops_sign_detached(io, f, out, seckey, hashalg,
873 				get_birthtime(netpgp_getvar(netpgp, "birthtime")),
874 				get_duration(netpgp_getvar(netpgp, "duration")));
875 	} else {
876 		ret = __ops_sign_file(io, f, out, seckey, hashalg,
877 				get_birthtime(netpgp_getvar(netpgp, "birthtime")),
878 				get_duration(netpgp_getvar(netpgp, "duration")),
879 				(unsigned)armored, (unsigned)cleartext,
880 				overwrite);
881 	}
882 	__ops_forget(seckey, sizeof(*seckey));
883 	return ret;
884 }
885 
886 /* verify a file */
887 int
888 netpgp_verify_file(netpgp_t *netpgp, const char *in, const char *out, int armored)
889 {
890 	__ops_validation_t	 result;
891 	__ops_io_t		*io;
892 
893 	(void) memset(&result, 0x0, sizeof(result));
894 	io = netpgp->io;
895 	if (in == NULL) {
896 		(void) fprintf(io->errs,
897 			"netpgp_verify_file: no filename specified\n");
898 		return 0;
899 	}
900 	if (__ops_validate_file(io, &result, in, out, armored,
901 						netpgp->pubring)) {
902 		resultp(io, in, &result, netpgp->pubring);
903 		return 1;
904 	}
905 	if (result.validc + result.invalidc + result.unknownc == 0) {
906 		(void) fprintf(io->errs,
907 		"\"%s\": No signatures found - is this a signed file?\n",
908 			in);
909 	} else if (result.invalidc == 0 && result.unknownc == 0) {
910 		(void) fprintf(io->errs,
911 			"\"%s\": file verification failure: invalid signature time\n", in);
912 	} else {
913 		(void) fprintf(io->errs,
914 "\"%s\": verification failure: %u invalid signatures, %u unknown signatures\n",
915 			in, result.invalidc, result.unknownc);
916 	}
917 	return 0;
918 }
919 
920 /* sign some memory */
921 int
922 netpgp_sign_memory(netpgp_t *netpgp,
923 		const char *userid,
924 		char *mem,
925 		size_t size,
926 		char *out,
927 		size_t outsize,
928 		const unsigned armored,
929 		const unsigned cleartext)
930 {
931 	const __ops_key_t	*keypair;
932 	const __ops_key_t	*pubkey;
933 	__ops_seckey_t		*seckey;
934 	__ops_memory_t		*signedmem;
935 	__ops_io_t		*io;
936 	char			*hashalg;
937 	int			 ret;
938 
939 	io = netpgp->io;
940 	if (mem == NULL) {
941 		(void) fprintf(io->errs,
942 			"netpgp_sign_memory: no memory to sign\n");
943 		return 0;
944 	}
945 	if (userid == NULL) {
946 		userid = netpgp_getvar(netpgp, "userid");
947 	}
948 	/* get key with which to sign */
949 	keypair = __ops_getkeybyname(io, netpgp->secring, userid);
950 	if (keypair == NULL) {
951 		(void) fprintf(io->errs, "Userid '%s' not found in keyring\n",
952 				userid);
953 		return 0;
954 	}
955 	ret = 1;
956 	do {
957 		if (netpgp->passfp == NULL) {
958 			/* print out the user id */
959 			pubkey = __ops_getkeybyname(io, netpgp->pubring, userid);
960 			if (pubkey == NULL) {
961 				(void) fprintf(io->errs,
962 					"netpgp: warning - using pubkey from secring\n");
963 				__ops_print_keydata(io, keypair, "pub",
964 					&keypair->key.seckey.pubkey);
965 			} else {
966 				__ops_print_keydata(io, pubkey, "pub", &pubkey->key.pubkey);
967 			}
968 		}
969 		/* now decrypt key */
970 		seckey = __ops_decrypt_seckey(keypair, netpgp->passfp);
971 		if (seckey == NULL) {
972 			(void) fprintf(io->errs, "Bad passphrase\n");
973 		}
974 	} while (seckey == NULL);
975 	/* sign file */
976 	(void) memset(out, 0x0, outsize);
977 	hashalg = netpgp_getvar(netpgp, "hash");
978 	signedmem = __ops_sign_buf(io, mem, size, seckey,
979 				get_birthtime(netpgp_getvar(netpgp, "birthtime")),
980 				get_duration(netpgp_getvar(netpgp, "duration")),
981 				hashalg, armored, cleartext);
982 	if (signedmem) {
983 		size_t	m;
984 
985 		m = MIN(__ops_mem_len(signedmem), outsize);
986 		(void) memcpy(out, __ops_mem_data(signedmem), m);
987 		__ops_memory_free(signedmem);
988 		ret = (int)m;
989 	} else {
990 		ret = 0;
991 	}
992 	__ops_forget(seckey, sizeof(*seckey));
993 	return ret;
994 }
995 
996 /* verify memory */
997 int
998 netpgp_verify_memory(netpgp_t *netpgp, const void *in, const size_t size,
999 			void *out, size_t outsize, const int armored)
1000 {
1001 	__ops_validation_t	 result;
1002 	__ops_memory_t		*signedmem;
1003 	__ops_memory_t		*cat;
1004 	__ops_io_t		*io;
1005 	size_t			 m;
1006 	int			 ret;
1007 
1008 	(void) memset(&result, 0x0, sizeof(result));
1009 	io = netpgp->io;
1010 	if (in == NULL) {
1011 		(void) fprintf(io->errs,
1012 			"netpgp_verify_memory: no memory to verify\n");
1013 		return 0;
1014 	}
1015 	signedmem = __ops_memory_new();
1016 	__ops_memory_add(signedmem, in, size);
1017 	if (out) {
1018 		cat = __ops_memory_new();
1019 	}
1020 	ret = __ops_validate_mem(io, &result, signedmem,
1021 				(out) ? &cat : NULL,
1022 				armored, netpgp->pubring);
1023 	__ops_memory_free(signedmem);
1024 	if (ret) {
1025 		resultp(io, "<stdin>", &result, netpgp->pubring);
1026 		if (out) {
1027 			m = MIN(__ops_mem_len(cat), outsize);
1028 			(void) memcpy(out, __ops_mem_data(cat), m);
1029 			__ops_memory_free(cat);
1030 		} else {
1031 			m = 1;
1032 		}
1033 		return (int)m;
1034 	}
1035 	if (result.validc + result.invalidc + result.unknownc == 0) {
1036 		(void) fprintf(io->errs,
1037 		"No signatures found - is this memory signed?\n");
1038 	} else if (result.invalidc == 0 && result.unknownc == 0) {
1039 		(void) fprintf(io->errs,
1040 			"memory verification failure: invalid signature time\n");
1041 	} else {
1042 		(void) fprintf(io->errs,
1043 "memory verification failure: %u invalid signatures, %u unknown signatures\n",
1044 			result.invalidc, result.unknownc);
1045 	}
1046 	return 0;
1047 }
1048 
1049 /* encrypt some memory */
1050 int
1051 netpgp_encrypt_memory(netpgp_t *netpgp,
1052 			const char *userid,
1053 			void *in,
1054 			const size_t insize,
1055 			char *out,
1056 			size_t outsize,
1057 			int armored)
1058 {
1059 	const __ops_key_t	*keypair;
1060 	__ops_memory_t		*enc;
1061 	__ops_io_t		*io;
1062 	size_t			 m;
1063 
1064 	io = netpgp->io;
1065 	if (in == NULL) {
1066 		(void) fprintf(io->errs,
1067 			"netpgp_encrypt_buf: no memory to encrypt\n");
1068 		return 0;
1069 	}
1070 	if (userid == NULL) {
1071 		userid = netpgp_getvar(netpgp, "userid");
1072 	}
1073 	keypair = __ops_getkeybyname(io, netpgp->pubring, userid);
1074 	if (keypair == NULL) {
1075 		(void) fprintf(io->errs, "Userid '%s' not found in keyring\n",
1076 					userid);
1077 		return 0;
1078 	}
1079 	if (in == out) {
1080 		(void) fprintf(io->errs,
1081 			"netpgp_encrypt_buf: input and output bufs need to be different\n");
1082 		return 0;
1083 	}
1084 	if (outsize < insize) {
1085 		(void) fprintf(io->errs,
1086 			"netpgp_encrypt_buf: input size is larger than output size\n");
1087 		return 0;
1088 	}
1089 	enc = __ops_encrypt_buf(io, in, insize, keypair, (unsigned)armored);
1090 	m = MIN(__ops_mem_len(enc), outsize);
1091 	(void) memcpy(out, __ops_mem_data(enc), m);
1092 	__ops_memory_free(enc);
1093 	return (int)m;
1094 }
1095 
1096 /* decrypt a chunk of memory */
1097 int
1098 netpgp_decrypt_memory(netpgp_t *netpgp, const void *input, const size_t insize,
1099 			char *out, size_t outsize, const int armored)
1100 {
1101 	__ops_memory_t	*mem;
1102 	__ops_io_t	*io;
1103 	unsigned	 realarmour;
1104 	size_t		 m;
1105 
1106 	io = netpgp->io;
1107 	realarmour = (unsigned) armored;
1108 	if (input == NULL) {
1109 		(void) fprintf(io->errs,
1110 			"netpgp_decrypt_memory: no memory\n");
1111 		return 0;
1112 	}
1113 	realarmour = (strncmp(input, ARMOR_HEAD, sizeof(ARMOR_HEAD) - 1) == 0);
1114 	mem = __ops_decrypt_buf(netpgp->io, input, insize, netpgp->secring,
1115 				netpgp->pubring,
1116 				realarmour, netpgp->passfp,
1117 				get_passphrase_cb);
1118 	m = MIN(__ops_mem_len(mem), outsize);
1119 	(void) memcpy(out, __ops_mem_data(mem), m);
1120 	__ops_memory_free(mem);
1121 	return (int)m;
1122 }
1123 
1124 /* wrappers for the ops_debug_level functions we added to openpgpsdk */
1125 
1126 /* set the debugging level per filename */
1127 int
1128 netpgp_set_debug(const char *f)
1129 {
1130 	return __ops_set_debug_level(f);
1131 }
1132 
1133 /* get the debugging level per filename */
1134 int
1135 netpgp_get_debug(const char *f)
1136 {
1137 	return __ops_get_debug_level(f);
1138 }
1139 
1140 /* return the version for the library */
1141 const char *
1142 netpgp_get_info(const char *type)
1143 {
1144 	return __ops_get_info(type);
1145 }
1146 
1147 /* list all the packets in a file */
1148 int
1149 netpgp_list_packets(netpgp_t *netpgp, char *f, int armour, char *pubringname)
1150 {
1151 	__ops_keyring_t	*keyring;
1152 	const unsigned	 noarmor = 0;
1153 	struct stat	 st;
1154 	__ops_io_t	*io;
1155 	char		 ringname[MAXPATHLEN];
1156 	char		*homedir;
1157 	int		 ret;
1158 
1159 	io = netpgp->io;
1160 	if (f == NULL) {
1161 		(void) fprintf(io->errs, "No file containing packets\n");
1162 		return 0;
1163 	}
1164 	if (stat(f, &st) < 0) {
1165 		(void) fprintf(io->errs, "No such file '%s'\n", f);
1166 		return 0;
1167 	}
1168 	homedir = netpgp_getvar(netpgp, "homedir");
1169 	if (pubringname == NULL) {
1170 		(void) snprintf(ringname, sizeof(ringname),
1171 				"%s/pubring.gpg", homedir);
1172 		pubringname = ringname;
1173 	}
1174 	if ((keyring = calloc(1, sizeof(*keyring))) == NULL) {
1175 		(void) fprintf(io->errs, "netpgp_list_packets: bad alloc\n");
1176 		return 0;
1177 	}
1178 	if (!__ops_keyring_fileread(keyring, noarmor, pubringname)) {
1179 		free(keyring);
1180 		(void) fprintf(io->errs, "Cannot read pub keyring %s\n",
1181 			pubringname);
1182 		return 0;
1183 	}
1184 	netpgp->pubring = keyring;
1185 	netpgp_setvar(netpgp, "pubring", pubringname);
1186 	ret = __ops_list_packets(io, f, (unsigned)armour,
1187 					netpgp->secring,
1188 					netpgp->pubring,
1189 					netpgp->passfp,
1190 					get_passphrase_cb);
1191 	free(keyring);
1192 	return ret;
1193 }
1194 
1195 /* set a variable */
1196 int
1197 netpgp_setvar(netpgp_t *netpgp, const char *name, const char *value)
1198 {
1199 	int	i;
1200 
1201 	if ((i = findvar(netpgp, name)) < 0) {
1202 		/* add the element to the array */
1203 		if (size_arrays(netpgp, netpgp->size + 15)) {
1204 			netpgp->name[i = netpgp->c++] = strdup(name);
1205 		}
1206 	} else {
1207 		/* replace the element in the array */
1208 		if (netpgp->value[i]) {
1209 			free(netpgp->value[i]);
1210 			netpgp->value[i] = NULL;
1211 		}
1212 	}
1213 	/* sanity checks for range of values */
1214 	if (strcmp(name, "hash") == 0 || strcmp(name, "algorithm") == 0) {
1215 		if (__ops_str_to_hash_alg(value) == OPS_HASH_UNKNOWN) {
1216 			return 0;
1217 		}
1218 	}
1219 	netpgp->value[i] = strdup(value);
1220 	return 1;
1221 }
1222 
1223 /* get a variable's value (NULL if not set) */
1224 char *
1225 netpgp_getvar(netpgp_t *netpgp, const char *name)
1226 {
1227 	int	i;
1228 
1229 	return ((i = findvar(netpgp, name)) < 0) ? NULL : netpgp->value[i];
1230 }
1231 
1232 /* increment a value */
1233 int
1234 netpgp_incvar(netpgp_t *netpgp, const char *name, const int delta)
1235 {
1236 	char	*cp;
1237 	char	 num[16];
1238 	int	 val;
1239 
1240 	val = 0;
1241 	if ((cp = netpgp_getvar(netpgp, name)) != NULL) {
1242 		val = atoi(cp);
1243 	}
1244 	(void) snprintf(num, sizeof(num), "%d", val + delta);
1245 	netpgp_setvar(netpgp, name, num);
1246 	return 1;
1247 }
1248 
1249 /* set the home directory value to "home/subdir" */
1250 int
1251 netpgp_set_homedir(netpgp_t *netpgp, char *home, const char *subdir, const int quiet)
1252 {
1253 	struct stat	st;
1254 	char		d[MAXPATHLEN];
1255 
1256 	if (home == NULL) {
1257 		if (!quiet) {
1258 			(void) fprintf(stderr, "NULL HOME directory\n");
1259 		}
1260 		return 0;
1261 	}
1262 	(void) snprintf(d, sizeof(d), "%s%s", home, (subdir) ? subdir : "");
1263 	if (stat(d, &st) == 0) {
1264 		if ((st.st_mode & S_IFMT) == S_IFDIR) {
1265 			netpgp_setvar(netpgp, "homedir", d);
1266 			return 1;
1267 		}
1268 		(void) fprintf(stderr, "netpgp: homedir \"%s\" is not a dir\n",
1269 					d);
1270 		return 0;
1271 	}
1272 	if (!quiet) {
1273 		(void) fprintf(stderr,
1274 			"netpgp: warning homedir \"%s\" not found\n", d);
1275 	}
1276 	return 1;
1277 }
1278 
1279 /* validate all sigs in the pub keyring */
1280 int
1281 netpgp_validate_sigs(netpgp_t *netpgp)
1282 {
1283 	__ops_validation_t	result;
1284 
1285 	return (int)__ops_validate_all_sigs(&result, netpgp->pubring, NULL);
1286 }
1287 
1288 #if 0
1289 #include "sshkey.h"
1290 
1291 int
1292 netpgp_pgpkey_to_sshkey(netpgp_t *netpgp, char *name, SSHKey *sshkey)
1293 {
1294 	const __ops_key_t	*pgpkey;
1295 	unsigned		 k;
1296 
1297 	k = 0;
1298 	pgpkey = __ops_getnextkeybyname(netpgp->io, netpgp->pubring, name, &k);
1299 	if (pgpkey == NULL) {
1300 		pgpkey = __ops_getkeybyname(io, netpgp->pubring, userid);
1301 	}
1302 	if (pgpkey == NULL) {
1303 		(void) fprintf(stderr, "No key matching '%s'\n", name);
1304 		return 0;
1305 	}
1306 	switch(pgpkey->key.pubkey.alg) {
1307 	case OPS_PKA_RSA:
1308 		sshkey->type = KEY_RSA;
1309 		sshkey->rsa = calloc(1, sizeof(*sshkey->rsa);
1310 		if (sshkey->rsa == NULL) {
1311 			(void) fprintf(stderr, "RSA memory problems\n");
1312 			return 0;
1313 		}
1314 		sshkey->rsa->n = pgpkey->key.pubkey.key.rsa.n;
1315 		sshkey->rsa->e = pgpkey->key.pubkey.key.rsa.e;
1316 		sshkey->rsa->d = pgpkey->key.seckey.key.rsa.d;
1317 		sshkey->rsa->p = pgpkey->key.seckey.key.rsa.p;
1318 		sshkey->rsa->q = pgpkey->key.seckey.key.rsa.q;
1319 		sshkey->rsa->iqmp = pgpkey->key.seckey.key.rsa.u;
1320 		break;
1321 	case OPS_PKA_DSA:
1322 		sshkey->type = KEY_DSA;
1323 		sshkey->dsa = calloc(1, sizeof(*sshkey->dsa);
1324 		if (sshkey->dsa == NULL) {
1325 			(void) fprintf(stderr, "DSA memory problems\n");
1326 			return 0;
1327 		}
1328 		sshkey->rsa->n = pgpkey->key.pubkey.key.rsa.n;
1329 		key->dsa->p = pgpkey->key.pubkey.key.dsa.p;
1330 		key->dsa->q = pgpkey->key.pubkey.key.dsa.q;
1331 		key->dsa->g = pgpkey->key.pubkey.key.dsa.g;
1332 		key->dsa->pub_key = pgpkey->key.pubkey.key.dsa.y;
1333 		key->dsa->priv_key = pgpkey->key.seckey.key.dsa.x;
1334 		break;
1335 	default:
1336 		(void) fprintf(stderr, "weird type\n");
1337 		return 0;
1338 	}
1339 	return 1;
1340 }
1341 #endif
1342