Merge lp:~hipl-core/hipl/certificate-exchange into lp:hipl

Proposed by Diego Biurrun
Status: Merged
Merged at revision: 6333
Proposed branch: lp:~hipl-core/hipl/certificate-exchange
Merge into: lp:hipl
Diff against target: 3349 lines (+1511/-1027)
35 files modified
Makefile.am (+5/-1)
configure.ac (+2/-0)
doc/HOWTO.xml.in (+75/-0)
hipd/cert.c (+158/-84)
hipd/input.c (+0/-1)
hipd/output.c (+0/-1)
hipfw/cert.c (+167/-528)
hipfw/cert.h (+14/-24)
hipfw/conntrack.c (+20/-9)
hipfw/hipfw.c (+5/-7)
hipfw/hipfw.conf (+1/-0)
hipfw/hipfw_defines.h (+0/-1)
hipfw/main.c (+2/-1)
hipfw/pisa_cert.c (+0/-205)
hipfw/pisa_cert.h (+0/-47)
hipfw/rule_management.c (+23/-0)
hipfw/rule_management.h (+1/-0)
lib/core/builder.c (+29/-16)
lib/core/builder.h (+7/-9)
lib/core/cert.c (+298/-0)
lib/core/cert.h (+51/-0)
lib/core/certtools.c (+9/-9)
lib/core/certtools.h (+2/-2)
lib/core/conf.c (+190/-4)
lib/core/protodefs.h (+19/-4)
modules/cert/hipd/cert.c (+169/-49)
modules/cert/hipd/cert.h (+7/-20)
modules/cert/module_info.xml (+23/-0)
test/certteststub.c (+2/-1)
test/check_lib_core.c (+2/-0)
test/lib/core/cert.c (+198/-0)
test/lib/core/test_cert.pem (+15/-0)
test/lib/core/test_key.pem (+15/-0)
test/lib/core/test_suites.h (+1/-0)
tools/hipl_autobuild.sh (+1/-4)
To merge this branch: bzr merge lp:~hipl-core/hipl/certificate-exchange
Reviewer Review Type Date Requested Status
Christoph Viethen Approve
Review via email: mp+96786@code.launchpad.net

This proposal supersedes a proposal from 2012-03-09.

Description of the change

.. and another version, now with David's exponential backoff branch already merged in via trunk.

To post a comment you must log in.
Revision history for this message
Miika Komu (miika-iki) wrote : Posted in a previous version of this proposal

Did I understand correctly, is the certificate parameter added only when the corresponding non-automatically generated file exists?

Can you remind why the PISA stuff was removed?

review: Needs Information
Revision history for this message
Miika Komu (miika-iki) wrote : Posted in a previous version of this proposal

Forgot to mention:

Text conflict in hipd/cert.c
Text conflict in test/check_lib_core.c

Revision history for this message
Diego Biurrun (diego-biurrun) wrote : Posted in a previous version of this proposal

On Fri, Mar 02, 2012 at 10:23:21PM +0000, Miika Komu wrote:
> Review: Needs Information
>
> Can you remind why the PISA stuff was removed?

I'm not sure what you mean by PISA stuff here. We renamed everything
labeled PISA because it really is more generic functionality that can
be used outside of the PISA project.

Diego

Revision history for this message
Diego Biurrun (diego-biurrun) wrote : Posted in a previous version of this proposal

On Sat, Mar 03, 2012 at 07:15:22AM +0000, Miika Komu wrote:
> Forgot to mention:
>
> Text conflict in hipd/cert.c
> Text conflict in test/check_lib_core.c

Yes, I did not bother to merge the last two commits from trunk.
I can redo the merge request from a branch with latest trunk merged
tomorrow if that is preferred. But the conflicts should not make
much of a difference for reviewing.

Diego

Revision history for this message
Miika Komu (miika-iki) wrote : Posted in a previous version of this proposal

Works for me.

review: Approve
Revision history for this message
René Hummen (rene-hummen) wrote : Posted in a previous version of this proposal

The code to be merged has been tested and worked fine. Also the code looks ok. A few minor issues below.

On 02.03.2012, at 19:08, Diego Biurrun wrote:
> Diego Biurrun has proposed merging lp:~hipl-core/hipl/certificate-exchange into lp:hipl.

> === modified file 'hipfw/main.c'
> --- hipfw/main.c 2011-11-25 13:52:20 +0000
> +++ hipfw/main.c 2012-03-02 18:07:40 +0000
> @@ -37,14 +37,16 @@
>
> #include <stdio.h>
> #include <stdlib.h>
> +#include <string.h>
> #include <unistd.h>
> #include <sys/types.h>
>
> #include "lib/core/filemanip.h"
> #include "lib/core/debug.h"
> #include "lib/core/util.h"
> +#include "cert.h"
> +#include "conntrack.h"
> #include "hipfw.h"
> -#include "conntrack.h"
> #include "midauth.h"

Why was cert.h included here? -> Removed in new revision.

> === modified file 'modules/update/hipd/update.c'
> --- modules/update/hipd/update.c 2012-01-17 08:34:18 +0000
> +++ modules/update/hipd/update.c 2012-03-02 18:07:40 +0000
> @@ -57,6 +57,7 @@
> #include "lib/core/prefix.h"
> #include "lib/core/state.h"
> #include "lib/core/performance.h"
> +#include "modules/cert/hipd/cert.h"
> #include "update_builder.h"
> #include "update_locator.h"
> #include "update_param_handling.h"

Why was this include added? -> Removed in new revision.

--
Dipl.-Inform. Rene Hummen, Ph.D. Student
Chair of Communication and Distributed Systems
RWTH Aachen University, Germany
tel: +49 241 80 20772
web: http://www.comsys.rwth-aachen.de/team/rene-hummen/

Revision history for this message
Diego Biurrun (diego-biurrun) wrote : Posted in a previous version of this proposal
Download full text (18.6 KiB)

review needs-fixing

On Fri, Mar 02, 2012 at 06:08:20PM +0000, Diego Biurrun wrote:
> Diego Biurrun has proposed merging lp:~hipl-core/hipl/certificate-exchange into lp:hipl.
>
> --- hipd/cert.c 2012-03-01 14:06:24 +0000
> +++ hipd/cert.c 2012-03-02 18:07:40 +0000

The functions in this file are HUUUUGE - IMO this needs some refactoring.

> @@ -682,89 +688,109 @@
> +
> + /* Were we sent a timestamp which indicates a requested cert validity? */
> + validity_param = hip_get_param(msg, HIP_PARAM_UINT);
> +
> + if (validity_param) {
> + const uint32_t valid_until_n = *(const uint32_t *) hip_get_param_contents_direct(validity_param);
> + const uint32_t valid_until_h = ntohl(valid_until_n);

Gah, pointer type punning.

> @@ -797,33 +821,67 @@
> +
> + X509_get_notBefore(cert)->type = V_ASN1_GENERALIZEDTIME;
> + X509_get_notAfter(cert)->type = V_ASN1_GENERALIZEDTIME;
> +
> + {
> + const time_t now = time(NULL);
> + time_t starttime = 0;
> + time_t endtime = 0;
> + time_t *starttime_p = NULL;
> + time_t *endtime_p = NULL;

The block braces are unnecessary, we allow mixed declarations and
statements.

> switch (algo) {
> case HIP_HI_RSA:
> - HIP_IFEL(!EVP_PKEY_assign_RSA(pkey, rsa), -1,
> + HIP_IFEL(!EVP_PKEY_set1_RSA(pkey, (RSA *) ha->peer_pub_key), -1,
> "Failed to convert RSA to EVP_PKEY\n");
> HIP_IFEL(X509_set_pubkey(cert, pkey) != 1, -1,
> "Failed to set public key of the certificate\n");
> break;
> case HIP_HI_DSA:
> - HIP_IFEL(!EVP_PKEY_assign_DSA(pkey, dsa), -1,
> + HIP_IFEL(!EVP_PKEY_set1_DSA(pkey, (DSA *) ha->peer_pub_key), -1,
> "Failed to convert DSA to EVP_PKEY\n");

peer_pub_key is a void*, the casts are unnecessary.

> @@ -926,7 +984,25 @@
>
> + switch (host_id->rdata.algorithm) {
> + case HIP_HI_RSA:
> + HIP_IFEL(!EVP_PKEY_set1_RSA(sig_key, (RSA *) key), -1,
> + "Failed to convert RSA to EVP_PKEY\n");
> + break;
> + case HIP_HI_DSA:
> + HIP_IFEL(!EVP_PKEY_set1_DSA(sig_key, (DSA *) key), -1,
> + "Failed to convert DSA to EVP_PKEY\n");
> + break;

same here

> --- hipfw/pisa.c 2011-11-25 13:52:20 +0000
> +++ hipfw/cert.c 2012-03-02 18:07:40 +0000
> @@ -25,551 +25,192 @@
> +#include "rule_management.h"
> +#include "cert.h"
> +
> +// runtime configuration
> +int use_cert = false;

This could be static.

> +const char *root_certificate_file = NULL;

This is unused.

> --- lib/core/builder.c 2012-03-01 14:06:24 +0000
> +++ lib/core/builder.c 2012-03-02 18:07:40 +0000
> @@ -3388,16 +3395,21 @@
> int hip_build_param_cert_x509_ver(struct hip_common *msg, char *der, int len)
> {
> + int err = -1;
> + struct hip_cert_x509_resp subj = { 0 };
> +
> + if (len > 0 && (unsigned int) len <= sizeof(subj.der)) {
> + hip_set_param_type((struct hip_tlv_common *) &subj, HIP_PARAM_CERT_X509_REQ);
> + hip_calc_param_len((struct hip_tlv_common *) &subj,
> + sizeof(struct hip_cert...

Revision history for this message
Diego Biurrun (diego-biurrun) wrote : Posted in a previous version of this proposal
Download full text (6.9 KiB)

On Thu, Mar 08, 2012 at 06:41:47PM +0100, Diego Biurrun wrote:
> review needs-fixing

It still needs fixing, I'm just commenting on the issues I addressed.

> On Fri, Mar 02, 2012 at 06:08:20PM +0000, Diego Biurrun wrote:
> > Diego Biurrun has proposed merging lp:~hipl-core/hipl/certificate-exchange into lp:hipl.
> >
> > --- hipd/cert.c 2012-03-01 14:06:24 +0000
> > +++ hipd/cert.c 2012-03-02 18:07:40 +0000
> > @@ -682,89 +688,109 @@
> > +
> > + /* Were we sent a timestamp which indicates a requested cert validity? */
> > + validity_param = hip_get_param(msg, HIP_PARAM_UINT);
> > +
> > + if (validity_param) {
> > + const uint32_t valid_until_n = *(const uint32_t *) hip_get_param_contents_direct(validity_param);
> > + const uint32_t valid_until_h = ntohl(valid_until_n);
>
> Gah, pointer type punning.

Fixed.

> > @@ -797,33 +821,67 @@
> > +
> > + X509_get_notBefore(cert)->type = V_ASN1_GENERALIZEDTIME;
> > + X509_get_notAfter(cert)->type = V_ASN1_GENERALIZEDTIME;
> > +
> > + {
> > + const time_t now = time(NULL);
> > + time_t starttime = 0;
> > + time_t endtime = 0;
> > + time_t *starttime_p = NULL;
> > + time_t *endtime_p = NULL;
>
> The block braces are unnecessary, we allow mixed declarations and
> statements.

Fixed.

Apparently Christoph's intention here was to reduce the scope of the
variables and possibly split the function into pieces along this line.
So if somebody wants to step forward and do that.. :)

> > switch (algo) {
> > case HIP_HI_RSA:
> > - HIP_IFEL(!EVP_PKEY_assign_RSA(pkey, rsa), -1,
> > + HIP_IFEL(!EVP_PKEY_set1_RSA(pkey, (RSA *) ha->peer_pub_key), -1,
> > "Failed to convert RSA to EVP_PKEY\n");
> > HIP_IFEL(X509_set_pubkey(cert, pkey) != 1, -1,
> > "Failed to set public key of the certificate\n");
> > break;
> > case HIP_HI_DSA:
> > - HIP_IFEL(!EVP_PKEY_assign_DSA(pkey, dsa), -1,
> > + HIP_IFEL(!EVP_PKEY_set1_DSA(pkey, (DSA *) ha->peer_pub_key), -1,
> > "Failed to convert DSA to EVP_PKEY\n");
>
> peer_pub_key is a void*, the casts are unnecessary.

Fixed.

> > @@ -926,7 +984,25 @@
> >
> > + switch (host_id->rdata.algorithm) {
> > + case HIP_HI_RSA:
> > + HIP_IFEL(!EVP_PKEY_set1_RSA(sig_key, (RSA *) key), -1,
> > + "Failed to convert RSA to EVP_PKEY\n");
> > + break;
> > + case HIP_HI_DSA:
> > + HIP_IFEL(!EVP_PKEY_set1_DSA(sig_key, (DSA *) key), -1,
> > + "Failed to convert DSA to EVP_PKEY\n");
> > + break;
>
> same here

Fixed.

> > --- hipfw/pisa.c 2011-11-25 13:52:20 +0000
> > +++ hipfw/cert.c 2012-03-02 18:07:40 +0000
> > @@ -25,551 +25,192 @@
> > +#include "rule_management.h"
> > +#include "cert.h"
> > +
> > +// runtime configuration
> > +int use_cert = false;
>
> This could be static.

Fixed.

> > +const char *root_certificate_file = NULL;
>
> This is unused.

Fixed.

> > --- lib/core/builder.c 2012-03-01 14:06:24 +0000
> > +++ lib/core/builder.c 2012-03-02 18:07:40 +0000
> > @@ -3388,16 +3395,21 @@
> ...

Read more...

Revision history for this message
Miika Komu (miika-iki) wrote : Posted in a previous version of this proposal

Looks ok to me.

review: Approve
Revision history for this message
Diego Biurrun (diego-biurrun) wrote : Posted in a previous version of this proposal
Download full text (4.9 KiB)

On Thu, Mar 08, 2012 at 06:41:47PM +0100, Diego Biurrun wrote:
> review needs-fixing
>
> On Fri, Mar 02, 2012 at 06:08:20PM +0000, Diego Biurrun wrote:
> > Diego Biurrun has proposed merging lp:~hipl-core/hipl/certificate-exchange into lp:hipl.
> >
> > --- test/lib/core/cert.c 1970-01-01 00:00:00 +0000
> > +++ test/lib/core/cert.c 2012-03-02 18:07:40 +0000
> > @@ -0,0 +1,189 @@
> > +
> > +START_TEST(test_cert_DER_encoding)
> > +{
> > + int len = 0;
> > + X509 *cert = NULL;
> > + X509 *cert_decoded = NULL;
> > + unsigned char *buf = NULL;
> > +
> > + HIP_DEBUG("Test DER en/decoding of X509 certificates.\n");
> > +
> > + fail_unless((cert = cert_load_x509_certificate(TEST_CERT,
> > + ENCODING_FORMAT_PEM)) != NULL,
> > + NULL);
> > + fail_unless((len = cert_X509_to_DER(cert, &buf)) > 0, NULL);
> > + fail_unless((cert_decoded = cert_DER_to_X509(buf, len)) != NULL, NULL);
> > + fail_unless(X509_cmp(cert, cert_decoded) == 0, NULL);
> > +
> > + fail_unless((len = cert_X509_to_DER(NULL, &buf)) < 0, NULL);
> > + fail_unless((len = cert_X509_to_DER(cert, NULL)) < 0, NULL);
> > + fail_unless((len = cert_X509_to_DER(NULL, NULL)) < 0, NULL);
> > +
> > + fail_unless((cert_decoded = cert_DER_to_X509(NULL, len)) == NULL, NULL);
> > + fail_unless((cert_decoded = cert_DER_to_X509(buf, len - 1)) == NULL, NULL);
> > + fail_unless((cert_decoded = cert_DER_to_X509(buf, len + 1)) == NULL, NULL);
> > + fail_unless((cert_decoded = cert_DER_to_X509(buf, 0)) == NULL, NULL);
> > +
> > + X509_free(cert);
> > + X509_free(cert_decoded);
>
> buf does not need to be freed?
>
> > +START_TEST(test_cert_match_public_key)
> > +{
> > + int err = 0;
> > + RSA *rsa = NULL;
> > + X509 *cert = NULL;
> > + EVP_PKEY *pkey = NULL;
> > +
> > + HIP_DEBUG("Test matching of public keys.\n");
> > +
> > + fail_unless((err = load_rsa_private_key(TEST_KEY, &rsa)) == 0, NULL);
> > + fail_unless((cert = cert_load_x509_certificate(TEST_CERT,
> > + ENCODING_FORMAT_PEM)) != NULL,
> > + NULL);
> > + pkey = EVP_PKEY_new();
> > + EVP_PKEY_assign_RSA(pkey, rsa);
> > + fail_unless((err = cert_match_public_key(cert, pkey)) == 1, NULL);
> > +
> > + fail_unless((err = cert_match_public_key(NULL, pkey)) == 0, NULL);
> > + fail_unless((err = cert_match_public_key(cert, NULL)) == 0, NULL);
> > + fail_unless((err = cert_match_public_key(NULL, NULL)) == 0, NULL);
> > +
> > + EVP_PKEY_free(pkey);
> > + X509_free(cert);
>
> RSA_free(rsa);
>
> .. at least if the doxy of load_rsa_private_key() is to be believed.
>
> > +START_TEST(test_cert_verify_chain)
> > +{
> > + int err = 0;
> > + X509 *cert = NULL;
> > + STACK_OF(X509) * chain = NULL;
> > +
> > + HIP_DEBUG("Test verification of certificate chains.\n");
> > +
> > + fail_unless((cert = cert_load_x509_certificate(TEST_CERT,
> > + ENCODING_FORMAT_PEM)) != NULL,
> > + NULL);
> > + ...

Read more...

Revision history for this message
Diego Biurrun (diego-biurrun) wrote : Posted in a previous version of this proposal
Download full text (10.0 KiB)

On Thu, Mar 08, 2012 at 06:41:47PM +0100, Diego Biurrun wrote:
> review needs-fixing

This branch still has serious issues, even after the number of fixes
I applied in the last few days. I'll ping the areas that I have
questions about and remain unfixed below.

> On Fri, Mar 02, 2012 at 06:08:20PM +0000, Diego Biurrun wrote:
> > Diego Biurrun has proposed merging lp:~hipl-core/hipl/certificate-exchange into lp:hipl.
> >
> > --- hipd/cert.c 2012-03-01 14:06:24 +0000
> > +++ hipd/cert.c 2012-03-02 18:07:40 +0000
>
> The functions in this file are HUUUUGE - IMO this needs some refactoring.

Any volunteers? The original authors maybe? I still don't really
understand the "big picture" of this branch.

> > --- lib/core/cert.c 1970-01-01 00:00:00 +0000
> > +++ lib/core/cert.c 2012-03-02 18:07:40 +0000
> > @@ -0,0 +1,292 @@
> > +/**
> > + * This function encodes the given certificate to its DER encoding for
> > + * transmission over the wire. The encoded certificate is written to @ *buf.
> > + *
> > + * @param cert the certificate to encode
> > + * @param buf the output is written here
> > + *
> > + * @return the length of the encoded data
> > + *
> > + * @note: The encoded data is in binary form and may contain embedded zeroes.
> > + * Functions such as strlen() will not return the correct length of the
> > + * encoded structure. Therefore length value returned by this function
> > + * should always be used.
> > + */
> > +int cert_X509_to_DER(X509 *const cert, unsigned char **buf)
> > +{
> > + int len;
> > +
> > + if (!cert) {
> > + HIP_ERROR("Cannot encode NULL-certificate\n");
> > + return -1;
> > + }
> > + if (!buf) {
> > + HIP_ERROR("Cannot create output buffer at NULL-pointer.\n");
> > + return -1;
> > + }
> > +
> > + *buf = NULL;
> > + len = i2d_X509(cert, buf);
> > +
> > + if (len < 0) {
> > + HIP_ERROR("Could not DER-encode the given certificate.\n");
> > + return -1;
> > + }
> > + return len;
> > +}
>
> The
>
> *buf = NULL;
>
> assignment looks suspicious to me, can somebody explain it?

Please somebody enlighten us.

> > +/**
> > + * Load a X509 certificate from @ file. If @ file contains more
> > + * than one certificate, the certificate at the top of the file is
> > + * returned.
> > + *
> > + * @param file the file to load the certficate from
> > + * @param fmt the input format of the certificate
> > + *
> > + * @return a X509 certificate on success, NULL on error
> > + */
> > +X509 *cert_load_x509_certificate(const char *const file,
> > + enum encoding_format fmt)
> > +{
> > + FILE *fp = NULL;
> > + X509 *cert = NULL;
> > +
> > + if (!file) {
> > + HIP_ERROR("Cannot read certificate from NULL-filename.\n");
> > + return NULL;
> > + }
> > +
> > + fp = fopen(file, "rb");
> > + if (!fp) {
> > + HIP_ERROR("Could not open file for reading: %s\n", file);
> > + return NULL;
> > + }
> > +
> > + if (fmt == ENCODING_FORMAT_PEM) {
> > + cert = PEM_read_X509(fp, NULL, NULL, NULL);
> > + } else if (fmt == ENCODING_FORMAT_DER...

Revision history for this message
Miika Komu (miika-iki) wrote : Posted in a previous version of this proposal

Hi,

On 03/12/2012 10:29 PM, Diego Biurrun wrote:
>> > On Fri, Mar 02, 2012 at 06:08:20PM +0000, Diego Biurrun wrote:
>>> > > Diego Biurrun has proposed merging lp:~hipl-core/hipl/certificate-exchange into lp:hipl.
>>> > >
>>> > > --- hipd/cert.c 2012-03-01 14:06:24 +0000
>>> > > +++ hipd/cert.c 2012-03-02 18:07:40 +0000
>> >
>> > The functions in this file are HUUUUGE - IMO this needs some refactoring.
> Any volunteers? The original authors maybe? I still don't really
> understand the "big picture" of this branch.

not volunteering, but asking if the merge make things worse or keep them
function length the same? If the length is the same, this should be
handled separately.

Revision history for this message
Diego Biurrun (diego-biurrun) wrote : Posted in a previous version of this proposal
Download full text (6.3 KiB)

On Mon, Mar 12, 2012 at 09:29:29PM +0100, Diego Biurrun wrote:
> On Thu, Mar 08, 2012 at 06:41:47PM +0100, Diego Biurrun wrote:
> > On Fri, Mar 02, 2012 at 06:08:20PM +0000, Diego Biurrun wrote:
> > > Diego Biurrun has proposed merging lp:~hipl-core/hipl/certificate-exchange into lp:hipl.
> > >
> > > --- hipd/cert.c 2012-03-01 14:06:24 +0000
> > > +++ hipd/cert.c 2012-03-02 18:07:40 +0000
> >
> > The functions in this file are HUUUUGE - IMO this needs some refactoring.
>
> Any volunteers? The original authors maybe? I still don't really
> understand the "big picture" of this branch.

Left for never^wlater.

> > > --- lib/core/cert.c 1970-01-01 00:00:00 +0000
> > > +++ lib/core/cert.c 2012-03-02 18:07:40 +0000
> > > @@ -0,0 +1,292 @@
> > > +/**
> > > + * Load a X509 certificate from @ file. If @ file contains more
> > > + * than one certificate, the certificate at the top of the file is
> > > + * returned.
> > > + *
> > > + * @param file the file to load the certficate from
> > > + * @param fmt the input format of the certificate
> > > + *
> > > + * @return a X509 certificate on success, NULL on error
> > > + */
> > > +X509 *cert_load_x509_certificate(const char *const file,
> > > + enum encoding_format fmt)
> > > +{
> > > + FILE *fp = NULL;
> > > + X509 *cert = NULL;
> > > +
> > > + if (!file) {
> > > + HIP_ERROR("Cannot read certificate from NULL-filename.\n");
> > > + return NULL;
> > > + }
> > > +
> > > + fp = fopen(file, "rb");
> > > + if (!fp) {
> > > + HIP_ERROR("Could not open file for reading: %s\n", file);
> > > + return NULL;
> > > + }
> > > +
> > > + if (fmt == ENCODING_FORMAT_PEM) {
> > > + cert = PEM_read_X509(fp, NULL, NULL, NULL);
> > > + } else if (fmt == ENCODING_FORMAT_DER) {
> > > + cert = d2i_X509_fp(fp, NULL);
> > > + } else {
> > > + HIP_ERROR("Invalid encoding format %i \n", fmt);
> > > + return NULL;
> > > + }
> >
> > switch/case? Might more formats get added here?
>
> Anybody?

Converted to switch/case, looks nicer at least.

> > > + if (fclose(fp)) {
> > > + HIP_ERROR("Error closing file: %s\n", file);
> > > + X509_free(cert);
> > > + return NULL;
> > > + } else if (!cert) {
> > > + HIP_ERROR("Could not decode certificate from file.\n");
> > > + return NULL;
> > > + }
> > > +
> > > + return cert;
> > > +}
> >
> > If I read this correctly, fp will not get closed on encountering an
> > invalid encoding format.
>
> Is my assessment correct?

It is correct, function logic fixed on branch.

> > > +/**
> > > + * Search for hip_cert parameter in @ msg and try to decode the data in
> > > + * the first certificate parameter of a X509 certificate.
> > > + *
> > > + * @param msg the message to extract the certificate from
> > > + *
> > > + * @return the first X509 certificate found in the message on success,
> > > + * NULL on error and if no certificates were found
> > > + */
> > > +X509 *cert_get_X509_from_msg(const struct hip_common *const msg)
> > > +{
> > > + const struct hip_cert *param_cert = NULL;
> > > +
> > > + ...

Read more...

Revision history for this message
Christof Mroz (christof-mroz) wrote : Posted in a previous version of this proposal

On 13.03.2012 17:31, Diego Biurrun wrote:
> On Mon, Mar 12, 2012 at 09:29:29PM +0100, Diego Biurrun wrote:
>> On Thu, Mar 08, 2012 at 06:41:47PM +0100, Diego Biurrun wrote:
>>> What is "param_cert + 1" supposed to be? Are you trying to move the
>>> pointer past the struct? This is extremely brittle, see the cast
>>> and the length calculation that are necessary.
>>
>> I'm still mystified about this one.
>
> Christoph confirms the intention. Repairing this likely entails quite
> a bit of fiddling with structures.

Related:
https://answers.launchpad.net/hipl/+question/151048

>>>> + if (optc == 2&& is_pos_natural_number(opt[1])) {
>>>
>>> OK, what exactly is the problem here? Why do you need the utility function?
>>
>> Can the original author shed some light on this?
>
> Christoph said scanf did not work for him. I guess we'll trust his word.

I still consider explicit type checks an anti pattern which should be
replaced by coercion, in this case scanf(), whenever easily possible.

As a fan of obscure facts I'd really like to know why scanf("%u",...)
failed. Don't let my curiosity stall the merge, though.

6125. By Diego Biurrun

Fix memory leaks in cert_match_public_key() and cert_verify_chain().

6126. By Diego Biurrun

Fix a number of memory leaks in the certificate unit test.

6127. By Christoph Viethen

Fix a few more problems related to certificate generation:

Remove some redundancy from hipd/cert.c, and replace braces which served
to limit the scope of temporary variables.

Fix serious bug in lib/core/builder.c:build_param_cert_x509, which caused
corrupt certificate length value to be transmitted on little-endian
platforms. Also add the zeroing of the entire packet (again), to ease
debugging. Additionally, re-add the check for sufficient target space
before performing memcpy().

Fix function cert_match_public_key(), enabling it to cope with OpenSSL's
"creative" error handling and return codes (verified against OpenSSL
0.9.8 source code).

6128. By Diego Biurrun

Merge current trunk.

6129. By Diego Biurrun

Fix program logic in cert_load_x509_certificate().

The function would not correctly close file descriptors on error.

6130. By Diego Biurrun

Fix another memleak in the test_cert_DER_encoding() unit test.

6131. By René Hummen

add missing type in cert enum

This fixes an issue where the hipd would send certificates with the
type RESERVED (0) by default, instead of the correct type.

6132. By René Hummen

merge trunk revision 6332

6133. By Christoph Viethen

Fix defective logic in conf_handle_certificate().

Still an awfully long function, though.

6134. By Christoph Viethen

Refactor conf_handle_certificate(), moving the functionality that evaluates
the input parameters and converts them into HIP message parameters into a
separate function conf_handle_certificate_parms().

Also, overhaul the comments: Make sure they line-break before 80 chars,
clarify / shorten some of them, and add Doxygen headers.

6135. By Christoph Viethen

Fix minor off-by-one bug in lib/core/builder.c:build_param_cert_x509().

Also, replace one occurence of "struct in6_addr" by "hip_hit_t". Finally,
fix a little typo in a comment.

6136. By Christoph Viethen

Correct type of the "der_len" element of the hip_cert_x509_resp structure
(see lib/core/protodefs.h) to be uint32_t. This structure reflects the
format of HIP messages on the wire, so the typical rules (use network
byte order, define sizes of struct elements unambiguously ... ) apply.

This change causes a number of other changes in places where the very
same value gets handled. Note also that htonl() and ntohl() already were
used in a few of these places for byte order conversion of said value;
they generally use uint32_t for their input and output, so using
different types instead was just asking for trouble.

Revision history for this message
Christoph Viethen (cviethen) wrote :

I guess this all really could be merged now.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'Makefile.am'
2--- Makefile.am 2012-03-13 15:00:27 +0000
3+++ Makefile.am 2012-03-16 04:27:22 +0000
4@@ -31,10 +31,10 @@
5 EXTRA_DIST += .vimrc process_modules.py version.h
6 EXTRA_DIST += debian doc patches packaging tools/bazaar tools/maintainer
7 EXTRA_DIST += $(wildcard modules/*/module_info.xml)
8+EXTRA_DIST += $(wildcard $(addprefix $(srcdir)/test/lib/core/,*.pem))
9 EXTRA_DIST += $(wildcard $(addprefix $(srcdir)/tools/,*.cfg *.pl *.sh *.xml))
10 EXTRA_DIST += $(wildcard $(addprefix $(srcdir)/hipfw/,*.cfg))
11 EXTRA_DIST += $(HIPL_HEADER_LIST)
12-EXTRA_DIST += hipd/pisa.c hipfw/pisa.c hipfw/pisa_cert.c
13
14
15 ### superuser programs ###
16@@ -117,6 +117,7 @@
17 hipd/user_ipsec_sadb_api.c \
18 modules/heartbeat/hipd/heartbeat.c \
19 modules/heartbeat_update/hipd/hb_update.c \
20+ modules/cert/hipd/cert.c \
21 modules/update/hipd/update.c \
22 modules/update/hipd/update_builder.c \
23 modules/update/hipd/update_locator.c \
24@@ -134,6 +135,7 @@
25 tools/nsupdate/nsupdate.conf
26
27 hipfw_hipfw_sources = hipfw/cache.c \
28+ hipfw/cert.c \
29 hipfw/dlist.c \
30 hipfw/esp_prot_api.c \
31 hipfw/esp_prot_config.c \
32@@ -165,6 +167,7 @@
33
34 lib_core_libhipcore_la_SOURCES = lib/core/builder.c \
35 lib/core/capability.c \
36+ lib/core/cert.c \
37 lib/core/certtools.c \
38 lib/core/conf.c \
39 lib/core/crypto.c \
40@@ -217,6 +220,7 @@
41 $(hipfw_hipfw_sources)
42
43 test_check_lib_core_SOURCES = test/check_lib_core.c \
44+ test/lib/core/cert.c \
45 test/lib/core/crypto.c \
46 test/lib/core/hit.c \
47 test/lib/core/hostid.c \
48
49=== modified file 'configure.ac'
50--- configure.ac 2012-03-09 14:42:31 +0000
51+++ configure.ac 2012-03-16 04:27:22 +0000
52@@ -101,6 +101,8 @@
53 AC_DEFINE_UNQUOTED(HIPL_LOCKDIR, "$(eval echo $lockdir)")
54 AH_TEMPLATE(HIPL_LOCKDIR, [default lock file location])
55
56+AC_DEFINE_UNQUOTED(HIPL_SOURCEDIR, "$(eval echo $srcdir)")
57+AH_TEMPLATE(HIPL_SOURCEDIR, [HIPL source directory location])
58 # Make sure that pythondir does not contain ${prefix} or similar so that it
59 # can be substituted into our Python scripts.
60 AC_SUBST(pythondir, $(eval echo $pythondir))
61
62=== modified file 'doc/HOWTO.xml.in'
63--- doc/HOWTO.xml.in 2012-01-25 10:44:48 +0000
64+++ doc/HOWTO.xml.in 2012-03-16 04:27:22 +0000
65@@ -2532,6 +2532,81 @@
66
67 </chapter>
68
69+<chapter id="ch_cert_exchange">
70+ <title>Certificate Exchange</title>
71+
72+ <section id="ch_cert_functionality">
73+ <title>Provided functionality</title>
74+ <para>At the protocol level, HIPL implements the HIP_CERT parameter as
75+ defined in RFC 6253. Specifically, X509 certificates are supported, whereas
76+ no functionality is provided for SPKI certificates. HIP does not define
77+ the usage of certificates in the protocol exchange. In HIPL, we currently
78+ add certificates to the R2 in the BEX and the second update message U2
79+ (e.g. during the mobility-triggered update exchange). The HIP firewall
80+ verifies the certificate in the R2 and U2 if configured accordingly. If your
81+ use case requires certificates to be included in different messages, changes
82+ in the source code will be necessary.</para>
83+ </section>
84+
85+ <section id="ch_cert_usage">
86+ <title>Setting up a network scenario with certificates</title>
87+ <para>For the following guide, we assume a setup consisting of three
88+ machines (A, B, and C), where B is situated on the forwarding path between
89+ A and C. A and C execute the hipd, while B executes the hipfw. The hipd
90+ automatically adds a certificate to R2s and U2s if a file called
91+ host-cert.der is located in @sysconfdir@. The hipfw checks for certificates
92+ if certificate-based rules exist in @sysconfdir@/hipfw.conf.</para>
93+ <para>To set up certificates, you have to perform the following steps:</para>
94+ <itemizedlist>
95+ <listitem><para>Generate a root certificate in PEM format (e.g. with
96+ OpenSSL).</para></listitem>
97+ <listitem><para>Copy the root certificate to @sysconfdir@/ca-root-cert.pem on
98+ B.</para></listitem>
99+ <listitem><para>Add a certificate-based rule to @sysconfdir@/hipfw.conf on B
100+ (e.g. 'FORWARD -cert @sysconfdir@/ca-root-cert.pem ACCEPT').</para>
101+ </listitem>
102+ <listitem><para>Generate a certificate in DER format for the HI used by C
103+ and place it at @sysconfdir@/host-cert.der on C.</para></listitem>
104+ <listitem><para>No changes are required for A if its role is restricted to
105+ an initiator. Otherwise, A requires the same setup as C.</para></listitem>
106+ </itemizedlist>
107+ <para>The setup of a certificate-based network scenario can be vastly
108+ simplified by using a fourth HIPL-enabled host D as the certificate
109+ authority. In this case, generate the root certificate on D by running:
110+ </para>
111+ <para><programlisting>
112+ openssl req -new -x509 -key @sysconfdir@/hip_host_rsa_key_pub -out ca-root-cert.pem
113+ </programlisting></para>
114+ <para>NOTE: Apart from the common name, all fields in the certificate can be
115+ empty. The common name must contain the HIT of D.</para>
116+ <para>Now, run a BEX between C and D. After the BEX has succeeded, run the
117+ following command on D as root in order to generate the certificate for C:
118+ </para>
119+ <para><programlisting>
120+ hipconf acquire certificate #HIT_OF_C# > host-cert.der
121+ </programlisting></para>
122+ <para>As the final step, copy the certificates to the places mentioned in
123+ the guide above.</para>
124+ </section>
125+
126+ <section id="ch_cert_troubleshooting">
127+ <title>Troubleshooting</title>
128+ <para>There are a couple of things that may go wrong in a certificate-based
129+ setup. The most common ones are listed below. Please, make sure to check
130+ the listed items before asking questions on the hipl-users mailing list.</para>
131+ <itemizedlist>
132+ <listitem><para>Ensure that the certificates have not yet expired (e.g.
133+ by checking the certificate lifetime with OpenSSL).</para></listitem>
134+ <listitem><para>Validate that the time is set correctly on all hosts.
135+ </para></listitem>
136+ <listitem><para>Verify the certificate chain consisting of
137+ root-ca-cert.pem and host-cert.der with an external tool (e.g. with
138+ OpenSSL).</para></listitem>
139+ </itemizedlist>
140+ </section>
141+
142+</chapter> <!-- ch_cert_exchange -->
143+
144 <chapter id="ch_exp_extensions">
145 <title>Other Experimental HIP Extensions</title>
146
147
148=== modified file 'hipd/cert.c'
149--- hipd/cert.c 2012-03-01 14:06:24 +0000
150+++ hipd/cert.c 2012-03-16 04:27:22 +0000
151@@ -49,10 +49,13 @@
152 #include "lib/core/common.h"
153 #include "lib/core/crypto.h"
154 #include "lib/core/debug.h"
155+#include "lib/core/hit.h"
156 #include "lib/core/ife.h"
157+#include "lib/core/prefix.h"
158 #include "lib/core/protodefs.h"
159 #include "lib/core/straddr.h"
160 #include "lib/core/gpl/pk.h"
161+#include "hadb.h"
162 #include "hidb.h"
163 #include "cert.h"
164
165@@ -661,20 +664,19 @@
166 */
167 int hip_cert_x509v3_handle_request_to_sign(struct hip_common *msg)
168 {
169- int err = 0, i = 0, nid = 0, ret = 0, secs = 0, algo = 0;
170- CONF *conf;
171+ int err = 0, i = 0, ret = 0, secs = 0, algo = 0;
172+ CONF *conf = NULL;
173 CONF_VALUE *item;
174 STACK_OF(CONF_VALUE) *sec_general = NULL;
175- STACK_OF(CONF_VALUE) *sec_name = NULL;
176 STACK_OF(CONF_VALUE) *sec_ext = NULL;
177
178- X509_REQ *req = NULL;
179 X509_NAME *issuer = NULL;
180 X509_NAME *subj = NULL;
181 X509_EXTENSION *ext = NULL;
182 STACK_OF(X509_EXTENSION) *extlist = NULL;
183- X509_NAME_ENTRY *ent;
184- EVP_PKEY *pkey;
185+ X509_NAME_ENTRY *ent = NULL;
186+ EVP_PKEY *pkey = NULL;
187+ EVP_PKEY *sig_key = NULL;
188 /** XX TODO THIS should come from a configuration file
189 * monotonically increasing counter */
190 long serial = 0;
191@@ -682,89 +684,108 @@
192 X509 *cert;
193 X509V3_CTX ctx;
194 const struct hip_cert_x509_req *subject;
195- char subject_hit[41];
196- char issuer_hit[41];
197- char ialtname[45];
198- char saltname[45];
199- struct in6_addr *issuer_hit_n;
200- struct hip_host_id *host_id;
201- RSA *rsa = NULL;
202- DSA *dsa = NULL;
203+ char subject_hit[INET6_ADDRSTRLEN];
204+ char issuer_hit[INET6_ADDRSTRLEN] = { 0 };
205+ char ialtname[INET6_ADDRSTRLEN + 3];
206+ char saltname[INET6_ADDRSTRLEN + 3];
207+ hip_hit_t *issuer_hit_n = NULL;
208+ struct hip_host_id *host_id = NULL;
209+ void *key = NULL;
210 unsigned char *der_cert = NULL;
211 int der_cert_len = 0;
212 char arg1[21];
213 char arg2[21];
214-
215- HIP_IFEL(!(issuer_hit_n = malloc(sizeof(struct in6_addr))), -1,
216+ const struct hip_tlv_common *validity_param = NULL;
217+ time_t expiry_time = 0;
218+ const struct hip_hadb_state *ha = NULL;
219+
220+
221+ HIP_IFEL(!(issuer_hit_n = malloc(sizeof(hip_hit_t))), -1,
222 "Malloc for subject failed\n");
223- HIP_IFEL(!(pkey = malloc(sizeof(EVP_PKEY))), -1,
224- "Malloc for pkey failed\n");
225+ HIP_IFEL(!(pkey = EVP_PKEY_new()), -1,
226+ "Allocating subject pub key failed\n");
227+ HIP_IFEL(!(sig_key = EVP_PKEY_new()), -1,
228+ "Allocating issuer signature key failed\n");
229
230- OpenSSL_add_all_algorithms();
231 ERR_load_crypto_strings();
232
233 HIP_DEBUG("Reading configuration file (%s)\n", HIP_CERT_CONF_PATH);
234 conf = hip_open_conf(HIP_CERT_CONF_PATH);
235 sec_general = hip_read_conf_section("hip_x509v3", conf);
236- sec_name = hip_read_conf_section("hip_x509v3_name", conf);
237 sec_ext = hip_read_conf_section("hip_x509v3_extensions", conf);
238- NCONF_free(conf);
239
240- /* Get the general information */
241+ /* Fail if the hip_x509v3 or hip_x509v3_name sections are not found. */
242 HIP_IFEL(sec_general == NULL, -1,
243 "Failed to load general certificate information\n");
244- HIP_IFEL(!(req = X509_REQ_new()), -1, "Failed to create X509_REQ object");
245-
246- HIP_IFEL(sec_name == NULL, -1,
247- "Failed to load issuer naming information for the certificate\n");
248
249 /* Issuer naming */
250- if (sec_general != NULL) {
251- /* Loop through the conf stack for general information */
252- extlist = sk_X509_EXTENSION_new_null();
253- for (i = 0; i < sk_CONF_VALUE_num(sec_general); i++) {
254- item = sk_CONF_VALUE_value(sec_general, i);
255- if (!strcmp(item->name, "issuerhit")) {
256- strcpy(issuer_hit, item->value);
257- ret = inet_pton(AF_INET6, item->value, issuer_hit_n);
258- HIP_IFEL(ret < 0 && errno == EAFNOSUPPORT, -1,
259- "Failed to convert issuer HIT to hip_hit_t\n");
260- HIP_DEBUG_HIT("Issuer HIT", issuer_hit_n);
261- HIP_IFEL(!inet_ntop(AF_INET6, issuer_hit_n,
262- issuer_hit, sizeof(issuer_hit)),
263- -1, "Failed to convert subject hit to "
264- "presentation format\n");
265- }
266- if (!strcmp(item->name, "days")) {
267- secs = HIP_CERT_DAY * atoi(item->value);
268- }
269- }
270- }
271- HIP_IFEL(!(issuer = X509_NAME_new()), -1, "Failed to set create issuer name");
272- nid = OBJ_txt2nid("commonName");
273- HIP_IFEL(nid == NID_undef, -1, "NID text not defined\n");
274- HIP_IFEL(!(ent = X509_NAME_ENTRY_create_by_NID(NULL, nid, MBSTRING_ASC,
275+ /* Loop through the conf stack for general information */
276+ for (i = 0; i < sk_CONF_VALUE_num(sec_general); i++) {
277+ item = sk_CONF_VALUE_value(sec_general, i);
278+ if (!strcmp(item->name, "issuerhit")) {
279+ ret = inet_pton(AF_INET6, item->value, issuer_hit_n);
280+ HIP_IFEL(ret != 1, -1,
281+ "Failed to convert issuer HIT to hip_hit_t\n");
282+ HIP_DEBUG_HIT("Issuer HIT", issuer_hit_n);
283+ hip_convert_hit_to_str(issuer_hit_n, NULL, issuer_hit);
284+ }
285+ if (!strcmp(item->name, "days")) {
286+ secs = HIP_CERT_DAY * atoi(item->value);
287+ }
288+ }
289+
290+ /* In case no issuerhit was in the config, just use our default HIT. */
291+ if (issuer_hit[0] == 0) {
292+ HIP_IFEL(hip_get_default_hit(issuer_hit_n), -1,
293+ "Unable to determine default HIT\n");
294+ hip_convert_hit_to_str(issuer_hit_n, NULL, issuer_hit);
295+ }
296+
297+ HIP_IFEL(!(issuer = X509_NAME_new()), -1, "Failed to create issuer name");
298+
299+ HIP_IFEL(!(ent = X509_NAME_ENTRY_create_by_NID(NULL, NID_commonName, MBSTRING_ASC,
300 (unsigned char *) issuer_hit, -1)), -1,
301 "Failed to create name entry for issuer\n");
302 HIP_IFEL(X509_NAME_add_entry(issuer, ent, -1, 0) != 1, -1,
303 "Failed to add entry to issuer name\n");
304
305+ X509_NAME_ENTRY_free(ent); /* "ent" var will be re-used */
306+ ent = NULL;
307+
308 /* Subject naming */
309 /* Get the subject hit from msg */
310 HIP_IFEL(!(subject = hip_get_param(msg, HIP_PARAM_CERT_X509_REQ)),
311- -1, "No cert_info struct found\n");
312- HIP_IFEL(!inet_ntop(AF_INET6, &subject->addr, subject_hit, sizeof(subject_hit)),
313- -1, "Failed to convert subject hit to presentation format\n");
314- HIP_IFEL(!(subj = X509_NAME_new()), -1, "Failed to set create subject name");
315- nid = OBJ_txt2nid("commonName");
316- HIP_IFEL(nid == NID_undef, -1, "NID text not defined\n");
317- HIP_IFEL(!(ent = X509_NAME_ENTRY_create_by_NID(NULL, nid, MBSTRING_ASC,
318+ -1, "No cert_x509_req struct found\n");
319+ HIP_IFEL(!ipv6_addr_is_hit(&subject->addr),
320+ -1, "Address in certificate request is no HIT.\n");
321+ HIP_DEBUG_HIT("Subject HIT", &subject->addr);
322+ hip_convert_hit_to_str(&subject->addr, NULL, subject_hit);
323+
324+ HIP_IFEL(!(subj = X509_NAME_new()), -1, "Failed to create subject name");
325+
326+ HIP_IFEL(!(ent = X509_NAME_ENTRY_create_by_NID(NULL, NID_commonName, MBSTRING_ASC,
327 (unsigned char *) subject_hit, -1)), -1,
328 "Failed to create name entry for subject\n");
329 HIP_IFEL(X509_NAME_add_entry(subj, ent, -1, 0) != 1, -1,
330 "Failed to add entry to subject name\n");
331- HIP_IFEL(X509_REQ_set_subject_name(req, subj) != 1, -1,
332- "Failed to add subject name to certificate request\n");
333+
334+ /* Were we sent a timestamp which indicates a requested cert validity? */
335+ validity_param = hip_get_param(msg, HIP_PARAM_UINT);
336+
337+ if (validity_param) {
338+ const uint32_t *valid_until_n = hip_get_param_contents_direct(validity_param);
339+ const uint32_t valid_until_h = ntohl(*valid_until_n);
340+
341+ /* If time_t is only 32 bits wide and signed, we cannot copy a value of
342+ * valid_until_h which has its MSB set since it would be misunderstood
343+ * as being negative; so only set the value if this is not the case. */
344+ if (!(sizeof(time_t) == 4 && ((time_t) -1 < 0) &&
345+ (0x80000000 & valid_until_h))) {
346+ expiry_time = valid_until_h;
347+ } else {
348+ HIP_OUT_ERR(-1, "Received invalid timestamp parameter.\n");
349+ }
350+ }
351
352 /* XX TODO add a check to skip subjectAltName and issuerAltName because they are
353 * already in use by with IP:<hit> stuff */
354@@ -778,8 +799,6 @@
355 "Failed to create extension\n");
356 sk_X509_EXTENSION_push(extlist, ext);
357 }
358- HIP_IFEL(!X509_REQ_add_extensions(req, extlist), -1,
359- "Failed to add extensions to the request\n");
360 }
361
362 /** NOW WE ARE READY TO CREATE A CERTIFICATE FROM THE REQUEST */
363@@ -797,33 +816,63 @@
364 "Failed to set subject name of certificate\n");
365 HIP_IFEL(X509_set_issuer_name(cert, issuer) != 1, -1,
366 "Failed to set issuer name of certificate\n");
367- HIP_IFEL(!X509_gmtime_adj(X509_get_notBefore(cert), 0), -1,
368- "Error setting beginning time of the certificate");
369- HIP_IFEL(!X509_gmtime_adj(X509_get_notAfter(cert), secs), -1,
370- "Error setting ending time of the certificate");
371-
372- HIP_DEBUG("Getting the key\n");
373-
374- HIP_IFEL(hip_get_host_id_and_priv_key(issuer_hit_n,
375- HIP_ANY_ALGO,
376- &host_id,
377- (void *) &rsa),
378- -1, "Private key not found\n");
379-
380- algo = host_id->rdata.algorithm;
381- if (algo == HIP_HI_DSA) {
382- dsa = (DSA *) rsa;
383+
384+ X509_get_notBefore(cert)->type = V_ASN1_GENERALIZEDTIME;
385+ X509_get_notAfter(cert)->type = V_ASN1_GENERALIZEDTIME;
386+
387+ {
388+ const time_t now = time(NULL);
389+ time_t starttime = 0, endtime = 0;
390+ time_t *starttime_p = NULL, *endtime_p = NULL;
391+
392+ if (expiry_time) {
393+ /* A specific expiry time is demanded by the caller. */
394+ if (now < expiry_time) {
395+ /* Just set it up as wanted. */
396+ starttime = now;
397+ endtime = expiry_time;
398+ } else {
399+ /* Just set the start time to one second before the expiry time.
400+ * This yields a - syntactically - valid certificate. It is not
401+ * our task to second-guess the motives for requesting an expiry
402+ * time from the past. */
403+ if (expiry_time == 1) {
404+ expiry_time++; /* another pathological case */
405+ }
406+ starttime = expiry_time - 1;
407+ endtime = expiry_time;
408+ }
409+
410+ starttime_p = &starttime;
411+ endtime_p = &endtime;
412+ secs = 0;
413+ } else {
414+ if (secs <= 0) {
415+ secs = 10; /* and yet another one */
416+ }
417+ }
418+
419+ HIP_IFEL(!X509_time_adj(X509_get_notBefore(cert), 0, starttime_p), -1,
420+ "Error setting beginning time of the certificate");
421+ HIP_IFEL(!X509_time_adj(X509_get_notAfter(cert), secs, endtime_p), -1,
422+ "Error setting ending time of the certificate");
423 }
424
425+ /* Get the subject public key from HADB */
426+ HIP_IFEL(!(ha = hip_hadb_find_byhits(issuer_hit_n, &subject->addr)),
427+ -1, "Could not retrieve host association for subject HIT\n");
428+
429+ algo = ha->peer_pub->rdata.algorithm;
430+
431 switch (algo) {
432 case HIP_HI_RSA:
433- HIP_IFEL(!EVP_PKEY_assign_RSA(pkey, rsa), -1,
434+ HIP_IFEL(!EVP_PKEY_set1_RSA(pkey, ha->peer_pub_key), -1,
435 "Failed to convert RSA to EVP_PKEY\n");
436 HIP_IFEL(X509_set_pubkey(cert, pkey) != 1, -1,
437 "Failed to set public key of the certificate\n");
438 break;
439 case HIP_HI_DSA:
440- HIP_IFEL(!EVP_PKEY_assign_DSA(pkey, dsa), -1,
441+ HIP_IFEL(!EVP_PKEY_set1_DSA(pkey, ha->peer_pub_key), -1,
442 "Failed to convert DSA to EVP_PKEY\n");
443 HIP_IFEL(X509_set_pubkey(cert, pkey) != 1, -1,
444 "Failed to set public key of the certificate\n");
445@@ -926,7 +975,25 @@
446 HIP_OUT_ERR(-1, "Unknown algorithm\n");
447 }
448
449- HIP_IFEL(!X509_sign(cert, pkey, digest), -1,
450+ /* Get the issuer key for signing */
451+ HIP_IFEL(hip_get_host_id_and_priv_key(issuer_hit_n, HIP_ANY_ALGO,
452+ &host_id, &key),
453+ -1, "Private key not found\n");
454+
455+ switch (host_id->rdata.algorithm) {
456+ case HIP_HI_RSA:
457+ HIP_IFEL(!EVP_PKEY_set1_RSA(sig_key, key), -1,
458+ "Failed to convert RSA to EVP_PKEY\n");
459+ break;
460+ case HIP_HI_DSA:
461+ HIP_IFEL(!EVP_PKEY_set1_DSA(sig_key, key), -1,
462+ "Failed to convert DSA to EVP_PKEY\n");
463+ break;
464+ default:
465+ HIP_OUT_ERR(-1, "Unknown algorithm\n");
466+ }
467+
468+ HIP_IFEL(!X509_sign(cert, sig_key, digest), -1,
469 "Failed to sign x509v3 certificate\n");
470
471 /** DER */
472@@ -943,8 +1010,15 @@
473
474 out_err:
475 free(host_id);
476- X509_REQ_free(req);
477 sk_X509_EXTENSION_pop_free(extlist, X509_EXTENSION_free);
478+ X509_NAME_ENTRY_free(ent);
479+ X509_NAME_free(subj);
480+ X509_NAME_free(issuer);
481+ NCONF_free(conf);
482+ ERR_free_strings();
483+ EVP_PKEY_free(pkey);
484+ EVP_PKEY_free(sig_key);
485+ free(issuer_hit_n);
486 return err;
487 }
488
489@@ -985,7 +1059,7 @@
490 der_cert = (unsigned char *) &p->der;
491
492 vessel = p->der;
493- HIP_IFEL((cert = d2i_X509(NULL, &vessel, verify.der_len)) == NULL, -1,
494+ HIP_IFEL((cert = d2i_X509(NULL, &vessel, ntohl(verify.der_len))) == NULL, -1,
495 "Failed to convert cert from DER to internal format\n");
496 /*
497 * HIP_IFEL(!X509_print_fp(stdout, cert), -1,
498@@ -996,7 +1070,7 @@
499 "Failed to create X509_STORE_CTX object\n");
500 X509_STORE_set_verify_cb_func(store, verify_callback);
501
502- /* self signed so te cert itself should verify itself */
503+ /* self signed so the cert itself should verify itself */
504
505 HIP_IFEL(!X509_STORE_add_cert(store, cert), -1,
506 "Failed to add cert to ctx\n");
507
508=== modified file 'hipd/input.c'
509--- hipd/input.c 2012-03-14 19:03:04 +0000
510+++ hipd/input.c 2012-03-16 04:27:22 +0000
511@@ -73,7 +73,6 @@
512 #include "netdev.h"
513 #include "opp_mode.h"
514 #include "output.h"
515-#include "pisa.h"
516 #include "pkt_handling.h"
517 #include "registration.h"
518 #include "input.h"
519
520=== modified file 'hipd/output.c'
521--- hipd/output.c 2012-03-09 13:38:34 +0000
522+++ hipd/output.c 2012-03-16 04:27:22 +0000
523@@ -65,7 +65,6 @@
524 #include "hiprelay.h"
525 #include "nat.h"
526 #include "netdev.h"
527-#include "pisa.h"
528 #include "registration.h"
529 #include "output.h"
530
531
532=== renamed file 'hipfw/pisa.c' => 'hipfw/cert.c'
533--- hipfw/pisa.c 2011-11-25 13:52:20 +0000
534+++ hipfw/cert.c 2012-03-16 04:27:22 +0000
535@@ -1,5 +1,5 @@
536 /*
537- * Copyright (c) 2010 Aalto University and RWTH Aachen University.
538+ * Copyright (c) 2010-2011 Aalto University and RWTH Aachen University.
539 *
540 * Permission is hereby granted, free of charge, to any person
541 * obtaining a copy of this software and associated documentation
542@@ -25,551 +25,190 @@
543
544 /**
545 * @file
546- * This file contains PISA specific functions for the firewall. The basic idea
547- * is to modify the HIP messages and manage state for allowed connections to
548- * allow or reject associated ESP traffic.
549+ * certifcate functionality for the firewall
550 *
551- * @brief PISA functions for the firewall
552+ * @brief certificate functions for the firewall
553 */
554
555 #define _BSD_SOURCE
556
557+#include <limits.h>
558 #include <stdint.h>
559 #include <stdio.h>
560 #include <stdlib.h>
561 #include <string.h>
562-#include <time.h>
563-#include <arpa/inet.h>
564 #include <netinet/in.h>
565 #include <linux/netfilter.h>
566-#include <openssl/hmac.h>
567+#include <linux/netfilter_ipv6.h>
568+#include <openssl/x509.h>
569
570-#include "config.h"
571+#include "lib/core/common.h"
572+#include "lib/core/ife.h"
573 #include "lib/core/builder.h"
574-#include "lib/core/certtools.h"
575-#include "lib/core/crypto.h"
576+#include "lib/core/cert.h"
577 #include "lib/core/debug.h"
578-#include "lib/core/ife.h"
579-#include "lib/core/performance.h"
580-#include "lib/core/prefix.h"
581-#include "modules/midauth/hipd/midauth.h"
582 #include "conntrack.h"
583 #include "hipfw_defines.h"
584-#include "midauth.h"
585-#include "pisa_cert.h"
586-#include "pisa.h"
587-
588-
589-#define PISA_RANDOM_LEN 16
590-#define PISA_PUZZLE_SEED 0xDEADC0DE
591-#define PISA_PUZZLE_OPAQUE_LEN (4 + HIP_AH_SHA_LEN)
592-
593-/* pisa_check_for_random_update is called at least every PISA_RANDOM_TTL
594- * seconds. Worst case timer resolution depends on the timeout in the select
595- * call */
596-#define PISA_RANDOM_TTL 2.0
597-
598-static char pisa_random_data[2][PISA_RANDOM_LEN];
599-static struct in6_addr community_operator_hit;
600-
601-/* @todo make this configurable, issuer HIT */
602-#define CO_HIT "2001:001a:b1b0:0aad:0f92:15ca:280c:9430"
603-#define CO_HIT_FILE HIPL_SYSCONFDIR "/co_hit"
604-
605-/**
606- * Generate a new random number and shift the old one down.
607- */
608-static void pisa_generate_random(void)
609-{
610- void *p0, *p1;
611-
612- p0 = &pisa_random_data[0][0];
613- p1 = &pisa_random_data[1][0];
614-
615- memcpy(p0, p1, PISA_RANDOM_LEN);
616- get_random_bytes(p1, PISA_RANDOM_LEN);
617-}
618-
619-/**
620- * Reads out the HIT of the Community-Operator
621- * from file CO_HIT_FILE
622- * @param hit A pointer to the char where the HIT should be stored
623- * @return 1-> success
624- * @return 0-> error
625- */
626-static int pisa_read_communit_operator_hit(char *hit)
627-{
628- FILE *f;
629- char *eofline;
630-
631- f = fopen(CO_HIT_FILE, "r");
632-
633- if (f == NULL) {
634+#include "rule_management.h"
635+#include "cert.h"
636+
637+// runtime configuration
638+static int use_cert = false;
639+
640+static STACK_OF(X509) *root_chain = NULL;
641+
642+/**
643+ * Init function for certificate functionality.
644+ *
645+ * Iterate the firewall rules and look for the cert option. If found,
646+ * certificates are used and the root certificate is preloaded to verify
647+ * certificates. If no such rule is found, certificates are deactivated.
648+ *
649+ * @return 0 on success, negative if an error occurred
650+ */
651+int cert_init(void)
652+{
653+ X509 *cert = NULL;
654+ struct rule *rule = NULL;
655+ struct dlist *list = NULL;
656+
657+ if (!(list = get_rule_list(NF_IP6_FORWARD))) {
658+ use_cert = false;
659+ HIP_DEBUG("certificates deactivated\n");
660 return 0;
661 }
662
663- if (fgets(hit, INET6_ADDRSTRLEN, f) != NULL) {
664- eofline = strchr(hit, '\n');
665- if (eofline) {
666- *eofline = '\0';
667- }
668- } else {
669- HIP_ERROR("Fgets failed");
670- }
671- fclose(f);
672-
673- return 1;
674-}
675-
676-void pisa_check_for_random_update(void)
677-{
678- static time_t lastupdate = 0;
679- time_t now;
680-
681- time(&now);
682- if (difftime(now, lastupdate) > PISA_RANDOM_TTL) {
683- pisa_generate_random();
684- lastupdate = now;
685- }
686-}
687-
688-/**
689- * Appends HMAC/SHA1 to a block of data.
690- *
691- * @param hit1 first HIT
692- * @param hit2 second HIT
693- * @param rnd which random number to use, either 0 or 1
694- * @param data pointer to buffer for data and the HMAC
695- * @param data_len length of data
696- * @return 0 on success
697- */
698-static int pisa_append_hmac(struct in6_addr *hit1, struct in6_addr *hit2,
699- int rnd, void *data, int data_len)
700-{
701- uint8_t key[32 + PISA_RANDOM_LEN];
702- int err = 0;
703- unsigned int len = HIP_AH_SHA_LEN;
704-
705- /* sanity checks for arguments */
706- HIP_IFEL(data == NULL, -1, "No data given.\n");
707- HIP_IFEL(hit1 == NULL, -1, "No first HIT given.\n");
708- HIP_IFEL(hit2 == NULL, -1, "No second HIT given.\n");
709- HIP_IFEL(data_len < 1, -1, "Data has invalid length.\n");
710- HIP_IFEL(rnd != 0 && rnd != 1, -1, "Random ID is neither 0 nor 1.\n");
711-
712- /* The key for HMAC/SHA1 consists of:
713- * 16 bytes HIT1
714- * 16 bytes HIT2
715- * PISA_RANDOM_LEN bytes pisa_random_data
716- */
717-
718- ipv6_addr_copy((struct in6_addr *) (key + 0), hit1);
719- ipv6_addr_copy((struct in6_addr *) (key + 16), hit2);
720- memcpy(key + 32, &pisa_random_data[rnd][0], PISA_RANDOM_LEN);
721-
722- HMAC(EVP_sha1(), key, 32 + PISA_RANDOM_LEN, data, data_len,
723- (uint8_t *) data + data_len, &len);
724-
725-out_err:
726- return err;
727-}
728-
729-/**
730- * Insert a PISA puzzle into a packet.
731- *
732- * @param ctx context of the packet where the puzzle will be inserted
733- * @return success (0) or failure
734- */
735-static int pisa_insert_puzzle(struct hip_fw_context *ctx)
736-{
737- uint8_t opaque[PISA_PUZZLE_OPAQUE_LEN];
738-
739- struct hip_common *hip = ctx->transport_hdr.hip;
740- int seed = PISA_PUZZLE_SEED;
741-
742- memcpy(&opaque, &seed, 4);
743-
744- /* here we switch order of initiator and receiver to obtain a
745- * different SHA1 hash */
746- pisa_append_hmac(&hip->hitr, &hip->hits, 1, &opaque, 4);
747-
748- return midauth_add_challenge_request(ctx, 3, 4, opaque, PISA_PUZZLE_OPAQUE_LEN);
749-}
750-
751-/**
752- * Check the validity of a PISA challenge_response.
753- *
754- * @param ctx context of the packet with the puzzle to check
755- * @return pointer to the puzzle we accepted or NULL at failure
756- */
757-static struct hip_challenge_response *pisa_check_challenge_response(struct hip_fw_context *ctx)
758-{
759- struct hip_challenge_response *response;
760- struct hip_common *hip = ctx->transport_hdr.hip;
761- uint8_t hash[2][PISA_PUZZLE_OPAQUE_LEN];
762- int seed = PISA_PUZZLE_SEED;
763-
764- memcpy(&hash[0][0], &seed, 4);
765- memcpy(&hash[1][0], &seed, 4);
766-
767- pisa_append_hmac(&hip->hits, &hip->hitr, 0, &hash[0], 4);
768- pisa_append_hmac(&hip->hits, &hip->hitr, 1, &hash[1], 4);
769-
770- response = hip_get_param_readwrite(hip, HIP_PARAM_CHALLENGE_RESPONSE);
771-
772- while (response) {
773- /* loop over all HIP_PARAM_CHALLENGE_RESPONSE */
774- if (hip_get_param_type(response) != HIP_PARAM_CHALLENGE_RESPONSE) {
775- break;
776- }
777- if ((!memcmp(response->opaque, &hash[1][0], PISA_PUZZLE_OPAQUE_LEN)) ||
778- (!memcmp(response->opaque, &hash[0][0], PISA_PUZZLE_OPAQUE_LEN))) {
779- if (!midauth_verify_challenge_response(response,
780- hip->hits,
781- hip->hitr)) {
782- return response;
783+ if (!(root_chain = sk_X509_new_null())) {
784+ HIP_ERROR("Memory allocation failure.\n");
785+ return -ENOMEM;
786+ }
787+
788+ /* Search for rules with cert option */
789+ while (list) {
790+ rule = list->data;
791+ if (rule->cert) {
792+ HIP_DEBUG("allowed cert: %s\n", rule->cert->value);
793+ use_cert = true;
794+ if (!(cert = cert_load_x509_certificate(rule->cert->value,
795+ ENCODING_FORMAT_PEM))) {
796+ HIP_ERROR("Could not load certificate of community operator from file: %s \n",
797+ rule->cert->value);
798+ return -1;
799 }
800- }
801-
802- response = (struct hip_challenge_response *)
803- hip_get_next_param_readwrite(hip,
804- (struct hip_tlv_common *) response);
805- }
806-
807- return NULL;
808-}
809-
810-/**
811- * Check the certificate of the packet.
812- *
813- * @param ctx context of the packet with the certificate to check
814- * @return success (0) or failure
815- */
816-static int pisa_check_certificate(struct hip_fw_context *ctx)
817-{
818- struct hip_common *hip = ctx->transport_hdr.hip;
819- const struct hip_cert *cert;
820- struct hip_cert_spki_info ci;
821- struct pisa_cert pc;
822- char *buf = NULL;
823- int err = 0, len;
824- time_t now = time(NULL);
825-
826- cert = hip_get_param(hip, HIP_PARAM_CERT);
827- HIP_IFEL(cert == NULL, -1, "No certificate found.\n");
828-
829- len = ntohs(cert->length);
830- buf = calloc(1, len);
831- memcpy(buf, cert + 1, len);
832-
833- HIP_IFEL(hip_cert_spki_char2certinfo(buf, &ci), -1,
834- "Certificate could not be parsed.\n");
835- HIP_IFEL(hip_cert_spki_lib_verify(&ci), -1,
836- "Certificate could not be verified.\n");
837-
838- pisa_split_cert(ci.cert, &pc);
839-
840- /* Three conditions must be fulfilled for a certificate to be valid:
841- *
842- * - The current time on the middlebox must be in the before/after
843- * interval
844- * - The certificate must be issued by the community operator (i.e.
845- * the CO HIT must be used by the issuer)
846- * - The host sending the certificate must be the one mentioned in
847- * the certificate
848- */
849- HIP_IFEL(now < pc.not_before, -1,
850- "Certificate is not valid yet.\n");
851- HIP_IFEL(now > pc.not_after, -1,
852- "Certificate has expired.\n");
853-
854-
855- HIP_IFEL(ipv6_addr_cmp(&pc.hit_issuer, &community_operator_hit) != 0,
856- -1, "Certificate not issued by the community operator.\n");
857- HIP_IFEL(ipv6_addr_cmp(&pc.hit_subject, &hip->hits) != 0, -1,
858- "Certificate does not belong to subject.\n");
859-
860- HIP_INFO("Certificate successfully verified.\n");
861-
862-out_err:
863- free(buf);
864- return err;
865-}
866-
867-/**
868- * Accept a connection via PISA. Update firewall to allow data packets to
869- * pass through.
870- *
871- * @param ctx context of the packet that belongs to that connection
872- */
873-static void pisa_accept_connection(const struct hip_fw_context *ctx)
874-{
875- struct hip_common *hip = ctx->transport_hdr.hip;
876- struct tuple *t = get_tuple_by_hits(&hip->hits, &hip->hitr);
877-
878- if (t) {
879- t->connection->pisa_state = PISA_STATE_ALLOW;
880- HIP_INFO("PISA accepted the connection.\n");
881- hip_fw_manage_all_esp_tuples(t, true);
882- } else {
883- HIP_ERROR("Connection not found.\n");
884- }
885-}
886-
887-/**
888- * Remove a connection from the list of accepted connections based on the hits
889- * of a packet.
890- *
891- * @param ctx context of the packet that contains HITs of the connection
892- */
893-static void pisa_remove_connection(const struct hip_fw_context *ctx)
894-{
895- struct hip_common *hip = ctx->transport_hdr.hip;
896- struct tuple *t = get_tuple_by_hits(&hip->hits, &hip->hitr);
897-
898- if (t) {
899- t->connection->pisa_state = PISA_STATE_DISALLOW;
900- HIP_INFO("PISA removed the connection.\n");
901- hip_fw_manage_all_esp_tuples(t, false);
902- } else {
903- HIP_ERROR("Connection not found.\n");
904- }
905-}
906-
907-/**
908- * Reject a connection via PISA. Update firewall to allow no data packets
909- * to pass through.
910- *
911- * @param ctx context of the packet that belongs to that connection
912- */
913-static void pisa_reject_connection(const struct hip_fw_context *ctx)
914-{
915- HIP_INFO("PISA rejected the connection.\n");
916- pisa_remove_connection(ctx);
917-}
918-
919-/**
920- * Dummy function, necessary only for performance measurements.
921- *
922- * @param ctx context of the packet containing the I1
923- * @return NF_ACCEPT verdict
924- */
925-static int pisa_handler_i1(UNUSED struct hip_fw_context *ctx)
926-{
927-#ifdef CONFIG_HIP_PERFORMANCE
928- HIP_DEBUG("Start PERF_BASE, PERF_I1\n");
929- hip_perf_start_benchmark(perf_set, PERF_BASE);
930- hip_perf_start_benchmark(perf_set, PERF_I1);
931-#endif
932-
933-#ifdef CONFIG_HIP_PERFORMANCE
934- HIP_DEBUG("Stop and write PERF_I1\n");
935- hip_perf_stop_benchmark(perf_set, PERF_I1);
936- hip_perf_write_benchmark(perf_set, PERF_I1);
937-#endif
938-
939- return NF_ACCEPT;
940-}
941-
942-/**
943- * Dummy function, necessary only for performance measurements.
944- *
945- * @param ctx context of the packet containing the R1
946- * @return NF_ACCEPT verdict
947- */
948-static int pisa_handler_r1(UNUSED struct hip_fw_context *ctx)
949-{
950-#ifdef CONFIG_HIP_PERFORMANCE
951- HIP_DEBUG("Start PERF_R1\n");
952- hip_perf_start_benchmark(perf_set, PERF_R1);
953-#endif
954-
955-#ifdef CONFIG_HIP_PERFORMANCE
956- HIP_DEBUG("Stop and write PERF_R1\n");
957- hip_perf_stop_benchmark(perf_set, PERF_R1);
958- hip_perf_write_benchmark(perf_set, PERF_R1);
959-#endif
960-
961- return NF_ACCEPT;
962-}
963-
964-/**
965- * Insert a PISA puzzle into the I2 packet.
966- *
967- * @param ctx context of the packet to modify
968- * @return NF_ACCEPT verdict
969- */
970-static int pisa_handler_i2(struct hip_fw_context *ctx)
971-{
972-#ifdef CONFIG_HIP_PERFORMANCE
973- HIP_DEBUG("Start PERF_I2\n");
974- hip_perf_start_benchmark(perf_set, PERF_I2);
975-#endif
976- pisa_insert_puzzle(ctx);
977-
978-#ifdef CONFIG_HIP_PERFORMANCE
979- HIP_DEBUG("Stop and write PERF_I2\n");
980- hip_perf_stop_benchmark(perf_set, PERF_I2);
981- hip_perf_write_benchmark(perf_set, PERF_I2);
982-#endif
983-
984- return NF_ACCEPT;
985-}
986-
987-/**
988- * Check for a PISA puzzle, a valid signature and a valid
989- * certificate in the R2 packet.
990- *
991- * @param ctx context of the packet to check
992- * @return verdict, either NF_ACCEPT or NF_DROP
993- */
994-static int pisa_handler_r2(struct hip_fw_context *ctx)
995-{
996- int verdict = NF_DROP, sig = 0, cert = 0;
997- struct hip_challenge_response *solution = NULL;
998-
999-#ifdef CONFIG_HIP_PERFORMANCE
1000- HIP_DEBUG("Start PERF_R2\n");
1001- hip_perf_start_benchmark(perf_set, PERF_R2);
1002-#endif
1003-
1004- solution = pisa_check_challenge_response(ctx);
1005- cert = pisa_check_certificate(ctx);
1006-
1007- if (solution == NULL || sig != 0 || cert != 0) {
1008- /* disallow further communication if either nonce, solution,
1009- * signature or certificate were not correct */
1010- pisa_reject_connection(ctx);
1011- verdict = NF_DROP;
1012- } else {
1013- /* allow futher communication otherwise */
1014- pisa_accept_connection(ctx);
1015- verdict = NF_ACCEPT;
1016- }
1017-
1018-#ifdef CONFIG_HIP_PERFORMANCE
1019- HIP_DEBUG("Stop and write PERF_R2, PERF_BASE\n");
1020- hip_perf_stop_benchmark(perf_set, PERF_R2);
1021- hip_perf_stop_benchmark(perf_set, PERF_BASE);
1022- hip_perf_write_benchmark(perf_set, PERF_R2);
1023- hip_perf_write_benchmark(perf_set, PERF_BASE);
1024-#endif
1025-
1026- return verdict;
1027-}
1028-
1029-/**
1030- * Insert a PISA nonce and a PISA puzzle into the U1 packet.
1031- *
1032- * @param ctx context of the packet to modify
1033- * @return NF_ACCEPT verdict
1034- */
1035-static int pisa_handler_u1(struct hip_fw_context *ctx)
1036-{
1037- pisa_insert_puzzle(ctx);
1038-
1039- return NF_ACCEPT;
1040-}
1041-
1042-/**
1043- * Check for a PISA nonce, a PISA puzzle, a valid signature and a valid
1044- * certificate in the U2 packet.
1045- *
1046- * @param ctx context of the packet to check
1047- * @return verdict, either NF_ACCEPT or NF_DROP
1048- */
1049-static int pisa_handler_u2(struct hip_fw_context *ctx)
1050-{
1051- int verdict = NF_DROP;
1052- int sig = 0;
1053- int cert = 0;
1054- struct hip_challenge_response *solution = NULL;
1055-
1056- solution = pisa_check_challenge_response(ctx);
1057- cert = pisa_check_certificate(ctx);
1058-
1059- if (solution == NULL || sig != 0 || cert != 0) {
1060- HIP_DEBUG("U2 packet did not match criteria: "
1061- "solution %p, signature %i, cert %i\n",
1062- solution, sig, cert);
1063- verdict = NF_DROP;
1064- } else {
1065- /* packet was ok, insert another puzzle */
1066- pisa_insert_puzzle(ctx);
1067- verdict = NF_ACCEPT;
1068- }
1069-
1070- return verdict;
1071-}
1072-
1073-/**
1074- * Check for a PISA nonce and a valid signature in the U3 packet.
1075- *
1076- * @param ctx context of the packet to check
1077- * @return verdict, either NF_ACCEPT or NF_DROP
1078- */
1079-static int pisa_handler_u3(struct hip_fw_context *ctx)
1080-{
1081- int verdict = NF_DROP;
1082- int sig = 0;
1083- struct hip_challenge_response *solution = NULL;
1084-
1085- solution = pisa_check_challenge_response(ctx);
1086-
1087- if (solution == NULL || sig != 0) {
1088- HIP_DEBUG("U2 packet did not match criteria: "
1089- "solution %p\n",
1090- solution);
1091- pisa_reject_connection(ctx);
1092- verdict = NF_DROP;
1093- } else {
1094- pisa_accept_connection(ctx);
1095- verdict = NF_ACCEPT;
1096- }
1097- return verdict;
1098-}
1099-
1100-/**
1101- * Handle CLOSE_ACK packet. Remove the connection from the list of accepted
1102- * connections
1103- *
1104- * @param ctx context of the packet
1105- * @return verdict, either NF_ACCEPT or NF_DROP
1106- */
1107-static int pisa_handler_close_ack(struct hip_fw_context *ctx)
1108-{
1109- pisa_remove_connection(ctx);
1110- return NF_ACCEPT;
1111-}
1112-
1113-/**
1114- * Initialize basic PISA functionality
1115- *
1116- * @param h function pointers for packet handlers
1117- */
1118-void pisa_init(struct midauth_handlers *h)
1119-{
1120- char hit[INET6_ADDRSTRLEN];
1121- h->i1 = pisa_handler_i1;
1122- h->r1 = pisa_handler_r1;
1123- h->i2 = pisa_handler_i2;
1124- h->r2 = pisa_handler_r2;
1125- h->u1 = pisa_handler_u1;
1126- h->u2 = pisa_handler_u2;
1127- h->u3 = pisa_handler_u3;
1128- h->close = midauth_handler_accept;
1129- h->close_ack = pisa_handler_close_ack;
1130-
1131- pisa_generate_random();
1132- pisa_generate_random();
1133-
1134- if (!pisa_read_communit_operator_hit(hit)) {
1135- hit[0] = '\0';
1136- HIP_ERROR("Could not load Communit-Operator HIT from file %s\n",
1137- CO_HIT_FILE);
1138- }
1139-
1140- if (inet_pton(AF_INET6, hit, &community_operator_hit) <= 0) {
1141- HIP_ERROR("Coult not parse Community-Operator HIT\n");
1142- }
1143+ sk_X509_push(root_chain, cert);
1144+ }
1145+ list = list->next;
1146+ }
1147+
1148+ if (use_cert) {
1149+ HIP_DEBUG("certificates activated\n");
1150+ }
1151+
1152+ return 0;
1153+}
1154+
1155+/**
1156+ * Uninit function for certificate functionality.
1157+ *
1158+ * @return 0
1159+ */
1160+int cert_uninit(void)
1161+{
1162+ sk_X509_free(root_chain);
1163+ return 0;
1164+}
1165+
1166+/**
1167+ * Helper function that converts the special RSA and DSA key structures
1168+ * to the generic EVP_PKEY structure.
1169+ *
1170+ * @param key the RSA or DSA key structure
1171+ * @param algo either HIP_HI_RSA or HIP_HI_DSA
1172+ *
1173+ * @return the EVP_PKEY structure that wraps the original key,
1174+ * or NULL on error
1175+ */
1176+static EVP_PKEY *any_key_to_evp_key(void *key, int algo)
1177+{
1178+ int err = 0;
1179+ EVP_PKEY *ret = NULL;
1180+
1181+ if (!(ret = EVP_PKEY_new())) {
1182+ HIP_ERROR("Could not init EVP_PKEY wrapper\n");
1183+ return NULL;
1184+ }
1185+
1186+ switch (algo) {
1187+ case HIP_HI_RSA:
1188+ err = EVP_PKEY_assign_RSA(ret, key);
1189+ break;
1190+ case HIP_HI_DSA:
1191+ err = EVP_PKEY_assign_DSA(ret, key);
1192+ break;
1193+ default:
1194+ HIP_DEBUG("Unknown algorithm \n");
1195+ }
1196+ if (err == 0) {
1197+ HIP_ERROR("Could not assign key to EVP_PKEY.\n");
1198+ EVP_PKEY_free(ret);
1199+ return NULL;
1200+ }
1201+
1202+ return ret;
1203+}
1204+
1205+/**
1206+ * Extract the certificate from the R2 packet and match the contained public
1207+ * key against the HI provided in the R1 and try to build and verify
1208+ * a certificate chain.
1209+ *
1210+ * For an update exchange, a certificate must be contained either in the U2
1211+ * (if the exchange was started by the Initiator) or in the U3
1212+ * (if the exchange was started by the Responder). If a certificate cannot be
1213+ * found in these situations an error is returned.
1214+ *
1215+ * @param common the R2 or U2 packet
1216+ * @param tuple the connection tracking tuple
1217+ * @param ctx the firewall context
1218+ * @return 0 on success, negative error code otherwise
1219+ */
1220+int cert_handle_certificate(const struct hip_common *const common,
1221+ UNUSED struct tuple *const tuple,
1222+ UNUSED const struct hip_fw_context *const ctx)
1223+{
1224+ X509 *cert = NULL;
1225+ EVP_PKEY *pkey = NULL;
1226+
1227+ if (use_cert) {
1228+ /* Should there be a certificate?
1229+ * Not if this update is not sent by the Responder. */
1230+ if (!(tuple->direction == REPLY_DIR)) {
1231+ return 0;
1232+ }
1233+
1234+ /* Extract certificate of trust point from the packet. */
1235+ if (!(cert = cert_get_X509_from_msg(common))) {
1236+ HIP_DEBUG("Could not find trust-point certificate in R2/U2.\n");
1237+ return -1;
1238+ }
1239+
1240+ /* Match HI against public key in given certificate. */
1241+ pkey = any_key_to_evp_key(tuple->hip_tuple->data->src_pub_key,
1242+ hip_get_host_id_algo(tuple->hip_tuple->data->src_hi));
1243+ if (!cert_match_public_key(cert, pkey)) {
1244+ HIP_ERROR("HI does not match public key in given certificate.\n");
1245+ return -1;
1246+ }
1247+ HIP_DEBUG("HI matches given certificate.\n");
1248+
1249+ /* Check certificate of trust point. */
1250+ if (cert_verify_chain(cert, NULL, root_chain, NULL)) {
1251+ HIP_ERROR("Could not verify trust point certificate.\n");
1252+ return -1;
1253+ }
1254+
1255+ HIP_DEBUG("Verified trust-point certificate.\n");
1256+ }
1257+
1258+ return 0;
1259 }
1260
1261=== renamed file 'hipfw/pisa.h' => 'hipfw/cert.h'
1262--- hipfw/pisa.h 2011-11-25 13:52:20 +0000
1263+++ hipfw/cert.h 2012-03-16 04:27:22 +0000
1264@@ -1,5 +1,5 @@
1265 /*
1266- * Copyright (c) 2010 Aalto University and RWTH Aachen University.
1267+ * Copyright (c) 2010-2011 Aalto University and RWTH Aachen University.
1268 *
1269 * Permission is hereby granted, free of charge, to any person
1270 * obtaining a copy of this software and associated documentation
1271@@ -23,26 +23,16 @@
1272 * OTHER DEALINGS IN THE SOFTWARE.
1273 */
1274
1275-#ifndef HIPL_HIPFW_PISA_H
1276-#define HIPL_HIPFW_PISA_H
1277-
1278-#include "midauth.h"
1279-
1280-#define PISA_STATE_DISALLOW 0
1281-#define PISA_STATE_ALLOW 1
1282-
1283-#ifdef CONFIG_HIP_PISA
1284-/**
1285- * Register PISA handlers with midauth and initialize data structures.
1286- *
1287- * @param h pointer to the handlers
1288- */
1289-void pisa_init(struct midauth_handlers *h);
1290-#endif
1291-
1292-/**
1293- * Check if a new random number is necessary.
1294- */
1295-void pisa_check_for_random_update(void);
1296-
1297-#endif /* HIPL_HIPFW_PISA_H */
1298+#ifndef HIPL_HIPFW_CERT_H
1299+#define HIPL_HIPFW_CERT_H
1300+
1301+#include "hipfw_defines.h"
1302+
1303+int cert_init(void);
1304+int cert_uninit(void);
1305+
1306+int cert_handle_certificate(const struct hip_common *const common,
1307+ struct tuple *const tuple,
1308+ const struct hip_fw_context *const ctx);
1309+
1310+#endif /* HIPL_HIPFW_CERT_H */
1311
1312=== modified file 'hipfw/conntrack.c'
1313--- hipfw/conntrack.c 2012-03-08 14:33:33 +0000
1314+++ hipfw/conntrack.c 2012-03-16 04:27:22 +0000
1315@@ -1,5 +1,5 @@
1316 /*
1317- * Copyright (c) 2010-2011 Aalto University and RWTH Aachen University.
1318+ * Copyright (c) 2010-2012 Aalto University and RWTH Aachen University.
1319 *
1320 * Permission is hereby granted, free of charge, to any person
1321 * obtaining a copy of this software and associated documentation
1322@@ -62,8 +62,9 @@
1323 #include "lib/core/state.h"
1324 #include "lib/core/gpl/pk.h"
1325 #include "modules/update/hipd/update.h"
1326+#include "config.h"
1327+#include "cert.h"
1328 #include "common_types.h"
1329-#include "config.h"
1330 #include "conntrack.h"
1331 #include "dlist.h"
1332 #include "hslist.h"
1333@@ -72,7 +73,7 @@
1334 #include "hipfw.h"
1335 #include "helpers.h"
1336 #include "hslist.h"
1337-#include "pisa.h"
1338+#include "midauth.h"
1339 #include "reinject.h"
1340
1341
1342@@ -1296,6 +1297,11 @@
1343 return 0;
1344 }
1345
1346+ if (cert_handle_certificate(common, tuple, ctx)) {
1347+ HIP_ERROR("certificate error on R2\n");
1348+ return 0;
1349+ }
1350+
1351 /* check if the R2 contains ESP protection anchor and store state */
1352 if (esp_prot_conntrack_R2_anchor(common, tuple)) {
1353 HIP_ERROR("failed to track esp protection extension state\n");
1354@@ -1330,7 +1336,7 @@
1355 uint8_t locator_type;
1356
1357 ptr = (const char *) (locator + 1);
1358- while (ptr < ptr + hip_get_param_contents_len(locator)) {
1359+ while (ptr < ((const char *) (locator + 1)) + hip_get_param_contents_len(locator)) {
1360 locator_type = ((const struct hip_locator_type_0 *) ptr)->header.locator_type;
1361 if (locator_type == HIP_LOCATOR_LOCATOR_TYPE_IPV6) {
1362 esp_dest_addr = &((const struct hip_locator_type_0 *) ptr)->address;
1363@@ -1368,11 +1374,6 @@
1364 {
1365 int err = 1;
1366
1367- if (hip_get_param_total_len(locator) - sizeof(struct hip_locator) < sizeof(struct hip_locator_type_0)) {
1368- HIP_ERROR("no locator param found\n");
1369- return 0;
1370- }
1371-
1372 if (esp_info && locator && seq) {
1373 HIP_DEBUG("esp_info, locator and seq\n");
1374
1375@@ -1386,6 +1387,11 @@
1376 esp_tuple->spi = ntohl(esp_info->new_spi);
1377 esp_tuple->spi_update_id = seq->update_id;
1378
1379+ if (hip_get_param_total_len(locator) - sizeof(struct hip_locator) < sizeof(struct hip_locator_type_0)) {
1380+ HIP_ERROR("no locator param found\n");
1381+ return 0;
1382+ }
1383+
1384 HIP_IFEL(!update_esp_dest_addr(locator, seq, esp_tuple),
1385 0, "error updateing ESP destination addresses\n");
1386 } else if (esp_info && seq) {
1387@@ -1597,6 +1603,11 @@
1388 return 0;
1389 }
1390
1391+ if (cert_handle_certificate(common, tuple, ctx)) {
1392+ HIP_ERROR("certificate error on U2\n");
1393+ return 0;
1394+ }
1395+
1396 if (handle_second_update(tuple, ctx, esp_info, seq)) {
1397 HIP_ERROR("unable to process second UPDATE message\n");
1398 return 0;
1399
1400=== modified file 'hipfw/hipfw.c'
1401--- hipfw/hipfw.c 2012-03-08 12:28:00 +0000
1402+++ hipfw/hipfw.c 2012-03-16 04:27:22 +0000
1403@@ -78,6 +78,7 @@
1404 #include "hipd/hipd.h"
1405 #include "config.h"
1406 #include "cache.h"
1407+#include "cert.h"
1408 #include "common_types.h"
1409 #include "conntrack.h"
1410 #include "esp_prot_api.h"
1411@@ -87,7 +88,6 @@
1412 #include "helpers.h"
1413 #include "lsi.h"
1414 #include "midauth.h"
1415-#include "pisa.h"
1416 #include "port_bindings.h"
1417 #include "reinject.h"
1418 #include "rewrite.h"
1419@@ -481,6 +481,8 @@
1420
1421 midauth_init();
1422
1423+ HIP_IFEL(cert_init(), -1, "failed to load extension (cert)\n");
1424+
1425 // Initializing local port cache database
1426 hip_port_bindings_init(true);
1427 /* Initialize raw sockets for packet reinjection */
1428@@ -628,6 +630,8 @@
1429 fw_uninit_lsi_support();
1430 hip_fw_uninit_conntrack();
1431
1432+ cert_uninit();
1433+
1434 #ifdef CONFIG_HIP_PERFORMANCE
1435 /* Deallocate memory of perf_set after finishing all of tests */
1436 hip_perf_destroy(perf_set);
1437@@ -1876,12 +1880,6 @@
1438 continue;
1439 }
1440
1441-#ifdef CONFIG_HIP_PISA
1442- if (use_midauth) {
1443- pisa_check_for_random_update();
1444- }
1445-#endif
1446-
1447 if (FD_ISSET(h4->fd, &read_fdset)) {
1448 HIP_DEBUG("received IPv4 packet from iptables queue\n");
1449 err = fw_handle_packet(buf, h4, 4, &ctx);
1450
1451=== modified file 'hipfw/hipfw.conf'
1452--- hipfw/hipfw.conf 2011-12-15 13:25:00 +0000
1453+++ hipfw/hipfw.conf 2012-03-16 04:27:22 +0000
1454@@ -7,5 +7,6 @@
1455 # -i [!] <incoming interface>
1456 # -o [!] <outgoing interface>
1457 # -state [!] <state> --verify_responder --accept_mobile --decrypt_contents
1458+# -cert <root certificate>"
1459 #
1460
1461
1462=== modified file 'hipfw/hipfw_defines.h'
1463--- hipfw/hipfw_defines.h 2012-02-17 18:01:18 +0000
1464+++ hipfw/hipfw_defines.h 2012-03-16 04:27:22 +0000
1465@@ -158,7 +158,6 @@
1466 /* members needed for ESP protection extension */
1467 int num_esp_prot_tfms;
1468 uint8_t esp_prot_tfms[MAX_NUM_TRANSFORMS];
1469- int pisa_state;
1470 };
1471
1472 #endif /* HIPL_HIPFW_FIREWALL_DEFINES_H */
1473
1474=== modified file 'hipfw/main.c'
1475--- hipfw/main.c 2011-11-25 13:52:20 +0000
1476+++ hipfw/main.c 2012-03-16 04:27:22 +0000
1477@@ -37,14 +37,15 @@
1478
1479 #include <stdio.h>
1480 #include <stdlib.h>
1481+#include <string.h>
1482 #include <unistd.h>
1483 #include <sys/types.h>
1484
1485 #include "lib/core/filemanip.h"
1486 #include "lib/core/debug.h"
1487 #include "lib/core/util.h"
1488+#include "conntrack.h"
1489 #include "hipfw.h"
1490-#include "conntrack.h"
1491 #include "midauth.h"
1492
1493
1494
1495=== removed file 'hipfw/pisa_cert.c'
1496--- hipfw/pisa_cert.c 2011-08-15 14:11:56 +0000
1497+++ hipfw/pisa_cert.c 1970-01-01 00:00:00 +0000
1498@@ -1,205 +0,0 @@
1499-/*
1500- * Copyright (c) 2010 Aalto University and RWTH Aachen University.
1501- *
1502- * Permission is hereby granted, free of charge, to any person
1503- * obtaining a copy of this software and associated documentation
1504- * files (the "Software"), to deal in the Software without
1505- * restriction, including without limitation the rights to use,
1506- * copy, modify, merge, publish, distribute, sublicense, and/or sell
1507- * copies of the Software, and to permit persons to whom the
1508- * Software is furnished to do so, subject to the following
1509- * conditions:
1510- *
1511- * The above copyright notice and this permission notice shall be
1512- * included in all copies or substantial portions of the Software.
1513- *
1514- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
1515- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
1516- * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
1517- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
1518- * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
1519- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
1520- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
1521- * OTHER DEALINGS IN THE SOFTWARE.
1522- */
1523-
1524-/**
1525- * @file
1526- * This file deals with the PISA specific handling of SPKI certificates. The
1527- * certificate is parsed and split into small chunks.
1528- *
1529- * @brief PISA handling for SPKI certificates
1530- */
1531-
1532-#define _BSD_SOURCE
1533-
1534-#include <string.h>
1535-#include <time.h>
1536-#include <arpa/inet.h>
1537-#include <netinet/in.h>
1538-#include <sys/types.h>
1539-
1540-#include "pisa_cert.h"
1541-
1542-
1543-/**
1544- * Extract parts of a SPKI certificate.
1545- *
1546- * @param cert pointer to the certificate text or part of a certificate text
1547- * @param name pointer to the pattern we are looking for
1548- * @param r pointer to a buffer that the search result will be copied to
1549- * @return 0 on success
1550- */
1551-static char *pisa_cert_get_part(char *cert, const char *name, char *r)
1552-{
1553- int level = 0, len = 0;
1554- char *p = cert, *start = NULL;
1555-
1556- if (!r) {
1557- return NULL;
1558- }
1559-
1560- if (!cert) {
1561- goto out_err;
1562- }
1563-
1564- if (!name) {
1565- goto out_err;
1566- }
1567-
1568- len = strlen(name);
1569- if (len == 0) {
1570- goto out_err;
1571- }
1572-
1573- while (*p) {
1574- if (*p == '(') {
1575- level++;
1576- if (level == 2 && !strncmp(p + 1, name, len)) {
1577- if (*(p + len + 1) == ' ') {
1578- start = p++;
1579- break;
1580- }
1581- }
1582- }
1583- if (*p == ')') {
1584- level--;
1585- }
1586- if (level == 0) {
1587- break;
1588- }
1589- p++;
1590- }
1591-
1592- if (!start) {
1593- goto out_err;
1594- }
1595-
1596- len = 0;
1597-
1598- while (*p) {
1599- if (*p == '(') {
1600- level++;
1601- }
1602- if (*p == ')') {
1603- level--;
1604- if (level == 1) {
1605- len = p - start + 1;
1606- break;
1607- }
1608- }
1609- if (level == 0) {
1610- break;
1611- }
1612- p++;
1613- }
1614-
1615- strncpy(r, start, len);
1616- r[len] = '\0';
1617-
1618- return r;
1619-
1620-out_err:
1621- r[0] = '\0';
1622- return NULL;
1623-}
1624-
1625-/**
1626- * Get the content from a SPKI certificate part.
1627- *
1628- * @param cert pointer to the certificate text or part of a certificate text
1629- * @param name pointer to the pattern we are looking for
1630- * @param r pointer to a buffer that the search result will be copied to
1631- * @return 0 on success
1632- */
1633-static void pisa_cert_get_content(char *cert, const char *name, char *r)
1634-{
1635- char *start = cert;
1636- int len = 0;
1637-
1638- if (!r) {
1639- return;
1640- }
1641-
1642- if (!cert || !name || !*name == '(') {
1643- goto out_err;
1644- }
1645-
1646- if (strlen(name) + 3 > strlen(cert)) {
1647- goto out_err;
1648- }
1649-
1650- if (strncmp(name, cert + 1, strlen(name))) {
1651- goto out_err;
1652- }
1653- start = cert + strlen(name) + 2;
1654-
1655- if (*start == '\0') {
1656- goto out_err;
1657- }
1658-
1659- len = strlen(start) - 1;
1660- if (*(start + len) != ')') {
1661- goto out_err;
1662- }
1663- strncpy(r, start, len);
1664-
1665-out_err:
1666- r[len] = '\0';
1667-}
1668-
1669-/**
1670- * Splits a certificate into semantic chunks and converts these to
1671- * sensible binary representations.
1672- *
1673- * @param cert the original certificate
1674- * @param pc internal representation of the certificate
1675- */
1676-void pisa_split_cert(char *cert, struct pisa_cert *pc)
1677-{
1678- struct tm t;
1679- char buffer1[224], buffer2[224];
1680- struct in6_addr addr;
1681-
1682- pisa_cert_get_part(cert, "not-before", buffer1);
1683- pisa_cert_get_content(buffer1, "not-before", buffer2);
1684- strptime(buffer2, "\"%Y-%m-%d_%H:%M:%S\"", &t);
1685- pc->not_before = mktime(&t);
1686-
1687- pisa_cert_get_part(cert, "not-after", buffer1);
1688- pisa_cert_get_content(buffer1, "not-after", buffer2);
1689- strptime(buffer2, "\"%Y-%m-%d_%H:%M:%S\"", &t);
1690- pc->not_after = mktime(&t);
1691-
1692- pisa_cert_get_part(cert, "issuer", buffer1);
1693- pisa_cert_get_part(buffer1, "hash hit", buffer2);
1694- pisa_cert_get_content(buffer2, "hash hit", buffer1);
1695- inet_pton(AF_INET6, buffer1, &addr);
1696- memcpy(&pc->hit_issuer, &addr, sizeof(struct in6_addr));
1697-
1698- pisa_cert_get_part(cert, "subject", buffer1);
1699- pisa_cert_get_part(buffer1, "hash hit", buffer2);
1700- pisa_cert_get_content(buffer2, "hash hit", buffer1);
1701- inet_pton(AF_INET6, buffer1, &addr);
1702- memcpy(&pc->hit_subject, &addr, sizeof(struct in6_addr));
1703-}
1704
1705=== removed file 'hipfw/pisa_cert.h'
1706--- hipfw/pisa_cert.h 2011-11-25 13:52:20 +0000
1707+++ hipfw/pisa_cert.h 1970-01-01 00:00:00 +0000
1708@@ -1,47 +0,0 @@
1709-/*
1710- * Copyright (c) 2010 Aalto University and RWTH Aachen University.
1711- *
1712- * Permission is hereby granted, free of charge, to any person
1713- * obtaining a copy of this software and associated documentation
1714- * files (the "Software"), to deal in the Software without
1715- * restriction, including without limitation the rights to use,
1716- * copy, modify, merge, publish, distribute, sublicense, and/or sell
1717- * copies of the Software, and to permit persons to whom the
1718- * Software is furnished to do so, subject to the following
1719- * conditions:
1720- *
1721- * The above copyright notice and this permission notice shall be
1722- * included in all copies or substantial portions of the Software.
1723- *
1724- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
1725- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
1726- * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
1727- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
1728- * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
1729- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
1730- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
1731- * OTHER DEALINGS IN THE SOFTWARE.
1732- */
1733-
1734-#ifndef HIPL_HIPFW_PISA_CERT_H
1735-#define HIPL_HIPFW_PISA_CERT_H
1736-
1737-#include <time.h>
1738-#include <netinet/in.h>
1739-
1740-struct pisa_cert {
1741- struct in6_addr hit_issuer;
1742- struct in6_addr hit_subject;
1743- time_t not_before;
1744- time_t not_after;
1745-};
1746-
1747-/**
1748- * Split the hip_cert_spki_info.cert part into small chunks
1749- *
1750- * @param cert the hip_cert_spki_info.cert part of the certificate
1751- * @param pc datastructure that will contain the chunks
1752- */
1753-void pisa_split_cert(char *cert, struct pisa_cert *pc);
1754-
1755-#endif /* HIPL_HIPFW_PISA_CERT_H */
1756
1757=== modified file 'hipfw/rule_management.c'
1758--- hipfw/rule_management.c 2011-12-15 13:53:03 +0000
1759+++ hipfw/rule_management.c 2012-03-16 04:27:22 +0000
1760@@ -68,6 +68,7 @@
1761 #define IN_IF_STR "-i"
1762 #define OUT_IF_STR "-o"
1763 #define STATE_STR "-state"
1764+#define CERT_STR "-cert"
1765 #define SRC_HI_STR "--hi"
1766 #define VERIFY_RESPONDER_STR "--verify_responder"
1767 #define ACCEPT_MOBILE_STR "--accept_mobile"
1768@@ -97,6 +98,7 @@
1769 STATE_OPTION,
1770 IN_IF_OPTION,
1771 OUT_IF_OPTION,
1772+ CERT_OPTION,
1773 HOOK
1774 };
1775
1776@@ -248,6 +250,7 @@
1777 rule->state = NULL;
1778 rule->in_if = NULL;
1779 rule->out_if = NULL;
1780+ rule->cert = NULL;
1781 rule->hook = -1;
1782 rule->accept = -1;
1783 return rule;
1784@@ -283,6 +286,7 @@
1785 free(rule->state);
1786 free_string_option(rule->in_if);
1787 free_string_option(rule->out_if);
1788+ free_string_option(rule->cert);
1789 free(rule);
1790 }
1791 }
1792@@ -682,6 +686,15 @@
1793 return NULL;
1794 }
1795 option_found = STATE_OPTION;
1796+ } else if (!strcmp(token, CERT_STR)) {
1797+ /* option already defined */
1798+ /* rule only applicable to forward hook */
1799+ if (rule->cert != NULL || rule->hook != NF_IP6_FORWARD) {
1800+ HIP_DEBUG("error parsing rule: cert option \n");
1801+ free_rule(rule);
1802+ return NULL;
1803+ }
1804+ option_found = CERT_OPTION;
1805 } else if (!strcmp(token, VERIFY_RESPONDER_STR)) {
1806 /* related state option must be defined */
1807 if (rule->state == NULL) {
1808@@ -794,6 +807,16 @@
1809 return NULL;
1810 }
1811 option_found = NO_OPTION;
1812+ } else if (option_found == CERT_OPTION) {
1813+ rule->cert = malloc(sizeof(struct string_option));
1814+ rule->cert->value = strdup(token);
1815+ rule->cert->boolean = 0;
1816+ if (rule->cert == NULL || rule->cert->value == NULL) {
1817+ HIP_DEBUG("error parsing rule: cert value \n");
1818+ free_rule(rule);
1819+ return NULL;
1820+ }
1821+ option_found = NO_OPTION;
1822 } else if (option_found == IN_IF_OPTION) {
1823 rule->in_if = parse_if(token);
1824 if (rule->in_if == NULL) {
1825
1826=== modified file 'hipfw/rule_management.h'
1827--- hipfw/rule_management.h 2011-11-25 13:52:20 +0000
1828+++ hipfw/rule_management.h 2012-03-16 04:27:22 +0000
1829@@ -76,6 +76,7 @@
1830 struct hip_host_id *src_hi;
1831 struct int_option *type;
1832 struct state_option *state;
1833+ struct string_option *cert;
1834 struct string_option *in_if;
1835 struct string_option *out_if;
1836 unsigned int hook;
1837
1838=== modified file 'lib/core/builder.c'
1839--- lib/core/builder.c 2012-03-12 15:55:54 +0000
1840+++ lib/core/builder.c 2012-03-16 04:27:22 +0000
1841@@ -1118,6 +1118,10 @@
1842 case HIP_MSG_REINIT_FULLRELAY: return "HIP_MSG_REINIT_FULLRELAY";
1843 case HIP_MSG_FIREWALL_START: return "HIP_MSG_FIREWALL_START";
1844 case HIP_MSG_MANUAL_UPDATE_PACKET: return "HIP_MSG_MANUAL_UPDATE_PACKET";
1845+ case HIP_MSG_CERT_SPKI_SIGN: return "HIP_MSG_CERT_SPKI_SIGN";
1846+ case HIP_MSG_CERT_SPKI_VERIFY: return "HIP_MSG_CERT_SPKI_VERIFY";
1847+ case HIP_MSG_CERT_X509V3_SIGN: return "HIP_MSG_CERT_X509V3_SIGN";
1848+ case HIP_MSG_CERT_X509V3_VERIFY: return "HIP_MSG_CERT_X509V3_VERIFY";
1849 default:
1850 return lmod_get_packet_identifier(msg_type);
1851 }
1852@@ -1137,6 +1141,8 @@
1853 switch (param_type) {
1854 case HIP_PARAM_ACK: return "HIP_PARAM_ACK";
1855 case HIP_PARAM_CERT: return "HIP_PARAM_CERT";
1856+ case HIP_PARAM_CERT_X509_REQ: return "HIP_PARAM_CERT_X509_REQ";
1857+ case HIP_PARAM_CERT_X509_RESP: return "HIP_PARAM_CERT_X509_RESP";
1858 case HIP_PARAM_DH_SHARED_KEY: return "HIP_PARAM_DH_SHARED_KEY";
1859 case HIP_PARAM_DIFFIE_HELLMAN: return "HIP_PARAM_DIFFIE_HELLMAN";
1860 case HIP_PARAM_DSA_SIGN_DATA: return "HIP_PARAM_DSA_SIGN_DATA";
1861@@ -3265,7 +3271,8 @@
1862 * @return zero on success or negative on failure
1863 */
1864 int hip_build_param_cert(struct hip_common *msg, uint8_t group, uint8_t count,
1865- uint8_t id, uint8_t type, void *data, size_t size)
1866+ uint8_t id, enum hip_cert_type type, void *data,
1867+ size_t size)
1868 {
1869 struct hip_cert cert;
1870
1871@@ -3352,7 +3359,7 @@
1872 }
1873
1874 /**
1875- * Build and append a X509 certiticate request parameter into a HIP control
1876+ * Build and append a X509 certificate request parameter into a HIP control
1877 * message (on-the-wire)
1878 *
1879 * @param msg a pointer to the message where the parameter will be
1880@@ -3361,7 +3368,7 @@
1881 * @return zero on success, or negative on failure
1882 * @see <a href="http://tools.ietf.org/html/draft-ietf-hip-cert">draft-ietf-hip-cert</a>
1883 */
1884-int hip_build_param_cert_x509_req(struct hip_common *msg, struct in6_addr *addr)
1885+int hip_build_param_cert_x509_req(struct hip_common *msg, hip_hit_t *addr)
1886 {
1887 struct hip_cert_x509_req subj;
1888
1889@@ -3374,18 +3381,24 @@
1890 return hip_build_param(msg, &subj);
1891 }
1892
1893-static int build_param_cert_x509(struct hip_common *msg, char *der, int len, unsigned param)
1894+static int build_param_cert_x509(struct hip_common *msg, char *der, uint32_t len, unsigned param)
1895 {
1896- struct hip_cert_x509_resp local;
1897-
1898- hip_set_param_type((struct hip_tlv_common *) &local, param);
1899- hip_calc_param_len((struct hip_tlv_common *) &local,
1900- sizeof(struct hip_cert_x509_resp)
1901- - sizeof(struct hip_tlv_common));
1902- memcpy(&local.der, der, len);
1903- local.der_len = len;
1904-
1905- return hip_build_param(msg, &local);
1906+ int err = -1;
1907+ struct hip_cert_x509_resp local = { 0 };
1908+
1909+ if (len <= sizeof(local.der)) {
1910+ hip_set_param_type((struct hip_tlv_common *) &local, param);
1911+ hip_calc_param_len((struct hip_tlv_common *) &local,
1912+ sizeof(struct hip_cert_x509_resp)
1913+ - sizeof(struct hip_tlv_common));
1914+ memcpy(&local.der, der, len);
1915+
1916+ const uint32_t der_len_h = len;
1917+ local.der_len = htonl(der_len_h);
1918+
1919+ err = hip_build_param(msg, &local);
1920+ }
1921+ return err;
1922 }
1923
1924 /**
1925@@ -3399,7 +3412,7 @@
1926 * @return zero on success, or negative on failure
1927 * @see <a href="http://tools.ietf.org/html/draft-ietf-hip-cert">draft-ietf-hip-cert</a>
1928 */
1929-int hip_build_param_cert_x509_resp(struct hip_common *msg, char *der, int len)
1930+int hip_build_param_cert_x509_resp(struct hip_common *msg, char *der, uint32_t len)
1931 {
1932 return build_param_cert_x509(msg, der, len, HIP_PARAM_CERT_X509_RESP);
1933 }
1934@@ -3415,7 +3428,7 @@
1935 * @return zero on success, or negative on failure
1936 * @see <a href="http://tools.ietf.org/html/draft-ietf-hip-cert">draft-ietf-hip-cert</a>
1937 */
1938-int hip_build_param_cert_x509_ver(struct hip_common *msg, char *der, int len)
1939+int hip_build_param_cert_x509_ver(struct hip_common *msg, char *der, uint32_t len)
1940 {
1941 return build_param_cert_x509(msg, der, len, HIP_PARAM_CERT_X509_REQ);
1942 }
1943
1944=== modified file 'lib/core/builder.h'
1945--- lib/core/builder.h 2012-02-23 10:43:16 +0000
1946+++ lib/core/builder.h 2012-03-16 04:27:22 +0000
1947@@ -115,13 +115,9 @@
1948 uint32_t,
1949 uint16_t,
1950 struct hip_crypto_key *);
1951-int hip_build_param_cert(struct hip_common *,
1952- uint8_t,
1953- uint8_t,
1954- uint8_t,
1955- uint8_t,
1956- void *,
1957- size_t);
1958+int hip_build_param_cert(struct hip_common *msg, uint8_t group, uint8_t count,
1959+ uint8_t id, enum hip_cert_type type, void *data,
1960+ size_t size);
1961 int hip_build_param_puzzle(struct hip_common *const msg,
1962 const uint8_t val_K,
1963 const uint8_t lifetime,
1964@@ -159,8 +155,10 @@
1965 int hip_build_param_cert_spki_info(struct hip_common *msg,
1966 struct hip_cert_spki_info *cert_info);
1967 int hip_build_param_cert_x509_req(struct hip_common *, struct in6_addr *);
1968-int hip_build_param_cert_x509_resp(struct hip_common *, char *, int);
1969-int hip_build_param_cert_x509_ver(struct hip_common *, char *, int);
1970+int hip_build_param_cert_x509_resp(struct hip_common *msg, char *der,
1971+ uint32_t len);
1972+int hip_build_param_cert_x509_ver(struct hip_common *msg, char *der,
1973+ uint32_t len);
1974
1975 int hip_build_param_hit_to_ip_set(struct hip_common *, const char *);
1976 int hip_build_user_hdr(struct hip_common *, hip_hdr, hip_hdr_err);
1977
1978=== added file 'lib/core/cert.c'
1979--- lib/core/cert.c 1970-01-01 00:00:00 +0000
1980+++ lib/core/cert.c 2012-03-16 04:27:22 +0000
1981@@ -0,0 +1,298 @@
1982+/*
1983+ * Copyright (c) 2010-2012 Aalto University and RWTH Aachen University.
1984+ *
1985+ * Permission is hereby granted, free of charge, to any person
1986+ * obtaining a copy of this software and associated documentation
1987+ * files (the "Software"), to deal in the Software without
1988+ * restriction, including without limitation the rights to use,
1989+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
1990+ * copies of the Software, and to permit persons to whom the
1991+ * Software is furnished to do so, subject to the following
1992+ * conditions:
1993+ *
1994+ * The above copyright notice and this permission notice shall be
1995+ * included in all copies or substantial portions of the Software.
1996+ *
1997+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
1998+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
1999+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
2000+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
2001+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
2002+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
2003+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
2004+ * OTHER DEALINGS IN THE SOFTWARE.
2005+ */
2006+
2007+/**
2008+ * @file
2009+ * @brief functionality for handling X509 certificates
2010+ */
2011+
2012+#include <errno.h>
2013+#include <stdio.h>
2014+#include <stdlib.h>
2015+#include <string.h>
2016+#include <unistd.h>
2017+#include <openssl/x509.h>
2018+#include <openssl/pem.h>
2019+
2020+#include "builder.h"
2021+#include "debug.h"
2022+#include "ife.h"
2023+#include "common.h"
2024+#include "cert.h"
2025+
2026+/**
2027+ * This function encodes the given certificate to its DER encoding for
2028+ * transmission over the wire. The encoded certificate is written to @p buf.
2029+ *
2030+ * @param cert the certificate to encode
2031+ * @param buf the output is written here
2032+ *
2033+ * @return the length of the encoded data
2034+ *
2035+ * @note: The encoded data is in binary form and may contain embedded zeroes.
2036+ * Functions such as strlen() will not return the correct length of the
2037+ * encoded structure. Therefore the length value returned by this
2038+ * function should always be used.
2039+ */
2040+int cert_X509_to_DER(X509 *const cert, unsigned char **buf)
2041+{
2042+ int len;
2043+
2044+ if (!cert) {
2045+ HIP_ERROR("Cannot encode NULL-certificate\n");
2046+ return -1;
2047+ }
2048+ if (!buf) {
2049+ HIP_ERROR("Cannot create output buffer at NULL-pointer.\n");
2050+ return -1;
2051+ }
2052+
2053+ *buf = NULL;
2054+ len = i2d_X509(cert, buf);
2055+
2056+ if (len < 0) {
2057+ HIP_ERROR("Could not DER-encode the given certificate.\n");
2058+ return -1;
2059+ }
2060+ return len;
2061+}
2062+
2063+/**
2064+ * Function to decode a DER-encoded certificate to the internal OpenSSL X509
2065+ * structure.
2066+ *
2067+ * @param buf the buffer from which the DER-encoded certificate is read
2068+ * @param len the length of the DER-encoded certificate
2069+ * (NOTE: strlen() and similar functions fail, since DER is
2070+ * basically binary data that can contain 0-bytes).
2071+ *
2072+ * @return the OpenSSL X509 structure corresponding the DER-encoded
2073+ * certificate, NULL if errors occured
2074+ */
2075+X509 *cert_DER_to_X509(const unsigned char *buf, const int len)
2076+{
2077+ if (!buf) {
2078+ HIP_ERROR("Cannot decode from NULL-buffer\n");
2079+ return NULL;
2080+ }
2081+ if (len <= 0) {
2082+ HIP_ERROR("Cannot decode certificate of length <= 0\n");
2083+ return NULL;
2084+ }
2085+ return d2i_X509(NULL, &buf, len);
2086+}
2087+
2088+/**
2089+ * Load a X509 certificate from @p file. If @p file contains more
2090+ * than one certificate, the certificate at the top of the file is
2091+ * returned.
2092+ *
2093+ * @param file the file to load the certficate from
2094+ * @param fmt the input format of the certificate
2095+ *
2096+ * @return a pointer to an X.509 certificate on success, NULL on error
2097+ */
2098+X509 *cert_load_x509_certificate(const char *const file,
2099+ enum encoding_format fmt)
2100+{
2101+ FILE *fp = NULL;
2102+ X509 *cert = NULL;
2103+
2104+ if (!file) {
2105+ HIP_ERROR("Cannot read certificate from NULL-filename.\n");
2106+ return NULL;
2107+ }
2108+
2109+ fp = fopen(file, "rb");
2110+ if (!fp) {
2111+ HIP_ERROR("Could not open file for reading: %s\n", file);
2112+ return NULL;
2113+ }
2114+
2115+ switch (fmt) {
2116+ case ENCODING_FORMAT_PEM:
2117+ cert = PEM_read_X509(fp, NULL, NULL, NULL);
2118+ break;
2119+ case ENCODING_FORMAT_DER:
2120+ cert = d2i_X509_fp(fp, NULL);
2121+ break;
2122+ default:
2123+ HIP_ERROR("Invalid encoding format %i \n", fmt);
2124+ }
2125+
2126+ if (!cert) {
2127+ HIP_ERROR("Could not decode certificate from file.\n");
2128+ }
2129+
2130+ if (fclose(fp)) {
2131+ HIP_ERROR("Error closing file: %s\n", file);
2132+ X509_free(cert);
2133+ return NULL;
2134+ }
2135+
2136+ return cert;
2137+}
2138+
2139+/**
2140+ * Search for hip_cert parameter in @p msg and try to decode the data in
2141+ * the first certificate parameter of a X509 certificate.
2142+ *
2143+ * @param msg the message to extract the certificate from
2144+ *
2145+ * @return the first X509 certificate found in the message on success,
2146+ * NULL on error and if no certificates were found
2147+ */
2148+X509 *cert_get_X509_from_msg(const struct hip_common *const msg)
2149+{
2150+ const struct hip_cert *param_cert = NULL;
2151+
2152+ if (!(param_cert = hip_get_param(msg, HIP_PARAM_CERT))) {
2153+ HIP_ERROR("Message contains no certificate.\n");
2154+ return NULL;
2155+ }
2156+
2157+ /* The contents of the certificate begin after the header of the
2158+ * hip_cert parameter. */
2159+ return cert_DER_to_X509((const unsigned char *) (param_cert + 1),
2160+ ntohs(param_cert->length) -
2161+ sizeof(struct hip_cert) +
2162+ sizeof(struct hip_tlv_common));
2163+}
2164+
2165+/**
2166+ * Compare a given public key @p pkey with the public key
2167+ * contained in @p cert.
2168+ *
2169+ * @param cert the X509 certificate
2170+ * @param pkey the public key to match
2171+ *
2172+ * @return 1 if match, 0 otherwise
2173+ */
2174+int cert_match_public_key(X509 *cert, const EVP_PKEY *pkey)
2175+{
2176+ int ret = 0;
2177+ EVP_PKEY *pkey2 = NULL;
2178+
2179+ if (!cert || !pkey) {
2180+ return 0;
2181+ }
2182+
2183+ pkey2 = X509_get_pubkey(cert);
2184+
2185+ if (pkey2) {
2186+ ret = (EVP_PKEY_cmp(pkey2, pkey) == 1);
2187+ EVP_PKEY_free(pkey2);
2188+ }
2189+
2190+ return ret;
2191+}
2192+
2193+/**
2194+ * Build and verify a certificate chain.
2195+ *
2196+ * @param leaf_cert the certificate to verify
2197+ * @param trusted_lookup_dir certificates in this directory are used as
2198+ * root certificates
2199+ * @param trusted_chain a certificate stack that can contain additional
2200+ * trusted certificates
2201+ * @param untrusted_chain a chain of untrusted certificates that can be
2202+ * used to build a complete certificate chain
2203+ *
2204+ * @return 0 if a certificate chain could be built and
2205+ * verified, a non-zero error code otherwise
2206+ */
2207+int cert_verify_chain(X509 *leaf_cert,
2208+ const char *trusted_lookup_dir,
2209+ STACK_OF(X509) *trusted_chain,
2210+ STACK_OF(X509) *untrusted_chain)
2211+{
2212+ int err = 0;
2213+ X509_LOOKUP *lookup = NULL;
2214+ X509_STORE *verify_ctx_store = NULL;
2215+ X509_STORE_CTX *verify_ctx = NULL;
2216+
2217+ if (!leaf_cert) {
2218+ HIP_ERROR("Cannot verify NULL-certificate.\n");
2219+ return -1;
2220+ }
2221+
2222+ if (!trusted_lookup_dir && !trusted_chain) {
2223+ HIP_ERROR("Need trusted dir and trusted chain.\n");
2224+ return -1;
2225+ }
2226+
2227+ /* Build the verify context */
2228+ if (!(verify_ctx_store = X509_STORE_new())) {
2229+ HIP_ERROR("Failed to init certificate store.\n");
2230+ return -1;
2231+ }
2232+ if (!(lookup = X509_STORE_add_lookup(verify_ctx_store, X509_LOOKUP_hash_dir()))) {
2233+ HIP_ERROR("Failed to init lookup directory.\n");
2234+ return -1;
2235+ }
2236+ if (trusted_lookup_dir) {
2237+ if (!X509_LOOKUP_add_dir(lookup, trusted_lookup_dir,
2238+ X509_FILETYPE_PEM)) {
2239+ HIP_ERROR("Failed to add directory %s to trusted lookup resources.\n",
2240+ trusted_lookup_dir);
2241+ return -1;
2242+ }
2243+ } else {
2244+ X509_LOOKUP_add_dir(lookup, NULL, X509_FILETYPE_DEFAULT);
2245+ }
2246+
2247+ if (!(verify_ctx = X509_STORE_CTX_new())) {
2248+ HIP_ERROR("Failed to allocate new verify context.\n");
2249+ return -ENOMEM;
2250+ }
2251+ if (!X509_STORE_CTX_init(verify_ctx, verify_ctx_store, leaf_cert,
2252+ untrusted_chain)) {
2253+ HIP_ERROR("Failed to setup verify context.\n");
2254+ X509_STORE_CTX_free(verify_ctx);
2255+ return -1;
2256+ }
2257+ if (trusted_chain) {
2258+ X509_STORE_CTX_trusted_stack(verify_ctx, trusted_chain);
2259+ }
2260+
2261+ /* Finally do the verification and output some info on error */
2262+ OpenSSL_add_all_algorithms();
2263+ err = X509_verify_cert(verify_ctx);
2264+
2265+ if (err != 1) {
2266+ err = X509_STORE_CTX_get_error(verify_ctx);
2267+ HIP_DEBUG("X509 verify cert error: %d \n", err);
2268+ HIP_DEBUG("at depth: %d \n", X509_STORE_CTX_get_error_depth(verify_ctx));
2269+ HIP_DEBUG("reason: %s\n", X509_verify_cert_error_string(err));
2270+ HIP_DEBUG("certificate:\n");
2271+ X509_print_fp(stderr, X509_STORE_CTX_get_current_cert(verify_ctx));
2272+ } else {
2273+ err = 0;
2274+ }
2275+
2276+ X509_STORE_free(verify_ctx_store);
2277+ X509_STORE_CTX_free(verify_ctx);
2278+ return err;
2279+}
2280
2281=== added file 'lib/core/cert.h'
2282--- lib/core/cert.h 1970-01-01 00:00:00 +0000
2283+++ lib/core/cert.h 2012-03-16 04:27:22 +0000
2284@@ -0,0 +1,51 @@
2285+/*
2286+ * Copyright (c) 2010-2011 Aalto University and RWTH Aachen University.
2287+ *
2288+ * Permission is hereby granted, free of charge, to any person
2289+ * obtaining a copy of this software and associated documentation
2290+ * files (the "Software"), to deal in the Software without
2291+ * restriction, including without limitation the rights to use,
2292+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
2293+ * copies of the Software, and to permit persons to whom the
2294+ * Software is furnished to do so, subject to the following
2295+ * conditions:
2296+ *
2297+ * The above copyright notice and this permission notice shall be
2298+ * included in all copies or substantial portions of the Software.
2299+ *
2300+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
2301+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
2302+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
2303+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
2304+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
2305+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
2306+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
2307+ * OTHER DEALINGS IN THE SOFTWARE.
2308+ */
2309+
2310+#ifndef HIPL_LIB_CORE_CERT_H
2311+#define HIPL_LIB_CORE_CERT_H
2312+
2313+#include <openssl/x509.h>
2314+
2315+#include "lib/core/protodefs.h"
2316+
2317+enum encoding_format {
2318+ ENCODING_FORMAT_PEM,
2319+ ENCODING_FORMAT_DER
2320+};
2321+
2322+int cert_X509_to_DER(X509 *const cert, unsigned char **buf);
2323+X509 *cert_DER_to_X509(const unsigned char *const buf, const int len);
2324+
2325+X509 *cert_load_x509_certificate(const char *const file,
2326+ enum encoding_format fmt);
2327+X509 *cert_get_X509_from_msg(const struct hip_common *const msg);
2328+
2329+int cert_match_public_key(X509 *cert, const EVP_PKEY *pkey);
2330+int cert_verify_chain(X509 *leaf_cert,
2331+ const char *trusted_lookup_dir,
2332+ STACK_OF(X509) *trusted_chain,
2333+ STACK_OF(X509) *untrusted_chain);
2334+
2335+#endif /* HIPL_LIB_CORE_CERT_H */
2336
2337=== modified file 'lib/core/certtools.c'
2338--- lib/core/certtools.c 2012-01-14 15:29:47 +0000
2339+++ lib/core/certtools.c 2012-03-16 04:27:22 +0000
2340@@ -685,10 +685,10 @@
2341 *
2342 * @note The certificate is given in DER encoding
2343 */
2344-int hip_cert_x509v3_request_certificate(struct in6_addr *subject,
2345- unsigned char *certificate)
2346+uint32_t hip_cert_x509v3_request_certificate(struct in6_addr *subject,
2347+ unsigned char *certificate)
2348 {
2349- int err = 0;
2350+ uint32_t err = 0;
2351 struct hip_common *msg;
2352 const struct hip_cert_x509_resp *p;
2353
2354@@ -710,8 +710,8 @@
2355 /* get the struct from the message sent back by the daemon */
2356 HIP_IFEL(!(p = hip_get_param(msg, HIP_PARAM_CERT_X509_RESP)), -1,
2357 "No name x509 struct found\n");
2358- memcpy(certificate, p->der, p->der_len);
2359- err = p->der_len;
2360+ memcpy(certificate, p->der, ntohl(p->der_len));
2361+ err = ntohl(p->der_len);
2362
2363 out_err:
2364 free(msg);
2365@@ -729,7 +729,7 @@
2366 *
2367 * @note give the certificate in PEM encoding
2368 */
2369-int hip_cert_x509v3_request_verification(unsigned char *certificate, int len)
2370+int hip_cert_x509v3_request_verification(unsigned char *certificate, uint32_t len)
2371 {
2372 int err = 0;
2373 struct hip_common *msg;
2374@@ -797,18 +797,18 @@
2375 }
2376
2377 /**
2378- * Load a configuration file from HIP_CERT_CONF_PATH.
2379+ * Load the indicated configuration file.
2380 *
2381 * @return CONF pointer if OK, NULL on error
2382 */
2383 CONF *hip_open_conf(const char *filename)
2384 {
2385- long err;
2386 CONF *conf;
2387
2388 conf = NCONF_new(NCONF_default());
2389- if (!NCONF_load(conf, filename, &err)) {
2390+ if (!NCONF_load(conf, filename, NULL)) {
2391 HIP_ERROR("Error opening the configuration file");
2392+ NCONF_free(conf);
2393 return NULL;
2394 }
2395 return conf;
2396
2397=== modified file 'lib/core/certtools.h'
2398--- lib/core/certtools.h 2012-01-14 15:29:47 +0000
2399+++ lib/core/certtools.h 2012-03-16 04:27:22 +0000
2400@@ -67,8 +67,8 @@
2401 int hip_cert_spki_send_to_verification(struct hip_cert_spki_info *);
2402
2403 /* x509v3 cert related functions */
2404-int hip_cert_x509v3_request_certificate(struct in6_addr *, unsigned char *);
2405-int hip_cert_x509v3_request_verification(unsigned char *, int);
2406+uint32_t hip_cert_x509v3_request_certificate(struct in6_addr *, unsigned char *);
2407+int hip_cert_x509v3_request_verification(unsigned char *, uint32_t);
2408
2409 /** utility functions */
2410 STACK_OF(CONF_VALUE) *hip_read_conf_section(const char *section_name,
2411
2412=== modified file 'lib/core/conf.c'
2413--- lib/core/conf.c 2012-01-13 16:25:15 +0000
2414+++ lib/core/conf.c 2012-03-16 04:27:22 +0000
2415@@ -1,5 +1,5 @@
2416 /*
2417- * Copyright (c) 2010-2011 Aalto University and RWTH Aachen University.
2418+ * Copyright (c) 2010-2012 Aalto University and RWTH Aachen University.
2419 *
2420 * Permission is hereby granted, free of charge, to any person
2421 * obtaining a copy of this software and associated documentation
2422@@ -59,10 +59,12 @@
2423 #include <sys/ioctl.h>
2424 #include <sys/socket.h>
2425 #include <sys/types.h>
2426+#include <openssl/pem.h>
2427
2428-#include "common.h"
2429 #include "config.h"
2430 #include "builder.h"
2431+#include "cert.h"
2432+#include "common.h"
2433 #include "crypto.h"
2434 #include "debug.h"
2435 #include "hostid.h"
2436@@ -126,7 +128,8 @@
2437 /* unused, was ACTION_HANDOVER 39 */
2438 #define ACTION_MANUAL_UPDATE 40
2439 #define ACTION_BROADCAST 41
2440-#define ACTION_MAX 42 /* exclusive */
2441+#define ACTION_ACQUIRE 42
2442+#define ACTION_MAX 43 /* exclusive */
2443
2444 /**
2445 * TYPE_ constant list, as an index for each action_handler function.
2446@@ -176,7 +179,8 @@
2447 /* unused, was TYPE_HANDOVER 42 */
2448 #define TYPE_MANUAL_UPDATE 43
2449 #define TYPE_BROADCAST 44
2450-#define TYPE_MAX 45 /* exclusive */
2451+#define TYPE_CERTIFICATE 45
2452+#define TYPE_MAX 46 /* exclusive */
2453
2454 /* #define TYPE_RELAY 22 */
2455
2456@@ -230,6 +234,7 @@
2457 "shotgun on|off\n"
2458 "id-to-addr hit|lsi\n"
2459 "broadcast on|off\n"
2460+ "acquire certificate <hit> [valid-till_timestamp]\n"
2461 ;
2462
2463 /**
2464@@ -648,6 +653,8 @@
2465 }
2466 } else if (!strcmp("broadcast", argv[2])) {
2467 ret = ACTION_BROADCAST;
2468+ } else if (!strcmp("acquire", argv[2])) {
2469+ ret = ACTION_ACQUIRE;
2470 }
2471
2472 return ret;
2473@@ -698,6 +705,7 @@
2474 case ACTION_TRANSORDER:
2475 case ACTION_NAT_LOCAL_PORT:
2476 case ACTION_NAT_PEER_PORT:
2477+ case ACTION_ACQUIRE:
2478 count = 2;
2479 break;
2480 default:
2481@@ -750,6 +758,8 @@
2482 } else {
2483 ret = TYPE_NAT;
2484 }
2485+ } else if (!strcmp("certificate", text)) {
2486+ ret = TYPE_CERTIFICATE;
2487 } else if (strcmp("locator", argv[2]) == 0) {
2488 ret = TYPE_LOCATOR;
2489 } else if (!strcmp("debug", text)) {
2490@@ -819,6 +829,7 @@
2491 case ACTION_HIT_TO_IP:
2492 case ACTION_HIT_TO_IP_SET:
2493 case ACTION_BROADCAST:
2494+ case ACTION_ACQUIRE:
2495 type_arg = 3;
2496 break;
2497 case ACTION_MANUAL_UPDATE:
2498@@ -2424,6 +2435,180 @@
2499 }
2500
2501 /**
2502+ * Utility function which compactly checks whether a string represents
2503+ * a positive natural number, since scanf() is too lenient.
2504+ *
2505+ * @param string NULL-terminated string to be checked
2506+ *
2507+ * @return 1 if the only characters in the string are digits,
2508+ * optionally with one leading '+' sign; 0 otherwise
2509+ */
2510+static int is_pos_natural_number(const char *string)
2511+{
2512+ if (string) {
2513+ size_t len;
2514+
2515+ // allow one leading '+'
2516+ if (string[0] == '+') {
2517+ string++;
2518+ }
2519+
2520+ if ((len = strlen(string)) > 0) {
2521+ for (size_t i = 0; i < len; i++) {
2522+ if (string[i] < '0' || string[i] > '9') {
2523+ return 0;
2524+ }
2525+ }
2526+ return 1;
2527+ }
2528+ }
2529+ return 0;
2530+}
2531+
2532+/**
2533+ * Process parameters of "hipconf acquire certificate", converting and
2534+ * entering them into a HIP message. Only to be used internally by
2535+ * conf_handle_certificate().
2536+ *
2537+ * @param msg HIP message to be set up with the parameters
2538+ * @param opt array of parameter strings
2539+ * @param optc number of parameters (one or two are accepted)
2540+ *
2541+ * @return 0 upon success, or -1 in case of failure
2542+ */
2543+static int conf_handle_certificate_parms(struct hip_common *msg,
2544+ const char *opt[],
2545+ int optc)
2546+{
2547+ hip_hit_t subject_hit;
2548+ uint32_t valid_until_h = 0, valid_until_n = 0;
2549+ int scanf_res = 0;
2550+
2551+ /* turn the HIT string into its binary representation */
2552+ if (optc < 1 || inet_pton(AF_INET6, opt[0], &subject_hit) != 1) {
2553+ return -1;
2554+ }
2555+
2556+ /* same for the optional numeric parameter after the HIT */
2557+ if (optc == 2 && is_pos_natural_number(opt[1])) {
2558+ /* Need to use sscanf() here: strtol() won't do since we want the
2559+ * result of the conversion to fit into an uint32_t, whereas strtol()
2560+ * and relatives would write to a variable of platform-dependent
2561+ * size. */
2562+ scanf_res = sscanf(opt[1], "%" SCNu32, &valid_until_h);
2563+ }
2564+
2565+ /* optc == 1 as well as optc == 2 is acceptable - the latter is
2566+ * implied if scanf_res is 1. */
2567+ if (optc != 1 && scanf_res != 1) {
2568+ return -1;
2569+ }
2570+
2571+ HIP_DEBUG_HIT("Requesting certificate for subject", &subject_hit);
2572+
2573+ if (hip_build_user_hdr(msg, HIP_MSG_CERT_X509V3_SIGN, 0)) {
2574+ HIP_ERROR("Failed to build user message header.\n");
2575+ return -1;
2576+ }
2577+
2578+ /* The optional parameter following the HIT is meant to indicate the
2579+ * point in time when validity of the issued certificate ends; expressed
2580+ * in "number of seconds since the epoch"; we use a uint32_t for this, so
2581+ * we're creating a year-2106-problem here (be scared). */
2582+ if (scanf_res == 1) {
2583+ valid_until_n = htonl(valid_until_h);
2584+ if (hip_build_param_contents(msg, &valid_until_n,
2585+ HIP_PARAM_UINT, sizeof(uint32_t))) {
2586+ HIP_ERROR("Failed to build validity parameter.\n");
2587+ return -1;
2588+ }
2589+ }
2590+
2591+ if (hip_build_param_cert_x509_req(msg, &subject_hit)) {
2592+ HIP_ERROR("Failed to build cert_x509_req parameter.\n");
2593+ return -1;
2594+ }
2595+
2596+ return 0;
2597+}
2598+
2599+/**
2600+ * Handles the hipconf command "acquire certificate".
2601+ *
2602+ * @param msg a pointer to the buffer where the message for hipd will
2603+ * be written.
2604+ * @param action the numeric action identifier for the action to be performed
2605+ * (error if != ACTION_ACQUIRE).
2606+ * @param opt an array of pointers to the command line arguments after
2607+ * the action and type.
2608+ * @param optc the number of elements in the array (one or two).
2609+ * @param send_only 0 (send message to hipd and wait for result) is expected.
2610+ *
2611+ * @return 0 upon success, or -1 in case of failure.
2612+ */
2613+static int conf_handle_certificate(struct hip_common *msg,
2614+ int action,
2615+ const char *opt[],
2616+ int optc,
2617+ int send_only)
2618+{
2619+ X509 *cert = NULL;
2620+ const struct hip_cert_x509_resp *response_param = NULL;
2621+
2622+ /* It does not make any sense to send a certificate request and then
2623+ * ignore the returned certificate. (I.e., using "acquire certificate"
2624+ * as part of HIPL config files is not a good idea.) */
2625+ if (send_only != 0) {
2626+ return -1;
2627+ }
2628+
2629+ /* only react to "hipconf daemon x certificate" if x == "acquire" -
2630+ * then process parameters and set up message accordingly */
2631+ if (action != ACTION_ACQUIRE ||
2632+ conf_handle_certificate_parms(msg, opt, optc)) {
2633+ HIP_ERROR("Invalid arguments.\n");
2634+ return -1;
2635+ }
2636+
2637+ /* Send the message to the daemon. "msg" gets overwritten with the
2638+ * response. */
2639+ if (hip_send_recv_daemon_info(msg, 0, 0)) {
2640+ HIP_ERROR("Error sending message to hip daemon.\n");
2641+ return -1;
2642+ }
2643+
2644+ /* Check for correct message type of the response, and find the one
2645+ * parameter in it that's relevant. */
2646+ if ((hip_get_msg_type(msg) != HIP_MSG_CERT_X509V3_SIGN) ||
2647+ (!(response_param = hip_get_param(msg, HIP_PARAM_CERT_X509_RESP)))) {
2648+ HIP_ERROR("Received invalid response message for certificate request.\n");
2649+ return -1;
2650+ }
2651+
2652+ /* Try to convert DER certificate into the internal OpenSSL
2653+ * structured X509 format, as a simple consistency check */
2654+ const uint32_t der_len_h = ntohl(response_param->der_len);
2655+ if (!(cert = cert_DER_to_X509(response_param->der, der_len_h))) {
2656+ HIP_ERROR("Could not get X509 certificate from DER encoding\n.");
2657+ return -1;
2658+ } else {
2659+ X509_free(cert);
2660+ }
2661+
2662+ /* dump the DER encoded certificate to stdout */
2663+ if (fwrite(response_param->der, der_len_h, 1, stdout) != 1) {
2664+ HIP_ERROR("Couldn't output certificate.\n");
2665+ return -1;
2666+ }
2667+
2668+ /* Clear the msg (and in particular its message type field)
2669+ * to prevent hip_do_hipconf() from sending it again. */
2670+ hip_msg_init(msg);
2671+
2672+ return 0;
2673+}
2674+
2675+/**
2676 * Function pointer array containing pointers to handler functions.
2677 * Add a handler function for your new action in the action_handler[] array.
2678 * If you added a handler function here, do not forget to define that function
2679@@ -2492,6 +2677,7 @@
2680 NULL, /* 42: unused, was TYPE_HANDOVER */
2681 conf_handle_manual_update, /* 43: TYPE_MANUAL_UPDATE */
2682 conf_handle_broadcast, /* 44: TYPE_BROADCAST */
2683+ conf_handle_certificate, /* 45: TYPE_CERTIFICATE */
2684 NULL /* TYPE_MAX, the end. */
2685 };
2686
2687
2688=== modified file 'lib/core/protodefs.h'
2689--- lib/core/protodefs.h 2012-03-08 18:50:52 +0000
2690+++ lib/core/protodefs.h 2012-03-16 04:27:22 +0000
2691@@ -375,6 +375,21 @@
2692 #define HIP_VER_RES 0x01 /* Version 1, reserved 0 */
2693 #define HIP_USER_VER_RES 0xF0 /* Internal messages */
2694
2695+
2696+/* HIP certificate types
2697+ * (according to RFC 6253) */
2698+enum hip_cert_type {
2699+ HIP_CERT_RESERVED,
2700+ HIP_CERT_X509V3,
2701+ HIP_CERT_SPKI,
2702+ HIP_CERT_X509V3_HASH_URL,
2703+ HIP_CERT_SPKI_HASH_URL,
2704+ HIP_CERT_X509V3_LDAP_URL,
2705+ HIP_CERT_SPKI_LDAP_URL,
2706+ HIP_CERT_X509V3_DN,
2707+ HIP_CERT_SPKI_DN,
2708+};
2709+
2710 /**
2711 * @defgroup hip_ha_controls HIP host association controls
2712 *
2713@@ -987,16 +1002,16 @@
2714 } __attribute__((packed));
2715
2716 struct hip_cert_x509_req {
2717- hip_tlv type;
2718- hip_tlv_len length;
2719- struct in6_addr addr;
2720+ hip_tlv type;
2721+ hip_tlv_len length;
2722+ hip_hit_t addr;
2723 } __attribute__((packed));
2724
2725 struct hip_cert_x509_resp {
2726 hip_tlv type;
2727 hip_tlv_len length;
2728 unsigned char der[1024];
2729- int der_len;
2730+ uint32_t der_len;
2731 } __attribute__((packed));
2732
2733 struct hip_transformation_order {
2734
2735=== added directory 'modules/cert'
2736=== added directory 'modules/cert/hipd'
2737=== renamed file 'hipd/pisa.c' => 'modules/cert/hipd/cert.c'
2738--- hipd/pisa.c 2011-10-25 21:14:16 +0000
2739+++ modules/cert/hipd/cert.c 2012-03-16 04:27:22 +0000
2740@@ -1,5 +1,5 @@
2741 /*
2742- * Copyright (c) 2010 Aalto University and RWTH Aachen University.
2743+ * Copyright (c) 2010-2012 Aalto University and RWTH Aachen University.
2744 *
2745 * Permission is hereby granted, free of charge, to any person
2746 * obtaining a copy of this software and associated documentation
2747@@ -25,59 +25,179 @@
2748
2749 /**
2750 * @file
2751- * This file contains functions that are specific to PISA. They deal with the
2752- * certificate loading.
2753- *
2754- * @brief Functions for certificate loading
2755+ * @brief functions to add certificates to R2 and U2 messages
2756 */
2757
2758+#include <stdbool.h>
2759 #include <stdio.h>
2760 #include <stdlib.h>
2761 #include <string.h>
2762
2763-#include "config.h"
2764+#include "hipd/hipd.h"
2765+#include "hipd/pkt_handling.h"
2766+#include "lib/core/builder.h"
2767+#include "lib/core/cert.h"
2768 #include "lib/core/debug.h"
2769-#include "hipd.h"
2770-#include "pisa.h"
2771-
2772-#define CERT_MAX_SIZE 1024
2773-
2774-static char *midauth_cert = NULL;
2775-
2776-/**
2777- * Load a certificate from the file HIPL_SYSCONFDIR/cert and store it in memory
2778- *
2779- * @return 0 on success
2780- */
2781-static int pisa_load_certificate(void)
2782-{
2783- FILE *f = NULL;
2784-
2785- free(midauth_cert);
2786- midauth_cert = calloc(1, CERT_MAX_SIZE);
2787-
2788- if (!(f = fopen(HIPL_SYSCONFDIR "/cert", "r"))) {
2789- HIP_ERROR("Could not open certificate file.\n");
2790- return -1;
2791- }
2792-
2793- if (fread(midauth_cert, CERT_MAX_SIZE - 1, 1, f) == 0) {
2794- perror("fread returned 0");
2795- }
2796- fclose(f);
2797- return 0;
2798-}
2799-
2800-/**
2801- * Load a certificate from disk and return a pointer to the global
2802- * variable containing it.
2803- *
2804- * @see pisa_load_certificate*
2805- *
2806- * @return pointer to midauth_cert
2807- */
2808-char *hip_pisa_get_certificate(void)
2809-{
2810- pisa_load_certificate();
2811- return midauth_cert;
2812+#include "lib/core/ife.h"
2813+#include "lib/core/protodefs.h"
2814+#include "modules/midauth/hipd/midauth.h"
2815+#include "modules/update/hipd/update.h"
2816+#include "cert.h"
2817+
2818+static X509 *host_cert = NULL;
2819+
2820+/**
2821+ * Handler that adds the certificate to an R2 message.
2822+ *
2823+ * @param msg the message where to add the certificate
2824+ * @param certificate the certificate to add to the message
2825+ *
2826+ * @return 0 on success, negative on error
2827+ */
2828+static int hip_add_certificate(struct hip_common *msg, X509 *certificate)
2829+{
2830+ unsigned char *buf;
2831+ int len = 0;
2832+
2833+ /* Sanity checks */
2834+ if (!msg) {
2835+ HIP_ERROR("Message is NULL\n");
2836+ return -1;
2837+ }
2838+ if (!certificate) {
2839+ HIP_ERROR("Certificate is NULL\n");
2840+ return -1;
2841+ }
2842+
2843+ /* Encode the certificate to DER and build the certificate parameter. */
2844+ if ((len = cert_X509_to_DER(certificate, &buf)) < 0) {
2845+ HIP_ERROR("Encoding error\n");
2846+ return -1;
2847+ }
2848+ if (hip_build_param_cert(msg, 0, 1, 1, HIP_CERT_X509V3, buf, len)) {
2849+ HIP_ERROR("Building of certificate parameter failed.\n");
2850+ return -1;
2851+ }
2852+
2853+ return 0;
2854+}
2855+
2856+/**
2857+ * Handler that adds the certificate to an R2 message.
2858+ *
2859+ * @param packet_type unused
2860+ * @param ha_state unused
2861+ * @param ctx the packet context
2862+ *
2863+ * @return 0 on success, negative on failure
2864+ *
2865+ * @note: The certificate is regarded non-critical thus the function does
2866+ * not fail even if no certificate is available.
2867+ */
2868+static int hip_add_certificate_r2(UNUSED const uint8_t packet_type,
2869+ UNUSED const uint32_t ha_state,
2870+ struct hip_packet_context *ctx)
2871+{
2872+ if (hip_add_certificate(ctx->output_msg, host_cert)) {
2873+ HIP_DEBUG("Sending R2 without certificate.\n");
2874+ }
2875+ return 0;
2876+}
2877+
2878+/**
2879+ * Handler that adds the certificate to the second or third update message.
2880+ * A certificate should only be included if the previous
2881+ * update packet contained a middlebox challenge.
2882+ *
2883+ * @param packet_type unused
2884+ * @param ha_state unused
2885+ * @param ctx the packet context
2886+ *
2887+ * @return 0 on success, negative on failure
2888+ *
2889+ * @note: The certificate is regarded non-critical thus the function does
2890+ * not fail even if no certificate is available.
2891+ */
2892+static int hip_add_certificate_update(UNUSED const uint8_t packet_type,
2893+ UNUSED const uint32_t ha_state,
2894+ struct hip_packet_context *ctx)
2895+{
2896+ if (!host_cert) {
2897+ HIP_DEBUG("No certificate available.\n");
2898+ return 0;
2899+ }
2900+
2901+ /* Include a certificate in the U2 or U3, if available. */
2902+ if (hip_classify_update_type(ctx->input_msg) == FIRST_UPDATE_PACKET ||
2903+ hip_classify_update_type(ctx->input_msg) == SECOND_UPDATE_PACKET) {
2904+ if (hip_get_param_contents(ctx->input_msg, HIP_PARAM_CHALLENGE_REQUEST)) {
2905+ if (hip_add_certificate(ctx->output_msg, host_cert)) {
2906+ HIP_ERROR("Failed to add certificate to update message.\n");
2907+ return -1;
2908+ }
2909+ } else {
2910+ HIP_DEBUG("No middlebox found in previous update, omitting certificate.\n");
2911+ }
2912+ }
2913+
2914+ return 0;
2915+}
2916+
2917+/**
2918+ * Initialize certificate functionality in the hipd.
2919+ * Registers handlers to add the trust point certificate in R2 and U2 messages.
2920+ *
2921+ * @return 0 on success, negative on error
2922+ */
2923+int hip_cert_init(void)
2924+{
2925+ if (hip_register_handle_function(HIP_I2, HIP_STATE_NONE,
2926+ &hip_add_certificate_r2, 40500)) {
2927+ HIP_ERROR("Error on registering certificate handle function.\n");
2928+ return -1;
2929+ }
2930+ if (hip_register_handle_function(HIP_I2, HIP_STATE_UNASSOCIATED,
2931+ &hip_add_certificate_r2, 40500)) {
2932+ HIP_ERROR("Error on registering certificate handle function.\n");
2933+ return -1;
2934+ }
2935+ if (hip_register_handle_function(HIP_I2, HIP_STATE_I1_SENT,
2936+ &hip_add_certificate_r2, 40500)) {
2937+ HIP_ERROR("Error on registering certificate handle function.\n");
2938+ return -1;
2939+ }
2940+ if (hip_register_handle_function(HIP_I2, HIP_STATE_I2_SENT,
2941+ &hip_add_certificate_r2, 40500)) {
2942+ HIP_ERROR("Error on registering certificate handle function.\n");
2943+ return -1;
2944+ }
2945+ if (hip_register_handle_function(HIP_I2, HIP_STATE_R2_SENT,
2946+ &hip_add_certificate_r2, 40500)) {
2947+ HIP_ERROR("Error on registering certificate handle function.\n");
2948+ return -1;
2949+ }
2950+ if (hip_register_handle_function(HIP_I2, HIP_STATE_ESTABLISHED,
2951+ &hip_add_certificate_r2, 40500)) {
2952+ HIP_ERROR("Error on registering certificate handle function.\n");
2953+ return -1;
2954+ }
2955+ if (hip_register_handle_function(HIP_UPDATE, HIP_STATE_ESTABLISHED,
2956+ &hip_add_certificate_update, 20752)) {
2957+ HIP_ERROR("Error on registering certificate handle function.\n");
2958+ return -1;
2959+ }
2960+ if (hip_register_handle_function(HIP_UPDATE, HIP_STATE_R2_SENT,
2961+ &hip_add_certificate_update, 20752)) {
2962+ HIP_ERROR("Error on registering certificate handle function.\n");
2963+ return -1;
2964+ }
2965+
2966+ if (!(host_cert = cert_load_x509_certificate(HIPL_SYSCONFDIR "/host-cert.der",
2967+ ENCODING_FORMAT_DER))) {
2968+ HIP_DEBUG("Could not load certificate.\n");
2969+ }
2970+
2971+ HIP_DEBUG("certificates initialized\n");
2972+
2973+ return 0;
2974 }
2975
2976=== renamed file 'hipd/pisa.h' => 'modules/cert/hipd/cert.h'
2977--- hipd/pisa.h 2011-11-25 17:56:24 +0000
2978+++ modules/cert/hipd/cert.h 2012-03-16 04:27:22 +0000
2979@@ -1,5 +1,5 @@
2980 /*
2981- * Copyright (c) 2010 Aalto University and RWTH Aachen University.
2982+ * Copyright (c) 2010-2011 Aalto University and RWTH Aachen University.
2983 *
2984 * Permission is hereby granted, free of charge, to any person
2985 * obtaining a copy of this software and associated documentation
2986@@ -23,22 +23,9 @@
2987 * OTHER DEALINGS IN THE SOFTWARE.
2988 */
2989
2990-/**
2991- * @file
2992- * This file contains function declarations specific to PISA. They deal with the
2993- * certificate loading.
2994- *
2995- * @brief Functions declarations for certificate loading
2996- */
2997-
2998-#ifndef HIPL_HIPD_PISA_H
2999-#define HIPL_HIPD_PISA_H
3000-
3001-/**
3002- * Get the certificate text that will be appended to R2 and U2 packets
3003- *
3004- * @return pointer to the certificate text
3005- */
3006-char *hip_pisa_get_certificate(void);
3007-
3008-#endif /* HIPL_HIPD_PISA_H */
3009+#ifndef HIPL_MODULES_CERT_HIPD_CERT_H
3010+#define HIPL_MODULES_CERT_HIPD_CERT_H
3011+
3012+int hip_cert_init(void);
3013+
3014+#endif /* HIPL_MODULES_CERT_HIPD_CERT_H */
3015
3016=== added file 'modules/cert/module_info.xml'
3017--- modules/cert/module_info.xml 1970-01-01 00:00:00 +0000
3018+++ modules/cert/module_info.xml 2012-03-16 04:27:22 +0000
3019@@ -0,0 +1,23 @@
3020+<?xml version="1.0" encoding="UTF-8"?>
3021+
3022+<!-- Mandatory: name, version -->
3023+<module
3024+ name="cert"
3025+ version="0.0.1"
3026+ description="certificate exchange for the HIP daemon."
3027+ developer=""
3028+ bugaddress="hipl-users@freelists.org"
3029+ webpage="http://infrahip.hiit.fi/">
3030+
3031+ <requires>
3032+ <module name="update" minversion="0.0.1" />
3033+ <module name="midauth" minversion="0.0.1" />
3034+ </requires>
3035+
3036+ <!-- Mandatory: name, header_file, init_function -->
3037+ <application
3038+ name="hipd"
3039+ header_file="modules/cert/hipd/cert.h"
3040+ init_function="hip_cert_init" />
3041+</module>
3042+
3043
3044=== modified file 'modules/update/hipd/update.c' (properties changed: -x to +x)
3045=== modified file 'test/certteststub.c'
3046--- test/certteststub.c 2012-01-14 15:29:47 +0000
3047+++ test/certteststub.c 2012-03-16 04:27:22 +0000
3048@@ -50,7 +50,8 @@
3049
3050 int main(int argc, char *argv[])
3051 {
3052- int err = 0, i = 0, len;
3053+ int err = 0, i = 0;
3054+ uint32_t len;
3055 struct hip_cert_spki_info *cert = NULL;
3056 struct hip_cert_spki_info *to_verification = NULL;
3057 time_t not_before = 0, not_after = 0;
3058
3059=== modified file 'test/check_lib_core.c'
3060--- test/check_lib_core.c 2012-03-13 13:33:06 +0000
3061+++ test/check_lib_core.c 2012-03-16 04:27:22 +0000
3062@@ -36,7 +36,9 @@
3063 int main(void)
3064 {
3065 int number_failed;
3066+
3067 SRunner *sr = srunner_create(NULL);
3068+ srunner_add_suite(sr, lib_core_cert());
3069 srunner_add_suite(sr, lib_core_hit());
3070 srunner_add_suite(sr, lib_core_hostid());
3071 srunner_add_suite(sr, lib_core_solve());
3072
3073=== added file 'test/lib/core/cert.c'
3074--- test/lib/core/cert.c 1970-01-01 00:00:00 +0000
3075+++ test/lib/core/cert.c 2012-03-16 04:27:22 +0000
3076@@ -0,0 +1,198 @@
3077+/*
3078+ * Copyright (c) 2011 Aalto University and RWTH Aachen University.
3079+ *
3080+ * Permission is hereby granted, free of charge, to any person
3081+ * obtaining a copy of this software and associated documentation
3082+ * files (the "Software"), to deal in the Software without
3083+ * restriction, including without limitation the rights to use,
3084+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
3085+ * copies of the Software, and to permit persons to whom the
3086+ * Software is furnished to do so, subject to the following
3087+ * conditions:
3088+ *
3089+ * The above copyright notice and this permission notice shall be
3090+ * included in all copies or substantial portions of the Software.
3091+ *
3092+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
3093+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
3094+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
3095+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
3096+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
3097+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
3098+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
3099+ * OTHER DEALINGS IN THE SOFTWARE.
3100+ */
3101+
3102+#include <check.h>
3103+#include <stdlib.h>
3104+#include <string.h>
3105+#include <stdio.h>
3106+
3107+#include "lib/core/cert.h"
3108+#include "lib/core/crypto.h"
3109+#include "lib/core/ife.h"
3110+#include "lib/core/protodefs.h"
3111+#include "config.h"
3112+#include "test_suites.h"
3113+
3114+#define TEST_CERT HIPL_SOURCEDIR "/test/lib/core/test_cert.pem"
3115+#define TEST_KEY HIPL_SOURCEDIR "/test/lib/core/test_key.pem"
3116+
3117+START_TEST(test_cert_load_x509_certificate)
3118+{
3119+ X509 *cert = NULL;
3120+
3121+ HIP_DEBUG("Test loading of X509 certificates.\n");
3122+
3123+ fail_unless((cert = cert_load_x509_certificate(TEST_CERT,
3124+ ENCODING_FORMAT_PEM)) != NULL,
3125+ NULL);
3126+ X509_free(cert);
3127+ fail_unless((cert = cert_load_x509_certificate("non_existing_cert.pem",
3128+ ENCODING_FORMAT_PEM)) == NULL,
3129+ NULL);
3130+ X509_free(cert);
3131+ fail_unless((cert = cert_load_x509_certificate(NULL,
3132+ ENCODING_FORMAT_PEM)) == NULL,
3133+ NULL);
3134+ X509_free(cert);
3135+
3136+ HIP_DEBUG("Successfully passed tests for loading X509 certificates.\n");
3137+}
3138+END_TEST
3139+
3140+START_TEST(test_cert_DER_encoding)
3141+{
3142+ int len = 0;
3143+ X509 *cert = NULL;
3144+ X509 *cert_decoded = NULL;
3145+ unsigned char *buf = NULL;
3146+
3147+ HIP_DEBUG("Test DER en/decoding of X509 certificates.\n");
3148+
3149+ fail_unless((cert = cert_load_x509_certificate(TEST_CERT,
3150+ ENCODING_FORMAT_PEM)) != NULL,
3151+ NULL);
3152+ fail_unless((len = cert_X509_to_DER(cert, &buf)) > 0, NULL);
3153+ fail_unless((cert_decoded = cert_DER_to_X509(buf, len)) != NULL, NULL);
3154+ fail_unless(X509_cmp(cert, cert_decoded) == 0, NULL);
3155+ X509_free(cert_decoded);
3156+
3157+ fail_unless((len = cert_X509_to_DER(NULL, &buf)) < 0, NULL);
3158+ fail_unless((len = cert_X509_to_DER(cert, NULL)) < 0, NULL);
3159+ fail_unless((len = cert_X509_to_DER(NULL, NULL)) < 0, NULL);
3160+
3161+ fail_unless((cert_decoded = cert_DER_to_X509(NULL, len)) == NULL, NULL);
3162+ fail_unless((cert_decoded = cert_DER_to_X509(buf, len - 1)) == NULL, NULL);
3163+ fail_unless((cert_decoded = cert_DER_to_X509(buf, len + 1)) == NULL, NULL);
3164+ fail_unless((cert_decoded = cert_DER_to_X509(buf, 0)) == NULL, NULL);
3165+
3166+ X509_free(cert);
3167+ X509_free(cert_decoded);
3168+ free(buf);
3169+
3170+ HIP_DEBUG("Successfully passed tests for DER en/decoding of X509 certificates.\n");
3171+}
3172+
3173+END_TEST
3174+
3175+START_TEST(test_cert_match_public_key)
3176+{
3177+ int err = 0;
3178+ RSA *rsa = NULL;
3179+ X509 *cert = NULL;
3180+ EVP_PKEY *pkey = NULL;
3181+
3182+ HIP_DEBUG("Test matching of public keys.\n");
3183+
3184+ fail_unless((err = load_rsa_private_key(TEST_KEY, &rsa)) == 0, NULL);
3185+ fail_unless((cert = cert_load_x509_certificate(TEST_CERT,
3186+ ENCODING_FORMAT_PEM)) != NULL,
3187+ NULL);
3188+ pkey = EVP_PKEY_new();
3189+ EVP_PKEY_assign_RSA(pkey, rsa);
3190+ fail_unless((err = cert_match_public_key(cert, pkey)) == 1, NULL);
3191+
3192+ fail_unless((err = cert_match_public_key(NULL, pkey)) == 0, NULL);
3193+ fail_unless((err = cert_match_public_key(cert, NULL)) == 0, NULL);
3194+ fail_unless((err = cert_match_public_key(NULL, NULL)) == 0, NULL);
3195+
3196+ EVP_PKEY_free(pkey);
3197+ X509_free(cert);
3198+
3199+ HIP_DEBUG("Successfully passed test for matching of public keys.\n");
3200+}
3201+
3202+END_TEST
3203+
3204+START_TEST(test_cert_verify_chain)
3205+{
3206+ int err = 0;
3207+ X509 *cert = NULL;
3208+ STACK_OF(X509) *chain = NULL;
3209+
3210+ HIP_DEBUG("Test verification of certificate chains.\n");
3211+
3212+ fail_unless((cert = cert_load_x509_certificate(TEST_CERT,
3213+ ENCODING_FORMAT_PEM)) != NULL,
3214+ NULL);
3215+ fail_unless((chain = sk_X509_new_null()) != NULL, NULL);
3216+ sk_X509_push(chain, cert);
3217+ fail_unless((err = cert_verify_chain(cert, NULL, chain, NULL)) == 0, NULL);
3218+
3219+ fail_unless((err = cert_verify_chain(NULL, NULL, chain, NULL)) != 0, NULL);
3220+ fail_unless((err = cert_verify_chain(cert, NULL, NULL, NULL)) != 0, NULL);
3221+
3222+ X509_free(cert);
3223+ sk_X509_free(chain);
3224+
3225+ HIP_DEBUG("Successfully passed test for verification of certificate chains.\n");
3226+}
3227+
3228+END_TEST
3229+
3230+START_TEST(test_cert_get_X509_from_msg)
3231+{
3232+ int len = 0;
3233+ X509 *cert = NULL, *cert2 = NULL;
3234+ struct hip_common *msg = NULL;
3235+ unsigned char *buf = NULL;
3236+
3237+ HIP_DEBUG("Test certificate extraction functionality.\n");
3238+
3239+ fail_unless((cert = cert_load_x509_certificate(TEST_CERT,
3240+ ENCODING_FORMAT_PEM)) != NULL,
3241+ NULL);
3242+ msg = hip_msg_alloc();
3243+ hip_build_network_hdr(msg, HIP_UPDATE, 0, &in6addr_any, &in6addr_any);
3244+ fail_unless((len = cert_X509_to_DER(cert, &buf)) > 0, NULL);
3245+ fail_unless(hip_build_param_cert(msg, 0, 1, 1, HIP_CERT_X509V3, buf, len) == 0, NULL);
3246+ fail_unless((cert2 = cert_get_X509_from_msg(msg)) != NULL, NULL);
3247+ fail_unless(X509_cmp(cert, cert2) == 0, NULL);
3248+
3249+ X509_free(cert);
3250+ X509_free(cert2);
3251+ free(buf);
3252+ free(msg);
3253+
3254+ HIP_DEBUG("Successfully passed test for certificate extraction functionality.\n");
3255+}
3256+
3257+END_TEST
3258+
3259+
3260+Suite *lib_core_cert(void)
3261+{
3262+ Suite *s = suite_create("lib/core/cert");
3263+
3264+ TCase *tc_core = tcase_create("Core");
3265+ tcase_add_test(tc_core, test_cert_load_x509_certificate);
3266+ tcase_add_test(tc_core, test_cert_DER_encoding);
3267+ tcase_add_test(tc_core, test_cert_match_public_key);
3268+ tcase_add_test(tc_core, test_cert_verify_chain);
3269+ tcase_add_test(tc_core, test_cert_get_X509_from_msg);
3270+
3271+ suite_add_tcase(s, tc_core);
3272+
3273+ return s;
3274+}
3275
3276=== added file 'test/lib/core/test_cert.pem'
3277--- test/lib/core/test_cert.pem 1970-01-01 00:00:00 +0000
3278+++ test/lib/core/test_cert.pem 2012-03-16 04:27:22 +0000
3279@@ -0,0 +1,15 @@
3280+-----BEGIN CERTIFICATE-----
3281+MIICWTCCAcKgAwIBAgIJAPRDK58Gc992MA0GCSqGSIb3DQEBBQUAMCgxCzAJBgNV
3282+BAYTAkRFMRkwFwYDVQQDExBUZXN0IENlcnRpZmljYXRlMB4XDTExMTExNTA4NDYx
3283+MloXDTE0MDgxMTA4NDYxMlowKDELMAkGA1UEBhMCREUxGTAXBgNVBAMTEFRlc3Qg
3284+Q2VydGlmaWNhdGUwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMn5azBSwPlu
3285+DIzEhd6fGdo1+ze9uS+i+AbifvjHKYaDwDZktANnUmTuLNAXoeVtFi5GH/5aczUx
3286+rFaW+XT33oO1OjotZOHvoQd5cVAvXTtzuJj9PnBtA0lkrQ36f765p65Id0+Xme3o
3287+sXfqLsJy12C23RjisPgAo0hsLUFXt+FZAgMBAAGjgYowgYcwHQYDVR0OBBYEFGrj
3288+JefuwL7xAFj9NZoDVksjz1JBMFgGA1UdIwRRME+AFGrjJefuwL7xAFj9NZoDVksj
3289+z1JBoSykKjAoMQswCQYDVQQGEwJERTEZMBcGA1UEAxMQVGVzdCBDZXJ0aWZpY2F0
3290+ZYIJAPRDK58Gc992MAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAKX5Q
3291+0di8aNk1Js5Sk6QstSWwoVT9DUNZ8wKKRZVHy4kSL7dGMNGRPyNydzJmKeacbZJ0
3292+wM64rMMC1E8Wnyo+7eS1k9NKgaR5S1K6SVTfgP0HYIeJquD5Im/KW3aMz/q5CWdV
3293+IZtpTC2/1YsK+dVlvvcYRxnSTpIEd/pmu574lis=
3294+-----END CERTIFICATE-----
3295
3296=== added file 'test/lib/core/test_key.pem'
3297--- test/lib/core/test_key.pem 1970-01-01 00:00:00 +0000
3298+++ test/lib/core/test_key.pem 2012-03-16 04:27:22 +0000
3299@@ -0,0 +1,15 @@
3300+-----BEGIN RSA PRIVATE KEY-----
3301+MIICXAIBAAKBgQDJ+WswUsD5bgyMxIXenxnaNfs3vbkvovgG4n74xymGg8A2ZLQD
3302+Z1Jk7izQF6HlbRYuRh/+WnM1MaxWlvl0996DtTo6LWTh76EHeXFQL107c7iY/T5w
3303+bQNJZK0N+n++uaeuSHdPl5nt6LF36i7Cctdgtt0Y4rD4AKNIbC1BV7fhWQIDAQAB
3304+AoGAT1OS8evOtyit7SvSmFlMwhOpk38EmN0dJTcYP4WZnadpevOacCvIhLO3DhP6
3305+Fi3+JDaOokvMK/xSf7/UQkiIL+dwY5FtWtG6K+T1WI4+DR7ULShr82jh4KemhYv3
3306+Xz6PvEBIUrf64VfsNsAzoWvbwum/Ev1XzFn5YS4/EW3ApnECQQD2YW6tTjzyq3y7
3307+sgil9/VtUrXpPi5Ekm8l/bFW2Ijwin03g6J+YvkDNIq5Wwyka7lBOLwpdSpzT2qB
3308+70Ne1nlfAkEA0dwlgou4xOVVmbtTb40FxIFgd2gDQO8bUFEa+TdPWLLxz9yxHQ7D
3309+YROYh5Gdi0u4lz0KNex/6zyaP7E+utbIRwJAexNc2FH2/DpSCuj6jP36qevhV2xq
3310+bHLB9zZtujZc4dwshOjK6VvDjKhYjBNBk3kEh+IxjHwtAoEvcUz2WI/G/QJAcMr5
3311+/ihKrsj0MSRVu+b36p3+0y68UPIypABzlu77XpkPDsF3ED8XE94MZREGtA+GrwLH
3312+siPivPRdk04YgSNfkQJBAMhHvxL5xsb31bu8h7kxoYHj/XuqJxyToTcqksr7M1RO
3313+z33Bid+znwnB7n8CLFpV3iqF14xbRKiPlc//wVNWtZ8=
3314+-----END RSA PRIVATE KEY-----
3315
3316=== modified file 'test/lib/core/test_suites.h'
3317--- test/lib/core/test_suites.h 2012-03-13 13:33:06 +0000
3318+++ test/lib/core/test_suites.h 2012-03-16 04:27:22 +0000
3319@@ -28,6 +28,7 @@
3320
3321 #include <check.h>
3322
3323+Suite *lib_core_cert(void);
3324 Suite *lib_core_crypto(void);
3325 Suite *lib_core_hit(void);
3326 Suite *lib_core_hostid(void);
3327
3328=== modified file 'tools/hipl_autobuild.sh'
3329--- tools/hipl_autobuild.sh 2012-02-28 16:54:46 +0000
3330+++ tools/hipl_autobuild.sh 2012-03-16 04:27:22 +0000
3331@@ -169,7 +169,7 @@
3332 run_program "make $MAKEOPTS check"
3333
3334 # minimal configuration
3335-compile --enable-firewall --disable-rvs --disable-profiling --disable-debug --disable-performance --with-nomodules=heartbeat,update,heartbeat_update,midauth
3336+compile --enable-firewall --disable-rvs --disable-profiling --disable-debug --disable-performance --with-nomodules=heartbeat,update,heartbeat_update,midauth,cert
3337
3338 # Max compile coverage configuration
3339 FEATURES_ALL="--enable-firewall --enable-rvs --enable-profiling --disable-debug --enable-performance"
3340@@ -185,9 +185,6 @@
3341 # FIXME: Disabled until the tree compiles with this optimization level.
3342 #compile $FEATURES_ALL CFLAGS="-O3"
3343
3344-# Without modules
3345-compile --with-nomodules=heartbeat,update,heartbeat_update,midauth
3346-
3347 # test binary distribution packages
3348 # This is run as the last test because it can have sideeffects on the
3349 # other standard configurations.

Subscribers

People subscribed via source and target branches

to all changes: