示例#1
0
static cdk_error_t
read_public_subkey (cdk_stream_t inp, size_t pktlen, cdk_pkt_pubkey_t pk)
{
  if (!inp || !pk)
    return CDK_Inv_Value;
  return read_public_key (inp, pktlen, pk);
}
示例#2
0
int
main(int argc, char **argv)
{
    GError *error = NULL;
    int retval = EXIT_SUCCESS;
    EVP_PKEY *pubkey;

    if (!process_arguments(&argc, &argv, &error)) {
        retval = handle_error(error);
        g_clear_error(&error);
    } else if ((pubkey = read_public_key(option_key_file, &error)) == NULL) {
        retval = handle_error(error);
        g_clear_error(&error);
    } else {
        FILE *infile = fopen(option_data_file, "rb");

        if (infile == NULL) {
            fprintf(stderr, "%s: %s\n", option_data_file, strerror(errno));
            retval = EXIT_IO_ERROR;
        } else {
            uint8_t hash[SHA256_DIGEST_LENGTH];
            uint8_t signature[SIGNATURE_SIZE];

            if (fread(signature, 1, sizeof(signature), infile) !=
                sizeof(signature)) {
                if (ferror(infile)) {
                    fprintf(
                        stderr, "%s: %s\n", option_data_file, strerror(errno));
                    retval = EXIT_IO_ERROR;
                } else {
                    fprintf(stderr,
                            "%s: File too short for signature\n",
                            option_data_file);
                    retval = EXIT_FORMAT_ERROR;
                }
            } else if (!hash_stream(infile, hash, &error) ||
                       !verify_signature(hash, signature, pubkey, &error)) {
                retval = handle_error(error);
                g_clear_error(&error);
            } else if (option_out_file &&
                       !write_out_file(infile, option_out_file, &error)) {
                retval = handle_error(error);
                g_clear_error(&error);
            }

            fclose(infile);
        }

        EVP_PKEY_free(pubkey);
    }

    return retval;
}
示例#3
0
/**
 * cdk_pkt_read:
 * @inp: the input stream
 * @pkt: allocated packet handle to store the packet
 *
 * Parse the next packet on the @inp stream and return its contents in @pkt.
 **/
