added x509_build_generalNames() and x509_build_subjectAltNames() functions
authorAndreas Steffen <andreas.steffen@strongswan.org>
Fri, 12 Oct 2007 21:56:30 +0000 (21:56 -0000)
committerAndreas Steffen <andreas.steffen@strongswan.org>
Fri, 12 Oct 2007 21:56:30 +0000 (21:56 -0000)
src/libstrongswan/crypto/x509.c
src/libstrongswan/crypto/x509.h

index e8f5823..4317810 100755 (executable)
@@ -116,7 +116,7 @@ struct private_x509_t {
        /**
         * Signature algorithm
         */
-       int sigAlg;
+       int signatureAlgorithm;
        
        /**
         * ID representing the certificate issuer
@@ -199,11 +199,6 @@ struct private_x509_t {
        bool isOcspSigner;
 
        /**
-        * Signature algorithm (must be identical to sigAlg)
-        */
-       int algorithm;
-
-       /**
         * Signature
         */
        chunk_t signature;
@@ -447,11 +442,10 @@ static bool parse_basicConstraints(chunk_t blob, int level0)
        return isCA;
 }
 
-/*
+/**
  * extracts an otherName
  */
-static bool
-parse_otherName(chunk_t blob, int level0)
+static bool parse_otherName(chunk_t blob, int level0)
 {
        asn1_ctx_t ctx;
        chunk_t object;
@@ -486,7 +480,7 @@ parse_otherName(chunk_t blob, int level0)
        return TRUE;
 }
 
-/*
+/**
  * extracts a generalName
  */
 static identification_t *parse_generalName(chunk_t blob, int level0)
@@ -546,10 +540,10 @@ static identification_t *parse_generalName(chunk_t blob, int level0)
 }
 
 
-/**
- * extracts one or several GNs and puts them into a chained list
+/*
+ * Defined in header.
  */
-void parse_generalNames(chunk_t blob, int level0, bool implicit, linked_list_t *list)
+void x509_parse_generalNames(chunk_t blob, int level0, bool implicit, linked_list_t *list)
 {
        asn1_ctx_t ctx;
        chunk_t object;
@@ -591,10 +585,10 @@ static chunk_t parse_keyIdentifier(chunk_t blob, int level0, bool implicit)
        return object;
 }
 
-/**
- * extracts an authoritykeyIdentifier
+/*
+ * Defined in header.
  */
