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