summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDamien Miller <djm@mindrot.org>2013-12-07 10:41:55 +1100
committerDamien Miller <djm@mindrot.org>2013-12-07 10:41:55 +1100
commitbcd00abd8451f36142ae2ee10cc657202149201e (patch)
tree946db23f1ec607d9260e46b9f6f2422e0e9c970c
parentf0e9060d236c0e38bec2fa1c6579fb0a2ea6458d (diff)
- markus@cvs.openbsd.org 2013/12/06 13:34:54
[authfile.c authfile.h cipher.c cipher.h key.c packet.c ssh-agent.c] [ssh-keygen.c PROTOCOL.key] new private key format, bcrypt as KDF by default; details in PROTOCOL.key; feedback and lots help from djm; ok djm@
-rw-r--r--ChangeLog5
-rw-r--r--PROTOCOL.key68
-rw-r--r--authfile.c371
-rw-r--r--authfile.h5
-rw-r--r--cipher.c18
-rw-r--r--cipher.h4
-rw-r--r--key.c3
-rw-r--r--packet.c27
-rw-r--r--ssh-agent.c3
-rw-r--r--ssh-keygen.c51
10 files changed, 505 insertions, 50 deletions
diff --git a/ChangeLog b/ChangeLog
index 0db8ab446..76854907d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -12,6 +12,11 @@
12 - markus@cvs.openbsd.org 2013/12/06 13:30:08 12 - markus@cvs.openbsd.org 2013/12/06 13:30:08
13 [authfd.c key.c key.h ssh-agent.c] 13 [authfd.c key.c key.h ssh-agent.c]
14 move private key (de)serialization to key.c; ok djm 14 move private key (de)serialization to key.c; ok djm
15 - markus@cvs.openbsd.org 2013/12/06 13:34:54
16 [authfile.c authfile.h cipher.c cipher.h key.c packet.c ssh-agent.c]
17 [ssh-keygen.c PROTOCOL.key] new private key format, bcrypt as KDF by
18 default; details in PROTOCOL.key; feedback and lots help from djm;
19 ok djm@
15 20
1620131205 2120131205
17 - (djm) OpenBSD CVS Sync 22 - (djm) OpenBSD CVS Sync
diff --git a/PROTOCOL.key b/PROTOCOL.key
new file mode 100644
index 000000000..959bd7aee
--- /dev/null
+++ b/PROTOCOL.key
@@ -0,0 +1,68 @@
1This document describes the private key format for OpenSSH.
2
31. Overall format
4
5The key consists of a header, a list of public keys, and
6an encrypted list of matching private keys.
7
8#define AUTH_MAGIC "openssh-key-v1"
9
10 byte[] AUTH_MAGIC
11 string ciphername
12 string kdfname
13 string kdfoptions
14 int number of keys N
15 string publickey1
16 string publickey2
17 ...
18 string publickeyN
19 string encrypted, padded list of private keys
20
212. KDF options for kdfname "bcrypt"
22
23The options:
24
25 string salt
26 uint32 rounds
27
28are concatenated and represented as a string.
29
303. Unencrypted list of N private keys
31
32The list of privatekey/comment pairs is padded with the
33bytes 1, 2, 3, ... until the total length is a multiple
34of the cipher block size.
35
36 uint32 checkint
37 uint32 checkint
38 string privatekey1
39 string comment1
40 string privatekey2
41 string comment2
42 ...
43 string privatekeyN
44 string commentN
45 char 1
46 char 2
47 char 3
48 ...
49 char padlen % 255
50
51Before the key is encrypted, a random integer is assigned
52to both checkint fields so successful decryption can be
53quickly checked by verifying that both checkint fields
54hold the same value.
55
564. Encryption
57
58The KDF is used to derive a key, IV (and other values required by
59the cipher) from the passphrase. These values are then used to
60encrypt the unencrypted list of private keys.
61
625. No encryption
63
64For unencrypted keys the cipher "none" and the KDF "none"
65are used with empty passphrases. The options if the KDF "none"
66are the empty string.
67
68$OpenBSD: PROTOCOL.key,v 1.1 2013/12/06 13:34:54 markus Exp $
diff --git a/authfile.c b/authfile.c
index d0c1089eb..e38a3dd14 100644
--- a/authfile.c
+++ b/authfile.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: authfile.c,v 1.98 2013/11/21 00:45:43 djm Exp $ */ 1/* $OpenBSD: authfile.c,v 1.99 2013/12/06 13:34:54 markus Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -13,7 +13,7 @@
13 * called by a name other than "ssh" or "Secure Shell". 13 * called by a name other than "ssh" or "Secure Shell".
14 * 14 *
15 * 15 *
16 * Copyright (c) 2000 Markus Friedl. All rights reserved. 16 * Copyright (c) 2000, 2013 Markus Friedl. All rights reserved.
17 * 17 *
18 * Redistribution and use in source and binary forms, with or without 18 * Redistribution and use in source and binary forms, with or without
19 * modification, are permitted provided that the following conditions 19 * modification, are permitted provided that the following conditions
@@ -58,6 +58,8 @@
58#include <string.h> 58#include <string.h>
59#include <unistd.h> 59#include <unistd.h>
60 60
61#include <util.h>
62
61#include "xmalloc.h" 63#include "xmalloc.h"
62#include "cipher.h" 64#include "cipher.h"
63#include "buffer.h" 65#include "buffer.h"
@@ -68,6 +70,16 @@
68#include "rsa.h" 70#include "rsa.h"
69#include "misc.h" 71#include "misc.h"
70#include "atomicio.h" 72#include "atomicio.h"
73#include "uuencode.h"
74
75/* openssh private key file format */
76#define MARK_BEGIN "-----BEGIN OPENSSH PRIVATE KEY-----\n"
77#define MARK_END "-----END OPENSSH PRIVATE KEY-----\n"
78#define KDFNAME "bcrypt"
79#define AUTH_MAGIC "openssh-key-v1"
80#define SALT_LEN 16
81#define DEFAULT_CIPHERNAME "aes256-cbc"
82#define DEFAULT_ROUNDS 16
71 83
72#define MAX_KEY_FILE_SIZE (1024 * 1024) 84#define MAX_KEY_FILE_SIZE (1024 * 1024)
73 85
@@ -75,6 +87,333 @@
75static const char authfile_id_string[] = 87static const char authfile_id_string[] =
76 "SSH PRIVATE KEY FILE FORMAT 1.1\n"; 88 "SSH PRIVATE KEY FILE FORMAT 1.1\n";
77 89
90static int
91key_private_to_blob2(Key *prv, Buffer *blob, const char *passphrase,
92 const char *comment, const char *ciphername, int rounds)
93{
94 u_char *key, *cp, salt[SALT_LEN];
95 size_t keylen, ivlen, blocksize, authlen;
96 u_int len, check;
97 int i, n;
98 const Cipher *c;
99 Buffer encoded, b, kdf;
100 CipherContext ctx;
101 const char *kdfname = KDFNAME;
102
103 if (rounds <= 0)
104 rounds = DEFAULT_ROUNDS;
105 if (passphrase == NULL || !strlen(passphrase)) {
106 ciphername = "none";
107 kdfname = "none";
108 } else if (ciphername == NULL)
109 ciphername = DEFAULT_CIPHERNAME;
110 else if (cipher_number(ciphername) != SSH_CIPHER_SSH2)
111 fatal("invalid cipher");
112
113 if ((c = cipher_by_name(ciphername)) == NULL)
114 fatal("unknown cipher name");
115 buffer_init(&kdf);
116 blocksize = cipher_blocksize(c);
117 keylen = cipher_keylen(c);
118 ivlen = cipher_ivlen(c);
119 authlen = cipher_authlen(c);
120 key = xcalloc(1, keylen + ivlen);
121 if (strcmp(kdfname, "none") != 0) {
122 arc4random_buf(salt, SALT_LEN);
123 if (bcrypt_pbkdf(passphrase, strlen(passphrase),
124 salt, SALT_LEN, key, keylen + ivlen, rounds) < 0)
125 fatal("bcrypt_pbkdf failed");
126 buffer_put_string(&kdf, salt, SALT_LEN);
127 buffer_put_int(&kdf, rounds);
128 }
129 cipher_init(&ctx, c, key, keylen, key + keylen , ivlen, 1);
130 memset(key, 0, keylen + ivlen);
131 free(key);
132
133 buffer_init(&encoded);
134 buffer_append(&encoded, AUTH_MAGIC, sizeof(AUTH_MAGIC));
135 buffer_put_cstring(&encoded, ciphername);
136 buffer_put_cstring(&encoded, kdfname);
137 buffer_put_string(&encoded, buffer_ptr(&kdf), buffer_len(&kdf));
138 buffer_put_int(&encoded, 1); /* number of keys */
139 key_to_blob(prv, &cp, &len); /* public key */
140 buffer_put_string(&encoded, cp, len);
141
142 memset(cp, 0, len);
143 free(cp);
144
145 buffer_free(&kdf);
146
147 /* set up the buffer that will be encrypted */
148 buffer_init(&b);
149
150 /* Random check bytes */
151 check = arc4random();
152 buffer_put_int(&b, check);
153 buffer_put_int(&b, check);
154
155 /* append private key and comment*/
156 key_private_serialize(prv, &b);
157 buffer_put_cstring(&b, comment);
158
159 /* padding */
160 i = 0;
161 while (buffer_len(&b) % blocksize)
162 buffer_put_char(&b, ++i & 0xff);
163
164 /* length */
165 buffer_put_int(&encoded, buffer_len(&b));
166
167 /* encrypt */
168 cp = buffer_append_space(&encoded, buffer_len(&b) + authlen);
169 if (cipher_crypt(&ctx, 0, cp, buffer_ptr(&b), buffer_len(&b), 0,
170 authlen) != 0)
171 fatal("%s: cipher_crypt failed", __func__);
172 buffer_free(&b);
173 cipher_cleanup(&ctx);
174
175 /* uuencode */
176 len = 2 * buffer_len(&encoded);
177 cp = xmalloc(len);
178 n = uuencode(buffer_ptr(&encoded), buffer_len(&encoded),
179 (char *)cp, len);
180 if (n < 0)
181 fatal("%s: uuencode", __func__);
182
183 buffer_clear(blob);
184 buffer_append(blob, MARK_BEGIN, sizeof(MARK_BEGIN) - 1);
185 for (i = 0; i < n; i++) {
186 buffer_put_char(blob, cp[i]);
187 if (i % 70 == 69)
188 buffer_put_char(blob, '\n');
189 }
190 if (i % 70 != 69)
191 buffer_put_char(blob, '\n');
192 buffer_append(blob, MARK_END, sizeof(MARK_END) - 1);
193 free(cp);
194
195 return buffer_len(blob);
196}
197
198static Key *
199key_parse_private2(Buffer *blob, int type, const char *passphrase,
200 char **commentp)
201{
202 u_char *key = NULL, *cp, *salt = NULL, pad, last;
203 char *comment = NULL, *ciphername = NULL, *kdfname = NULL, *kdfp;
204 u_int keylen = 0, ivlen, blocksize, slen, klen, len, rounds, nkeys;
205 u_int check1, check2, m1len, m2len;
206 size_t authlen;
207 const Cipher *c;
208 Buffer b, encoded, copy, kdf;
209 CipherContext ctx;
210 Key *k = NULL;
211 int dlen, ret, i;
212
213 buffer_init(&b);
214 buffer_init(&kdf);
215 buffer_init(&encoded);
216 buffer_init(&copy);
217
218 /* uudecode */
219 m1len = sizeof(MARK_BEGIN) - 1;
220 m2len = sizeof(MARK_END) - 1;
221 cp = buffer_ptr(blob);
222 len = buffer_len(blob);
223 if (len < m1len || memcmp(cp, MARK_BEGIN, m1len)) {
224 debug("%s: missing begin marker", __func__);
225 goto out;
226 }
227 cp += m1len;
228 len -= m1len;
229 while (len) {
230 if (*cp != '\n' && *cp != '\r')
231 buffer_put_char(&encoded, *cp);
232 last = *cp;
233 len--;
234 cp++;
235 if (last == '\n') {
236 if (len >= m2len && !memcmp(cp, MARK_END, m2len)) {
237 buffer_put_char(&encoded, '\0');
238 break;
239 }
240 }
241 }
242 if (!len) {
243 debug("%s: no end marker", __func__);
244 goto out;
245 }
246 len = buffer_len(&encoded);
247 if ((cp = buffer_append_space(&copy, len)) == NULL) {
248 error("%s: buffer_append_space", __func__);
249 goto out;
250 }
251 if ((dlen = uudecode(buffer_ptr(&encoded), cp, len)) < 0) {
252 error("%s: uudecode failed", __func__);
253 goto out;
254 }
255 if ((u_int)dlen > len) {
256 error("%s: crazy uudecode length %d > %u", __func__, dlen, len);
257 goto out;
258 }
259 buffer_consume_end(&copy, len - dlen);
260 if (buffer_len(&copy) < sizeof(AUTH_MAGIC) ||
261 memcmp(buffer_ptr(&copy), AUTH_MAGIC, sizeof(AUTH_MAGIC))) {
262 error("%s: bad magic", __func__);
263 goto out;
264 }
265 buffer_consume(&copy, sizeof(AUTH_MAGIC));
266
267 ciphername = buffer_get_cstring_ret(&copy, NULL);
268 if (ciphername == NULL ||
269 (c = cipher_by_name(ciphername)) == NULL) {
270 error("%s: unknown cipher name", __func__);
271 goto out;
272 }
273 if ((passphrase == NULL || !strlen(passphrase)) &&
274 strcmp(ciphername, "none") != 0) {
275 /* passphrase required */
276 goto out;
277 }
278 kdfname = buffer_get_cstring_ret(&copy, NULL);
279 if (kdfname == NULL ||
280 (!strcmp(kdfname, "none") && !strcmp(kdfname, "bcrypt"))) {
281 error("%s: unknown kdf name", __func__);
282 goto out;
283 }
284 if (!strcmp(kdfname, "none") && strcmp(ciphername, "none") != 0) {
285 error("%s: cipher %s requires kdf", __func__, ciphername);
286 goto out;
287 }
288 /* kdf options */
289 kdfp = buffer_get_string_ptr_ret(&copy, &klen);
290 if (kdfp == NULL) {
291 error("%s: kdf options not set", __func__);
292 goto out;
293 }
294 if (klen > 0) {
295 if ((cp = buffer_append_space(&kdf, klen)) == NULL) {
296 error("%s: kdf alloc failed", __func__);
297 goto out;
298 }
299 memcpy(cp, kdfp, klen);
300 }
301 /* number of keys */
302 if (buffer_get_int_ret(&nkeys, &copy) < 0) {
303 error("%s: key counter missing", __func__);
304 goto out;
305 }
306 if (nkeys != 1) {
307 error("%s: only one key supported", __func__);
308 goto out;
309 }
310 /* pubkey */
311 if ((cp = buffer_get_string_ret(&copy, &len)) == NULL) {
312 error("%s: pubkey not found", __func__);
313 goto out;
314 }
315 free(cp); /* XXX check pubkey against decrypted private key */
316
317 /* size of encrypted key blob */
318 len = buffer_get_int(&copy);
319 blocksize = cipher_blocksize(c);
320 authlen = cipher_authlen(c);
321 if (len < blocksize) {
322 error("%s: encrypted data too small", __func__);
323 goto out;
324 }
325 if (len % blocksize) {
326 error("%s: length not multiple of blocksize", __func__);
327 goto out;
328 }
329
330 /* setup key */
331 keylen = cipher_keylen(c);
332 ivlen = cipher_ivlen(c);
333 key = xcalloc(1, keylen + ivlen);
334 if (!strcmp(kdfname, "bcrypt")) {
335 if ((salt = buffer_get_string_ret(&kdf, &slen)) == NULL) {
336 error("%s: salt not set", __func__);
337 goto out;
338 }
339 if (buffer_get_int_ret(&rounds, &kdf) < 0) {
340 error("%s: rounds not set", __func__);
341 goto out;
342 }
343 if (bcrypt_pbkdf(passphrase, strlen(passphrase), salt, slen,
344 key, keylen + ivlen, rounds) < 0) {
345 error("%s: bcrypt_pbkdf failed", __func__);
346 goto out;
347 }
348 }
349
350 cp = buffer_append_space(&b, len);
351 cipher_init(&ctx, c, key, keylen, key + keylen, ivlen, 0);
352 ret = cipher_crypt(&ctx, 0, cp, buffer_ptr(&copy), len, 0, authlen);
353 cipher_cleanup(&ctx);
354 buffer_consume(&copy, len);
355
356 /* fail silently on decryption errors */
357 if (ret != 0) {
358 debug("%s: decrypt failed", __func__);
359 goto out;
360 }
361
362 if (buffer_len(&copy) != 0) {
363 error("%s: key blob has trailing data (len = %u)", __func__,
364 buffer_len(&copy));
365 goto out;
366 }
367
368 /* check bytes */
369 if (buffer_get_int_ret(&check1, &b) < 0 ||
370 buffer_get_int_ret(&check2, &b) < 0) {
371 error("check bytes missing");
372 goto out;
373 }
374 if (check1 != check2) {
375 debug("%s: decrypt failed: 0x%08x != 0x%08x", __func__,
376 check1, check2);
377 goto out;
378 }
379
380 k = key_private_deserialize(&b);
381
382 /* comment */
383 comment = buffer_get_cstring_ret(&b, NULL);
384
385 i = 0;
386 while (buffer_len(&b)) {
387 if (buffer_get_char_ret(&pad, &b) == -1 ||
388 pad != (++i & 0xff)) {
389 error("%s: bad padding", __func__);
390 key_free(k);
391 k = NULL;
392 goto out;
393 }
394 }
395
396 if (k && commentp) {
397 *commentp = comment;
398 comment = NULL;
399 }
400
401 /* XXX decode pubkey and check against private */
402 out:
403 free(ciphername);
404 free(kdfname);
405 free(salt);
406 free(comment);
407 if (key)
408 memset(key, 0, keylen + ivlen);
409 free(key);
410 buffer_free(&encoded);
411 buffer_free(&copy);
412 buffer_free(&kdf);
413 buffer_free(&b);
414 return k;
415}
416
78/* 417/*
79 * Serialises the authentication (private) key to a blob, encrypting it with 418 * Serialises the authentication (private) key to a blob, encrypting it with
80 * passphrase. The identification of the blob (lowest 64 bits of n) will 419 * passphrase. The identification of the blob (lowest 64 bits of n) will
@@ -149,8 +488,9 @@ key_private_rsa1_to_blob(Key *key, Buffer *blob, const char *passphrase,
149 488
150 cipher_set_key_string(&ciphercontext, cipher, passphrase, 489 cipher_set_key_string(&ciphercontext, cipher, passphrase,
151 CIPHER_ENCRYPT); 490 CIPHER_ENCRYPT);
152 cipher_crypt(&ciphercontext, 0, cp, 491 if (cipher_crypt(&ciphercontext, 0, cp,
153 buffer_ptr(&buffer), buffer_len(&buffer), 0, 0); 492 buffer_ptr(&buffer), buffer_len(&buffer), 0, 0) != 0)
493 fatal("%s: cipher_crypt failed", __func__);
154 cipher_cleanup(&ciphercontext); 494 cipher_cleanup(&ciphercontext);
155 memset(&ciphercontext, 0, sizeof(ciphercontext)); 495 memset(&ciphercontext, 0, sizeof(ciphercontext));
156 496
@@ -239,7 +579,8 @@ key_save_private_blob(Buffer *keybuf, const char *filename)
239/* Serialise "key" to buffer "blob" */ 579/* Serialise "key" to buffer "blob" */
240static int 580static int
241key_private_to_blob(Key *key, Buffer *blob, const char *passphrase, 581key_private_to_blob(Key *key, Buffer *blob, const char *passphrase,
242 const char *comment) 582 const char *comment, int force_new_format, const char *new_format_cipher,
583 int new_format_rounds)
243{ 584{
244 switch (key->type) { 585 switch (key->type) {
245 case KEY_RSA1: 586 case KEY_RSA1:
@@ -247,6 +588,10 @@ key_private_to_blob(Key *key, Buffer *blob, const char *passphrase,
247 case KEY_DSA: 588 case KEY_DSA:
248 case KEY_ECDSA: 589 case KEY_ECDSA:
249 case KEY_RSA: 590 case KEY_RSA:
591 if (force_new_format) {
592 return key_private_to_blob2(key, blob, passphrase,
593 comment, new_format_cipher, new_format_rounds);
594 }
250 return key_private_pem_to_blob(key, blob, passphrase, comment); 595 return key_private_pem_to_blob(key, blob, passphrase, comment);
251 default: 596 default:
252 error("%s: cannot save key type %d", __func__, key->type); 597 error("%s: cannot save key type %d", __func__, key->type);
@@ -256,13 +601,15 @@ key_private_to_blob(Key *key, Buffer *blob, const char *passphrase,
256 601
257int 602int
258key_save_private(Key *key, const char *filename, const char *passphrase, 603key_save_private(Key *key, const char *filename, const char *passphrase,
259 const char *comment) 604 const char *comment, int force_new_format, const char *new_format_cipher,
605 int new_format_rounds)
260{ 606{
261 Buffer keyblob; 607 Buffer keyblob;
262 int success = 0; 608 int success = 0;
263 609
264 buffer_init(&keyblob); 610 buffer_init(&keyblob);
265 if (!key_private_to_blob(key, &keyblob, passphrase, comment)) 611 if (!key_private_to_blob(key, &keyblob, passphrase, comment,
612 force_new_format, new_format_cipher, new_format_rounds))
266 goto out; 613 goto out;
267 if (!key_save_private_blob(&keyblob, filename)) 614 if (!key_save_private_blob(&keyblob, filename))
268 goto out; 615 goto out;
@@ -473,8 +820,9 @@ key_parse_private_rsa1(Buffer *blob, const char *passphrase, char **commentp)
473 /* Rest of the buffer is encrypted. Decrypt it using the passphrase. */ 820 /* Rest of the buffer is encrypted. Decrypt it using the passphrase. */
474 cipher_set_key_string(&ciphercontext, cipher, passphrase, 821 cipher_set_key_string(&ciphercontext, cipher, passphrase,
475 CIPHER_DECRYPT); 822 CIPHER_DECRYPT);
476 cipher_crypt(&ciphercontext, 0, cp, 823 if (cipher_crypt(&ciphercontext, 0, cp,
477 buffer_ptr(&copy), buffer_len(&copy), 0, 0); 824 buffer_ptr(&copy), buffer_len(&copy), 0, 0) != 0)
825 fatal("%s: cipher_crypt failed", __func__);
478 cipher_cleanup(&ciphercontext); 826 cipher_cleanup(&ciphercontext);
479 memset(&ciphercontext, 0, sizeof(ciphercontext)); 827 memset(&ciphercontext, 0, sizeof(ciphercontext));
480 buffer_free(&copy); 828 buffer_free(&copy);
@@ -641,6 +989,8 @@ static Key *
641key_parse_private_type(Buffer *blob, int type, const char *passphrase, 989key_parse_private_type(Buffer *blob, int type, const char *passphrase,
642 char **commentp) 990 char **commentp)
643{ 991{
992 Key *k;
993
644 switch (type) { 994 switch (type) {
645 case KEY_RSA1: 995 case KEY_RSA1:
646 return key_parse_private_rsa1(blob, passphrase, commentp); 996 return key_parse_private_rsa1(blob, passphrase, commentp);
@@ -648,6 +998,8 @@ key_parse_private_type(Buffer *blob, int type, const char *passphrase,
648 case KEY_ECDSA: 998 case KEY_ECDSA:
649 case KEY_RSA: 999 case KEY_RSA:
650 case KEY_UNSPEC: 1000 case KEY_UNSPEC:
1001 if ((k = key_parse_private2(blob, type, passphrase, commentp)))
1002 return k;
651 return key_parse_private_pem(blob, type, passphrase, commentp); 1003 return key_parse_private_pem(blob, type, passphrase, commentp);
652 default: 1004 default:
653 error("%s: cannot parse key type %d", __func__, type); 1005 error("%s: cannot parse key type %d", __func__, type);
@@ -943,4 +1295,3 @@ key_in_file(Key *key, const char *filename, int strict_type)
943 fclose(f); 1295 fclose(f);
944 return ret; 1296 return ret;
945} 1297}
946
diff --git a/authfile.h b/authfile.h
index 78349beb5..8ba1c2dbe 100644
--- a/authfile.h
+++ b/authfile.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: authfile.h,v 1.16 2011/05/04 21:15:29 djm Exp $ */ 1/* $OpenBSD: authfile.h,v 1.17 2013/12/06 13:34:54 markus Exp $ */
2 2
3/* 3/*
4 * Author: Tatu Ylonen <ylo@cs.hut.fi> 4 * Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -15,7 +15,8 @@
15#ifndef AUTHFILE_H 15#ifndef AUTHFILE_H
16#define AUTHFILE_H 16#define AUTHFILE_H
17 17
18int key_save_private(Key *, const char *, const char *, const char *); 18int key_save_private(Key *, const char *, const char *, const char *,
19 int, const char *, int);
19int key_load_file(int, const char *, Buffer *); 20int key_load_file(int, const char *, Buffer *);
20Key *key_load_cert(const char *); 21Key *key_load_cert(const char *);
21Key *key_load_public(const char *, char **); 22Key *key_load_public(const char *, char **);
diff --git a/cipher.c b/cipher.c
index fbb730148..76e6c5963 100644
--- a/cipher.c
+++ b/cipher.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: cipher.c,v 1.92 2013/12/02 03:13:14 djm Exp $ */ 1/* $OpenBSD: cipher.c,v 1.93 2013/12/06 13:34:54 markus Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -344,17 +344,16 @@ cipher_init(CipherContext *cc, const Cipher *cipher,
344 * Use 'authlen' bytes at offset 'len'+'aadlen' as the authentication tag. 344 * Use 'authlen' bytes at offset 'len'+'aadlen' as the authentication tag.
345 * This tag is written on encryption and verified on decryption. 345 * This tag is written on encryption and verified on decryption.
346 * Both 'aadlen' and 'authlen' can be set to 0. 346 * Both 'aadlen' and 'authlen' can be set to 0.
347 * cipher_crypt() returns 0 on success and -1 if the decryption integrity
348 * check fails.
347 */ 349 */
348void 350int
349cipher_crypt(CipherContext *cc, u_int seqnr, u_char *dest, const u_char *src, 351cipher_crypt(CipherContext *cc, u_int seqnr, u_char *dest, const u_char *src,
350 u_int len, u_int aadlen, u_int authlen) 352 u_int len, u_int aadlen, u_int authlen)
351{ 353{
352 if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) { 354 if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0)
353 if (chachapoly_crypt(&cc->cp_ctx, seqnr, dest, src, len, aadlen, 355 return chachapoly_crypt(&cc->cp_ctx, seqnr, dest, src, len,
354 authlen, cc->encrypt) != 0) 356 aadlen, authlen, cc->encrypt);
355 fatal("Decryption integrity check failed");
356 return;
357 }
358 if (authlen) { 357 if (authlen) {
359 u_char lastiv[1]; 358 u_char lastiv[1];
360 359
@@ -387,13 +386,14 @@ cipher_crypt(CipherContext *cc, u_int seqnr, u_char *dest, const u_char *src,
387 if (cc->encrypt) 386 if (cc->encrypt)
388 fatal("%s: EVP_Cipher(final) failed", __func__); 387 fatal("%s: EVP_Cipher(final) failed", __func__);
389 else 388 else
390 fatal("Decryption integrity check failed"); 389 return -1;
391 } 390 }
392 if (cc->encrypt && 391 if (cc->encrypt &&
393 !EVP_CIPHER_CTX_ctrl(&cc->evp, EVP_CTRL_GCM_GET_TAG, 392 !EVP_CIPHER_CTX_ctrl(&cc->evp, EVP_CTRL_GCM_GET_TAG,
394 authlen, dest + aadlen + len)) 393 authlen, dest + aadlen + len))
395 fatal("%s: EVP_CTRL_GCM_GET_TAG", __func__); 394 fatal("%s: EVP_CTRL_GCM_GET_TAG", __func__);
396 } 395 }
396 return 0;
397} 397}
398 398
399/* Extract the packet length, including any decryption necessary beforehand */ 399/* Extract the packet length, including any decryption necessary beforehand */
diff --git a/cipher.h b/cipher.h
index 4e837a754..d78245615 100644
--- a/cipher.h
+++ b/cipher.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: cipher.h,v 1.42 2013/11/21 00:45:44 djm Exp $ */ 1/* $OpenBSD: cipher.h,v 1.43 2013/12/06 13:34:54 markus Exp $ */
2 2
3/* 3/*
4 * Author: Tatu Ylonen <ylo@cs.hut.fi> 4 * Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -81,7 +81,7 @@ int ciphers_valid(const char *);
81char *cipher_alg_list(char, int); 81char *cipher_alg_list(char, int);
82void cipher_init(CipherContext *, const Cipher *, const u_char *, u_int, 82void cipher_init(CipherContext *, const Cipher *, const u_char *, u_int,
83 const u_char *, u_int, int); 83 const u_char *, u_int, int);
84void cipher_crypt(CipherContext *, u_int, u_char *, const u_char *, 84int cipher_crypt(CipherContext *, u_int, u_char *, const u_char *,
85 u_int, u_int, u_int); 85 u_int, u_int, u_int);
86int cipher_get_length(CipherContext *, u_int *, u_int, 86int cipher_get_length(CipherContext *, u_int *, u_int,
87 const u_char *, u_int); 87 const u_char *, u_int);
diff --git a/key.c b/key.c
index 0282e0823..c09f43f19 100644
--- a/key.c
+++ b/key.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: key.c,v 1.107 2013/12/06 13:30:08 markus Exp $ */ 1/* $OpenBSD: key.c,v 1.108 2013/12/06 13:34:54 markus Exp $ */
2/* 2/*
3 * read_bignum(): 3 * read_bignum():
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -1892,6 +1892,7 @@ key_certify(Key *k, Key *ca)
1892 if (!key_cert_is_legacy(k)) 1892 if (!key_cert_is_legacy(k))
1893 buffer_put_string(&k->cert->certblob, nonce, sizeof(nonce)); 1893 buffer_put_string(&k->cert->certblob, nonce, sizeof(nonce));
1894 1894
1895 /* XXX this substantially duplicates to_blob(); refactor */
1895 switch (k->type) { 1896 switch (k->type) {
1896 case KEY_DSA_CERT_V00: 1897 case KEY_DSA_CERT_V00:
1897 case KEY_DSA_CERT: 1898 case KEY_DSA_CERT:
diff --git a/packet.c b/packet.c
index 029bb4c98..6cf7edbb8 100644
--- a/packet.c
+++ b/packet.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: packet.c,v 1.190 2013/11/21 00:45:44 djm Exp $ */ 1/* $OpenBSD: packet.c,v 1.191 2013/12/06 13:34:54 markus Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -713,9 +713,10 @@ packet_send1(void)
713 buffer_append(&active_state->output, buf, 4); 713 buffer_append(&active_state->output, buf, 4);
714 cp = buffer_append_space(&active_state->output, 714 cp = buffer_append_space(&active_state->output,
715 buffer_len(&active_state->outgoing_packet)); 715 buffer_len(&active_state->outgoing_packet));
716 cipher_crypt(&active_state->send_context, 0, cp, 716 if (cipher_crypt(&active_state->send_context, 0, cp,
717 buffer_ptr(&active_state->outgoing_packet), 717 buffer_ptr(&active_state->outgoing_packet),
718 buffer_len(&active_state->outgoing_packet), 0, 0); 718 buffer_len(&active_state->outgoing_packet), 0, 0) != 0)
719 fatal("%s: cipher_crypt failed", __func__);
719 720
720#ifdef PACKET_DEBUG 721#ifdef PACKET_DEBUG
721 fprintf(stderr, "encrypted: "); 722 fprintf(stderr, "encrypted: ");
@@ -946,9 +947,10 @@ packet_send2_wrapped(void)
946 } 947 }
947 /* encrypt packet and append to output buffer. */ 948 /* encrypt packet and append to output buffer. */
948 cp = buffer_append_space(&active_state->output, len + authlen); 949 cp = buffer_append_space(&active_state->output, len + authlen);
949 cipher_crypt(&active_state->send_context, active_state->p_send.seqnr, 950 if (cipher_crypt(&active_state->send_context, active_state->p_send.seqnr,
950 cp, buffer_ptr(&active_state->outgoing_packet), 951 cp, buffer_ptr(&active_state->outgoing_packet),
951 len - aadlen, aadlen, authlen); 952 len - aadlen, aadlen, authlen) != 0)
953 fatal("%s: cipher_crypt failed", __func__);
952 /* append unencrypted MAC */ 954 /* append unencrypted MAC */
953 if (mac && mac->enabled) { 955 if (mac && mac->enabled) {
954 if (mac->etm) { 956 if (mac->etm) {
@@ -1208,8 +1210,9 @@ packet_read_poll1(void)
1208 /* Decrypt data to incoming_packet. */ 1210 /* Decrypt data to incoming_packet. */
1209 buffer_clear(&active_state->incoming_packet); 1211 buffer_clear(&active_state->incoming_packet);
1210 cp = buffer_append_space(&active_state->incoming_packet, padded_len); 1212 cp = buffer_append_space(&active_state->incoming_packet, padded_len);
1211 cipher_crypt(&active_state->receive_context, 0, cp, 1213 if (cipher_crypt(&active_state->receive_context, 0, cp,
1212 buffer_ptr(&active_state->input), padded_len, 0, 0); 1214 buffer_ptr(&active_state->input), padded_len, 0, 0) != 0)
1215 fatal("%s: cipher_crypt failed", __func__);
1213 1216
1214 buffer_consume(&active_state->input, padded_len); 1217 buffer_consume(&active_state->input, padded_len);
1215 1218
@@ -1304,9 +1307,10 @@ packet_read_poll2(u_int32_t *seqnr_p)
1304 buffer_clear(&active_state->incoming_packet); 1307 buffer_clear(&active_state->incoming_packet);
1305 cp = buffer_append_space(&active_state->incoming_packet, 1308 cp = buffer_append_space(&active_state->incoming_packet,
1306 block_size); 1309 block_size);
1307 cipher_crypt(&active_state->receive_context, 1310 if (cipher_crypt(&active_state->receive_context,
1308 active_state->p_read.seqnr, cp, 1311 active_state->p_read.seqnr, cp,
1309 buffer_ptr(&active_state->input), block_size, 0, 0); 1312 buffer_ptr(&active_state->input), block_size, 0, 0) != 0)
1313 fatal("Decryption integrity check failed");
1310 cp = buffer_ptr(&active_state->incoming_packet); 1314 cp = buffer_ptr(&active_state->incoming_packet);
1311 active_state->packlen = get_u32(cp); 1315 active_state->packlen = get_u32(cp);
1312 if (active_state->packlen < 1 + 4 || 1316 if (active_state->packlen < 1 + 4 ||
@@ -1360,9 +1364,10 @@ packet_read_poll2(u_int32_t *seqnr_p)
1360 macbuf = mac_compute(mac, active_state->p_read.seqnr, 1364 macbuf = mac_compute(mac, active_state->p_read.seqnr,
1361 buffer_ptr(&active_state->input), aadlen + need); 1365 buffer_ptr(&active_state->input), aadlen + need);
1362 cp = buffer_append_space(&active_state->incoming_packet, aadlen + need); 1366 cp = buffer_append_space(&active_state->incoming_packet, aadlen + need);
1363 cipher_crypt(&active_state->receive_context, 1367 if (cipher_crypt(&active_state->receive_context,
1364 active_state->p_read.seqnr, cp, 1368 active_state->p_read.seqnr, cp,
1365 buffer_ptr(&active_state->input), need, aadlen, authlen); 1369 buffer_ptr(&active_state->input), need, aadlen, authlen) != 0)
1370 fatal("Decryption integrity check failed");
1366 buffer_consume(&active_state->input, aadlen + need + authlen); 1371 buffer_consume(&active_state->input, aadlen + need + authlen);
1367 /* 1372 /*
1368 * compute MAC over seqnr and packet, 1373 * compute MAC over seqnr and packet,
diff --git a/ssh-agent.c b/ssh-agent.c
index 0196f8f6b..579ee3840 100644
--- a/ssh-agent.c
+++ b/ssh-agent.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: ssh-agent.c,v 1.178 2013/12/06 13:30:08 markus Exp $ */ 1/* $OpenBSD: ssh-agent.c,v 1.179 2013/12/06 13:34:54 markus Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -484,7 +484,6 @@ process_add_identity(SocketEntry *e, int version)
484 /* Generate additional parameters */ 484 /* Generate additional parameters */
485 rsa_generate_additional_parameters(k->rsa); 485 rsa_generate_additional_parameters(k->rsa);
486 486
487 /* enable blinding */
488 if (RSA_blinding_on(k->rsa, NULL) != 1) { 487 if (RSA_blinding_on(k->rsa, NULL) != 1) {
489 error("process_add_identity: RSA_blinding_on failed"); 488 error("process_add_identity: RSA_blinding_on failed");
490 key_free(k); 489 key_free(k);
diff --git a/ssh-keygen.c b/ssh-keygen.c
index e5e2f2f6c..533eed291 100644
--- a/ssh-keygen.c
+++ b/ssh-keygen.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: ssh-keygen.c,v 1.236 2013/12/06 03:40:51 djm Exp $ */ 1/* $OpenBSD: ssh-keygen.c,v 1.237 2013/12/06 13:34:54 markus Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1994 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1994 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -150,6 +150,18 @@ char *key_type_name = NULL;
150/* Load key from this PKCS#11 provider */ 150/* Load key from this PKCS#11 provider */
151char *pkcs11provider = NULL; 151char *pkcs11provider = NULL;
152 152
153/* Use new OpenSSH private key format when writing SSH2 keys instead of PEM */
154int use_new_format = 0;
155
156/* Cipher for new-format private keys */
157char *new_format_cipher = NULL;
158
159/*
160 * Number of KDF rounds to derive new format keys /
161 * number of primality trials when screening moduli.
162 */
163int rounds = 0;
164
153/* argv0 */ 165/* argv0 */
154extern char *__progname; 166extern char *__progname;
155 167
@@ -923,7 +935,8 @@ do_gen_all_hostkeys(struct passwd *pw)
923 public = key_from_private(private); 935 public = key_from_private(private);
924 snprintf(comment, sizeof comment, "%s@%s", pw->pw_name, 936 snprintf(comment, sizeof comment, "%s@%s", pw->pw_name,
925 hostname); 937 hostname);
926 if (!key_save_private(private, identity_file, "", comment)) { 938 if (!key_save_private(private, identity_file, "", comment,
939 use_new_format, new_format_cipher, rounds)) {
927 printf("Saving the key failed: %s.\n", identity_file); 940 printf("Saving the key failed: %s.\n", identity_file);
928 key_free(private); 941 key_free(private);
929 key_free(public); 942 key_free(public);
@@ -1275,7 +1288,8 @@ do_change_passphrase(struct passwd *pw)
1275 } 1288 }
1276 1289
1277 /* Save the file using the new passphrase. */ 1290 /* Save the file using the new passphrase. */
1278 if (!key_save_private(private, identity_file, passphrase1, comment)) { 1291 if (!key_save_private(private, identity_file, passphrase1, comment,
1292 use_new_format, new_format_cipher, rounds)) {
1279 printf("Saving the key failed: %s.\n", identity_file); 1293 printf("Saving the key failed: %s.\n", identity_file);
1280 memset(passphrase1, 0, strlen(passphrase1)); 1294 memset(passphrase1, 0, strlen(passphrase1));
1281 free(passphrase1); 1295 free(passphrase1);
@@ -1385,7 +1399,8 @@ do_change_comment(struct passwd *pw)
1385 } 1399 }
1386 1400
1387 /* Save the file using the new passphrase. */ 1401 /* Save the file using the new passphrase. */
1388 if (!key_save_private(private, identity_file, passphrase, new_comment)) { 1402 if (!key_save_private(private, identity_file, passphrase, new_comment,
1403 use_new_format, new_format_cipher, rounds)) {
1389 printf("Saving the key failed: %s.\n", identity_file); 1404 printf("Saving the key failed: %s.\n", identity_file);
1390 memset(passphrase, 0, strlen(passphrase)); 1405 memset(passphrase, 0, strlen(passphrase));
1391 free(passphrase); 1406 free(passphrase);
@@ -2132,7 +2147,7 @@ usage(void)
2132 fprintf(stderr, "usage: %s [options]\n", __progname); 2147 fprintf(stderr, "usage: %s [options]\n", __progname);
2133 fprintf(stderr, "Options:\n"); 2148 fprintf(stderr, "Options:\n");
2134 fprintf(stderr, " -A Generate non-existent host keys for all key types.\n"); 2149 fprintf(stderr, " -A Generate non-existent host keys for all key types.\n");
2135 fprintf(stderr, " -a trials Number of trials for screening DH-GEX moduli.\n"); 2150 fprintf(stderr, " -a number Number of KDF rounds for new key format or moduli primality tests.\n");
2136 fprintf(stderr, " -B Show bubblebabble digest of key file.\n"); 2151 fprintf(stderr, " -B Show bubblebabble digest of key file.\n");
2137 fprintf(stderr, " -b bits Number of bits in the key to create.\n"); 2152 fprintf(stderr, " -b bits Number of bits in the key to create.\n");
2138 fprintf(stderr, " -C comment Provide new comment.\n"); 2153 fprintf(stderr, " -C comment Provide new comment.\n");
@@ -2160,6 +2175,7 @@ usage(void)
2160 fprintf(stderr, " -N phrase Provide new passphrase.\n"); 2175 fprintf(stderr, " -N phrase Provide new passphrase.\n");
2161 fprintf(stderr, " -n name,... User/host principal names to include in certificate\n"); 2176 fprintf(stderr, " -n name,... User/host principal names to include in certificate\n");
2162 fprintf(stderr, " -O option Specify a certificate option.\n"); 2177 fprintf(stderr, " -O option Specify a certificate option.\n");
2178 fprintf(stderr, " -o Enforce new private key format.\n");
2163 fprintf(stderr, " -P phrase Provide old passphrase.\n"); 2179 fprintf(stderr, " -P phrase Provide old passphrase.\n");
2164 fprintf(stderr, " -p Change passphrase of private key file.\n"); 2180 fprintf(stderr, " -p Change passphrase of private key file.\n");
2165 fprintf(stderr, " -Q Test whether key(s) are revoked in KRL.\n"); 2181 fprintf(stderr, " -Q Test whether key(s) are revoked in KRL.\n");
@@ -2176,6 +2192,7 @@ usage(void)
2176 fprintf(stderr, " -W gen Generator to use for generating DH-GEX moduli.\n"); 2192 fprintf(stderr, " -W gen Generator to use for generating DH-GEX moduli.\n");
2177 fprintf(stderr, " -y Read private key file and print public key.\n"); 2193 fprintf(stderr, " -y Read private key file and print public key.\n");
2178 fprintf(stderr, " -z serial Specify a serial number.\n"); 2194 fprintf(stderr, " -z serial Specify a serial number.\n");
2195 fprintf(stderr, " -Z cipher Specify a cipher for new private key format.\n");
2179 2196
2180 exit(1); 2197 exit(1);
2181} 2198}
@@ -2193,7 +2210,7 @@ main(int argc, char **argv)
2193 struct passwd *pw; 2210 struct passwd *pw;
2194 struct stat st; 2211 struct stat st;
2195 int opt, type, fd; 2212 int opt, type, fd;
2196 u_int32_t memory = 0, generator_wanted = 0, trials = 100; 2213 u_int32_t memory = 0, generator_wanted = 0;
2197 int do_gen_candidates = 0, do_screen_candidates = 0; 2214 int do_gen_candidates = 0, do_screen_candidates = 0;
2198 int gen_all_hostkeys = 0, gen_krl = 0, update_krl = 0, check_krl = 0; 2215 int gen_all_hostkeys = 0, gen_krl = 0, update_krl = 0, check_krl = 0;
2199 unsigned long start_lineno = 0, lines_to_process = 0; 2216 unsigned long start_lineno = 0, lines_to_process = 0;
@@ -2225,9 +2242,9 @@ main(int argc, char **argv)
2225 exit(1); 2242 exit(1);
2226 } 2243 }
2227 2244
2228 /* Remaining characters: EUYZdow */ 2245 /* Remaining characters: EUYdw */
2229 while ((opt = getopt(argc, argv, "ABHLQXceghiklpquvxy" 2246 while ((opt = getopt(argc, argv, "ABHLQXceghiklopquvxy"
2230 "C:D:F:G:I:J:K:M:N:O:P:R:S:T:V:W:a:b:f:j:m:n:r:s:t:z:")) != -1) { 2247 "C:D:F:G:I:J:K:M:N:O:P:R:S:T:V:W:Z:a:b:f:g:j:m:n:r:s:t:z:")) != -1) {
2231 switch (opt) { 2248 switch (opt) {
2232 case 'A': 2249 case 'A':
2233 gen_all_hostkeys = 1; 2250 gen_all_hostkeys = 1;
@@ -2285,6 +2302,9 @@ main(int argc, char **argv)
2285 case 'n': 2302 case 'n':
2286 cert_principals = optarg; 2303 cert_principals = optarg;
2287 break; 2304 break;
2305 case 'o':
2306 use_new_format = 1;
2307 break;
2288 case 'p': 2308 case 'p':
2289 change_passphrase = 1; 2309 change_passphrase = 1;
2290 break; 2310 break;
@@ -2312,6 +2332,9 @@ main(int argc, char **argv)
2312 case 'O': 2332 case 'O':
2313 add_cert_option(optarg); 2333 add_cert_option(optarg);
2314 break; 2334 break;
2335 case 'Z':
2336 new_format_cipher = optarg;
2337 break;
2315 case 'C': 2338 case 'C':
2316 identity_comment = optarg; 2339 identity_comment = optarg;
2317 break; 2340 break;
@@ -2370,9 +2393,9 @@ main(int argc, char **argv)
2370 optarg, errstr); 2393 optarg, errstr);
2371 break; 2394 break;
2372 case 'a': 2395 case 'a':
2373 trials = (u_int32_t)strtonum(optarg, 1, UINT_MAX, &errstr); 2396 rounds = (int)strtonum(optarg, 1, INT_MAX, &errstr);
2374 if (errstr) 2397 if (errstr)
2375 fatal("Invalid number of trials: %s (%s)", 2398 fatal("Invalid number: %s (%s)",
2376 optarg, errstr); 2399 optarg, errstr);
2377 break; 2400 break;
2378 case 'M': 2401 case 'M':
@@ -2531,7 +2554,8 @@ main(int argc, char **argv)
2531 fatal("Couldn't open moduli file \"%s\": %s", 2554 fatal("Couldn't open moduli file \"%s\": %s",
2532 out_file, strerror(errno)); 2555 out_file, strerror(errno));
2533 } 2556 }
2534 if (prime_test(in, out, trials, generator_wanted, checkpoint, 2557 if (prime_test(in, out, rounds == 0 ? 100 : rounds,
2558 generator_wanted, checkpoint,
2535 start_lineno, lines_to_process) != 0) 2559 start_lineno, lines_to_process) != 0)
2536 fatal("modulus screening failed"); 2560 fatal("modulus screening failed");
2537 return (0); 2561 return (0);
@@ -2623,7 +2647,8 @@ passphrase_again:
2623 } 2647 }
2624 2648
2625 /* Save the key with the given passphrase and comment. */ 2649 /* Save the key with the given passphrase and comment. */
2626 if (!key_save_private(private, identity_file, passphrase1, comment)) { 2650 if (!key_save_private(private, identity_file, passphrase1, comment,
2651 use_new_format, new_format_cipher, rounds)) {
2627 printf("Saving the key failed: %s.\n", identity_file); 2652 printf("Saving the key failed: %s.\n", identity_file);
2628 memset(passphrase1, 0, strlen(passphrase1)); 2653 memset(passphrase1, 0, strlen(passphrase1));
2629 free(passphrase1); 2654 free(passphrase1);