-void parse_authorityKeyIdentifier(chunk_t blob, int level0 , chunk_t *authKeyID, chunk_t *authKeySerialNumber)
+void x509_parse_authorityKeyIdentifier(chunk_t blob, int level0 , chunk_t *authKeyID, chunk_t *authKeySerialNumber)
 {
        asn1_ctx_t ctx;
        chunk_t object;
@@ -743,7 +737,7 @@ static void parse_crlDistributionPoints(chunk_t blob, int level0, linked_list_t
                if (objectID == CRL_DIST_POINTS_FULLNAME)
                {
                        /* append extracted generalNames to existing chained list */
-                       parse_generalNames(object, level+1, TRUE, list);
+                       x509_parse_generalNames(object, level+1, TRUE, list);
 
                }
                objectID++;
@@ -790,7 +784,7 @@ static bool parse_certificate(chunk_t blob, u_int level0, private_x509_t *this)
                                this->serialNumber = object;
                                break;
                        case X509_OBJ_SIG_ALG:
-                               this->sigAlg = parse_algorithmIdentifier(object, level, NULL);
+                               this->signatureAlgorithm = parse_algorithmIdentifier(object, level, NULL);
                                break;
                        case X509_OBJ_ISSUER:
                                this->issuer = identification_create_from_encoding(ID_DER_ASN1_DN, object);
@@ -843,7 +837,7 @@ static bool parse_certificate(chunk_t blob, u_int level0, private_x509_t *this)
                                                this->subjectKeyID = chunk_clone(parse_keyIdentifier(object, level, FALSE));
                                                break;
                                        case OID_SUBJECT_ALT_NAME:
-                                               parse_generalNames(object, level, FALSE, this->subjectAltNames);
+                                               x509_parse_generalNames(object, level, FALSE, this->subjectAltNames);
                                                break;
                                        case OID_BASIC_CONSTRAINTS:
                                                this->isCA = parse_basicConstraints(object, level);
@@ -852,7 +846,8 @@ static bool parse_certificate(chunk_t blob, u_int level0, private_x509_t *this)
                                                parse_crlDistributionPoints(object, level, this->crlDistributionPoints);
                                                break;
                                        case OID_AUTHORITY_KEY_ID:
-                                               parse_authorityKeyIdentifier(object, level , &this->authKeyID, &this->authKeySerialNumber);
+                                               x509_parse_authorityKeyIdentifier(object, level,
+                                                        &this->authKeyID, &this->authKeySerialNumber);
                                                break;
                                        case OID_AUTHORITY_INFO_ACCESS:
                                                parse_authorityInfoAccess(object, level, this->ocspAccessLocations);
@@ -873,11 +868,14 @@ static bool parse_certificate(chunk_t blob, u_int level0, private_x509_t *this)
                                break;
                        }
                        case X509_OBJ_ALGORITHM:
-                               this->algorithm = parse_algorithmIdentifier(object, level, NULL);
-                               if (this->algorithm != this->sigAlg)
                                {
-                                       DBG1("  signature algorithms do not agree");
-                                       return FALSE;
+                                       int alg = parse_algorithmIdentifier(object, level, NULL);
+
+                                       if (alg != this->signatureAlgorithm)
+                                       {
+                                               DBG1("  signature algorithms do not agree");
+                                               return FALSE;
+                                       }
                                }
                                break;
                        case X509_OBJ_SIGNATURE:
@@ -1136,7 +1134,7 @@ static iterator_t *create_ocspuri_iterator(const private_x509_t *this)
  */
 static bool verify(const private_x509_t *this, const rsa_public_key_t *signer)
 {
-       hash_algorithm_t algorithm = hasher_algorithm_from_oid(this->algorithm);
+       hash_algorithm_t algorithm = hasher_algorithm_from_oid(this->signatureAlgorithm);
 
        if (algorithm == HASH_UNKNOWN)
        {
@@ -1245,6 +1243,101 @@ static void list(private_x509_t *this, FILE *out, bool utc)
        }
 }
 
+/*
+ * Defined in header.
+ */
+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;
+       size_t len = 0;
+
+       while (iterator->iterate(iterator, (void**)&name))
+       {
+               asn1_t asn1_type = ASN1_EOC;
+               chunk_t *generalName = malloc_thing(chunk_t);
+
+               switch (name->get_type(name))
+               {
+                       case ID_RFC822_ADDR:
+                               asn1_type = ASN1_CONTEXT_S_1;
+                               break;
+                       case ID_FQDN:
+                               asn1_type = ASN1_CONTEXT_S_2;
+                               break;
+                       case ID_DER_ASN1_DN:
+                               asn1_type = ASN1_CONTEXT_C_4;
+                       break;
+                       case ID_DER_ASN1_GN_URI:
+                               asn1_type = ASN1_CONTEXT_S_6;
+                               break;
+                       case ID_IPV4_ADDR:
+                               asn1_type = ASN1_CONTEXT_S_7;
+                               break;
+                       default:
+                               continue;
+               }
+
+               *generalName = asn1_simple_object(asn1_type, name->get_encoding(name));
+               len += generalName->len;
+               generalNames->insert_last(generalNames, generalName);
+       }
+       iterator->destroy(iterator);
+
+       if (len > 0)
+       {
+               iterator_t *iterator = generalNames->create_iterator(generalNames, TRUE);
+               chunk_t names, *generalName;
+               u_char *pos = build_asn1_object(&names, ASN1_SEQUENCE, len);
+
+               while (iterator->iterate(iterator, (void**)&generalName))
+               {
+                       memcpy(pos, generalName->ptr, generalName->len);
+                       pos += generalName->len;
+                       free(generalName->ptr);
+                       free(generalName);
+               }
+               iterator->destroy(iterator);
+               generalNames->destroy(generalNames);
+
+               return asn1_wrap(ASN1_OCTET_STRING, "m", names);
+       }
+       else
+       {
+               return chunk_empty;
+       }
+}
+
+/*
+ * Defined in header.
+ */
+chunk_t x509_build_subjectAltNames(linked_list_t *list)
+{
+       chunk_t generalNames = x509_build_generalNames(list);
+
+       if (generalNames.len)
+       {
+               return asn1_wrap(ASN1_SEQUENCE, "cm",
+                                       ASN1_subjectAltName_oid,
+                                       asn1_wrap(ASN1_OCTET_STRING, "m", generalNames)
+                               );
+       }
+       else
+       {
+               return chunk_empty;
+       }
+}
+
+/**
+ * Implementation of x509_t.build_encoding.
+ */
+static void build_encoding(private_x509_t *this, hash_algorithm_t alg,
+                                                  rsa_private_key_t *private_key)
+{
+
+}
+
 /**
  * Implements x509_t.destroy
  */
