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
33void
34key_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 */
51void
52key_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 */
96char *
97key_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.  */
114void *
115key_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 */
144void
145key_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