hooray, pluto and scepclient do not depend on libgmp anymore
[strongswan.git] / src / scepclient / pkcs10.c
index de3f06e..cdd6843 100644 (file)
 #include <arpa/inet.h>
 
 #include <freeswan.h>
+#include <asn1/asn1.h>
+#include <asn1/oid.h>
 
 #include "../pluto/constants.h"
 #include "../pluto/defs.h"
-#include "../pluto/oid.h"
-#include "../pluto/asn1.h"
-#include "../pluto/pkcs1.h"
 #include "../pluto/log.h"
 #include "../pluto/x509.h"
 
 /* some pre-coded OIDs */
 
 static u_char ASN1_challengePassword_oid_str[] = {
-    0x06,0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x07
+       0x06,0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x07
 };
 
-static const chunk_t ASN1_challengePassword_oid = strchunk(ASN1_challengePassword_oid_str);
+static const chunk_t ASN1_challengePassword_oid = chunk_from_buf(ASN1_challengePassword_oid_str);
 
 static u_char ASN1_extensionRequest_oid_str[] = {
-    0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x0E
+       0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x0E
 };
 
-static const chunk_t ASN1_extensionRequest_oid = strchunk(ASN1_extensionRequest_oid_str);
+static const chunk_t ASN1_extensionRequest_oid = chunk_from_buf(ASN1_extensionRequest_oid_str);
 
 /** 
  * @brief Adds a subjectAltName in DER-coded form to a linked list
  * 
- * @param[in,out]      subjectAltNames head of the linked list of subjectAltNames
- * @param[in]          kind            type of the subjectAltName (which is a generalName)
- * @param[in]          value           value of the subjectAltName as an ASCII string
+ * @param[in,out]       subjectAltNames head of the linked list of subjectAltNames
+ * @param[in]           kind            type of the subjectAltName (which is a generalName)
+ * @param[in]           value           value of the subjectAltName as an ASCII string
  */
 void
 pkcs10_add_subjectAltName(generalName_t **subjectAltNames, generalNames_t kind
 , char *value) 
 {
-    generalName_t *gn;
-    asn1_t asn1_type = ASN1_EOC;
-    chunk_t name = { value, strlen(value) };
-
-    switch (kind)
-    {
-    case GN_RFC822_NAME:
-       asn1_type = ASN1_CONTEXT_S_1;
-       break;
-    case GN_DNS_NAME:
-       asn1_type = ASN1_CONTEXT_S_2;
-       break;
-    case GN_IP_ADDRESS:
+       generalName_t *gn;
+       asn1_t asn1_type = ASN1_EOC;
+       chunk_t name = { value, strlen(value) };
+
+       switch (kind)
        {
-           struct in_addr addr;
-
-           /* convert an ASCII dotted IPv4 address (e.g. 123.456.78.90)
-             * to a byte representation in network order
-             */
-           if (!inet_aton(value, &addr))
-           {
-               fprintf(stderr, "error in IPv4 subjectAltName\n");
-               return;
-           }
-           asn1_type = ASN1_CONTEXT_S_7;
-           name.ptr = (u_char *) &addr.s_addr;
-            name.len = sizeof(addr.s_addr);
-           break;
-        }
-    default:
-       break;
-    }
-
-    gn = alloc_thing(generalName_t, "subjectAltName");
-    gn->kind = kind;
-    gn->name = asn1_simple_object(asn1_type, name);
-    gn->next = *subjectAltNames;
-    *subjectAltNames = gn;
+       case GN_RFC822_NAME:
+               asn1_type = ASN1_CONTEXT_S_1;
+               break;
+       case GN_DNS_NAME:
+               asn1_type = ASN1_CONTEXT_S_2;
+               break;
+       case GN_IP_ADDRESS:
+               {
+                       struct in_addr addr;
+
+                       /* convert an ASCII dotted IPv4 address (e.g. 123.456.78.90)
+                        * to a byte representation in network order
+                        */
+                       if (!inet_aton(value, &addr))
+                       {
+                               fprintf(stderr, "error in IPv4 subjectAltName\n");
+                               return;
+                       }
+                       asn1_type = ASN1_CONTEXT_S_7;
+                       name.ptr = (u_char *) &addr.s_addr;
+                       name.len = sizeof(addr.s_addr);
+                       break;
+               }
+       default:
+               break;
+       }
+
+       gn = malloc_thing(generalName_t);
+       gn->kind = kind;
+       gn->name = asn1_simple_object(asn1_type, name);
+       gn->next = *subjectAltNames;
+       *subjectAltNames = gn;
 }
 
 /**
@@ -108,71 +107,75 @@ pkcs10_add_subjectAltName(generalName_t **subjectAltNames, generalNames_t kind
  * challenge password ans subjectAltNames are only included,
  * when avaiable in given #pkcs10_t structure
  *
- * @param[in]  pkcs10          Pointer to a #pkcs10_t structure
- * @return                                     1 if succeeded, 0 otherwise
+ * @param[in]   pkcs10          Pointer to a #pkcs10_t structure
+ * @return                                      1 if succeeded, 0 otherwise
  */
 static chunk_t
 build_req_info_attributes(pkcs10_t* pkcs10)
 {
 
-    chunk_t subjectAltNames   = empty_chunk;
-    chunk_t challengePassword = empty_chunk;
-
-    if (pkcs10->subjectAltNames != NULL) 
-    {
-
-       subjectAltNames = asn1_wrap(ASN1_SEQUENCE, "cm"
-               , ASN1_extensionRequest_oid
-               , asn1_wrap(ASN1_SET, "m"
-                   , asn1_wrap(ASN1_SEQUENCE, "m"
-                       , build_subjectAltNames(pkcs10->subjectAltNames)
-                     )
-                 )
-           );
-    }
-
-    if (pkcs10->challengePassword.len > 0)
-    {
-       asn1_t type = is_printablestring(pkcs10->challengePassword)
-                     ? ASN1_PRINTABLESTRING : ASN1_T61STRING;
-
-       challengePassword = asn1_wrap(ASN1_SEQUENCE, "cm"
-               , ASN1_challengePassword_oid
-               , asn1_wrap(ASN1_SET, "m"
-                   , asn1_simple_object(type, pkcs10->challengePassword)
-                 )
-           );
-    }
-
-    return asn1_wrap(ASN1_CONTEXT_C_0, "mm"
-               , subjectAltNames
-               , challengePassword);
+       chunk_t subjectAltNames   = chunk_empty;
+       chunk_t challengePassword = chunk_empty;
+
+       if (pkcs10->subjectAltNames != NULL) 
+       {
+
+               subjectAltNames = asn1_wrap(ASN1_SEQUENCE, "cm"
+                               , ASN1_extensionRequest_oid
+                               , asn1_wrap(ASN1_SET, "m"
+                                       , asn1_wrap(ASN1_SEQUENCE, "m"
+                                               , build_subjectAltNames(pkcs10->subjectAltNames)
+                                         )
+                                 )
+                       );
+       }
+
+       if (pkcs10->challengePassword.len > 0)
+       {
+               asn1_t type = asn1_is_printablestring(pkcs10->challengePassword)
+                                         ? ASN1_PRINTABLESTRING : ASN1_T61STRING;
+
+               challengePassword = asn1_wrap(ASN1_SEQUENCE, "cm"
+                               , ASN1_challengePassword_oid
+                               , asn1_wrap(ASN1_SET, "m"
+                                       , asn1_simple_object(type, pkcs10->challengePassword)
+                                 )
+                       );
+       }
+
+       return asn1_wrap(ASN1_CONTEXT_C_0, "mm"
+                               , subjectAltNames
+                               , challengePassword);
 }
 
 /**
  * @brief Builds a DER-code pkcs#10 certificate request
  *
- * @param[in]  pkcs10          pointer to a pkcs10_t struct
- * @return                     DER-code pkcs10 request
+ * @param[in]   pkcs10          pointer to a pkcs10_t struct
+ * @return                      DER-code pkcs10 request
  */
 static chunk_t
 pkcs10_build_request(pkcs10_t *pkcs10, int signature_alg)
 {
-    RSA_public_key_t *rsak = (RSA_public_key_t *) pkcs10->private_key;
+       chunk_t key = pkcs10->public_key->get_encoding(pkcs10->public_key);
+
+       chunk_t keyInfo = asn1_wrap(ASN1_SEQUENCE, "cm",
+                                                       asn1_algorithmIdentifier(OID_RSA_ENCRYPTION), 
+                                                       asn1_bitstring("m", key));      
 
-    chunk_t cert_req_info = asn1_wrap(ASN1_SEQUENCE, "ccmm"
-               , ASN1_INTEGER_0
-               , pkcs10->subject
-               , pkcs1_build_publicKeyInfo(rsak)
-               , build_req_info_attributes(pkcs10));
+       chunk_t cert_req_info = asn1_wrap(ASN1_SEQUENCE, "ccmm",
+                                                               ASN1_INTEGER_0,
+                                                               pkcs10->subject,
+                                                               keyInfo,
+                                                               build_req_info_attributes(pkcs10));
 
-    chunk_t signature = pkcs1_build_signature(cert_req_info
-               , signature_alg, pkcs10->private_key, TRUE);
+       chunk_t signature = x509_build_signature(cert_req_info, signature_alg,
+                                                                                        pkcs10->private_key, TRUE);
 
-    return asn1_wrap(ASN1_SEQUENCE, "mcm"
-               , cert_req_info
-               , asn1_algorithmIdentifier(signature_alg)
-               , signature);
+       return asn1_wrap(ASN1_SEQUENCE, "mcm",
+                               cert_req_info,
+                               asn1_algorithmIdentifier(signature_alg),
+                               signature);
 }
 
 /**
@@ -183,38 +186,39 @@ pkcs10_build_request(pkcs10_t *pkcs10, int signature_alg)
  * (e.g. commonName, organization) are needed. An optional challenge
  * password or some subjectAltNames may be included.
  *
- * @param[in]  key                     rsakey of type #rsakey_t
- * @param[in]  subject                 DER-coded subject distinguished name
- * @param[in]  challengePassword       challenge password or empty_chunk
- * @param[in]  subjectAltNames         linked list of subjectAltNames or NULL
- * @return                             pointer to a #pkcs10_t object
+ * @param[in]   key                     rsakey of type #rsakey_t
+ * @param[in]   subject                 DER-coded subject distinguished name
+ * @param[in]   challengePassword       challenge password or chunk_empty
+ * @param[in]   subjectAltNames         linked list of subjectAltNames or NULL
+ * @return                              pointer to a #pkcs10_t object
  */
