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