2 * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
18 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
20 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
22 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
23 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
24 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 /************************************************************
31 * This program is for converting from BIND .private-key
32 * format to PKCS#8 key file format. So that keys can be
33 * imported from BIND to SoftHSM.
35 * Some of the design/code is from keyconv.c written by
36 * Hakan Olsson and Jakob Schlyter in 2000 and 2001.
38 ************************************************************/
41 #include "softhsm2-keyconv.h"
60 #include <sys/types.h>
66 printf("Converting from BIND .private-key format to PKCS#8 key file format.\n");
67 printf("Usage: softhsm2-keyconv [OPTIONS]\n");
69 printf(" -h Shows this help screen.\n");
70 printf(" --help Shows this help screen.\n");
71 printf(" --in <path> The path to the input file.\n");
72 printf(" --out <path> The path to the output file.\n");
73 printf(" --pin <PIN> To encrypt PKCS#8 file. Optional.\n");
74 printf(" -v Show version info.\n");
75 printf(" --version Show version info.\n");
78 // Give a number to each option
88 static const struct option long_options[] = {
89 { "help", 0, NULL, OPT_HELP },
90 { "in", 1, NULL, OPT_IN },
91 { "out", 1, NULL, OPT_OUT },
92 { "pin", 1, NULL, OPT_PIN },
93 { "version", 0, NULL, OPT_VERSION },
97 int main(int argc, char* argv[])
102 char* in_path = NULL;
103 char* out_path = NULL;
104 char* file_pin = NULL;
112 while ((opt = getopt_long(argc, argv, "hv", long_options, &option_index)) != -1)
127 printf("%s\n", PACKAGE_VERSION);
139 // We should convert to PKCS#8
140 result = to_pkcs8(in_path, out_path, file_pin);
145 // Convert from BIND to PKCS#8
146 int to_pkcs8(char* in_path, char* out_path, char* file_pin)
148 FILE* file_pointer = NULL;
149 char line[MAX_LINE], data[MAX_LINE];
150 char* value_pointer = NULL;
151 int lineno = 0, m, n, error = 0, found, algorithm = DNS_KEYALG_ERROR, data_length;
152 uint32_t bitfield = 0;
153 key_material_t pkey[TAG_MAX];
157 fprintf(stderr, "ERROR: A path to the input file must be supplied. Use --in <path>\n");
161 if (out_path == NULL)
163 fprintf(stderr, "ERROR: A path to the output file must be supplied. Use --out <path>\n");
167 file_pointer = fopen(in_path, "r");
168 if (file_pointer == NULL)
170 fprintf(stderr, "ERROR: Could not open input file %.100s for reading.\n", in_path);
174 // Loop over all of the lines
175 while (fgets(line, MAX_LINE, file_pointer) != NULL)
179 // Find the current text field in the BIND file.
180 for (m = 0, found = -1; found == -1 && file_tags[m]; m++)
182 if (strncasecmp(line, file_tags[m], strlen(file_tags[m])) == 0)
188 // The text files is not recognized.
191 fprintf(stderr, "ERROR: Unrecognized input line %i\n", lineno);
192 fprintf(stderr, "ERROR: --> %s", line);
196 // Point to the data for this text field.
197 value_pointer = line + strlen(file_tags[found]) + 1;
199 // Continue if we are at the end of the string
200 if (*value_pointer == 0)
205 // Check that we do not get duplicates.
206 if (bitfield & (1 << found))
208 fprintf(stderr, "ERROR: Duplicate \"%s\" field, line %i - ignored\n",
209 file_tags[found], lineno);
212 bitfield |= (1 << found);
214 // Handle the data for this text field.
218 if (sscanf(value_pointer, "v%i.%i", &m, &n) != 2)
220 fprintf(stderr, "ERROR: Invalid/unknown version string "
221 "(%.100s).\n", value_pointer);
225 if (m > FILE_MAJOR_VERSION || (m == FILE_MAJOR_VERSION && n > FILE_MINOR_VERSION))
227 fprintf(stderr, "ERROR: Cannot parse this version of file format, "
233 algorithm = strtol(value_pointer, NULL, 10);
250 data_length = b64_pton(value_pointer, (unsigned char*)data, MAX_LINE);
251 if (data_length == -1)
254 fprintf(stderr, "ERROR: Could not parse the base64 string on line %i.\n", lineno);
258 pkey[found].big = malloc(data_length);
259 if (!pkey[found].big)
261 fprintf(stderr, "ERROR: Could not allocate memory.\n");
265 memcpy(pkey[found].big, data, data_length);
266 pkey[found].size = data_length;
278 fclose(file_pointer);
280 // Something went wrong. Clean up and quit.
283 free_key_material(pkey);
287 // Create and set file permissions if the file does not exist.
288 int fd = open(out_path, O_CREAT, S_IRUSR | S_IWUSR);
291 fprintf(stderr, "ERROR: Could not open the output file: %s (errno %i)\n",
293 free_key_material(pkey);
300 // Save the the key to the disk
303 case DNS_KEYALG_ERROR:
304 fprintf(stderr, "ERROR: The algorithm %i was not given in the file.\n",
308 case DNS_KEYALG_RSAMD5:
309 case DNS_KEYALG_RSASHA1:
310 case DNS_KEYALG_RSASHA1_NSEC3_SHA1:
311 case DNS_KEYALG_RSASHA256:
312 case DNS_KEYALG_RSASHA512:
313 error = save_rsa_pkcs8(out_path, file_pin, pkey);
316 case DNS_KEYALG_DSA_NSEC3_SHA1:
317 error = save_dsa_pkcs8(out_path, file_pin, pkey);
320 case DNS_KEYALG_ECC_GOST:
322 fprintf(stderr, "ERROR: The algorithm %i is not supported.\n",
329 free_key_material(pkey);
334 // Free allocated memory
335 void free_key_material(key_material_t* pkey)
344 for (i = 0; i < TAG_MAX; i++)