Correct PPTP server firewall rules chain.
[tomato/davidwu.git] / release / src / router / nettle / tools / pkcs1-conv.c
blob231b2acd4348161808b2612dae77e9dd04cf3edd
1 /* pkcs1-conv.c
3 * Converting pkcs#1 and similar keys to sexp format. */
5 /* nettle, low-level cryptographics library
7 * Copyright (C) 2005, 2009 Niels Möller, Magnus Holmgren
8 *
9 * The nettle library is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU Lesser General Public License as published by
11 * the Free Software Foundation; either version 2.1 of the License, or (at your
12 * option) any later version.
14 * The nettle library is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
17 * License for more details.
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with the nettle library; see the file COPYING.LIB. If not, write to
21 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
22 * MA 02111-1301, USA.
25 #if HAVE_CONFIG_H
26 # include "config.h"
27 #endif
29 #include <errno.h>
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <string.h>
34 #include "asn1.h"
35 #include "base64.h"
36 #include "buffer.h"
37 #include "rsa.h"
38 #include "dsa.h"
40 #include "getopt.h"
41 #include "misc.h"
43 enum object_type
45 /* Use a range of values which also work as option id:s */
46 RSA_PRIVATE_KEY = 0x200,
47 RSA_PUBLIC_KEY,
48 DSA_PRIVATE_KEY,
49 /* DSA public keys only supported as part of a
50 SubjectPublicKeyInfo, i.e., the GENERAL_PUBLIC_KEY case. */
51 GENERAL_PUBLIC_KEY,
54 static int
55 write_file(struct nettle_buffer *buffer, FILE *f)
57 size_t res = fwrite(buffer->contents, 1, buffer->size, f);
58 if (res < buffer->size)
60 werror("Write failed: %s.\n", strerror(errno));
61 return 0;
63 else
64 return 1;
67 /* Return 1 on success, 0 on error, -1 on eof */
68 static int
69 read_line(struct nettle_buffer *buffer, FILE *f)
71 int c;
73 while ((c = getc(f)) != EOF)
75 if (!NETTLE_BUFFER_PUTC(buffer, c))
76 return 0;
78 if (c == '\n')
79 return 1;
81 if (ferror(f))
83 werror("Read failed: %s\n", strerror(errno));
84 return 0;
87 else
88 return -1;
91 static int
92 read_file(struct nettle_buffer *buffer, FILE *f)
94 int c;
96 while ((c = getc(f)) != EOF)
97 if (!NETTLE_BUFFER_PUTC(buffer, c))
98 return 0;
100 if (ferror(f))
102 werror("Read failed: %s\n", strerror(errno));
103 return 0;
105 else
106 return 1;
109 static const uint8_t
110 pem_start_pattern[11] = "-----BEGIN ";
112 static const uint8_t
113 pem_end_pattern[9] = "-----END ";
115 static const uint8_t
116 pem_trailer_pattern[5] = "-----";
118 static const char
119 pem_ws[33] = {
120 0, 0, 0, 0, 0, 0, 0, 0,
121 0, 1, 1, 1, 1, 1, 0, 0, /* \t, \n, \v, \f, \r */
122 0, 0, 0, 0, 0, 0, 0, 0,
123 0, 0, 0, 0, 0, 0, 0, 0,
124 1 /* SPC */
127 #define PEM_IS_SPACE(c) ((c) < sizeof(pem_ws) && pem_ws[(c)])
129 /* Returns 1 on match, otherwise 0. */
130 static int
131 match_pem_start(unsigned length, const uint8_t *line,
132 unsigned *marker_start,
133 unsigned *marker_length)
135 while (length > 0 && PEM_IS_SPACE(line[length - 1]))
136 length--;
138 if (length > (sizeof(pem_start_pattern) + sizeof(pem_trailer_pattern))
139 && memcmp(line, pem_start_pattern, sizeof(pem_start_pattern)) == 0
140 && memcmp(line + length - sizeof(pem_trailer_pattern),
141 pem_trailer_pattern, sizeof(pem_trailer_pattern)) == 0)
143 *marker_start = 11;
144 *marker_length = length - (sizeof(pem_start_pattern) + sizeof(pem_trailer_pattern));
146 return 1;
148 else
149 return 0;
152 /* Returns 1 on match, -1 if the line is of the right form except for
153 the marker, otherwise 0. */
154 static int
155 match_pem_end(unsigned length, const uint8_t *line,
156 unsigned marker_length,
157 const uint8_t *marker)
159 while (length > 0 && PEM_IS_SPACE(line[length - 1]))
160 length--;
162 if (length > (sizeof(pem_end_pattern) + sizeof(pem_trailer_pattern))
163 && memcmp(line, pem_end_pattern, sizeof(pem_end_pattern)) == 0
164 && memcmp(line + length - sizeof(pem_trailer_pattern),
165 pem_trailer_pattern, sizeof(pem_trailer_pattern)) == 0)
167 /* Right form. Check marker */
168 if (length == marker_length + (sizeof(pem_end_pattern) + sizeof(pem_trailer_pattern))
169 && memcmp(line + sizeof(pem_end_pattern), marker, marker_length) == 0)
170 return 1;
171 else
172 return -1;
174 else
175 return 0;
178 struct pem_info
180 /* The FOO part in "-----BEGIN FOO-----" */
181 unsigned marker_start;
182 unsigned marker_length;
183 unsigned data_start;
184 unsigned data_length;
187 static int
188 read_pem(struct nettle_buffer *buffer, FILE *f,
189 struct pem_info *info)
191 /* Find start line */
192 for (;;)
194 int res;
196 nettle_buffer_reset(buffer);
198 res = read_line(buffer, f);
199 if (res != 1)
200 return res;
202 if (match_pem_start(buffer->size, buffer->contents,
203 &info->marker_start, &info->marker_length))
204 break;
207 /* NUL-terminate the marker. Don't care to check for embedded NULs. */
208 buffer->contents[info->marker_start + info->marker_length] = 0;
210 info->data_start = buffer->size;
212 for (;;)
214 unsigned line_start = buffer->size;
216 if (read_line(buffer, f) != 1)
217 return 0;
219 switch (match_pem_end(buffer->size - line_start,
220 buffer->contents + line_start,
221 info->marker_length,
222 buffer->contents + info->marker_start))
224 case 0:
225 break;
226 case -1:
227 werror("PEM END line doesn't match BEGIN.\n");
228 return 0;
229 case 1:
230 /* Return base 64 data; let caller do the decoding */
231 info->data_length = line_start - info->data_start;
232 return 1;
237 static int
238 decode_base64(struct nettle_buffer *buffer,
239 unsigned start, unsigned *length)
241 struct base64_decode_ctx ctx;
243 base64_decode_init(&ctx);
245 /* Decode in place */
246 if (base64_decode_update(&ctx,
247 length, buffer->contents + start,
248 *length, buffer->contents + start)
249 && base64_decode_final(&ctx))
250 return 1;
252 else
254 werror("Invalid base64 date.\n");
255 return 0;
259 static int
260 convert_rsa_public_key(struct nettle_buffer *buffer, unsigned length, const uint8_t *data)
262 struct rsa_public_key pub;
263 int res;
265 rsa_public_key_init(&pub);
267 if (rsa_keypair_from_der(&pub, NULL, 0,
268 length, data))
270 /* Reuses the buffer */
271 nettle_buffer_reset(buffer);
272 res = rsa_keypair_to_sexp(buffer, NULL, &pub, NULL);
274 else
276 werror("Invalid PKCS#1 public key.\n");
277 res = 0;
279 rsa_public_key_clear(&pub);
280 return res;
283 static int
284 convert_rsa_private_key(struct nettle_buffer *buffer, unsigned length, const uint8_t *data)
286 struct rsa_public_key pub;
287 struct rsa_private_key priv;
288 int res;
290 rsa_public_key_init(&pub);
291 rsa_private_key_init(&priv);
293 if (rsa_keypair_from_der(&pub, &priv, 0,
294 length, data))
296 /* Reuses the buffer */
297 nettle_buffer_reset(buffer);
298 res = rsa_keypair_to_sexp(buffer, NULL, &pub, &priv);
300 else
302 werror("Invalid PKCS#1 private key.\n");
303 res = 0;
305 rsa_public_key_clear(&pub);
306 rsa_private_key_clear(&priv);
308 return res;
311 static int
312 convert_dsa_private_key(struct nettle_buffer *buffer, unsigned length, const uint8_t *data)
314 struct dsa_public_key pub;
315 struct dsa_private_key priv;
316 int res;
318 dsa_public_key_init(&pub);
319 dsa_private_key_init(&priv);
321 if (dsa_openssl_private_key_from_der(&pub, &priv, 0,
322 length, data))
324 /* Reuses the buffer */
325 nettle_buffer_reset(buffer);
326 res = dsa_keypair_to_sexp(buffer, NULL, &pub, &priv);
328 else
330 werror("Invalid OpenSSL private key.\n");
331 res = 0;
333 dsa_public_key_clear(&pub);
334 dsa_private_key_clear(&priv);
336 return res;
339 /* Returns 1 on success, 0 on error, and -1 for unsupported algorithms. */
340 static int
341 convert_public_key(struct nettle_buffer *buffer, unsigned length, const uint8_t *data)
343 /* SubjectPublicKeyInfo ::= SEQUENCE {
344 algorithm AlgorithmIdentifier,
345 subjectPublicKey BIT STRING
348 AlgorithmIdentifier ::= SEQUENCE {
349 algorithm OBJECT IDENTIFIER,
350 parameters OPTIONAL
353 struct asn1_der_iterator i;
354 struct asn1_der_iterator j;
355 int res = 0;
357 if (asn1_der_iterator_first(&i, length, data) == ASN1_ITERATOR_CONSTRUCTED
358 && i.type == ASN1_SEQUENCE
359 && asn1_der_decode_constructed_last(&i) == ASN1_ITERATOR_CONSTRUCTED
360 && i.type == ASN1_SEQUENCE
362 /* Use the j iterator to parse the algorithm identifier */
363 && asn1_der_decode_constructed(&i, &j) == ASN1_ITERATOR_PRIMITIVE
364 && j.type == ASN1_IDENTIFIER
365 && asn1_der_iterator_next(&i) == ASN1_ITERATOR_PRIMITIVE
366 && i.type == ASN1_BITSTRING
368 /* Use i to parse the object wrapped in the bit string.*/
369 && asn1_der_decode_bitstring_last(&i))
371 /* pkcs-1 {
372 iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs-1(1)
373 modules(0) pkcs-1(1)
377 -- When rsaEncryption is used in an AlgorithmIdentifier the
378 -- parameters MUST be present and MUST be NULL.
380 rsaEncryption OBJECT IDENTIFIER ::= { pkcs-1 1 }
382 static const uint8_t id_rsaEncryption[9] =
383 { 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01 };
386 -- When dsa is used in an AlgorithmIdentifier the
387 -- parameters MUST be present and MUST NOT be NULL.
389 dsa OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) x9-57(10040) x9algorithm(4) 1 }
391 static const uint8_t id_dsa[7] =
392 { 0x2A, 0x86, 0x48, 0xCE, 0x38, 0x04, 0x01 };
394 switch (j.length)
396 unknown:
397 default:
398 werror("SubjectPublicKeyInfo: Unsupported algorithm.\n");
399 res = -1;
400 break;
402 case 7:
403 if (memcmp(j.data, id_dsa, 7) == 0)
405 if (asn1_der_iterator_next(&j) == ASN1_ITERATOR_CONSTRUCTED
406 && asn1_der_decode_constructed_last(&j) == ASN1_ITERATOR_PRIMITIVE)
408 struct dsa_public_key pub;
410 dsa_public_key_init(&pub);
412 if (dsa_params_from_der_iterator(&pub, 0, &i)
413 && dsa_public_key_from_der_iterator(&pub, 0, &j))
415 nettle_buffer_reset(buffer);
416 res = dsa_keypair_to_sexp(buffer, NULL, &pub, NULL) > 0;
418 dsa_public_key_clear(&pub);
420 if (!res)
421 werror("SubjectPublicKeyInfo: Invalid DSA key.\n");
422 break;
424 else goto unknown;
425 case 9:
426 if (memcmp(j.data, id_rsaEncryption, 9) == 0)
428 if (asn1_der_iterator_next(&j) == ASN1_ITERATOR_PRIMITIVE
429 && j.type == ASN1_NULL
430 && j.length == 0
431 && asn1_der_iterator_next(&j) == ASN1_ITERATOR_END)
433 struct rsa_public_key pub;
435 rsa_public_key_init(&pub);
437 if (rsa_public_key_from_der_iterator(&pub, 0, &i))
439 nettle_buffer_reset(buffer);
440 res = rsa_keypair_to_sexp(buffer, NULL, &pub, NULL) > 0;
442 rsa_public_key_clear(&pub);
444 if (!res)
445 werror("SubjectPublicKeyInfo: Invalid RSA key.\n");
446 break;
448 else goto unknown;
451 else
452 werror("SubjectPublicKeyInfo: Invalid object.\n");
454 return res;
457 /* NOTE: Destroys contents of buffer */
458 /* Returns 1 on success, 0 on error, and -1 for unsupported algorithms. */
459 static int
460 convert_type(struct nettle_buffer *buffer,
461 enum object_type type,
462 unsigned length, const uint8_t *data)
464 int res;
466 switch(type)
468 default:
469 abort();
471 case GENERAL_PUBLIC_KEY:
472 res = convert_public_key(buffer, length, data);
473 break;
475 case RSA_PUBLIC_KEY:
476 res = convert_rsa_public_key(buffer, length, data);
477 break;
479 case RSA_PRIVATE_KEY:
480 res = convert_rsa_private_key(buffer, length, data);
481 break;
483 case DSA_PRIVATE_KEY:
484 res = convert_dsa_private_key(buffer, length, data);
485 break;
488 if (res > 0)
489 res = write_file(buffer, stdout);
491 return res;
494 static int
495 convert_file(struct nettle_buffer *buffer,
496 FILE *f,
497 enum object_type type,
498 int base64)
500 if (type)
502 read_file(buffer, f);
503 if (base64 && !decode_base64(buffer, 0, &buffer->size))
504 return 0;
506 if (convert_type(buffer, type,
507 buffer->size, buffer->contents) != 1)
508 return 0;
510 return 1;
512 else
514 /* PEM processing */
515 for (;;)
517 struct pem_info info;
518 const uint8_t *marker;
520 nettle_buffer_reset(buffer);
521 switch (read_pem(buffer, f, &info))
523 default:
524 return 0;
525 case 1:
526 break;
527 case -1:
528 /* EOF */
529 return 1;
532 if (!decode_base64(buffer, info.data_start, &info.data_length))
533 return 0;
535 marker = buffer->contents + info.marker_start;
537 type = 0;
538 switch (info.marker_length)
540 case 10:
541 if (memcmp(marker, "PUBLIC KEY", 10) == 0)
543 type = GENERAL_PUBLIC_KEY;
544 break;
546 case 14:
547 if (memcmp(marker, "RSA PUBLIC KEY", 14) == 0)
549 type = RSA_PUBLIC_KEY;
550 break;
553 case 15:
554 if (memcmp(marker, "RSA PRIVATE KEY", 15) == 0)
556 type = RSA_PRIVATE_KEY;
557 break;
559 if (memcmp(marker, "DSA PRIVATE KEY", 15) == 0)
561 type = DSA_PRIVATE_KEY;
562 break;
566 if (!type)
567 werror("Ignoring unsupported object type `%s'.\n", marker);
569 else if (convert_type(buffer, type,
570 info.data_length,
571 buffer->contents + info.data_start) != 1)
572 return 0;
578 main(int argc, char **argv)
580 struct nettle_buffer buffer;
581 enum object_type type = 0;
582 int base64 = 0;
583 int c;
585 enum {
586 OPT_HELP = 0x300,
587 OPT_PRIVATE_RSA = RSA_PRIVATE_KEY,
588 OPT_PUBLIC_RSA = RSA_PUBLIC_KEY,
589 OPT_PRIVATE_DSA = DSA_PRIVATE_KEY,
590 OPT_PUBLIC_KEY = GENERAL_PUBLIC_KEY,
593 static const struct option options[] =
595 /* Name, args, flag, val */
596 { "help", no_argument, NULL, OPT_HELP },
597 { "version", no_argument, NULL, 'V' },
598 { "private-rsa-key", no_argument, NULL, OPT_PRIVATE_RSA },
599 { "public-rsa-key", no_argument, NULL, OPT_PUBLIC_RSA },
600 { "private-dsa-key", no_argument, NULL, OPT_PRIVATE_DSA },
601 { "public-key-info", no_argument, NULL, OPT_PUBLIC_KEY },
602 { "base-64", no_argument, NULL, 'b' },
603 { NULL, 0, NULL, 0 }
606 while ( (c = getopt_long(argc, argv, "Vb", options, NULL)) != -1)
608 switch (c)
610 default:
611 abort();
613 case 'b':
614 base64 = 1;
615 break;
617 case OPT_PRIVATE_RSA:
618 case OPT_PUBLIC_RSA:
619 case OPT_PRIVATE_DSA:
620 case OPT_PUBLIC_KEY:
621 /* Same values as the type codes. */
622 type = c;
623 break;
625 case OPT_HELP:
626 printf("FIXME: Usage information.\n");
627 return EXIT_SUCCESS;
628 case '?':
629 return EXIT_FAILURE;
631 case 'V':
632 printf("pkcs1-conv (" PACKAGE_STRING ")\n");
633 return EXIT_SUCCESS;
637 nettle_buffer_init_realloc(&buffer, NULL, nettle_xrealloc);
639 if (optind == argc)
641 if (!convert_file(&buffer, stdin, type, base64))
642 return EXIT_FAILURE;
644 else
646 int i;
647 const char *mode = (type || base64) ? "r" : "rb";
649 for (i = optind; i < argc; i++)
651 FILE *f = fopen(argv[i], mode);
652 if (!f)
653 die("Failed to open `%s': %s.\n", argv[i], strerror(errno));
655 if (!convert_file(&buffer, f, type, base64))
656 return EXIT_FAILURE;
658 fclose(f);
661 nettle_buffer_clear (&buffer);
663 return EXIT_SUCCESS;