cdk_error_t
cdk_pkt_read (cdk_stream_t inp, cdk_packet_t pkt)
{
  int ctb, is_newctb;
  int pkttype;
  size_t pktlen = 0, pktsize = 0, is_partial = 0;
  cdk_error_t rc;

  if (!inp || !pkt)
    return CDK_Inv_Value;

  ctb = cdk_stream_getc (inp);
  if (cdk_stream_eof (inp) || ctb == EOF)
    return CDK_EOF;
  else if (!ctb)
    return CDK_Inv_Packet;

  pktsize++;
  if (!(ctb & 0x80))
    {
      _cdk_log_info ("cdk_pkt_read: no openpgp data found. "
		     "(ctb=%02X; fpos=%02X)\n", ctb, cdk_stream_tell (inp));
      return CDK_Inv_Packet;
    }

  if (ctb & 0x40)		/* RFC2440 packet format. */
    {
      pkttype = ctb & 0x3f;
      is_newctb = 1;
    }
  else				/* the old RFC1991 packet format. */
    {
      pkttype = ctb & 0x3f;
      pkttype >>= 2;
      is_newctb = 0;
    }

  if (pkttype > 63)
    {
      _cdk_log_info ("cdk_pkt_read: unknown type %d\n", pkttype);
      return CDK_Inv_Packet;
    }

  if (is_newctb)
    read_new_length (inp, &pktlen, &pktsize, &is_partial);
  else
    read_old_length (inp, ctb, &pktlen, &pktsize);

  pkt->pkttype = pkttype;
  pkt->pktlen = pktlen;
  pkt->pktsize = pktsize + pktlen;
  pkt->old_ctb = is_newctb ? 0 : 1;

  rc = 0;
  switch (pkt->pkttype)
    {
    case CDK_PKT_ATTRIBUTE:
      pkt->pkt.user_id = cdk_calloc (1, sizeof *pkt->pkt.user_id
				     + pkt->pktlen + 16 + 1);
      if (!pkt->pkt.user_id)
	return CDK_Out_Of_Core;
      pkt->pkt.user_id->name = (char*)pkt->pkt.user_id + sizeof(*pkt->pkt.user_id);

      rc = read_attribute (inp, pktlen, pkt->pkt.user_id);
      pkt->pkttype = CDK_PKT_ATTRIBUTE;
      break;

    case CDK_PKT_USER_ID:
      pkt->pkt.user_id = cdk_calloc (1, sizeof *pkt->pkt.user_id
				     + pkt->pktlen + 1);
      if (!pkt->pkt.user_id)
	return CDK_Out_Of_Core;
      pkt->pkt.user_id->name = (char*)pkt->pkt.user_id + sizeof(*pkt->pkt.user_id);
      rc = read_user_id (inp, pktlen, pkt->pkt.user_id);
      break;

    case CDK_PKT_PUBLIC_KEY:
      pkt->pkt.public_key = cdk_calloc (1, sizeof *pkt->pkt.public_key);
      if (!pkt->pkt.public_key)
	return CDK_Out_Of_Core;
      rc = read_public_key (inp, pktlen, pkt->pkt.public_key);
      break;

    case CDK_PKT_PUBLIC_SUBKEY:
      pkt->pkt.public_key = cdk_calloc (1, sizeof *pkt->pkt.public_key);
      if (!pkt->pkt.public_key)
	return CDK_Out_Of_Core;
      rc = read_public_subkey (inp, pktlen, pkt->pkt.public_key);
      break;

    case CDK_PKT_SECRET_KEY:
      pkt->pkt.secret_key = cdk_calloc (1, sizeof *pkt->pkt.secret_key);
      if (!pkt->pkt.secret_key)
	return CDK_Out_Of_Core;
      pkt->pkt.secret_key->pk = cdk_calloc (1,
					    sizeof *pkt->pkt.secret_key->pk);
      if (!pkt->pkt.secret_key->pk)
	return CDK_Out_Of_Core;
      rc = read_secret_key (inp, pktlen, pkt->pkt.secret_key);
      break;

    case CDK_PKT_SECRET_SUBKEY:
      pkt->pkt.secret_key = cdk_calloc (1, sizeof *pkt->pkt.secret_key);
      if (!pkt->pkt.secret_key)
	return CDK_Out_Of_Core;
      pkt->pkt.secret_key->pk = cdk_calloc (1,
					    sizeof *pkt->pkt.secret_key->pk);
      if (!pkt->pkt.secret_key->pk)
	return CDK_Out_Of_Core;
      rc = read_secret_subkey (inp, pktlen, pkt->pkt.secret_key);
      break;

    case CDK_PKT_LITERAL:
      pkt->pkt.literal = cdk_calloc (1, sizeof *pkt->pkt.literal);
      if (!pkt->pkt.literal)
	return CDK_Out_Of_Core;
      rc = read_literal (inp, pktlen, &pkt->pkt.literal, is_partial);
      break;

    case CDK_PKT_ONEPASS_SIG:
      pkt->pkt.onepass_sig = cdk_calloc (1, sizeof *pkt->pkt.onepass_sig);
      if (!pkt->pkt.onepass_sig)
	return CDK_Out_Of_Core;
      rc = read_onepass_sig (inp, pktlen, pkt->pkt.onepass_sig);
      break;

    case CDK_PKT_SIGNATURE:
      pkt->pkt.signature = cdk_calloc (1, sizeof *pkt->pkt.signature);
      if (!pkt->pkt.signature)
	return CDK_Out_Of_Core;
      rc = read_signature (inp, pktlen, pkt->pkt.signature);
      break;

    case CDK_PKT_PUBKEY_ENC:
      pkt->pkt.pubkey_enc = cdk_calloc (1, sizeof *pkt->pkt.pubkey_enc);
      if (!pkt->pkt.pubkey_enc)
	return CDK_Out_Of_Core;
      rc = read_pubkey_enc (inp, pktlen, pkt->pkt.pubkey_enc);
      break;

    case CDK_PKT_COMPRESSED:
      pkt->pkt.compressed = cdk_calloc (1, sizeof *pkt->pkt.compressed);
      if (!pkt->pkt.compressed)
	return CDK_Out_Of_Core;
      rc = read_compressed (inp, pktlen, pkt->pkt.compressed);
      break;

    case CDK_PKT_MDC:
      pkt->pkt.mdc = cdk_calloc (1, sizeof *pkt->pkt.mdc);
      if (!pkt->pkt.mdc)
	return CDK_Out_Of_Core;
      rc = read_mdc (inp, pkt->pkt.mdc);
      break;

    default:
      /* Skip all packets we don't understand */
      skip_packet (inp, pktlen);
      break;
    }

  return rc;
}
示例#4
0
static cdk_error_t
read_secret_key (cdk_stream_t inp, size_t pktlen, cdk_pkt_seckey_t sk)
{
  size_t p1, p2, nread;
  int i, nskey;
  int rc;

  if (!inp || !sk || !sk->pk)
    return CDK_Inv_Value;

  if (DEBUG_PKT)
    _cdk_log_debug ("read_secret_key: %d octets\n", pktlen);

  p1 = cdk_stream_tell (inp);
  rc = read_public_key (inp, pktlen, sk->pk);
  if (rc)
    return rc;

  sk->s2k_usage = cdk_stream_getc (inp);
  sk->protect.sha1chk = 0;
  if (sk->s2k_usage == 254 || sk->s2k_usage == 255)
    {
      sk->protect.sha1chk = (sk->s2k_usage == 254);
      sk->protect.algo = _pgp_cipher_to_gnutls (cdk_stream_getc (inp));
      sk->protect.s2k = cdk_calloc (1, sizeof *sk->protect.s2k);
      if (!sk->protect.s2k)
	return CDK_Out_Of_Core;
      rc = read_s2k (inp, sk->protect.s2k);
      if (rc)
	return rc;
      /* refer to --export-secret-subkeys in gpg(1) */
      if (sk->protect.s2k->mode == CDK_S2K_GNU_EXT)
	sk->protect.ivlen = 0;
      else
	{
	  sk->protect.ivlen =
	    _gnutls_cipher_get_block_size (sk->protect.algo);
	  if (!sk->protect.ivlen)
	    return CDK_Inv_Packet;
	  rc = stream_read (inp, sk->protect.iv, sk->protect.ivlen, &nread);
	  if (rc)
	    return rc;
	  if (nread != sk->protect.ivlen)
	    return CDK_Inv_Packet;
	}
    }
  else
    sk->protect.algo = _pgp_cipher_to_gnutls (sk->s2k_usage);
  if (sk->protect.algo == GNUTLS_CIPHER_NULL)
    {
      sk->csum = 0;
      nskey = cdk_pk_get_nskey (sk->pk->pubkey_algo);
      if (!nskey)
	{
	  gnutls_assert ();
	  return CDK_Inv_Algo;
	}
      for (i = 0; i < nskey; i++)
	{
	  rc = read_mpi (inp, &sk->mpi[i], 1);
	  if (rc)
	    return rc;
	}
      sk->csum = read_16 (inp);
      sk->is_protected = 0;
    }
  else if (sk->pk->version < 4)
    {
      /* The length of each multiprecision integer is stored in plaintext. */
      nskey = cdk_pk_get_nskey (sk->pk->pubkey_algo);
      if (!nskey)
	{
	  gnutls_assert ();
	  return CDK_Inv_Algo;
	}
      for (i = 0; i < nskey; i++)
	{
	  rc = read_mpi (inp, &sk->mpi[i], 1);
	  if (rc)
	    return rc;
	}
      sk->csum = read_16 (inp);
      sk->is_protected = 1;
    }
  else
    {
      /* We need to read the rest of the packet because we do not
         have any information how long the encrypted mpi's are */
      p2 = cdk_stream_tell (inp);
      p2 -= p1;
      sk->enclen = pktlen - p2;
      if (sk->enclen < 2)
	return CDK_Inv_Packet;	/* at least 16 bits for the checksum! */
      sk->encdata = cdk_calloc (1, sk->enclen + 1);
      if (!sk->encdata)
	return CDK_Out_Of_Core;
      if (stream_read (inp, sk->encdata, sk->enclen, &nread))
	return CDK_Inv_Packet;
      /* Handle the GNU S2K extensions we know (just gnu-dummy right now): */
      if (sk->protect.s2k->mode == CDK_S2K_GNU_EXT)
	{
	  unsigned char gnumode;
	  if ((sk->enclen < strlen ("GNU") + 1) ||
	      (0 != memcmp ("GNU", sk->encdata, strlen ("GNU"))))
	    return CDK_Inv_Packet;
	  gnumode = sk->encdata[strlen ("GNU")];
	  /* we only handle gnu-dummy (mode 1).
	     mode 2 should refer to external smart cards.
	   */
	  if (gnumode != 1)
	    return CDK_Inv_Packet;
	  /* gnu-dummy should have no more data */
	  if (sk->enclen != strlen ("GNU") + 1)
	    return CDK_Inv_Packet;
	}
      nskey = cdk_pk_get_nskey (sk->pk->pubkey_algo);
      if (!nskey)
	{
	  gnutls_assert ();
	  return CDK_Inv_Algo;
	}
      /* We mark each MPI entry with NULL to indicate a protected key. */
      for (i = 0; i < nskey; i++)
	sk->mpi[i] = NULL;
      sk->is_protected = 1;
    }

  sk->is_primary = 1;
  _cdk_copy_pk_to_sk (sk->pk, sk);
  return 0;
}