-pkcs10_t*
-pkcs10_build(RSA_private_key_t *key, chunk_t subject, chunk_t challengePassword
-, generalName_t *subjectAltNames, int signature_alg)
+pkcs10_t* pkcs10_build(private_key_t *private, public_key_t *public,
+                                          chunk_t subject, chunk_t challengePassword,
+                                          generalName_t *subjectAltNames, int signature_alg)
 {
-    pkcs10_t *pkcs10 = alloc_thing(pkcs10_t, "pkcs10_t");
+       pkcs10_t *pkcs10 = malloc_thing(pkcs10_t);
 
-    pkcs10->subject = subject;
-    pkcs10->private_key = key;
-    pkcs10->challengePassword = challengePassword;
-    pkcs10->subjectAltNames = subjectAltNames;
+       pkcs10->subject = subject;
+       pkcs10->private_key = private;
+       pkcs10->public_key = public;
+       pkcs10->challengePassword = challengePassword;
+       pkcs10->subjectAltNames = subjectAltNames;
 
-    pkcs10->request = pkcs10_build_request(pkcs10, signature_alg);
-    return pkcs10;
+       pkcs10->request = pkcs10_build_request(pkcs10, signature_alg);
+       return pkcs10;
 }
 
 /**
  * @brief Frees the resources used by an #pkcs10_t object
  *
- * @param[in]  pkcs10          #pkcs10_t to free
+ * @param[in]   pkcs10          #pkcs10_t to free
  */
 void
 pkcs10_free(pkcs10_t *pkcs10)
 {
-    if (pkcs10 != NULL)
-    {
-       freeanychunk(pkcs10->request);
-       pfree(pkcs10);
-    }
+       if (pkcs10 != NULL)
+       {
+               free(pkcs10->request.ptr);
+               free(pkcs10);
+       }
 }