load_private_key() loads all kinds of keys
[strongswan.git] / src / pluto / certs.c
index 92cad9c..ca3019b 100644 (file)
@@ -1,5 +1,7 @@
 /* Certificate support for IKE authentication
- * Copyright (C) 2002-2004 Andreas Steffen, Zuercher Hochschule Winterthur
+ * Copyright (C) 2002-2009 Andreas Steffen
+ *
+ * HSR - 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
@@ -10,8 +12,6 @@
  * 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$
  */
 
 #include <stdlib.h>
 #include <string.h>
 
 #include <freeswan.h>
-#include <ipsec_policy.h>
+
+#include "library.h"
+#include "asn1/asn1.h"
 
 #include "constants.h"
 #include "defs.h"
 #include "log.h"
-#include "asn1.h"
 #include "id.h"
-#include "x509.h"
-#include "pgp.h"
 #include "pem.h"
 #include "certs.h"
-#include "pkcs1.h"
 
-/*
+/**
  * used for initializatin of certs
  */
-const cert_t empty_cert = {CERT_NONE, {NULL}};
+const cert_t cert_empty = {CERT_NONE, {NULL}};
 
-/*
+/**
  * extracts the certificate to be sent to the peer
  */
-chunk_t
-get_mycert(cert_t cert)
+chunk_t cert_get_encoding(cert_t cert)
 {
-    switch (cert.type)
-    {
-    case CERT_PGP:
-       return cert.u.pgp->certificate;
-    case CERT_X509_SIGNATURE:
-       return cert.u.x509->certificate;
-    default:
-       return empty_chunk;
-    }
+       switch (cert.type)
+       {
+       case CERT_PGP:
+               return cert.u.pgp->certificate;
+       case CERT_X509_SIGNATURE:
+               return cert.u.x509->certificate;
+       default:
+               return chunk_empty;
+       }
+}
+
+public_key_t* cert_get_public_key(const cert_t cert)
+{
+       switch (cert.type)
+       {
+               case CERT_PGP:
+                       return cert.u.pgp->public_key;
+                       break;
+               case CERT_X509_SIGNATURE:
+                       return cert.u.x509->public_key;
+                       break;
+               default:
+                       return NULL;
+       }
 }
 
 /* load a coded key or certificate file with autodetection
  * of binary DER or base64 PEM ASN.1 formats and armored PGP format
  */
-bool
-load_coded_file(const char *filename, prompt_pass_t *pass, const char *type
-, chunk_t *blob, bool *pgp)
+bool load_coded_file(char *filename, prompt_pass_t *pass, const char *type,
+                                        chunk_t *blob, bool *pgp)
 {
-    err_t ugh = NULL;
+       err_t ugh = NULL;
+
+       FILE *fd = fopen(filename, "r");
 
-    FILE *fd = fopen(filename, "r");
+       if (fd)
+       {
+               int bytes;
+               fseek(fd, 0, SEEK_END );
+               blob->len = ftell(fd);
+               rewind(fd);
+               blob->ptr = malloc(blob->len);
+               bytes = fread(blob->ptr, 1, blob->len, fd);
+               fclose(fd);
+               plog("  loaded %s file '%s' (%d bytes)", type, filename, bytes);
 
-    if (fd)
-    {
-       int bytes;
-       fseek(fd, 0, SEEK_END );
-       blob->len = ftell(fd);
-       rewind(fd);
-       blob->ptr = alloc_bytes(blob->len, type);
-       bytes = fread(blob->ptr, 1, blob->len, fd);
-       fclose(fd);
-       plog("  loaded %s file '%s' (%d bytes)", type, filename, bytes);
+               *pgp = FALSE;
 
-       *pgp = FALSE;
+               /* try DER format */
+               if (is_asn1(*blob))
+               {
+                       DBG(DBG_PARSING,
+                               DBG_log("  file coded in DER format");
+                       )
+                       return TRUE;
+               }
 
-       /* try DER format */
-       if (is_asn1(*blob))
-       {
-           DBG(DBG_PARSING,
-               DBG_log("  file coded in DER format");
-           )
-           return TRUE;
-       }
+               /* try PEM format */
+               ugh = pemtobin(blob, pass, filename, pgp);
 
-       /* try PEM format */
-       ugh = pemtobin(blob, pass, filename, pgp);
+               if (ugh == NULL)
+               {
+                       if (*pgp)
+                       {
+                               DBG(DBG_PARSING,
+                                       DBG_log("  file coded in armored PGP format");
+                               )
+                               return TRUE;
+                       }
+                       if (is_asn1(*blob))
+                       {
+                               DBG(DBG_PARSING,
+                                       DBG_log("  file coded in PEM format");
+                               )
+                               return TRUE;
+                       }
+                       ugh = "file coded in unknown format, discarded";
+               }
 
-       if (ugh == NULL)
+               /* a conversion error has occured */
+               plog("  %s", ugh);
+               free(blob->ptr);
+               *blob = chunk_empty;
+       }
+       else
        {
-           if (*pgp)
-           {
-                DBG(DBG_PARSING,
-                    DBG_log("  file coded in armored PGP format");
-                )
-                return TRUE;
-           }
-           if (is_asn1(*blob))
-           {
-               DBG(DBG_PARSING,
-                   DBG_log("  file coded in PEM format");
-               )
-               return TRUE;
-           }
-           ugh = "file coded in unknown format, discarded";
+               plog("  could not open %s file '%s'", type, filename);
        }
-
-       /* a conversion error has occured */
-       plog("  %s", ugh);
-       pfree(blob->ptr);
-       *blob = empty_chunk;
-    }
-    else
-    {
-       plog("  could not open %s file '%s'", type, filename);
-    }
-    return FALSE;
+       return FALSE;
 }
 
