1 /* 2 * 3 * authfile.c 4 * 5 * Author: Tatu Ylonen <ylo@cs.hut.fi> 6 * 7 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 8 * All rights reserved 9 * 10 * Created: Mon Mar 27 03:52:05 1995 ylo 11 * 12 * This file contains functions for reading and writing identity files, and 13 * for reading the passphrase from the user. 14 * 15 * $FreeBSD$ 16 */ 17 18 #include "includes.h" 19 RCSID("$Id: authfile.c,v 1.11 1999/12/06 19:11:15 deraadt Exp $"); 20 21 #include <openssl/bn.h> 22 #include "xmalloc.h" 23 #include "buffer.h" 24 #include "bufaux.h" 25 #include "cipher.h" 26 #include "ssh.h" 27 28 /* Version identification string for identity files. */ 29 #define AUTHFILE_ID_STRING "SSH PRIVATE KEY FILE FORMAT 1.1\n" 30 31 /* 32 * Saves the authentication (private) key in a file, encrypting it with 33 * passphrase. The identification of the file (lowest 64 bits of n) will 34 * precede the key to provide identification of the key without needing a 35 * passphrase. 36 */ 37 38 int 39 save_private_key(const char *filename, const char *passphrase, 40 RSA *key, const char *comment) 41 { 42 Buffer buffer, encrypted; 43 char buf[100], *cp; 44 int fd, i; 45 CipherContext cipher; 46 int cipher_type; 47 u_int32_t rand; 48 49 /* 50 * If the passphrase is empty, use SSH_CIPHER_NONE to ease converting 51 * to another cipher; otherwise use SSH_AUTHFILE_CIPHER. 52 */ 53 if (strcmp(passphrase, "") == 0) 54 cipher_type = SSH_CIPHER_NONE; 55 else 56 cipher_type = SSH_AUTHFILE_CIPHER; 57 58 /* This buffer is used to built the secret part of the private key. */ 59 buffer_init(&buffer); 60 61 /* Put checkbytes for checking passphrase validity. */ 62 rand = arc4random(); 63 buf[0] = rand & 0xff; 64 buf[1] = (rand >> 8) & 0xff; 65 buf[2] = buf[0]; 66 buf[3] = buf[1]; 67 buffer_append(&buffer, buf, 4); 68 69 /* 70 * Store the private key (n and e will not be stored because they 71 * will be stored in plain text, and storing them also in encrypted 72 * format would just give known plaintext). 73 */ 74 buffer_put_bignum(&buffer, key->d); 75 buffer_put_bignum(&buffer, key->iqmp); 76 buffer_put_bignum(&buffer, key->q); /* reverse from SSL p */ 77 buffer_put_bignum(&buffer, key->p); /* reverse from SSL q */ 78 79 /* Pad the part to be encrypted until its size is a multiple of 8. */ 80 while (buffer_len(&buffer) % 8 != 0) 81 buffer_put_char(&buffer, 0); 82 83 /* This buffer will be used to contain the data in the file. */ 84 buffer_init(&encrypted); 85 86 /* First store keyfile id string. */ 87 cp = AUTHFILE_ID_STRING; 88 for (i = 0; cp[i]; i++) 89 buffer_put_char(&encrypted, cp[i]); 90 buffer_put_char(&encrypted, 0); 91 92 /* Store cipher type. */ 93 buffer_put_char(&encrypted, cipher_type); 94 buffer_put_int(&encrypted, 0); /* For future extension */ 95 96 /* Store public key. This will be in plain text. */ 97 buffer_put_int(&encrypted, BN_num_bits(key->n)); 98 buffer_put_bignum(&encrypted, key->n); 99 buffer_put_bignum(&encrypted, key->e); 100 buffer_put_string(&encrypted, comment, strlen(comment)); 101 102 /* Allocate space for the private part of the key in the buffer. */ 103 buffer_append_space(&encrypted, &cp, buffer_len(&buffer)); 104 105 cipher_set_key_string(&cipher, cipher_type, passphrase, 1); 106 cipher_encrypt(&cipher, (unsigned char *) cp, 107 (unsigned char *) buffer_ptr(&buffer), 108 buffer_len(&buffer)); 109 memset(&cipher, 0, sizeof(cipher)); 110 111 /* Destroy temporary data. */ 112 memset(buf, 0, sizeof(buf)); 113 buffer_free(&buffer); 114 115 fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0600); 116 if (fd < 0) 117 return 0; 118 if (write(fd, buffer_ptr(&encrypted), buffer_len(&encrypted)) != 119 buffer_len(&encrypted)) { 120 debug("Write to key file %.200s failed: %.100s", filename, 121 strerror(errno)); 122 buffer_free(&encrypted); 123 close(fd); 124 remove(filename); 125 return 0; 126 } 127 close(fd); 128 buffer_free(&encrypted); 129 return 1; 130 } 131 132 /* 133 * Loads the public part of the key file. Returns 0 if an error was 134 * encountered (the file does not exist or is not readable), and non-zero 135 * otherwise. 136 */ 137 138 int 139 load_public_key(const char *filename, RSA * pub, 140 char **comment_return) 141 { 142 int fd, i; 143 off_t len; 144 Buffer buffer; 145 char *cp; 146 147 fd = open(filename, O_RDONLY); 148 if (fd < 0) 149 return 0; 150 len = lseek(fd, (off_t) 0, SEEK_END); 151 lseek(fd, (off_t) 0, SEEK_SET); 152 153 buffer_init(&buffer); 154 buffer_append_space(&buffer, &cp, len); 155 156 if (read(fd, cp, (size_t) len) != (size_t) len) { 157 debug("Read from key file %.200s failed: %.100s", filename, 158 strerror(errno)); 159 buffer_free(&buffer); 160 close(fd); 161 return 0; 162 } 163 close(fd); 164 165 /* Check that it is at least big enought to contain the ID string. */ 166 if (len < strlen(AUTHFILE_ID_STRING) + 1) { 167 debug("Bad key file %.200s.", filename); 168 buffer_free(&buffer); 169 return 0; 170 } 171 /* 172 * Make sure it begins with the id string. Consume the id string 173 * from the buffer. 174 */ 175 for (i = 0; i < (unsigned int) strlen(AUTHFILE_ID_STRING) + 1; i++) 176 if (buffer_get_char(&buffer) != (u_char) AUTHFILE_ID_STRING[i]) { 177 debug("Bad key file %.200s.", filename); 178 buffer_free(&buffer); 179 return 0; 180 } 181 /* Skip cipher type and reserved data. */ 182 (void) buffer_get_char(&buffer); /* cipher type */ 183 (void) buffer_get_int(&buffer); /* reserved */ 184 185 /* Read the public key from the buffer. */ 186 buffer_get_int(&buffer); 187 pub->n = BN_new(); 188 buffer_get_bignum(&buffer, pub->n); 189 pub->e = BN_new(); 190 buffer_get_bignum(&buffer, pub->e); 191 if (comment_return) 192 *comment_return = buffer_get_string(&buffer, NULL); 193 /* The encrypted private part is not parsed by this function. */ 194 195 buffer_free(&buffer); 196 197 return 1; 198 } 199 200 /* 201 * Loads the private key from the file. Returns 0 if an error is encountered 202 * (file does not exist or is not readable, or passphrase is bad). This 203 * initializes the private key. 204 * Assumes we are called under uid of the owner of the file. 205 */ 206 207 int 208 load_private_key(const char *filename, const char *passphrase, 209 RSA * prv, char **comment_return) 210 { 211 int fd, i, check1, check2, cipher_type; 212 off_t len; 213 Buffer buffer, decrypted; 214 char *cp; 215 CipherContext cipher; 216 BN_CTX *ctx; 217 BIGNUM *aux; 218 struct stat st; 219 220 fd = open(filename, O_RDONLY); 221 if (fd < 0) 222 return 0; 223 224 /* check owner and modes */ 225 if (fstat(fd, &st) < 0 || 226 (st.st_uid != 0 && st.st_uid != getuid()) || 227 (st.st_mode & 077) != 0) { 228 close(fd); 229 error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"); 230 error("@ WARNING: UNPROTECTED PRIVATE KEY FILE! @"); 231 error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"); 232 error("Bad ownership or mode(0%3.3o) for '%s'.", 233 st.st_mode & 0777, filename); 234 error("It is recommended that your private key files are NOT accessible by others."); 235 return 0; 236 } 237 len = lseek(fd, (off_t) 0, SEEK_END); 238 lseek(fd, (off_t) 0, SEEK_SET); 239 240 buffer_init(&buffer); 241 buffer_append_space(&buffer, &cp, len); 242 243 if (read(fd, cp, (size_t) len) != (size_t) len) { 244 debug("Read from key file %.200s failed: %.100s", filename, 245 strerror(errno)); 246 buffer_free(&buffer); 247 close(fd); 248 return 0; 249 } 250 close(fd); 251 252 /* Check that it is at least big enought to contain the ID string. */ 253 if (len < strlen(AUTHFILE_ID_STRING) + 1) { 254 debug("Bad key file %.200s.", filename); 255 buffer_free(&buffer); 256 return 0; 257 } 258 /* 259 * Make sure it begins with the id string. Consume the id string 260 * from the buffer. 261 */ 262 for (i = 0; i < (unsigned int) strlen(AUTHFILE_ID_STRING) + 1; i++) 263 if (buffer_get_char(&buffer) != (unsigned char) AUTHFILE_ID_STRING[i]) { 264 debug("Bad key file %.200s.", filename); 265 buffer_free(&buffer); 266 return 0; 267 } 268 /* Read cipher type. */ 269 cipher_type = buffer_get_char(&buffer); 270 (void) buffer_get_int(&buffer); /* Reserved data. */ 271 272 /* Read the public key from the buffer. */ 273 buffer_get_int(&buffer); 274 prv->n = BN_new(); 275 buffer_get_bignum(&buffer, prv->n); 276 prv->e = BN_new(); 277 buffer_get_bignum(&buffer, prv->e); 278 if (comment_return) 279 *comment_return = buffer_get_string(&buffer, NULL); 280 else 281 xfree(buffer_get_string(&buffer, NULL)); 282 283 /* Check that it is a supported cipher. */ 284 if (((cipher_mask() | SSH_CIPHER_NONE | SSH_AUTHFILE_CIPHER) & 285 (1 << cipher_type)) == 0) { 286 debug("Unsupported cipher %.100s used in key file %.200s.", 287 cipher_name(cipher_type), filename); 288 buffer_free(&buffer); 289 goto fail; 290 } 291 /* Initialize space for decrypted data. */ 292 buffer_init(&decrypted); 293 buffer_append_space(&decrypted, &cp, buffer_len(&buffer)); 294 295 /* Rest of the buffer is encrypted. Decrypt it using the passphrase. */ 296 cipher_set_key_string(&cipher, cipher_type, passphrase, 0); 297 cipher_decrypt(&cipher, (unsigned char *) cp, 298 (unsigned char *) buffer_ptr(&buffer), 299 buffer_len(&buffer)); 300 301 buffer_free(&buffer); 302 303 check1 = buffer_get_char(&decrypted); 304 check2 = buffer_get_char(&decrypted); 305 if (check1 != buffer_get_char(&decrypted) || 306 check2 != buffer_get_char(&decrypted)) { 307 if (strcmp(passphrase, "") != 0) 308 debug("Bad passphrase supplied for key file %.200s.", filename); 309 /* Bad passphrase. */ 310 buffer_free(&decrypted); 311 fail: 312 BN_clear_free(prv->n); 313 BN_clear_free(prv->e); 314 if (comment_return) 315 xfree(*comment_return); 316 return 0; 317 } 318 /* Read the rest of the private key. */ 319 prv->d = BN_new(); 320 buffer_get_bignum(&decrypted, prv->d); 321 prv->iqmp = BN_new(); 322 buffer_get_bignum(&decrypted, prv->iqmp); /* u */ 323 /* in SSL and SSH p and q are exchanged */ 324 prv->q = BN_new(); 325 buffer_get_bignum(&decrypted, prv->q); /* p */ 326 prv->p = BN_new(); 327 buffer_get_bignum(&decrypted, prv->p); /* q */ 328 329 ctx = BN_CTX_new(); 330 aux = BN_new(); 331 332 BN_sub(aux, prv->q, BN_value_one()); 333 prv->dmq1 = BN_new(); 334 BN_mod(prv->dmq1, prv->d, aux, ctx); 335 336 BN_sub(aux, prv->p, BN_value_one()); 337 prv->dmp1 = BN_new(); 338 BN_mod(prv->dmp1, prv->d, aux, ctx); 339 340 BN_clear_free(aux); 341 BN_CTX_free(ctx); 342 343 buffer_free(&decrypted); 344 345 return 1; 346 } 347