summaryrefslogtreecommitdiff
path: root/src/libstrongswan
diff options
context:
space:
mode:
Diffstat (limited to 'src/libstrongswan')
-rw-r--r--src/libstrongswan/Makefile.am1
-rw-r--r--src/libstrongswan/Makefile.in57
-rw-r--r--src/libstrongswan/asn1/asn1.c133
-rw-r--r--src/libstrongswan/asn1/asn1.h32
-rw-r--r--src/libstrongswan/asn1/oid.c221
-rw-r--r--src/libstrongswan/asn1/oid.h74
-rw-r--r--src/libstrongswan/asn1/oid.pl8
-rw-r--r--src/libstrongswan/asn1/oid.txt111
-rw-r--r--src/libstrongswan/crypto/hashers/hasher.c38
-rw-r--r--src/libstrongswan/crypto/hashers/hasher.h21
-rw-r--r--src/libstrongswan/crypto/ocsp.c8
-rw-r--r--src/libstrongswan/crypto/ocsp.h5
-rw-r--r--src/libstrongswan/crypto/pkcs7.c449
-rw-r--r--src/libstrongswan/crypto/pkcs7.h85
-rw-r--r--src/libstrongswan/crypto/pkcs9.c470
-rw-r--r--src/libstrongswan/crypto/pkcs9.h121
-rw-r--r--src/libstrongswan/crypto/rsa/rsa_private_key.c123
-rw-r--r--src/libstrongswan/crypto/rsa/rsa_private_key.h6
-rw-r--r--src/libstrongswan/crypto/rsa/rsa_public_key.c117
-rw-r--r--src/libstrongswan/crypto/rsa/rsa_public_key.h40
-rwxr-xr-xsrc/libstrongswan/crypto/x509.c94
-rwxr-xr-xsrc/libstrongswan/crypto/x509.h10
-rw-r--r--src/libstrongswan/utils/linked_list.c48
-rw-r--r--src/libstrongswan/utils/linked_list.h57
-rw-r--r--src/libstrongswan/utils/optionsfrom.c143
-rw-r--r--src/libstrongswan/utils/optionsfrom.h50
26 files changed, 2015 insertions, 507 deletions
diff --git a/src/libstrongswan/Makefile.am b/src/libstrongswan/Makefile.am
index e8859ad4c..fc642c615 100644
--- a/src/libstrongswan/Makefile.am
+++ b/src/libstrongswan/Makefile.am
@@ -35,6 +35,7 @@ crypto/hmac.c crypto/hmac.h \
crypto/ietf_attr_list.c crypto/ietf_attr_list.h \
crypto/ocsp.c crypto/ocsp.h \
crypto/pkcs7.c crypto/pkcs7.h \
+crypto/pkcs9.c crypto/pkcs9.h \
crypto/prfs/fips_prf.c crypto/prfs/fips_prf.h \
crypto/prfs/hmac_prf.c crypto/prfs/hmac_prf.h \
crypto/prfs/prf.c crypto/prfs/prf.h \
diff --git a/src/libstrongswan/Makefile.in b/src/libstrongswan/Makefile.in
index 75d3dddd4..c8a471e00 100644
--- a/src/libstrongswan/Makefile.in
+++ b/src/libstrongswan/Makefile.in
@@ -75,17 +75,18 @@ am__libstrongswan_la_SOURCES_DIST = credential_store.h library.c \
crypto/hashers/md5_hasher.c crypto/hashers/md5_hasher.h \
crypto/hmac.c crypto/hmac.h crypto/ietf_attr_list.c \
crypto/ietf_attr_list.h crypto/ocsp.c crypto/ocsp.h \
- crypto/pkcs7.c crypto/pkcs7.h crypto/prfs/fips_prf.c \
- crypto/prfs/fips_prf.h crypto/prfs/hmac_prf.c \
- crypto/prfs/hmac_prf.h crypto/prfs/prf.c crypto/prfs/prf.h \
- crypto/prf_plus.h crypto/prf_plus.c \
- crypto/rsa/rsa_private_key.c crypto/rsa/rsa_private_key.h \
- crypto/rsa/rsa_public_key.h crypto/rsa/rsa_public_key.c \
- crypto/signers/hmac_signer.c crypto/signers/hmac_signer.h \
- crypto/signers/signer.c crypto/signers/signer.h crypto/x509.c \
- crypto/x509.h utils/fetcher.c utils/fetcher.h utils/host.c \
- utils/host.h utils/identification.c utils/identification.h \
- utils/iterator.h utils/leak_detective.c utils/leak_detective.h \
+ crypto/pkcs7.c crypto/pkcs7.h crypto/pkcs9.c crypto/pkcs9.h \
+ crypto/prfs/fips_prf.c crypto/prfs/fips_prf.h \
+ crypto/prfs/hmac_prf.c crypto/prfs/hmac_prf.h \
+ crypto/prfs/prf.c crypto/prfs/prf.h crypto/prf_plus.h \
+ crypto/prf_plus.c crypto/rsa/rsa_private_key.c \
+ crypto/rsa/rsa_private_key.h crypto/rsa/rsa_public_key.h \
+ crypto/rsa/rsa_public_key.c crypto/signers/hmac_signer.c \
+ crypto/signers/hmac_signer.h crypto/signers/signer.c \
+ crypto/signers/signer.h crypto/x509.c crypto/x509.h \
+ utils/fetcher.c utils/fetcher.h utils/host.c utils/host.h \
+ utils/identification.c utils/identification.h utils/iterator.h \
+ utils/leak_detective.c utils/leak_detective.h \
utils/lexparser.c utils/lexparser.h utils/linked_list.c \
utils/linked_list.h utils/enumerator.c utils/enumerator.h \
utils/optionsfrom.c utils/optionsfrom.h utils/randomizer.c \
@@ -100,14 +101,14 @@ am__libstrongswan_la_SOURCES_DIST = credential_store.h library.c \
@USE_INTEGRITY_TEST_FALSE@ hasher.lo sha1_hasher.lo \
@USE_INTEGRITY_TEST_FALSE@ sha2_hasher.lo md5_hasher.lo hmac.lo \
@USE_INTEGRITY_TEST_FALSE@ ietf_attr_list.lo ocsp.lo pkcs7.lo \
-@USE_INTEGRITY_TEST_FALSE@ fips_prf.lo hmac_prf.lo prf.lo \
-@USE_INTEGRITY_TEST_FALSE@ prf_plus.lo rsa_private_key.lo \
-@USE_INTEGRITY_TEST_FALSE@ rsa_public_key.lo hmac_signer.lo \
-@USE_INTEGRITY_TEST_FALSE@ signer.lo x509.lo fetcher.lo host.lo \
-@USE_INTEGRITY_TEST_FALSE@ identification.lo leak_detective.lo \
-@USE_INTEGRITY_TEST_FALSE@ lexparser.lo linked_list.lo \
-@USE_INTEGRITY_TEST_FALSE@ enumerator.lo optionsfrom.lo \
-@USE_INTEGRITY_TEST_FALSE@ randomizer.lo
+@USE_INTEGRITY_TEST_FALSE@ pkcs9.lo fips_prf.lo hmac_prf.lo \
+@USE_INTEGRITY_TEST_FALSE@ prf.lo prf_plus.lo \
+@USE_INTEGRITY_TEST_FALSE@ rsa_private_key.lo rsa_public_key.lo \
+@USE_INTEGRITY_TEST_FALSE@ hmac_signer.lo signer.lo x509.lo \
+@USE_INTEGRITY_TEST_FALSE@ fetcher.lo host.lo identification.lo \
+@USE_INTEGRITY_TEST_FALSE@ leak_detective.lo lexparser.lo \
+@USE_INTEGRITY_TEST_FALSE@ linked_list.lo enumerator.lo \
+@USE_INTEGRITY_TEST_FALSE@ optionsfrom.lo randomizer.lo
@USE_INTEGRITY_TEST_TRUE@am_libstrongswan_la_OBJECTS = \
@USE_INTEGRITY_TEST_TRUE@ fips_canister_start.lo fips.lo \
@USE_INTEGRITY_TEST_TRUE@ library.lo chunk.lo debug.lo enum.lo \
@@ -118,8 +119,8 @@ am__libstrongswan_la_SOURCES_DIST = credential_store.h library.c \
@USE_INTEGRITY_TEST_TRUE@ hasher.lo sha1_hasher.lo \
@USE_INTEGRITY_TEST_TRUE@ sha2_hasher.lo md5_hasher.lo hmac.lo \
@USE_INTEGRITY_TEST_TRUE@ ietf_attr_list.lo ocsp.lo pkcs7.lo \
-@USE_INTEGRITY_TEST_TRUE@ fips_prf.lo hmac_prf.lo prf.lo \
-@USE_INTEGRITY_TEST_TRUE@ prf_plus.lo rsa_private_key.lo \
+@USE_INTEGRITY_TEST_TRUE@ pkcs9.lo fips_prf.lo hmac_prf.lo \
+@USE_INTEGRITY_TEST_TRUE@ prf.lo prf_plus.lo rsa_private_key.lo \
@USE_INTEGRITY_TEST_TRUE@ rsa_public_key.lo hmac_signer.lo \
@USE_INTEGRITY_TEST_TRUE@ signer.lo x509.lo fetcher.lo host.lo \
@USE_INTEGRITY_TEST_TRUE@ identification.lo leak_detective.lo \
@@ -269,11 +270,13 @@ mkdir_p = @mkdir_p@
oldincludedir = @oldincludedir@
pdfdir = @pdfdir@
piddir = @piddir@
+plugindir = @plugindir@
prefix = @prefix@
program_transform_name = @program_transform_name@
psdir = @psdir@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
+simreader = @simreader@
srcdir = @srcdir@
sysconfdir = @sysconfdir@
target_alias = @target_alias@
@@ -314,6 +317,7 @@ lib_LTLIBRARIES = libstrongswan.la
@USE_INTEGRITY_TEST_FALSE@ crypto/ietf_attr_list.h \
@USE_INTEGRITY_TEST_FALSE@ crypto/ocsp.c crypto/ocsp.h \
@USE_INTEGRITY_TEST_FALSE@ crypto/pkcs7.c crypto/pkcs7.h \
+@USE_INTEGRITY_TEST_FALSE@ crypto/pkcs9.c crypto/pkcs9.h \
@USE_INTEGRITY_TEST_FALSE@ crypto/prfs/fips_prf.c \
@USE_INTEGRITY_TEST_FALSE@ crypto/prfs/fips_prf.h \
@USE_INTEGRITY_TEST_FALSE@ crypto/prfs/hmac_prf.c \
@@ -378,7 +382,8 @@ lib_LTLIBRARIES = libstrongswan.la
@USE_INTEGRITY_TEST_TRUE@ crypto/ietf_attr_list.c \
@USE_INTEGRITY_TEST_TRUE@ crypto/ietf_attr_list.h crypto/ocsp.c \
@USE_INTEGRITY_TEST_TRUE@ crypto/ocsp.h crypto/pkcs7.c \
-@USE_INTEGRITY_TEST_TRUE@ crypto/pkcs7.h crypto/prfs/fips_prf.c \
+@USE_INTEGRITY_TEST_TRUE@ crypto/pkcs7.h crypto/pkcs9.c \
+@USE_INTEGRITY_TEST_TRUE@ crypto/pkcs9.h crypto/prfs/fips_prf.c \
@USE_INTEGRITY_TEST_TRUE@ crypto/prfs/fips_prf.h \
@USE_INTEGRITY_TEST_TRUE@ crypto/prfs/hmac_prf.c \
@USE_INTEGRITY_TEST_TRUE@ crypto/prfs/hmac_prf.h \
@@ -533,6 +538,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/optionsfrom.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pem.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pkcs7.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pkcs9.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/prf.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/prf_plus.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/printf_hook.Plo@am__quote@
@@ -706,6 +712,13 @@ pkcs7.lo: crypto/pkcs7.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o pkcs7.lo `test -f 'crypto/pkcs7.c' || echo '$(srcdir)/'`crypto/pkcs7.c
+pkcs9.lo: crypto/pkcs9.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT pkcs9.lo -MD -MP -MF $(DEPDIR)/pkcs9.Tpo -c -o pkcs9.lo `test -f 'crypto/pkcs9.c' || echo '$(srcdir)/'`crypto/pkcs9.c
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/pkcs9.Tpo $(DEPDIR)/pkcs9.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='crypto/pkcs9.c' object='pkcs9.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o pkcs9.lo `test -f 'crypto/pkcs9.c' || echo '$(srcdir)/'`crypto/pkcs9.c
+
fips_prf.lo: crypto/prfs/fips_prf.c
@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT fips_prf.lo -MD -MP -MF $(DEPDIR)/fips_prf.Tpo -c -o fips_prf.lo `test -f 'crypto/prfs/fips_prf.c' || echo '$(srcdir)/'`crypto/prfs/fips_prf.c
@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/fips_prf.Tpo $(DEPDIR)/fips_prf.Plo
diff --git a/src/libstrongswan/asn1/asn1.c b/src/libstrongswan/asn1/asn1.c
index 3191c89bd..3f0b829a9 100644
--- a/src/libstrongswan/asn1/asn1.c
+++ b/src/libstrongswan/asn1/asn1.c
@@ -1,6 +1,15 @@
-/* Simple ASN.1 parser
- * Copyright (C) 2000-2004 Andreas Steffen, Zuercher Hochschule Winterthur
- * Copyright (C) 2006 Martin Will, Hochschule fuer Technik Rapperswil
+/**
+ * @file asn1.c
+ *
+ * @brief Simple ASN.1 parser
+ *
+ */
+
+/*
+ * Copyright (C) 2006 Martin Will
+ * Copyright (C) 2000-2008 Andreas Steffen
+ *
+ * Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -12,7 +21,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * RCSID $Id: asn1.c 3299 2007-10-12 19:29:00Z andreas $
+ * RCSID $Id: asn1.c 3451 2008-02-05 19:27:05Z andreas $
*/
#include <stdio.h>
@@ -77,6 +86,13 @@ static u_char ASN1_sha512_id_str[] = {
0x05,0x00
};
+static u_char ASN1_md2WithRSA_id_str[] = {
+ 0x30, 0x0D,
+ 0x06, 0x09,
+ 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x02,
+ 0x05, 0x00
+};
+
static u_char ASN1_md5WithRSA_id_str[] = {
0x30, 0x0D,
0x06, 0x09,
@@ -91,6 +107,27 @@ static u_char ASN1_sha1WithRSA_id_str[] = {
0x05, 0x00
};
+static u_char ASN1_sha256WithRSA_id_str[] = {
+ 0x30, 0x0D,
+ 0x06, 0x09,
+ 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B,
+ 0x05, 0x00
+};
+
+static u_char ASN1_sha384WithRSA_id_str[] = {
+ 0x30, 0x0D,
+ 0x06, 0x09,
+ 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0C,
+ 0x05, 0x00
+};
+
+static u_char ASN1_sha512WithRSA_id_str[] = {
+ 0x30, 0x0D,
+ 0x06, 0x09,
+ 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0D,
+ 0x05, 0x00
+};
+
static u_char ASN1_rsaEncryption_id_str[] = {
0x30, 0x0D,
0x06, 0x09,
@@ -98,15 +135,19 @@ static u_char ASN1_rsaEncryption_id_str[] = {
0x05, 0x00
};
-const chunk_t ASN1_md2_id = chunk_from_buf(ASN1_md2_id_str);
-const chunk_t ASN1_md5_id = chunk_from_buf(ASN1_md5_id_str);
-const chunk_t ASN1_sha1_id = chunk_from_buf(ASN1_sha1_id_str);
-const chunk_t ASN1_sha256_id = chunk_from_buf(ASN1_sha256_id_str);
-const chunk_t ASN1_sha384_id = chunk_from_buf(ASN1_sha384_id_str);
-const chunk_t ASN1_sha512_id = chunk_from_buf(ASN1_sha512_id_str);
-const chunk_t ASN1_rsaEncryption_id = chunk_from_buf(ASN1_rsaEncryption_id_str);
-const chunk_t ASN1_md5WithRSA_id = chunk_from_buf(ASN1_md5WithRSA_id_str);
-const chunk_t ASN1_sha1WithRSA_id = chunk_from_buf(ASN1_sha1WithRSA_id_str);
+static const chunk_t ASN1_md2_id = chunk_from_buf(ASN1_md2_id_str);
+static const chunk_t ASN1_md5_id = chunk_from_buf(ASN1_md5_id_str);
+static const chunk_t ASN1_sha1_id = chunk_from_buf(ASN1_sha1_id_str);
+static const chunk_t ASN1_sha256_id = chunk_from_buf(ASN1_sha256_id_str);
+static const chunk_t ASN1_sha384_id = chunk_from_buf(ASN1_sha384_id_str);
+static const chunk_t ASN1_sha512_id = chunk_from_buf(ASN1_sha512_id_str);
+static const chunk_t ASN1_rsaEncryption_id = chunk_from_buf(ASN1_rsaEncryption_id_str);
+static const chunk_t ASN1_md2WithRSA_id = chunk_from_buf(ASN1_md2WithRSA_id_str);
+static const chunk_t ASN1_md5WithRSA_id = chunk_from_buf(ASN1_md5WithRSA_id_str);
+static const chunk_t ASN1_sha1WithRSA_id = chunk_from_buf(ASN1_sha1WithRSA_id_str);
+static const chunk_t ASN1_sha256WithRSA_id = chunk_from_buf(ASN1_sha256WithRSA_id_str);
+static const chunk_t ASN1_sha384WithRSA_id = chunk_from_buf(ASN1_sha384WithRSA_id_str);
+static const chunk_t ASN1_sha512WithRSA_id = chunk_from_buf(ASN1_sha512WithRSA_id_str);
/* ASN.1 definiton of an algorithmIdentifier */
static const asn1Object_t algorithmIdentifierObjects[] = {
@@ -128,14 +169,30 @@ chunk_t asn1_algorithmIdentifier(int oid)
{
case OID_RSA_ENCRYPTION:
return ASN1_rsaEncryption_id;
+ case OID_MD2_WITH_RSA:
+ return ASN1_md2WithRSA_id;
case OID_MD5_WITH_RSA:
return ASN1_md5WithRSA_id;
case OID_SHA1_WITH_RSA:
return ASN1_sha1WithRSA_id;
+ case OID_SHA256_WITH_RSA:
+ return ASN1_sha256WithRSA_id;
+ case OID_SHA384_WITH_RSA:
+ return ASN1_sha384WithRSA_id;
+ case OID_SHA512_WITH_RSA:
+ return ASN1_sha512WithRSA_id;
+ case OID_MD2:
+ return ASN1_md2_id;
case OID_MD5:
return ASN1_md5_id;
case OID_SHA1:
return ASN1_sha1_id;
+ case OID_SHA256:
+ return ASN1_sha256_id;
+ case OID_SHA384:
+ return ASN1_sha384_id;
+ case OID_SHA512:
+ return ASN1_sha512_id;
default:
return chunk_empty;
}
@@ -620,13 +677,23 @@ bool is_asn1(chunk_t blob)
DBG2(" file content is not binary ASN.1");
return FALSE;
}
+
len = asn1_length(&blob);
- if (len != blob.len)
+
+ /* exact match */
+ if (len == blob.len)
{
- DBG2(" file size does not match ASN.1 coded length");
- return FALSE;
+ return TRUE;
}
- return TRUE;
+
+ /* some websites append a surplus newline character to the blob */
+ if (len + 1 == blob.len && *(blob.ptr + len) == '\n')
+ {
+ return TRUE;
+ }
+
+ DBG2(" file size does not match ASN.1 coded length");
+ return FALSE;
}
/**
@@ -706,6 +773,23 @@ chunk_t asn1_simple_object(asn1_t tag, chunk_t content)
}
/**
+ * Build an ASN.1 BITSTRING object
+ */
+chunk_t asn1_bitstring(const char *mode, chunk_t content)
+{
+ chunk_t object;
+ u_char *pos = build_asn1_object(&object, ASN1_BIT_STRING, 1 + content.len);
+
+ *pos++ = 0x00;
+ memcpy(pos, content.ptr, content.len);
+ if (*mode == 'm')
+ {
+ free(content.ptr);
+ }
+ return object;
+}
+
+/**
* Build an ASN.1 object from a variable number of individual chunks.
* Depending on the mode, chunks either are moved ('m') or copied ('c').
*/
@@ -736,17 +820,12 @@ chunk_t asn1_wrap(asn1_t type, const char *mode, ...)
{
chunk_t ch = va_arg(chunks, chunk_t);
- switch (*mode++)
+ memcpy(pos, ch.ptr, ch.len);
+ pos += ch.len;
+
+ if (*mode++ == 'm')
{
- case 'm':
- memcpy(pos, ch.ptr, ch.len);
- pos += ch.len;
- free(ch.ptr);
- break;
- case 'c':
- default:
- memcpy(pos, ch.ptr, ch.len);
- pos += ch.len;
+ free(ch.ptr);
}
}
va_end(chunks);
diff --git a/src/libstrongswan/asn1/asn1.h b/src/libstrongswan/asn1/asn1.h
index 18742d18d..d9d85ba44 100644
--- a/src/libstrongswan/asn1/asn1.h
+++ b/src/libstrongswan/asn1/asn1.h
@@ -1,6 +1,15 @@
-/* Simple ASN.1 parser
- * Copyright (C) 2000-2004 Andreas Steffen, Zuercher Hochschule Winterthur
- * Copyright (C) 2006 Martin Will, Hochschule fuer Technik Rapperswil
+/**
+ * @file asn1.h
+ *
+ * @brief Simple ASN.1 parser
+ *
+ */
+
+/*
+ * Copyright (C) 2006 Martin Will
+ * Copyright (C) 2000-2008 Andreas Steffen
+ *
+ * Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -12,7 +21,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * RCSID $Id: asn1.h 3299 2007-10-12 19:29:00Z andreas $
+ * RCSID $Id: asn1.h 3423 2008-01-22 10:32:37Z andreas $
*/
#ifndef _ASN1_H
@@ -114,19 +123,9 @@ extern const chunk_t ASN1_INTEGER_0;
extern const chunk_t ASN1_INTEGER_1;
extern const chunk_t ASN1_INTEGER_2;
-/* some popular algorithmIdentifiers */
-extern const chunk_t ASN1_md2_id;
-extern const chunk_t ASN1_md5_id;
-extern const chunk_t ASN1_sha1_id;
-extern const chunk_t ASN1_sha256_id;
-extern const chunk_t ASN1_sha384_id;
-extern const chunk_t ASN1_sha512_id;
-
-extern const chunk_t ASN1_rsaEncryption_id;
-extern const chunk_t ASN1_md5WithRSA_id;
-extern const chunk_t ASN1_sha1WithRSA_id;
-
+/* returns some popular algorithmIdentifiers */
extern chunk_t asn1_algorithmIdentifier(int oid);
+
extern int known_oid(chunk_t object);
extern u_int asn1_length(chunk_t *blob);
extern bool is_printablestring(chunk_t str);
@@ -144,6 +143,7 @@ extern void code_asn1_length(size_t length, chunk_t *code);
extern u_char* build_asn1_object(chunk_t *object, asn1_t type, size_t datalen);
extern chunk_t asn1_integer_from_mpz(const mpz_t value);
extern chunk_t asn1_simple_object(asn1_t tag, chunk_t content);
+extern chunk_t asn1_bitstring(const char *mode, chunk_t content);
extern chunk_t asn1_wrap(asn1_t type, const char *mode, ...);
#endif /* _ASN1_H */
diff --git a/src/libstrongswan/asn1/oid.c b/src/libstrongswan/asn1/oid.c
index 28a915433..63896be6b 100644
--- a/src/libstrongswan/asn1/oid.c
+++ b/src/libstrongswan/asn1/oid.c
@@ -1,5 +1,5 @@
/* List of some useful object identifiers (OIDs)
- * Copyright (C) 2003-2004 Andreas Steffen, Zuercher Hochschule Winterthur
+ * Copyright (C) 2003-2008 Andreas Steffen, Hochschule fuer Technik Rapperswil
*
* This file has been automatically generated by the script oid.pl
* Do not edit manually!
@@ -62,7 +62,7 @@ const oid_t oid_names[] = {
{ 0x25, 50, 0, "extendedKeyUsage" }, /* 49 */
{ 0x37, 51, 0, "targetInformation" }, /* 50 */
{ 0x38, 0, 0, "noRevAvail" }, /* 51 */
- {0x2A, 94, 1, "" }, /* 52 */
+ {0x2A, 95, 1, "" }, /* 52 */
{ 0x86, 0, 1, "" }, /* 53 */
{ 0x48, 0, 1, "" }, /* 54 */
{ 0x86, 0, 1, "" }, /* 55 */
@@ -73,7 +73,7 @@ const oid_t oid_names[] = {
{ 0x00, 0, 0, "entrustVersInfo" }, /* 60 */
{ 0xF7, 0, 1, "" }, /* 61 */
{ 0x0D, 0, 1, "RSADSI" }, /* 62 */
- { 0x01, 89, 1, "PKCS" }, /* 63 */
+ { 0x01, 90, 1, "PKCS" }, /* 63 */
{ 0x01, 72, 1, "PKCS-1" }, /* 64 */
{ 0x01, 66, 0, "rsaEncryption" }, /* 65 */
{ 0x02, 67, 0, "md2WithRSAEncryption" }, /* 66 */
@@ -98,111 +98,112 @@ const oid_t oid_names[] = {
{ 0x06, 86, 0, "counterSignature" }, /* 85 */
{ 0x07, 87, 0, "challengePassword" }, /* 86 */
{ 0x08, 88, 0, "unstructuredAddress" }, /* 87 */
- { 0x0E, 0, 0, "extensionRequest" }, /* 88 */
- { 0x02, 92, 1, "digestAlgorithm" }, /* 89 */
- { 0x02, 91, 0, "md2" }, /* 90 */
- { 0x05, 0, 0, "md5" }, /* 91 */
- { 0x03, 0, 1, "encryptionAlgorithm" }, /* 92 */
- { 0x07, 0, 0, "3des-ede-cbc" }, /* 93 */
- {0x2B, 160, 1, "" }, /* 94 */
- { 0x06, 147, 1, "dod" }, /* 95 */
- { 0x01, 0, 1, "internet" }, /* 96 */
- { 0x04, 115, 1, "private" }, /* 97 */
- { 0x01, 0, 1, "enterprise" }, /* 98 */
- { 0x82, 108, 1, "" }, /* 99 */
- { 0x37, 0, 1, "Microsoft" }, /* 100 */
- { 0x0A, 105, 1, "" }, /* 101 */
- { 0x03, 0, 1, "" }, /* 102 */
- { 0x03, 104, 0, "msSGC" }, /* 103 */
- { 0x04, 0, 0, "msEncryptingFileSystem" }, /* 104 */
- { 0x14, 0, 1, "msEnrollmentInfrastructure"}, /* 105 */
- { 0x02, 0, 1, "msCertificateTypeExtension"}, /* 106 */
- { 0x02, 0, 0, "msSmartcardLogon" }, /* 107 */
- { 0x89, 0, 1, "" }, /* 108 */
- { 0x31, 0, 1, "" }, /* 109 */
- { 0x01, 0, 1, "" }, /* 110 */
- { 0x01, 0, 1, "" }, /* 111 */
- { 0x02, 0, 1, "" }, /* 112 */
- { 0x02, 114, 0, "" }, /* 113 */
- { 0x4B, 0, 0, "TCGID" }, /* 114 */
- { 0x05, 0, 1, "security" }, /* 115 */
- { 0x05, 0, 1, "mechanisms" }, /* 116 */
- { 0x07, 0, 1, "id-pkix" }, /* 117 */
- { 0x01, 120, 1, "id-pe" }, /* 118 */
- { 0x01, 0, 0, "authorityInfoAccess" }, /* 119 */
- { 0x03, 130, 1, "id-kp" }, /* 120 */
- { 0x01, 122, 0, "serverAuth" }, /* 121 */
- { 0x02, 123, 0, "clientAuth" }, /* 122 */
- { 0x03, 124, 0, "codeSigning" }, /* 123 */
- { 0x04, 125, 0, "emailProtection" }, /* 124 */
- { 0x05, 126, 0, "ipsecEndSystem" }, /* 125 */
- { 0x06, 127, 0, "ipsecTunnel" }, /* 126 */
- { 0x07, 128, 0, "ipsecUser" }, /* 127 */
- { 0x08, 129, 0, "timeStamping" }, /* 128 */
- { 0x09, 0, 0, "ocspSigning" }, /* 129 */
- { 0x08, 132, 1, "id-otherNames" }, /* 130 */
- { 0x05, 0, 0, "xmppAddr" }, /* 131 */
- { 0x0A, 137, 1, "id-aca" }, /* 132 */
- { 0x01, 134, 0, "authenticationInfo" }, /* 133 */
- { 0x02, 135, 0, "accessIdentity" }, /* 134 */
- { 0x03, 136, 0, "chargingIdentity" }, /* 135 */
- { 0x04, 0, 0, "group" }, /* 136 */
- { 0x30, 0, 1, "id-ad" }, /* 137 */
- { 0x01, 146, 1, "ocsp" }, /* 138 */
- { 0x01, 140, 0, "basic" }, /* 139 */
- { 0x02, 141, 0, "nonce" }, /* 140 */
- { 0x03, 142, 0, "crl" }, /* 141 */
- { 0x04, 143, 0, "response" }, /* 142 */
- { 0x05, 144, 0, "noCheck" }, /* 143 */
- { 0x06, 145, 0, "archiveCutoff" }, /* 144 */
- { 0x07, 0, 0, "serviceLocator" }, /* 145 */
- { 0x02, 0, 0, "caIssuers" }, /* 146 */
- { 0x0E, 153, 1, "oiw" }, /* 147 */
- { 0x03, 0, 1, "secsig" }, /* 148 */
- { 0x02, 0, 1, "algorithms" }, /* 149 */
- { 0x07, 151, 0, "des-cbc" }, /* 150 */
- { 0x1A, 152, 0, "sha-1" }, /* 151 */
- { 0x1D, 0, 0, "sha-1WithRSASignature" }, /* 152 */
- { 0x24, 0, 1, "TeleTrusT" }, /* 153 */
- { 0x03, 0, 1, "algorithm" }, /* 154 */
- { 0x03, 0, 1, "signatureAlgorithm" }, /* 155 */
- { 0x01, 0, 1, "rsaSignature" }, /* 156 */
- { 0x02, 158, 0, "rsaSigWithripemd160" }, /* 157 */
- { 0x03, 159, 0, "rsaSigWithripemd128" }, /* 158 */
- { 0x04, 0, 0, "rsaSigWithripemd256" }, /* 159 */
- {0x60, 0, 1, "" }, /* 160 */
- { 0x86, 0, 1, "" }, /* 161 */
- { 0x48, 0, 1, "" }, /* 162 */
- { 0x01, 0, 1, "organization" }, /* 163 */
- { 0x65, 171, 1, "gov" }, /* 164 */
- { 0x03, 0, 1, "csor" }, /* 165 */
- { 0x04, 0, 1, "nistalgorithm" }, /* 166 */
- { 0x02, 0, 1, "hashalgs" }, /* 167 */
- { 0x01, 169, 0, "id-SHA-256" }, /* 168 */
- { 0x02, 170, 0, "id-SHA-384" }, /* 169 */
- { 0x03, 0, 0, "id-SHA-512" }, /* 170 */
- { 0x86, 0, 1, "" }, /* 171 */
- { 0xf8, 0, 1, "" }, /* 172 */
- { 0x42, 185, 1, "netscape" }, /* 173 */
- { 0x01, 180, 1, "" }, /* 174 */
- { 0x01, 176, 0, "nsCertType" }, /* 175 */
- { 0x03, 177, 0, "nsRevocationUrl" }, /* 176 */
- { 0x04, 178, 0, "nsCaRevocationUrl" }, /* 177 */
- { 0x08, 179, 0, "nsCaPolicyUrl" }, /* 178 */
- { 0x0d, 0, 0, "nsComment" }, /* 179 */
- { 0x03, 183, 1, "directory" }, /* 180 */
- { 0x01, 0, 1, "" }, /* 181 */
- { 0x03, 0, 0, "employeeNumber" }, /* 182 */
- { 0x04, 0, 1, "policy" }, /* 183 */
- { 0x01, 0, 0, "nsSGC" }, /* 184 */
- { 0x45, 0, 1, "verisign" }, /* 185 */
- { 0x01, 0, 1, "pki" }, /* 186 */
- { 0x09, 0, 1, "attributes" }, /* 187 */
- { 0x02, 189, 0, "messageType" }, /* 188 */
- { 0x03, 190, 0, "pkiStatus" }, /* 189 */
- { 0x04, 191, 0, "failInfo" }, /* 190 */
- { 0x05, 192, 0, "senderNonce" }, /* 191 */
- { 0x06, 193, 0, "recipientNonce" }, /* 192 */
- { 0x07, 194, 0, "transID" }, /* 193 */
- { 0x08, 0, 0, "extensionReq" } /* 194 */
+ { 0x0E, 89, 0, "extensionRequest" }, /* 88 */
+ { 0x0F, 0, 0, "S/MIME Capabilities" }, /* 89 */
+ { 0x02, 93, 1, "digestAlgorithm" }, /* 90 */
+ { 0x02, 92, 0, "md2" }, /* 91 */
+ { 0x05, 0, 0, "md5" }, /* 92 */
+ { 0x03, 0, 1, "encryptionAlgorithm" }, /* 93 */
+ { 0x07, 0, 0, "3des-ede-cbc" }, /* 94 */
+ {0x2B, 161, 1, "" }, /* 95 */
+ { 0x06, 148, 1, "dod" }, /* 96 */
+ { 0x01, 0, 1, "internet" }, /* 97 */
+ { 0x04, 116, 1, "private" }, /* 98 */
+ { 0x01, 0, 1, "enterprise" }, /* 99 */
+ { 0x82, 109, 1, "" }, /* 100 */
+ { 0x37, 0, 1, "Microsoft" }, /* 101 */
+ { 0x0A, 106, 1, "" }, /* 102 */
+ { 0x03, 0, 1, "" }, /* 103 */
+ { 0x03, 105, 0, "msSGC" }, /* 104 */
+ { 0x04, 0, 0, "msEncryptingFileSystem" }, /* 105 */
+ { 0x14, 0, 1, "msEnrollmentInfrastructure"}, /* 106 */
+ { 0x02, 0, 1, "msCertificateTypeExtension"}, /* 107 */
+ { 0x02, 0, 0, "msSmartcardLogon" }, /* 108 */
+ { 0x89, 0, 1, "" }, /* 109 */
+ { 0x31, 0, 1, "" }, /* 110 */
+ { 0x01, 0, 1, "" }, /* 111 */
+ { 0x01, 0, 1, "" }, /* 112 */
+ { 0x02, 0, 1, "" }, /* 113 */
+ { 0x02, 115, 0, "" }, /* 114 */
+ { 0x4B, 0, 0, "TCGID" }, /* 115 */
+ { 0x05, 0, 1, "security" }, /* 116 */
+ { 0x05, 0, 1, "mechanisms" }, /* 117 */
+ { 0x07, 0, 1, "id-pkix" }, /* 118 */
+ { 0x01, 121, 1, "id-pe" }, /* 119 */
+ { 0x01, 0, 0, "authorityInfoAccess" }, /* 120 */
+ { 0x03, 131, 1, "id-kp" }, /* 121 */
+ { 0x01, 123, 0, "serverAuth" }, /* 122 */
+ { 0x02, 124, 0, "clientAuth" }, /* 123 */
+ { 0x03, 125, 0, "codeSigning" }, /* 124 */
+ { 0x04, 126, 0, "emailProtection" }, /* 125 */
+ { 0x05, 127, 0, "ipsecEndSystem" }, /* 126 */
+ { 0x06, 128, 0, "ipsecTunnel" }, /* 127 */
+ { 0x07, 129, 0, "ipsecUser" }, /* 128 */
+ { 0x08, 130, 0, "timeStamping" }, /* 129 */
+ { 0x09, 0, 0, "ocspSigning" }, /* 130 */
+ { 0x08, 133, 1, "id-otherNames" }, /* 131 */
+ { 0x05, 0, 0, "xmppAddr" }, /* 132 */
+ { 0x0A, 138, 1, "id-aca" }, /* 133 */
+ { 0x01, 135, 0, "authenticationInfo" }, /* 134 */
+ { 0x02, 136, 0, "accessIdentity" }, /* 135 */
+ { 0x03, 137, 0, "chargingIdentity" }, /* 136 */
+ { 0x04, 0, 0, "group" }, /* 137 */
+ { 0x30, 0, 1, "id-ad" }, /* 138 */
+ { 0x01, 147, 1, "ocsp" }, /* 139 */
+ { 0x01, 141, 0, "basic" }, /* 140 */
+ { 0x02, 142, 0, "nonce" }, /* 141 */
+ { 0x03, 143, 0, "crl" }, /* 142 */
+ { 0x04, 144, 0, "response" }, /* 143 */
+ { 0x05, 145, 0, "noCheck" }, /* 144 */
+ { 0x06, 146, 0, "archiveCutoff" }, /* 145 */
+ { 0x07, 0, 0, "serviceLocator" }, /* 146 */
+ { 0x02, 0, 0, "caIssuers" }, /* 147 */
+ { 0x0E, 154, 1, "oiw" }, /* 148 */
+ { 0x03, 0, 1, "secsig" }, /* 149 */
+ { 0x02, 0, 1, "algorithms" }, /* 150 */
+ { 0x07, 152, 0, "des-cbc" }, /* 151 */
+ { 0x1A, 153, 0, "sha-1" }, /* 152 */
+ { 0x1D, 0, 0, "sha-1WithRSASignature" }, /* 153 */
+ { 0x24, 0, 1, "TeleTrusT" }, /* 154 */
+ { 0x03, 0, 1, "algorithm" }, /* 155 */
+ { 0x03, 0, 1, "signatureAlgorithm" }, /* 156 */
+ { 0x01, 0, 1, "rsaSignature" }, /* 157 */
+ { 0x02, 159, 0, "rsaSigWithripemd160" }, /* 158 */
+ { 0x03, 160, 0, "rsaSigWithripemd128" }, /* 159 */
+ { 0x04, 0, 0, "rsaSigWithripemd256" }, /* 160 */
+ {0x60, 0, 1, "" }, /* 161 */
+ { 0x86, 0, 1, "" }, /* 162 */
+ { 0x48, 0, 1, "" }, /* 163 */
+ { 0x01, 0, 1, "organization" }, /* 164 */
+ { 0x65, 172, 1, "gov" }, /* 165 */
+ { 0x03, 0, 1, "csor" }, /* 166 */
+ { 0x04, 0, 1, "nistalgorithm" }, /* 167 */
+ { 0x02, 0, 1, "hashalgs" }, /* 168 */
+ { 0x01, 170, 0, "id-SHA-256" }, /* 169 */
+ { 0x02, 171, 0, "id-SHA-384" }, /* 170 */
+ { 0x03, 0, 0, "id-SHA-512" }, /* 171 */
+ { 0x86, 0, 1, "" }, /* 172 */
+ { 0xf8, 0, 1, "" }, /* 173 */
+ { 0x42, 186, 1, "netscape" }, /* 174 */
+ { 0x01, 181, 1, "" }, /* 175 */
+ { 0x01, 177, 0, "nsCertType" }, /* 176 */
+ { 0x03, 178, 0, "nsRevocationUrl" }, /* 177 */
+ { 0x04, 179, 0, "nsCaRevocationUrl" }, /* 178 */
+ { 0x08, 180, 0, "nsCaPolicyUrl" }, /* 179 */
+ { 0x0d, 0, 0, "nsComment" }, /* 180 */
+ { 0x03, 184, 1, "directory" }, /* 181 */
+ { 0x01, 0, 1, "" }, /* 182 */
+ { 0x03, 0, 0, "employeeNumber" }, /* 183 */
+ { 0x04, 0, 1, "policy" }, /* 184 */
+ { 0x01, 0, 0, "nsSGC" }, /* 185 */
+ { 0x45, 0, 1, "verisign" }, /* 186 */
+ { 0x01, 0, 1, "pki" }, /* 187 */
+ { 0x09, 0, 1, "attributes" }, /* 188 */
+ { 0x02, 190, 0, "messageType" }, /* 189 */
+ { 0x03, 191, 0, "pkiStatus" }, /* 190 */
+ { 0x04, 192, 0, "failInfo" }, /* 191 */
+ { 0x05, 193, 0, "senderNonce" }, /* 192 */
+ { 0x06, 194, 0, "recipientNonce" }, /* 193 */
+ { 0x07, 195, 0, "transID" }, /* 194 */
+ { 0x08, 0, 0, "extensionReq" } /* 195 */
};
diff --git a/src/libstrongswan/asn1/oid.h b/src/libstrongswan/asn1/oid.h
index 5814a3ba0..9980221ab 100644
--- a/src/libstrongswan/asn1/oid.h
+++ b/src/libstrongswan/asn1/oid.h
@@ -1,5 +1,5 @@
/* Object identifiers (OIDs) used by FreeS/WAN
- * Copyright (C) 2003-2004 Andreas Steffen, Zuercher Hochschule Winterthur
+ * Copyright (C) 2003-2008 Andreas Steffen, Hochschule fuer Technik Rapperswil
*
* This file has been automatically generated by the script oid.pl
* Do not edit manually!
@@ -17,7 +17,7 @@ typedef struct {
extern const oid_t oid_names[];
-#define OID_UNKNOWN -1
+#define OID_UNKNOWN -1
#define OID_ROLE 35
#define OID_SUBJECT_KEY_ID 38
#define OID_SUBJECT_ALT_NAME 41
@@ -46,40 +46,40 @@ extern const oid_t oid_names[];
#define OID_PKCS9_CONTENT_TYPE 82
#define OID_PKCS9_MESSAGE_DIGEST 83
#define OID_PKCS9_SIGNING_TIME 84
-#define OID_MD2 90
-#define OID_MD5 91
-#define OID_3DES_EDE_CBC 93
-#define OID_AUTHORITY_INFO_ACCESS 119
-#define OID_OCSP_SIGNING 129
-#define OID_XMPP_ADDR 131
-#define OID_AUTHENTICATION_INFO 133
-#define OID_ACCESS_IDENTITY 134
-#define OID_CHARGING_IDENTITY 135
-#define OID_GROUP 136
-#define OID_OCSP 138
-#define OID_BASIC 139
-#define OID_NONCE 140
-#define OID_CRL 141
-#define OID_RESPONSE 142
-#define OID_NO_CHECK 143
-#define OID_ARCHIVE_CUTOFF 144
-#define OID_SERVICE_LOCATOR 145
-#define OID_CA_ISSUERS 146
-#define OID_DES_CBC 150
-#define OID_SHA1 151
-#define OID_SHA1_WITH_RSA_OIW 152
-#define OID_SHA256 168
-#define OID_SHA384 169
-#define OID_SHA512 170
-#define OID_NS_REVOCATION_URL 176
-#define OID_NS_CA_REVOCATION_URL 177
-#define OID_NS_CA_POLICY_URL 178
-#define OID_NS_COMMENT 179
-#define OID_PKI_MESSAGE_TYPE 188
-#define OID_PKI_STATUS 189
-#define OID_PKI_FAIL_INFO 190
-#define OID_PKI_SENDER_NONCE 191
-#define OID_PKI_RECIPIENT_NONCE 192
-#define OID_PKI_TRANS_ID 193
+#define OID_MD2 91
+#define OID_MD5 92
+#define OID_3DES_EDE_CBC 94
+#define OID_AUTHORITY_INFO_ACCESS 120
+#define OID_OCSP_SIGNING 130
+#define OID_XMPP_ADDR 132
+#define OID_AUTHENTICATION_INFO 134
+#define OID_ACCESS_IDENTITY 135
+#define OID_CHARGING_IDENTITY 136
+#define OID_GROUP 137
+#define OID_OCSP 139
+#define OID_BASIC 140
+#define OID_NONCE 141
+#define OID_CRL 142
+#define OID_RESPONSE 143
+#define OID_NO_CHECK 144
+#define OID_ARCHIVE_CUTOFF 145
+#define OID_SERVICE_LOCATOR 146
+#define OID_CA_ISSUERS 147
+#define OID_DES_CBC 151
+#define OID_SHA1 152
+#define OID_SHA1_WITH_RSA_OIW 153
+#define OID_SHA256 169
+#define OID_SHA384 170
+#define OID_SHA512 171
+#define OID_NS_REVOCATION_URL 177
+#define OID_NS_CA_REVOCATION_URL 178
+#define OID_NS_CA_POLICY_URL 179
+#define OID_NS_COMMENT 180
+#define OID_PKI_MESSAGE_TYPE 189
+#define OID_PKI_STATUS 190
+#define OID_PKI_FAIL_INFO 191
+#define OID_PKI_SENDER_NONCE 192
+#define OID_PKI_RECIPIENT_NONCE 193
+#define OID_PKI_TRANS_ID 194
#endif /* OID_H_ */
diff --git a/src/libstrongswan/asn1/oid.pl b/src/libstrongswan/asn1/oid.pl
index 5db619755..04030d3ee 100644
--- a/src/libstrongswan/asn1/oid.pl
+++ b/src/libstrongswan/asn1/oid.pl
@@ -1,6 +1,8 @@
#!/usr/bin/perl
# Generates oid.h and oid.c out of oid.txt
-# Copyright (C) 2003-2004 Andreas Steffen, Zuercher Hochschule Winterthur
+#
+# Copyright (C) 2003-2008 Andreas Steffen
+# Hochschule fuer Technik Rapperswil
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
@@ -13,7 +15,7 @@
# for more details.
#
-$copyright="Copyright (C) 2003-2004 Andreas Steffen, Zuercher Hochschule Winterthur";
+$copyright="Copyright (C) 2003-2008 Andreas Steffen, Hochschule fuer Technik Rapperswil";
$automatic="This file has been automatically generated by the script oid.pl";
$warning="Do not edit manually!";
@@ -41,7 +43,7 @@ print OID_H "/* Object identifiers (OIDs) used by FreeS/WAN\n",
"\n",
"extern const oid_t oid_names[];\n",
"\n",
- "#define OID_UNKNOWN -1\n";
+ "#define OID_UNKNOWN -1\n";
# parse oid.txt
diff --git a/src/libstrongswan/asn1/oid.txt b/src/libstrongswan/asn1/oid.txt
index 6ae2dc29a..e6dede287 100644
--- a/src/libstrongswan/asn1/oid.txt
+++ b/src/libstrongswan/asn1/oid.txt
@@ -33,23 +33,23 @@
0x2A "G"
0x2B "I"
0x2D "ID"
- 0x48 "role" OID_ROLE
+ 0x48 "role" OID_ROLE
0x1D "id-ce"
0x09 "subjectDirectoryAttrs"
- 0x0E "subjectKeyIdentifier" OID_SUBJECT_KEY_ID
+ 0x0E "subjectKeyIdentifier" OID_SUBJECT_KEY_ID
0x0F "keyUsage"
0x10 "privateKeyUsagePeriod"
- 0x11 "subjectAltName" OID_SUBJECT_ALT_NAME
+ 0x11 "subjectAltName" OID_SUBJECT_ALT_NAME
0x12 "issuerAltName"
- 0x13 "basicConstraints" OID_BASIC_CONSTRAINTS
- 0x14 "crlNumber" OID_CRL_NUMBER
- 0x15 "reasonCode" OID_CRL_REASON_CODE
+ 0x13 "basicConstraints" OID_BASIC_CONSTRAINTS
+ 0x14 "crlNumber" OID_CRL_NUMBER
+ 0x15 "reasonCode" OID_CRL_REASON_CODE
0x1F "crlDistributionPoints" OID_CRL_DISTRIBUTION_POINTS
0x20 "certificatePolicies"
0x23 "authorityKeyIdentifier" OID_AUTHORITY_KEY_ID
- 0x25 "extendedKeyUsage" OID_EXTENDED_KEY_USAGE
- 0x37 "targetInformation" OID_TARGET_INFORMATION
- 0x38 "noRevAvail" OID_NO_REV_AVAIL
+ 0x25 "extendedKeyUsage" OID_EXTENDED_KEY_USAGE
+ 0x37 "targetInformation" OID_TARGET_INFORMATION
+ 0x38 "noRevAvail" OID_NO_REV_AVAIL
0x2A ""
0x86 ""
0x48 ""
@@ -63,35 +63,36 @@
0x0D "RSADSI"
0x01 "PKCS"
0x01 "PKCS-1"
- 0x01 "rsaEncryption" OID_RSA_ENCRYPTION
- 0x02 "md2WithRSAEncryption" OID_MD2_WITH_RSA
- 0x04 "md5WithRSAEncryption" OID_MD5_WITH_RSA
+ 0x01 "rsaEncryption" OID_RSA_ENCRYPTION
+ 0x02 "md2WithRSAEncryption" OID_MD2_WITH_RSA
+ 0x04 "md5WithRSAEncryption" OID_MD5_WITH_RSA
0x05 "sha-1WithRSAEncryption" OID_SHA1_WITH_RSA
0x0B "sha256WithRSAEncryption" OID_SHA256_WITH_RSA
0x0C "sha384WithRSAEncryption" OID_SHA384_WITH_RSA
0x0D "sha512WithRSAEncryption" OID_SHA512_WITH_RSA
0x07 "PKCS-7"
- 0x01 "data" OID_PKCS7_DATA
- 0x02 "signedData" OID_PKCS7_SIGNED_DATA
- 0x03 "envelopedData" OID_PKCS7_ENVELOPED_DATA
+ 0x01 "data" OID_PKCS7_DATA
+ 0x02 "signedData" OID_PKCS7_SIGNED_DATA
+ 0x03 "envelopedData" OID_PKCS7_ENVELOPED_DATA
0x04 "signedAndEnvelopedData" OID_PKCS7_SIGNED_ENVELOPED_DATA
- 0x05 "digestedData" OID_PKCS7_DIGESTED_DATA
- 0x06 "encryptedData" OID_PKCS7_ENCRYPTED_DATA
+ 0x05 "digestedData" OID_PKCS7_DIGESTED_DATA
+ 0x06 "encryptedData" OID_PKCS7_ENCRYPTED_DATA
0x09 "PKCS-9"
- 0x01 "E" OID_PKCS9_EMAIL
+ 0x01 "E" OID_PKCS9_EMAIL
0x02 "unstructuredName"
- 0x03 "contentType" OID_PKCS9_CONTENT_TYPE
- 0x04 "messageDigest" OID_PKCS9_MESSAGE_DIGEST
- 0x05 "signingTime" OID_PKCS9_SIGNING_TIME
+ 0x03 "contentType" OID_PKCS9_CONTENT_TYPE
+ 0x04 "messageDigest" OID_PKCS9_MESSAGE_DIGEST
+ 0x05 "signingTime" OID_PKCS9_SIGNING_TIME
0x06 "counterSignature"
0x07 "challengePassword"
0x08 "unstructuredAddress"
0x0E "extensionRequest"
+ 0x0F "S/MIME Capabilities"
0x02 "digestAlgorithm"
- 0x02 "md2" OID_MD2
- 0x05 "md5" OID_MD5
+ 0x02 "md2" OID_MD2
+ 0x05 "md5" OID_MD5
0x03 "encryptionAlgorithm"
- 0x07 "3des-ede-cbc" OID_3DES_EDE_CBC
+ 0x07 "3des-ede-cbc" OID_3DES_EDE_CBC
0x2B ""
0x06 "dod"
0x01 "internet"
@@ -117,7 +118,7 @@
0x05 "mechanisms"
0x07 "id-pkix"
0x01 "id-pe"
- 0x01 "authorityInfoAccess" OID_AUTHORITY_INFO_ACCESS
+ 0x01 "authorityInfoAccess" OID_AUTHORITY_INFO_ACCESS
0x03 "id-kp"
0x01 "serverAuth"
0x02 "clientAuth"
@@ -127,29 +128,29 @@
0x06 "ipsecTunnel"
0x07 "ipsecUser"
0x08 "timeStamping"
- 0x09 "ocspSigning" OID_OCSP_SIGNING
+ 0x09 "ocspSigning" OID_OCSP_SIGNING
0x08 "id-otherNames"
- 0x05 "xmppAddr" OID_XMPP_ADDR
+ 0x05 "xmppAddr" OID_XMPP_ADDR
0x0A "id-aca"
- 0x01 "authenticationInfo" OID_AUTHENTICATION_INFO
- 0x02 "accessIdentity" OID_ACCESS_IDENTITY
- 0x03 "chargingIdentity" OID_CHARGING_IDENTITY
- 0x04 "group" OID_GROUP
+ 0x01 "authenticationInfo" OID_AUTHENTICATION_INFO
+ 0x02 "accessIdentity" OID_ACCESS_IDENTITY
+ 0x03 "chargingIdentity" OID_CHARGING_IDENTITY
+ 0x04 "group" OID_GROUP
0x30 "id-ad"
- 0x01 "ocsp" OID_OCSP
- 0x01 "basic" OID_BASIC
- 0x02 "nonce" OID_NONCE
- 0x03 "crl" OID_CRL
- 0x04 "response" OID_RESPONSE
- 0x05 "noCheck" OID_NO_CHECK
- 0x06 "archiveCutoff" OID_ARCHIVE_CUTOFF
- 0x07 "serviceLocator" OID_SERVICE_LOCATOR
- 0x02 "caIssuers" OID_CA_ISSUERS
+ 0x01 "ocsp" OID_OCSP
+ 0x01 "basic" OID_BASIC
+ 0x02 "nonce" OID_NONCE
+ 0x03 "crl" OID_CRL
+ 0x04 "response" OID_RESPONSE
+ 0x05 "noCheck" OID_NO_CHECK
+ 0x06 "archiveCutoff" OID_ARCHIVE_CUTOFF
+ 0x07 "serviceLocator" OID_SERVICE_LOCATOR
+ 0x02 "caIssuers" OID_CA_ISSUERS
0x0E "oiw"
0x03 "secsig"
0x02 "algorithms"
- 0x07 "des-cbc" OID_DES_CBC
- 0x1A "sha-1" OID_SHA1
+ 0x07 "des-cbc" OID_DES_CBC
+ 0x1A "sha-1" OID_SHA1
0x1D "sha-1WithRSASignature" OID_SHA1_WITH_RSA_OIW
0x24 "TeleTrusT"
0x03 "algorithm"
@@ -166,18 +167,18 @@
0x03 "csor"
0x04 "nistalgorithm"
0x02 "hashalgs"
- 0x01 "id-SHA-256" OID_SHA256
- 0x02 "id-SHA-384" OID_SHA384
- 0x03 "id-SHA-512" OID_SHA512
+ 0x01 "id-SHA-256" OID_SHA256
+ 0x02 "id-SHA-384" OID_SHA384
+ 0x03 "id-SHA-512" OID_SHA512
0x86 ""
0xf8 ""
0x42 "netscape"
0x01 ""
0x01 "nsCertType"
- 0x03 "nsRevocationUrl" OID_NS_REVOCATION_URL
- 0x04 "nsCaRevocationUrl" OID_NS_CA_REVOCATION_URL
- 0x08 "nsCaPolicyUrl" OID_NS_CA_POLICY_URL
- 0x0d "nsComment" OID_NS_COMMENT
+ 0x03 "nsRevocationUrl" OID_NS_REVOCATION_URL
+ 0x04 "nsCaRevocationUrl" OID_NS_CA_REVOCATION_URL
+ 0x08 "nsCaPolicyUrl" OID_NS_CA_POLICY_URL
+ 0x0d "nsComment" OID_NS_COMMENT
0x03 "directory"
0x01 ""
0x03 "employeeNumber"
@@ -186,10 +187,10 @@
0x45 "verisign"
0x01 "pki"
0x09 "attributes"
- 0x02 "messageType" OID_PKI_MESSAGE_TYPE
- 0x03 "pkiStatus" OID_PKI_STATUS
- 0x04 "failInfo" OID_PKI_FAIL_INFO
- 0x05 "senderNonce" OID_PKI_SENDER_NONCE
- 0x06 "recipientNonce" OID_PKI_RECIPIENT_NONCE
- 0x07 "transID" OID_PKI_TRANS_ID
+ 0x02 "messageType" OID_PKI_MESSAGE_TYPE
+ 0x03 "pkiStatus" OID_PKI_STATUS
+ 0x04 "failInfo" OID_PKI_FAIL_INFO
+ 0x05 "senderNonce" OID_PKI_SENDER_NONCE
+ 0x06 "recipientNonce" OID_PKI_RECIPIENT_NONCE
+ 0x07 "transID" OID_PKI_TRANS_ID
0x08 "extensionReq"
diff --git a/src/libstrongswan/crypto/hashers/hasher.c b/src/libstrongswan/crypto/hashers/hasher.c
index 14bfb022f..9fa778aa6 100644
--- a/src/libstrongswan/crypto/hashers/hasher.c
+++ b/src/libstrongswan/crypto/hashers/hasher.c
@@ -6,8 +6,9 @@
*/
/*
- * Copyright (C) 2005-2006 Martin Willi
* Copyright (C) 2005 Jan Hutter
+ * Copyright (C) 2005-2006 Martin Willi
+ *
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -20,7 +21,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * RCSID $Id: hasher.c 3304 2007-10-12 23:18:42Z andreas $
+ * RCSID $Id: hasher.c 3423 2008-01-22 10:32:37Z andreas $
*/
@@ -110,6 +111,39 @@ hash_algorithm_t hasher_algorithm_from_oid(int oid)
/*
* Described in header.
*/
+int hasher_algorithm_to_oid(hash_algorithm_t alg)
+{
+ int oid;
+
+ switch (alg)
+ {
+ case HASH_MD2:
+ oid = OID_MD2;
+ break;
+ case HASH_MD5:
+ oid = OID_MD5;
+ break;
+ case HASH_SHA1:
+ oid = OID_SHA1;
+ break;
+ case HASH_SHA256:
+ oid = OID_SHA256;
+ break;
+ case HASH_SHA384:
+ oid = OID_SHA384;
+ break;
+ case HASH_SHA512:
+ oid = OID_SHA512;
+ break;
+ default:
+ oid = OID_UNKNOWN;
+ }
+ return oid;
+}
+
+/*
+ * Described in header.
+ */
int hasher_signature_algorithm_to_oid(hash_algorithm_t alg)
{
int oid;
diff --git a/src/libstrongswan/crypto/hashers/hasher.h b/src/libstrongswan/crypto/hashers/hasher.h
index 48b904576..e73de7f01 100644
--- a/src/libstrongswan/crypto/hashers/hasher.h
+++ b/src/libstrongswan/crypto/hashers/hasher.h
@@ -6,8 +6,9 @@
*/
/*
- * Copyright (C) 2005-2006 Martin Willi
* Copyright (C) 2005 Jan Hutter
+ * Copyright (C) 2005-2006 Martin Willi
+ *
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -20,7 +21,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * RCSID $Id: hasher.h 3307 2007-10-17 02:56:24Z andreas $
+ * RCSID $Id: hasher.h 3423 2008-01-22 10:32:37Z andreas $
*/
#ifndef HASHER_H_
@@ -171,11 +172,23 @@ hasher_t *hasher_create(hash_algorithm_t hash_algorithm);
hash_algorithm_t hasher_algorithm_from_oid(int oid);
/**
- * @brief Conversion of hash signature algorithm ASN.1 OID.
+ * @brief Conversion of hash algorithm into ASN.1 OID.
+ *
+ * @param alg hash algorithm
+ * @return
+ * - ASN.1 hash OID if known hash algorithm
+ * - OID_UNKNOW
+ *
+ * @ingroup hashers
+ */
+int hasher_algorithm_to_oid(hash_algorithm_t alg);
+
+/**
+ * @brief Conversion of hash signature algorithm into ASN.1 OID.
*
* @param alg hash algorithm
* @return
- * - ASN.1 OID if known hash algorithm
+ * - ASN.1 signature OID if known hash algorithm
* - OID_UNKNOW
*
* @ingroup hashers
diff --git a/src/libstrongswan/crypto/ocsp.c b/src/libstrongswan/crypto/ocsp.c
index e4d907188..4bbec31de 100644
--- a/src/libstrongswan/crypto/ocsp.c
+++ b/src/libstrongswan/crypto/ocsp.c
@@ -6,8 +6,11 @@
*/
/* Support of the Online Certificate Status Protocol (OCSP)
+ *
* Copyright (C) 2003 Christoph Gysin, Simon Zwahlen
- * Zuercher Hochschule Winterthur
+ * Copyright (C) 2007 Andreas Steffen
+ *
+ * Hochschule für Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -19,6 +22,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
+ * RCSID $Id$
*/
#include <unistd.h>
@@ -325,7 +329,7 @@ static chunk_t build_request(private_ocsp_t *this, certinfo_t *certinfo)
chunk_t serialNumber = certinfo->get_serialNumber(certinfo);
chunk_t reqCert = asn1_wrap(ASN1_SEQUENCE, "cmmm",
- ASN1_sha1_id,
+ asn1_algorithmIdentifier(OID_SHA1),
asn1_simple_object(ASN1_OCTET_STRING, this->authNameID),
asn1_simple_object(ASN1_OCTET_STRING, this->authKeyID),
asn1_simple_object(ASN1_INTEGER, serialNumber));
diff --git a/src/libstrongswan/crypto/ocsp.h b/src/libstrongswan/crypto/ocsp.h
index 42059e1c6..e468bb8be 100644
--- a/src/libstrongswan/crypto/ocsp.h
+++ b/src/libstrongswan/crypto/ocsp.h
@@ -6,9 +6,11 @@
*/
/* Support of the Online Certificate Status Protocol (OCSP) Support
+ *
* Copyright (C) 2003 Christoph Gysin, Simon Zwahlen
* Copyright (C) 2007 Andreas Steffen
- * Hochschule fuer Technik Rapperswil, Switzerland
+ *
+ * Hochschule fuer Technik Rapperswil, Switzerland
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -20,6 +22,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
+ * RCSID $Id$
*/
#ifndef OCSP_H_
diff --git a/src/libstrongswan/crypto/pkcs7.c b/src/libstrongswan/crypto/pkcs7.c
index 70510471a..48d3e2d78 100644
--- a/src/libstrongswan/crypto/pkcs7.c
+++ b/src/libstrongswan/crypto/pkcs7.c
@@ -7,7 +7,8 @@
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
- * Copyright (C) 2002-2005 Andreas Steffen
+ * Copyright (C) 2002-2008 Andreas Steffen
+ *
* Hochschule fuer Technik Rapperswil, Switzerland
*
* This program is free software; you can redistribute it and/or modify it
@@ -20,7 +21,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * RCSID $Id: pkcs7.c 3302 2007-10-12 21:57:20Z andreas $
+ * RCSID $Id: pkcs7.c 3438 2008-02-02 00:29:03Z andreas $
*/
#include <stdlib.h>
@@ -32,8 +33,11 @@
#include <asn1/asn1.h>
#include <asn1/oid.h>
#include <crypto/x509.h>
+#include <crypto/pkcs9.h>
#include <crypto/hashers/hasher.h>
#include <crypto/crypters/crypter.h>
+#include <crypto/rsa/rsa_public_key.h>
+#include <utils/randomizer.h>
#include <utils/linked_list.h>
#include "pkcs7.h"
@@ -77,7 +81,7 @@ struct private_pkcs7_t {
/**
* ASN.1 encoded attributes
*/
- chunk_t attributes;
+ pkcs9_t *attributes;
/**
* Linked list of X.509 certificates
@@ -244,25 +248,7 @@ static const chunk_t ASN1_des_cbc_oid =
chunk_from_buf(ASN1_des_cbc_oid_str);
/**
- * PKCS#7 attribute type OIDs
- */
-static u_char ASN1_contentType_oid_str[] = {
- 0x06, 0x09,
- 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x03
-};
-
-static u_char ASN1_messageDigest_oid_str[] = {
- 0x06, 0x09,
- 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x04
-};
-
-static const chunk_t ASN1_contentType_oid =
- chunk_from_buf(ASN1_contentType_oid_str);
-static const chunk_t ASN1_messageDigest_oid =
- chunk_from_buf(ASN1_messageDigest_oid_str);
-
-/**
- * Implements pkcs7_t.is_signedData.
+ * Implements pkcs7_t.is_data.
*/
static bool is_data(private_pkcs7_t *this)
{
@@ -278,7 +264,7 @@ static bool is_signedData(private_pkcs7_t *this)
}
/**
- * Implements pkcs7_t.is_signedData.
+ * Implements pkcs7_t.is_envelopedData.
*/
static bool is_envelopedData(private_pkcs7_t *this)
{
@@ -316,6 +302,11 @@ static bool parse_data(private_pkcs7_t *this)
{
return FALSE;
}
+ if (data.len == 0)
+ {
+ this->data = chunk_empty;
+ return TRUE;
+ }
if (parse_asn1_simple_object(&data, ASN1_OCTET_STRING, this->level, "data"))
{
this->data = chunk_clone(data);
@@ -328,7 +319,7 @@ static bool parse_data(private_pkcs7_t *this)
}
/**
- * Parse PKCS#7 signedData content
+ * Implements pkcs7_t.parse_signedData.
*/
static bool parse_signedData(private_pkcs7_t *this, x509_t *cacert)
{
@@ -363,11 +354,27 @@ static bool parse_signedData(private_pkcs7_t *this, x509_t *cacert)
digest_alg = parse_algorithmIdentifier(object, level, NULL);
break;
case PKCS7_SIGNED_CONTENT_INFO:
- this->data = chunk_clone(object);
+ {
+ chunk_t pureData;
+ pkcs7_t *data = pkcs7_create_from_chunk(object, level+1);
+
+ if (data == NULL)
+ {
+ return FALSE;
+ }
+ if (!data->parse_data(data))
+ {
+ data->destroy(data);
+ return FALSE;
+ }
+ pureData = data->get_data(data);
+ this->data = (pureData.len)? chunk_clone(pureData) : chunk_empty;
+ data->destroy(data);
+ }
break;
case PKCS7_SIGNED_CERT:
{
- x509_t *cert = x509_create_from_chunk(object, level+1);
+ x509_t *cert = x509_create_from_chunk(chunk_clone(object), level+1);
if (cert)
{
@@ -389,8 +396,9 @@ static bool parse_signedData(private_pkcs7_t *this, x509_t *cacert)
}
break;
case PKCS7_AUTH_ATTRIBUTES:
- this->attributes = object;
- *this->attributes.ptr = ASN1_SET;
+ *object.ptr = ASN1_SET;
+ this->attributes = pkcs9_create_from_chunk(object, level+1);
+ *object.ptr = ASN1_CONTEXT_C_0;
break;
case PKCS7_DIGEST_ALGORITHM:
digest_alg = parse_algorithmIdentifier(object, level, NULL);
@@ -407,8 +415,8 @@ static bool parse_signedData(private_pkcs7_t *this, x509_t *cacert)
/* check the signature only if a cacert is available */
if (cacert != NULL)
{
- rsa_public_key_t *signer = cacert->get_public_key(cacert);
hash_algorithm_t algorithm = hasher_algorithm_from_oid(digest_alg);
+ rsa_public_key_t *signer = cacert->get_public_key(cacert);
if (signerInfos == 0)
{
@@ -420,7 +428,7 @@ static bool parse_signedData(private_pkcs7_t *this, x509_t *cacert)
DBG1("more than one signerInfo object found");
return FALSE;
}
- if (this->attributes.ptr == NULL)
+ if (this->attributes == NULL)
{
DBG1("no authenticatedAttributes object found");
return FALSE;
@@ -431,7 +439,7 @@ static bool parse_signedData(private_pkcs7_t *this, x509_t *cacert)
return FALSE;
}
if (signer->verify_emsa_pkcs1_signature(signer, algorithm,
- this->attributes, encrypted_digest) != SUCCESS)
+ this->attributes->get_encoding(this->attributes), encrypted_digest) != SUCCESS)
{
DBG1("invalid digest signature");
return FALSE;
@@ -440,6 +448,39 @@ static bool parse_signedData(private_pkcs7_t *this, x509_t *cacert)
{
DBG2("digest signature is valid");
}
+ if (this->data.ptr != NULL)
+ {
+ chunk_t messageDigest = this->attributes->get_messageDigest(this->attributes);
+
+ if (messageDigest.ptr == NULL)
+ {
+ DBG1("messageDigest attribute not found");
+ return FALSE;
+ }
+ else
+ {
+ hasher_t *hasher = hasher_create(algorithm);
+ chunk_t hash;
+ bool valid;
+
+ hasher->allocate_hash(hasher, this->data, &hash);
+ hasher->destroy(hasher);
+ DBG3("hash: %B", &hash);
+
+ valid = chunk_equals(messageDigest, hash);
+ free(messageDigest.ptr);
+ free(hash.ptr);
+ if (valid)
+ {
+ DBG2("messageDigest is valid");
+ }
+ else
+ {
+ DBG1("invalid messageDigest");
+ return FALSE;
+ }
+ }
+ }
}
return TRUE;
}
@@ -574,8 +615,9 @@ static bool parse_envelopedData(private_pkcs7_t *this, chunk_t serialNumber,
}
/* decrypt the content */
+ crypter->set_key(crypter, symmetric_key);
crypter->decrypt(crypter, encrypted_content, iv, &this->data);
- DBG4("decrypted content with padding: %B", &this->data);
+ DBG3("decrypted content with padding: %B", &this->data);
/* remove the padding */
{
@@ -611,7 +653,7 @@ failed:
}
/**
- * Implements pkcs7_t.get_data
+ * Implements pkcs7_t.get_data.
*/
static chunk_t get_data(private_pkcs7_t *this)
{
@@ -619,7 +661,49 @@ static chunk_t get_data(private_pkcs7_t *this)
}
/**
- * Implements pkcs_t.create_crluri_iterator
+ * Implements pkcs7_t.get_contentInfo.
+ */
+static chunk_t get_contentInfo(private_pkcs7_t *this)
+{
+ chunk_t content_type;
+
+ /* select DER-encoded OID for pkcs7_contentInfo type */
+ switch(this->type)
+ {
+ case OID_PKCS7_DATA:
+ content_type = ASN1_pkcs7_data_oid;
+ break;
+ case OID_PKCS7_SIGNED_DATA:
+ content_type = ASN1_pkcs7_signed_data_oid;
+ break;
+ case OID_PKCS7_ENVELOPED_DATA:
+ content_type = ASN1_pkcs7_enveloped_data_oid;
+ break;
+ case OID_PKCS7_SIGNED_ENVELOPED_DATA:
+ content_type = ASN1_pkcs7_signed_enveloped_data_oid;
+ break;
+ case OID_PKCS7_DIGESTED_DATA:
+ content_type = ASN1_pkcs7_digested_data_oid;
+ break;
+ case OID_PKCS7_ENCRYPTED_DATA:
+ content_type = ASN1_pkcs7_encrypted_data_oid;
+ break;
+ case OID_UNKNOWN:
+ default:
+ DBG1("invalid pkcs7 contentInfo type");
+ return chunk_empty;
+ }
+
+ return (this->content.ptr == NULL)
+ ? asn1_simple_object(ASN1_SEQUENCE, content_type)
+ : asn1_wrap(ASN1_SEQUENCE, "cm",
+ content_type,
+ asn1_simple_object(ASN1_CONTEXT_C_0, this->content)
+ );
+}
+
+/**
+ * Implements pkcs7_t.create_certificate_iterator
*/
static iterator_t *create_certificate_iterator(const private_pkcs7_t *this)
{
@@ -627,11 +711,243 @@ static iterator_t *create_certificate_iterator(const private_pkcs7_t *this)
}
/**
+ * Implements pkcs7_t.set_certificate
+ */
+static void set_certificate(private_pkcs7_t *this, x509_t *cert)
+{
+ if (cert)
+ {
+ /* TODO the certificate is currently not cloned */
+ this->certs->insert_last(this->certs, cert);
+ }
+}
+
+/**
+ * Implements pkcs7_t.set_attributes
+ */
+static void set_attributes(private_pkcs7_t *this, pkcs9_t *attributes)
+{
+ this->attributes = attributes;
+}
+
+/**
+ * build a DER-encoded issuerAndSerialNumber object
+ */
+chunk_t pkcs7_build_issuerAndSerialNumber(x509_t *cert)
+{
+ identification_t *issuer = cert->get_issuer(cert);
+
+ return asn1_wrap(ASN1_SEQUENCE, "cm",
+ issuer->get_encoding(issuer),
+ asn1_simple_object(ASN1_INTEGER, cert->get_serialNumber(cert)));
+}
+
+/**
+ * Implements pkcs7_t.build_envelopedData.
+ */
+bool build_envelopedData(private_pkcs7_t *this, x509_t *cert,
+ encryption_algorithm_t alg)
+{
+ chunk_t iv, symmetricKey, in, out, alg_oid;
+ crypter_t *crypter;
+
+ /* select OID of symmetric encryption algorithm */
+ switch (alg)
+ {
+ case ENCR_DES:
+ alg_oid = ASN1_des_cbc_oid;
+ break;
+ case ENCR_3DES:
+ alg_oid = ASN1_3des_ede_cbc_oid;
+ break;
+ default:
+ DBG1(" encryption algorithm %N not supported",
+ encryption_algorithm_names, alg);
+ return FALSE;
+ }
+
+ crypter = crypter_create(alg, 0);
+ if (crypter == NULL)
+ {
+ DBG1(" could not create crypter for algorithm %N",
+ encryption_algorithm_names, alg);
+ return FALSE;
+ }
+
+ /* generate a true random symmetric encryption key
+ * and a pseudo-random iv
+ */
+ {
+ randomizer_t *randomizer = randomizer_create();
+
+ randomizer->allocate_random_bytes(randomizer,
+ crypter->get_key_size(crypter), &symmetricKey);
+ DBG4(" symmetric encryption key: %B", &symmetricKey);
+
+ randomizer->allocate_pseudo_random_bytes(randomizer,
+ crypter->get_block_size(crypter), &iv);
+ DBG4(" initialization vector: %B", &iv);
+
+ randomizer->destroy(randomizer);
+ }
+
+ /* pad the data so that the total length becomes
+ * a multiple of the block size
+ */
+ {
+ size_t block_size = crypter->get_block_size(crypter);
+ size_t padding = block_size - this->data.len % block_size;
+
+ in.len = this->data.len + padding;
+ in.ptr = malloc(in.len);
+
+ DBG2(" padding %d bytes of data to multiple block size of %d bytes",
+ (int)this->data.len, (int)in.len);
+
+ /* copy data */
+ memcpy(in.ptr, this->data.ptr, this->data.len);
+ /* append padding */
+ memset(in.ptr + this->data.len, padding, padding);
+ }
+ DBG3(" padded unencrypted data: %B", &in);
+
+ /* symmetric encryption of data object */
+ crypter->set_key(crypter, symmetricKey);
+ crypter->encrypt(crypter, in, iv, &out);
+ crypter->destroy(crypter);
+ chunk_free_randomized(&in);
+ DBG3(" encrypted data: %B", &out);
+
+ /* build pkcs7 enveloped data object */
+ {
+ chunk_t contentEncryptionAlgorithm = asn1_wrap(ASN1_SEQUENCE, "cm",
+ alg_oid,
+ asn1_wrap(ASN1_OCTET_STRING, "m", iv));
+
+ chunk_t encryptedContentInfo = asn1_wrap(ASN1_SEQUENCE, "cmm",
+ ASN1_pkcs7_data_oid,
+ contentEncryptionAlgorithm,
+ asn1_wrap(ASN1_CONTEXT_S_0, "m", out));
+
+ chunk_t wrappedKey, encryptedKey, recipientInfo;
+
+ rsa_public_key_t *public_key = cert->get_public_key(cert);
+
+ public_key->pkcs1_encrypt(public_key, symmetricKey, &wrappedKey);
+ chunk_free_randomized(&symmetricKey);
+
+ encryptedKey = asn1_wrap(ASN1_OCTET_STRING, "m", wrappedKey);
+
+ recipientInfo = asn1_wrap(ASN1_SEQUENCE, "cmcm",
+ ASN1_INTEGER_0,
+ pkcs7_build_issuerAndSerialNumber(cert),
+ asn1_algorithmIdentifier(OID_RSA_ENCRYPTION),
+ encryptedKey);
+
+ this->content = asn1_wrap(ASN1_SEQUENCE, "cmm",
+ ASN1_INTEGER_0,
+ asn1_wrap(ASN1_SET, "m", recipientInfo),
+ encryptedContentInfo);
+ this->type = OID_PKCS7_ENVELOPED_DATA;
+ }
+ return TRUE;
+}
+
+/**
+ * Implements pkcs7_t.build_signedData.
+ */
+bool build_signedData(private_pkcs7_t *this, rsa_private_key_t *private_key,
+ hash_algorithm_t alg)
+{
+ int signature_oid = hasher_signature_algorithm_to_oid(alg);
+ chunk_t authenticatedAttributes = chunk_empty;
+ chunk_t encryptedDigest = chunk_empty;
+ chunk_t signerInfo;
+ x509_t *cert;
+
+ if (this->certs->get_first(this->certs, (void**)&cert) != SUCCESS)
+ {
+ DBG1(" no pkcs7 signer certificate found");
+ return FALSE;
+ }
+
+ if (this->attributes != NULL)
+ {
+ if (this->data.ptr != NULL)
+ {
+ /* take the current time as signingTime */
+ time_t now = time(NULL);
+ chunk_t signingTime = timetoasn1(&now, ASN1_UTCTIME);
+
+ chunk_t messageDigest, attributes;
+ hasher_t *hasher = hasher_create(alg);
+
+ hasher->allocate_hash(hasher, this->data, &messageDigest);
+ hasher->destroy(hasher);
+ this->attributes->set_attribute(this->attributes,
+ OID_PKCS9_CONTENT_TYPE, ASN1_pkcs7_data_oid);
+ this->attributes->set_messageDigest(this->attributes,
+ messageDigest);
+ this->attributes->set_attribute(this->attributes,
+ OID_PKCS9_SIGNING_TIME, signingTime);
+ attributes = this->attributes->get_encoding(this->attributes);
+
+ free(messageDigest.ptr);
+ free(signingTime.ptr);
+
+ private_key->build_emsa_pkcs1_signature(private_key, alg,
+ attributes, &encryptedDigest);
+ authenticatedAttributes = chunk_clone(attributes);
+ *authenticatedAttributes.ptr = ASN1_CONTEXT_C_0;
+ }
+ }
+ else if (this->data.ptr != NULL)
+ {
+ private_key->build_emsa_pkcs1_signature(private_key, alg,
+ this->data, &encryptedDigest);
+ }
+ if (encryptedDigest.ptr)
+ {
+ encryptedDigest = asn1_wrap(ASN1_OCTET_STRING, "m", encryptedDigest);
+ }
+
+ signerInfo = asn1_wrap(ASN1_SEQUENCE, "cmcmcm",
+ ASN1_INTEGER_1,
+ pkcs7_build_issuerAndSerialNumber(cert),
+ asn1_algorithmIdentifier(signature_oid),
+ authenticatedAttributes,
+ asn1_algorithmIdentifier(OID_RSA_ENCRYPTION),
+ encryptedDigest);
+
+ if (this->data.ptr != NULL)
+ {
+ this->content = asn1_simple_object(ASN1_OCTET_STRING, this->data);
+ chunk_free(&this->data);
+ }
+ this->type = OID_PKCS7_DATA;
+ this->data = get_contentInfo(this);
+ chunk_free(&this->content);
+
+ this->type = OID_PKCS7_SIGNED_DATA;
+
+ this->content = asn1_wrap(ASN1_SEQUENCE, "cmcmm",
+ ASN1_INTEGER_1,
+ asn1_simple_object(ASN1_SET, asn1_algorithmIdentifier(signature_oid)),
+ this->data,
+ asn1_simple_object(ASN1_CONTEXT_C_0, cert->get_certificate(cert)),
+ asn1_wrap(ASN1_SET, "m", signerInfo));
+
+ return TRUE;
+}
+
+/**
* Implements pkcs7_t.destroy
*/
static void destroy(private_pkcs7_t *this)
{
+ DESTROY_IF(this->attributes);
this->certs->destroy_offset(this->certs, offsetof(x509_t, destroy));
+ free(this->content.ptr);
free(this->data.ptr);
free(this);
}
@@ -665,19 +981,19 @@ static bool parse_contentInfo(chunk_t blob, u_int level0, private_pkcs7_t *cInfo
return FALSE;
}
}
- else if (objectID == PKCS7_INFO_CONTENT)
+ else if (objectID == PKCS7_INFO_CONTENT && object.len > 0)
{
- cInfo->content = object;
+ cInfo->content = chunk_clone(object);
}
objectID++;
}
return TRUE;
}
-/*
- * Described in header.
+/**
+ * Generic private constructor
*/
-pkcs7_t *pkcs7_create_from_chunk(chunk_t chunk, u_int level)
+static private_pkcs7_t *pkcs7_create_empty(void)
{
private_pkcs7_t *this = malloc_thing(private_pkcs7_t);
@@ -685,9 +1001,9 @@ pkcs7_t *pkcs7_create_from_chunk(chunk_t chunk, u_int level)
this->type = OID_UNKNOWN;
this->content = chunk_empty;
this->parsed = FALSE;
- this->level = level + 2;
+ this->level = 0;
this->data = chunk_empty;
- this->attributes = chunk_empty;
+ this->attributes = NULL;
this->certs = linked_list_create();
/*public functions */
@@ -698,9 +1014,25 @@ pkcs7_t *pkcs7_create_from_chunk(chunk_t chunk, u_int level)
this->public.parse_signedData = (bool (*) (pkcs7_t*,x509_t*))parse_signedData;
this->public.parse_envelopedData = (bool (*) (pkcs7_t*,chunk_t,rsa_private_key_t*))parse_envelopedData;
this->public.get_data = (chunk_t (*) (pkcs7_t*))get_data;
+ this->public.get_contentInfo = (chunk_t (*) (pkcs7_t*))get_contentInfo;
this->public.create_certificate_iterator = (iterator_t* (*) (pkcs7_t*))create_certificate_iterator;
+ this->public.set_certificate = (void (*) (pkcs7_t*,x509_t*))set_certificate;
+ this->public.set_attributes = (void (*) (pkcs7_t*,pkcs9_t*))set_attributes;
+ this->public.build_envelopedData = (bool (*) (pkcs7_t*,x509_t*,encryption_algorithm_t))build_envelopedData;
+ this->public.build_signedData = (bool (*) (pkcs7_t*,rsa_private_key_t*,hash_algorithm_t))build_signedData;
this->public.destroy = (void (*) (pkcs7_t*))destroy;
+ return this;
+}
+
+/*
+ * Described in header.
+ */
+pkcs7_t *pkcs7_create_from_chunk(chunk_t chunk, u_int level)
+{
+ private_pkcs7_t *this = pkcs7_create_empty();
+
+ this->level = level + 2;
if (!parse_contentInfo(chunk, level, this))
{
destroy(this);
@@ -708,3 +1040,38 @@ pkcs7_t *pkcs7_create_from_chunk(chunk_t chunk, u_int level)
}
return &this->public;
}
+
+/*
+ * Described in header.
+ */
+pkcs7_t *pkcs7_create_from_data(chunk_t data)
+{
+ private_pkcs7_t *this = pkcs7_create_empty();
+
+ this->data = chunk_clone(data);
+ this->parsed = TRUE;
+
+ return &this->public;
+}
+
+/*
+ * Described in header.
+ */
+pkcs7_t *pkcs7_create_from_file(const char *filename, const char *label)
+{
+ bool pgp = FALSE;
+ chunk_t chunk = chunk_empty;
+ char cert_label[BUF_LEN];
+ pkcs7_t *pkcs7;
+
+ snprintf(cert_label, BUF_LEN, "%s pkcs7", label);
+
+ if (!pem_asn1_load_file(filename, NULL, cert_label, &chunk, &pgp))
+ {
+ return NULL;
+ }
+
+ pkcs7 = pkcs7_create_from_chunk(chunk, 0);
+ free(chunk.ptr);
+ return pkcs7;
+}
diff --git a/src/libstrongswan/crypto/pkcs7.h b/src/libstrongswan/crypto/pkcs7.h
index c8434225a..74bd25361 100644
--- a/src/libstrongswan/crypto/pkcs7.h
+++ b/src/libstrongswan/crypto/pkcs7.h
@@ -7,7 +7,7 @@
/*
* Copyright (C) 2005 Jan Hutter, Martin Willi
- * Copyright (C) 2002-2007 Andreas Steffen
+ * Copyright (C) 2002-2008 Andreas Steffen
*
* Hochschule fuer Technik Rapperswil, Switzerland
*
@@ -21,7 +21,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * RCSID $Id: pkcs7.h 3302 2007-10-12 21:57:20Z andreas $
+ * RCSID $Id: pkcs7.h 3437 2008-02-01 22:26:01Z andreas $
*/
#ifndef _PKCS7_H
@@ -31,7 +31,9 @@ typedef struct pkcs7_t pkcs7_t;
#include <library.h>
#include <crypto/x509.h>
+#include <crypto/pkcs9.h>
#include <crypto/rsa/rsa_private_key.h>
+#include <crypto/crypters/crypter.h>
#include <utils/iterator.h>
/**
@@ -39,6 +41,7 @@ typedef struct pkcs7_t pkcs7_t;
*
* @b Constructors:
* -pkcs7_create_from_chunk()
+ * -pkcs7_create_from_data()
*
* @ingroup crypto
*/
@@ -103,14 +106,66 @@ struct pkcs7_t {
chunk_t (*get_data) (pkcs7_t *this);
/**
+ * @brief Returns the a DER-encoded contentInfo object
+ *
+ * @param this calling object
+ * @return chunk containing the contentInfo object
+ */
+ chunk_t (*get_contentInfo) (pkcs7_t *this);
+
+ /**
* @brief Create an iterator for the certificates.
*
- * @param this calling object
- * @return iterator for the certificates
+ * @param this calling object
+ * @return iterator for the certificates
*/
iterator_t *(*create_certificate_iterator) (pkcs7_t *this);
/**
+ * @brief Add a certificate.
+ *
+ * @param this calling object
+ * @param cert certificate to be included
+ */
+ void (*set_certificate) (pkcs7_t *this, x509_t *cert);
+
+ /**
+ * @brief Add authenticated attributes.
+ *
+ * @param this calling object
+ * @param attributes attributes to be included
+ */
+ void (*set_attributes) (pkcs7_t *this, pkcs9_t *attributes);
+
+ /**
+ * @brief Build a data object
+ *
+ * @param this PKCS#7 data to be built
+ * @return TRUE if build was successful
+ */
+ bool (*build_data) (pkcs7_t *this);
+
+ /**
+ * @brief Build an envelopedData object
+ *
+ * @param this PKCS#7 data object to envelop
+ * @param cert receivers's certificate
+ * @param alg encryption algorithm
+ * @return TRUE if build was successful
+ */
+ bool (*build_envelopedData) (pkcs7_t *this, x509_t *cert, encryption_algorithm_t alg);
+
+ /**
+ * @brief Build an signedData object
+ *
+ * @param this PKCS#7 data object to sign
+ * @param key signer's RSA private key
+ * @param alg digest algorithm used for signature
+ * @return TRUE if build was successful
+ */
+ bool (*build_signedData) (pkcs7_t *this, rsa_private_key_t *key, hash_algorithm_t alg);
+
+ /**
* @brief Destroys the contentInfo object.
*
* @param this PKCS#7 contentInfo object to destroy
@@ -129,4 +184,26 @@ struct pkcs7_t {
*/
pkcs7_t *pkcs7_create_from_chunk(chunk_t chunk, u_int level);
+/**
+ * @brief Create a PKCS#7 contentInfo object
+ *
+ * @param chunk chunk containing data
+ * @return created pkcs7_contentInfo object.
+ *
+ * @ingroup crypto
+ */
+pkcs7_t *pkcs7_create_from_data(chunk_t data);
+
+/**
+ * @brief Read a X.509 certificate from a DER encoded file.
+ *
+ * @param filename file containing DER encoded data
+ * @param label label describing kind of PKCS#7 file
+ * @return created pkcs7_t object, or NULL if invalid.
+ *
+ * @ingroup crypto
+ */
+pkcs7_t *pkcs7_create_from_file(const char *filename, const char *label);
+
+
#endif /* _PKCS7_H */
diff --git a/src/libstrongswan/crypto/pkcs9.c b/src/libstrongswan/crypto/pkcs9.c
new file mode 100644
index 000000000..1003c9011
--- /dev/null
+++ b/src/libstrongswan/crypto/pkcs9.c
@@ -0,0 +1,470 @@
+/**
+ * @file pkcs9.c
+ *
+ * @brief Implementation of pkcs9_t.
+ *
+ */
+
+/*
+ * Copyright (C)2008 Andreas Steffen
+ *
+ * Hochschule fuer Technik Rapperswil, Switzerland
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * RCSID $Id: pkcs7.c 3423 2008-01-22 10:32:37Z andreas $
+ */
+
+#include <library.h>
+#include <debug.h>
+
+#include <asn1/oid.h>
+#include <asn1/asn1.h>
+#include <utils/linked_list.h>
+
+#include "pkcs9.h"
+
+typedef struct private_pkcs9_t private_pkcs9_t;
+
+/**
+ * Private data of a pkcs9_t attribute list.
+ */
+struct private_pkcs9_t {
+ /**
+ * Public interface
+ */
+ pkcs9_t public;
+
+ /**
+ * DER encoding of PKCS#9 attributes
+ */
+ chunk_t encoding;
+
+ /**
+ * Linked list of PKCS#9 attributes
+ */
+ linked_list_t *attributes;
+};
+
+typedef struct attribute_t attribute_t;
+
+/**
+ * Definition of an attribute_t object.
+ */
+struct attribute_t {
+ /**
+ * Object Identifier (OID)
+ */
+ int oid;
+
+ /**
+ * Attribute value
+ */
+ chunk_t value;
+
+ /**
+ * ASN.1 encoding
+ */
+ chunk_t encoding;
+
+ /**
+ * Destroys the attribute.
+ *
+ * @param this attribute to destroy
+ */
+ void (*destroy) (attribute_t *this);
+
+};
+
+/* ASN.1 definition of the X.501 atttribute type */
+
+static const asn1Object_t attributesObjects[] = {
+ { 0, "attributes", ASN1_SET, ASN1_LOOP }, /* 0 */
+ { 1, "attribute", ASN1_SEQUENCE, ASN1_NONE }, /* 1 */
+ { 2, "type", ASN1_OID, ASN1_BODY }, /* 2 */
+ { 2, "values", ASN1_SET, ASN1_LOOP }, /* 3 */
+ { 3, "value", ASN1_EOC, ASN1_RAW }, /* 4 */
+ { 2, "end loop", ASN1_EOC, ASN1_END }, /* 5 */
+ { 0, "end loop", ASN1_EOC, ASN1_END }, /* 6 */
+};
+
+#define ATTRIBUTE_OBJ_TYPE 2
+#define ATTRIBUTE_OBJ_VALUE 4
+#define ATTRIBUTE_OBJ_ROOF 7
+
+/**
+ * PKCS#9 attribute type OIDs
+ */
+static u_char ASN1_contentType_oid_str[] = {
+ 0x06, 0x09,
+ 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x03
+};
+
+static u_char ASN1_messageDigest_oid_str[] = {
+ 0x06, 0x09,
+ 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x04
+};
+
+static u_char ASN1_signingTime_oid_str[] = {
+ 0x06, 0x09,
+ 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x05
+};
+
+static char ASN1_messageType_oid_str[] = {
+ 0x06, 0x0A,
+ 0x60, 0x86, 0x48, 0x01, 0x86, 0xF8, 0x45, 0x01, 0x09, 0x02
+};
+
+static char ASN1_senderNonce_oid_str[] = {
+ 0x06, 0x0A,
+ 0x60, 0x86, 0x48, 0x01, 0x86, 0xF8, 0x45, 0x01, 0x09, 0x05
+};
+
+static char ASN1_transId_oid_str[] = {
+ 0x06, 0x0A,
+ 0x60, 0x86, 0x48, 0x01, 0x86, 0xF8, 0x45, 0x01, 0x09, 0x07
+};
+
+static const chunk_t ASN1_contentType_oid =
+ chunk_from_buf(ASN1_contentType_oid_str);
+static const chunk_t ASN1_messageDigest_oid =
+ chunk_from_buf(ASN1_messageDigest_oid_str);
+static const chunk_t ASN1_signingTime_oid =
+ chunk_from_buf(ASN1_signingTime_oid_str);
+static const chunk_t ASN1_messageType_oid =
+ chunk_from_buf(ASN1_messageType_oid_str);
+static const chunk_t ASN1_senderNonce_oid =
+ chunk_from_buf(ASN1_senderNonce_oid_str);
+static const chunk_t ASN1_transId_oid =
+ chunk_from_buf(ASN1_transId_oid_str);
+
+/**
+ * return the ASN.1 encoded OID of a PKCS#9 attribute
+ */
+static chunk_t asn1_attributeIdentifier(int oid)
+{
+ switch (oid)
+ {
+ case OID_PKCS9_CONTENT_TYPE:
+ return ASN1_contentType_oid;
+ case OID_PKCS9_MESSAGE_DIGEST:
+ return ASN1_messageDigest_oid;
+ case OID_PKCS9_SIGNING_TIME:
+ return ASN1_signingTime_oid;
+ case OID_PKI_MESSAGE_TYPE:
+ return ASN1_messageType_oid;
+ case OID_PKI_SENDER_NONCE:
+ return ASN1_senderNonce_oid;
+ case OID_PKI_TRANS_ID:
+ return ASN1_transId_oid;;
+ default:
+ return chunk_empty;
+ }
+}
+
+/**
+ * return the ASN.1 encoding of a PKCS#9 attribute
+ */
+static asn1_t asn1_attributeType(int oid)
+{
+ asn1_t type;
+
+ switch (oid)
+ {
+ case OID_PKCS9_CONTENT_TYPE:
+ type = ASN1_OID;
+ break;
+ case OID_PKCS9_SIGNING_TIME:
+ type = ASN1_UTCTIME;
+ break;
+ case OID_PKCS9_MESSAGE_DIGEST:
+ type = ASN1_OCTET_STRING;
+ break;
+ case OID_PKI_MESSAGE_TYPE:
+ type = ASN1_PRINTABLESTRING;
+ break;
+ case OID_PKI_STATUS:
+ type = ASN1_PRINTABLESTRING;
+ break;
+ case OID_PKI_FAIL_INFO:
+ type = ASN1_PRINTABLESTRING;
+ break;
+ case OID_PKI_SENDER_NONCE:
+ type = ASN1_OCTET_STRING;
+ break;
+ case OID_PKI_RECIPIENT_NONCE:
+ type = ASN1_OCTET_STRING;
+ break;
+ case OID_PKI_TRANS_ID:
+ type = ASN1_PRINTABLESTRING;
+ break;
+ default:
+ type = ASN1_EOC;
+ }
+ return type;
+}
+
+/**
+ * Destroy an attribute_t object.
+ */
+static void attribute_destroy(attribute_t *this)
+{
+ free(this->value.ptr);
+ free(this->encoding.ptr);
+ free(this);
+}
+
+/**
+ * Create an attribute_t object.
+ */
+static attribute_t *attribute_create(int oid, chunk_t value)
+{
+ attribute_t *this = malloc_thing(attribute_t);
+
+ this->oid = oid;
+ this->value = chunk_clone(value);
+ this->encoding = asn1_wrap(ASN1_SEQUENCE, "cm",
+ asn1_attributeIdentifier(oid),
+ asn1_simple_object(ASN1_SET, value));
+ this->destroy = (void (*) (attribute_t*))attribute_destroy;
+ return this;
+}
+
+/**
+ * Implements pkcs9_t.build_encoding
+ */
+static void build_encoding(private_pkcs9_t *this)
+{
+ iterator_t *iterator;
+ attribute_t *attribute;
+ u_int attributes_len = 0;
+
+ if (this->encoding.ptr)
+ {
+ chunk_free(&this->encoding);
+ }
+ if (this->attributes->get_count(this->attributes) == 0)
+ {
+ return;
+ }
+
+ /* compute the total length of the encoded attributes */
+ iterator = this->attributes->create_iterator(this->attributes, TRUE);
+
+ while (iterator->iterate(iterator, (void**)&attribute))
+ {
+ attributes_len += attribute->encoding.len;
+ }
+ iterator->destroy(iterator);
+
+ /* allocate memory for the attributes and build the encoding */
+ {
+ u_char *pos = build_asn1_object(&this->encoding, ASN1_SET, attributes_len);
+
+ iterator = this->attributes->create_iterator(this->attributes, TRUE);
+
+ while (iterator->iterate(iterator, (void**)&attribute))
+ {
+ memcpy(pos, attribute->encoding.ptr, attribute->encoding.len);
+ pos += attribute->encoding.len;
+ }
+ iterator->destroy(iterator);
+ }
+}
+
+/**
+ * Implements pkcs9_t.get_encoding
+ */
+static chunk_t get_encoding(private_pkcs9_t *this)
+{
+ if (this->encoding.ptr == NULL)
+ {
+ build_encoding(this);
+ }
+ return this->encoding;
+}
+
+/**
+ * Implements pkcs9_t.get_attribute
+ */
+static chunk_t get_attribute(private_pkcs9_t *this, int oid)
+{
+ iterator_t *iterator = this->attributes->create_iterator(this->attributes, TRUE);
+ chunk_t value = chunk_empty;
+ attribute_t *attribute;
+
+ while (iterator->iterate(iterator, (void**)&attribute))
+ {
+ if (attribute->oid == oid)
+ {
+ value = attribute->value;
+ break;
+ }
+ }
+ iterator->destroy(iterator);
+ return value;
+}
+
+/**
+ * Implements pkcs9_t.set_attribute
+ */
+static void set_attribute(private_pkcs9_t *this, int oid, chunk_t value)
+{
+ attribute_t *attribute = attribute_create(oid, value);
+
+ this->attributes->insert_last(this->attributes, (void*)attribute);
+}
+
+/**
+ * Implements pkcs9_t.get_messageDigest
+ */
+static chunk_t get_messageDigest(private_pkcs9_t *this)
+{
+ const int oid = OID_PKCS9_MESSAGE_DIGEST;
+ chunk_t value = get_attribute(this, oid);
+
+ if (value.ptr == NULL)
+ {
+ return chunk_empty;
+ }
+ if (!parse_asn1_simple_object(&value, asn1_attributeType(oid), 0, oid_names[oid].name))
+ {
+ return chunk_empty;
+ }
+ return chunk_clone(value);
+}
+
+/**
+ * Implements pkcs9_t.set_attribute
+ */
+static void set_messageDigest(private_pkcs9_t *this, chunk_t value)
+{
+ const int oid = OID_PKCS9_MESSAGE_DIGEST;
+ chunk_t messageDigest = asn1_simple_object(asn1_attributeType(oid), value);
+
+ set_attribute(this, oid, messageDigest);
+ free(messageDigest.ptr);
+}
+
+/**
+ * Implements pkcs9_t.destroy
+ */
+static void destroy(private_pkcs9_t *this)
+{
+ this->attributes->destroy_offset(this->attributes, offsetof(attribute_t, destroy));
+ free(this->encoding.ptr);
+ free(this);
+}
+
+/**
+ * Generic private constructor
+ */
+static private_pkcs9_t *pkcs9_create_empty(void)
+{
+ private_pkcs9_t *this = malloc_thing(private_pkcs9_t);
+
+ /* initialize */
+ this->encoding = chunk_empty;
+ this->attributes = linked_list_create();
+
+ /*public functions */
+ this->public.build_encoding = (void (*) (pkcs9_t*))build_encoding;
+ this->public.get_encoding = (chunk_t (*) (pkcs9_t*))get_encoding;
+ this->public.get_attribute = (chunk_t (*) (pkcs9_t*,int))get_attribute;
+ this->public.set_attribute = (void (*) (pkcs9_t*,int,chunk_t))set_attribute;
+ this->public.get_messageDigest = (chunk_t (*) (pkcs9_t*))get_messageDigest;
+ this->public.set_messageDigest = (void (*) (pkcs9_t*,chunk_t))set_messageDigest;
+ this->public.destroy = (void (*) (pkcs9_t*))destroy;
+
+ return this;
+}
+
+/*
+ * Described in header.
+ */
+pkcs9_t *pkcs9_create(void)
+{
+ private_pkcs9_t *this = pkcs9_create_empty();
+
+ return &this->public;
+}
+
+/**
+ * Parse a PKCS#9 attribute list
+ */
+static bool parse_attributes(chunk_t chunk, int level0, private_pkcs9_t* this)
+{
+ asn1_ctx_t ctx;
+ chunk_t object;
+ u_int level;
+ int oid = OID_UNKNOWN;
+ int objectID = 0;
+
+ asn1_init(&ctx, chunk, level0, FALSE, FALSE);
+
+ while (objectID < ATTRIBUTE_OBJ_ROOF)
+ {
+ if (!extract_object(attributesObjects, &objectID, &object, &level, &ctx))
+ {
+ return FALSE;
+ }
+
+ switch (objectID)
+ {
+ case ATTRIBUTE_OBJ_TYPE:
+ oid = known_oid(object);
+ break;
+ case ATTRIBUTE_OBJ_VALUE:
+ if (oid == OID_UNKNOWN)
+ {
+ break;
+ }
+ /* add the attribute to a linked list */
+ {
+ attribute_t *attribute = attribute_create(oid, object);
+
+ this->attributes->insert_last(this->attributes, (void*)attribute);
+ }
+ /* parse known attributes */
+ {
+ asn1_t type = asn1_attributeType(oid);
+
+ if (type != ASN1_EOC)
+ {
+ if (!parse_asn1_simple_object(&object, type, level+1, oid_names[oid].name))
+ {
+ return FALSE;
+ }
+ }
+ }
+ }
+ objectID++;
+ }
+ return TRUE;
+}
+
+
+ /*
+ * Described in header.
+ */
+pkcs9_t *pkcs9_create_from_chunk(chunk_t chunk, u_int level)
+{
+ private_pkcs9_t *this = pkcs9_create_empty();
+
+ this->encoding = chunk_clone(chunk);
+
+ if (!parse_attributes(chunk, level, this))
+ {
+ destroy(this);
+ return NULL;
+ }
+ return &this->public;
+}
diff --git a/src/libstrongswan/crypto/pkcs9.h b/src/libstrongswan/crypto/pkcs9.h
new file mode 100644
index 000000000..44915720c
--- /dev/null
+++ b/src/libstrongswan/crypto/pkcs9.h
@@ -0,0 +1,121 @@
+/**
+ * @file pkcs7.h
+ *
+ * @brief Interface of pkcs9_t.
+ *
+ */
+
+/*
+ * Copyright (C) 2008 Andreas Steffen
+ *
+ * Hochschule fuer Technik Rapperswil, Switzerland
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * RCSID $Id: pkcs7.h 3423 2008-01-22 10:32:37Z andreas $
+ */
+
+#ifndef _PKCS9_H
+#define _PKCS9_H
+
+typedef struct pkcs9_t pkcs9_t;
+
+#include <library.h>
+
+/**
+ * @brief PKCS#9 .
+ *
+ * @b Constructors:
+ * -pkcs9_create_from_chunk()
+ * -pkcs9_create()
+ *
+ * @ingroup crypto
+ */
+struct pkcs9_t {
+ /**
+ * @brief generate ASN.1 encoding of attribute list
+ *
+ * @param this PKCS#9 attribute list to be encoded
+ */
+ void (*build_encoding) (pkcs9_t *this);
+
+ /**
+ * @brief gets ASN.1 encoding of PKCS#9 attribute list
+ *
+ * @param this calling object
+ * @return ASN.1 encoded PKCSI#9 list
+ */
+ chunk_t (*get_encoding) (pkcs9_t *this);
+
+ /**
+ * @brief gets a PKCS#9 attribute
+ *
+ * @param this calling object
+ * @param oid OID of the attribute
+ * @return ASN.1 encoded value of the attribute
+ */
+ chunk_t (*get_attribute) (pkcs9_t *this, int oid);
+
+ /**
+ * @brief adds a PKCS#9 attribute
+ *
+ * @param this calling object
+ * @param oid OID of the attribute
+ * @param value ASN.1 encoded value of the attribute
+ */
+ void (*set_attribute) (pkcs9_t *this, int oid, chunk_t value);
+
+ /**
+ * @brief gets a PKCS#9 messageDigest attribute
+ *
+ * @param this calling object
+ * @return messageDigest
+ */
+ chunk_t (*get_messageDigest) (pkcs9_t *this);
+
+ /**
+ * @brief add a PKCS#9 messageDigest attribute
+ *
+ * @param this calling object
+ * @param value messageDigest
+ */
+ void (*set_messageDigest) (pkcs9_t *this, chunk_t value);
+
+ /**
+ * @brief Destroys the PKCS#9 attribute list.
+ *
+ * @param this PKCS#9 attribute list to destroy
+ */
+ void (*destroy) (pkcs9_t *this);
+};
+
+/**
+ * @brief Read a PKCS#9 attribute list from a DER encoded chunk.
+ *
+ * @param chunk chunk containing DER encoded data
+ * @param level ASN.1 parsing start level
+ * @return created pkcs9 attribute list, or NULL if invalid.
+ *
+ * @ingroup crypto
+ */
+pkcs9_t *pkcs9_create_from_chunk(chunk_t chunk, u_int level);
+
+/**
+ * @brief Create an empty PKCS#9 attribute list
+ *
+ * @param chunk chunk containing data
+ * @return created pkcs9 attribute list.
+ *
+ * @ingroup crypto
+ */
+pkcs9_t *pkcs9_create(void);
+
+#endif /* _PKCS9_H */
diff --git a/src/libstrongswan/crypto/rsa/rsa_private_key.c b/src/libstrongswan/crypto/rsa/rsa_private_key.c
index ec2f2fc74..1b1499887 100644
--- a/src/libstrongswan/crypto/rsa/rsa_private_key.c
+++ b/src/libstrongswan/crypto/rsa/rsa_private_key.c
@@ -6,8 +6,10 @@
*/
/*
- * Copyright (C) 2005-2006 Martin Willi
* Copyright (C) 2005 Jan Hutter
+ * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2007-2008 Andreas Steffen
+ *
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -20,7 +22,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * RCSID $Id: rsa_private_key.c 3306 2007-10-17 02:55:53Z andreas $
+ * RCSID $Id: rsa_private_key.c 3429 2008-01-27 20:59:22Z andreas $
*/
#include <gmp.h>
@@ -40,6 +42,7 @@
* defined in rsa_public_key.c
*/
extern chunk_t rsa_public_key_info_to_asn1(const mpz_t n, const mpz_t e);
+extern chunk_t rsa_public_key_id_create(const mpz_t n, const mpz_t e);
/**
* Public exponent to use for key generation.
@@ -111,7 +114,6 @@ struct private_rsa_private_key_t {
* Keyid formed as a SHA-1 hash of a publicKeyInfo object
*/
chunk_t keyid;
-
/**
* @brief Implements the RSADP algorithm specified in PKCS#1.
@@ -129,16 +131,6 @@ struct private_rsa_private_key_t {
* @return processed data
*/
chunk_t (*rsasp1) (private_rsa_private_key_t *this, chunk_t data);
-
- /**
- * @brief Generate a prime value.
- *
- * @param this calling object
- * @param prime_size size of the prime, in bytes
- * @param[out] prime uninitialized mpz
- */
- status_t (*compute_prime) (private_rsa_private_key_t *this, size_t prime_size, mpz_t *prime);
-
};
/* ASN.1 definition of a PKCS#1 RSA private key */
@@ -173,8 +165,6 @@ static const asn1Object_t privkey_objects[] = {
#define PRIV_KEY_COEFF 9
#define PRIV_KEY_ROOF 16
-static private_rsa_private_key_t *rsa_private_key_create_empty(void);
-
/**
* Auxiliary function overwriting private key material with
* pseudo-random bytes before releasing it
@@ -196,9 +186,9 @@ static void mpz_clear_randomized(mpz_t z)
}
/**
- * Implementation of private_rsa_private_key_t.compute_prime.
+ * Generate a random prime number with prime_len bytes
*/
-static status_t compute_prime(private_rsa_private_key_t *this, size_t prime_size, mpz_t *prime)
+static status_t compute_prime(private_rsa_private_key_t *this, size_t prime_len, mpz_t *prime)
{
randomizer_t *randomizer;
chunk_t random_bytes;
@@ -209,7 +199,8 @@ static status_t compute_prime(private_rsa_private_key_t *this, size_t prime_size
do
{
- status = randomizer->allocate_random_bytes(randomizer, prime_size, &random_bytes);
+ DBG1(" generating %d bit prime from %s ...", BITS_PER_BYTE * prime_len, DEV_RANDOM);
+ status = randomizer->allocate_random_bytes(randomizer, prime_len, &random_bytes);
if (status != SUCCESS)
{
randomizer->destroy(randomizer);
@@ -230,7 +221,7 @@ static status_t compute_prime(private_rsa_private_key_t *this, size_t prime_size
chunk_free_randomized(&random_bytes);
}
/* check if it isnt too large */
- while (((mpz_sizeinbase(*prime, 2) + 7) / 8) > prime_size);
+ while (((mpz_sizeinbase(*prime, 2) + 7) / BITS_PER_BYTE) > prime_len);
randomizer->destroy(randomizer);
return SUCCESS;
@@ -269,7 +260,7 @@ static chunk_t rsadp(private_rsa_private_key_t *this, chunk_t data)
}
/**
- * Implementation of rsa_private_key_t.eme_pkcs1_decrypt.
+ * Implementation of rsa_private_key_t.pkcs1_decrypt.
*/
static status_t pkcs1_decrypt(private_rsa_private_key_t *this,
chunk_t in, chunk_t *out)
@@ -319,47 +310,14 @@ static status_t build_emsa_pkcs1_signature(private_rsa_private_key_t *this,
chunk_t data, chunk_t *signature)
{
hasher_t *hasher;
- chunk_t em, digestInfo, hash_id, hash;
-
- /* get oid string prepended to hash */
- switch (hash_algorithm)
- {
- case HASH_MD2:
- {
- hash_id =ASN1_md2_id;
- break;
- }
- case HASH_MD5:
- {
- hash_id = ASN1_md5_id;
- break;
- }
- case HASH_SHA1:
- {
- hash_id = ASN1_sha1_id;
- break;
- }
- case HASH_SHA256:
- {
- hash_id = ASN1_sha256_id;
- break;
- }
- case HASH_SHA384:
- {
- hash_id = ASN1_sha384_id;
- break;
- }
- case HASH_SHA512:
- {
- hash_id = ASN1_sha512_id;
- break;
- }
- default:
- {
- return NOT_SUPPORTED;
- }
+ chunk_t em, digestInfo, hash;
+ int hash_oid = hasher_algorithm_to_oid(hash_algorithm);
+
+ if (hash_oid == OID_UNKNOWN)
+ {
+ return NOT_SUPPORTED;
}
-
+
/* get hasher */
hasher = hasher_create(hash_algorithm);
if (hasher == NULL)
@@ -373,7 +331,7 @@ static status_t build_emsa_pkcs1_signature(private_rsa_private_key_t *this,
/* build DER-encoded digestInfo */
digestInfo = asn1_wrap(ASN1_SEQUENCE, "cm",
- hash_id,
+ asn1_algorithmIdentifier(hash_oid),
asn1_simple_object(ASN1_OCTET_STRING, hash)
);
chunk_free(&hash);
@@ -432,7 +390,7 @@ static bool pkcs1_write(private_rsa_private_key_t *this, const char *filename, b
*/
rsa_public_key_t *get_public_key(private_rsa_private_key_t *this)
{
- return NULL;
+ return rsa_public_key_create(this->n, this->e);
}
/**
@@ -455,13 +413,13 @@ static status_t check(private_rsa_private_key_t *this)
/* PKCS#1 1.5 section 6 requires modulus to have at least 12 octets.
* We actually require more (for security).
*/
- if (this->k < 512/8)
+ if (this->k < 512 / BITS_PER_BYTE)
{
return FAILED;
}
/* we picked a max modulus size to simplify buffer allocation */
- if (this->k > 8192/8)
+ if (this->k > 8192 / BITS_PER_BYTE)
{
return FAILED;
}
@@ -572,7 +530,6 @@ static private_rsa_private_key_t *rsa_private_key_create_empty(void)
/* private functions */
this->rsadp = rsadp;
this->rsasp1 = rsadp; /* same algorithm */
- this->compute_prime = compute_prime;
this->keyid = chunk_empty;
@@ -587,20 +544,17 @@ rsa_private_key_t *rsa_private_key_create(size_t key_size)
mpz_t p, q, n, e, d, exp1, exp2, coeff;
mpz_t m, q1, t;
private_rsa_private_key_t *this;
-
- this = rsa_private_key_create_empty();
- key_size = key_size / 8;
+ size_t key_len = key_size / BITS_PER_BYTE;
+ size_t prime_len = key_len / 2;
/* Get values of primes p and q */
- if (this->compute_prime(this, key_size/2, &p) != SUCCESS)
+ if (compute_prime(this, prime_len, &p) != SUCCESS)
{
- free(this);
return NULL;
}
- if (this->compute_prime(this, key_size/2, &q) != SUCCESS)
+ if (compute_prime(this, prime_len, &q) != SUCCESS)
{
mpz_clear(p);
- free(this);
return NULL;
}
@@ -648,7 +602,13 @@ rsa_private_key_t *rsa_private_key_create(size_t key_size)
mpz_clear_randomized(m);
mpz_clear_randomized(t);
- /* apply values */
+ /* determine exact the modulus size in bits */
+ key_size = mpz_sizeinbase(n, 2);
+
+ /* create and fill in rsa_private_key_t object */
+ this = rsa_private_key_create_empty();
+ this->k = (key_size + 7) / BITS_PER_BYTE;
+ this->keyid = rsa_public_key_id_create(n, e);
*(this->p) = *p;
*(this->q) = *q;
*(this->n) = *n;
@@ -657,10 +617,8 @@ rsa_private_key_t *rsa_private_key_create(size_t key_size)
*(this->exp1) = *exp1;
*(this->exp2) = *exp2;
*(this->coeff) = *coeff;
-
- /* set key size in bytes */
- this->k = key_size;
-
+ DBG1("generated %d bit RSA key with keyid: %#B", key_size, &this->keyid);
+
return &this->public;
}
@@ -733,17 +691,8 @@ rsa_private_key_t *rsa_private_key_create_from_chunk(chunk_t blob)
}
this->k = (mpz_sizeinbase(this->n, 2) + 7) / BITS_PER_BYTE;
+ this->keyid = rsa_public_key_id_create(this->n, this->e);
- /* form the keyid as a SHA-1 hash of a publicKeyInfo object */
- {
- chunk_t publicKeyInfo = rsa_public_key_info_to_asn1(this->n, this->e);
- hasher_t *hasher = hasher_create(HASH_SHA1);
-
- hasher->allocate_hash(hasher, publicKeyInfo, &this->keyid);
- hasher->destroy(hasher);
- free(publicKeyInfo.ptr);
- }
-
if (check(this) != SUCCESS)
{
destroy(this);
diff --git a/src/libstrongswan/crypto/rsa/rsa_private_key.h b/src/libstrongswan/crypto/rsa/rsa_private_key.h
index e5cf49810..8013f03c2 100644
--- a/src/libstrongswan/crypto/rsa/rsa_private_key.h
+++ b/src/libstrongswan/crypto/rsa/rsa_private_key.h
@@ -6,8 +6,10 @@
*/
/*
- * Copyright (C) 2005-2006 Martin Willi
* Copyright (C) 2005 Jan Hutter
+ * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2007-2008 Andreas Steffen
+ *
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -20,7 +22,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * RCSID $Id: rsa_private_key.h 3296 2007-10-12 15:23:29Z andreas $
+ * RCSID $Id: rsa_private_key.h 3423 2008-01-22 10:32:37Z andreas $
*/
#ifndef RSA_PRIVATE_KEY_H_
diff --git a/src/libstrongswan/crypto/rsa/rsa_public_key.c b/src/libstrongswan/crypto/rsa/rsa_public_key.c
index 6f2158d2b..10af0527e 100644
--- a/src/libstrongswan/crypto/rsa/rsa_public_key.c
+++ b/src/libstrongswan/crypto/rsa/rsa_public_key.c
@@ -6,8 +6,10 @@
*/
/*
- * Copyright (C) 2005-2006 Martin Willi
* Copyright (C) 2005 Jan Hutter
+ * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2007-2008 Andreas Steffen
+ *
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -20,7 +22,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * RCSID $Id: rsa_public_key.c 3303 2007-10-12 22:49:39Z andreas $
+ * RCSID $Id: rsa_public_key.c 3428 2008-01-27 20:58:52Z andreas $
*/
#include <gmp.h>
@@ -32,6 +34,7 @@
#include "rsa_public_key.h"
#include <debug.h>
+#include <utils/randomizer.h>
#include <crypto/hashers/hasher.h>
#include <asn1/asn1.h>
#include <asn1/pem.h>
@@ -110,8 +113,6 @@ struct private_rsa_public_key_t {
chunk_t (*rsavp1) (const private_rsa_public_key_t *this, chunk_t data);
};
-private_rsa_public_key_t *rsa_public_key_create_empty(void);
-
/**
* Implementation of private_rsa_public_key_t.rsaep and private_rsa_public_key_t.rsavp1
*/
@@ -137,6 +138,55 @@ static chunk_t rsaep(const private_rsa_public_key_t *this, chunk_t data)
}
/**
+ * Implementation of rsa_public_key_t.eme_pkcs1_encrypt.
+ */
+static status_t pkcs1_encrypt(private_rsa_public_key_t *this,
+ chunk_t in, chunk_t *out)
+{
+ chunk_t em;
+ u_char *pos;
+ int padding = this->k - in.len - 3;
+
+ if (padding < 8)
+ {
+ DBG1("rsa padding of %d bytes is too small", padding);
+ return FAILED;
+ }
+ em.len = this->k;
+ em.ptr = pos = malloc(em.len);
+
+ /* add padding according to PKCS#1 7.2.1 1.+2. */
+ *pos++ = 0x00;
+ *pos++ = 0x02;
+
+ /* pad with pseudo random bytes unequal to zero */
+ {
+ randomizer_t *randomizer = randomizer_create();
+
+ /* pad with pseudo random bytes unequal to zero */
+ while (padding--)
+ {
+ randomizer->get_pseudo_random_bytes(randomizer, 1, pos);
+ while (!*pos)
+ {
+ randomizer->get_pseudo_random_bytes(randomizer, 1, pos);
+ }
+ pos++;
+ }
+ randomizer->destroy(randomizer);
+ }
+
+ /* append the padding terminator */
+ *pos++ = 0x00;
+
+ /* now add the data */
+ memcpy(pos, in.ptr, in.len);
+ *out = this->rsaep(this, em);
+ free(em.ptr);
+ return SUCCESS;
+}
+
+/**
* Implementation of rsa_public_key.verify_emsa_pkcs1_signature.
*/
static status_t verify_emsa_pkcs1_signature(const private_rsa_public_key_t *this,
@@ -297,19 +347,30 @@ static size_t get_keysize(const private_rsa_public_key_t *this)
*/
chunk_t rsa_public_key_info_to_asn1(const mpz_t n, const mpz_t e)
{
- chunk_t rawKey = asn1_wrap(ASN1_SEQUENCE, "mm",
+ chunk_t publicKey = asn1_wrap(ASN1_SEQUENCE, "mm",
asn1_integer_from_mpz(n),
asn1_integer_from_mpz(e));
- chunk_t publicKey;
- u_char *pos = build_asn1_object(&publicKey, ASN1_BIT_STRING, 1 + rawKey.len);
+ return asn1_wrap(ASN1_SEQUENCE, "cm",
+ asn1_algorithmIdentifier(OID_RSA_ENCRYPTION),
+ asn1_bitstring("m", publicKey));
+}
- *pos++ = 0x00;
- memcpy(pos, rawKey.ptr, rawKey.len);
- free(rawKey.ptr);
+/**
+ * Form the RSA keyid as a SHA-1 hash of a publicKeyInfo object
+ * Also used in rsa_private_key.c.
+ */
+chunk_t rsa_public_key_id_create(mpz_t n, mpz_t e)
+{
+ chunk_t keyid;
+ chunk_t publicKeyInfo = rsa_public_key_info_to_asn1(n, e);
+ hasher_t *hasher = hasher_create(HASH_SHA1);
+
+ hasher->allocate_hash(hasher, publicKeyInfo, &keyid);
+ hasher->destroy(hasher);
+ free(publicKeyInfo.ptr);
- return asn1_wrap(ASN1_SEQUENCE, "cm", ASN1_rsaEncryption_id,
- publicKey);
+ return keyid;
}
/**
@@ -328,6 +389,9 @@ static chunk_t get_keyid(const private_rsa_public_key_t *this)
return this->keyid;
}
+/* forward declaration used by rsa_public_key_t.clone */
+private_rsa_public_key_t *rsa_public_key_create_empty(void);
+
/**
* Implementation of rsa_public_key_t.clone.
*/
@@ -362,6 +426,7 @@ private_rsa_public_key_t *rsa_public_key_create_empty(void)
private_rsa_public_key_t *this = malloc_thing(private_rsa_public_key_t);
/* public functions */
+ this->public.pkcs1_encrypt = (status_t (*) (rsa_public_key_t*,chunk_t,chunk_t*))pkcs1_encrypt;
this->public.verify_emsa_pkcs1_signature = (status_t (*) (const rsa_public_key_t*,hash_algorithm_t,chunk_t,chunk_t))verify_emsa_pkcs1_signature;
this->public.get_modulus = (mpz_t *(*) (const rsa_public_key_t*))get_modulus;
this->public.get_keysize = (size_t (*) (const rsa_public_key_t*))get_keysize;
@@ -380,6 +445,20 @@ private_rsa_public_key_t *rsa_public_key_create_empty(void)
/*
* See header
*/
+rsa_public_key_t *rsa_public_key_create(mpz_t n, mpz_t e)
+{
+ private_rsa_public_key_t *this = rsa_public_key_create_empty();
+
+ mpz_init_set(this->n, n);
+ mpz_init_set(this->e, e);
+
+ this->k = (mpz_sizeinbase(n, 2) + 7) / BITS_PER_BYTE;
+ this->keyid = rsa_public_key_id_create(n, e);
+ return &this->public;
+}
+/*
+ * See header
+ */
rsa_public_key_t *rsa_public_key_create_from_chunk(chunk_t blob)
{
asn1_ctx_t ctx;
@@ -412,19 +491,9 @@ rsa_public_key_t *rsa_public_key_create_from_chunk(chunk_t blob)
}
objectID++;
}
-
- this->k = (mpz_sizeinbase(this->n, 2) + 7) / 8;
-
- /* form the keyid as a SHA-1 hash of a publicKeyInfo object */
- {
- chunk_t publicKeyInfo = rsa_public_key_info_to_asn1(this->n, this->e);
- hasher_t *hasher = hasher_create(HASH_SHA1);
-
- hasher->allocate_hash(hasher, publicKeyInfo, &this->keyid);
- hasher->destroy(hasher);
- free(publicKeyInfo.ptr);
- }
+ this->k = (mpz_sizeinbase(this->n, 2) + 7) / BITS_PER_BYTE;
+ this->keyid = rsa_public_key_id_create(this->n, this->e);
return &this->public;
}
diff --git a/src/libstrongswan/crypto/rsa/rsa_public_key.h b/src/libstrongswan/crypto/rsa/rsa_public_key.h
index 0a40c2204..c0bd3e351 100644
--- a/src/libstrongswan/crypto/rsa/rsa_public_key.h
+++ b/src/libstrongswan/crypto/rsa/rsa_public_key.h
@@ -6,8 +6,10 @@
*/
/*
- * Copyright (C) 2005-2006 Martin Willi
* Copyright (C) 2005 Jan Hutter
+ * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2007-2008 Andreas Steffen
+ *
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -20,7 +22,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * RCSID $Id: rsa_public_key.h 3303 2007-10-12 22:49:39Z andreas $
+ * RCSID $Id: rsa_public_key.h 3423 2008-01-22 10:32:37Z andreas $
*/
#ifndef RSA_PUBLIC_KEY_H_
@@ -40,20 +42,29 @@ typedef struct rsa_public_key_t rsa_public_key_t;
* the EMSA encoding (see PKCS1)
*
* @b Constructors:
+ * - rsa_public_key_create()
* - rsa_public_key_create_from_chunk()
* - rsa_public_key_create_from_file()
- * - rsa_private_key_t.get_public_key()
- *
- * @see rsa_private_key_t
- *
- * @todo Implement getkey() and savekey()
- *
+ *
* @ingroup rsa
*/
struct rsa_public_key_t {
/**
- * @brief Verify a EMSA-PKCS1 encodined signature.
+ * @brief Encrypt a data block using EME-PKCS1 encoding.
+ *
+ *
+ * @param this calling object
+ * @param data plaintext input data
+ * @param out encrypted output data
+ * @return
+ * - SUCCESS
+ * - FAILED if data block is too large
+ */
+ status_t (*pkcs1_encrypt) (rsa_public_key_t *this, chunk_t in, chunk_t *out);
+
+ /**
+ * @brief Verify an EMSA-PKCS1 encoded signature.
*
* Processes the supplied signature with the RSAVP1 function,
* selects the hash algorithm form the resultign ASN1-OID and
@@ -123,6 +134,17 @@ struct rsa_public_key_t {
};
/**
+ * @brief Create a RSA public key from modulus and public exponent.
+ *
+ * @param n modulus
+ * @param e public exponent
+ * @return created rsa_public_key_t
+ *
+ * @ingroup rsa
+ */
+rsa_public_key_t *rsa_public_key_create(mpz_t n, mpz_t e);
+
+/**
* @brief Load an RSA public key from a chunk.
*
* Load a key from a chunk, encoded in the more frequently
diff --git a/src/libstrongswan/crypto/x509.c b/src/libstrongswan/crypto/x509.c
index 6f154b36f..eadf11327 100755
--- a/src/libstrongswan/crypto/x509.c
+++ b/src/libstrongswan/crypto/x509.c
@@ -9,8 +9,8 @@
* Copyright (C) 2000 Andreas Hess, Patric Lichtsteiner, Roger Wegmann
* Copyright (C) 2001 Marco Bertossa, Andreas Schleiss
* Copyright (C) 2002 Mario Strasser
- * Copyright (C) 2000-2004 Andreas Steffen, Zuercher Hochschule Winterthur
- * Copyright (C) 2006 Martin Willi, Andreas Steffen
+ * Copyright (C) 2006 Martin Willi
+ * Copyright (C) 2000-2008 Andreas Steffen
*
* Hochschule fuer Technik Rapperswil
*
@@ -24,7 +24,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * RCSID $Id: x509.c 3355 2007-11-20 12:06:40Z martin $
+ * RCSID $Id: x509.c 3423 2008-01-22 10:32:37Z andreas $
*/
#include <gmp.h>
@@ -514,7 +514,7 @@ static identification_t *parse_generalName(chunk_t blob, int level0)
id_type = ID_DER_ASN1_DN;
break;
case GN_OBJ_IP_ADDRESS:
- id_type = ID_IPV4_ADDR;
+ id_type = (object.len == 4)? ID_IPV4_ADDR : ID_IPV6_ADDR;
break;
case GN_OBJ_OTHER_NAME:
if (!parse_otherName(object, level + 1))
@@ -1243,6 +1243,22 @@ static void list(private_x509_t *this, FILE *out, bool utc)
}
}
+/**
+ * Implements x509_t.add_subjectAltNames.
+ */
+static void add_subjectAltNames(private_x509_t *this, linked_list_t *subjectAltNames)
+{
+ iterator_t *iterator = subjectAltNames->create_iterator(subjectAltNames, TRUE);
+ identification_t *name = NULL;
+
+ while (iterator->iterate(iterator, (void**)&name))
+ {
+ name = name->clone(name);
+ this->subjectAltNames->insert_last(this->subjectAltNames, (void*)name);
+ }
+ iterator->destroy(iterator);
+}
+
/*
* Defined in header.
*/
@@ -1251,12 +1267,13 @@ chunk_t x509_build_generalNames(linked_list_t *list)
linked_list_t *generalNames = linked_list_create();
iterator_t *iterator = list->create_iterator(list, TRUE);
identification_t *name;
+ chunk_t names = chunk_empty;
size_t len = 0;
while (iterator->iterate(iterator, (void**)&name))
{
asn1_t asn1_type = ASN1_EOC;
- chunk_t *generalName = malloc_thing(chunk_t);
+ chunk_t *generalName;
switch (name->get_type(name))
{
@@ -1273,22 +1290,24 @@ chunk_t x509_build_generalNames(linked_list_t *list)
asn1_type = ASN1_CONTEXT_S_6;
break;
case ID_IPV4_ADDR:
+ case ID_IPV6_ADDR:
asn1_type = ASN1_CONTEXT_S_7;
break;
default:
continue;
}
+ generalName = malloc_thing(chunk_t);
*generalName = asn1_simple_object(asn1_type, name->get_encoding(name));
len += generalName->len;
- generalNames->insert_last(generalNames, generalName);
+ generalNames->insert_last(generalNames, (void*)generalName);
}
iterator->destroy(iterator);
if (len > 0)
{
iterator_t *iterator = generalNames->create_iterator(generalNames, TRUE);
- chunk_t names, *generalName;
+ chunk_t *generalName;
u_char *pos = build_asn1_object(&names, ASN1_SEQUENCE, len);
while (iterator->iterate(iterator, (void**)&generalName))
@@ -1299,14 +1318,9 @@ chunk_t x509_build_generalNames(linked_list_t *list)
free(generalName);
}
iterator->destroy(iterator);
- generalNames->destroy(generalNames);
-
- return asn1_wrap(ASN1_OCTET_STRING, "m", names);
- }
- else
- {
- return chunk_empty;
}
+ generalNames->destroy(generalNames);
+ return names;
}
/*
@@ -1330,11 +1344,54 @@ chunk_t x509_build_subjectAltNames(linked_list_t *list)
}
/**
+ * Build a to-be-signed X.509 certificate body
+ */
+static chunk_t x509_build_tbs(private_x509_t *this)
+{
+ /* version is always X.509v3 */
+ chunk_t version = asn1_simple_object(ASN1_CONTEXT_C_0, ASN1_INTEGER_2);
+
+ chunk_t extensions = chunk_empty;
+
+ if (this->subjectAltNames->get_count(this->subjectAltNames))
+ {
+ extensions = asn1_wrap(ASN1_CONTEXT_C_3, "m",
+ asn1_wrap(ASN1_SEQUENCE, "m",
+ x509_build_subjectAltNames(this->subjectAltNames)));
+ }
+
+ return asn1_wrap(ASN1_SEQUENCE, "mmccmcmm",
+ version,
+ asn1_simple_object(ASN1_INTEGER, this->serialNumber),
+ asn1_algorithmIdentifier(this->signatureAlgorithm),
+ this->issuer->get_encoding(this->issuer),
+ asn1_wrap(ASN1_SEQUENCE, "mm",
+ timetoasn1(&this->notBefore, ASN1_UTCTIME),
+ timetoasn1(&this->notAfter, ASN1_UTCTIME)
+ ),
+ this->subject->get_encoding(this->subject),
+ this->public_key->get_publicKeyInfo(this->public_key),
+ extensions
+ );
+}
+
+/**
* Implementation of x509_t.build_encoding.
*/
static void build_encoding(private_x509_t *this, hash_algorithm_t alg,
rsa_private_key_t *private_key)
{
+ chunk_t signature;
+
+ this->signatureAlgorithm = hasher_signature_algorithm_to_oid(alg);
+ this->tbsCertificate = x509_build_tbs(this);
+ private_key->build_emsa_pkcs1_signature(private_key, alg,
+ this->tbsCertificate, &signature);
+ this->signature = asn1_bitstring("m", signature);
+ this->certificate = asn1_wrap(ASN1_SEQUENCE, "mcm",
+ this->tbsCertificate,
+ asn1_algorithmIdentifier(this->signatureAlgorithm),
+ this->signature);
}
@@ -1408,6 +1465,7 @@ static private_x509_t *x509_create_empty(void)
this->public.create_ocspuri_iterator = (iterator_t* (*) (const x509_t*))create_ocspuri_iterator;
this->public.verify = (bool (*) (const x509_t*,const rsa_public_key_t*))verify;
this->public.list = (void (*) (x509_t*, FILE *out, bool utc))list;
+ this->public.add_subjectAltNames = (void (*) (x509_t*,linked_list_t*))add_subjectAltNames;
this->public.build_encoding = (void (*) (x509_t*,hash_algorithm_t,rsa_private_key_t*))build_encoding;
this->public.destroy = (void (*) (x509_t*))destroy;
@@ -1417,13 +1475,19 @@ static private_x509_t *x509_create_empty(void)
/*
* Described in header.
*/
-x509_t *x509_create_(chunk_t serialNumber, identification_t *issuer, identification_t *subject)
+x509_t *x509_create(chunk_t serialNumber, identification_t *issuer,
+ time_t notBefore, time_t notAfter,
+ identification_t *subject,
+ rsa_public_key_t *public_key)
{
private_x509_t *this = x509_create_empty();
this->serialNumber = serialNumber;
this->issuer = issuer->clone(issuer);
+ this->notBefore = notBefore;
+ this->notAfter = notAfter;
this->subject = subject->clone(subject);
+ this->public_key = public_key->clone(public_key);
return &this->public;
}
diff --git a/src/libstrongswan/crypto/x509.h b/src/libstrongswan/crypto/x509.h
index 1ab267dac..def45be6b 100755
--- a/src/libstrongswan/crypto/x509.h
+++ b/src/libstrongswan/crypto/x509.h
@@ -9,8 +9,8 @@
* Copyright (C) 2000 Andreas Hess, Patric Lichtsteiner, Roger Wegmann
* Copyright (C) 2001 Marco Bertossa, Andreas Schleiss
* Copyright (C) 2002 Mario Strasser
- * Copyright (C) 2000-2004 Andreas Steffen, Zuercher Hochschule Winterthur
- * Copyright (C) 2006 Martin Willi, Andreas Steffen
+ * Copyright (C) 2006 Martin Willi
+ * Copyright (C) 2000-2008 Andreas Steffen
*
* Hochschule fuer Technik Rapperswil
*
@@ -24,7 +24,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * RCSID $Id: x509.h 3301 2007-10-12 21:56:30Z andreas $
+ * RCSID $Id: x509.h 3421 2008-01-22 01:09:19Z andreas $
*/
#ifndef X509_H_
@@ -327,6 +327,7 @@ struct x509_t {
* @param notBefore start date of validity
* @param notAfter end date of validity
* @param subject subject distinguished name
+ * @param public_key public key
*
* @return created x509_t certificate, or NULL if invalid.
*
@@ -334,7 +335,8 @@ struct x509_t {
*/
x509_t *x509_create(chunk_t serialNumber, identification_t *issuer,
time_t notBefore, time_t notAfter,
- identification_t *subject);
+ identification_t *subject,
+ rsa_public_key_t *public_key);
/**
* @brief Read a X.509 certificate from a DER encoded blob.
diff --git a/src/libstrongswan/utils/linked_list.c b/src/libstrongswan/utils/linked_list.c
index 5cd8ffd7a..63e1bcfbf 100644
--- a/src/libstrongswan/utils/linked_list.c
+++ b/src/libstrongswan/utils/linked_list.c
@@ -677,6 +677,52 @@ static status_t get_last(private_linked_list_t *this, void **item)
}
/**
+ * Implementation of linked_list_t.find_first.
+ */
+static status_t find_first(private_linked_list_t *this, linked_list_match_t match,
+ void **item, void *d1, void *d2, void *d3, void *d4, void *d5)
+{
+ element_t *current = this->first;
+
+ while (current)
+ {
+ if (match(current->value, d1, d2, d3, d4, d5))
+ {
+ if (item != NULL)
+ {
+ *item = current->value;
+ }
+ return SUCCESS;
+ }
+ current = current->next;
+ }
+ return NOT_FOUND;
+}
+
+/**
+ * Implementation of linked_list_t.find_last.
+ */
+static status_t find_last(private_linked_list_t *this, linked_list_match_t match,
+ void **item, void *d1, void *d2, void *d3, void *d4, void *d5)
+{
+ element_t *current = this->last;
+
+ while (current)
+ {
+ if (match(current->value, d1, d2, d3, d4, d5))
+ {
+ if (item != NULL)
+ {
+ *item = current->value;
+ }
+ return SUCCESS;
+ }
+ current = current->previous;
+ }
+ return NOT_FOUND;
+}
+
+/**
* Implementation of linked_list_t.invoke_offset.
*/
static void invoke_offset(private_linked_list_t *this, size_t offset)
@@ -843,6 +889,8 @@ linked_list_t *linked_list_create()
this->public.create_enumerator = (enumerator_t*(*)(linked_list_t*))create_enumerator;
this->public.get_first = (status_t (*) (linked_list_t *, void **item))get_first;
this->public.get_last = (status_t (*) (linked_list_t *, void **item))get_last;
+ this->public.find_first = (status_t (*) (linked_list_t *, linked_list_match_t,void**,...))find_first;
+ this->public.find_last = (status_t (*) (linked_list_t *, linked_list_match_t,void**,...))find_last;
this->public.insert_first = (void (*) (linked_list_t *, void *item))insert_first;
this->public.insert_last = (void (*) (linked_list_t *, void *item))insert_last;
this->public.remove_first = (status_t (*) (linked_list_t *, void **item))remove_first;
diff --git a/src/libstrongswan/utils/linked_list.h b/src/libstrongswan/utils/linked_list.h
index ebe5c187c..ac36ef46d 100644
--- a/src/libstrongswan/utils/linked_list.h
+++ b/src/libstrongswan/utils/linked_list.h
@@ -33,6 +33,19 @@ typedef struct linked_list_t linked_list_t;
#include <utils/iterator.h>
#include <utils/enumerator.h>
+
+/**
+ * Method to match elements in a linked list (used in find_* functions)
+ *
+ * @param item current list item
+ * @param ... user supplied data (only pointers, at most 5)
+ * @return
+ * - TRUE, if the item matched
+ * - FALSE, otherwise
+ * @ingroup utils
+ */
+typedef bool (*linked_list_match_t)(void *item, ...);
+
/**
* @brief Class implementing a double linked list.
*
@@ -187,6 +200,50 @@ struct linked_list_t {
*/
status_t (*get_last) (linked_list_t *this, void **item);
+ /** @brief Find the first matching element in the list.
+ *
+ * The first object passed to the match function is the current list item,
+ * followed by the user supplied data.
+ * If the supplied function returns TRUE this function returns SUCCESS, and
+ * the current object is returned in the third parameter, otherwise,
+ * the next item is checked.
+ *
+ * @warning Only use pointers as user supplied data.
+ *
+ * @param this calling object
+ * @param match comparison function to call on each object
+ * @param[out] item
+ * - the list item, if found
+ * - NULL, otherwise
+ * @param ... user data to supply to match function (limited to 5 arguments)
+ * @return
+ * - SUCCESS, if found
+ * - NOT_FOUND, otherwise
+ */
+ status_t (*find_first) (linked_list_t *this, linked_list_match_t match, void **item, ...);
+
+ /** @brief Find the last matching element in the list.
+ *
+ * The first object passed to the match function is the current list item,
+ * followed by the user supplied data.
+ * If the supplied function returns TRUE this function returns SUCCESS, and
+ * the current object is returned in the third parameter, otherwise,
+ * the next item is checked.
+ *
+ * @warning Only use pointers as user supplied data.
+ *
+ * @param this calling object
+ * @param match comparison function to call on each object
+ * @param[out] item
+ * - the list item, if found
+ * - NULL, otherwise
+ * @param ... user data to supply to match function (limited to 5 arguments)
+ * @return
+ * - SUCCESS, if found
+ * - NOT_FOUND, otherwise
+ */
+ status_t (*find_last) (linked_list_t *this, linked_list_match_t match, void **item, ...);
+
/**
* @brief Invoke a method on all of the contained objects.
*
diff --git a/src/libstrongswan/utils/optionsfrom.c b/src/libstrongswan/utils/optionsfrom.c
index ffa571b05..39e38cc58 100644
--- a/src/libstrongswan/utils/optionsfrom.c
+++ b/src/libstrongswan/utils/optionsfrom.c
@@ -6,8 +6,10 @@
*/
/*
- * Copyright (C) 1998, 1999 Henry Spencer.
- *
+ * Copyright (C) 2007-2008 Andreas Steffen
+ *
+ * Hochschule fuer Technik Rapperswil
+ *
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Library General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at your
@@ -18,6 +20,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
* License for more details.
*
+ * RCSID $Id$
*/
#include <stdio.h>
@@ -30,29 +33,64 @@
#include "optionsfrom.h"
#define MAX_USES 20 /* loop-detection limit */
-#define SOME_ARGS 10 /* first guess at how many arguments we'll need */
+#define MORE_ARGS 10 /* first guess at how many arguments we'll need */
/*
* Defined in header.
*/
-bool optionsfrom(const char *filename, int *argcp, char **argvp[], int optind)
-{
- static int nuses = 0;
+
+typedef struct private_options_t private_options_t;
+
+/**
+ * Private data of a options_t object.
+ */
+struct private_options_t {
+ /**
+ * Public interface
+ */
+ options_t public;
+
+ /**
+ * reallocated argv array
+ */
char **newargv;
+
+ /**
+ * number of free arguments in newargv
+ */
+ int room;
+
+ /**
+ * number of included option files
+ */
+ int nuses;
+
+ /**
+ * allocated space for option files
+ */
+ char *buffers[MAX_USES];
+};
+
+/**
+ * Defined in header
+ */
+bool from(private_options_t *this, char *filename, int *argcp, char **argvp[],
+ int optind)
+{
int newargc;
int next; /* place for next argument */
- int room; /* how many more new arguments we can hold */
+ char **newargv;
size_t bytes;
- chunk_t chunk, src, line, token;
+ chunk_t src, line, token;
bool good = TRUE;
int linepos = 0;
FILE *fd;
/* avoid endless loops with recursive --optionsfrom arguments */
- nuses++;
- if (nuses >= MAX_USES)
+ this->nuses++;
+ if (this->nuses >= MAX_USES)
{
- DBG1("optionsfrom called %d times - looping?", (*argvp)[0], nuses);
+ DBG1("optionsfrom called %d times by \"%s\" - looping?", this->nuses + 1, (*argvp)[0]);
return FALSE;
}
@@ -66,26 +104,31 @@ bool optionsfrom(const char *filename, int *argcp, char **argvp[], int optind)
/* determine the file size */
fseek(fd, 0, SEEK_END);
- chunk.len = ftell(fd);
+ src.len = ftell(fd);
rewind(fd);
/* allocate one byte more just in case of a missing final newline */
- chunk.ptr = malloc(chunk.len + 1);
+ src.ptr = this->buffers[this->nuses] = malloc(src.len + 1);
/* read the whole file into a chunk */
- bytes = fread(chunk.ptr, 1, chunk.len, fd);
+ bytes = fread(src.ptr, 1, src.len, fd);
fclose(fd);
- newargc = *argcp + SOME_ARGS;
- newargv = malloc((newargc + 1) * sizeof(char *));
+ if (this->room)
+ {
+ newargc = *argcp;
+ newargv = malloc((newargc + 1 + this->room) * sizeof(char *));
+ }
+ else
+ {
+ newargc = *argcp + MORE_ARGS;
+ this->room = MORE_ARGS;
+ newargv = malloc((newargc + 1) * sizeof(char *));
+ }
memcpy(newargv, *argvp, optind * sizeof(char *));
- room = SOME_ARGS;
next = optind;
newargv[next] = NULL;
- /* we keep the chunk pointer so that we can still free it */
- src = chunk;
-
while (fetchline(&src, &line) && good)
{
linepos++;
@@ -116,11 +159,11 @@ bool optionsfrom(const char *filename, int *argcp, char **argvp[], int optind)
}
/* do we have to allocate more memory for additional arguments? */
- if (room == 0)
+ if (this->room == 0)
{
- newargc += SOME_ARGS;
- newargv = realloc(newargv, (newargc+1) * sizeof(char *));
- room = SOME_ARGS;
+ newargc += MORE_ARGS;
+ newargv = realloc(newargv, (newargc + 1) * sizeof(char *));
+ this->room = MORE_ARGS;
}
/* terminate the token by replacing the delimiter with a null character */
@@ -129,20 +172,54 @@ bool optionsfrom(const char *filename, int *argcp, char **argvp[], int optind)
/* assign the token to the next argument */
newargv[next] = token.ptr;
next++;
- room--;
+ this->room--;
}
}
- if (!good) /* error of some kind */
+ /* assign newargv to argv */
+ if (good)
{
- free(chunk.ptr);
- free(newargv);
- return FALSE;
+ memcpy(newargv + next, *argvp + optind, (*argcp + 1 - optind) * sizeof(char *));
+ *argcp += next - optind;
+ *argvp = newargv;
}
- memcpy(newargv + next, *argvp + optind, (*argcp + 1 - optind) * sizeof(char *));
- *argcp += next - optind;
- *argvp = newargv;
- return TRUE;
+ /* keep a pointer to the latest newargv and free any earlier version */
+ free(this->newargv);
+ this->newargv = newargv;
+
+ return good;
+}
+
+/**
+ * Defined in header
+ */
+void destroy(private_options_t *this)
+{
+ while (this->nuses >= 0)
+ {
+ free(this->buffers[this->nuses--]);
+ }
+ free(this->newargv);
+ free(this);
}
+/*
+ * Defined in header
+ */
+options_t *options_create(void)
+{
+ private_options_t *this = malloc_thing(private_options_t);
+
+ /* initialize */
+ this->newargv = NULL;
+ this->room = 0;
+ this->nuses = -1;
+ memset(this->buffers, '\0', MAX_USES);
+
+ /* public functions */
+ this->public.from = (bool (*) (options_t*,char*,int*,char***,int))from;
+ this->public.destroy = (void (*) (options_t*))destroy;
+
+ return &this->public;
+}
diff --git a/src/libstrongswan/utils/optionsfrom.h b/src/libstrongswan/utils/optionsfrom.h
index d6b9efde5..0014cec36 100644
--- a/src/libstrongswan/utils/optionsfrom.h
+++ b/src/libstrongswan/utils/optionsfrom.h
@@ -6,8 +6,9 @@
*/
/*
- * Copyright (C) 1998, 1999 Henry Spencer.
- * Copyright (C) 2007 Andreas Steffen, Hochschule fuer Technik Rapperswil
+ * Copyright (C) 2007-2008 Andreas Steffen
+ *
+ * Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -18,20 +19,51 @@
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
+ *
+ * RCSID $Id$
*/
#ifndef OPTIONSFROM_H_
#define OPTIONSFROM_H_
+typedef struct options_t options_t;
+
/**
- * @brief Pick up more options from a file, in the middle of an option scan
+ * @brief options object.
*
- * @param filename file containing the options
- * @param argcp pointer to argc
- * @param argvp pointer to argv[]
- * @param optind current optind, number of next argument
- * @return TRUE if optionsfrom parsing successful
+ * @b Constructors:
+ * - options_create()
+ *
+ * @ingroup utils
+ */
+struct options_t {
+ /**
+ * @brief Check if the PKCS#7 contentType is data
+ *
+ * @param this calling object
+ * @param filename file containing the options
+ * @param argcp pointer to argc
+ * @param argvp pointer to argv[]
+ * @param optind current optind, number of next argument
+ * @return TRUE if optionsfrom parsing successful
+ */
+ bool (*from) (options_t * this, char *filename, int *argcp, char **argvp[], int optind);
+
+ /**
+ * @brief Destroys the options_t object.
+ *
+ * @param this options_t object to destroy
+ */
+ void (*destroy) (options_t *this);
+};
+
+/**
+ * @brief Create an options object.
+ *
+ * @return created options_t object
+ *
+ * @ingroup utils
*/
-bool optionsfrom(const char *filename, int *argcp, char **argvp[], int optind);
+options_t *options_create(void);
#endif /*OPTIONSFROM_H_*/