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

Proposed by Diego Biurrun
Status: Superseded
Proposed branch: lp:~hipl-core/hipl/certificate-exchange
Merge into: lp:hipl
Diff against target: 3147 lines (+1398/-1002)
33 files modified
Makefile.am (+5/-1)
configure.ac (+2/-0)
doc/HOWTO.xml.in (+75/-0)
hipd/cert.c (+155/-81)
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 (+12/-5)
lib/core/builder.h (+7/-9)
lib/core/cert.c (+286/-0)
lib/core/cert.h (+51/-0)
lib/core/certtools.c (+5/-5)
lib/core/conf.c (+132/-4)
lib/core/protodefs.h (+14/-0)
modules/cert/hipd/cert.c (+169/-49)
modules/cert/hipd/cert.h (+7/-20)
modules/cert/module_info.xml (+23/-0)
test/check_lib_core.c (+1/-0)
test/lib/core/cert.c (+189/-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
Miika Komu Approve
Review via email: mp+95634@code.launchpad.net

This proposal has been superseded by a proposal from 2012-03-09.

Description of the change

The certificate exchange branch is ready to be reviewed by the general public. Here is the short description from the HOWTO:

At the protocol level, HIPL implements the HIP_CERT parameter as defined in RFC 6253. Specifically, X509 certificates are supported, whereas no functionality is provided for SPKI certificates. HIP does not define the usage of certificates in the protocol exchange. In HIPL, we currently add certificates to the R2 in the BEX and the second update message U2 (e.g. during the mobility-triggered update exchange).

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

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 :

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 :

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 :

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 :

Works for me.

review: Approve
Revision history for this message
René Hummen (rene-hummen) wrote :

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/

6107. By René Hummen

remove unnecessary includes

6108. By René Hummen

add missing include

6109. By David Martin

Fix hipconf command parsing for 'acquire certificate'.

hipconf syntax was changed some time ago, so instead of
'hipconf acquire certificate <HIT>' it is
'hipconf daemon acquire certificate <HIT>'.

This commit makes hipconf correctly read the passed command again.
It does _not_ fix the segfault of hipd when it tries to actually
acquire the certificate.

6110. By David Martin

Cosmetics: uncrustify lib/core/conf.c.

6111. By Christoph Viethen

Fix three problem areas related to certificate creation:

Remove duplicate NCONF_free() in hipd/cert.c, fixing the segfault problem.

Fix lib/core/certtools.c:hip_open_conf() to correctly deallocate structures
pointed to by the "conf" handle in case of error. Also do away with a
redundant variable.

Repair lib/core/conf.c:conf_handle_certificate() and its interaction
with hip_do_hipconf(). The first function would generate a message,
and itself look after sending it to the hipd. Subsequently, the second
function mentioned would take the very same message and send it
again, causing havoc. Fix: Perform hip_msg_init() at the end of
the first function to indicate to hip_do_hipconf() that the message
has already been sent, just like some other "conf_handle_...()"
functions do it.

Revision history for this message
Diego Biurrun (diego-biurrun) wrote :
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...

6112. By Diego Biurrun

cert: Make variable not used outside of cert.c static.

6113. By Diego Biurrun

Remove unused root_certificate_file variable.

6114. By Diego Biurrun

Remove some unnecessary void* casts.

6115. By Diego Biurrun

Avoid some unnecessary pointer type punning.

6116. By Diego Biurrun

cosmetics: whitespace adjustments, drop unnecessary block braces, ordering

6117. By Diego Biurrun

Merge current tip of trunk.

6118. By Diego Biurrun

cosmetics: comment typos, prettyprinting, ordering

6119. By Diego Biurrun

Get rid of an unnecessary variable indirection in cert_DER_to_X509().

6120. By Diego Biurrun

builder: Make hip_build_param_cert_x509_{ver|resp} function parameter unsigned.

This is simpler than checking it is non-negative and casting.

6121. By Diego Biurrun

Merge two conditions in cert_match_public_key().

6122. By Diego Biurrun

Fix some Doxygen markup errors and wording improvements.

Revision history for this message
Diego Biurrun (diego-biurrun) wrote :
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...

6123. By Diego Biurrun

Merge current trunk.

6124. By Diego Biurrun

Merge trunk again after landing of exponential backoff branch.

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.

Revision history for this message
Diego Biurrun (diego-biurrun) wrote :
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 :
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...

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).

Revision history for this message
Miika Komu (miika-iki) wrote :

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 :
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...

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.

Revision history for this message
Christof Mroz (christof-mroz) wrote :

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.

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.

Unmerged revisions

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

Subscribers

People subscribed via source and target branches

to all changes: