xref: /openbsd/sbin/isakmpd/key.c (revision 264ca280)
1 /* $OpenBSD: key.c,v 1.25 2007/03/05 20:11:40 moritz Exp $	 */
2 /*
3  * The author of this code is Angelos D. Keromytis (angelos@cis.upenn.edu)
4  *
5  * Copyright (c) 2000-2001 Angelos D. Keromytis.
6  *
7  * Permission to use, copy, and modify this software with or without fee
8  * is hereby granted, provided that this entire notice is included in
9  * all copies of any software which is or includes a copy or
10  * modification of this software.
11  * You may use this code under the GNU public license if you so wish. Please
12  * contribute changes back to the authors under this freer than GPL license
13  * so that we may further the use of strong encryption without limitations to
14  * all.
15  *
16  * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR
17  * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY
18  * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE
19  * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
20  * PURPOSE.
21  */
22 
23 #include <string.h>
24 #include <stdlib.h>
25 
26 #include "key.h"
27 #include "libcrypto.h"
28 #include "log.h"
29 #include "util.h"
30 #include "x509.h"
31 
32 void
33 key_free(int type, int private, void *key)
34 {
35 	switch (type) {
36 	case ISAKMP_KEY_PASSPHRASE:
37 		free(key);
38 		break;
39 	case ISAKMP_KEY_RSA:
40 		RSA_free(key);
41 		break;
42 	case ISAKMP_KEY_NONE:
43 	default:
44 		log_error("key_free: unknown/unsupportedkey type %d", type);
45 		break;
46 	}
47 }
48 
49 /* Convert from internal form to serialized */
50 void
51 key_serialize(int type, int private, void *key, u_int8_t **data,
52     size_t *datalenp)
53 {
54 	u_int8_t       *p;
55 	size_t		datalen;
56 
57 	switch (type) {
58 	case ISAKMP_KEY_PASSPHRASE:
59 		*datalenp = strlen((char *)key);
60 		*data = (u_int8_t *)strdup((char *)key);
61 		break;
62 	case ISAKMP_KEY_RSA:
63 		switch (private) {
64 		case ISAKMP_KEYTYPE_PUBLIC:
65 			datalen = i2d_RSAPublicKey((RSA *)key, NULL);
66 			*data = p = malloc(datalen);
67 			if (!p) {
68 				log_error("key_serialize: malloc (%lu) failed",
69 				    (unsigned long)datalen);
70 				return;
71 			}
72 			*datalenp = i2d_RSAPublicKey((RSA *) key, &p);
73 			break;
74 
75 		case ISAKMP_KEYTYPE_PRIVATE:
76 			datalen = i2d_RSAPrivateKey((RSA *)key, NULL);
77 			*data = p = malloc(datalen);
78 			if (!p) {
79 				log_error("key_serialize: malloc (%lu) failed",
80 				    (unsigned long)datalen);
81 				return;
82 			}
83 			*datalenp = i2d_RSAPrivateKey((RSA *)key, &p);
84 			break;
85 		}
86 		break;
87 	default:
88 		log_error("key_serialize: unknown/unsupported key type %d",
89 		    type);
90 		break;
91 	}
92 }
93 
94 /* Convert from serialized to printable */
95 char *
96 key_printable(int type, int private, u_int8_t *data, size_t datalen)
97 {
98 	switch (type) {
99 	case ISAKMP_KEY_PASSPHRASE:
100 		return strdup((char *)data);
101 
102 	case ISAKMP_KEY_RSA:
103 		return raw2hex(data, datalen);
104 
105 	default:
106 		log_error("key_printable: unknown/unsupported key type %d",
107 		    type);
108 		return 0;
109 	}
110 }
111 
112 /* Convert from serialized to internal.  */
113 void *
114 key_internalize(int type, int private, u_int8_t *data, size_t datalen)
115 {
116 	switch (type) {
117 	case ISAKMP_KEY_PASSPHRASE:
118 		return strdup((char *)data);
119 	case ISAKMP_KEY_RSA:
120 		switch (private) {
121 #if OPENSSL_VERSION_NUMBER >= 0x00907000L
122 		case ISAKMP_KEYTYPE_PUBLIC:
123 			return d2i_RSAPublicKey(NULL,
124 			    (const u_int8_t **)&data, datalen);
125 		case ISAKMP_KEYTYPE_PRIVATE:
126 			return d2i_RSAPrivateKey(NULL,
127 			    (const u_int8_t **)&data, datalen);
128 #else
129 		case ISAKMP_KEYTYPE_PUBLIC:
130 			return d2i_RSAPublicKey(NULL, &data, datalen);
131 		case ISAKMP_KEYTYPE_PRIVATE:
132 			return d2i_RSAPrivateKey(NULL, &data, datalen);
133 #endif
134 		default:
135 			log_error("key_internalize: not public or private "
136 			    "RSA key passed");
137 			return 0;
138 		}
139 		break;
140 	default:
141 		log_error("key_internalize: unknown/unsupported key type %d",
142 		    type);
143 		break;
144 	}
145 
146 	return 0;
147 }
148 
149 /* Convert from printable to serialized */
150 void
151 key_from_printable(int type, int private, char *key, u_int8_t **data,
152     u_int32_t *datalenp)
153 {
154 	u_int32_t datalen;
155 
156 	switch (type) {
157 	case ISAKMP_KEY_PASSPHRASE:
158 		*datalenp = strlen(key);
159 		*data = (u_int8_t *) strdup(key);
160 		break;
161 
162 	case ISAKMP_KEY_RSA:
163 		datalen = (strlen(key) + 1) / 2; /* Round up, just in case */
164 		*data = malloc(datalen);
165 		if (!*data) {
166 			log_error("key_from_printable: malloc (%d) failed",
167 			    datalen);
168 			*datalenp = 0;
169 			return;
170 		}
171 		if (hex2raw(key, *data, datalen)) {
172 			log_error("key_from_printable: invalid hex key");
173 			free(*data);
174 			*data = NULL;
175 			*datalenp = 0;
176 			return;
177 		}
178 		*datalenp = datalen;
179 		break;
180 
181 	default:
182 		log_error("key_from_printable: "
183 		    "unknown/unsupported key type %d", type);
184 		*data = NULL;
185 		*datalenp = 0;
186 		break;
187 	}
188 }
189