@@ -1314,7 +1407,8 @@ static private_x509_t *x509_create_empty(void)
        this->public.create_crluri_iterator = (iterator_t* (*) (const x509_t*))create_crluri_iterator;
        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.list = (void (*) (x509_t*, FILE *out, bool utc))list;
+       this->public.build_encoding = (void (*) (x509_t*,hash_algorithm_t,rsa_private_key_t*))build_encoding;
        this->public.destroy = (void (*) (x509_t*))destroy;
        
        return this;
@@ -1362,7 +1456,7 @@ x509_t *x509_create_from_chunk(chunk_t chunk, u_int level)
        this->isSelfSigned = FALSE;
        if (this->subject->equals(this->subject, this->issuer))
        {
-               hash_algorithm_t algorithm = hasher_algorithm_from_oid(this->algorithm);
+               hash_algorithm_t algorithm = hasher_algorithm_from_oid(this->signatureAlgorithm);
 
                if (algorithm == HASH_UNKNOWN)
                {
index ffb90de..c97214d 100755 (executable)
@@ -33,7 +33,8 @@
 typedef struct x509_t x509_t;
 
 #include <library.h>
-#include <crypto/rsa/rsa_public_key.h>
+#include <crypto/rsa/rsa_private_key.h>
+#include <crypto/hashers/hasher.h>
 #include <crypto/certinfo.h>
 #include <crypto/ca.h>
 #include <utils/identification.h>
@@ -51,6 +52,7 @@ typedef struct x509_t x509_t;
  * @brief X.509 certificate.
  * 
  * @b Constructors:
+ *  - x509_create()
  *  - x509_create_from_chunk()
  *  - x509_create_from_file()
  *
@@ -290,9 +292,26 @@ struct x509_t {
         * @param out                   stream to write to
         * @param utc                   TRUE for UTC times, FALSE for local time
         */
-       void (*list)(x509_t *this, FILE *out, bool utc);
+       void (*list) (x509_t *this, FILE *out, bool utc);
        
        /**
+        * @brief Adds a list of subjectAltNames
+        * 
+        * @param this                          calling object
+        * @param subjectAltNames       list of subjectAltNames to be added
+        */
+       void (*add_subjectAltNames) (x509_t *this, linked_list_t *subjectAltNames);
+
+       /**
+        * @brief Builds a DER-encoded signed X.509 certificate
+        * 
+        * @param this                  calling object
+        * @param alg                   hash algorithm used to compute the certificate digest
+        * @param private_key   RSA private key used to sign the certificate digest
+        */
+       void (*build_encoding) (x509_t *this, hash_algorithm_t alg, rsa_private_key_t *private_key);
+
+       /**
         * @brief Destroys the certificate.
         * 
         * @param this                  certificate to destroy
@@ -348,7 +367,7 @@ x509_t *x509_create_from_file(const char *filename, const char *label);
  * 
  * @ingroup crypto
  */
-void parse_authorityKeyIdentifier(chunk_t blob, int level0, chunk_t *authKeyID, chunk_t *authKeySerialNumber);
+void x509_parse_authorityKeyIdentifier(chunk_t blob, int level0, chunk_t *authKeyID, chunk_t *authKeySerialNumber);
 
 /**
  * @brief Parses DER encoded generalNames
@@ -356,10 +375,30 @@ void parse_authorityKeyIdentifier(chunk_t blob, int level0, chunk_t *authKeyID,
  * @param blob                         blob containing DER encoded data
  * @param level0               indicates the current parsing level
  * @param implicit             implicit coding is used
- * @param list                 linked list of decoded generalNames
+ * @param list                 list of decoded generalNames
+ * 
+ * @ingroup crypto
+ */
+void x509_parse_generalNames(chunk_t blob, int level0, bool implicit, linked_list_t *list);
+
+/**
+ * @brief Builds a DER encoded list of generalNames
+ * 
+ * @param list                 list of generalNames to be encoded
+ * @return                             DER encoded list of generalNames
+ * 
+ * @ingroup crypto
+ */
+chunk_t x509_build_generalNames(linked_list_t *list);
+
+/**
+ * @brief Builds a DER encoded list of subjectAltNames
+ * 
+ * @param list                 list of subjectAltNames to be encoded
+ * @return                             DER encoded list of subjectAltNames
  * 
  * @ingroup crypto
  */
-void parse_generalNames(chunk_t blob, int level0, bool implicit, linked_list_t *list);
+chunk_t x509_build_subjectAltNames(linked_list_t *list);
 
 #endif /* X509_H_ */