-/*
- *  Loads a PKCS#1 or PGP private RSA key file
+/**
+ *  Loads a PKCS#1 or PGP privatekey file
  */
-err_t
-load_rsa_private_key(const char* filename, prompt_pass_t *pass
-, RSA_private_key_t *key)
+private_key_t* load_private_key(char* filename, prompt_pass_t *pass,
+                                                               key_type_t type)
 {
-    err_t ugh = NULL;
-    bool pgp = FALSE;
-    chunk_t blob = empty_chunk;
+       private_key_t *key = NULL;
+       chunk_t blob = chunk_empty;
+       bool pgp = FALSE;
 
-    const char *path = concatenate_paths(PRIVATE_KEY_PATH, filename);
+       char *path = concatenate_paths(PRIVATE_KEY_PATH, filename);
 
-    if (load_coded_file(path, pass, "private key", &blob, &pgp))
-    {
-       if (pgp)
+       if (load_coded_file(path, pass, "private key", &blob, &pgp))
        {
-           if (!parse_pgp(blob, NULL, key))
-               ugh = "syntax error in PGP private key file";
+               if (pgp)
+               {
+                       parse_pgp(blob, NULL, &key);
+               }
+               else
+               {
+                       key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, type,
+                                                                        BUILD_BLOB_ASN1_DER, blob, BUILD_END);
+               }
+               if (key == NULL)
+               {
+                       plog("  syntax error in %s private key file", pgp ? "PGP":"PKCS#");
+               }                       
+               free(blob.ptr);
        }
        else
        {
-           if (!pkcs1_parse_private_key(blob, key))
-               ugh = "syntax error in PKCS#1 private key file";
+               plog("  error loading private key file");
        }
-       pfree(blob.ptr);
-    }
-    else
-       ugh = "error loading RSA private key file";
-
-    return ugh;
+       return key;
 }
-/*
+
+/**
  *  Loads a X.509 or OpenPGP certificate
  */
