12232f800Sagc /*-
22232f800Sagc * Copyright (c) 2009 The NetBSD Foundation, Inc.
32232f800Sagc * All rights reserved.
42232f800Sagc *
52232f800Sagc * This code is derived from software contributed to The NetBSD Foundation
62232f800Sagc * by Alistair Crooks (agc@NetBSD.org)
72232f800Sagc *
82232f800Sagc * Redistribution and use in source and binary forms, with or without
92232f800Sagc * modification, are permitted provided that the following conditions
102232f800Sagc * are met:
112232f800Sagc * 1. Redistributions of source code must retain the above copyright
122232f800Sagc * notice, this list of conditions and the following disclaimer.
132232f800Sagc * 2. Redistributions in binary form must reproduce the above copyright
142232f800Sagc * notice, this list of conditions and the following disclaimer in the
152232f800Sagc * documentation and/or other materials provided with the distribution.
162232f800Sagc *
172232f800Sagc * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
182232f800Sagc * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
192232f800Sagc * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
202232f800Sagc * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
212232f800Sagc * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
222232f800Sagc * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
232232f800Sagc * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
242232f800Sagc * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
252232f800Sagc * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
262232f800Sagc * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
272232f800Sagc * POSSIBILITY OF SUCH DAMAGE.
282232f800Sagc */
2993bf6008Sagc /*
3093bf6008Sagc * Copyright (c) 2005-2008 Nominet UK (www.nic.uk)
3193bf6008Sagc * All rights reserved.
3293bf6008Sagc * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted
3393bf6008Sagc * their moral rights under the UK Copyright Design and Patents Act 1988 to
3493bf6008Sagc * be recorded as the authors of this copyright work.
3593bf6008Sagc *
3693bf6008Sagc * Licensed under the Apache License, Version 2.0 (the "License"); you may not
3793bf6008Sagc * use this file except in compliance with the License.
3893bf6008Sagc *
3993bf6008Sagc * You may obtain a copy of the License at
4093bf6008Sagc * http://www.apache.org/licenses/LICENSE-2.0
4193bf6008Sagc *
4293bf6008Sagc * Unless required by applicable law or agreed to in writing, software
4393bf6008Sagc * distributed under the License is distributed on an "AS IS" BASIS,
4493bf6008Sagc * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
4593bf6008Sagc *
4693bf6008Sagc * See the License for the specific language governing permissions and
4793bf6008Sagc * limitations under the License.
4893bf6008Sagc */
4993bf6008Sagc
5093bf6008Sagc /** \file
5193bf6008Sagc */
5293bf6008Sagc #include "config.h"
5393bf6008Sagc
5457324b9fSagc #ifdef HAVE_SYS_CDEFS_H
5557324b9fSagc #include <sys/cdefs.h>
5657324b9fSagc #endif
5757324b9fSagc
5857324b9fSagc #if defined(__NetBSD__)
5957324b9fSagc __COPYRIGHT("@(#) Copyright (c) 2009 The NetBSD Foundation, Inc. All rights reserved.");
60*0294a66bSjhigh __RCSID("$NetBSD: create.c,v 1.39 2022/08/26 19:18:38 jhigh Exp $");
6157324b9fSagc #endif
6257324b9fSagc
63bcfd8565Sagc #include <sys/types.h>
642232f800Sagc #include <sys/param.h>
65bcfd8565Sagc #include <sys/stat.h>
66bcfd8565Sagc
67bcfd8565Sagc #ifdef HAVE_FCNTL_H
68bcfd8565Sagc #include <fcntl.h>
69bcfd8565Sagc #endif
70bcfd8565Sagc
71bcfd8565Sagc #include <string.h>
72bcfd8565Sagc
73bcfd8565Sagc #ifdef HAVE_UNISTD_H
74bcfd8565Sagc #include <unistd.h>
75bcfd8565Sagc #endif
76bcfd8565Sagc
7793bf6008Sagc #ifdef HAVE_OPENSSL_CAST_H
7893bf6008Sagc #include <openssl/cast.h>
7993bf6008Sagc #endif
8093bf6008Sagc
8193bf6008Sagc #include "create.h"
8293bf6008Sagc #include "keyring.h"
8393bf6008Sagc #include "packet.h"
8493bf6008Sagc #include "signature.h"
8593bf6008Sagc #include "writer.h"
8693bf6008Sagc #include "readerwriter.h"
8793bf6008Sagc #include "memory.h"
8893bf6008Sagc #include "netpgpdefs.h"
896715e11aSagc #include "netpgpdigest.h"
9093bf6008Sagc
9193bf6008Sagc /**
9293bf6008Sagc * \ingroup Core_Create
9393bf6008Sagc * \param length
9493bf6008Sagc * \param type
9557324b9fSagc * \param output
964b3a3e18Sagc * \return 1 if OK, otherwise 0
9793bf6008Sagc */
9893bf6008Sagc
994b3a3e18Sagc unsigned
pgp_write_ss_header(pgp_output_t * output,unsigned length,pgp_content_enum type)100fc1f8641Sagc pgp_write_ss_header(pgp_output_t *output,
10157324b9fSagc unsigned length,
102fc1f8641Sagc pgp_content_enum type)
10393bf6008Sagc {
104fc1f8641Sagc return pgp_write_length(output, length) &&
105fc1f8641Sagc pgp_write_scalar(output, (unsigned)(type -
106fc1f8641Sagc (unsigned)PGP_PTAG_SIG_SUBPKT_BASE), 1);
10793bf6008Sagc }
10893bf6008Sagc
10993bf6008Sagc /*
11093bf6008Sagc * XXX: the general idea of _fast_ is that it doesn't copy stuff the safe
11193bf6008Sagc * (i.e. non _fast_) version will, and so will also need to be freed.
11293bf6008Sagc */
11393bf6008Sagc
11493bf6008Sagc /**
11593bf6008Sagc * \ingroup Core_Create
11693bf6008Sagc *
117fc1f8641Sagc * pgp_fast_create_userid() sets id->userid to the given userid.
11857324b9fSagc * This is fast because it is only copying a char*. However, if userid
11993bf6008Sagc * is changed or freed in the future, this could have injurious results.
12093bf6008Sagc * \param id
12157324b9fSagc * \param userid
12293bf6008Sagc */
12393bf6008Sagc
12493bf6008Sagc void
pgp_fast_create_userid(uint8_t ** id,uint8_t * userid)125fc1f8641Sagc pgp_fast_create_userid(uint8_t **id, uint8_t *userid)
12693bf6008Sagc {
127d427c17dSagc *id = userid;
12893bf6008Sagc }
12993bf6008Sagc
13093bf6008Sagc /**
13193bf6008Sagc * \ingroup Core_WritePackets
13293bf6008Sagc * \brief Writes a User Id packet
13393bf6008Sagc * \param id
13457324b9fSagc * \param output
1354b3a3e18Sagc * \return 1 if OK, otherwise 0
13693bf6008Sagc */
1374b3a3e18Sagc unsigned
pgp_write_struct_userid(pgp_output_t * output,const uint8_t * id)138fc1f8641Sagc pgp_write_struct_userid(pgp_output_t *output, const uint8_t *id)
13993bf6008Sagc {
140fc1f8641Sagc return pgp_write_ptag(output, PGP_PTAG_CT_USER_ID) &&
141fc1f8641Sagc pgp_write_length(output, (unsigned)strlen((const char *) id)) &&
142fc1f8641Sagc pgp_write(output, id, (unsigned)strlen((const char *) id));
14393bf6008Sagc }
14493bf6008Sagc
14593bf6008Sagc /**
14693bf6008Sagc * \ingroup Core_WritePackets
14793bf6008Sagc * \brief Write a User Id packet.
14857324b9fSagc * \param userid
14957324b9fSagc * \param output
15093bf6008Sagc *
151fc1f8641Sagc * \return return value from pgp_write_struct_userid()
15293bf6008Sagc */
1534b3a3e18Sagc unsigned
pgp_write_userid(const uint8_t * userid,pgp_output_t * output)154fc1f8641Sagc pgp_write_userid(const uint8_t *userid, pgp_output_t *output)
15593bf6008Sagc {
156fc1f8641Sagc return pgp_write_struct_userid(output, userid);
15793bf6008Sagc }
15893bf6008Sagc
15993bf6008Sagc /**
16093bf6008Sagc \ingroup Core_MPI
16193bf6008Sagc */
16293bf6008Sagc static unsigned
mpi_length(const BIGNUM * bn)16393bf6008Sagc mpi_length(const BIGNUM *bn)
16493bf6008Sagc {
1655a83dba0Sagc return (unsigned)(2 + (BN_num_bits(bn) + 7) / 8);
16693bf6008Sagc }
16793bf6008Sagc
16893bf6008Sagc static unsigned
pubkey_length(const pgp_pubkey_t * key)169fc1f8641Sagc pubkey_length(const pgp_pubkey_t *key)
17093bf6008Sagc {
1712232f800Sagc switch (key->alg) {
172fc1f8641Sagc case PGP_PKA_DSA:
173708e54deSagc return mpi_length(key->key.dsa.p) + mpi_length(key->key.dsa.q) +
174708e54deSagc mpi_length(key->key.dsa.g) + mpi_length(key->key.dsa.y);
175708e54deSagc
176fc1f8641Sagc case PGP_PKA_RSA:
17793bf6008Sagc return mpi_length(key->key.rsa.n) + mpi_length(key->key.rsa.e);
17893bf6008Sagc
17993bf6008Sagc default:
180ed0df671Sagc (void) fprintf(stderr,
1813326c4c5Sagc "pubkey_length: unknown key algorithm\n");
18293bf6008Sagc }
18393bf6008Sagc return 0;
18493bf6008Sagc }
18593bf6008Sagc
18693bf6008Sagc static unsigned
seckey_length(const pgp_seckey_t * key)187fc1f8641Sagc seckey_length(const pgp_seckey_t *key)
18893bf6008Sagc {
189ed0df671Sagc int len;
19093bf6008Sagc
191ed0df671Sagc len = 0;
1922232f800Sagc switch (key->pubkey.alg) {
193fc1f8641Sagc case PGP_PKA_DSA:
194708e54deSagc return (unsigned)(mpi_length(key->key.dsa.x) + pubkey_length(&key->pubkey));
195fc1f8641Sagc case PGP_PKA_RSA:
196ed0df671Sagc len = mpi_length(key->key.rsa.d) + mpi_length(key->key.rsa.p) +
197bcfd8565Sagc mpi_length(key->key.rsa.q) + mpi_length(key->key.rsa.u);
19893bf6008Sagc
1995a83dba0Sagc return (unsigned)(len + pubkey_length(&key->pubkey));
20093bf6008Sagc default:
201ed0df671Sagc (void) fprintf(stderr,
20257324b9fSagc "seckey_length: unknown key algorithm\n");
20393bf6008Sagc }
204ed0df671Sagc return 0;
20593bf6008Sagc }
20693bf6008Sagc
20793bf6008Sagc /**
20893bf6008Sagc * \ingroup Core_Create
20993bf6008Sagc * \param key
21093bf6008Sagc * \param t
21193bf6008Sagc * \param n
21293bf6008Sagc * \param e
21393bf6008Sagc */
21493bf6008Sagc void
pgp_fast_create_rsa_pubkey(pgp_pubkey_t * key,time_t t,BIGNUM * n,BIGNUM * e)215fc1f8641Sagc pgp_fast_create_rsa_pubkey(pgp_pubkey_t *key, time_t t,
21693bf6008Sagc BIGNUM *n, BIGNUM *e)
21793bf6008Sagc {
218fc1f8641Sagc key->version = PGP_V4;
2193326c4c5Sagc key->birthtime = t;
220fc1f8641Sagc key->alg = PGP_PKA_RSA;
22193bf6008Sagc key->key.rsa.n = n;
22293bf6008Sagc key->key.rsa.e = e;
22393bf6008Sagc }
22493bf6008Sagc
22593bf6008Sagc /*
22693bf6008Sagc * Note that we support v3 keys here because they're needed for for
22793bf6008Sagc * verification - the writer doesn't allow them, though
22893bf6008Sagc */
2294b3a3e18Sagc static unsigned
write_pubkey_body(const pgp_pubkey_t * key,pgp_output_t * output)230fc1f8641Sagc write_pubkey_body(const pgp_pubkey_t *key, pgp_output_t *output)
23193bf6008Sagc {
232fc1f8641Sagc if (!(pgp_write_scalar(output, (unsigned)key->version, 1) &&
233fc1f8641Sagc pgp_write_scalar(output, (unsigned)key->birthtime, 4))) {
2344b3a3e18Sagc return 0;
235bcfd8565Sagc }
23693bf6008Sagc
237bcfd8565Sagc if (key->version != 4 &&
238fc1f8641Sagc !pgp_write_scalar(output, key->days_valid, 2)) {
2394b3a3e18Sagc return 0;
240bcfd8565Sagc }
24193bf6008Sagc
242fc1f8641Sagc if (!pgp_write_scalar(output, (unsigned)key->alg, 1)) {
2434b3a3e18Sagc return 0;
244bcfd8565Sagc }
24593bf6008Sagc
2462232f800Sagc switch (key->alg) {
247fc1f8641Sagc case PGP_PKA_DSA:
248fc1f8641Sagc return pgp_write_mpi(output, key->key.dsa.p) &&
249fc1f8641Sagc pgp_write_mpi(output, key->key.dsa.q) &&
250fc1f8641Sagc pgp_write_mpi(output, key->key.dsa.g) &&
251fc1f8641Sagc pgp_write_mpi(output, key->key.dsa.y);
25293bf6008Sagc
253*0294a66bSjhigh case PGP_PKA_ECDSA:
254*0294a66bSjhigh return pgp_write(output, &key->key.ecdsa.len, 1) &&
255*0294a66bSjhigh pgp_write(output, key->key.ecdsa.oid, key->key.ecdsa.len) &&
256*0294a66bSjhigh pgp_write_mpi(output, key->key.ecdsa.p);
257*0294a66bSjhigh
258fc1f8641Sagc case PGP_PKA_RSA:
259fc1f8641Sagc case PGP_PKA_RSA_ENCRYPT_ONLY:
260fc1f8641Sagc case PGP_PKA_RSA_SIGN_ONLY:
261fc1f8641Sagc return pgp_write_mpi(output, key->key.rsa.n) &&
262fc1f8641Sagc pgp_write_mpi(output, key->key.rsa.e);
26393bf6008Sagc
264fc1f8641Sagc case PGP_PKA_ELGAMAL:
265fc1f8641Sagc return pgp_write_mpi(output, key->key.elgamal.p) &&
266fc1f8641Sagc pgp_write_mpi(output, key->key.elgamal.g) &&
267fc1f8641Sagc pgp_write_mpi(output, key->key.elgamal.y);
26893bf6008Sagc
26993bf6008Sagc default:
270ed0df671Sagc (void) fprintf(stderr,
2713326c4c5Sagc "write_pubkey_body: bad algorithm\n");
27293bf6008Sagc break;
27393bf6008Sagc }
2744b3a3e18Sagc return 0;
27593bf6008Sagc }
27693bf6008Sagc
27793bf6008Sagc /*
27857324b9fSagc * Note that we support v3 keys here because they're needed for
27944647216Sagc * verification.
28093bf6008Sagc */
2814b3a3e18Sagc static unsigned
write_seckey_body(const pgp_seckey_t * key,const uint8_t * passphrase,const size_t pplen,pgp_output_t * output)282fc1f8641Sagc write_seckey_body(const pgp_seckey_t *key,
283b15ec256Sagc const uint8_t *passphrase,
28493bf6008Sagc const size_t pplen,
285fc1f8641Sagc pgp_output_t *output)
28693bf6008Sagc {
28793bf6008Sagc /* RFC4880 Section 5.5.3 Secret-Key Packet Formats */
28893bf6008Sagc
289fc1f8641Sagc pgp_crypt_t crypted;
290fc1f8641Sagc pgp_hash_t hash;
291b15ec256Sagc unsigned done = 0;
292b15ec256Sagc unsigned i = 0;
29305e6b0bbSagc uint8_t *hashed;
294b15ec256Sagc uint8_t sesskey[CAST_KEY_LENGTH];
29593bf6008Sagc
29657324b9fSagc if (!write_pubkey_body(&key->pubkey, output)) {
2974b3a3e18Sagc return 0;
298bcfd8565Sagc }
299fc1f8641Sagc if (key->s2k_usage != PGP_S2KU_ENCRYPTED_AND_HASHED) {
3003326c4c5Sagc (void) fprintf(stderr, "write_seckey_body: s2k usage\n");
3014b3a3e18Sagc return 0;
302ed0df671Sagc }
303fc1f8641Sagc if (!pgp_write_scalar(output, (unsigned)key->s2k_usage, 1)) {
3044b3a3e18Sagc return 0;
305bcfd8565Sagc }
30693bf6008Sagc
307fc1f8641Sagc if (key->alg != PGP_SA_CAST5) {
3083326c4c5Sagc (void) fprintf(stderr, "write_seckey_body: algorithm\n");
3094b3a3e18Sagc return 0;
310ed0df671Sagc }
311fc1f8641Sagc if (!pgp_write_scalar(output, (unsigned)key->alg, 1)) {
3124b3a3e18Sagc return 0;
313bcfd8565Sagc }
31493bf6008Sagc
315fc1f8641Sagc if (key->s2k_specifier != PGP_S2KS_SIMPLE &&
316fc1f8641Sagc key->s2k_specifier != PGP_S2KS_SALTED) {
317bcfd8565Sagc /* = 1 \todo could also be iterated-and-salted */
3183326c4c5Sagc (void) fprintf(stderr, "write_seckey_body: s2k spec\n");
3194b3a3e18Sagc return 0;
320ed0df671Sagc }
321fc1f8641Sagc if (!pgp_write_scalar(output, (unsigned)key->s2k_specifier, 1)) {
3224b3a3e18Sagc return 0;
323bcfd8565Sagc }
324fc1f8641Sagc if (!pgp_write_scalar(output, (unsigned)key->hash_alg, 1)) {
3254b3a3e18Sagc return 0;
326bcfd8565Sagc }
32793bf6008Sagc
32893bf6008Sagc switch (key->s2k_specifier) {
329fc1f8641Sagc case PGP_S2KS_SIMPLE:
33093bf6008Sagc /* nothing more to do */
33193bf6008Sagc break;
33293bf6008Sagc
333fc1f8641Sagc case PGP_S2KS_SALTED:
33493bf6008Sagc /* 8-octet salt value */
335fc1f8641Sagc pgp_random(__UNCONST(&key->salt[0]), PGP_SALT_SIZE);
336fc1f8641Sagc if (!pgp_write(output, key->salt, PGP_SALT_SIZE)) {
3374b3a3e18Sagc return 0;
338bcfd8565Sagc }
33993bf6008Sagc break;
34093bf6008Sagc
34193bf6008Sagc /*
342fc1f8641Sagc * \todo case PGP_S2KS_ITERATED_AND_SALTED: // 8-octet salt
34393bf6008Sagc * value // 1-octet count break;
34493bf6008Sagc */
34593bf6008Sagc
34693bf6008Sagc default:
347bcfd8565Sagc (void) fprintf(stderr,
348bcfd8565Sagc "invalid/unsupported s2k specifier %d\n",
349bcfd8565Sagc key->s2k_specifier);
3504b3a3e18Sagc return 0;
35193bf6008Sagc }
35293bf6008Sagc
353fc1f8641Sagc if (!pgp_write(output, &key->iv[0], pgp_block_size(key->alg))) {
3544b3a3e18Sagc return 0;
355bcfd8565Sagc }
35693bf6008Sagc
35793bf6008Sagc /*
35893bf6008Sagc * create the session key for encrypting the algorithm-specific
35993bf6008Sagc * fields
36093bf6008Sagc */
36193bf6008Sagc
36293bf6008Sagc switch (key->s2k_specifier) {
363fc1f8641Sagc case PGP_S2KS_SIMPLE:
364fc1f8641Sagc case PGP_S2KS_SALTED:
36593bf6008Sagc /* RFC4880: section 3.7.1.1 and 3.7.1.2 */
36693bf6008Sagc
3675a83dba0Sagc for (done = 0, i = 0; done < CAST_KEY_LENGTH; i++) {
36805e6b0bbSagc unsigned hashsize;
3695a83dba0Sagc unsigned j;
37005e6b0bbSagc unsigned needed;
37105e6b0bbSagc unsigned size;
372b15ec256Sagc uint8_t zero = 0;
37393bf6008Sagc
37405e6b0bbSagc /* Hard-coded SHA1 for session key */
37505e6b0bbSagc pgp_hash_any(&hash, PGP_HASH_SHA1);
37605e6b0bbSagc hashsize = pgp_hash_size(key->hash_alg);
3772232f800Sagc needed = CAST_KEY_LENGTH - done;
37805e6b0bbSagc size = MIN(needed, hashsize);
37905e6b0bbSagc if ((hashed = calloc(1, hashsize)) == NULL) {
38005e6b0bbSagc (void) fprintf(stderr, "write_seckey_body: bad alloc\n");
38105e6b0bbSagc return 0;
38205e6b0bbSagc }
3837affbacaSagc if (!hash.init(&hash)) {
3847affbacaSagc (void) fprintf(stderr, "write_seckey_body: bad alloc\n");
3857affbacaSagc return 0;
3867affbacaSagc }
38793bf6008Sagc
38893bf6008Sagc /* preload if iterating */
38993bf6008Sagc for (j = 0; j < i; j++) {
39093bf6008Sagc /*
39193bf6008Sagc * Coverity shows a DEADCODE error on this
39293bf6008Sagc * line. This is expected since the hardcoded
39393bf6008Sagc * use of SHA1 and CAST5 means that it will
39493bf6008Sagc * not used. This will change however when
39593bf6008Sagc * other algorithms are supported.
39693bf6008Sagc */
39793bf6008Sagc hash.add(&hash, &zero, 1);
39893bf6008Sagc }
39993bf6008Sagc
400fc1f8641Sagc if (key->s2k_specifier == PGP_S2KS_SALTED) {
401fc1f8641Sagc hash.add(&hash, key->salt, PGP_SALT_SIZE);
40293bf6008Sagc }
40369d4f30fSagc hash.add(&hash, passphrase, (unsigned)pplen);
40493bf6008Sagc hash.finish(&hash, hashed);
40593bf6008Sagc
40693bf6008Sagc /*
40793bf6008Sagc * if more in hash than is needed by session key, use
40893bf6008Sagc * the leftmost octets
40993bf6008Sagc */
41005e6b0bbSagc (void) memcpy(&sesskey[i * hashsize],
411d21b929eSagc hashed, (unsigned)size);
4125a83dba0Sagc done += (unsigned)size;
413ed0df671Sagc if (done > CAST_KEY_LENGTH) {
414ed0df671Sagc (void) fprintf(stderr,
4153326c4c5Sagc "write_seckey_body: short add\n");
4164b3a3e18Sagc return 0;
417ed0df671Sagc }
41893bf6008Sagc }
41993bf6008Sagc
42093bf6008Sagc break;
42193bf6008Sagc
42293bf6008Sagc /*
423fc1f8641Sagc * \todo case PGP_S2KS_ITERATED_AND_SALTED: * 8-octet salt
42493bf6008Sagc * value * 1-octet count break;
42593bf6008Sagc */
42693bf6008Sagc
42793bf6008Sagc default:
428bcfd8565Sagc (void) fprintf(stderr,
429bcfd8565Sagc "invalid/unsupported s2k specifier %d\n",
430bcfd8565Sagc key->s2k_specifier);
4314b3a3e18Sagc return 0;
43293bf6008Sagc }
43393bf6008Sagc
43493bf6008Sagc /* use this session key to encrypt */
43593bf6008Sagc
436fc1f8641Sagc pgp_crypt_any(&crypted, key->alg);
43793bf6008Sagc crypted.set_iv(&crypted, key->iv);
438f72138f8Sagc crypted.set_crypt_key(&crypted, sesskey);
439fc1f8641Sagc pgp_encrypt_init(&crypted);
44093bf6008Sagc
441fc1f8641Sagc if (pgp_get_debug_level(__FILE__)) {
442fc1f8641Sagc hexdump(stderr, "writing: iv=", key->iv, pgp_block_size(key->alg));
44347561e26Sagc hexdump(stderr, "key= ", sesskey, CAST_KEY_LENGTH);
444651dd288Sagc (void) fprintf(stderr, "\nturning encryption on...\n");
44593bf6008Sagc }
446fc1f8641Sagc pgp_push_enc_crypt(output, &crypted);
44793bf6008Sagc
4482232f800Sagc switch (key->pubkey.alg) {
449fc1f8641Sagc case PGP_PKA_RSA:
450fc1f8641Sagc case PGP_PKA_RSA_ENCRYPT_ONLY:
451fc1f8641Sagc case PGP_PKA_RSA_SIGN_ONLY:
452fc1f8641Sagc if (!pgp_write_mpi(output, key->key.rsa.d) ||
453fc1f8641Sagc !pgp_write_mpi(output, key->key.rsa.p) ||
454fc1f8641Sagc !pgp_write_mpi(output, key->key.rsa.q) ||
455fc1f8641Sagc !pgp_write_mpi(output, key->key.rsa.u)) {
456fc1f8641Sagc if (pgp_get_debug_level(__FILE__)) {
4573326c4c5Sagc (void) fprintf(stderr,
4583326c4c5Sagc "4 x mpi not written - problem\n");
45993bf6008Sagc }
4604b3a3e18Sagc return 0;
46193bf6008Sagc }
46293bf6008Sagc break;
463fc1f8641Sagc case PGP_PKA_DSA:
464fc1f8641Sagc return pgp_write_mpi(output, key->key.dsa.x);
465fc1f8641Sagc case PGP_PKA_ELGAMAL:
466fc1f8641Sagc return pgp_write_mpi(output, key->key.elgamal.x);
46793bf6008Sagc default:
4684b3a3e18Sagc return 0;
46993bf6008Sagc }
47093bf6008Sagc
471fc1f8641Sagc if (!pgp_write(output, key->checkhash, PGP_CHECKHASH_SIZE)) {
4724b3a3e18Sagc return 0;
473bcfd8565Sagc }
47493bf6008Sagc
475fc1f8641Sagc pgp_writer_pop(output);
47693bf6008Sagc
4774b3a3e18Sagc return 1;
47893bf6008Sagc }
47993bf6008Sagc
48057324b9fSagc /**
48157324b9fSagc * \ingroup Core_WritePackets
48257324b9fSagc * \brief Writes a Public Key packet
48357324b9fSagc * \param key
48457324b9fSagc * \param output
48557324b9fSagc * \return 1 if OK, otherwise 0
48657324b9fSagc */
48757324b9fSagc static unsigned
write_struct_pubkey(pgp_output_t * output,const pgp_pubkey_t * key)488fc1f8641Sagc write_struct_pubkey(pgp_output_t *output, const pgp_pubkey_t *key)
48957324b9fSagc {
490fc1f8641Sagc return pgp_write_ptag(output, PGP_PTAG_CT_PUBLIC_KEY) &&
491fc1f8641Sagc pgp_write_length(output, 1 + 4 + 1 + pubkey_length(key)) &&
49257324b9fSagc write_pubkey_body(key, output);
49357324b9fSagc }
49457324b9fSagc
49593bf6008Sagc
49693bf6008Sagc /**
49793bf6008Sagc \ingroup HighLevel_KeyWrite
49893bf6008Sagc
49993bf6008Sagc \brief Writes a transferable PGP public key to the given output stream.
50093bf6008Sagc
50193bf6008Sagc \param keydata Key to be written
50293bf6008Sagc \param armoured Flag is set for armoured output
50357324b9fSagc \param output Output stream
50493bf6008Sagc
50593bf6008Sagc */
50693bf6008Sagc
5074b3a3e18Sagc unsigned
pgp_write_xfer_pubkey(pgp_output_t * output,const pgp_key_t * key,const unsigned armoured)508fc1f8641Sagc pgp_write_xfer_pubkey(pgp_output_t *output,
509fc1f8641Sagc const pgp_key_t *key,
510c64158a1Sagc const unsigned armoured)
51193bf6008Sagc {
512b15ec256Sagc unsigned i, j;
51393bf6008Sagc
51493bf6008Sagc if (armoured) {
515fc1f8641Sagc pgp_writer_push_armoured(output, PGP_PGP_PUBLIC_KEY_BLOCK);
51693bf6008Sagc }
51793bf6008Sagc /* public key */
51844647216Sagc if (!write_struct_pubkey(output, &key->key.pubkey)) {
51957324b9fSagc return 0;
520bcfd8565Sagc }
52193bf6008Sagc
52293bf6008Sagc /* TODO: revocation signatures go here */
52393bf6008Sagc
52493bf6008Sagc /* user ids and corresponding signatures */
5255aae2c74Sagc for (i = 0; i < key->uidc; i++) {
526fc1f8641Sagc if (!pgp_write_struct_userid(output, key->uids[i])) {
52757324b9fSagc return 0;
528bcfd8565Sagc }
5295aae2c74Sagc for (j = 0; j < key->packetc; j++) {
530fc1f8641Sagc if (!pgp_write(output, key->packets[j].raw, (unsigned)key->packets[j].length)) {
53157324b9fSagc return 0;
53293bf6008Sagc }
53393bf6008Sagc }
53493bf6008Sagc }
53593bf6008Sagc
53693bf6008Sagc /* TODO: user attributes and corresponding signatures */
53793bf6008Sagc
53893bf6008Sagc /*
53993bf6008Sagc * subkey packets and corresponding signatures and optional
54093bf6008Sagc * revocation
54193bf6008Sagc */
54293bf6008Sagc
54393bf6008Sagc if (armoured) {
544fc1f8641Sagc pgp_writer_info_finalise(&output->errors, &output->writer);
545fc1f8641Sagc pgp_writer_pop(output);
54693bf6008Sagc }
54757324b9fSagc return 1;
54893bf6008Sagc }
54993bf6008Sagc
55093bf6008Sagc /**
55193bf6008Sagc \ingroup HighLevel_KeyWrite
55293bf6008Sagc
55393bf6008Sagc \brief Writes a transferable PGP secret key to the given output stream.
55493bf6008Sagc
55593bf6008Sagc \param keydata Key to be written
55693bf6008Sagc \param passphrase
55793bf6008Sagc \param pplen
55893bf6008Sagc \param armoured Flag is set for armoured output
55957324b9fSagc \param output Output stream
56093bf6008Sagc
56193bf6008Sagc */
56293bf6008Sagc
5634b3a3e18Sagc unsigned
pgp_write_xfer_seckey(pgp_output_t * output,const pgp_key_t * key,const uint8_t * passphrase,const size_t pplen,unsigned armoured)564fc1f8641Sagc pgp_write_xfer_seckey(pgp_output_t *output,
565fc1f8641Sagc const pgp_key_t *key,
566b15ec256Sagc const uint8_t *passphrase,
56757324b9fSagc const size_t pplen,
56857324b9fSagc unsigned armoured)
56993bf6008Sagc {
5705a83dba0Sagc unsigned i, j;
57193bf6008Sagc
57293bf6008Sagc if (armoured) {
573fc1f8641Sagc pgp_writer_push_armoured(output, PGP_PGP_PRIVATE_KEY_BLOCK);
57493bf6008Sagc }
57593bf6008Sagc /* public key */
576fc1f8641Sagc if (!pgp_write_struct_seckey(&key->key.seckey, passphrase,
57757324b9fSagc pplen, output)) {
57857324b9fSagc return 0;
579bcfd8565Sagc }
58093bf6008Sagc
58193bf6008Sagc /* TODO: revocation signatures go here */
58293bf6008Sagc
58393bf6008Sagc /* user ids and corresponding signatures */
5845aae2c74Sagc for (i = 0; i < key->uidc; i++) {
585fc1f8641Sagc if (!pgp_write_struct_userid(output, key->uids[i])) {
58657324b9fSagc return 0;
587bcfd8565Sagc }
5885aae2c74Sagc for (j = 0; j < key->packetc; j++) {
589fc1f8641Sagc if (!pgp_write(output, key->packets[j].raw, (unsigned)key->packets[j].length)) {
59057324b9fSagc return 0;
59193bf6008Sagc }
59293bf6008Sagc }
59393bf6008Sagc }
59493bf6008Sagc
59593bf6008Sagc /* TODO: user attributes and corresponding signatures */
59693bf6008Sagc
59793bf6008Sagc /*
59893bf6008Sagc * subkey packets and corresponding signatures and optional
59993bf6008Sagc * revocation
60093bf6008Sagc */
60193bf6008Sagc
60293bf6008Sagc if (armoured) {
603fc1f8641Sagc pgp_writer_info_finalise(&output->errors, &output->writer);
604fc1f8641Sagc pgp_writer_pop(output);
60593bf6008Sagc }
60657324b9fSagc return 1;
60793bf6008Sagc }
60893bf6008Sagc
60993bf6008Sagc /**
61093bf6008Sagc * \ingroup Core_WritePackets
61193bf6008Sagc * \brief Writes one RSA public key packet.
61293bf6008Sagc * \param t Creation time
61393bf6008Sagc * \param n RSA public modulus
61493bf6008Sagc * \param e RSA public encryption exponent
61557324b9fSagc * \param output Writer settings
61693bf6008Sagc *
6174b3a3e18Sagc * \return 1 if OK, otherwise 0
61893bf6008Sagc */
61993bf6008Sagc
6204b3a3e18Sagc unsigned
pgp_write_rsa_pubkey(time_t t,const BIGNUM * n,const BIGNUM * e,pgp_output_t * output)621fc1f8641Sagc pgp_write_rsa_pubkey(time_t t, const BIGNUM *n,
62293bf6008Sagc const BIGNUM *e,
623fc1f8641Sagc pgp_output_t *output)
62493bf6008Sagc {
625fc1f8641Sagc pgp_pubkey_t key;
62693bf6008Sagc
627fc1f8641Sagc pgp_fast_create_rsa_pubkey(&key, t, __UNCONST(n), __UNCONST(e));
62857324b9fSagc return write_struct_pubkey(output, &key);
62993bf6008Sagc }
63093bf6008Sagc
63193bf6008Sagc /**
63293bf6008Sagc * \ingroup Core_Create
63393bf6008Sagc * \param out
63493bf6008Sagc * \param key
63593bf6008Sagc * \param make_packet
63693bf6008Sagc */
63793bf6008Sagc
63893bf6008Sagc void
pgp_build_pubkey(pgp_memory_t * out,const pgp_pubkey_t * key,unsigned make_packet)639fc1f8641Sagc pgp_build_pubkey(pgp_memory_t *out, const pgp_pubkey_t *key,
6404b3a3e18Sagc unsigned make_packet)
64193bf6008Sagc {
642fc1f8641Sagc pgp_output_t *output;
64393bf6008Sagc
644fc1f8641Sagc output = pgp_output_new();
645fc1f8641Sagc pgp_memory_init(out, 128);
646fc1f8641Sagc pgp_writer_set_memory(output, out);
64757324b9fSagc write_pubkey_body(key, output);
648bcfd8565Sagc if (make_packet) {
649fc1f8641Sagc pgp_memory_make_packet(out, PGP_PTAG_CT_PUBLIC_KEY);
650bcfd8565Sagc }
651fc1f8641Sagc pgp_output_delete(output);
65293bf6008Sagc }
65393bf6008Sagc
65493bf6008Sagc /**
65593bf6008Sagc * \ingroup Core_Create
65693bf6008Sagc *
65793bf6008Sagc * Create an RSA secret key structure. If a parameter is marked as
65893bf6008Sagc * [OPTIONAL], then it can be omitted and will be calculated from
65941335e2dSagc * other params - or, in the case of e, will default to 0x10001.
66093bf6008Sagc *
66193bf6008Sagc * Parameters are _not_ copied, so will be freed if the structure is
66293bf6008Sagc * freed.
66393bf6008Sagc *
66493bf6008Sagc * \param key The key structure to be initialised.
66593bf6008Sagc * \param t
66693bf6008Sagc * \param d The RSA parameter d (=e^-1 mod (p-1)(q-1)) [OPTIONAL]
66793bf6008Sagc * \param p The RSA parameter p
66893bf6008Sagc * \param q The RSA parameter q (q > p)
66993bf6008Sagc * \param u The RSA parameter u (=p^-1 mod q) [OPTIONAL]
67093bf6008Sagc * \param n The RSA public parameter n (=p*q) [OPTIONAL]
67193bf6008Sagc * \param e The RSA public parameter e */
67293bf6008Sagc
67393bf6008Sagc void
pgp_fast_create_rsa_seckey(pgp_seckey_t * key,time_t t,BIGNUM * d,BIGNUM * p,BIGNUM * q,BIGNUM * u,BIGNUM * n,BIGNUM * e)674fc1f8641Sagc pgp_fast_create_rsa_seckey(pgp_seckey_t *key, time_t t,
67593bf6008Sagc BIGNUM *d, BIGNUM *p, BIGNUM *q, BIGNUM *u,
67693bf6008Sagc BIGNUM *n, BIGNUM *e)
67793bf6008Sagc {
678fc1f8641Sagc pgp_fast_create_rsa_pubkey(&key->pubkey, t, n, e);
67993bf6008Sagc
68093bf6008Sagc /* XXX: calculate optionals */
68193bf6008Sagc key->key.rsa.d = d;
68293bf6008Sagc key->key.rsa.p = p;
68393bf6008Sagc key->key.rsa.q = q;
68493bf6008Sagc key->key.rsa.u = u;
68593bf6008Sagc
686fc1f8641Sagc key->s2k_usage = PGP_S2KU_NONE;
68793bf6008Sagc
68893bf6008Sagc /* XXX: sanity check and add errors... */
68993bf6008Sagc }
69093bf6008Sagc
69193bf6008Sagc /**
69293bf6008Sagc * \ingroup Core_WritePackets
69393bf6008Sagc * \brief Writes a Secret Key packet.
69493bf6008Sagc * \param key The secret key
69593bf6008Sagc * \param passphrase The passphrase
69693bf6008Sagc * \param pplen Length of passphrase
69757324b9fSagc * \param output
6984b3a3e18Sagc * \return 1 if OK; else 0
69993bf6008Sagc */
7004b3a3e18Sagc unsigned
pgp_write_struct_seckey(const pgp_seckey_t * key,const uint8_t * passphrase,const size_t pplen,pgp_output_t * output)701fc1f8641Sagc pgp_write_struct_seckey(const pgp_seckey_t *key,
702b15ec256Sagc const uint8_t *passphrase,
70393bf6008Sagc const size_t pplen,
704fc1f8641Sagc pgp_output_t *output)
70593bf6008Sagc {
70693bf6008Sagc int length = 0;
70793bf6008Sagc
708ed0df671Sagc if (key->pubkey.version != 4) {
709ed0df671Sagc (void) fprintf(stderr,
710fc1f8641Sagc "pgp_write_struct_seckey: public key version\n");
7114b3a3e18Sagc return 0;
712ed0df671Sagc }
71393bf6008Sagc
71493bf6008Sagc /* Ref: RFC4880 Section 5.5.3 */
71593bf6008Sagc
716bcfd8565Sagc /* pubkey, excluding MPIs */
71793bf6008Sagc length += 1 + 4 + 1 + 1;
71893bf6008Sagc
71993bf6008Sagc /* s2k usage */
72093bf6008Sagc length += 1;
72193bf6008Sagc
72293bf6008Sagc switch (key->s2k_usage) {
723fc1f8641Sagc case PGP_S2KU_NONE:
72493bf6008Sagc /* nothing to add */
72593bf6008Sagc break;
72693bf6008Sagc
727fc1f8641Sagc case PGP_S2KU_ENCRYPTED_AND_HASHED: /* 254 */
728fc1f8641Sagc case PGP_S2KU_ENCRYPTED: /* 255 */
72993bf6008Sagc
73093bf6008Sagc /* Ref: RFC4880 Section 3.7 */
73193bf6008Sagc length += 1; /* s2k_specifier */
73293bf6008Sagc
73393bf6008Sagc switch (key->s2k_specifier) {
734fc1f8641Sagc case PGP_S2KS_SIMPLE:
73593bf6008Sagc length += 1; /* hash algorithm */
73693bf6008Sagc break;
73793bf6008Sagc
738fc1f8641Sagc case PGP_S2KS_SALTED:
73993bf6008Sagc length += 1 + 8; /* hash algorithm + salt */
74093bf6008Sagc break;
74193bf6008Sagc
742fc1f8641Sagc case PGP_S2KS_ITERATED_AND_SALTED:
74393bf6008Sagc length += 1 + 8 + 1; /* hash algorithm, salt +
74493bf6008Sagc * count */
74593bf6008Sagc break;
74693bf6008Sagc
74793bf6008Sagc default:
748ed0df671Sagc (void) fprintf(stderr,
749fc1f8641Sagc "pgp_write_struct_seckey: s2k spec\n");
7504b3a3e18Sagc return 0;
75193bf6008Sagc }
75293bf6008Sagc break;
75393bf6008Sagc
75493bf6008Sagc default:
755ed0df671Sagc (void) fprintf(stderr,
756fc1f8641Sagc "pgp_write_struct_seckey: s2k usage\n");
7574b3a3e18Sagc return 0;
75893bf6008Sagc }
75993bf6008Sagc
76093bf6008Sagc /* IV */
7614b3a3e18Sagc if (key->s2k_usage) {
762fc1f8641Sagc length += pgp_block_size(key->alg);
76393bf6008Sagc }
76493bf6008Sagc /* checksum or hash */
76593bf6008Sagc switch (key->s2k_usage) {
766fc1f8641Sagc case PGP_S2KU_NONE:
767fc1f8641Sagc case PGP_S2KU_ENCRYPTED:
76893bf6008Sagc length += 2;
76993bf6008Sagc break;
77093bf6008Sagc
771fc1f8641Sagc case PGP_S2KU_ENCRYPTED_AND_HASHED:
772fc1f8641Sagc length += PGP_CHECKHASH_SIZE;
77393bf6008Sagc break;
77493bf6008Sagc
77593bf6008Sagc default:
776ed0df671Sagc (void) fprintf(stderr,
777fc1f8641Sagc "pgp_write_struct_seckey: s2k cksum usage\n");
7784b3a3e18Sagc return 0;
77993bf6008Sagc }
78093bf6008Sagc
78193bf6008Sagc /* secret key and public key MPIs */
7825a83dba0Sagc length += (unsigned)seckey_length(key);
78393bf6008Sagc
784fc1f8641Sagc return pgp_write_ptag(output, PGP_PTAG_CT_SECRET_KEY) &&
785fc1f8641Sagc /* pgp_write_length(output,1+4+1+1+seckey_length(key)+2) && */
786fc1f8641Sagc pgp_write_length(output, (unsigned)length) &&
78757324b9fSagc write_seckey_body(key, passphrase, pplen, output);
78893bf6008Sagc }
78993bf6008Sagc
79093bf6008Sagc /**
79193bf6008Sagc * \ingroup Core_Create
79293bf6008Sagc *
793fc1f8641Sagc * \brief Create a new pgp_output_t structure.
79493bf6008Sagc *
79593bf6008Sagc * \return the new structure.
796fc1f8641Sagc * \note It is the responsiblity of the caller to call pgp_output_delete().
797fc1f8641Sagc * \sa pgp_output_delete()
79893bf6008Sagc */
799fc1f8641Sagc pgp_output_t *
pgp_output_new(void)800fc1f8641Sagc pgp_output_new(void)
80193bf6008Sagc {
802fc1f8641Sagc return calloc(1, sizeof(pgp_output_t));
80393bf6008Sagc }
80493bf6008Sagc
80593bf6008Sagc /**
80693bf6008Sagc * \ingroup Core_Create
807fc1f8641Sagc * \brief Delete an pgp_output_t strucut and associated resources.
80893bf6008Sagc *
809fc1f8641Sagc * Delete an pgp_output_t structure. If a writer is active, then
81093bf6008Sagc * that is also deleted.
81193bf6008Sagc *
81293bf6008Sagc * \param info the structure to be deleted.
81393bf6008Sagc */
81493bf6008Sagc void
pgp_output_delete(pgp_output_t * output)815fc1f8641Sagc pgp_output_delete(pgp_output_t *output)
81693bf6008Sagc {
817fc1f8641Sagc pgp_writer_info_delete(&output->writer);
8185a83dba0Sagc free(output);
81993bf6008Sagc }
82093bf6008Sagc
82193bf6008Sagc /**
82293bf6008Sagc \ingroup Core_Create
82393bf6008Sagc \brief Calculate the checksum for a session key
8242232f800Sagc \param sesskey Session Key to use
82593bf6008Sagc \param cs Checksum to be written
8264b3a3e18Sagc \return 1 if OK; else 0
82793bf6008Sagc */
8284b3a3e18Sagc unsigned
pgp_calc_sesskey_checksum(pgp_pk_sesskey_t * sesskey,uint8_t cs[2])829fc1f8641Sagc pgp_calc_sesskey_checksum(pgp_pk_sesskey_t *sesskey, uint8_t cs[2])
83093bf6008Sagc {
831b15ec256Sagc uint32_t checksum = 0;
832b15ec256Sagc unsigned i;
83393bf6008Sagc
834fc1f8641Sagc if (!pgp_is_sa_supported(sesskey->symm_alg)) {
8354b3a3e18Sagc return 0;
836bcfd8565Sagc }
83793bf6008Sagc
838fc1f8641Sagc for (i = 0; i < pgp_key_size(sesskey->symm_alg); i++) {
8392232f800Sagc checksum += sesskey->key[i];
84093bf6008Sagc }
84193bf6008Sagc checksum = checksum % 65536;
84293bf6008Sagc
843b15ec256Sagc cs[0] = (uint8_t)((checksum >> 8) & 0xff);
844b15ec256Sagc cs[1] = (uint8_t)(checksum & 0xff);
84593bf6008Sagc
846fc1f8641Sagc if (pgp_get_debug_level(__FILE__)) {
84747561e26Sagc hexdump(stderr, "nm buf checksum:", cs, 2);
848efdd9dbaSagc }
8494b3a3e18Sagc return 1;
85093bf6008Sagc }
85193bf6008Sagc
8524b3a3e18Sagc static unsigned
create_unencoded_m_buf(pgp_pk_sesskey_t * sesskey,pgp_crypt_t * cipherinfo,uint8_t * m_buf)853fc1f8641Sagc create_unencoded_m_buf(pgp_pk_sesskey_t *sesskey, pgp_crypt_t *cipherinfo, uint8_t *m_buf)
85493bf6008Sagc {
855f7745f84Sagc unsigned i;
85693bf6008Sagc
857f7745f84Sagc /* m_buf is the buffer which will be encoded in PKCS#1 block
858f7745f84Sagc * encoding to form the "m" value used in the Public Key
859f7745f84Sagc * Encrypted Session Key Packet as defined in RFC Section 5.1
860f7745f84Sagc * "Public-Key Encrypted Session Key Packet"
86193bf6008Sagc */
8622232f800Sagc m_buf[0] = sesskey->symm_alg;
863f7745f84Sagc for (i = 0; i < cipherinfo->keysize ; i++) {
8645a83dba0Sagc /* XXX - Flexelint - Warning 679: Suspicious Truncation in arithmetic expression combining with pointer */
8652232f800Sagc m_buf[1 + i] = sesskey->key[i];
86693bf6008Sagc }
86793bf6008Sagc
868fc1f8641Sagc return pgp_calc_sesskey_checksum(sesskey,
869f7745f84Sagc m_buf + 1 + cipherinfo->keysize);
87093bf6008Sagc }
87193bf6008Sagc
87293bf6008Sagc /**
87393bf6008Sagc \ingroup Core_Create
87493bf6008Sagc \brief implementation of EME-PKCS1-v1_5-ENCODE, as defined in OpenPGP RFC
87593bf6008Sagc \param M
87693bf6008Sagc \param mLen
8770c310959Sagc \param pubkey
87893bf6008Sagc \param EM
8794b3a3e18Sagc \return 1 if OK; else 0
88093bf6008Sagc */
8814b3a3e18Sagc unsigned
encode_m_buf(const uint8_t * M,size_t mLen,const pgp_pubkey_t * pubkey,uint8_t * EM)882fc1f8641Sagc encode_m_buf(const uint8_t *M, size_t mLen, const pgp_pubkey_t * pubkey,
883b15ec256Sagc uint8_t *EM)
88493bf6008Sagc {
885b15ec256Sagc unsigned k;
88693bf6008Sagc unsigned i;
88793bf6008Sagc
88893bf6008Sagc /* implementation of EME-PKCS1-v1_5-ENCODE, as defined in OpenPGP RFC */
889520c968fSagc switch (pubkey->alg) {
890fc1f8641Sagc case PGP_PKA_RSA:
8915a83dba0Sagc k = (unsigned)BN_num_bytes(pubkey->key.rsa.n);
89293bf6008Sagc if (mLen > k - 11) {
893ed0df671Sagc (void) fprintf(stderr, "encode_m_buf: message too long\n");
8944b3a3e18Sagc return 0;
89593bf6008Sagc }
89637d8b79bSagc break;
897fc1f8641Sagc case PGP_PKA_DSA:
898fc1f8641Sagc case PGP_PKA_ELGAMAL:
89937d8b79bSagc k = (unsigned)BN_num_bytes(pubkey->key.elgamal.p);
90037d8b79bSagc if (mLen > k - 11) {
90137d8b79bSagc (void) fprintf(stderr, "encode_m_buf: message too long\n");
90237d8b79bSagc return 0;
90337d8b79bSagc }
90437d8b79bSagc break;
90537d8b79bSagc default:
90637d8b79bSagc (void) fprintf(stderr, "encode_m_buf: pubkey algorithm\n");
90737d8b79bSagc return 0;
90837d8b79bSagc }
90993bf6008Sagc /* these two bytes defined by RFC */
91093bf6008Sagc EM[0] = 0x00;
91193bf6008Sagc EM[1] = 0x02;
91293bf6008Sagc /* add non-zero random bytes of length k - mLen -3 */
9135a83dba0Sagc for (i = 2; i < (k - mLen) - 1; ++i) {
914bcfd8565Sagc do {
915fc1f8641Sagc pgp_random(EM + i, 1);
916bcfd8565Sagc } while (EM[i] == 0);
917bcfd8565Sagc }
918ed0df671Sagc if (i < 8 + 2) {
919ed0df671Sagc (void) fprintf(stderr, "encode_m_buf: bad i len\n");
9204b3a3e18Sagc return 0;
921ed0df671Sagc }
92293bf6008Sagc EM[i++] = 0;
92393bf6008Sagc (void) memcpy(EM + i, M, mLen);
924fc1f8641Sagc if (pgp_get_debug_level(__FILE__)) {
92547561e26Sagc hexdump(stderr, "Encoded Message:", EM, mLen);
92693bf6008Sagc }
9274b3a3e18Sagc return 1;
92893bf6008Sagc }
92993bf6008Sagc
93093bf6008Sagc /**
93193bf6008Sagc \ingroup Core_Create
932fc1f8641Sagc \brief Creates an pgp_pk_sesskey_t struct from keydata
93393bf6008Sagc \param key Keydata to use
934fc1f8641Sagc \return pgp_pk_sesskey_t struct
93593bf6008Sagc \note It is the caller's responsiblity to free the returned pointer
93693bf6008Sagc \note Currently hard-coded to use CAST5
93793bf6008Sagc \note Currently hard-coded to use RSA
93893bf6008Sagc */
939fc1f8641Sagc pgp_pk_sesskey_t *
pgp_create_pk_sesskey(const pgp_key_t * key,const char * ciphername)940fc1f8641Sagc pgp_create_pk_sesskey(const pgp_key_t *key, const char *ciphername)
94193bf6008Sagc {
94293bf6008Sagc /*
94393bf6008Sagc * Creates a random session key and encrypts it for the given key
94493bf6008Sagc *
94593bf6008Sagc * Encryption used is PK,
94693bf6008Sagc * can be any, we're hardcoding RSA for now
94793bf6008Sagc */
94893bf6008Sagc
949fc1f8641Sagc const pgp_pubkey_t *pubkey;
950fc1f8641Sagc pgp_pk_sesskey_t *sesskey;
951fc1f8641Sagc pgp_symm_alg_t cipher;
9529b987001Sagc const uint8_t *id;
953fc1f8641Sagc pgp_crypt_t cipherinfo;
954f7745f84Sagc uint8_t *unencoded_m_buf;
955b15ec256Sagc uint8_t *encoded_m_buf;
9565a83dba0Sagc size_t sz_encoded_m_buf;
9575a83dba0Sagc
9589b987001Sagc if (memcmp(key->encid, "\0\0\0\0\0\0\0\0", 8) == 0) {
959fc1f8641Sagc pubkey = pgp_get_pubkey(key);
9609b987001Sagc id = key->sigid;
9619b987001Sagc } else {
9629b987001Sagc pubkey = &key->enckey;
9639b987001Sagc id = key->encid;
9649b987001Sagc }
965f7745f84Sagc /* allocate unencoded_m_buf here */
966f7745f84Sagc (void) memset(&cipherinfo, 0x0, sizeof(cipherinfo));
967fc1f8641Sagc pgp_crypt_any(&cipherinfo,
968fc1f8641Sagc cipher = pgp_str_to_cipher((ciphername) ? ciphername : "cast5"));
969f7745f84Sagc unencoded_m_buf = calloc(1, cipherinfo.keysize + 1 + 2);
970f7745f84Sagc if (unencoded_m_buf == NULL) {
971f7745f84Sagc (void) fprintf(stderr,
972fc1f8641Sagc "pgp_create_pk_sesskey: can't allocate\n");
973f7745f84Sagc return NULL;
974f7745f84Sagc }
97537d8b79bSagc switch(pubkey->alg) {
976fc1f8641Sagc case PGP_PKA_RSA:
9775a83dba0Sagc sz_encoded_m_buf = BN_num_bytes(pubkey->key.rsa.n);
97837d8b79bSagc break;
979fc1f8641Sagc case PGP_PKA_DSA:
980fc1f8641Sagc case PGP_PKA_ELGAMAL:
98137d8b79bSagc sz_encoded_m_buf = BN_num_bytes(pubkey->key.elgamal.p);
98237d8b79bSagc break;
98337d8b79bSagc default:
98437d8b79bSagc sz_encoded_m_buf = 0;
98537d8b79bSagc break;
98637d8b79bSagc }
9875a83dba0Sagc if ((encoded_m_buf = calloc(1, sz_encoded_m_buf)) == NULL) {
9885a83dba0Sagc (void) fprintf(stderr,
989fc1f8641Sagc "pgp_create_pk_sesskey: can't allocate\n");
990f7745f84Sagc free(unencoded_m_buf);
9915a83dba0Sagc return NULL;
9925a83dba0Sagc }
9935a83dba0Sagc if ((sesskey = calloc(1, sizeof(*sesskey))) == NULL) {
9945a83dba0Sagc (void) fprintf(stderr,
995fc1f8641Sagc "pgp_create_pk_sesskey: can't allocate\n");
996f7745f84Sagc free(unencoded_m_buf);
9970aa60872Sagc free(encoded_m_buf);
9985a83dba0Sagc return NULL;
9995a83dba0Sagc }
1000fc1f8641Sagc if (key->type != PGP_PTAG_CT_PUBLIC_KEY) {
1001ed0df671Sagc (void) fprintf(stderr,
1002fc1f8641Sagc "pgp_create_pk_sesskey: bad type\n");
1003f7745f84Sagc free(unencoded_m_buf);
10040aa60872Sagc free(encoded_m_buf);
10050aa60872Sagc free(sesskey);
1006ed0df671Sagc return NULL;
1007ed0df671Sagc }
1008fc1f8641Sagc sesskey->version = PGP_PKSK_V3;
10099b987001Sagc (void) memcpy(sesskey->key_id, id, sizeof(sesskey->key_id));
101093bf6008Sagc
1011fc1f8641Sagc if (pgp_get_debug_level(__FILE__)) {
101237d8b79bSagc hexdump(stderr, "Encrypting for keyid", id, sizeof(sesskey->key_id));
101393bf6008Sagc }
10149b987001Sagc switch (pubkey->alg) {
1015fc1f8641Sagc case PGP_PKA_RSA:
1016fc1f8641Sagc case PGP_PKA_DSA:
1017fc1f8641Sagc case PGP_PKA_ELGAMAL:
1018520c968fSagc break;
1019520c968fSagc default:
1020ed0df671Sagc (void) fprintf(stderr,
1021fc1f8641Sagc "pgp_create_pk_sesskey: bad pubkey algorithm\n");
1022f7745f84Sagc free(unencoded_m_buf);
10230aa60872Sagc free(encoded_m_buf);
10240aa60872Sagc free(sesskey);
1025ed0df671Sagc return NULL;
1026ed0df671Sagc }
10279b987001Sagc sesskey->alg = pubkey->alg;
102893bf6008Sagc
1029f7745f84Sagc sesskey->symm_alg = cipher;
1030fc1f8641Sagc pgp_random(sesskey->key, cipherinfo.keysize);
103193bf6008Sagc
1032fc1f8641Sagc if (pgp_get_debug_level(__FILE__)) {
1033f7745f84Sagc hexdump(stderr, "sesskey created", sesskey->key,
1034f7745f84Sagc cipherinfo.keysize + 1 + 2);
103593bf6008Sagc }
1036f7745f84Sagc if (create_unencoded_m_buf(sesskey, &cipherinfo, &unencoded_m_buf[0]) == 0) {
1037f7745f84Sagc free(unencoded_m_buf);
10385a83dba0Sagc free(encoded_m_buf);
10390aa60872Sagc free(sesskey);
104093bf6008Sagc return NULL;
104193bf6008Sagc }
1042fc1f8641Sagc if (pgp_get_debug_level(__FILE__)) {
1043f7745f84Sagc hexdump(stderr, "uuencoded m buf", unencoded_m_buf, cipherinfo.keysize + 1 + 2);
1044bcfd8565Sagc }
1045f7745f84Sagc encode_m_buf(unencoded_m_buf, cipherinfo.keysize + 1 + 2, pubkey, encoded_m_buf);
104693bf6008Sagc
104793bf6008Sagc /* and encrypt it */
1048520c968fSagc switch (key->key.pubkey.alg) {
1049fc1f8641Sagc case PGP_PKA_RSA:
1050fc1f8641Sagc if (!pgp_rsa_encrypt_mpi(encoded_m_buf, sz_encoded_m_buf, pubkey,
105141335e2dSagc &sesskey->params)) {
1052f7745f84Sagc free(unencoded_m_buf);
10535a83dba0Sagc free(encoded_m_buf);
10540aa60872Sagc free(sesskey);
105593bf6008Sagc return NULL;
105693bf6008Sagc }
1057520c968fSagc break;
1058fc1f8641Sagc case PGP_PKA_DSA:
1059fc1f8641Sagc case PGP_PKA_ELGAMAL:
1060fc1f8641Sagc if (!pgp_elgamal_encrypt_mpi(encoded_m_buf, sz_encoded_m_buf, pubkey,
106137d8b79bSagc &sesskey->params)) {
1062f7745f84Sagc free(unencoded_m_buf);
1063520c968fSagc free(encoded_m_buf);
1064520c968fSagc free(sesskey);
1065520c968fSagc return NULL;
106637d8b79bSagc }
106737d8b79bSagc break;
1068520c968fSagc default:
1069520c968fSagc /* will not get here - for lint only */
1070520c968fSagc break;
1071520c968fSagc }
1072f7745f84Sagc free(unencoded_m_buf);
10735a83dba0Sagc free(encoded_m_buf);
10742232f800Sagc return sesskey;
107593bf6008Sagc }
107693bf6008Sagc
107793bf6008Sagc /**
107893bf6008Sagc \ingroup Core_WritePackets
107993bf6008Sagc \brief Writes Public Key Session Key packet
108093bf6008Sagc \param info Write settings
108193bf6008Sagc \param pksk Public Key Session Key to write out
10824b3a3e18Sagc \return 1 if OK; else 0
108393bf6008Sagc */
10844b3a3e18Sagc unsigned
pgp_write_pk_sesskey(pgp_output_t * output,pgp_pk_sesskey_t * pksk)1085fc1f8641Sagc pgp_write_pk_sesskey(pgp_output_t *output, pgp_pk_sesskey_t *pksk)
108693bf6008Sagc {
10875a83dba0Sagc /* XXX - Flexelint - Pointer parameter 'pksk' (line 1076) could be declared as pointing to const */
1088ed0df671Sagc if (pksk == NULL) {
1089ed0df671Sagc (void) fprintf(stderr,
1090fc1f8641Sagc "pgp_write_pk_sesskey: NULL pksk\n");
10914b3a3e18Sagc return 0;
1092ed0df671Sagc }
1093520c968fSagc switch (pksk->alg) {
1094fc1f8641Sagc case PGP_PKA_RSA:
1095fc1f8641Sagc return pgp_write_ptag(output, PGP_PTAG_CT_PK_SESSION_KEY) &&
1096fc1f8641Sagc pgp_write_length(output, (unsigned)(1 + 8 + 1 +
109741335e2dSagc BN_num_bytes(pksk->params.rsa.encrypted_m) + 2)) &&
1098fc1f8641Sagc pgp_write_scalar(output, (unsigned)pksk->version, 1) &&
1099fc1f8641Sagc pgp_write(output, pksk->key_id, 8) &&
1100fc1f8641Sagc pgp_write_scalar(output, (unsigned)pksk->alg, 1) &&
1101fc1f8641Sagc pgp_write_mpi(output, pksk->params.rsa.encrypted_m)
1102fc1f8641Sagc /* ?? && pgp_write_scalar(output, 0, 2); */
110393bf6008Sagc ;
1104fc1f8641Sagc case PGP_PKA_DSA:
1105fc1f8641Sagc case PGP_PKA_ELGAMAL:
1106fc1f8641Sagc return pgp_write_ptag(output, PGP_PTAG_CT_PK_SESSION_KEY) &&
1107fc1f8641Sagc pgp_write_length(output, (unsigned)(1 + 8 + 1 +
110837d8b79bSagc BN_num_bytes(pksk->params.elgamal.g_to_k) + 2 +
110937d8b79bSagc BN_num_bytes(pksk->params.elgamal.encrypted_m) + 2)) &&
1110fc1f8641Sagc pgp_write_scalar(output, (unsigned)pksk->version, 1) &&
1111fc1f8641Sagc pgp_write(output, pksk->key_id, 8) &&
1112fc1f8641Sagc pgp_write_scalar(output, (unsigned)pksk->alg, 1) &&
1113fc1f8641Sagc pgp_write_mpi(output, pksk->params.elgamal.g_to_k) &&
1114fc1f8641Sagc pgp_write_mpi(output, pksk->params.elgamal.encrypted_m)
1115fc1f8641Sagc /* ?? && pgp_write_scalar(output, 0, 2); */
111637d8b79bSagc ;
1117520c968fSagc default:
1118520c968fSagc (void) fprintf(stderr,
1119fc1f8641Sagc "pgp_write_pk_sesskey: bad algorithm\n");
1120520c968fSagc return 0;
1121520c968fSagc }
112293bf6008Sagc }
112393bf6008Sagc
112493bf6008Sagc /**
112593bf6008Sagc \ingroup Core_WritePackets
112693bf6008Sagc \brief Writes MDC packet
112793bf6008Sagc \param hashed Hash for MDC
112857324b9fSagc \param output Write settings
11294b3a3e18Sagc \return 1 if OK; else 0
113093bf6008Sagc */
113193bf6008Sagc
11324b3a3e18Sagc unsigned
pgp_write_mdc(pgp_output_t * output,const uint8_t * hashed)1133fc1f8641Sagc pgp_write_mdc(pgp_output_t *output, const uint8_t *hashed)
113493bf6008Sagc {
113593bf6008Sagc /* write it out */
1136fc1f8641Sagc return pgp_write_ptag(output, PGP_PTAG_CT_MDC) &&
1137fc1f8641Sagc pgp_write_length(output, PGP_SHA1_HASH_SIZE) &&
1138fc1f8641Sagc pgp_write(output, hashed, PGP_SHA1_HASH_SIZE);
113993bf6008Sagc }
114093bf6008Sagc
114193bf6008Sagc /**
114293bf6008Sagc \ingroup Core_WritePackets
114393bf6008Sagc \brief Writes Literal Data packet from buffer
114493bf6008Sagc \param data Buffer to write out
114593bf6008Sagc \param maxlen Max length of buffer
114693bf6008Sagc \param type Literal Data Type
114757324b9fSagc \param output Write settings
11484b3a3e18Sagc \return 1 if OK; else 0
114993bf6008Sagc */
11504b3a3e18Sagc unsigned
pgp_write_litdata(pgp_output_t * output,const uint8_t * data,const int maxlen,const pgp_litdata_enum type)1151fc1f8641Sagc pgp_write_litdata(pgp_output_t *output,
1152b15ec256Sagc const uint8_t *data,
115393bf6008Sagc const int maxlen,
1154fc1f8641Sagc const pgp_litdata_enum type)
115593bf6008Sagc {
115693bf6008Sagc /*
115793bf6008Sagc * RFC4880 does not specify a meaning for filename or date.
115893bf6008Sagc * It is implementation-dependent.
115993bf6008Sagc * We will not implement them.
116093bf6008Sagc */
116193bf6008Sagc /* \todo do we need to check text data for <cr><lf> line endings ? */
1162fc1f8641Sagc return pgp_write_ptag(output, PGP_PTAG_CT_LITDATA) &&
1163fc1f8641Sagc pgp_write_length(output, (unsigned)(1 + 1 + 4 + maxlen)) &&
1164fc1f8641Sagc pgp_write_scalar(output, (unsigned)type, 1) &&
1165fc1f8641Sagc pgp_write_scalar(output, 0, 1) &&
1166fc1f8641Sagc pgp_write_scalar(output, 0, 4) &&
1167fc1f8641Sagc pgp_write(output, data, (unsigned)maxlen);
116893bf6008Sagc }
116993bf6008Sagc
117093bf6008Sagc /**
117193bf6008Sagc \ingroup Core_WritePackets
117293bf6008Sagc \brief Writes Literal Data packet from contents of file
117393bf6008Sagc \param filename Name of file to read from
117493bf6008Sagc \param type Literal Data Type
117557324b9fSagc \param output Write settings
11764b3a3e18Sagc \return 1 if OK; else 0
117793bf6008Sagc */
117893bf6008Sagc
11794b3a3e18Sagc unsigned
pgp_fileread_litdata(const char * filename,const pgp_litdata_enum type,pgp_output_t * output)1180fc1f8641Sagc pgp_fileread_litdata(const char *filename,
1181fc1f8641Sagc const pgp_litdata_enum type,
1182fc1f8641Sagc pgp_output_t *output)
118393bf6008Sagc {
1184fc1f8641Sagc pgp_memory_t *mem;
118557324b9fSagc unsigned ret;
118638beab94Sagc int len;
118793bf6008Sagc
1188fc1f8641Sagc mem = pgp_memory_new();
1189fc1f8641Sagc if (!pgp_mem_readfile(mem, filename)) {
1190fc1f8641Sagc (void) fprintf(stderr, "pgp_mem_readfile of '%s' failed\n", filename);
11910df5e957Sagc return 0;
119285073018Sagc }
1193fc1f8641Sagc len = (int)pgp_mem_len(mem);
1194fc1f8641Sagc ret = pgp_write_litdata(output, pgp_mem_data(mem), len, type);
1195fc1f8641Sagc pgp_memory_free(mem);
119657324b9fSagc return ret;
119793bf6008Sagc }
119893bf6008Sagc
119993bf6008Sagc /**
120093bf6008Sagc \ingroup HighLevel_General
120193bf6008Sagc
1202efdd9dbaSagc \brief Writes contents of buffer into file
120393bf6008Sagc
120493bf6008Sagc \param filename Filename to write to
120593bf6008Sagc \param buf Buffer to write to file
120693bf6008Sagc \param len Size of buffer
120793bf6008Sagc \param overwrite Flag to set whether to overwrite an existing file
120893bf6008Sagc \return 1 if OK; 0 if error
120993bf6008Sagc */
121093bf6008Sagc
121193bf6008Sagc int
pgp_filewrite(const char * filename,const char * buf,const size_t len,const unsigned overwrite)1212fc1f8641Sagc pgp_filewrite(const char *filename, const char *buf,
12134b3a3e18Sagc const size_t len, const unsigned overwrite)
121493bf6008Sagc {
12155a83dba0Sagc int flags;
12165a83dba0Sagc int fd;
121793bf6008Sagc
121893bf6008Sagc flags = O_WRONLY | O_CREAT;
12194b3a3e18Sagc if (overwrite) {
122093bf6008Sagc flags |= O_TRUNC;
1221de704779Sagc } else {
122293bf6008Sagc flags |= O_EXCL;
1223de704779Sagc }
122493bf6008Sagc #ifdef O_BINARY
122593bf6008Sagc flags |= O_BINARY;
122693bf6008Sagc #endif
122793bf6008Sagc fd = open(filename, flags, 0600);
122893bf6008Sagc if (fd < 0) {
12295a83dba0Sagc (void) fprintf(stderr, "can't open '%s'\n", filename);
123093bf6008Sagc return 0;
123193bf6008Sagc }
12323326c4c5Sagc if (write(fd, buf, len) != (int)len) {
12330aa60872Sagc (void) close(fd);
123493bf6008Sagc return 0;
1235bcfd8565Sagc }
123693bf6008Sagc
12373326c4c5Sagc return (close(fd) == 0);
123893bf6008Sagc }
123993bf6008Sagc
124093bf6008Sagc /**
124193bf6008Sagc \ingroup Core_WritePackets
124293bf6008Sagc \brief Write Symmetrically Encrypted packet
124393bf6008Sagc \param data Data to encrypt
124493bf6008Sagc \param len Length of data
124557324b9fSagc \param output Write settings
12464b3a3e18Sagc \return 1 if OK; else 0
124793bf6008Sagc \note Hard-coded to use AES256
124893bf6008Sagc */
12494b3a3e18Sagc unsigned
pgp_write_symm_enc_data(const uint8_t * data,const int len,pgp_output_t * output)1250fc1f8641Sagc pgp_write_symm_enc_data(const uint8_t *data,
125193bf6008Sagc const int len,
1252fc1f8641Sagc pgp_output_t * output)
125393bf6008Sagc {
1254fc1f8641Sagc pgp_crypt_t crypt_info;
1255b15ec256Sagc uint8_t *encrypted = (uint8_t *) NULL;
1256b15ec256Sagc size_t encrypted_sz;
1257efdd9dbaSagc int done = 0;
125893bf6008Sagc
125993bf6008Sagc /* \todo assume AES256 for now */
1260fc1f8641Sagc pgp_crypt_any(&crypt_info, PGP_SA_AES_256);
1261fc1f8641Sagc pgp_encrypt_init(&crypt_info);
126293bf6008Sagc
12635a83dba0Sagc encrypted_sz = (size_t)(len + crypt_info.blocksize + 2);
12645a83dba0Sagc if ((encrypted = calloc(1, encrypted_sz)) == NULL) {
12655a83dba0Sagc (void) fprintf(stderr, "can't allocate %" PRIsize "d\n",
12665a83dba0Sagc encrypted_sz);
12675a83dba0Sagc return 0;
12685a83dba0Sagc }
126993bf6008Sagc
1270fc1f8641Sagc done = (int)pgp_encrypt_se(&crypt_info, encrypted, data, (unsigned)len);
1271ed0df671Sagc if (done != len) {
1272ed0df671Sagc (void) fprintf(stderr,
1273fc1f8641Sagc "pgp_write_symm_enc_data: done != len\n");
12744b3a3e18Sagc return 0;
1275ed0df671Sagc }
127693bf6008Sagc
1277fc1f8641Sagc return pgp_write_ptag(output, PGP_PTAG_CT_SE_DATA) &&
1278fc1f8641Sagc pgp_write_length(output, (unsigned)(1 + encrypted_sz)) &&
1279fc1f8641Sagc pgp_write(output, data, (unsigned)len);
128093bf6008Sagc }
128193bf6008Sagc
128293bf6008Sagc /**
128393bf6008Sagc \ingroup Core_WritePackets
128493bf6008Sagc \brief Write a One Pass Signature packet
12850c310959Sagc \param seckey Secret Key to use
128693bf6008Sagc \param hash_alg Hash Algorithm to use
128793bf6008Sagc \param sig_type Signature type
128857324b9fSagc \param output Write settings
12894b3a3e18Sagc \return 1 if OK; else 0
129093bf6008Sagc */
12914b3a3e18Sagc unsigned
pgp_write_one_pass_sig(pgp_output_t * output,const pgp_seckey_t * seckey,const pgp_hash_alg_t hash_alg,const pgp_sig_type_t sig_type)1292fc1f8641Sagc pgp_write_one_pass_sig(pgp_output_t *output,
1293fc1f8641Sagc const pgp_seckey_t *seckey,
1294fc1f8641Sagc const pgp_hash_alg_t hash_alg,
1295fc1f8641Sagc const pgp_sig_type_t sig_type)
129693bf6008Sagc {
1297fc1f8641Sagc uint8_t keyid[PGP_KEY_ID_SIZE];
129885073018Sagc
1299fc1f8641Sagc pgp_keyid(keyid, PGP_KEY_ID_SIZE, &seckey->pubkey, PGP_HASH_SHA1); /* XXX - hardcoded */
1300fc1f8641Sagc return pgp_write_ptag(output, PGP_PTAG_CT_1_PASS_SIG) &&
1301fc1f8641Sagc pgp_write_length(output, 1 + 1 + 1 + 1 + 8 + 1) &&
1302fc1f8641Sagc pgp_write_scalar(output, 3, 1) /* version */ &&
1303fc1f8641Sagc pgp_write_scalar(output, (unsigned)sig_type, 1) &&
1304fc1f8641Sagc pgp_write_scalar(output, (unsigned)hash_alg, 1) &&
1305fc1f8641Sagc pgp_write_scalar(output, (unsigned)seckey->pubkey.alg, 1) &&
1306fc1f8641Sagc pgp_write(output, keyid, 8) &&
1307fc1f8641Sagc pgp_write_scalar(output, 1, 1);
130893bf6008Sagc }
1309