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
key_free(int type,int private,void * key)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
key_serialize(int type,int private,void * key,u_int8_t ** data,size_t * datalenp)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 *
key_printable(int type,int private,u_int8_t * data,size_t datalen)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 *
key_internalize(int type,int private,u_int8_t * data,size_t datalen)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
key_from_printable(int type,int private,char * key,u_int8_t ** data,u_int32_t * datalenp)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