Пример #1
0
/*
 * Simple API for doing a single KeyNote query.
 */
int
kn_query(struct environment *env, char **retvalues, int numval,
	 char **trusted, int *trustedlen, int numtrusted,
	 char **untrusted, int *untrustedlen, int numuntrusted,
	 char **authorizers, int numauthorizers)
{
    struct environment *en;
    int sessid, i, serrno;

    keynote_errno = 0;
    if ((sessid = kn_init()) == -1)
      return -1;

    /* Action set */
    for (en = env; en != (struct environment *) NULL; en = en->env_next)
      if (kn_add_action(sessid, en->env_name, en->env_value,
          en->env_flags) == -1)
      {
	  serrno = keynote_errno;
	  kn_close(sessid);
	  keynote_errno = serrno;
	  return -1;
      }

    /* Locally trusted assertions */
    for (i = 0; i < numtrusted; i++)
      if ((kn_add_assertion(sessid, trusted[i], trustedlen[i],
	  ASSERT_FLAG_LOCAL) == -1) && (keynote_errno == ERROR_MEMORY))
      {
	  serrno = keynote_errno;
	  kn_close(sessid);
	  keynote_errno = serrno;
	  return -1;
      }

    /* Untrusted assertions */
    for (i = 0; i < numuntrusted; i++)
      if ((kn_add_assertion(sessid, untrusted[i], untrustedlen[i], 0) == -1)
	  && (keynote_errno == ERROR_MEMORY))
      {
	  serrno = keynote_errno;
	  kn_close(sessid);
	  keynote_errno = serrno;
	  return -1;
      }

    /* Authorizers */
    for (i = 0; i < numauthorizers; i++)
      if (kn_add_authorizer(sessid, authorizers[i]) == -1)
      {
	  serrno = keynote_errno;
	  kn_close(sessid);
	  keynote_errno = serrno;
	  return -1;
      }

    i = kn_do_query(sessid, retvalues, numval);
    serrno = keynote_errno;
    kn_close(sessid);

    if (serrno)
      keynote_errno = serrno;

    return i;
}
Пример #2
0
int
initialize_keynote(char *str_nonce, char *str_date)
{
    char *policy_assertions;	// policy file
    char *root_key;			// root of trust
    char policy_template[] = ""
	"KeyNote-Version: 2\n"
	"Authorizer: \"POLICY\"\n"
	"licensees:\n%s"
	"conditions: app_domain == \"%s\" && nonce == \"%s\" "
	"&& date >= \"%s\"-> \"true\";\n";


    int sessionid, num, i, j;
    char **decomposed;
    int rlen;

    /*
     * create temporary KeyNote session.
     */
    sessionid = kn_init();
    if (sessionid == -1)
    {
	fprintf(stderr, "Failed to create a new session.\n");
	return(-1);
    }

	/* create policy. We read in the root of trust key from 
	 * a file and create a policy file for the temporary session
	 * that is a close match to this request
	 */
    if (read_file("auth_public_key", &root_key, &rlen) < 0) {
	fprintf(stderr, "failed to read file 'auth_public_key'.\n");
	return(-1);
    } else {
	char *str_app_domain = APP_DOMAIN;
	// char *str_nonce = nonce;	// we get this from our offer
	// char *str_date = "20140216";	// we get this from our offer

	printf(policy_template, root_key, str_app_domain, str_nonce, str_date);
	rlen =  strlen(policy_template)
		+  strlen(root_key)
		+  strlen(str_app_domain)
		+  strlen(str_nonce)
		+  strlen(str_date);
	if ((policy_assertions = calloc(rlen, 1)) == NULL) {
		fprintf(stderr, "policy calloc failed to get %d bytes\n", rlen);
		return(-1);
	}

	snprintf(policy_assertions, rlen, policy_template, root_key,
	    str_app_domain, str_nonce, str_date);
	printf("policy file = <<<%s>>>\n", policy_assertions);
    }

    /* Let's find how many policies we just "read". */
    decomposed = kn_read_asserts(policy_assertions,  strlen(policy_assertions),
				 &num);
    if (decomposed == NULL)
    {
	fprintf(stderr, "Failed to allocate memory for policy assertions.\n");
	return(-1);
    }

    /*
     * If there were no assertions in the first argument to kn_read_asserts,
     * we'll get a valid pointer back, which we need to free. Note that this
     * is an error; we always MUST have at least one policy assertion.
     */
    if (num == 0)
    {
	free(decomposed);
	fprintf(stderr, "No policy assertions provided.\n");
	return(-1);
    }

    /*
     * We no longer need a copy of policy_assertions, so we could 
     * free it here.
     */
    free(policy_assertions);

    /*
     * decomposed now contains num pointers to strings, each containing a
     * single assertion. We now add them all to the session. 
     */
    for (i = 0; i < num; i++)
    {
        // printf("kn_add_assertion(%s)\n", decomposed[i]);
	j = kn_add_assertion(sessionid, decomposed[i],
			      strlen(decomposed[i]), ASSERT_FLAG_LOCAL);
	if (j == -1)
	{
	    switch (keynote_errno)
	    {
		case ERROR_MEMORY:
		    fprintf(stderr, "Out of memory, trying to add policy "
			    "assertion %d.\n", j);
		    break;

		case ERROR_SYNTAX:
		    fprintf(stderr, "Syntax error parsing policy "
			    "assertion %d.\n", j);
		    break;

		case ERROR_NOTFOUND:
		    fprintf(stderr, "Session %d not found while adding "
			    "policy assertion %d.\n", sessionid, j);
		default:
		    fprintf(stderr, "Unspecified error %d (shouldn't happen) "
			    "while adding policy assertion %d.\n",
			    keynote_errno, j);
		    break;
	    }

	    /* We don't need the assertion any more. */
	    free(decomposed[i]);
	}
    }

    /* Now free decomposed itself. */
    free(decomposed);

    return(sessionid);
}
Пример #3
0
/* 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;
}