pki: Add command to export certificates and keys from PKCS#12 containers
[strongswan.git] / src / pki / commands / pkcs12.c
index f871042..fe92fa8 100644 (file)
@@ -28,9 +28,9 @@ static int show(pkcs12_t *pkcs12)
        enumerator_t *enumerator;
        certificate_t *cert;
        private_key_t *key;
+       int index = 1;
 
-       printf("PKCS#12 contents:\n");
-
+       printf("Certificates:\n");
        enumerator = pkcs12->create_cert_enumerator(pkcs12);
        while (enumerator->enumerate(enumerator, &cert))
        {
@@ -38,34 +38,108 @@ static int show(pkcs12_t *pkcs12)
 
                if (x509->get_flags(x509) & X509_CA)
                {
-                       printf("  CA certificate \"%Y\"\n", cert->get_subject(cert));
+                       printf("[%2d] \"%Y\" (CA)\n", index++, cert->get_subject(cert));
                }
                else
                {
-                       printf("  Certificate \"%Y\"\n", cert->get_subject(cert));
+                       printf("[%2d] \"%Y\"\n", index++, cert->get_subject(cert));
                }
        }
        enumerator->destroy(enumerator);
+
+       printf("Private keys:\n");
        enumerator = pkcs12->create_key_enumerator(pkcs12);
        while (enumerator->enumerate(enumerator, &key))
        {
-               printf("  %N private key\n", key_type_names, key->get_type(key));
+               printf("[%2d] %N %d bits\n", index++, key_type_names,
+                          key->get_type(key), key->get_keysize(key));
        }
        enumerator->destroy(enumerator);
        return 0;
 }
 
+static int export(pkcs12_t *pkcs12, int index, char *outform)
+{
+       cred_encoding_type_t form;
+       enumerator_t *enumerator;
+       certificate_t *cert;
+       private_key_t *key;
+       chunk_t encoding;
+       int i = 1;
+
+       enumerator = pkcs12->create_cert_enumerator(pkcs12);
+       while (enumerator->enumerate(enumerator, &cert))
+       {
+               if (i++ == index)
+               {
+                       form = CERT_ASN1_DER;
+                       if (outform && !get_form(outform, &form, CRED_CERTIFICATE))
+                       {
+                               return command_usage("invalid output format");
+                       }
+                       if (cert->get_encoding(cert, form, &encoding))
+                       {
+                               set_file_mode(stdout, form);
+                               if (fwrite(encoding.ptr, encoding.len, 1, stdout) == 1)
+                               {
+                                       free(encoding.ptr);
+                                       enumerator->destroy(enumerator);
+                                       return 0;
+                               }
+                               free(encoding.ptr);
+                       }
+                       fprintf(stderr, "certificate export failed\n");
+                       enumerator->destroy(enumerator);
+                       return 1;
+               }
+       }
+       enumerator->destroy(enumerator);
+
+       enumerator = pkcs12->create_key_enumerator(pkcs12);
+       while (enumerator->enumerate(enumerator, &key))
+       {
+               if (i++ == index)
+               {
+                       form = PRIVKEY_ASN1_DER;
+                       if (outform && !get_form(outform, &form, CRED_PRIVATE_KEY))
+                       {
+                               return command_usage("invalid output format");
+                       }
+                       if (key->get_encoding(key, form, &encoding))
+                       {
+                               set_file_mode(stdout, form);
+                               if (fwrite(encoding.ptr, encoding.len, 1, stdout) == 1)
+                               {
+                                       free(encoding.ptr);
+                                       enumerator->destroy(enumerator);
+                                       return 0;
+                               }
+                               free(encoding.ptr);
+                       }
+                       fprintf(stderr, "private key export failed\n");
+                       enumerator->destroy(enumerator);
+                       return 0;
+               }
+       }
+       enumerator->destroy(enumerator);
+
+       fprintf(stderr, "invalid index %d\n", index);
+       return 1;
+}
+
+
 /**
  * Handle PKCs#12 containers
  */
 static int pkcs12()
 {
-       char *arg, *file = NULL;
+       char *arg, *file = NULL, *outform = NULL;
        pkcs12_t *p12 = NULL;
-       int res = 1;
+       int res = 1, index = 0;
        enum {
                OP_NONE,
-               OP_SHOW,
+               OP_LIST,
+               OP_EXPORT,
        } op = OP_NONE;
 
        while (TRUE)
@@ -77,12 +151,23 @@ static int pkcs12()
                        case 'i':
                                file = arg;
                                continue;
-                       case 'p':
+                       case 'l':
                                if (op != OP_NONE)
                                {
                                        goto invalid;
                                }
-                               op = OP_SHOW;
+                               op = OP_LIST;
+                               continue;
+                       case 'e':
+                               if (op != OP_NONE)
+                               {
+                                       goto invalid;
+                               }
+                               op = OP_EXPORT;
+                               index = atoi(arg);
+                               continue;
+                       case 'f':
+                               outform = arg;
                                continue;
                        case EOF:
                                break;
@@ -93,11 +178,6 @@ static int pkcs12()
                break;
        }
 
-       if (op != OP_SHOW)
-       {
-               return command_usage(NULL);
-       }
-
        if (file)
        {
                p12 = lib->creds->create(lib->creds, CRED_CONTAINER, CONTAINER_PKCS12,
@@ -124,7 +204,19 @@ static int pkcs12()
                goto end;
        }
 
-       res = show(p12);
+       switch (op)
+       {
+               case OP_LIST:
+                       res = show(p12);
+                       break;
+               case OP_EXPORT:
+                       res = export(p12, index, outform);
+                       break;
+               default:
+                       p12->container.destroy(&p12->container);
+                       return command_usage(NULL);
+       }
+
 end:
        if (p12)
        {
@@ -140,11 +232,14 @@ static void __attribute__ ((constructor))reg()
 {
        command_register((command_t) {
                pkcs12, 'u', "pkcs12", "PKCS#12 functions",
-               {"--show [--in file]"},
+               {"--export index|--list [--in file]",
+                "[--outform der|pem|dnskey|sshkey]"},
                {
                        {"help",        'h', 0, "show usage information"},
-                       {"show",        'p', 0, "show info about PKCS#12, print certificates and keys"},
                        {"in",          'i', 1, "input file, default: stdin"},
+                       {"list",        'l', 0, "list certificates and keys"},
+                       {"export",      'e', 1, "export the credential with the given index"},
+                       {"outform",     'f', 1, "encoding of extracted public key, default: der"},
                }
        });
 }