コード例 #1
0
ファイル: x509.c プロジェクト: appleorange1/bitrig
int
x509_cert_insert(int id, void *scert)
{
	X509	*cert;
	int	 res;

	cert = X509_dup((X509 *)scert);
	if (!cert) {
		log_print("x509_cert_insert: X509_dup failed");
		return 0;
	}
	if (x509_generate_kn(id, cert) == 0) {
		LOG_DBG((LOG_POLICY, 50,
		    "x509_cert_insert: x509_generate_kn failed"));
		X509_free(cert);
		return 0;
	}

	res = x509_hash_enter(cert);
	if (!res)
		X509_free(cert);

	return res;
}
コード例 #2
0
ファイル: ike_auth.c プロジェクト: ebichu/dd-wrt
/* Decrypt the HASH in SIG, we already need a parsed ID payload.  */
static int
rsa_sig_decode_hash (struct message *msg)
{
  struct cert_handler *handler;
  struct exchange *exchange = msg->exchange;
  struct ipsec_exch *ie = exchange->data;
  struct payload *p;
  void *cert = 0;
  u_int8_t *rawcert = 0;
  u_int32_t rawcertlen;
  RSA *key = 0;
  size_t hashsize = ie->hash->hashsize;
  char header[80];
  int len;
  int initiator = exchange->initiator;
  u_int8_t **hash_p, **id_cert, *id;
  u_int32_t *id_cert_len;
  size_t id_len;
  int found = 0, n, i, id_found;
#if defined (USE_DNSSEC)
  u_int8_t *rawkey = 0;
  u_int32_t rawkeylen;
#endif

  /* Choose the right fields to fill-in.  */
  hash_p = initiator ? &ie->hash_r : &ie->hash_i;
  id = initiator ? exchange->id_r : exchange->id_i;
  id_len = initiator ? exchange->id_r_len : exchange->id_i_len;

  if (!id || id_len == 0)
    {
      log_print ("rsa_sig_decode_hash: ID is missing");
      return -1;
    }

  /*
   * XXX Assume we should use the same kind of certification as the remote...
   * moreover, just use the first CERT payload to decide what to use.
   */
  p = TAILQ_FIRST (&msg->payload[ISAKMP_PAYLOAD_CERT]);
  if (!p)
    handler = cert_get (ISAKMP_CERTENC_KEYNOTE);
  else
    handler = cert_get (GET_ISAKMP_CERT_ENCODING (p->p));
  if (!handler)
    {
      log_print ("rsa_sig_decode_hash: cert_get (%d) failed",
		 p ? GET_ISAKMP_CERT_ENCODING (p->p) : -1);
      return -1;
    }

#if defined (USE_POLICY) && defined (USE_KEYNOTE)
  /*
   * We need the policy session initialized now, so we can add
   * credentials etc.
   */
  exchange->policy_id = kn_init ();
  if (exchange->policy_id == -1)
    {
      log_print ("rsa_sig_decode_hash: failed to initialize policy session");
      return -1;
    }
#endif /* USE_POLICY || USE_KEYNOTE */

  /* Obtain a certificate from our certificate storage.  */
  if (handler->cert_obtain (id, id_len, 0, &rawcert, &rawcertlen))
    {
      if (handler->id == ISAKMP_CERTENC_X509_SIG)
        {
	  cert = handler->cert_get (rawcert, rawcertlen);
	  if (!cert)
	    LOG_DBG ((LOG_CRYPTO, 50,
		      "rsa_sig_decode_hash: certificate malformed"));
	  else
	    {
	      if (!handler->cert_get_key (cert, &key))
	        {
		  log_print ("rsa_sig_decode_hash: "
			     "decoding certificate failed");
		  handler->cert_free (cert);
		}
	      else
	        {
		  found++;
		  LOG_DBG ((LOG_CRYPTO, 40,
			    "rsa_sig_decode_hash: using cert of type %d",
			    handler->id));
		  exchange->recv_cert = cert;
		  exchange->recv_certtype = handler->id;
#if defined (USE_POLICY)
		  x509_generate_kn (exchange->policy_id, cert);
#endif /* USE_POLICY */
		}
	    }
	}
      else if (handler->id == ISAKMP_CERTENC_KEYNOTE)
	handler->cert_insert (exchange->policy_id, rawcert);
      free (rawcert);
    }

  /*
   * Walk over potential CERT payloads in this message.
   * XXX I believe this is the wrong spot for this.  CERTs can appear
   * anytime.
   */
  for (p = TAILQ_FIRST (&msg->payload[ISAKMP_PAYLOAD_CERT]); p;
       p = TAILQ_NEXT (p, link))
    {
      p->flags |= PL_MARK;

      /* When we have found a key, just walk over the rest, marking them.  */
      if (found)
	continue;

      handler = cert_get (GET_ISAKMP_CERT_ENCODING (p->p));
      if (!handler)
	{
	  LOG_DBG ((LOG_MISC, 30,
		    "rsa_sig_decode_hash: no handler for %s CERT encoding",
		    constant_name (isakmp_certenc_cst,
				   GET_ISAKMP_CERT_ENCODING (p->p))));
	  continue;
	}

      cert = handler->cert_get (p->p + ISAKMP_CERT_DATA_OFF,
				GET_ISAKMP_GEN_LENGTH (p->p)
				- ISAKMP_CERT_DATA_OFF);
      if (!cert)
	{
	  log_print ("rsa_sig_decode_hash: can not get data from CERT");
	  continue;
	}

      if (!handler->cert_validate (cert))
	{
	  handler->cert_free (cert);
	  log_print ("rsa_sig_decode_hash: received CERT can't be validated");
	  continue;
	}

      if (GET_ISAKMP_CERT_ENCODING (p->p) == ISAKMP_CERTENC_X509_SIG)
        {
	  if (!handler->cert_get_subjects (cert, &n, &id_cert, &id_cert_len))
	    {
	      handler->cert_free (cert);
	      log_print ("rsa_sig_decode_hash: can not get subject from CERT");
	      continue;
	    }

	  id_found = 0;
	  for (i = 0; i < n; i++)
	    if (id_cert_len[i] == id_len
		&& id[0] == id_cert[i][0]
		&& memcmp (id + 4, id_cert[i] + 4, id_len - 4) == 0)
	      {
		id_found++;
		break;
	      }
	  if (!id_found)
	    {
	      handler->cert_free (cert);
	      log_print ("rsa_sig_decode_hash: no CERT subject match the ID");
	      free (id_cert);
	      continue;
	    }

	  cert_free_subjects (n, id_cert, id_cert_len);
	}

      if (!handler->cert_get_key (cert, &key))
	{
	  handler->cert_free (cert);
	  log_print ("rsa_sig_decode_hash: decoding payload CERT failed");
	  continue;
	}

      /* We validated the cert, cache it for later use.  */
      handler->cert_insert (exchange->policy_id, cert);

      exchange->recv_cert = cert;
      exchange->recv_certtype = GET_ISAKMP_CERT_ENCODING (p->p);

#if defined (USE_POLICY) && defined (USE_KEYNOTE)
      if (exchange->recv_certtype == ISAKMP_CERTENC_KEYNOTE)
        {
	  struct keynote_deckey dc;
	  char *pp;
	  int dclen;

	  dc.dec_algorithm = KEYNOTE_ALGORITHM_RSA;
	  dc.dec_key = key;

	  pp = kn_encode_key (&dc, INTERNAL_ENC_PKCS1, ENCODING_HEX,
			      KEYNOTE_PUBLIC_KEY);
	  if (pp == NULL)
	    {
	      kn_free_key (&dc);
	      log_print ("rsa_sig_decode_hash: failed to ASCII-encode key");
	      return -1;
	    }

	  dclen = strlen (pp) + sizeof "rsa-hex:";
	  exchange->keynote_key = calloc (dclen, sizeof (char));
	  if (!exchange->keynote_key)
	    {
	      free (pp);
	      kn_free_key (&dc);
	      log_print ("rsa_sig_decode_hash: failed to allocate %d bytes",
			 dclen);
	      return -1;
	    }

	  snprintf (exchange->keynote_key, dclen, "rsa-hex:%s", pp);
	  free (pp);
	}
#endif

      found++;
    }

#if defined (USE_DNSSEC)
  /* If no certificate provided a key, try to find a validated DNSSEC KEY.  */
  if (!found)
    {
      rawkey = dns_get_key (IKE_AUTH_RSA_SIG, msg, &rawkeylen);

      /* We need to convert 'void *rawkey' into 'RSA *key'.  */
      if (dns_RSA_dns_to_x509 (rawkey, rawkeylen, &key) == 0)
	found++;
      else
	log_print ("rsa_sig_decode_hash: KEY to RSA key conversion failed");

      if (rawkey)
	free (rawkey);
    }
#endif /* USE_DNSSEC */

#if defined (USE_RAWKEY)
  /* If we still have not found a key, try to read it from a file. */
  if (!found)
    if (get_raw_key_from_file (IKE_AUTH_RSA_SIG, id, id_len, &key) != -1)
      found++;
#endif

  if (!found)
    {
      log_print ("rsa_sig_decode_hash: no public key found");
      return -1;
    }

  p = TAILQ_FIRST (&msg->payload[ISAKMP_PAYLOAD_SIG]);
  if (!p)
    {
      log_print ("rsa_sig_decode_hash: missing signature payload");
      RSA_free (key);
      return -1;
    }

  /* Check that the sig is of the correct size.  */
  len = GET_ISAKMP_GEN_LENGTH (p->p) - ISAKMP_SIG_SZ;
  if (len != RSA_size (key))
    {
      RSA_free (key);
      log_print ("rsa_sig_decode_hash: "
		 "SIG payload length does not match public key");
      return -1;
    }

  *hash_p = malloc (len);
  if (!*hash_p)
    {
      RSA_free (key);
      log_error ("rsa_sig_decode_hash: malloc (%d) failed", len);
      return -1;
    }

  len = RSA_public_decrypt (len, p->p + ISAKMP_SIG_DATA_OFF, *hash_p, key,
			    RSA_PKCS1_PADDING);
  if (len == -1)
    {
      RSA_free (key);
      log_print ("rsa_sig_decode_hash: RSA_public_decrypt () failed");
      return -1;
    }

  /* Store key for later use */
  exchange->recv_key = key;
  exchange->recv_keytype = ISAKMP_KEY_RSA;

  if (len != hashsize)
    {
      free (*hash_p);
      *hash_p = 0;
      log_print ("rsa_sig_decode_hash: len %lu != hashsize %lu",
	(unsigned long)len, (unsigned long)hashsize);
      return -1;
    }

  snprintf (header, sizeof header, "rsa_sig_decode_hash: HASH_%c",
	    initiator ? 'R' : 'I');
  LOG_DBG_BUF ((LOG_MISC, 80, header, *hash_p, hashsize));

  p->flags |= PL_MARK;

  return 0;
}