Annotation of src/usr.bin/ssh/authfile.c, Revision 1.2
1.1 deraadt 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: */
16:
17: #include "includes.h"
1.2 ! deraadt 18: RCSID("$Id: authfile.c,v 1.1 1999/09/26 20:53:33 deraadt Exp $");
1.1 deraadt 19:
20: #include <gmp.h>
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: /* Saves the authentication (private) key in a file, encrypting it with
31: passphrase. The identification of the file (lowest 64 bits of n)
32: will precede the key to provide identification of the key without
33: needing a passphrase. */
34:
35: int save_private_key(const char *filename, const char *passphrase,
36: RSAPrivateKey *key, const char *comment,
37: RandomState *state)
38: {
39: Buffer buffer, encrypted;
40: char buf[100], *cp;
41: int f, i;
42: CipherContext cipher;
43: int cipher_type;
44:
45: /* If the passphrase is empty, use SSH_CIPHER_NONE to ease converting to
46: another cipher; otherwise use SSH_AUTHFILE_CIPHER. */
47: if (strcmp(passphrase, "") == 0)
48: cipher_type = SSH_CIPHER_NONE;
49: else
50: cipher_type = SSH_AUTHFILE_CIPHER;
51:
52: /* This buffer is used to built the secret part of the private key. */
53: buffer_init(&buffer);
54:
55: /* Put checkbytes for checking passphrase validity. */
56: buf[0] = random_get_byte(state);
57: buf[1] = random_get_byte(state);
58: buf[2] = buf[0];
59: buf[3] = buf[1];
60: buffer_append(&buffer, buf, 4);
61:
62: /* Store the private key (n and e will not be stored because they will
63: be stored in plain text, and storing them also in encrypted format
64: would just give known plaintext). */
65: buffer_put_mp_int(&buffer, &key->d);
66: buffer_put_mp_int(&buffer, &key->u);
67: buffer_put_mp_int(&buffer, &key->p);
68: buffer_put_mp_int(&buffer, &key->q);
69:
70: /* Pad the part to be encrypted until its size is a multiple of 8. */
71: while (buffer_len(&buffer) % 8 != 0)
72: buffer_put_char(&buffer, 0);
73:
74: /* This buffer will be used to contain the data in the file. */
75: buffer_init(&encrypted);
76:
77: /* First store keyfile id string. */
78: cp = AUTHFILE_ID_STRING;
79: for (i = 0; cp[i]; i++)
80: buffer_put_char(&encrypted, cp[i]);
81: buffer_put_char(&encrypted, 0);
82:
83: /* Store cipher type. */
84: buffer_put_char(&encrypted, cipher_type);
85: buffer_put_int(&encrypted, 0); /* For future extension */
86:
87: /* Store public key. This will be in plain text. */
88: buffer_put_int(&encrypted, key->bits);
89: buffer_put_mp_int(&encrypted, &key->n);
90: buffer_put_mp_int(&encrypted, &key->e);
91: buffer_put_string(&encrypted, comment, strlen(comment));
92:
93: /* Allocate space for the private part of the key in the buffer. */
94: buffer_append_space(&encrypted, &cp, buffer_len(&buffer));
95:
96: cipher_set_key_string(&cipher, cipher_type, passphrase, 1);
97: cipher_encrypt(&cipher, (unsigned char *)cp,
98: (unsigned char *)buffer_ptr(&buffer),
99: buffer_len(&buffer));
100: memset(&cipher, 0, sizeof(cipher));
101:
102: /* Destroy temporary data. */
103: memset(buf, 0, sizeof(buf));
104: buffer_free(&buffer);
105:
106: /* Write to a file. */
107: f = open(filename, O_WRONLY|O_CREAT|O_TRUNC, 0600);
108: if (f < 0)
109: return 0;
110:
111: if (write(f, buffer_ptr(&encrypted), buffer_len(&encrypted)) !=
112: buffer_len(&encrypted))
113: {
114: debug("Write to key file %.200s failed: %.100s", filename,
115: strerror(errno));
116: buffer_free(&encrypted);
117: close(f);
118: remove(filename);
119: return 0;
120: }
121: close(f);
122: buffer_free(&encrypted);
123: return 1;
124: }
125:
126: /* Loads the public part of the key file. Returns 0 if an error
127: was encountered (the file does not exist or is not readable), and
128: non-zero otherwise. */
129:
130: int load_public_key(const char *filename, RSAPublicKey *pub,
131: char **comment_return)
132: {
133: int f, i;
134: unsigned long len;
135: Buffer buffer;
136: char *cp;
137:
138: /* Read data from the file into the buffer. */
139: f = open(filename, O_RDONLY);
140: if (f < 0)
141: return 0;
142:
143: len = lseek(f, (off_t)0L, 2);
144: lseek(f, (off_t)0L, 0);
145:
146: buffer_init(&buffer);
147: buffer_append_space(&buffer, &cp, len);
148:
149: if (read(f, cp, len) != len)
150: {
151: debug("Read from key file %.200s failed: %.100s", filename,
152: strerror(errno));
153: buffer_free(&buffer);
154: close(f);
155: return 0;
156: }
157: close(f);
158:
159: /* Check that it is at least big enought to contain the ID string. */
160: if (len < strlen(AUTHFILE_ID_STRING) + 1)
161: {
162: debug("Bad key file %.200s.", filename);
163: buffer_free(&buffer);
164: return 0;
165: }
166:
167: /* Make sure it begins with the id string. Consume the id string from
168: the buffer. */
169: for (i = 0; i < (unsigned int)strlen(AUTHFILE_ID_STRING) + 1; i++)
170: if (buffer_get_char(&buffer) != (unsigned char)AUTHFILE_ID_STRING[i])
171: {
172: debug("Bad key file %.200s.", filename);
173: buffer_free(&buffer);
174: return 0;
175: }
176:
177: /* Skip cipher type and reserved data. */
178: (void)buffer_get_char(&buffer); /* cipher type */
179: (void)buffer_get_int(&buffer); /* reserved */
180:
181: /* Read the public key from the buffer. */
182: pub->bits = buffer_get_int(&buffer);
183: mpz_init(&pub->n);
184: buffer_get_mp_int(&buffer, &pub->n);
185: mpz_init(&pub->e);
186: buffer_get_mp_int(&buffer, &pub->e);
187: if (comment_return)
188: *comment_return = buffer_get_string(&buffer, NULL);
189: /* The encrypted private part is not parsed by this function. */
190:
191: buffer_free(&buffer);
192:
193: return 1;
194: }
195:
196: /* Loads the private key from the file. Returns 0 if an error is encountered
197: (file does not exist or is not readable, or passphrase is bad).
198: This initializes the private key. */
199:
200: int load_private_key(const char *filename, const char *passphrase,
201: RSAPrivateKey *prv, char **comment_return)
202: {
203: int f, i, check1, check2, cipher_type;
204: unsigned long len;
205: Buffer buffer, decrypted;
206: char *cp;
207: CipherContext cipher;
208:
209: /* Read the file into the buffer. */
210: f = open(filename, O_RDONLY);
211: if (f < 0)
212: return 0;
213:
214: len = lseek(f, (off_t)0L, 2);
215: lseek(f, (off_t)0L, 0);
216:
217: buffer_init(&buffer);
218: buffer_append_space(&buffer, &cp, len);
219:
220: if (read(f, cp, len) != len)
221: {
222: debug("Read from key file %.200s failed: %.100s", filename,
223: strerror(errno));
224: buffer_free(&buffer);
225: close(f);
226: return 0;
227: }
228: close(f);
229:
230: /* Check that it is at least big enought to contain the ID string. */
231: if (len < strlen(AUTHFILE_ID_STRING) + 1)
232: {
233: debug("Bad key file %.200s.", filename);
234: buffer_free(&buffer);
235: return 0;
236: }
237:
238: /* Make sure it begins with the id string. Consume the id string from
239: the buffer. */
240: for (i = 0; i < (unsigned int)strlen(AUTHFILE_ID_STRING) + 1; i++)
241: if (buffer_get_char(&buffer) != (unsigned char)AUTHFILE_ID_STRING[i])
242: {
243: debug("Bad key file %.200s.", filename);
244: buffer_free(&buffer);
245: return 0;
246: }
247:
248: /* Read cipher type. */
249: cipher_type = buffer_get_char(&buffer);
250: (void)buffer_get_int(&buffer); /* Reserved data. */
251:
252: /* Read the public key from the buffer. */
253: prv->bits = buffer_get_int(&buffer);
254: mpz_init(&prv->n);
255: buffer_get_mp_int(&buffer, &prv->n);
256: mpz_init(&prv->e);
257: buffer_get_mp_int(&buffer, &prv->e);
258: if (comment_return)
259: *comment_return = buffer_get_string(&buffer, NULL);
260: else
261: xfree(buffer_get_string(&buffer, NULL));
262:
263: /* Check that it is a supported cipher. */
264: if ((cipher_mask() & (1 << cipher_type)) == 0)
265: {
266: debug("Unsupported cipher %.100s used in key file %.200s.",
267: cipher_name(cipher_type), filename);
268: buffer_free(&buffer);
269: goto fail;
270: }
271:
272: /* Initialize space for decrypted data. */
273: buffer_init(&decrypted);
274: buffer_append_space(&decrypted, &cp, buffer_len(&buffer));
275:
276: /* Rest of the buffer is encrypted. Decrypt it using the passphrase. */
277: cipher_set_key_string(&cipher, cipher_type, passphrase, 0);
278: cipher_decrypt(&cipher, (unsigned char *)cp,
279: (unsigned char *)buffer_ptr(&buffer),
280: buffer_len(&buffer));
281:
282: buffer_free(&buffer);
283:
284: check1 = buffer_get_char(&decrypted);
285: check2 = buffer_get_char(&decrypted);
286: if (check1 != buffer_get_char(&decrypted) ||
287: check2 != buffer_get_char(&decrypted))
288: {
289: if (strcmp(passphrase, "") != 0)
290: debug("Bad passphrase supplied for key file %.200s.", filename);
291: /* Bad passphrase. */
292: buffer_free(&decrypted);
293: fail:
294: mpz_clear(&prv->n);
295: mpz_clear(&prv->e);
296: if (comment_return)
297: xfree(*comment_return);
298: return 0;
299: }
300:
301: /* Read the rest of the private key. */
302: mpz_init(&prv->d);
303: buffer_get_mp_int(&decrypted, &prv->d);
304: mpz_init(&prv->u);
305: buffer_get_mp_int(&decrypted, &prv->u);
306: mpz_init(&prv->p);
307: buffer_get_mp_int(&decrypted, &prv->p);
308: mpz_init(&prv->q);
309: buffer_get_mp_int(&decrypted, &prv->q);
310:
311: buffer_free(&decrypted);
312:
313: return 1;
314: }