/* * 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; }
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); }
/* 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; }