191c29c74Sagc /*-
291c29c74Sagc * Copyright (c) 2009 The NetBSD Foundation, Inc.
391c29c74Sagc * All rights reserved.
491c29c74Sagc *
591c29c74Sagc * This code is derived from software contributed to The NetBSD Foundation
691c29c74Sagc * by Alistair Crooks (agc@NetBSD.org)
791c29c74Sagc *
891c29c74Sagc * Redistribution and use in source and binary forms, with or without
991c29c74Sagc * modification, are permitted provided that the following conditions
1091c29c74Sagc * are met:
1191c29c74Sagc * 1. Redistributions of source code must retain the above copyright
1291c29c74Sagc * notice, this list of conditions and the following disclaimer.
1391c29c74Sagc * 2. Redistributions in binary form must reproduce the above copyright
1491c29c74Sagc * notice, this list of conditions and the following disclaimer in the
1591c29c74Sagc * documentation and/or other materials provided with the distribution.
1691c29c74Sagc *
1791c29c74Sagc * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
1891c29c74Sagc * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
1991c29c74Sagc * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2091c29c74Sagc * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
2191c29c74Sagc * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2291c29c74Sagc * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2391c29c74Sagc * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2491c29c74Sagc * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2591c29c74Sagc * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2691c29c74Sagc * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
2791c29c74Sagc * POSSIBILITY OF SUCH DAMAGE.
2891c29c74Sagc */
2991c29c74Sagc #include "config.h"
3091c29c74Sagc
3191c29c74Sagc #ifdef HAVE_SYS_CDEFS_H
3291c29c74Sagc #include <sys/cdefs.h>
3391c29c74Sagc #endif
3491c29c74Sagc
3591c29c74Sagc #include <sys/types.h>
3691c29c74Sagc #include <sys/stat.h>
3791c29c74Sagc #include <sys/param.h>
3891c29c74Sagc
3967149907Sagc #include <netinet/in.h>
4067149907Sagc
419e63cf3fSagc #include <arpa/inet.h>
421fc3f56aSagc
43fdfbba49Sagc #include <ctype.h>
449e63cf3fSagc #include <inttypes.h>
4591c29c74Sagc #include <stdio.h>
4691c29c74Sagc #include <stdlib.h>
4791c29c74Sagc #include <string.h>
4891c29c74Sagc
4991c29c74Sagc #ifdef HAVE_UNISTD_H
5091c29c74Sagc #include <unistd.h>
5191c29c74Sagc #endif
5291c29c74Sagc
5391c29c74Sagc #ifdef HAVE_LIMITS_H
5491c29c74Sagc #include <limits.h>
5591c29c74Sagc #endif
5691c29c74Sagc
5791c29c74Sagc #ifdef HAVE_OPENSSL_CAST_H
5891c29c74Sagc #include <openssl/cast.h>
5991c29c74Sagc #endif
6091c29c74Sagc
6191c29c74Sagc #include <openssl/pem.h>
6291c29c74Sagc
6391c29c74Sagc #include "bufgap.h"
6491c29c74Sagc
6591c29c74Sagc #include "packet-parse.h"
6691c29c74Sagc #include "netpgpdefs.h"
679e63cf3fSagc #include "netpgpsdk.h"
6891c29c74Sagc #include "crypto.h"
6991c29c74Sagc #include "netpgpdigest.h"
702e1539dfSagc #include "ssh2pgp.h"
7191c29c74Sagc
7291c29c74Sagc /* structure for earching for constant strings */
7391c29c74Sagc typedef struct str_t {
7491c29c74Sagc const char *s; /* string */
7591c29c74Sagc size_t len; /* its length */
7691c29c74Sagc int type; /* return type */
7791c29c74Sagc } str_t;
7891c29c74Sagc
7991c29c74Sagc #ifndef USE_ARG
8091c29c74Sagc #define USE_ARG(x) /*LINTED*/(void)&x
8191c29c74Sagc #endif
8291c29c74Sagc
8391c29c74Sagc static const uint8_t base64s[] =
8491c29c74Sagc /* 000 */ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
8591c29c74Sagc /* 016 */ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
8691c29c74Sagc /* 032 */ "\0\0\0\0\0\0\0\0\0\0\0?\0\0\0@"
8791c29c74Sagc /* 048 */ "56789:;<=>\0\0\0\0\0\0"
8891c29c74Sagc /* 064 */ "\0\1\2\3\4\5\6\7\10\11\12\13\14\15\16\17"
8991c29c74Sagc /* 080 */ "\20\21\22\23\24\25\26\27\30\31\32\0\0\0\0\0"
9091c29c74Sagc /* 096 */ "\0\33\34\35\36\37 !\"#$%&'()"
9191c29c74Sagc /* 112 */ "*+,-./01234\0\0\0\0\0"
9291c29c74Sagc /* 128 */ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
9391c29c74Sagc /* 144 */ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
9491c29c74Sagc /* 160 */ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
9591c29c74Sagc /* 176 */ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
9691c29c74Sagc /* 192 */ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
9791c29c74Sagc /* 208 */ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
9891c29c74Sagc /* 224 */ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
9991c29c74Sagc /* 240 */ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
10091c29c74Sagc
10191c29c74Sagc
10291c29c74Sagc /* short function to decode from base64 */
10391c29c74Sagc /* inspired by an ancient copy of b64.c, then rewritten, the bugs are all mine */
10491c29c74Sagc static int
frombase64(char * dst,const char * src,size_t size,int flag)10591c29c74Sagc frombase64(char *dst, const char *src, size_t size, int flag)
10691c29c74Sagc {
10791c29c74Sagc uint8_t out[3];
10891c29c74Sagc uint8_t in[4];
10991c29c74Sagc uint8_t b;
11091c29c74Sagc size_t srcc;
11191c29c74Sagc int dstc;
11291c29c74Sagc int gotc;
11391c29c74Sagc int i;
11491c29c74Sagc
11591c29c74Sagc USE_ARG(flag);
11691c29c74Sagc for (dstc = 0, srcc = 0 ; srcc < size; ) {
11791c29c74Sagc for (gotc = 0, i = 0; i < 4 && srcc < size; i++) {
11891c29c74Sagc for (b = 0x0; srcc < size && b == 0x0 ; ) {
11991c29c74Sagc b = base64s[(unsigned)src[srcc++]];
12091c29c74Sagc }
12191c29c74Sagc if (srcc < size) {
12291c29c74Sagc gotc += 1;
12391c29c74Sagc if (b) {
12491c29c74Sagc in[i] = (uint8_t)(b - 1);
12591c29c74Sagc }
12691c29c74Sagc } else {
12791c29c74Sagc in[i] = 0x0;
12891c29c74Sagc }
12991c29c74Sagc }
13091c29c74Sagc if (gotc) {
1315b91f35fSagc out[0] = (uint8_t)((unsigned)in[0] << 2 |
1325b91f35fSagc (unsigned)in[1] >> 4);
1335b91f35fSagc out[1] = (uint8_t)((unsigned)in[1] << 4 |
1345b91f35fSagc (unsigned)in[2] >> 2);
13591c29c74Sagc out[2] = (uint8_t)(((in[2] << 6) & 0xc0) | in[3]);
13691c29c74Sagc for (i = 0; i < gotc - 1; i++) {
13791c29c74Sagc *dst++ = out[i];
13891c29c74Sagc }
13991c29c74Sagc dstc += gotc - 1;
14091c29c74Sagc }
14191c29c74Sagc }
14291c29c74Sagc return dstc;
14391c29c74Sagc }
14491c29c74Sagc
14591c29c74Sagc /* get a bignum from the buffer gap */
14691c29c74Sagc static BIGNUM *
getbignum(bufgap_t * bg,char * buf,const char * header)14791c29c74Sagc getbignum(bufgap_t *bg, char *buf, const char *header)
14891c29c74Sagc {
14991c29c74Sagc uint32_t len;
15091c29c74Sagc BIGNUM *bignum;
15191c29c74Sagc
15291c29c74Sagc (void) bufgap_getbin(bg, &len, sizeof(len));
15391c29c74Sagc len = ntohl(len);
15491c29c74Sagc (void) bufgap_seek(bg, sizeof(len), BGFromHere, BGByte);
15591c29c74Sagc (void) bufgap_getbin(bg, buf, len);
156b15ec256Sagc bignum = BN_bin2bn((const uint8_t *)buf, (int)len, NULL);
157fc1f8641Sagc if (pgp_get_debug_level(__FILE__)) {
15847561e26Sagc hexdump(stderr, header, (const uint8_t *)(void *)buf, len);
15991c29c74Sagc }
16091c29c74Sagc (void) bufgap_seek(bg, len, BGFromHere, BGByte);
16191c29c74Sagc return bignum;
16291c29c74Sagc }
16391c29c74Sagc
16447561e26Sagc #if 0
16547561e26Sagc static int
16647561e26Sagc putbignum(bufgap_t *bg, BIGNUM *bignum)
16747561e26Sagc {
16847561e26Sagc uint32_t len;
16947561e26Sagc
17047561e26Sagc len = BN_num_bytes(bignum);
17147561e26Sagc (void) bufgap_insert(bg, &len, sizeof(len));
17247561e26Sagc (void) bufgap_insert(bg, buf, len);
17347561e26Sagc bignum = BN_bin2bn((const uint8_t *)buf, (int)len, NULL);
174fc1f8641Sagc if (pgp_get_debug_level(__FILE__)) {
17547561e26Sagc hexdump(stderr, header, buf, (int)len);
17647561e26Sagc }
17747561e26Sagc (void) bufgap_seek(bg, len, BGFromHere, BGByte);
17847561e26Sagc return bignum;
17947561e26Sagc }
18047561e26Sagc #endif
18147561e26Sagc
18291c29c74Sagc static str_t pkatypes[] = {
183fc1f8641Sagc { "ssh-rsa", 7, PGP_PKA_RSA },
184fc1f8641Sagc { "ssh-dss", 7, PGP_PKA_DSA },
185fc1f8641Sagc { "ssh-dsa", 7, PGP_PKA_DSA },
18691c29c74Sagc { NULL, 0, 0 }
18791c29c74Sagc };
18891c29c74Sagc
18991c29c74Sagc /* look for a string in the given array */
19091c29c74Sagc static int
findstr(str_t * array,const char * name)19191c29c74Sagc findstr(str_t *array, const char *name)
19291c29c74Sagc {
19391c29c74Sagc str_t *sp;
19491c29c74Sagc
19591c29c74Sagc for (sp = array ; sp->s ; sp++) {
19691c29c74Sagc if (strncmp(name, sp->s, sp->len) == 0) {
19791c29c74Sagc return sp->type;
19891c29c74Sagc }
19991c29c74Sagc }
20091c29c74Sagc return -1;
20191c29c74Sagc }
20291c29c74Sagc
20391c29c74Sagc /* convert an ssh (host) pubkey to a pgp pubkey */
20491c29c74Sagc int
pgp_ssh2pubkey(pgp_io_t * io,const char * f,pgp_key_t * key,pgp_hash_alg_t hashtype)205fc1f8641Sagc pgp_ssh2pubkey(pgp_io_t *io, const char *f, pgp_key_t *key, pgp_hash_alg_t hashtype)
20691c29c74Sagc {
207fc1f8641Sagc pgp_pubkey_t *pubkey;
20891c29c74Sagc struct stat st;
20991c29c74Sagc bufgap_t bg;
21091c29c74Sagc uint32_t len;
21191c29c74Sagc int64_t off;
212d427c17dSagc uint8_t *userid;
21391c29c74Sagc char hostname[256];
214d369874eSagc char owner[256];
21591c29c74Sagc char *space;
21691c29c74Sagc char *buf;
21791c29c74Sagc char *bin;
21891c29c74Sagc int ok;
21991c29c74Sagc int cc;
22091c29c74Sagc
22191c29c74Sagc (void) memset(&bg, 0x0, sizeof(bg));
22291c29c74Sagc if (!bufgap_open(&bg, f)) {
223fc1f8641Sagc (void) fprintf(stderr, "pgp_ssh2pubkey: can't open '%s'\n", f);
22491c29c74Sagc return 0;
22591c29c74Sagc }
22691c29c74Sagc (void)stat(f, &st);
227f20c4802Smartin if ((buf = calloc(1, (size_t)st.st_size)) == NULL) {
228f20c4802Smartin (void) fprintf(stderr, "can't calloc %zu bytes for '%s'\n", (size_t)st.st_size, f);
22991c29c74Sagc bufgap_close(&bg);
23091c29c74Sagc return 0;
23191c29c74Sagc }
232f20c4802Smartin if ((bin = calloc(1, (size_t)st.st_size)) == NULL) {
233f20c4802Smartin (void) fprintf(stderr, "can't calloc %zu bytes for '%s'\n", (size_t)st.st_size, f);
23491c29c74Sagc (void) free(buf);
23591c29c74Sagc bufgap_close(&bg);
23691c29c74Sagc return 0;
23791c29c74Sagc }
23891c29c74Sagc
23991c29c74Sagc /* move past ascii type of key */
24091c29c74Sagc while (bufgap_peek(&bg, 0) != ' ') {
24191c29c74Sagc bufgap_seek(&bg, 1, BGFromHere, BGByte);
24291c29c74Sagc }
24391c29c74Sagc bufgap_seek(&bg, 1, BGFromHere, BGByte);
24491c29c74Sagc off = bufgap_tell(&bg, BGFromBOF, BGByte);
24591c29c74Sagc
24673f34b00Sagc if (bufgap_size(&bg, BGByte) - off < 10) {
24773f34b00Sagc (void) fprintf(stderr, "bad key file '%s'\n", f);
24873f34b00Sagc (void) free(buf);
24973f34b00Sagc bufgap_close(&bg);
25073f34b00Sagc return 0;
25173f34b00Sagc }
25273f34b00Sagc
25391c29c74Sagc /* convert from base64 to binary */
254f14b9450Sagc cc = bufgap_getbin(&bg, buf, (size_t)bg.bcc);
25591c29c74Sagc if ((space = strchr(buf, ' ')) != NULL) {
25691c29c74Sagc cc = (int)(space - buf);
25791c29c74Sagc }
258fc1f8641Sagc if (pgp_get_debug_level(__FILE__)) {
25947561e26Sagc hexdump(stderr, NULL, (const uint8_t *)(const void *)buf, (size_t)cc);
26091c29c74Sagc }
26191c29c74Sagc cc = frombase64(bin, buf, (size_t)cc, 0);
262fc1f8641Sagc if (pgp_get_debug_level(__FILE__)) {
26347561e26Sagc hexdump(stderr, "decoded base64:", (const uint8_t *)(const void *)bin, (size_t)cc);
26491c29c74Sagc }
2655b91f35fSagc bufgap_delete(&bg, (uint64_t)bufgap_tell(&bg, BGFromEOF, BGByte));
26691c29c74Sagc bufgap_insert(&bg, bin, cc);
26791c29c74Sagc bufgap_seek(&bg, off, BGFromBOF, BGByte);
26891c29c74Sagc
26991c29c74Sagc /* get the type of key */
27091c29c74Sagc (void) bufgap_getbin(&bg, &len, sizeof(len));
27191c29c74Sagc len = ntohl(len);
27291c29c74Sagc (void) bufgap_seek(&bg, sizeof(len), BGFromHere, BGByte);
27391c29c74Sagc (void) bufgap_getbin(&bg, buf, len);
27491c29c74Sagc (void) bufgap_seek(&bg, len, BGFromHere, BGByte);
27591c29c74Sagc
27691c29c74Sagc (void) memset(key, 0x0, sizeof(*key));
27791c29c74Sagc pubkey = &key->key.seckey.pubkey;
278fc1f8641Sagc pubkey->version = PGP_V4;
279*7302906dSagc pubkey->birthtime = 0;
28091c29c74Sagc /* get key type */
28191c29c74Sagc ok = 1;
28291c29c74Sagc switch (pubkey->alg = findstr(pkatypes, buf)) {
283fc1f8641Sagc case PGP_PKA_RSA:
28491c29c74Sagc /* get the 'e' param of the key */
28591c29c74Sagc pubkey->key.rsa.e = getbignum(&bg, buf, "RSA E");
28691c29c74Sagc /* get the 'n' param of the key */
28791c29c74Sagc pubkey->key.rsa.n = getbignum(&bg, buf, "RSA N");
28891c29c74Sagc break;
289fc1f8641Sagc case PGP_PKA_DSA:
29091c29c74Sagc /* get the 'p' param of the key */
29191c29c74Sagc pubkey->key.dsa.p = getbignum(&bg, buf, "DSA P");
29291c29c74Sagc /* get the 'q' param of the key */
29391c29c74Sagc pubkey->key.dsa.q = getbignum(&bg, buf, "DSA Q");
29491c29c74Sagc /* get the 'g' param of the key */
29591c29c74Sagc pubkey->key.dsa.g = getbignum(&bg, buf, "DSA G");
29691c29c74Sagc /* get the 'y' param of the key */
29791c29c74Sagc pubkey->key.dsa.y = getbignum(&bg, buf, "DSA Y");
29891c29c74Sagc break;
29991c29c74Sagc default:
30091c29c74Sagc (void) fprintf(stderr, "Unrecognised pubkey type %d for '%s'\n",
30191c29c74Sagc pubkey->alg, f);
30291c29c74Sagc ok = 0;
30391c29c74Sagc break;
30491c29c74Sagc }
30591c29c74Sagc
30691c29c74Sagc /* check for stragglers */
30791c29c74Sagc if (ok && bufgap_tell(&bg, BGFromEOF, BGByte) > 0) {
308f20c4802Smartin printf("%"PRIi64" bytes left\n", bufgap_tell(&bg, BGFromEOF, BGByte));
30991c29c74Sagc printf("[%s]\n", bufgap_getstr(&bg));
31091c29c74Sagc ok = 0;
31191c29c74Sagc }
31291c29c74Sagc if (ok) {
31391c29c74Sagc (void) memset(&userid, 0x0, sizeof(userid));
31491c29c74Sagc (void) gethostname(hostname, sizeof(hostname));
315d369874eSagc if (strlen(space + 1) - 1 == 0) {
316d369874eSagc (void) snprintf(owner, sizeof(owner), "<root@%s>",
317d369874eSagc hostname);
318d369874eSagc } else {
319d369874eSagc (void) snprintf(owner, sizeof(owner), "<%.*s>",
32091c29c74Sagc (int)strlen(space + 1) - 1,
32191c29c74Sagc space + 1);
322d369874eSagc }
323fc1f8641Sagc (void) pgp_asprintf((char **)(void *)&userid,
324d369874eSagc "%s (%s) %s",
325d369874eSagc hostname,
326d369874eSagc f,
327d369874eSagc owner);
328fc1f8641Sagc pgp_keyid(key->sigid, sizeof(key->sigid), pubkey, hashtype);
329fc1f8641Sagc pgp_add_userid(key, userid);
330fc1f8641Sagc pgp_fingerprint(&key->sigfingerprint, pubkey, hashtype);
331d427c17dSagc free(userid);
332fc1f8641Sagc if (pgp_get_debug_level(__FILE__)) {
333fc1f8641Sagc /*pgp_print_keydata(io, keyring, key, "pub", pubkey, 0);*/
334fc1f8641Sagc __PGP_USED(io); /* XXX */
33591c29c74Sagc }
33691c29c74Sagc }
33791c29c74Sagc (void) free(bin);
33891c29c74Sagc (void) free(buf);
33991c29c74Sagc bufgap_close(&bg);
34091c29c74Sagc return ok;
34191c29c74Sagc }
34291c29c74Sagc
34391c29c74Sagc /* convert an ssh (host) seckey to a pgp seckey */
34491c29c74Sagc int
pgp_ssh2seckey(pgp_io_t * io,const char * f,pgp_key_t * key,pgp_pubkey_t * pubkey,pgp_hash_alg_t hashtype)345fc1f8641Sagc pgp_ssh2seckey(pgp_io_t *io, const char *f, pgp_key_t *key, pgp_pubkey_t *pubkey, pgp_hash_alg_t hashtype)
34691c29c74Sagc {
347fc1f8641Sagc pgp_crypt_t crypted;
348fc1f8641Sagc pgp_hash_t hash;
349b15ec256Sagc unsigned done = 0;
350b15ec256Sagc unsigned i = 0;
351b15ec256Sagc uint8_t sesskey[CAST_KEY_LENGTH];
352fc1f8641Sagc uint8_t hashed[PGP_SHA1_HASH_SIZE];
35347561e26Sagc BIGNUM *tmp;
35491c29c74Sagc
355fc1f8641Sagc __PGP_USED(io);
35691c29c74Sagc /* XXX - check for rsa/dsa */
357600b302bSagc if (!openssl_read_pem_seckey(f, key, "ssh-rsa", 0)) {
35891c29c74Sagc return 0;
35991c29c74Sagc }
360fc1f8641Sagc if (pgp_get_debug_level(__FILE__)) {
361fc1f8641Sagc /*pgp_print_keydata(io, key, "sec", &key->key.seckey.pubkey, 0);*/
3625aae2c74Sagc /* XXX */
36391c29c74Sagc }
36491c29c74Sagc /* let's add some sane defaults */
36591c29c74Sagc (void) memcpy(&key->key.seckey.pubkey, pubkey, sizeof(*pubkey));
366fc1f8641Sagc key->key.seckey.s2k_usage = PGP_S2KU_ENCRYPTED_AND_HASHED;
367fc1f8641Sagc key->key.seckey.alg = PGP_SA_CAST5;
368fc1f8641Sagc key->key.seckey.s2k_specifier = PGP_S2KS_SALTED;
369fc1f8641Sagc key->key.seckey.hash_alg = PGP_HASH_SHA1;
370fc1f8641Sagc if (key->key.seckey.pubkey.alg == PGP_PKA_RSA) {
37147561e26Sagc /* openssh and openssl have p and q swapped */
37247561e26Sagc tmp = key->key.seckey.key.rsa.p;
37347561e26Sagc key->key.seckey.key.rsa.p = key->key.seckey.key.rsa.q;
37447561e26Sagc key->key.seckey.key.rsa.q = tmp;
37547561e26Sagc }
37691c29c74Sagc for (done = 0, i = 0; done < CAST_KEY_LENGTH; i++) {
37791c29c74Sagc unsigned j;
378b15ec256Sagc uint8_t zero = 0;
37991c29c74Sagc int needed;
38091c29c74Sagc int size;
38191c29c74Sagc
38291c29c74Sagc needed = CAST_KEY_LENGTH - done;
383fc1f8641Sagc size = MIN(needed, PGP_SHA1_HASH_SIZE);
38491c29c74Sagc
385fc1f8641Sagc pgp_hash_any(&hash, key->key.seckey.hash_alg);
38691c29c74Sagc if (!hash.init(&hash)) {
38791c29c74Sagc (void) fprintf(stderr, "write_seckey_body: bad alloc\n");
38891c29c74Sagc return 0;
38991c29c74Sagc }
39091c29c74Sagc
39191c29c74Sagc /* preload if iterating */
39291c29c74Sagc for (j = 0; j < i; j++) {
39391c29c74Sagc /*
39491c29c74Sagc * Coverity shows a DEADCODE error on this
39591c29c74Sagc * line. This is expected since the hardcoded
39691c29c74Sagc * use of SHA1 and CAST5 means that it will
39791c29c74Sagc * not used. This will change however when
39891c29c74Sagc * other algorithms are supported.
39991c29c74Sagc */
40091c29c74Sagc hash.add(&hash, &zero, 1);
40191c29c74Sagc }
40291c29c74Sagc
403fc1f8641Sagc if (key->key.seckey.s2k_specifier == PGP_S2KS_SALTED) {
404fc1f8641Sagc hash.add(&hash, key->key.seckey.salt, PGP_SALT_SIZE);
40591c29c74Sagc }
40691c29c74Sagc hash.finish(&hash, hashed);
40791c29c74Sagc
40891c29c74Sagc /*
40991c29c74Sagc * if more in hash than is needed by session key, use
41091c29c74Sagc * the leftmost octets
41191c29c74Sagc */
412fc1f8641Sagc (void) memcpy(&sesskey[i * PGP_SHA1_HASH_SIZE],
41391c29c74Sagc hashed, (unsigned)size);
41491c29c74Sagc done += (unsigned)size;
41591c29c74Sagc if (done > CAST_KEY_LENGTH) {
41691c29c74Sagc (void) fprintf(stderr,
41791c29c74Sagc "write_seckey_body: short add\n");
41891c29c74Sagc return 0;
41991c29c74Sagc }
42091c29c74Sagc }
421fc1f8641Sagc pgp_crypt_any(&crypted, key->key.seckey.alg);
42291c29c74Sagc crypted.set_iv(&crypted, key->key.seckey.iv);
42391c29c74Sagc crypted.set_crypt_key(&crypted, sesskey);
424fc1f8641Sagc pgp_encrypt_init(&crypted);
425fc1f8641Sagc key->key.seckey.pubkey.alg = PGP_PKA_RSA;
426fc1f8641Sagc pgp_fingerprint(&key->sigfingerprint, pubkey, hashtype);
427fc1f8641Sagc pgp_keyid(key->sigid, sizeof(key->sigid), pubkey, hashtype);
42891c29c74Sagc return 1;
42991c29c74Sagc }
43091c29c74Sagc
43191c29c74Sagc /* read a key from the ssh file, and add it to a keyring */
43291c29c74Sagc int
pgp_ssh2_readkeys(pgp_io_t * io,pgp_keyring_t * pubring,pgp_keyring_t * secring,const char * pubfile,const char * secfile,unsigned hashtype)433fc1f8641Sagc pgp_ssh2_readkeys(pgp_io_t *io, pgp_keyring_t *pubring,
434fc1f8641Sagc pgp_keyring_t *secring, const char *pubfile,
43547561e26Sagc const char *secfile, unsigned hashtype)
43691c29c74Sagc {
437fc1f8641Sagc pgp_key_t *pubkey;
438fc1f8641Sagc pgp_key_t *seckey;
439fc1f8641Sagc pgp_key_t key;
44091c29c74Sagc
44191c29c74Sagc pubkey = NULL;
44291c29c74Sagc (void) memset(&key, 0x0, sizeof(key));
44391c29c74Sagc if (pubfile) {
444fc1f8641Sagc if (pgp_get_debug_level(__FILE__)) {
445fc1f8641Sagc (void) fprintf(io->errs, "pgp_ssh2_readkeys: pubfile '%s'\n", pubfile);
44691c29c74Sagc }
447fc1f8641Sagc if (!pgp_ssh2pubkey(io, pubfile, &key, (pgp_hash_alg_t)hashtype)) {
448fc1f8641Sagc (void) fprintf(io->errs, "pgp_ssh2_readkeys: can't read pubkeys '%s'\n", pubfile);
449520c968fSagc return 0;
450520c968fSagc }
45191c29c74Sagc EXPAND_ARRAY(pubring, key);
45291c29c74Sagc pubkey = &pubring->keys[pubring->keyc++];
45391c29c74Sagc (void) memcpy(pubkey, &key, sizeof(key));
454fc1f8641Sagc pubkey->type = PGP_PTAG_CT_PUBLIC_KEY;
45591c29c74Sagc }
45691c29c74Sagc if (secfile) {
457fc1f8641Sagc if (pgp_get_debug_level(__FILE__)) {
458fc1f8641Sagc (void) fprintf(io->errs, "pgp_ssh2_readkeys: secfile '%s'\n", secfile);
45991c29c74Sagc }
46091c29c74Sagc if (pubkey == NULL) {
46191c29c74Sagc pubkey = &pubring->keys[0];
46291c29c74Sagc }
463fc1f8641Sagc if (!pgp_ssh2seckey(io, secfile, &key, &pubkey->key.pubkey, (pgp_hash_alg_t)hashtype)) {
464fc1f8641Sagc (void) fprintf(io->errs, "pgp_ssh2_readkeys: can't read seckeys '%s'\n", secfile);
465520c968fSagc return 0;
466520c968fSagc }
46791c29c74Sagc EXPAND_ARRAY(secring, key);
46891c29c74Sagc seckey = &secring->keys[secring->keyc++];
46991c29c74Sagc (void) memcpy(seckey, &key, sizeof(key));
470fc1f8641Sagc seckey->type = PGP_PTAG_CT_SECRET_KEY;
47191c29c74Sagc }
47291c29c74Sagc return 1;
47391c29c74Sagc }
474