646447c1add1dad537ddfafbb1bf4cdf31244123
[strongswan.git] / src / pluto / pem.c
1 /* Loading of PEM encoded files with optional encryption
2 * Copyright (C) 2001-2009 Andreas Steffen
3 * HSR Hochschule fuer Technik Rapperswil
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * for more details.
14 */
15
16 /* decrypt a PEM encoded data block using DES-EDE3-CBC
17 * see RFC 1423 PEM: Algorithms, Modes and Identifiers
18 */
19
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <unistd.h>
23 #include <errno.h>
24 #include <string.h>
25 #include <stddef.h>
26 #include <sys/types.h>
27
28 #include <freeswan.h>
29
30 #include <library.h>
31 #include <asn1/pem.h>
32
33 #include "constants.h"
34 #include "defs.h"
35 #include "log.h"
36 #include "whack.h"
37 #include "pem.h"
38
39 /**
40 * Converts a PEM encoded file into its binary form
41 * RFC 1421 Privacy Enhancement for Electronic Mail, February 1993
42 * RFC 934 Message Encapsulation, January 1985
43 */
44 err_t pemtobin(chunk_t *blob, prompt_pass_t *pass, const char* label, bool *pgp)
45 {
46 chunk_t password = chunk_empty;
47
48 /* do we prompt for the passphrase? */
49 if (pass && pass->prompt && pass->fd != NULL_FD)
50 {
51 int i;
52 chunk_t blob_copy;
53 err_t ugh = "invalid passphrase, too many trials";
54 status_t status;
55
56 whack_log(RC_ENTERSECRET, "need passphrase for '%s'", label);
57
58 for (i = 0; i < MAX_PROMPT_PASS_TRIALS; i++)
59 {
60 int n;
61
62 if (i > 0)
63 {
64 whack_log(RC_ENTERSECRET, "invalid passphrase, please try again");
65 }
66 n = read(pass->fd, pass->secret, PROMPT_PASS_LEN);
67
68 if (n == -1)
69 {
70 err_t ugh = "read(whackfd) failed";
71
72 whack_log(RC_LOG_SERIOUS,ugh);
73 return ugh;
74 }
75
76 pass->secret[n-1] = '\0';
77
78 if (strlen(pass->secret) == 0)
79 {
80 err_t ugh = "no passphrase entered, aborted";
81
82 whack_log(RC_LOG_SERIOUS, ugh);
83 return ugh;
84 }
85
86 blob_copy = chunk_clone(*blob);
87 password = chunk_create(pass->secret, strlen(pass->secret));
88
89 status = pem_to_bin(blob, password, pgp);
90 if (status != INVALID_ARG)
91 {
92 if (status == SUCCESS)
93 {
94 whack_log(RC_SUCCESS, "valid passphrase");
95 }
96 else
97 {
98 whack_log(RC_LOG_SERIOUS, "%N, aborted", status_names, status);
99 }
100 free(blob_copy.ptr);
101 return NULL;
102 }
103
104 /* blob is useless after wrong decryption, restore the original */
105 free(blob->ptr);
106 *blob = blob_copy;
107 }
108 whack_log(RC_LOG_SERIOUS, ugh);
109 return ugh;
110 }
111 else
112 {
113 if (pass)
114 {
115 password = chunk_create(pass->secret, strlen(pass->secret));
116 }
117 if (pem_to_bin(blob, password, pgp) == SUCCESS)
118 {
119 return NULL;
120 }
121 else
122 {
123 return "pem to bin conversion failed";
124 }
125 }
126 }