-bool
-load_cert(const char *filename, const char *label, cert_t *cert)
+bool load_cert(char *filename, const char *label, cert_t *cert)
 {
-    bool pgp = FALSE;
-    chunk_t blob = empty_chunk;
+       bool pgp = FALSE;
+       chunk_t blob = chunk_empty;
 
-    /* initialize cert struct */
-    cert->type = CERT_NONE;
-    cert->u.x509 = NULL;
+       /* initialize cert struct */
+       cert->type = CERT_NONE;
+       cert->u.x509 = NULL;
 
-    if (load_coded_file(filename, NULL, label, &blob, &pgp))
-    {
-       if (pgp)
-       {
-           pgpcert_t *pgpcert = alloc_thing(pgpcert_t, "pgpcert");
-           *pgpcert = empty_pgpcert;
-           if (parse_pgp(blob, pgpcert, NULL))
-           {
-               cert->type = CERT_PGP;
-               cert->u.pgp = pgpcert;
-               return TRUE;
-           }
-           else
-           {
-               plog("  error in OpenPGP certificate");
-               free_pgpcert(pgpcert);
-               return FALSE;
-           }
-       }
-       else
+       if (load_coded_file(filename, NULL, label, &blob, &pgp))
        {
-           x509cert_t *x509cert = alloc_thing(x509cert_t, "x509cert");
-           *x509cert = empty_x509cert;
-           if (parse_x509cert(blob, 0, x509cert))
-           {
-               cert->type = CERT_X509_SIGNATURE;
-               cert->u.x509 = x509cert;
-               return TRUE;
-           }
-           else
-           {
-               plog("  error in X.509 certificate");
-               free_x509cert(x509cert);
-               return FALSE;
-           }
+               if (pgp)
+               {
+                       pgpcert_t *pgpcert = malloc_thing(pgpcert_t);
+                       *pgpcert = pgpcert_empty;
+                       if (parse_pgp(blob, pgpcert, NULL))
+                       {
+                               cert->type = CERT_PGP;
+                               cert->u.pgp = pgpcert;
+                               return TRUE;
+                       }
+                       else
+                       {
+                               plog("  error in OpenPGP certificate");
+                               free_pgpcert(pgpcert);
+                               return FALSE;
+                       }
+               }
+               else
+               {
+                       x509cert_t *x509cert = malloc_thing(x509cert_t);
+                       *x509cert = empty_x509cert;
+                       if (parse_x509cert(blob, 0, x509cert))
+                       {
+                               cert->type = CERT_X509_SIGNATURE;
+                               cert->u.x509 = x509cert;
+                               return TRUE;
+                       }
+                       else
+                       {
+                               plog("  error in X.509 certificate");
+                               free_x509cert(x509cert);
+                               return FALSE;
+                       }
+               }
        }
-    }
-    return FALSE;
+       return FALSE;
 }
 
-/*
+/**
  *  Loads a host certificate
  */
-bool
-load_host_cert(const char *filename, cert_t *cert)
+bool load_host_cert(char *filename, cert_t *cert)
 {
-    const char *path = concatenate_paths(HOST_CERT_PATH, filename);
+       char *path = concatenate_paths(HOST_CERT_PATH, filename);
 
-    return load_cert(path, "host cert", cert);
+       return load_cert(path, "host cert", cert);
 }
 
-/*
+/**
  *  Loads a CA certificate
  */
-bool
-load_ca_cert(const char *filename, cert_t *cert)
+bool load_ca_cert(char *filename, cert_t *cert)
 {
-    const char *path = concatenate_paths(CA_CERT_PATH, filename);
+       char *path = concatenate_paths(CA_CERT_PATH, filename);
 
-    return load_cert(path, "CA cert", cert);
+       return load_cert(path, "CA cert", cert);
 }
 
-/*
+/**
  * establish equality of two certificates
  */
-bool
-same_cert(const cert_t *a, const cert_t *b)
+bool same_cert(const cert_t *a, const cert_t *b)
 {
-    return a->type == b->type && a->u.x509 == b->u.x509;
+       return a->type == b->type && a->u.x509 == b->u.x509;
 }
 
-/*  for each link pointing to the certif icate
 increase the count by one
+/**
* for each link pointing to the certificate increase the count by one
  */
-void
-share_cert(cert_t cert)
+void share_cert(cert_t cert)
 {
-    switch (cert.type)
-    {
-    case CERT_PGP:
-       share_pgpcert(cert.u.pgp);
-       break;
-    case CERT_X509_SIGNATURE:
-       share_x509cert(cert.u.x509);
-       break;
-    default:
-        break;
-    }
+       switch (cert.type)
+       {
+       case CERT_PGP:
+               share_pgpcert(cert.u.pgp);
+               break;
+       case CERT_X509_SIGNATURE:
+               share_x509cert(cert.u.x509);
+               break;
+       default:
+               break;
+       }
 }
 
 /*  release of a certificate decreases the count by one
@@ -263,16 +273,16 @@ void
 release_cert(cert_t cert)
 {
    switch (cert.type)
-    {
-    case CERT_PGP:
-       release_pgpcert(cert.u.pgp);
-       break;
-    case CERT_X509_SIGNATURE:
-       release_x509cert(cert.u.x509);
-       break;
-    default:
-        break;
-    }
+       {
+       case CERT_PGP:
+               release_pgpcert(cert.u.pgp);
+               break;
+       case CERT_X509_SIGNATURE:
+               release_x509cert(cert.u.x509);
+               break;
+       default:
+               break;
+       }
 }
 
 /*
@@ -281,7 +291,7 @@ release_cert(cert_t cert)
 void
 list_certs(bool utc)
 {
-    list_x509_end_certs(utc);
-    list_pgp_end_certs(utc);
+       list_x509_end_certs(utc);
+       list_pgp_end_certs(utc);
 }