static cdk_error_t write_user_id (cdk_stream_t out, cdk_pkt_userid_t id, int old_ctb, int pkttype) { cdk_error_t rc; if (!out || !id) return CDK_Inv_Value; if (pkttype == CDK_PKT_ATTRIBUTE) { if (!id->attrib_img) return CDK_Inv_Value; rc = pkt_write_head (out, old_ctb, id->attrib_len + 6, CDK_PKT_ATTRIBUTE); if (rc) return rc; /* Write subpacket part. */ stream_putc (out, 255); write_32 (out, id->attrib_len + 1); stream_putc (out, 1); rc = stream_write (out, id->attrib_img, id->attrib_len); } else { if (!id->name) return CDK_Inv_Value; rc = pkt_write_head (out, old_ctb, id->len, CDK_PKT_USER_ID); if (!rc) rc = stream_write (out, id->name, id->len); } return rc; }
static cdk_error_t write_onepass_sig (cdk_stream_t out, cdk_pkt_onepass_sig_t sig) { cdk_error_t rc; assert (out); assert (sig); if (sig->version != 3) return CDK_Inv_Packet; if (DEBUG_PKT) _cdk_log_debug ("write_onepass_sig:\n"); rc = pkt_write_head (out, 0, 13, CDK_PKT_ONEPASS_SIG); if (!rc) rc = stream_putc (out, sig->version); if (!rc) rc = stream_putc (out, sig->sig_class); if (!rc) rc = stream_putc (out, _gnutls_hash_algo_to_pgp (sig->digest_algo)); if (!rc) rc = stream_putc (out, _cdk_pub_algo_to_pgp (sig->pubkey_algo)); if (!rc) rc = write_32 (out, sig->keyid[0]); if (!rc) rc = write_32 (out, sig->keyid[1]); if (!rc) rc = stream_putc (out, sig->last); return rc; }
static cdk_error_t write_v3_sig (cdk_stream_t out, cdk_pkt_signature_t sig, int nsig) { size_t size; cdk_error_t rc; size = 19 + calc_mpisize (sig->mpi, nsig); if (is_RSA (sig->pubkey_algo)) rc = pkt_write_head2 (out, size, CDK_PKT_SIGNATURE); else rc = pkt_write_head (out, 1, size, CDK_PKT_SIGNATURE); if (!rc) rc = stream_putc (out, sig->version); if (!rc) rc = stream_putc (out, 5); if (!rc) rc = stream_putc (out, sig->sig_class); if (!rc) rc = write_32 (out, sig->timestamp); if (!rc) rc = write_32 (out, sig->keyid[0]); if (!rc) rc = write_32 (out, sig->keyid[1]); if (!rc) rc = stream_putc (out, _cdk_pub_algo_to_pgp (sig->pubkey_algo)); if (!rc) rc = stream_putc (out, _gnutls_hash_algo_to_pgp (sig->digest_algo)); if (!rc) rc = stream_putc (out, sig->digest_start[0]); if (!rc) rc = stream_putc (out, sig->digest_start[1]); if (!rc) rc = write_mpibuf (out, sig->mpi, nsig); return rc; }
static int write_pubkey_enc (cdk_stream_t out, cdk_pkt_pubkey_enc_t pke, int old_ctb) { size_t size; int rc, nenc; assert (out); assert (pke); if (pke->version < 2 || pke->version > 3) return CDK_Inv_Packet; if (!KEY_CAN_ENCRYPT (pke->pubkey_algo)) return CDK_Inv_Algo; if (DEBUG_PKT) _cdk_log_debug ("write_pubkey_enc:\n"); nenc = cdk_pk_get_nenc (pke->pubkey_algo); size = 10 + calc_mpisize (pke->mpi, nenc); rc = pkt_write_head (out, old_ctb, size, CDK_PKT_PUBKEY_ENC); if (rc) return rc; rc = stream_putc (out, pke->version); if (!rc) rc = write_32 (out, pke->keyid[0]); if (!rc) rc = write_32 (out, pke->keyid[1]); if (!rc) rc = stream_putc (out, _cdk_pub_algo_to_pgp (pke->pubkey_algo)); if (!rc) rc = write_mpibuf (out, pke->mpi, nenc); return rc; }
static cdk_error_t write_literal (cdk_stream_t out, cdk_pkt_literal_t pt, int old_ctb) { byte buf[BUFSIZE]; size_t size; cdk_error_t rc; assert (out); assert (pt); /* We consider a packet without a body as an invalid packet. At least one octet must be present. */ if (!pt->len) return CDK_Inv_Packet; if (DEBUG_PKT) _cdk_log_debug ("write_literal:\n"); size = 6 + pt->namelen + pt->len; rc = pkt_write_head (out, old_ctb, size, CDK_PKT_LITERAL); if (rc) return rc; rc = stream_putc (out, pt->mode); if (rc) return rc; rc = stream_putc (out, pt->namelen); if (rc) return rc; if (pt->namelen > 0) rc = stream_write (out, pt->name, pt->namelen); if (!rc) rc = write_32 (out, pt->timestamp); if (rc) return rc; while (!cdk_stream_eof (pt->buf) && !rc) { rc = stream_read (pt->buf, buf, DIM (buf), &size); if (!rc) rc = stream_write (out, buf, size); } wipemem (buf, sizeof (buf)); return rc; }
static cdk_error_t write_compressed (cdk_stream_t out, cdk_pkt_compressed_t cd) { cdk_error_t rc; assert (out); assert (cd); if (DEBUG_PKT) _cdk_log_debug ("packet: write_compressed\n"); /* Use an old (RFC1991) header for this packet. */ rc = pkt_write_head (out, 1, 0, CDK_PKT_COMPRESSED); if (!rc) rc = stream_putc (out, cd->algorithm); return rc; }
static cdk_error_t write_public_key (cdk_stream_t out, cdk_pkt_pubkey_t pk, int is_subkey, int old_ctb) { int pkttype, ndays = 0; size_t npkey = 0, size = 6; cdk_error_t rc; assert (out); assert (pk); if (pk->version < 2 || pk->version > 4) return CDK_Inv_Packet; if (DEBUG_PKT) _cdk_log_debug ("write_public_key: subkey=%d\n", is_subkey); pkttype = is_subkey ? CDK_PKT_PUBLIC_SUBKEY : CDK_PKT_PUBLIC_KEY; npkey = cdk_pk_get_npkey (pk->pubkey_algo); if (!npkey) return CDK_Inv_Algo; if (pk->version < 4) size += 2; /* expire date */ if (is_subkey) old_ctb = 0; size += calc_mpisize (pk->mpi, npkey); if (old_ctb) rc = pkt_write_head2 (out, size, pkttype); else rc = pkt_write_head (out, old_ctb, size, pkttype); if (!rc) rc = stream_putc (out, pk->version); if (!rc) rc = write_32 (out, pk->timestamp); if (!rc && pk->version < 4) { if (pk->expiredate) ndays = (u16) ((pk->expiredate - pk->timestamp) / 86400L); rc = write_16 (out, ndays); } if (!rc) rc = stream_putc (out, _cdk_pub_algo_to_pgp (pk->pubkey_algo)); if (!rc) rc = write_mpibuf (out, pk->mpi, npkey); return rc; }
static cdk_error_t write_secret_key (cdk_stream_t out, cdk_pkt_seckey_t sk, int is_subkey, int old_ctb) { cdk_pkt_pubkey_t pk = NULL; size_t size = 6, npkey, nskey; int pkttype, s2k_mode; cdk_error_t rc; assert (out); assert (sk); if (!sk->pk) return CDK_Inv_Value; pk = sk->pk; if (pk->version < 2 || pk->version > 4) return CDK_Inv_Packet; if (DEBUG_PKT) _cdk_log_debug ("write_secret_key:\n"); npkey = cdk_pk_get_npkey (pk->pubkey_algo); nskey = cdk_pk_get_nskey (pk->pubkey_algo); if (!npkey || !nskey) { gnutls_assert (); return CDK_Inv_Algo; } if (pk->version < 4) size += 2; /* If the key is unprotected, the 1 extra byte: 1 octet - cipher algorithm byte (0x00) the other bytes depend on the mode: a) simple checksum - 2 octets b) sha-1 checksum - 20 octets */ size = !sk->is_protected ? size + 1 : size + 1 + calc_s2ksize (sk); size += calc_mpisize (pk->mpi, npkey); if (sk->version == 3 || !sk->is_protected) { if (sk->version == 3) { size += 2; /* force simple checksum */ sk->protect.sha1chk = 0; } else size += sk->protect.sha1chk ? 20 : 2; size += calc_mpisize (sk->mpi, nskey); } else /* We do not know anything about the encrypted mpi's so we treat the data as opaque. */ size += sk->enclen; pkttype = is_subkey ? CDK_PKT_SECRET_SUBKEY : CDK_PKT_SECRET_KEY; rc = pkt_write_head (out, old_ctb, size, pkttype); if (!rc) rc = stream_putc (out, pk->version); if (!rc) rc = write_32 (out, pk->timestamp); if (!rc && pk->version < 4) { u16 ndays = 0; if (pk->expiredate) ndays = (u16) ((pk->expiredate - pk->timestamp) / 86400L); rc = write_16 (out, ndays); } if (!rc) rc = stream_putc (out, _cdk_pub_algo_to_pgp (pk->pubkey_algo)); if (!rc) rc = write_mpibuf (out, pk->mpi, npkey); if (!rc) { if (sk->is_protected == 0) rc = stream_putc (out, 0x00); else { if (is_RSA (pk->pubkey_algo) && pk->version < 4) rc = stream_putc (out, _gnutls_cipher_to_pgp (sk->protect.algo)); else if (sk->protect.s2k) { s2k_mode = sk->protect.s2k->mode; rc = stream_putc (out, sk->protect.sha1chk ? 0xFE : 0xFF); if (!rc) rc = stream_putc (out, _gnutls_cipher_to_pgp (sk->protect.algo)); if (!rc) rc = stream_putc (out, sk->protect.s2k->mode); if (!rc) rc = stream_putc (out, sk->protect.s2k->hash_algo); if (!rc && (s2k_mode == 1 || s2k_mode == 3)) { rc = stream_write (out, sk->protect.s2k->salt, 8); if (!rc && s2k_mode == 3) rc = stream_putc (out, sk->protect.s2k->count); } } else return CDK_Inv_Value; if (!rc) rc = stream_write (out, sk->protect.iv, sk->protect.ivlen); } } if (!rc && sk->is_protected && pk->version == 4) { if (sk->encdata && sk->enclen) rc = stream_write (out, sk->encdata, sk->enclen); } else { if (!rc) rc = write_mpibuf (out, sk->mpi, nskey); if (!rc) { if (!sk->csum) sk->csum = _cdk_sk_get_csum (sk); rc = write_16 (out, sk->csum); } } return rc; }
static cdk_error_t write_signature (cdk_stream_t out, cdk_pkt_signature_t sig, int old_ctb) { byte *buf; size_t nbytes, size, nsig; cdk_error_t rc; assert (out); assert (sig); if (!KEY_CAN_SIGN (sig->pubkey_algo)) return CDK_Inv_Algo; if (sig->version < 2 || sig->version > 4) return CDK_Inv_Packet; if (DEBUG_PKT) _cdk_log_debug ("write_signature:\n"); nsig = cdk_pk_get_nsig (sig->pubkey_algo); if (!nsig) return CDK_Inv_Algo; if (sig->version < 4) return write_v3_sig (out, sig, nsig); size = 10 + calc_subpktsize (sig->hashed) + calc_subpktsize (sig->unhashed) + calc_mpisize (sig->mpi, nsig); rc = pkt_write_head (out, 0, size, CDK_PKT_SIGNATURE); if (!rc) rc = stream_putc (out, 4); if (!rc) rc = stream_putc (out, sig->sig_class); if (!rc) rc = stream_putc (out, _cdk_pub_algo_to_pgp (sig->pubkey_algo)); if (!rc) rc = stream_putc (out, _gnutls_hash_algo_to_pgp (sig->digest_algo)); if (!rc) rc = write_16 (out, sig->hashed_size); if (!rc) { buf = _cdk_subpkt_get_array (sig->hashed, 0, &nbytes); if (!buf) return CDK_Out_Of_Core; rc = stream_write (out, buf, nbytes); cdk_free (buf); } if (!rc) rc = write_16 (out, sig->unhashed_size); if (!rc) { buf = _cdk_subpkt_get_array (sig->unhashed, 0, &nbytes); if (!buf) return CDK_Out_Of_Core; rc = stream_write (out, buf, nbytes); cdk_free (buf); } if (!rc) rc = stream_putc (out, sig->digest_start[0]); if (!rc) rc = stream_putc (out, sig->digest_start[1]); if (!rc) rc = write_mpibuf (out, sig->mpi, nsig); return rc; }