xref: /openbsd/sbin/isakmpd/key.c (revision 73471bf0)
1 /* $OpenBSD: key.c,v 1.27 2021/10/13 16:57:43 tb 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 <netinet/in.h>
24 #include <string.h>
25 #include <stdlib.h>
26 
27 #include "key.h"
28 #include "libcrypto.h"
29 #include "log.h"
30 #include "util.h"
31 #include "x509.h"
32 
33 void
34 key_free(int type, int private, void *key)
35 {
36 	switch (type) {
37 	case ISAKMP_KEY_PASSPHRASE:
38 		free(key);
39 		break;
40 	case ISAKMP_KEY_RSA:
41 		RSA_free(key);
42 		break;
43 	case ISAKMP_KEY_NONE:
44 	default:
45 		log_error("key_free: unknown/unsupportedkey type %d", type);
46 		break;
47 	}
48 }
49 
50 /* Convert from internal form to serialized */
51 void
52 key_serialize(int type, int private, void *key, u_int8_t **data,
53     size_t *datalenp)
54 {
55 	u_int8_t       *p;
56 	size_t		datalen;
57 
58 	switch (type) {
59 	case ISAKMP_KEY_PASSPHRASE:
60 		*datalenp = strlen((char *)key);
61 		*data = (u_int8_t *)strdup((char *)key);
62 		break;
63 	case ISAKMP_KEY_RSA:
64 		switch (private) {
65 		case ISAKMP_KEYTYPE_PUBLIC:
66 			datalen = i2d_RSAPublicKey((RSA *)key, NULL);
67 			*data = p = malloc(datalen);
68 			if (!p) {
69 				log_error("key_serialize: malloc (%lu) failed",
70 				    (unsigned long)datalen);
71 				return;
72 			}
73 			*datalenp = i2d_RSAPublicKey((RSA *) key, &p);
74 			break;
75 
76 		case ISAKMP_KEYTYPE_PRIVATE:
77 			datalen = i2d_RSAPrivateKey((RSA *)key, NULL);
78 			*data = p = malloc(datalen);
79 			if (!p) {
80 				log_error("key_serialize: malloc (%lu) failed",
81 				    (unsigned long)datalen);
82 				return;
83 			}
84 			*datalenp = i2d_RSAPrivateKey((RSA *)key, &p);
85 			break;
86 		}
87 		break;
88 	default:
89 		log_error("key_serialize: unknown/unsupported key type %d",
90 		    type);
91 		break;
92 	}
93 }
94 
95 /* Convert from serialized to printable */
96 char *
97 key_printable(int type, int private, u_int8_t *data, size_t datalen)
98 {
99 	switch (type) {
100 	case ISAKMP_KEY_PASSPHRASE:
101 		return strdup((char *)data);
102 
103 	case ISAKMP_KEY_RSA:
104 		return raw2hex(data, datalen);
105 
106 	default:
107 		log_error("key_printable: unknown/unsupported key type %d",
108 		    type);
109 		return 0;
110 	}
111 }
112 
113 /* Convert from serialized to internal.  */
114 void *
115 key_internalize(int type, int private, u_int8_t *data, size_t datalen)
116 {
117 	switch (type) {
118 	case ISAKMP_KEY_PASSPHRASE:
119 		return strdup((char *)data);
120 	case ISAKMP_KEY_RSA:
121 		switch (private) {
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 		default:
129 			log_error("key_internalize: not public or private "
130 			    "RSA key passed");
131 			return 0;
132 		}
133 		break;
134 	default:
135 		log_error("key_internalize: unknown/unsupported key type %d",
136 		    type);
137 		break;
138 	}
139 
140 	return 0;
141 }
142 
143 /* Convert from printable to serialized */
144 void
145 key_from_printable(int type, int private, char *key, u_int8_t **data,
146     u_int32_t *datalenp)
147 {
148 	u_int32_t datalen;
149 
150 	switch (type) {
151 	case ISAKMP_KEY_PASSPHRASE:
152 		*datalenp = strlen(key);
153 		*data = (u_int8_t *) strdup(key);
154 		break;
155 
156 	case ISAKMP_KEY_RSA:
157 		datalen = (strlen(key) + 1) / 2; /* Round up, just in case */
158 		*data = malloc(datalen);
159 		if (!*data) {
160 			log_error("key_from_printable: malloc (%d) failed",
161 			    datalen);
162 			*datalenp = 0;
163 			return;
164 		}
165 		if (hex2raw(key, *data, datalen)) {
166 			log_error("key_from_printable: invalid hex key");
167 			free(*data);
168 			*data = NULL;
169 			*datalenp = 0;
170 			return;
171 		}
172 		*datalenp = datalen;
173 		break;
174 
175 	default:
176 		log_error("key_from_printable: "
177 		    "unknown/unsupported key type %d", type);
178 		*data = NULL;
179 		*datalenp = 0;
180 		break;
181 	}
182 }
183